SymbolTable.java 5.4 KB

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