Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / gnu / gcj / runtime / NameFinder.java
blob4c629bb22ece41693845f8e5d9abfedf7fbf8778
1 /* NameFinder.java -- Translates addresses to StackTraceElements.
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of libgcj.
6 This software is copyrighted work licensed under the terms of the
7 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
8 details. */
10 package gnu.gcj.runtime;
12 import gnu.classpath.Configuration;
13 import gnu.gcj.RawData;
15 import java.lang.StringBuffer;
17 import java.io.BufferedReader;
18 import java.io.BufferedWriter;
19 import java.io.InputStreamReader;
20 import java.io.OutputStreamWriter;
21 import java.io.IOException;
22 import java.io.File;
23 import java.util.Iterator;
24 import java.util.HashMap;
27 /**
28 * Lookup addresses (represented as longs) to find source & line number info.
30 * The following system property is available (defaults to true):
31 * <li>
32 * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code>
33 * Whether an external process, addr2line, should be used to look up
34 * source file and line number info. Throwable.printStackTrace() will
35 * be faster if this property is set to 'false'.
36 * </ul>
37 * </li>
39 * <code>close()</code> should be called to get rid of all resources.
41 * This class is used from <code>java.lang.VMThrowable</code>.
43 * @author Mark Wielaard (mark@klomp.org)
45 public class NameFinder
47 /**
48 * The name of the binary to look up.
50 private String binaryFile;
51 private String sourceFile;
52 private int lineNum;
53 private HashMap procs = new HashMap();
55 private static final boolean use_addr2line
56 = Boolean.valueOf(System.getProperty
57 ("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
58 ).booleanValue();
60 class Addr2Line
62 Process proc;
63 BufferedWriter out;
64 BufferedReader in;
66 Addr2Line(String binaryFile)
68 try
70 String[] exec = new String[] {"addr2line", "-e", binaryFile};
71 Runtime runtime = Runtime.getRuntime();
72 proc = runtime.exec(exec);
74 catch (IOException ioe)
78 if (proc != null)
80 in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
81 out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
85 void close()
87 try
89 if (in != null)
90 in.close();
91 if (out != null)
92 out.close();
94 catch (IOException x) {}
95 if (proc != null)
96 proc.destroy();
101 * Create a new NameFinder to lookup names in binaryFile. Call close to get rid of any
102 * resources created while using the <code>lookup</code> methods.
104 public NameFinder()
109 * Returns the source file name if lookup() was successful. If the source file could not be
110 * determined, the binary name will be returned instead.
112 public String getSourceFile()
114 String file;
115 if (sourceFile != null)
116 file = sourceFile;
117 else
118 file = binaryFile;
120 return file.substring(file.lastIndexOf(File.separator) + 1, file.length());
124 * If lookup() was successful, returns the line number of addr. If the line number could not
125 * be determined, -1 is returned.
127 public int getLineNum()
129 return lineNum;
132 public void lookup (String file, long addr)
134 binaryFile = file;
135 sourceFile = null;
136 lineNum = -1;
138 if (! use_addr2line)
139 return;
140 Addr2Line addr2line = (Addr2Line) procs.get(file);
141 if (addr2line == null)
143 addr2line = new Addr2Line(file);
144 procs.put(file, addr2line);
147 if (addr2line.proc == null)
148 return;
150 String hexAddr = "0x" + Long.toHexString(addr);
151 String name;
155 addr2line.out.write(hexAddr);
156 addr2line.out.newLine();
157 addr2line.out.flush();
158 String result = addr2line.in.readLine();
160 if (result.indexOf("??") == -1)
162 int split = result.lastIndexOf(':');
163 sourceFile = result.substring(0, split);
164 String lineNumStr = result.substring(split + 1, result.length());
165 lineNum = Integer.parseInt (lineNumStr);
168 catch (IOException ioe)
170 addr2line = null;
172 catch (NumberFormatException x)
178 * Returns human readable method name and aguments given a method type
179 * signature as known to the interpreter and a classname.
181 public static String demangleInterpreterMethod(String m, String cn)
183 int index = 0;
184 int length = m.length();
185 StringBuffer sb = new StringBuffer(length);
187 // Figure out the real method name
188 if (m.startsWith("<init>"))
190 String className;
191 int i = cn.lastIndexOf('.');
192 if (i < 0)
193 className = cn;
194 else
195 className = cn.substring(i + 1);
196 sb.append(className);
197 index += 7;
199 else
201 int i = m.indexOf('(');
202 if (i > 0)
204 sb.append(m.substring(0,i));
205 index += i + 1;
209 sb.append('(');
211 // Demangle the type arguments
212 int arrayDepth = 0;
213 char c = (index < length) ? m.charAt(index) : ')';
214 while (c != ')')
216 String type;
217 switch(c)
219 case 'B':
220 type = "byte";
221 break;
222 case 'C':
223 type = "char";
224 break;
225 case 'D':
226 type = "double";
227 break;
228 case 'F':
229 type = "float";
230 break;
231 case 'I':
232 type = "int";
233 break;
234 case 'J':
235 type = "long";
236 break;
237 case 'S':
238 type = "short";
239 break;
240 case 'Z':
241 type = "boolean";
242 break;
243 case 'L':
244 int i = m.indexOf(';', index);
245 if (i > 0)
247 type = m.substring(index+1, i);
248 index = i;
250 else
251 type = "<unknown ref>";
252 break;
253 case '[':
254 type = "";
255 arrayDepth++;
256 break;
257 default:
258 type = "<unknown " + c + '>';
260 sb.append(type);
262 // Handle arrays
263 if (c != '[' && arrayDepth > 0)
264 while (arrayDepth > 0)
266 sb.append("[]");
267 arrayDepth--;
270 index++;
271 char nc = (index < length) ? m.charAt(index) : ')';
272 if (c != '[' && nc != ')')
273 sb.append(", ");
274 c = nc;
277 // Stop. We are not interested in the return type.
278 sb.append(')');
279 return sb.toString();
283 * Releases all resources used by this NameFinder.
285 public void close()
287 Iterator itr = procs.values().iterator();
288 while (itr.hasNext())
290 Addr2Line proc = (Addr2Line) itr.next();
291 proc.close();