Demangling with c++filt on windows - gnu-v3 - c++

I am trying to properly demangle some symbols taken from a DWARF output.
On Linux, when i do c++filt --format gnu-v3. I can convert _ZZNV9SomeClass5afuncEiE1x to SomeClass::afunc(int) volatile::x
On Windows, I have installed Mingw32 which includes c++filt. The same command line yield the input, which means it hasn't been able to demangle.
What could cause this?
I assumed that specifying the format (gnu-v3) would be enough to make it work cross platform.

Related

Failure to demangle symbol name in library (nm, objdump, c++filt)

I noticed non-demangled functions in my output of perf script and originally thought perf might be doing something wrong.
But, looking deeper into some of the *.so files, I've been able to reproduce the problem with c++filt -t, nm -C, and objdump -D -C.
I'm a bit lost as to what could possibly be going wrong in the demangling process.
One of the symbols that isn't getting demangled is:
_ZZNK5Gaudi10Functional7details16MultiTransformerIFSt5tupleIJSt6vectorIN4LHCb14VPLightClusterESaIS6_EESt5arrayIjLm53EEEERK12EventContextRKNS5_8RawEventERK4DeVPENS0_6Traits4use_IJNS5_7DetDesc21useConditionHandleForIJSI_EEENSM_11BaseClass_tINSO_23ConditionAccessorHolderI10FixTESPathINS_9AlgorithmEEEEEEEEELb0EE7executeESE_ENKUlDpRT_E_clIJK21DataObjectWriteHandleIS8_S8_EKS15_ISA_SA_EEEEDaS12_
The library was compiled with GCC 10.1. But if I compile with clang 11, I can find the same symbol in objdump -D -C.
I'm a bit at a dead end now, so any suggestions as to what I could possibly check would be really appreciated. :)
Resolved by using the tool suggested in the comments.
llvm-cxxfilt also works and might be already available on some machines.
c++filt, nm, perf, and objdump use functionality that is implemented in libiberty which is part of GCC.
Thus I've filed a bug report there: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102851

What are mechanisms of selection of emulation mode for a linker?

I am trying to compile arduino code under codeblocks with avr-gnu compiler. I was getting this error:
avr-ld.exe unrecognized emulation mode: mcu=atmega328p.
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
I found this page: https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html which suggests that it should be linked under avr5 sim mode, so I added -mmcu=avr5 to linker options. Now I am getting:
avr-ld.exe unrecognized emulation mode: mcu=avr5
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
How is avr5 unrecognized if it is supported?o0
I tried few different toolchains from few different years but it seems that linker cant interpret this emulation mode correctly. Newer toolchains had support for 328p but still somehow dont work. I also tried creating CodeBlocks project dedicated for Arduino but the difference is that it passes -mmcu=atmega328p itself and still doesnt work on this or newer toolchains.
Update:
There is something that I am totally missing here. I changed linker to a standard x86 32 ld.exe from Mingw and passed -mmcu=i386pe and I am getting the similar error:
ld.exe unrecognized emulation mode: mcu=i386pe
Supported emulations:i386pe
So this only leads to my lack of understanding of mechanisms how the linker emulation mode is selected/configured.
In almost any case, you do not want to call the linker (ld resp. avr-ld) by hand!
Use avr-gcc to link your programs!
Notice that avr-gcc is not a compiler by itself, it's just a driver program that calls sub-programs like compiler proper (cc1 for C, cc1plus for C++, lto1 for LTO-compiled byte-code), assembler and linker depending on command-line options and input files provided on the command line.
avr-gcc knows how to provide the respective tools with appropriate command line options like: emulation, libraries, paths for includes and libraries, startup-code, sub-options, etc.
In order to see which tools are called by avr-gcc, add the -v option. For example, for a compile command as simple as
> avr-gcc -v main.c -mmcu=atmega328p -save-temps
You'll see somethinh like (here for avr-gcc v8.5.0):
...
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-specs=device-specs/specs-atmega328p' '-mmcu=avr5'
$AVRGCC_HOME/bin/../libexec/gcc/avr/8.5.0/collect2 <many options> -plugin-opt=-pass-through=-latmega328p -mavr5 -Tdata 0x800100 $AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5/crtatmega328p.o -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0 -L$AVRGCC_HOME/bin/../lib/gcc -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib main.o --start-group -lgcc -lm -lc -latmega328p --end-group
collect2 is just some other tool that wraps the call to ld. If you want to see the real thing, use avr-gcc ... -v -Wl,-v.
The correct emulation for the linker is worked out by the device-specific spec file device-specs/specs-atmega328p located at ./lib/gcc/avr/$version in the compiler's install directory. The specs "language" is a means to describe option mappings; in particular the bits that are responsible for mapping `-mmcu=atmega328p' to the right emulation are
*link_arch:
%{mmcu=*:-m%*}
...
*self_spec:
%{!mmcu=avr*: %<mmcu=* -mmcu=avr5} %<mshort-calls %<msp8
self_spec removes -mmcu=* from the command line and sets -mmcu=avr5 which is the core family ATmega328P belongs to. Then as part of the linker invocation, link_arch maps -mmcu=avr5 to -mavr5 which is the linker emulation to be used.

How do you use c++filt with llvm-cov report?

I'm trying to use a demangler with the llvm-cov report tool. The following is the command I'm running:
llvm-cov report /path/to/executable -instr-profile /path/to/default.profdata /path/to/src/ -Xdemangler c++filt -Xdemangler -n
I've tried rearranging the options and have tried using "-Xdemangler=c++filt -Xdemangler=-n" instead, and also using --no-strip-underscore instead of -n. It does not complain about the demangler, whereas if I make an obvious error with the command syntax it does tell me, but the output is not demangled.
From the llvm-cov documentation:
-Xdemangler=< TOOL >|< TOOL-OPTION >
Specify a symbol demangler. This can be used to make reports more human-readable. This option can be specified multiple times to supply arguments to the demangler (e.g -Xdemangler c++filt -Xdemangler -n for C++). The demangler is expected to read a newline-separated list of symbols from stdin and write a newline-separated list of the same length to stdout.
I've used the following to ensure that c++filt works, and it does:
c++filt -n _ZN4core6ZipperC2ENSt3__110shared_ptrIN8core_gen14PlatformZipperEEE
Output:
core::Zipper::Zipper(std::__1::shared_ptr<core_gen::PlatformZipper>)
I have to use the -n option, or it will not demangle, but I'm at a loss for why llvm-cov does not seem to be using it correctly.
I've also tried using a shell script to try to capture the input llvm-cov gives to the demangler and write it to a file before invoking c++filt, but the file was empty when I looked after running the command.
Am I doing something wrong?
It appears use of demangled function names is not hooked in everywhere in llvm-cov.
This report (the -name-regex option is needed to produce function names) does respond to the -Xdemangler option:
llvm-cov report /path/to/exe -name-regex=\.* -instr-profile=default.profdata -Xdemangler=c++filt
I see it's fixed in https://reviews.llvm.org/rL294136

Weird characters in perf output...

I'm trying to debug a webkit build with Linux perf that I compiled with symbols.
The output of "perf report -g" has the symbols with half human readable and the other half alphanumeric values.
For example:
_ZN7WebCore12RenderObject18setAnimatableStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
|
|--91.30%-- _ZN7WebCore4Node14setRenderStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
What's happening here?
What's _ZN7?
My hunch is that this is something to do with C++ and maybe I need to compile with more options to get the symbols to be represented in perf correctly.
ANY pointers here would be appreciated. I can't find anything about this anywhere in the documentation.
These are so-called "mangled names": The C++ compiler encodes type information into symbol names, so that the linker can correctly implement overloading, class scoping and namespaces without having to actually understand the C++ type system, and without having to support characters outside of basic alphanumerics and underscores.
You can turn these back into human-readable names with tools such as c++filt under Linux.
For example:
$ echo _ZN7WebCore12RenderObject18setAnimatableStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE | c++filt
WebCore::RenderObject::setAnimatableStyle(WTF::PassRefPtr<WebCore::RenderStyle>)
Or in your case, perf report -g | c++filt will probably do what you want.

How to map PC (ARMv5) address to source code?

I'm developing on an ARM9E processor running Linux. Sometimes my application crashes with the following message :
[ 142.410000] Alignment trap: rtspserverd (996) PC=0x4034f61c
Instr=0xe591300c Address=0x0000000d FSR 0x001
How can I translate the PC address to actual source code? In other words, how can I make sense out of this message?
With objdump. Dump your executable, then search for 4034f61c:.
The -x, --disassemble, and -l options are particularly useful.
You can turn on listings in the compiler and tell the linker to produce a map file. The map file will give you the meaning of the absolute addresses up to the function where the problem occurs, while the listing will help you pinpoint the exact location of the exception within the function.
For example in gcc you can do
gcc -Wa,-a,-ad -c foo.c > foo.lst
to produce a listing in the file foo.lst.
-Wa, sends the following options to the assembler (gas).
-a tells gas to produce a listing on standard output.
-ad tells gas to omit debug directives, which would otherwise add a lot of clutter.
The option for the GNU linker to produce a map file is -M or --print-map. If you link with gcc you need to pass the option to the linker with an option starting with -Wl,, for example -Wl,-M.
Alternatively you could also run your application in the debugger (e.g. gdb) and look at the stack dump after the crash with the bt command.