diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java')
-rw-r--r-- | libjava/gnu/gcj/tools/gc_analyze/SymbolTable.java | 198 |
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(); + } +} |