summaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java')
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java198
1 files changed, 198 insertions, 0 deletions
diff --git a/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java b/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
new file mode 100644
index 000000000..eb5df7641
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java
@@ -0,0 +1,198 @@
+/* SymbolTable.java -- Maintains a mapping of addresses to names.
+ Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+package gnu.gcj.tools.gc_analyze;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class SymbolTable
+{
+ // Long address->String name
+ private HashMap<Long, String> map = new HashMap<Long, String>();
+
+ // Reverse
+ // String name -> Long address
+ // used for RelocateImage
+ private HashMap<String, Long> reverse = new HashMap<String, Long>();
+
+ long loadAddr;
+ long relocation;
+
+ static Matcher interestingSymbol =
+ Pattern.compile("^([0-9a-fA-F]+)\\s+\\S+\\s+(_Z\\S+)").matcher("");
+ static Matcher readelfLoadMatcher =
+ Pattern.compile("^\\s+LOAD\\s+(\\S+)\\s+(\\S+)\\s.*").matcher("");
+
+ public SymbolTable(String filename) throws IOException
+ {
+ Process p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
+ + "nm " + filename);
+ InputStream es = p.getErrorStream();
+ InputStream is = p.getInputStream();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ int count = 0;
+
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ interestingSymbol.reset(line);
+ if (interestingSymbol.matches())
+ {
+ try
+ {
+ String name = interestingSymbol.group(2);
+ String addr = interestingSymbol.group(1);
+ if (name.startsWith("_ZTVN") || name.endsWith("6class$E"))
+ {
+ long address = MemoryMap.parseHexLong(addr);
+ Long l = new Long(address);
+ map.put(l, name);
+ count++;
+ reverse.put(name, l);
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ // ignore it
+ }
+ }
+ }
+ es.close();
+ is.close();
+ p.destroy();
+
+ if (count > 0)
+ {
+ // Assume nm read some symbols from it and that
+ // readelf can tell us something about how it is loaded.
+ p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix
+ + "readelf -l " + filename);
+ es = p.getErrorStream();
+ is = p.getInputStream();
+
+ reader = new BufferedReader(new InputStreamReader(is));
+ while ((line = reader.readLine()) != null)
+ {
+ readelfLoadMatcher.reset(line);
+ if (readelfLoadMatcher.matches())
+ {
+ loadAddr
+ = Long.decode(readelfLoadMatcher.group(2)).longValue();
+ break;
+ }
+ }
+ es.close();
+ is.close();
+ p.destroy();
+ }
+
+ System.out.println(ToolPrefix.toolPrefix + "nm " + filename
+ + " -> " + count + " symbols");
+ }
+
+ public static void main(String args[])
+ {
+ try
+ {
+ SymbolTable st = new SymbolTable(args[0]);
+ st.dump();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public static String demangleVTName(String n)
+ {
+ if (n.startsWith("_ZTVN") && n.endsWith("E"))
+ return demangle(n.substring(5, n.length() - 1));
+ else
+ return null;
+ }
+
+ public void dump()
+ {
+ for (Map.Entry<Long, String> me : map.entrySet())
+ {
+ long address = me.getKey();
+ String symbol = me.getValue();
+ System.out.println(Long.toHexString(address) + " -> " + symbol);
+ if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
+ {
+ System.out.println(" Class: "
+ + demangle(symbol.substring(3, symbol.length()
+ - 8)));
+ }
+ else if (symbol.startsWith("_ZTVN") && symbol.endsWith("E"))
+ {
+ System.out.println(" VT: "
+ + demangle(symbol.substring(5, symbol.length()
+ - 1)));
+ }
+ }
+ }
+
+ private static String demangle(String symbol)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i=0; i<symbol.length(); )
+ {
+ int l = 0;
+ while (i < symbol.length())
+ {
+ int d = symbol.charAt(i);
+ if (d < '0' || d > '9')
+ break;
+ l = 10 * l + (d - '0');
+ i++;
+ }
+ if (l == 0)
+ break;
+ // copy
+ if (sb.length() > 0)
+ sb.append('.');
+ while (l > 0 && i < symbol.length())
+ {
+ sb.append(symbol.charAt(i));
+ l--;
+ i++;
+ }
+ }
+ return sb.toString();
+ }
+
+ public String getSymbol(long address)
+ {
+ String symbol = map.get(address);
+ if (symbol == null)
+ return null;
+
+ if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E"))
+ symbol = demangle(symbol.substring(3, symbol.length() - 8));
+ return symbol;
+ }
+
+ // will return -1 if not found
+ public long getAddress(String symbol)
+ {
+ Long address = reverse.get(symbol);
+ if (address == null)
+ return -1;
+ return address.longValue();
+ }
+}