objdump shows different function names - g++

I have a cpp file that was compiled into an object file. For some reason, the functions inside the cpp file are named differently so one of the functions is "undefined". I don't know why g++ would label the functions differently.
Here are the relevant objdump output:
root#0b8da3d55c14:~/GF# g++ -g -Wall -o polynomial_arith.o -c polynomial_arith.cpp
root#0b8da3d55c14:~/GF# objdump -t polynomial_arith.o | grep Add
0000000000000219 g F .text 00000000000001fc _Z13polynomialAddPKxsS0_sPxsx
root#0b8da3d55c14:~/GF# objdump -t polynomial_arith.o | grep Sub
0000000000000462 l F .text 0000000000000019 _GLOBAL__sub_I__Z13polynomialSubPKxsS0_iPxsx
0000000000000000 g F .text 0000000000000219 _Z13polynomialSubPKxsS0_iPxsx
root#0b8da3d55c14:~/GF# objdump -t test.o | grep Add
0000000000000000 *UND* 0000000000000000 _Z13polynomialAddPKxsS0_sPxsx
root#0b8da3d55c14:~/GF# objdump -t test.o | grep Sub
0000000000000000 *UND* 0000000000000000 _Z13polynomialSubPKxsS0_sPxsx
You can see that polynomialAdd is _Z13polynomialAddPKxsS0_sPxsx in the object file while polynomialSub is _Z13polynomialSubPKxsS0_iPxsx. The test function (test.o) expects _Z13polynomialAddPKxsS0_sPxsx and _Z13polynomialSubPKxsS0_sPxsx. Thus polynomialSub is undefined because its name in polynomial_arith.o is _Z13polynomialSubPKxsS0_iPxsx, while polynomialAdd is just fine.
Are there special meaning to _iPxsx vs. SPxsx, and why they are generated differently?

$ demumble _Z13polynomialSubPKxsS0_iPxsx
polynomialSub(long long const*, short, long long const*, int, long long*, short, long long)
$ demumble _Z13polynomialSubPKxsS0_sPxsx
polynomialSub(long long const*, short, long long const*, short, long long*, short, long long)
They are different functions with different parameters.

Related

extract source code from ELF with debug symbols

I'm trying to extract the original source code from an ELF with debug symbols.
$ sed -n "14,16p" main.c
for (int p=start;p<end;p++)
if (isPrime(p))
printf("%d\n",p);
I want the "closest", preceeding source line from a given address:
$ gcc -g -O0 main.c -o main
$ objdump -D -S main > main.asm
$ sed -n "451,457p" main.asm
if (isPrime(p))
6ba: 8b 45 f4 mov -0xc(%rbp),%eax
6bd: 89 c7 mov %eax,%edi
6bf: e8 86 ff ff ff callq 64a <isPrime>
6c4: 85 c0 test %eax,%eax
6c6: 74 16 je 6de <main+0x49>
printf("%d\n",p);
So given the 0x6bf call instruction, I would like to extract if (isPrime(p)).
This seems possible since objdump does it (right?)
I'm trying to extract the original source code from an ELF with debug symbols.
That's impossible: the ELF with debug symbols contains no original source code.
What you appear to be after is source code location, i.e. file and line. Armed with file name, line number, and the original source, you can trivially print that line.
To recover file/line info, you could use addr2line -e main 0x6bf.
It turns out that it can be quite easily done with pyelftools:
import elftools
from elftools.elf.elffile import ELFFile as ELF
def addr_2_line(ELFname: str, addr: int) -> int:
with open(ELFname, "rb") as fl:
elf = ELF(fl)
dwarf_info = elf.get_dwarf_info()
for cu in dwarf_info.iter_CUs():
line = 1
for entry in dwarf_info.line_program_for_CU(cu).get_entries():
if entry.state:
if addr > entry.state.address:
line = entry.state.line
else:
return line
address = addr_2_line("main", 0x6bf)
print(f"src code[ 0x6bf ] = {address}")
When I run it it indeed gives the desired line:
src code[ 0x6bf ] = 15
It is probably worth checking if no adjustments are needed when there are more than just one compilation unit (cu)

Why do I see symbol linking error messages when the symbols are present?

I have two object files, one with a couple of symbols defined and one in which those symbols are undefined:
nm ./src/freertos/freertos.o |grep pvPortMalloc
000000000000d045 T pvPortMalloc
...and...
nm ./src/clib/new_delete.o
U _GLOBAL_OFFSET_TABLE_
U _Z12pvPortMalloci
U _Z9vPortFreePv
0000000000000019 T _ZdlPv
0000000000000000 T _Znwm
When I attempt to link them together, I see this:
ld ./src/clib/new_delete.o ./src/freertos/freertos.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld: ./src/clib/new_delete.o: in function `operator new(unsigned long)':
new_delete.cc:(.text+0x13): undefined reference to `pvPortMalloc(int)'
ld: ./src/clib/new_delete.o: in function `operator delete(void*)':
new_delete.cc:(.text+0x2d): undefined reference to `vPortFree(void*)'
Anyone have any ideas?
Your nm listings do not show there is any undefined symbol reported in ./src/clib/new_delete.o
that is defined in ./src/freertos/freertos.o.
There is a similarity between the
symbol pvPortMalloc defined in ./src/freertos/freertos.o and the undefined
symbol _Z12pvPortMalloci in ./src/clib/new_delete.o which I guess leads you to suppose that they are
the same, but the linker does not equate symbols on the basis of any similarity short of identity.
The symbol _Z12pvPortMalloci is the C++ mangled name of:
$ c++filt _Z12pvPortMalloci
pvPortMalloc(int)
showing that ./src/clib/new_delete.o was compiled with a C++ compiler. ./src/freertos/freertos.o,
on the other hand, was compiled with a C compiler, which does not do name-mangling.
If you want to tell your C++ compiler that the external name pvPortMalloc in
your source code is to have C linkage language, and therefore not to mangle it,
you must declare it extern "C".
Wrong
$ cat wrong.cpp
extern void * pvPortMalloc(int);
int main()
{
return pvPortMalloc(42) != nullptr;
}
$ g++ -Wall -c wrong.cpp
$ nm wrong.o
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U _Z12pvPortMalloci
Right
$ cat right.cpp
extern "C" {
void * pvPortMalloc(int);
// And any more...
}
int main()
{
return pvPortMalloc(42) != nullptr;
}
$ g++ -Wall -c right.cpp
$ nm right.o
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U pvPortMalloc

Error cross compiling Tensorflow using contrib/makefile while linking the host proto_text

I have made a short script to cross compile tensorflow and am getting linker errors during linking of proto_text on the host side, however I have checked and I am linking the appropriate library and it appears to contain the correct symbols (see below).
version: tensorflow # tags/v1.4.0-rc1
Here is my script to cross-compile (I could not get the default compile_nsync.sh script working for my case)
unset CC CXX AS AR
pushd tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc
CC=gcc AR=ar CXX=g++ AS=as make clean VERBOSE=1
CC=gcc AR=ar CXX=g++ AS=as make depend VERBOSE=1
CC=gcc AR=ar CXX=g++ AS=as make VERBOSE=1
HOST_NSYNC_LIB="$(pwd)/nsync.a"
popd
export CXX=arm-linux-gnueabihf-g++-6
export CC=arm-linux-gnueabihf-gcc-6
export AR=arm-linux-gnueabihf-ar
export AS=arm-linux-gnueabihf-as
pushd tensorflow/contrib/makefile/downloads/nsync/tools
rm -rf ../builds/arm.linux.arm-linux-gnueabihf-gcc-6
sh mkmakefile.sh -arch arm -os linux -cc arm-linux-gnueabihf-gcc-6
popd
pushd tensorflow/contrib/makefile/downloads/nsync/builds/arm.linux.arm-linux-gnueabihf-gcc-6
make clean VERBOSE=1
#make depend VERBOSE=1
make VERBOSE=1
TARGET_NSYNC_LIB="$(pwd)/nsync.a"
popd
export HOST_NSYNC_LIB TARGET_NSYNC_LIB
echo "HOST nsync: $HOST_NSYNC_LIB"
echo "TARGET nsync: $TARGET_NSYNC_LIB"
make -j -f tensorflow/contrib/makefile/Makefile \
TARGET=LINUX CC_PREFIX="${CC_PREFIX}" \
HOST_CC=gcc HOST_CXX=g++ \
CXX=arm-linux-gnueabihf-g++-6 CC=arm-linux-gnueabihf-gcc-6 \
CXX_FLAGS="-mfpu=neon-vfpv4 -ftree-vectorize" \
HOST_NSYNC_LIB="$HOST_NSYNC_LIB" TARGET_NSYNC_LIB="$TARGET_NSYNC_LIB" \
SUB_MAKEFILES="${SUB_MAKEFILES}" ${EXTRA_MAKE_ARGS[#]}
the halting error
.... /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/grappler/costs/op_performance_data.pb.o -L/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/lib -L/usr/local/lib /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc/nsync.a -lstdc++ -lprotobuf -lpthread -lm -lz -ldl -lpthread
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::mutex()':
env.cc:(.text._ZN10tensorflow5mutexC2Ev[_ZN10tensorflow5mutexC5Ev]+0x14): undefined reference to `nsync::nsync_mu_init(nsync::nsync_mu_s_*)'
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::lock()':
env.cc:(.text._ZN10tensorflow5mutex4lockEv[_ZN10tensorflow5mutex4lockEv]+0x14): undefined reference to `nsync::nsync_mu_lock(nsync::nsync_mu_s_*)'
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::unlock()':
env.cc:(.text._ZN10tensorflow5mutex6unlockEv[_ZN10tensorflow5mutex6unlockEv]+0x14): undefined reference to `nsync::nsync_mu_unlock(nsync::nsync_mu_s_*)'
collect2: error: ld returned 1 exit status
tensorflow/contrib/makefile/Makefile:631: recipe for target '/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_bin/proto_text' failed
make: *** [/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_bin/proto_text] Error 1
Note the nsync library is supplied and no error is thrown saying it cannot be found (quoting above: /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc/nsync.a)
Inspecting the library there it appears to have the symbols. All three missing methods have both "T" & "U" entries...
$nm nsync.a | grep nsync_mu
U nsync_mu_semaphore_init
U nsync_mu_lock
U nsync_mu_semaphore_v
U nsync_mu_unlock
U nsync_mu_lock
U nsync_mu_lock_slow_
U nsync_mu_rlock
U nsync_mu_runlock
U nsync_mu_semaphore_v
U nsync_mu_unlock
0000000000000611 T nsync_mu_debug_state
0000000000000683 T nsync_mu_debug_state_and_waiters
00000000000006f5 T nsync_mu_debugger
00000000000009aa T nsync_mu_assert_held
0000000000000021 T nsync_mu_init
00000000000009e9 T nsync_mu_is_reader
0000000000000213 T nsync_mu_lock
0000000000000031 T nsync_mu_lock_slow_
00000000000009c8 T nsync_mu_rassert_held
00000000000002e3 T nsync_mu_rlock
0000000000000294 T nsync_mu_rtrylock
000000000000090a T nsync_mu_runlock
U nsync_mu_semaphore_p
U nsync_mu_semaphore_v
00000000000001c1 T nsync_mu_trylock
000000000000087d T nsync_mu_unlock
000000000000046c T nsync_mu_unlock_slow_
U nsync_mu_lock_slow_
U nsync_mu_unlock_slow_
000000000000041a T nsync_mu_unlock_without_wakeup
00000000000003e6 T nsync_mu_wait
0000000000000000 T nsync_mu_wait_with_deadline
U nsync_mu_lock
U nsync_mu_semaphore_v
U nsync_mu_trylock
U nsync_mu_unlock
U nsync_mu_wait
U nsync_mu_lock
U nsync_mu_unlock
U nsync_mu_lock
U nsync_mu_semaphore_p_with_deadline
U nsync_mu_unlock
U nsync_mu_semaphore_p_with_deadline
0000000000000000 T nsync_mu_semaphore_init
0000000000000007 T nsync_mu_semaphore_p
000000000000008e T nsync_mu_semaphore_p_with_deadline
00000000000001c7 T nsync_mu_semaphore_v
What am I missing here? Thanks for reading this far.
Classic case of not reading carefully enough.
The missing linker errors say they are looking for methods of the form
nsync::nsync_mu_init(nsync::nsync_mu_s_*).
The nm output specifies C-style functions.
The error can be resolved by compiling and linking against a C++ version of nsync instead of a C-version.

Import class-dump info into GDB

Is there a way to import the output from class-dump into GDB?
Example code:
$ cat > test.m
#include <stdio.h>
#import <Foundation/Foundation.h>
#interface TestClass : NSObject
+ (int)randomNum;
#end
#implementation TestClass
+ (int)randomNum {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
#end
int main(void) {
printf("num: %d\n", [TestClass randomNum]);
return 0;
}
^D
$ gcc test.m -lobjc -o test
$ ./test
num: 4
$ gdb test
...
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000e5c
(gdb) ^D
$ strip test
$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) ^D
$ class-dump -A test
...
#interface TestClass : NSObject
{
}
+ (int)randomNum; // IMP=0x0000000100000e50
#end
I know I can now use b *0x0000000100000e50 in gdb, but is there a way of modifying GDB's symbol table to make it accept b +[TestClass randomNum]?
Edit: It would be preferably if it would work with GDB v6 and not only GDB v7, as GDB v6 is the latest version with Apple's patches.
It’s possible to load a symbol file in gdb with the add-symbol-file command. The hardest part is to produce this symbol file.
With the help of libMachObjC (which is part of class-dump), it’s very easy to dump all addresses and their corresponding Objective-C methods. I have written a small tool, objc-symbols which does exactly this.
Let’s use Calendar.app as an example. If you try to list the symbols with the nm tool, you will notice that the Calendar app has been stripped:
$ nm -U /Applications/Calendar.app/Contents/MacOS/Calendar
0000000100000000 T __mh_execute_header
0000000005614542 - 00 0000 OPT radr://5614542
But with objc-symbols you can easily retrieve the addresses of all the missing Objective-C methods:
$ objc-symbols /Applications/Calendar.app
00000001000c774c +[CALCanvasAttributedText textWithPosition:size:text:]
00000001000c8936 -[CALCanvasAttributedText createTextureIfNeeded]
00000001000c8886 -[CALCanvasAttributedText bounds]
00000001000c883b -[CALCanvasAttributedText updateBezierRepresentation]
...
00000001000309eb -[CALApplication applicationDidFinishLaunching:]
...
Then, with SymTabCreator you can create a symbol file, which is just actually an empty dylib with all the symbols.
Using objc-symbols and SymTabCreator together is straightforward:
$ objc-symbols /Applications/Calendar.app | SymTabCreator -o Calendar.stabs
You can check that Calendar.stabs contains all the symbols:
$ nm Calendar.stabs
000000010014a58b T +[APLCALSource printingCachedTextSize]
000000010013e7c5 T +[APLColorSource alternateGenerator]
000000010013e780 T +[APLColorSource defaultColorSource]
000000010013e7bd T +[APLColorSource defaultGenerator]
000000010011eb12 T +[APLConstraint constraintOfClass:withProperties:]
...
00000001000309eb T -[CALApplication applicationDidFinishLaunching:]
...
Now let’s see what happens in gdb:
$ gdb --silent /Applications/Calendar.app
Reading symbols for shared libraries ................................. done
Without the symbol file:
(gdb) b -[CALApplication applicationDidFinishLaunching:]
Function "-[CALApplication applicationDidFinishLaunching:]" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
And after loading the symbol file:
(gdb) add-symbol-file Calendar.stabs
add symbol table from file "Calendar.stabs"? (y or n) y
Reading symbols from /Users/0xced/Calendar.stabs...done.
(gdb) b -[CALApplication applicationDidFinishLaunching:]
Breakpoint 1 at 0x1000309f2
You will notice that the breakpoint address does not exactly match the symbol address (0x1000309f2 vs 0x1000309eb, 7 bytes of difference), this is because gdb automatically recognizes the function prologue and sets the breakpoint just after.
GDB script
You can use this GDB script to automate this, given that the stripped executable is the current target.
Add the script from below to your .gdbinit, target the stripped executable and run the command objc_symbols in gdb:
$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) objc_symbols
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000ee1
(gdb) ^D
define objc_symbols
shell rm -f /tmp/gdb-objc_symbols
set logging redirect on
set logging file /tmp/gdb-objc_symbols
set logging on
info target
set logging off
shell target="$(head -1 /tmp/gdb-objc_symbols | head -1 | awk -F '"' '{ print $2 }')"; objc-symbols "$target" | SymTabCreator -o /tmp/gdb-symtab
set logging on
add-symbol-file /tmp/gdb-symtab
set logging off
end
There is no direct way to do this (that I know of), but it seems like a great idea.
And now there is a way to do it... nice answer, 0xced!
The DWARF file format is well documented, IIRC, and, as the lldb source is available, you have a working example of a parser.
Since the source to class-dump is also available, it shouldn't be too hard to modify it to spew DWARF output that could then be loaded into the debugger.
Obviously, you wouldn't be able to dump symbols with full fidelity, but this would probably be quite useful.
You can use DSYMCreator.
With DSYMCreator, you can create a symbol file from an iOS executable binary.
It's a toolchain, so you can use it like this.
$ ./main.py --only-objc /path/to/binary/xxx
Then a file /path/to/binary/xxx.symbol will be created, which is a DWARF format symbol. you can import it to lldb by yourself.
Apart from that, DSYMCreator also supports to export symbols from IDA Pro, you can use it like this.
$ ./main.py /path/to/binary/xxx
YES, just ignore --only-objc flag. Then the IDA Pro will run automatically, and then a file /path/to/binary/xxx.symbol will be created, which is the symbol file.
Thanks 0xced for creating objc-symbols, which is a part of DSYMCreator toolchain.
BTW, https://github.com/tobefuturer/restore-symbol is another choice.

Contiki compile error, " ERROR: address 0x820003 out of range at line 1740 of..."

I started to use contiki operating system with atmel atmega128rfa1.
I can compile my example, but the hex file is bad. The error is:
ERROR: address 0x820003 out of range at line 1740 of ipso.hex (i am not using IPSO, just i kept this name).
When I compile in linux system the code is program size is 27804 byte and the data is 4809byte.
When I compile in windows the program is 28292 and the data is 4791.
I use only one process and one etimer, I would like to turn on and off 1 led.
the makefile consinst of:
`
TARGET=avr-atmega128rfa1
CONTIKI = ../..
include $(CONTIKI)/Makefile.include
all:
make -f Makefile.ipso TARGET=avr-atmega128rfa1 ipso.elf
avr-objcopy -O ihex -R .eeprom ipso.elf ipso.hex
avr-size -C --mcu=atmega128rfa1 ipso.elf `
i can't program the controller. What is the problem?
thank you.
Special sections in the .elf file start above 0x810000 and must be removed when generating a hex file for programming a particular memory, e.g.
$ avr-objdump -h webserver6.avr-atmega128rfa1
webserver6.avr-atmega128rfa1: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00001bda 00800200 0000e938 0000ea2c 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 0000e938 00000000 00000000 000000f4 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .bss 000031a6 00801dda 00801dda 00010606 2**0
ALLOC
3 .eeprom 00000029 00810000 00810000 00010606 2**0
CONTENTS, ALLOC, LOAD, DATA
4 .fuse 00000003 00820000 00820000 0001062f 2**0
CONTENTS, ALLOC, LOAD, DATA
5 .signature 00000003 00840000 00840000 00010632 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
So,
avr-objcopy -O ihex -R .eeprom -R .fuse -R signature ipso.elf ipso.hex
alternately, only copy the desired sections:
avr-objcopy -O ihex -j .text -j .data ipso.elf ipso.hex
avr-objcopy --change-section-lma .eeprom=0
this works for me