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
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
;
23 import java
.util
.Iterator
;
24 import java
.util
.HashMap
;
28 * Lookup addresses (represented as longs) to find source & line number info.
30 * The following system property is available (defaults to true):
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'.
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
48 * The name of the binary to look up.
50 private String binaryFile
;
51 private String sourceFile
;
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")
66 Addr2Line(String binaryFile
)
70 String
[] exec
= new String
[] {"addr2line", "-e", binaryFile
};
71 Runtime runtime
= Runtime
.getRuntime();
72 proc
= runtime
.exec(exec
);
74 catch (IOException ioe
)
80 in
= new BufferedReader(new InputStreamReader(proc
.getInputStream()));
81 out
= new BufferedWriter(new OutputStreamWriter(proc
.getOutputStream()));
94 catch (IOException x
) {}
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.
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()
115 if (sourceFile
!= null)
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()
132 public void lookup (String file
, long addr
)
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)
150 String hexAddr
= "0x" + Long
.toHexString(addr
);
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
)
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
)
184 int length
= m
.length();
185 StringBuffer sb
= new StringBuffer(length
);
187 // Figure out the real method name
188 if (m
.startsWith("<init>"))
191 int i
= cn
.lastIndexOf('.');
195 className
= cn
.substring(i
+ 1);
196 sb
.append(className
);
201 int i
= m
.indexOf('(');
204 sb
.append(m
.substring(0,i
));
211 // Demangle the type arguments
213 char c
= (index
< length
) ? m
.charAt(index
) : ')';
244 int i
= m
.indexOf(';', index
);
247 type
= m
.substring(index
+1, i
);
251 type
= "<unknown ref>";
258 type
= "<unknown " + c
+ '>';
263 if (c
!= '[' && arrayDepth
> 0)
264 while (arrayDepth
> 0)
271 char nc
= (index
< length
) ? m
.charAt(index
) : ')';
272 if (c
!= '[' && nc
!= ')')
277 // Stop. We are not interested in the return type.
279 return sb
.toString();
283 * Releases all resources used by this NameFinder.
287 Iterator itr
= procs
.values().iterator();
288 while (itr
.hasNext())
290 Addr2Line proc
= (Addr2Line
) itr
.next();