From 53973c81d70dccdd1e1ca48555ddf8620c652bcd Mon Sep 17 00:00:00 2001 From: daney Date: Thu, 15 Feb 2007 17:25:24 +0000 Subject: gcc/java: 2007-02-15 David Daney * 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 David Daney * 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 * tools/Makefile.am (TOOLS_ZIP): Add classes from vm-tools-packages. * tools/Makefile.in: Regenerated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122007 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java | 359 ++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java (limited to 'libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java') diff --git a/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java b/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java new file mode 100644 index 00000000000..1bc06d58422 --- /dev/null +++ b/libjava/gnu/gcj/tools/gc_analyze/MemoryMap.java @@ -0,0 +1,359 @@ +/* MemoryMap.java -- Maps address ranges to their data. + 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.EOFException; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.util.Comparator; +import java.util.HashMap; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Reads /proc/self/maps output from dump file. + * Creates map of to Range. + * + * Returns filename given address. + * Returns offset given address. + * Returns BytePtr given address. + * + */ +class MemoryMap +{ + static class RangeComparator implements Comparator + { + public int compare(Range r1, Range r2) + { + if (r2.end == 0 && r1.end != 0) + return -compare(r2, r1); + + if (r1.begin < r2.begin) + return -1; + else if (r1.begin >= r2.end) + return 1; + else + return 0; + } + } + + static class Range + { + long begin; + long end; + + long offset; + String filename; + Range() + { + } + + Range(long b, long e, String s, long o) + { + begin = b; + end = e; + filename = s; + offset = o; + } + } + + /** + * Parse the string as an unsigned hexadecimal number. This is + * similar to Long.parseInt(s,16), but without the restriction that + * values that have the sign bit set not being allowed. + * + * @param s the number as a String. + * @return the number. + */ + static long parseHexLong(String s) + { + if (s.length() > 16) + throw new NumberFormatException(); + long r = 0; + for (int i = 0; i < s.length(); i++) + { + int digit = 0; + char c = s.charAt(i); + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + digit = c - '0'; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + digit = 10 + c - 'a'; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + digit = 10 + c - 'A'; + break; + default: + throw new NumberFormatException(); + } + r = (r << 4) + digit; + } + return r; + } + + // String filename -> Range + TreeSet map = new TreeSet(new RangeComparator()); + HashMap symbolTables = + new HashMap(); + ByteOrder byteOrder; + int wordSize; + + public MemoryMap(BufferedReader reader, + String rawFileName) throws IOException + { + FileChannel raw = (new RandomAccessFile(rawFileName, "r")).getChannel(); + ByteBuffer buf = ByteBuffer.allocate(8); + raw.read(buf); + if (buf.hasRemaining()) + { + raw.close(); + throw new EOFException(); + } + buf.flip(); + wordSize = buf.get(); + + if (wordSize == 8 || wordSize == 4) + byteOrder = ByteOrder.LITTLE_ENDIAN; + else + { + byteOrder = ByteOrder.BIG_ENDIAN; + buf.rewind(); + wordSize = buf.getInt(); + if (0 == wordSize) + wordSize = buf.getInt(); + } + switch (wordSize) + { + case 4: + case 8: + break; + default: + throw new IOException("Bad .bytes file header"); + } + buf = ByteBuffer.allocate(3 * wordSize); + buf.order(byteOrder); + raw.position(0L); + + for(;;) + { + // Read the block header. + buf.clear(); + if (-1 == raw.read(buf)) + { + //EOF + raw.close(); + break; + } + if (buf.hasRemaining()) + { + raw.close(); + throw new EOFException(); + } + buf.flip(); + long dummy + = (wordSize == 4) ? (buf.getInt() & 0xffffffffL) : buf.getLong(); + if (dummy != wordSize) + throw new IOException("Bad .bytes file header"); + long start + = wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong(); + long length + = wordSize == 4 ? (buf.getInt() & 0xffffffffL) : buf.getLong(); + if (length < 0L) + throw new IOException("Bad .bytes file header"); + + long currentPos = raw.position(); + raw.position(currentPos + length); + + Range range = new Range(start, start + length, + rawFileName, currentPos); + map.add(range); + } + + for (;;) + { + String s = reader.readLine(); + if (s == null) + break; + if (s.indexOf("Begin address map") >= 0) + { + for (;;) + { + s = reader.readLine(); + if (s.indexOf("End address map") >= 0) + { + dump(); + return; + } + int endOfAddress = s.indexOf('-'); + long address = parseHexLong(s.substring(0, endOfAddress)); + int endOfAddress2 = s.indexOf(' ', endOfAddress + 1); + long address2 = parseHexLong(s.substring(endOfAddress + 1, + endOfAddress2)); + int endOfOffset = s.indexOf(' ', endOfAddress2 + 6); + long offset; + try + { + offset = parseHexLong(s.substring(endOfAddress2 + 6, + endOfOffset)); + } + catch (Exception e) + { + offset = 0; + } + int end = s.indexOf('/'); + + if (end > 0) + { + String file = s.substring(end); + if (file.startsWith("/dev/")) + continue; + + Range r = new Range(address, address2, file, offset); + if (offset == 0) + { + // Read the file's symbol table + try + { + File f = ToolPrefix.fileForName(file); + if (f != null) + { + SymbolTable st = new SymbolTable(f.getPath()); + if (st.loadAddr != address) + st.relocation = address - st.loadAddr; + symbolTables.put(file, st); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + map.add(r); + } + } // inner loop + } // started inner loop + } // outer loop - finding begin + } // memoryMap + + + public void dump() + { + System.out.println("MemoryMap:"); + for (Range r : map) + { + System.out.println(Long.toHexString(r.begin) + "-" + + Long.toHexString(r.end) + " -> " + + r.filename + " offset " + + Long.toHexString(r.offset)); + } + } + + Range getRange(long addr) + { + Range r = new Range(); + r.begin = addr; + SortedSet t = map.tailSet(r); + if (t.isEmpty()) + return null; + Range c = t.first(); + if (c.begin <= addr && addr < c.end) + return c; + return null; + } + + String getFile(long addr) + { + Range r = getRange(addr); + if (null != r) + return r.filename; + return null; + } + + long getOffset(long addr) + { + Range r = getRange(addr); + if (null != r) + return r.offset; + return 0L; + } + + /** + * @return BytePtr which includes given address. + */ + BytePtr getBytePtr(long addr, int length) throws IOException + { + Range r = getRange(addr); + + if (null == r) + return null; + + File f = ToolPrefix.fileForName(r.filename); + if (null == f) + return null; + + if (addr + length > r.end) + length = (int)(r.end - addr); + + ByteBuffer b = ByteBuffer.allocate(length); + b.order(byteOrder); + + FileChannel fc = (new RandomAccessFile(f, "r")).getChannel(); + fc.position(r.offset + addr - r.begin); + int nr = fc.read(b); + fc.close(); + if (nr != length) + return null; + b.flip(); + return new BytePtr(b, wordSize); + } + + public String getSymbol(long addr) + { + Range r = getRange(addr); + + if (r == null) + return null; + + SymbolTable st = symbolTables.get(r.filename); + if (st == null) + return null; + + // Apply relocation + addr -= st.relocation; + + return st.getSymbol(addr); + } +} -- cgit v1.2.3