Function, file and line information out of '_Unwind_Context' ptr
Gerrit Bruchhäuser
gbruchhaeuser@orga-systems.com
Tue Jun 29 13:22:00 GMT 2004
Hi Jim,
it seems like 'libbfd' and 'Unwind_Context' pointer are to be
interpreted differently.
Given the example program (just the relevant parts):
--- main.cc ---
...
static _Unwind_Reason_Code
Trace_cb(struct _Unwind_Context *ptr, void *)
{
void *pc = (void *) _Unwind_GetIP(ptr);
std::cout << "Function: " << (void *) pc<< std::endl;
return _URC_NO_REASON;
}
void foo1()
{
_Unwind_Backtrace(Trace_cb, NULL);
}
void foo()
{
foo1();
}
int main()
{
foo();
read_symbols();
return 0;
}
---
Produces a correct backtrace:
---
Function: 0x12002d508
Function: 0x12002d544
Function: 0x12002d580
Function: 0x12002d22c
---
This is the output of 'addr2line' on the complete source:
---
addr2line -e main 0x12002d508 0x12002d544 0x12002d580
/buildspace/GBruchhaeuser/SCMws/bt/main.cc:18
/buildspace/GBruchhaeuser/SCMws/bt/main.cc:25
/buildspace/GBruchhaeuser/SCMws/bt/main.cc:31
---
Well, these pointers refer to the function calls.
The symbols which from libbfd are pointing to the function definition:
---
...
void
process_symbol(asymbol *symbol)
{
std::cout << (void *) bfd_asymbol_value(symbol) << " = "
<< bfd_asymbol_name(symbol) << std::endl;
}
...
void read_symbols()
{
...
asymbol **symbol_table = (asymbol **) calloc(1, storage_needed);
long number_of_symbols = bfd_canonicalize_symtab(abfd,
symbol_table);
if (number_of_symbols < 0) {
std::cout << "Function 'bfd_canonicalize_symtab'
failed!" << std::endl;
return;
}
for (int i = 0; i < number_of_symbols; i++) {
process_symbol(symbol_table[i]);
}
}
...
---
If I compare these pointers then it looks like:
=== Unwind ==> BFD ==> Symbol
Function: 0x12002d508 ==> 0x12002d560 ==> main
Function: 0x12002d544 ==> 0x12002d4dc ==> foo1
Function: 0x12002d580 ==> 0x12002d524 ==> foo
Function: 0x12002d22c ==> ??:0
===
How can I combine both the pointer information so that I can printout
function names instead of addresses in my backtrace? A simple range
check doesn't seem to do it :-(
Any idea??
Many thanks,
Gerrit
Gerrit Bruchhäuser wrote:
> Hi Jim,
>
> wow. This mail must have taken a lot of your time.
> Many thanks for all this information. I am really impressed!
>
>> Try calling _Unwind_GetIP for the function address. IP is Instruction
>> Pointer, which is just another name for PC Program Counter.
>
>
> well, it worked: :-)
> ---
> ggbruchha@tru64-unix-4:~> g++ -g3 -O0 -o main main.cc
> gbruchha@tru64-unix-4:~> ./main
> Function: 0x1200226a8
> Function: 0x1200226e4
> Function: 0x120022720
> Function: 0x1200223cc
> gbruchha@tru64-unix-4:~> addr2line --exe main 0x1200223cc 0x120022720
> 0x1200226e4 0x1200226a8
> ??:0
> /users/gbruchha/main.cc:31
> /users/gbruchha/main.cc:26
> /users/gbruchha/main.cc:19
> ---
>
>
>
>> The LSB is a good source of documentation and references to other
>> docs. We also have links to documentation on our home page under Further
>> Readings. This has pointers to the C++ ABI (which includes Unwinder
>> info), and the Alpha ABI (function descriptors).
>
>
> What did you mean with LSB?? I never heard of it before. Did you mean
> one of:
> http://www.linuxbase.org/
> http://freestandards.org/
> ?
>
>
> Now I am able to create backtraces in case '-O0 -g3' is given to g++.
> Well, this is almost all I wanted to do. Just the function names are
> missing but I think I am able to figure this out someway. I want to
> integrate 'addr2line' into my program anyways.
>
> Is there any buildin to retreive an indication on whether the
> unwinding may work (-O0 and -g are given)?
>
> Many thanks,
> Gerrit
>
>
> Jim Wilson wrote:
>
>> On Sun, 2004-06-27 at 06:47, Gerrit Bruchhäuser wrote:
>>
>>
>>> It would be extremly useful to have a 'Backtrace' like building
>>> function in g++ (as there is in GLIBC) which does work with any
>>> platform g++ runs on. I thought I could use the '_Unwind_Stack'
>>> function for this. Is there maybe an other way to retreive file and
>>> line information out of the mentioned structure pointer??
>>>
>>
>>
>> The glibc backtrace function is x86 specific. It is trivial to generate
>> a backtrace on a CISC like the x86, but it is hard on a RISC, and it is
>> getting harder with newer ABIs and more agressively optimizing
>> compilers.
>>
>> By the way, if you are using -foptimize-sibling-calls, which is the
>> default at -O2, then your backtraces are already broken. This option
>> optimizes away stack frames when we have a sibling call, and you can't
>> backtrace through a stack frame that isn't there.
>>
>> Similarly, if you are using function inlining, then the backtraces won't
>> exactly represent what the programs is doing. This is fixable by
>> reading the debug info, but even gdb/addr2line doesn't have code to do
>> this yet.
>>
>> As for Alpha, the Alpha ABI has function descriptors which can be used
>> to generate backtraces. The Alpha ABI deliberately sacrifices some
>> performance so that backtraces can still work. If you find an Alpha ABI
>> reference and read up on it, you should be able to write your own code
>> to do stack backtraces on the alpha. This will be faster than using the
>> unwinder.
>>
>> But for most common RISC targets nowadays, the only safe way to do a
>> backtrace is to use the unwinder, and this will be a slow process
>> compared to the glibc backtrace function.
>>
>> If you just want function names in the backtrace, you can do this pretty
>> easily by reading the symbol table (e.g. the ECOFF symbol table). If
>> you want line numbers also, then you have to read the debug info, and
>> there is no getting around the fact that this will be an even slower
>> process. This is best done offline as Arnaud Charlet suggested if you
>> really need this. I believe the glibc backtrace function only gives you
>> function names.
>>
>> The LSB is a good source of documentation and references to other
>> docs. We also have links to documentation on our home page under Further
>> Readings. This has pointers to the C++ ABI (which includes Unwinder
>> info), and the Alpha ABI (function descriptors).
>>
>> Try calling _Unwind_GetIP for the function address. IP is Instruction
>> Pointer, which is just another name for PC Program Counter.
>>
>>
>
>
More information about the Gcc
mailing list