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