summaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java')
-rw-r--r--libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java112
1 files changed, 112 insertions, 0 deletions
diff --git a/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java b/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
new file mode 100644
index 000000000..b3963d8cf
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gc_analyze/SymbolLookup.java
@@ -0,0 +1,112 @@
+/* SymbolLookup.java -- Finds class names by analyzing memory.
+ 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;
+
+class SymbolLookup
+{
+ MemoryMap memoryMap;
+
+ public SymbolLookup(BufferedReader reader,
+ String rawFileName)
+ throws IOException
+ {
+ memoryMap = new MemoryMap(reader, rawFileName);
+ }
+
+ public String decodeUTF8(long address) throws IOException
+ {
+ return decodeUTF8(address, -1);
+ }
+
+ public String decodeUTF8(long address, int limit) throws IOException
+ {
+ if (address == 0)
+ return null;
+
+ BytePtr utf8 = memoryMap.getBytePtr(address, 64);
+
+ if (utf8 == null)
+ return null;
+
+ int len = utf8.getShort(1);
+ int hash16 = utf8.getShort(0) & 0xffff;
+
+ if (len <= 0 || (limit > 0 && len > (limit - 4)))
+ return null;
+
+ if (len > utf8.getsize() + 4)
+ utf8 = memoryMap.getBytePtr(address, len + 4);
+
+ if (utf8 == null)
+ return null;
+
+ StringBuilder sb = new StringBuilder(len);
+ int pos = 4;
+ len += 4;
+
+ while (pos < len)
+ {
+ int f = utf8.getByte(pos++);
+ if ((f & 0x80) == 0)
+ {
+ sb.append((char)f);
+ }
+ else if ((f & 0xe0) == 0xc0)
+ {
+ int s = utf8.getByte(pos++);
+ char c = (char)(((f & 0x1f) << 6) | (s & 0x80));
+ sb.append(c);
+ }
+ else if ((f & 0xe0) == 0xe0)
+ {
+ int s = utf8.getByte(pos++);
+ int t = utf8.getByte(pos++);
+ char c = (char)(((f & 0x0f) << 12)
+ | ((s & 0x80) << 6) | (t & 0x80));
+ sb.append(c);
+ }
+ else
+ break; // Bad utf8
+ }
+ String rv = sb.toString();
+ if (hash16 == (rv.hashCode() & 0xffff))
+ return rv;
+ else
+ return null;
+ }
+
+ public String getSymbolViaVtable(long address) throws IOException
+ {
+ return memoryMap.getSymbol(address);
+ }
+
+ public String getSymbol(long address) throws IOException
+ {
+ String symbol = memoryMap.getSymbol(address);
+ if (null != symbol)
+ return symbol;
+
+ BytePtr klass = memoryMap.getBytePtr(address, 3 * memoryMap.wordSize);
+ if (klass == null)
+ return null;
+
+ long nameUTF8p = klass.getWord(2);
+
+ return decodeUTF8(nameUTF8p);
+ }
+
+ BytePtr getBytePtr(long addr, int length) throws IOException
+ {
+ return memoryMap.getBytePtr(addr, length);
+ }
+}