Come posso mappare un indirizzo puntatore di istruzione segfault da / var / log / messages a un indirizzo / funzione nel mio file .map?
-
05-07-2019 - |
Domanda
(Il mio ambiente è Ubuntu a 64 bit, la mia applicazione è compilata in C ++ e collegata a g ++.)
Quando un'applicazione fa qualcosa come dividere per zero o eseguire un asm (" int $ 3 ")
lasciato nel codice, uno dei seguenti viene registrato tramite syslog su / var /log/kern.log
e / var / log / messages
:
Sep 10 18:06:47 VM kernel: [117194.123452] a.out[20288] trap divide error ip:45c59d sp:7fff65a91810 error:0 in a.out[400000+144000]
Sep 10 18:07:10 VM kernel: [117217.020833] a.out[20294] trap int3 ip:45c493 sp:7fff5cc559f0 error:0
In entrambi i casi, l'indirizzo del puntatore dell'istruzione punta a qualcosa che posso facilmente cercare nel file .map
prodotto al momento del collegamento (usando il " -Wl, -Map , output.map
".)
Ma se provoco un errore seg, in questo caso da una chiamata a memcpy ()
con la sorgente impostata su NULL, il puntatore dell'istruzione è così fuori portata, non ho idea di come dovrebbe essere mappato:
Sep 10 18:06:13 VM kernel: [117160.228587] a.out[20282]: segfault at 0 ip 00007f7e79209092 sp 00007fff831faf08 error 4 in libc-2.9.so[7f7e79185000+168000]
In questo esempio, mi sarei aspettato che l'IP fosse compreso nell'intervallo 0x445e70-0x445e7f, che è la posizione di memcpy () secondo il mio file .map.
La mia domanda: qual è il trucco per interpretare l'ip in questo caso?
Soluzione
Secondo il messaggio sembra che si sia bloccato in memcpy ()
, da libc-2.9.so
, che è mappato nel tuo processo a partire da 0x7f7e79185000. Ciò è previsto poiché memcpy
è la funzione che sta tentando di dereferenziare il puntatore. Il puntatore alle istruzioni sembra valido poiché è compreso nell'intervallo di libc. Se intendevi ignorare memcpy e chiamare la tua versione, potresti dover compilare con -fno-builtin-memcpy
.
Modifica: È possibile che si stia collegando staticamente libc ma in base al messaggio è stata mappata anche la libreria condivisa libc nella memoria del processo. Dovresti vederlo elencato in /proc/
pid / maps
mentre il tuo programma è in esecuzione. È possibile che si stia collegando a un'altra libreria condivisa, come libstdc ++, e dipende dalla libreria condivisa libc. Di conseguenza hai due versioni di memcpy, e in questo caso sta chiamando la versione della libreria condivisa libc che è mappata all'indirizzo alto. Se non vuoi la libreria condivisa libc, assicurati di collegare staticamente tutte librerie; utilizzare l'opzione -static
all'inizio della riga del collegamento.