2006/10/03

Stack trace linuxilla (osa 1)

Pinojäljityksen saa aikaiseksi funktioilla backtrace ja backtrace_symbols, jotka löytyvät GNU:n C-kirjastosta.

Sitten itse asiaan. Esimerkkiohjelma joka demonstroi funktioita.

#include <execinfo.h>
#include <iostream>

void trace()
{
const int ARRAY_SIZE = 5;
void *array[ARRAY_SIZE];

int size = backtrace (array, ARRAY_SIZE);
char **strings = backtrace_symbols(array, size);
if(strings == NULL)
return;

for( int i=0; i<size; ++i)
std::cout << strings[i] << std::endl;

free(strings);
}

void funktio()
{
trace();
}

int main()
{
funktio();
return 0;
}
Käännettynä komennolla g++ trace.cc -Wall:

./a.out(__gxx_personality_v0+0x172) [0x8048796]
./a.out(__gxx_personality_v0+0x1e7) [0x804880b]
./a.out(__gxx_personality_v0+0x200) [0x8048824]
/lib/tls/libc.so.6(__libc_start_main+0xc8) [0xb7d17ea8]
./a.out(__gxx_personality_v0+0x5d) [0x8048681]
Tuloste ei ole kovinkaan hyödyllinen sellaisenaan. Sama koodi käännettynä -rdynamic-vivulla:

./a.out(_Z5tracev+0x20) [0x8048956]
./a.out(_Z7funktiov+0xb) [0x80489cb]
./a.out(main+0x16) [0x80489e4]
/lib/tls/libc.so.6(__libc_start_main+0xc8) [0xb7d6bea8]
./a.out(__gxx_personality_v0+0x51) [0x8048841]
Manuaalisivulta ld(1):
--export-dynamic
When creating a dynamically linked executable, add all symbols to the dynamic symbol table. The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time.
Tulosteesta kuitenkin huomaa, että funktioiden nimet näyttävät oudoilta, koska nimet mankeloidaan muun muassa tilan säästämiseksi. Vertaa:
myclass& myclass::operator=(const myclass& from)
??4myclass@@QAEAAV0@ABV0@@Z

Muutama dokumentti nimien mankeloinnista.

GNU:n libstdc++ sisältää funktion näiden tietojen demankeloimiseen.
char* abi::__cxa_demangle(const char *      mangled_name,
char * output_buffer,
size_t * length,
int * status
)

Ei kommentteja: