Patch: Improve demangling w.r.t. possible underscore prefix
Ranjit Mathew
rmathew@hotmail.com
Sun Feb 16 15:12:00 GMT 2003
Hi,
This patch proposes to add GCC's USER_LABEL_PREFIX to the
symbols returned by addr2line so that they are at par with those
returned by addr2name.awk or dladdr( ), i.e. on systems where an
underscore is used as a prefix for names exported from C/C++/Java
programs, this allows c++filt to correctly demangle names generated
by addr2line, which uses symbolic debugging information instead of
the actual exported labels that are used by dladdr and
addr2name.awk (via "nm").
The train of reasoning leading to this patch can be found in the
thread starting from this message:
http://gcc.gnu.org/ml/java/2003-02/msg00145.html
__USER_LABEL_PREFIX__ is a predefined macro in the GCC preprocessor
that stands for the string (*not* string constant) that is prefixed
to a method name when it is exported as a label.
The XGLUE/GLUE idiom you see in the patch is borrowed from the
GCC sources and has been the only way I could make this
macro work as needed. I do not completely understand why the double
macro indirection is the only way it works. :-( (Search for
"__USER_LABEL_PREFIX__" within the subfolders of the "gcc/config"
folder in the GCC sources for instances of its usage within GCC.)
I have checked this patch with the current 3.3 snapshot on
Win32 (MinGW). I would greatly appreciate if someone could also
test this out on some other platform, say Linux, especially one
that does not have such a prefix, before committing it.
With this patch in place, stacktraces on Win32 finally show up
as one would expect them to, complete with class names
and method signatures!
Ranjit.
Index: ChangeLog
from Ranjit Mathew <rmathew@hotmail.com>
* gnu/gcj/runtime/NameFinder.java (usingAddr2name): New flag
to indicate if we are using addr2name.awk instead of addr2line.
(NameFinder): Set usingAddr2name to true if we have had to use
addr2name.awk instead of addr2line.
(getExternalLabel): New native method.
(lookup): If using addr2line, convert method name to an external
label using getExternalLabel( ).
* gnu/gcj/runtime/natNameFinder.cc (EXT_LABEL): New macro that
converts a name to an external label using the predefined GCC
preprocessor macro __USER_LABEL_PREFIX__.
(getExternalLabel): Define using EXT_LABEL.
Index: gnu/gcj/runtime/NameFinder.java
===================================================================
--- gnu/gcj/runtime/NameFinder.java 2003年02月13日 00:14:40.000000000 +0530
+++ gnu/gcj/runtime/NameFinder.java 2003年02月16日 13:56:22.000000000 +0530
@@ -104,4 +104,9 @@
/**
+ * Flag set if using addr2name.awk instead of addr2line from binutils.
+ */
+ private boolean usingAddr2name = false;
+
+ /**
* Creates a new NameFinder. Call close to get rid of any resources
* created while using the <code>lookup</code> methods.
@@ -143,4 +148,5 @@
String[] exec = new String[] {"addr2name.awk", executable};
addr2line = runtime.exec(exec);
+ usingAddr2name = true;
}
catch (IOException ioe2) { addr2line = null; }
@@ -182,4 +188,9 @@
/**
+ * Returns the label that is exported for the given name.
+ */
+ native private String getExternalLabel(String name);
+
+ /**
* If nth element of stack is an interpreted frame, return the
* element representing the method being interpreted.
@@ -213,4 +224,13 @@
name = addr2lineIn.readLine();
file = addr2lineIn.readLine();
+
+ // addr2line uses symbolic debugging information instead
+ // of the actually exported labels as addr2name.awk does.
+ // This name might need to be prefixed with an underscore,
+ // depending on the system, to make it consistent with
+ // those returned by addr2name.awk and dladdr.
+ if (! usingAddr2name)
+ if (name != null && ! "??".equals (name))
+ name = getExternalLabel (name);
}
catch (IOException ioe) { addr2line = null; }
Index: gnu/gcj/runtime/natNameFinder.cc
===================================================================
--- gnu/gcj/runtime/natNameFinder.cc 2003年02月16日 13:57:19.000000000 +0530
+++ gnu/gcj/runtime/natNameFinder.cc 2003年02月16日 15:28:48.000000000 +0530
@@ -29,4 +29,41 @@
#endif
+// On some systems, a prefix is attached to a name before
+// it is exported. The GCC preprocessor predefines this prefix
+// as the macro __USER_LABEL_PREFIX__. If used, this prefix
+// is usually just the underscore character.
+#undef EXT_LABEL
+#ifdef __USER_LABEL_PREFIX__
+
+#undef XGLUE
+#undef GLUE
+#define XGLUE(a,b) a ## b
+#define GLUE(a,b) XGLUE (a,b)
+
+#define EXT_LABEL(x) GLUE (__USER_LABEL_PREFIX__,x)
+
+#else /* __USER_LABEL_PREFIX__ */
+
+#define EXT_LABEL(x) x
+
+#endif /* ! __USER_LABEL_PREFIX__ */
+
+java::lang::String*
+gnu::gcj::runtime::NameFinder::getExternalLabel (java::lang::String* name)
+{
+ goto EXT_LABEL (transform);
+
+transform:
+ return name;
+
+_transform:
+ jsize nameLen = JvGetStringUTFLength (name);
+ char *newName = (char *) JvMalloc (1 + nameLen + 1);
+ *(newName + 0) = '_';
+ JvGetStringUTFRegion (name, 0, nameLen, newName + 1);
+ *(newName + 1 + nameLen) = '0円';
+ return JvNewStringLatin1 (newName);
+}
+
java::lang::String*
gnu::gcj::runtime::NameFinder::getExecutable (void)
More information about the Java
mailing list