[lug] good assert library

D. Stimits stimits at attbi.com
Sun Sep 22 15:52:31 MDT 2002

Chan Kar Heng wrote:
> At 2002/09/19 15:17, you wrote:
>>Chan Kar Heng wrote:
>>>thanks.. it's cool...
>>>i tried this... gcc -rdynamic -g -O0 a.c
>>>and i get a lot of hex addresses instead of function names...
>>>is this the expected output?
>>I haven't used this code in about a year, I recall having only hex addresses until the right option combination was used. You might experiment with leaving out any -O#; but once it is found, it will give you not hex, but plain English function names. You might also find it varies with the version of glibc and gcc/g++ that you use, but I am not positive. If you can't find the right arguments to get symbolic output, I can experiment with some of my old code and find out. I doubt it matters, but one detail of the last project I used this on compiled and linked in separate Makefile stages, where the -rdynamic was only in the linker stage; the -g was only in the intermediate object compile stage. Separation of stages without going directly from .c to executeable could allow a finer-grained testing of compile switches.
> I did a little searching... didn't do me much good though...
> This's through gcc -v :
> Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs
> gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
> Here's another version i got..:
> --bt.c---------------------------------------------------------------------
> #include <execinfo.h>
> #include <stdio.h>
> #include <stdlib.h>
> /* Obtain a backtrace and print it to stdout. */
> void
> print_trace (void)
> {
>   void *array[10];
>   size_t size;
>   char **strings;
>   size_t i;
>   size = backtrace (array, 10);
>   strings = backtrace_symbols (array, size);
>   printf ("Obtained %zd stack frames.\n", size);
>   for (i = 0; i < size; i++)
>      printf ("%s\n", strings[i]);
>   free (strings);
> }
> /* A dummy function to make the backtrace more interesting. */
> void
> dummy_function (void)
> {
>   print_trace ();
> }
> int
> main (void)
> {
>   dummy_function ();
>   return 0;
> }
> -----------------------------------------------------------------------
> This's what i used to compile... 
> gcc -Wl,--export-dynamic -g -Wall -O0 -o bt bt.c
> or
> gcc -rdynamic -g -Wall -O0 -o bt bt.c
> When i started the program, i got this:
> -----------------------------------------------------------------------
> Obtained 5 stack frames.
> [0x80486b1]
> [0x804872c]
> [0x8048738]
> /lib/libc.so.6(__libc_start_main+0xff) [0x400329cb]
> [0x8048611]
> -----------------------------------------------------------------------

I compiled this via "gcc -g -rdynamic bt.c -o bt", and ran it:
 > ./bt
Obtained 5 stack frames.
./bt(print_trace+0x14) [0x80486c4]
./bt(dummy_function+0xb) [0x8048747]
./bt(main+0xb) [0x8048757]
/lib/libc.so.6(__libc_start_main+0x90) [0x400461c4]
./bt(backtrace_symbols+0x3d) [0x80485d1]

In my case, it is showing actual frame names. I'm using Redhat's 2.96. I 
also tried with "-O0", it still worked, as well as "cc 
-Wl,--export-dynamic -g -Wall -O0 -o bt bt.c", which also worked. If I 
run ldd on the executable, I get:
 > ldd bt
         libc.so.6 => /lib/libc.so.6 (0x4002f000)
         /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

...so it isn't linking anything special, e.g., it is not linking a debug 
version of glibc. I wonder if perhaps your compiler version simply 
doesn't support it, or maybe the linker or glibc version does not 
support this. If I run "nm" on this executable, I get:
 > nm bt
080497fc A _DYNAMIC
080487c4 R _IO_stdin_used
080498c8 ? __CTOR_END__
080498c4 ? __CTOR_LIST__
080498d0 ? __DTOR_END__
080498cc ? __DTOR_LIST__
080497f8 ? __EH_FRAME_BEGIN__
080497f8 ? __FRAME_END__
08049900 A __bss_start
080497e8 D __data_start
          w __deregister_frame_info@@GLIBC_2.0
08048760 t __do_global_ctors_aux
08048600 t __do_global_dtors_aux
          w __gmon_start__
          U __libc_start_main@@GLIBC_2.0
          w __register_frame_info@@GLIBC_2.0
08049900 A _edata
08049918 A _end
080487a0 ? _fini
080487c0 R _fp_hw
0804850c ? _init
080485b0 T _start
          U backtrace@@GLIBC_2.1
          U backtrace_symbols@@GLIBC_2.1
080485d4 t call_gmon_start
080497f4 d completed.1
080497e8 W data_start
0804873c T dummy_function
08048660 t fini_dummy
080497f8 d force_to_data
080497f8 d force_to_data
08048670 t frame_dummy
          U free@@GLIBC_2.0
080485d4 t gcc2_compiled.
08048600 t gcc2_compiled.
08048760 t gcc2_compiled.
080487a0 t gcc2_compiled.
080486a0 t init_dummy
08048790 t init_dummy
0804874c T main
08049900 b object.2
080497f0 d p.0
080486b0 T print_trace
          U printf@@GLIBC_2.0

Oddly enough, these are almost identical, and indicate the same glibc 
and other functions. I do have a debug glibc installed on my system, but 
it is not linked against that, so I doubt it would have any effect. For 
reference, here is the RH output for gcc -v:
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)

I am guessing that there is an ABI (application binary interface) 
difference between our compiler versions which causes the backtrace to 
fail to read symbolic names correctly...it may not have been supported 
on your particular gcc version. If that were the case, it would likely 
become confused as to what part is the symbol text name. I'm not sure 
who you could ask about whether the backtrace() and backtrace_symbols() 
functions break on earlier ABI's or compilers, but I can't think of any 
other issue which would cause it to fail.

D. Stimits, stimits AT attbi.com

More information about the LUG mailing list