4

OK, I've used the Linux Dwarf ldw library to convert backtrace_symbols output to source code and line numbers but I've hit a snag. backtrace_symbols gives offsets in memory from which I subtract the base address (obtained using dladdr()) before using as input into Dwarf. But it seems that for the parent executable, I should NOT subtract the base address because the Dwarf offsets seem to include it.

So how do I either distinguish between EXE and SO in my code (I'm hoping there's something better than 'look for ending .so') or is there a different function I can call that will obtain the base address or zero for the parent EXE?

Papadeltasierra
  • 233
  • 1
  • 9

2 Answers2

3

Yes, you are right. If the executable is a ET_EXEC (not a DT_DYN i.e. it is not a position-independant executable), then the virtual addresses in the DWARF are the real virtual addresses in your program image. For DT_DYN the addresses in the DWARF are offsets from the base address of the module.

This is explained in 7.3 of the DWARF spec:

The relocated addresses in the debugging informations for an executable object are virtual addresses and the relocated addresses in the debugging informations for a shared object are offsets relative to the start of the lowest region of memory loaded from that shared memory.

You should use e_type in the ELF header to distinguish them.

ysdx
  • 8,889
  • 1
  • 38
  • 51
2

No sure if this is the best way, but ldw has a function, dwarf_getelf(), that can get you to the ELF information, from there use elf32/64_getehdr() and from there look at the e_type field. If e_type is ET_DYN then it's a shared object and you should carry on and use dladdr to find the offset to delete from addresses else just use the addresses generated by backtrace directly.

Papadeltasierra
  • 233
  • 1
  • 9