1 /* SymbolTable.java -- Maintains a mapping of addresses to names. 2 Copyright (C) 2007 Free Software Foundation 3 4 This file is part of libgcj. 5 6 This software is copyrighted work licensed under the terms of the 7 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for 8 details. */ 9 10 package gnu.gcj.tools.gc_analyze; 11 12 import java.io.BufferedReader; 13 import java.io.IOException; 14 import java.io.InputStream; 15 import java.io.InputStreamReader; 16 import java.util.HashMap; 17 import java.util.Map; 18 import java.util.regex.Matcher; 19 import java.util.regex.Pattern; 20 21 class SymbolTable 22 { 23 // Long address->String name 24 private HashMap<Long, String> map = new HashMap<Long, String>(); 25 26 // Reverse 27 // String name -> Long address 28 // used for RelocateImage 29 private HashMap<String, Long> reverse = new HashMap<String, Long>(); 30 31 long loadAddr; 32 long relocation; 33 34 static Matcher interestingSymbol = 35 Pattern.compile("^([0-9a-fA-F]+)\\s+\\S+\\s+(_Z\\S+)").matcher(""); 36 static Matcher readelfLoadMatcher = 37 Pattern.compile("^\\s+LOAD\\s+(\\S+)\\s+(\\S+)\\s.*").matcher(""); 38 SymbolTable(String filename)39 public SymbolTable(String filename) throws IOException 40 { 41 Process p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix 42 + "nm " + filename); 43 InputStream es = p.getErrorStream(); 44 InputStream is = p.getInputStream(); 45 46 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 47 int count = 0; 48 49 String line; 50 while ((line = reader.readLine()) != null) 51 { 52 interestingSymbol.reset(line); 53 if (interestingSymbol.matches()) 54 { 55 try 56 { 57 String name = interestingSymbol.group(2); 58 String addr = interestingSymbol.group(1); 59 if (name.startsWith("_ZTVN") || name.endsWith("6class$E")) 60 { 61 long address = MemoryMap.parseHexLong(addr); 62 Long l = new Long(address); 63 map.put(l, name); 64 count++; 65 reverse.put(name, l); 66 } 67 } 68 catch (NumberFormatException e) 69 { 70 // ignore it 71 } 72 } 73 } 74 es.close(); 75 is.close(); 76 p.destroy(); 77 78 if (count > 0) 79 { 80 // Assume nm read some symbols from it and that 81 // readelf can tell us something about how it is loaded. 82 p = Runtime.getRuntime().exec(ToolPrefix.toolPrefix 83 + "readelf -l " + filename); 84 es = p.getErrorStream(); 85 is = p.getInputStream(); 86 87 reader = new BufferedReader(new InputStreamReader(is)); 88 while ((line = reader.readLine()) != null) 89 { 90 readelfLoadMatcher.reset(line); 91 if (readelfLoadMatcher.matches()) 92 { 93 loadAddr 94 = Long.decode(readelfLoadMatcher.group(2)).longValue(); 95 break; 96 } 97 } 98 es.close(); 99 is.close(); 100 p.destroy(); 101 } 102 103 System.out.println(ToolPrefix.toolPrefix + "nm " + filename 104 + " -> " + count + " symbols"); 105 } 106 main(String args[])107 public static void main(String args[]) 108 { 109 try 110 { 111 SymbolTable st = new SymbolTable(args[0]); 112 st.dump(); 113 } 114 catch (Exception ex) 115 { 116 ex.printStackTrace(); 117 } 118 } 119 demangleVTName(String n)120 public static String demangleVTName(String n) 121 { 122 if (n.startsWith("_ZTVN") && n.endsWith("E")) 123 return demangle(n.substring(5, n.length() - 1)); 124 else 125 return null; 126 } 127 dump()128 public void dump() 129 { 130 for (Map.Entry<Long, String> me : map.entrySet()) 131 { 132 long address = me.getKey(); 133 String symbol = me.getValue(); 134 System.out.println(Long.toHexString(address) + " -> " + symbol); 135 if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E")) 136 { 137 System.out.println(" Class: " 138 + demangle(symbol.substring(3, symbol.length() 139 - 8))); 140 } 141 else if (symbol.startsWith("_ZTVN") && symbol.endsWith("E")) 142 { 143 System.out.println(" VT: " 144 + demangle(symbol.substring(5, symbol.length() 145 - 1))); 146 } 147 } 148 } 149 demangle(String symbol)150 private static String demangle(String symbol) 151 { 152 StringBuilder sb = new StringBuilder(); 153 for (int i=0; i<symbol.length(); ) 154 { 155 int l = 0; 156 while (i < symbol.length()) 157 { 158 int d = symbol.charAt(i); 159 if (d < '0' || d > '9') 160 break; 161 l = 10 * l + (d - '0'); 162 i++; 163 } 164 if (l == 0) 165 break; 166 // copy 167 if (sb.length() > 0) 168 sb.append('.'); 169 while (l > 0 && i < symbol.length()) 170 { 171 sb.append(symbol.charAt(i)); 172 l--; 173 i++; 174 } 175 } 176 return sb.toString(); 177 } 178 getSymbol(long address)179 public String getSymbol(long address) 180 { 181 String symbol = map.get(address); 182 if (symbol == null) 183 return null; 184 185 if (symbol.startsWith("_ZN") && symbol.endsWith("6class$E")) 186 symbol = demangle(symbol.substring(3, symbol.length() - 8)); 187 return symbol; 188 } 189 190 // will return -1 if not found getAddress(String symbol)191 public long getAddress(String symbol) 192 { 193 Long address = reverse.get(symbol); 194 if (address == null) 195 return -1; 196 return address.longValue(); 197 } 198 } 199