summaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj/runtime/NameFinder.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/gnu/gcj/runtime/NameFinder.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/gnu/gcj/runtime/NameFinder.java')
-rw-r--r--libjava/gnu/gcj/runtime/NameFinder.java341
1 files changed, 341 insertions, 0 deletions
diff --git a/libjava/gnu/gcj/runtime/NameFinder.java b/libjava/gnu/gcj/runtime/NameFinder.java
new file mode 100644
index 000000000..0742af193
--- /dev/null
+++ b/libjava/gnu/gcj/runtime/NameFinder.java
@@ -0,0 +1,341 @@
+/* NameFinder.java -- Translates addresses to StackTraceElements.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+ 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.runtime;
+
+import gnu.classpath.Configuration;
+import gnu.gcj.RawData;
+
+import java.lang.StringBuffer;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+import java.io.File;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * Lookup addresses (represented as longs) to find source & line number info.
+ *
+ * The following system property is available (defaults to true):
+ * <li>
+ * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code>
+ * Whether an external process, addr2line, should be used to look up
+ * source file and line number info. Throwable.printStackTrace() will
+ * be faster if this property is set to 'false'.
+ * </ul>
+ * <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code>
+ * Whether calls to unknown functions (class and method names are unknown)
+ * should be removed from the stack trace. </ul>
+ * </li>
+ *
+ * <code>close()</code> should be called to get rid of all resources.
+ *
+ * This class is used from <code>java.lang.VMThrowable</code>.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class NameFinder
+{
+ /**
+ * The name of the binary to look up.
+ */
+ private String binaryFile;
+ private String sourceFile;
+ private int lineNum;
+ private HashMap procs = new HashMap();
+ /**
+ * Set of binary files that addr2line should not be called on.
+ */
+ private static Set blacklist = Collections.synchronizedSet(new HashSet());
+
+ private static boolean use_addr2line
+ = Boolean.valueOf(System.getProperty
+ ("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
+ ).booleanValue();
+
+ private static boolean show_raw
+ = Boolean.valueOf(System.getProperty
+ ("gnu.gcj.runtime.NameFinder.show_raw", "false")
+ ).booleanValue();
+
+ /**
+ * Return true if raw addresses should be printed in stacktraces
+ * when no line number information is available.
+ */
+ static final boolean showRaw()
+ {
+ return show_raw;
+ }
+
+ private static final boolean remove_unknown
+ = Boolean.valueOf(System.getProperty
+ ("gnu.gcj.runtime.NameFinder.remove_unknown", "true")
+ ).booleanValue();
+
+ /**
+ * Return true if non-Java frames should be removed from stack
+ * traces.
+ */
+ static final boolean removeUnknown()
+ {
+ return remove_unknown;
+ }
+
+ class Addr2Line
+ {
+ Process proc;
+ BufferedWriter out;
+ BufferedReader in;
+
+ Addr2Line(String binaryFile)
+ {
+ try
+ {
+ String[] exec = new String[] {"addr2line", "-e", binaryFile};
+ Runtime runtime = Runtime.getRuntime();
+ proc = runtime.exec(exec);
+ }
+ catch (IOException ioe)
+ {
+ }
+
+ if (proc != null)
+ {
+ in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+ out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
+ }
+ }
+
+ void close()
+ {
+ try
+ {
+ if (in != null)
+ in.close();
+ if (out != null)
+ out.close();
+ }
+ catch (IOException x) {}
+ if (proc != null)
+ proc.destroy();
+ }
+ }
+
+ /**
+ * Create a new NameFinder to lookup names in binaryFile. Call close to get rid of any
+ * resources created while using the <code>lookup</code> methods.
+ */
+ public NameFinder()
+ {
+ }
+
+ /**
+ * Returns the source file name if lookup() was successful. If the source file could not be
+ * determined, the binary name will be returned instead.
+ */
+ public String getSourceFile()
+ {
+ String file;
+ if (sourceFile != null)
+ file = sourceFile;
+ else
+ file = binaryFile;
+
+ return file.substring(file.lastIndexOf(File.separator) + 1, file.length());
+ }
+
+ /**
+ * If lookup() was successful, returns the line number of addr. If the line number could not
+ * be determined, -1 is returned.
+ */
+ public int getLineNum()
+ {
+ return lineNum;
+ }
+
+ public void lookup (String file, long addr)
+ {
+ binaryFile = file;
+ sourceFile = null;
+ lineNum = -1;
+
+ if (! use_addr2line || blacklist.contains(file))
+ return;
+ Addr2Line addr2line = (Addr2Line) procs.get(file);
+ if (addr2line == null)
+ {
+ addr2line = new Addr2Line(file);
+ procs.put(file, addr2line);
+ }
+
+ if (addr2line.proc == null)
+ {
+ use_addr2line = false;
+ return;
+ }
+
+ String hexAddr = "0x" + Long.toHexString(addr);
+ String name;
+
+ try
+ {
+ addr2line.out.write(hexAddr);
+ addr2line.out.newLine();
+ addr2line.out.flush();
+ String result = addr2line.in.readLine();
+
+ if (result.indexOf("??") == -1)
+ {
+ int split = result.lastIndexOf(':');
+ sourceFile = result.substring(0, split);
+ String lineNumStr = result.substring(split + 1, result.length());
+ lineNum = Integer.parseInt (lineNumStr);
+ }
+ else
+ {
+ /* This binary has no debug info (assuming addr was valid).
+ Avoid repeat addr2line invocations. */
+ blacklist.add(binaryFile);
+ }
+ }
+ catch (IOException ioe)
+ {
+ addr2line = null;
+ }
+ catch (NumberFormatException x)
+ {
+ }
+ }
+
+ /**
+ * Returns human readable method name and aguments given a method type
+ * signature as known to the interpreter and a classname.
+ */
+ public static String demangleInterpreterMethod(String m, String cn)
+ {
+ int index = 0;
+ int length = m.length();
+ StringBuffer sb = new StringBuffer(length);
+
+ // Figure out the real method name
+ if (m.startsWith("<init>"))
+ {
+ String className;
+ int i = cn.lastIndexOf('.');
+ if (i < 0)
+ className = cn;
+ else
+ className = cn.substring(i + 1);
+ sb.append(className);
+ index += 7;
+ }
+ else
+ {
+ int i = m.indexOf('(');
+ if (i > 0)
+ {
+ sb.append(m.substring(0,i));
+ index += i + 1;
+ }
+ }
+
+ sb.append('(');
+
+ // Demangle the type arguments
+ int arrayDepth = 0;
+ char c = (index < length) ? m.charAt(index) : ')';
+ while (c != ')')
+ {
+ String type;
+ switch(c)
+ {
+ case 'B':
+ type = "byte";
+ break;
+ case 'C':
+ type = "char";
+ break;
+ case 'D':
+ type = "double";
+ break;
+ case 'F':
+ type = "float";
+ break;
+ case 'I':
+ type = "int";
+ break;
+ case 'J':
+ type = "long";
+ break;
+ case 'S':
+ type = "short";
+ break;
+ case 'Z':
+ type = "boolean";
+ break;
+ case 'L':
+ int i = m.indexOf(';', index);
+ if (i > 0)
+ {
+ type = m.substring(index+1, i);
+ index = i;
+ }
+ else
+ type = "<unknown ref>";
+ break;
+ case '[':
+ type = "";
+ arrayDepth++;
+ break;
+ default:
+ type = "<unknown " + c + '>';
+ }
+ sb.append(type);
+
+ // Handle arrays
+ if (c != '[' && arrayDepth > 0)
+ while (arrayDepth > 0)
+ {
+ sb.append("[]");
+ arrayDepth--;
+ }
+
+ index++;
+ char nc = (index < length) ? m.charAt(index) : ')';
+ if (c != '[' && nc != ')')
+ sb.append(", ");
+ c = nc;
+ }
+
+ // Stop. We are not interested in the return type.
+ sb.append(')');
+ return sb.toString();
+ }
+
+ /**
+ * Releases all resources used by this NameFinder.
+ */
+ public void close()
+ {
+ Iterator itr = procs.values().iterator();
+ while (itr.hasNext())
+ {
+ Addr2Line proc = (Addr2Line) itr.next();
+ proc.close();
+ }
+ }
+}