7f40378f06
gcc/java: 2007-02-15 David Daney <ddaney@avtrex.com> * Make-lang.in (JAVA_MANFILES): Add doc/gc-analyze.1. (java.maintainer-clean):Add gc-analyze.1. (.INTERMEDIATE): Add gc-analyze.pod. (gc-analyze.pod): New rule. (java.install-man): Install gc-analyze.1 * gcj.texi: Add new section for the gc-analyze program. libjava: 2007-02-15 Johannes Schmidt <jschmidt@avtrex.com> David Daney <ddaney@avtrex.com> * configure.ac: Create vm-tools-packages file. Add gnu/gcj/tools/gc_analyze to standard.omit and vm-tools-packages. Check for /proc/self/maps. * Makefile.am (bin_PROGRAMS): Added gc-analyze. (gc_analyze_SOURCES): New. (gc_analyze_LDFLAGS): New. (gc_analyze_LINK): New. (gc_analyze_LDADD): New. (gc_analyze_DEPENDENCIES): New. (nat_source_files): Add gnu/gcj/util/natGCInfo.cc. * Makefile.in: Regenerated. * configure: Regenerated. * include/config.h.in: Regenerated. * sources.am: Regenerated. * scripts/makemake.tcl: Don't include gc-analyze classes in libgcj. * gnu/gcj/tools/gc_analyze/SymbolLookup.java: New. * gnu/gcj/tools/gc_analyze/ObjectMap.java: New. * gnu/gcj/tools/gc_analyze/MemoryMap.java: New. * gnu/gcj/tools/gc_analyze/SymbolTable.java: New. * gnu/gcj/tools/gc_analyze/BlockMap.java: New. * gnu/gcj/tools/gc_analyze/BytePtr.java: New. * gnu/gcj/tools/gc_analyze/ItemList.java: New. * gnu/gcj/tools/gc_analyze/ToolPrefix.java: New. * gnu/gcj/tools/gc_analyze/MemoryAnalyze.java: New. * gnu/gcj/util/GCInfo.java: New. * gnu/gcj/util/GCInfo.h: New. * gnu/gcj/util/natGCInfo.cc: New. * gnu/gcj/util/UtilPermission.java: New. * gnu/gcj/util/UtilPermission.h: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolTable.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap$ObjectItem.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$RangeComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$PtrMarks.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap$Range.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BytePtr.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$SubstringComparator.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ItemList.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ToolPrefix.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1$Info.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$1.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$2.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$3.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$4.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryAnalyze$OptionParser.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/BlockMap$SizeKind.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/SymbolLookup.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/ObjectMap.class: New. * classpath/tools/gnu/gcj/tools/gc_analyze/MemoryMap.class: New. * classpath/lib/gnu/gcj/util/GCInfo.class: New. * classpath/lib/gnu/gcj/util/UtilPermission.class: New. libjava/classpath: 2007-02-15 David Daney <ddaney@avtrex.com> * tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages. * tools/Makefile.in: Regenerated. From-SVN: r122007
199 lines
5.4 KiB
Java
199 lines
5.4 KiB
Java
/* 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();
|
|
}
|
|
}
|