Dies kann eine sehr einfache Frage sein. Ich versuche, eine Anwendung zu debuggen, die den folgenden Segfault-Fehler in der generiert kern.log
kernel: myapp[15514]: segfault at 794ef0 ip 080513b sp 794ef0 error 6 in myapp[8048000+24000]
Hier sind meine Fragen:
-
Gibt es eine Dokumentation darüber, was die Diff-Fehlernummern auf segfault sind, in diesem Fall ist es Fehler 6, aber ich habe Fehler 4, 5 gesehen
-
Welche Bedeutung haben die Informationen at bf794ef0 ip 0805130b sp bf794ef0 and myapp[8048000+24000]
?
Bisher konnte ich mit Symbolen kompilieren, und wenn ich a x 0x8048000+24000
es gibt ein Symbol zurück, ist das der richtige Weg? Meine Vermutungen sind bisher folgende:
- sp = Stapelzeiger?
- ip = Befehlszeiger
- bei = ????
- meine App[8048000+24000] = Adresse des Symbols?
Wenn der Bericht auf ein Programm verweist, nicht auf eine gemeinsam genutzte Bibliothek
Laufen addr2line -e myapp 080513b
(und wiederholen Sie dies für die anderen angegebenen Anweisungszeigerwerte), um zu sehen, wo der Fehler auftritt. Holen Sie sich besser einen debug-instrumentierten Build und reproduzieren Sie das Problem mit einem Debugger wie gdb.
Wenn es sich um eine gemeinsam genutzte Bibliothek handelt
In dem libfoo.so[NNNNNN+YYYY]
Teil, der NNNNNN
wo die Bibliothek geladen wurde. Subtrahieren Sie dies vom Befehlszeiger (ip
) und Sie erhalten den Offset in die .so
der anstößigen Belehrung. Dann können Sie verwenden objdump -DCgl libfoo.so
und suche nach der Anweisung an diesem Offset. Sie sollten anhand der asm-Labels leicht erkennen können, um welche Funktion es sich handelt. Wenn die .so
hat keine Optimierungen, die Sie auch ausprobieren können addr2line -e libfoo.so <offset>
.
Was der Fehler bedeutet
Hier die Aufteilung der Felder:
address
– der Ort im Speicher, auf den der Code zuzugreifen versucht (es ist wahrscheinlich das 10
und 11
sind Offsets von einem Zeiger, von dem wir erwarten, dass er auf einen gültigen Wert gesetzt wird, der aber stattdessen zeigt 0
)
ip
– Anweisungszeiger, dh. wo der Code lebt, der dies versucht
sp
– Stapelzeiger
error
– Architekturspezifische Flags; sehen arch/*/mm/fault.c
für Ihre Plattform.
Nach meinem begrenzten Wissen sind Ihre Annahmen richtig.
sp
= Stapelzeiger
ip
= Anweisungszeiger
myapp[8048000+24000]
= Adresse
Wenn ich das Problem debuggen würde, würde ich den Code ändern, um einen Core-Dump zu erzeugen oder einen Stack-Backtrace für den Absturz zu protokollieren. Sie können das Programm auch unter GDB ausführen (oder anhängen).
Der Fehlercode ist nur der architektonische Fehlercode für Seitenfehler und scheint architekturspezifisch zu sein. Sie sind oft dokumentiert in arch/*/mm/fault.c
in der Kernelquelle. Meine Kopie von Linux/arch/i386/mm/fault.c
hat die folgende Definition für error_code:
- Bit 0 == 0 bedeutet keine Seite gefunden, 1 bedeutet Schutzfehler
- Bit 1 == 0 bedeutet lesen, 1 bedeutet schreiben
- Bit 2 == 0 bedeutet Kernel, 1 bedeutet Benutzermodus
Meine Kopie von Linux/arch/x86_64/mm/fault.c
fügt folgendes hinzu:
- Bit 3 == 1 bedeutet, dass der Fehler ein Befehlsabruf war
Wenn es sich um eine gemeinsam genutzte Bibliothek handelt
Du bist leider abgespritzt; Es ist nicht möglich, im Nachhinein zu wissen, wo die Bibliotheken vom dynamischen Linker im Speicher platziert wurden.
Nun, es gibt immer noch eine Möglichkeit, die Informationen nicht aus der Binärdatei, sondern aus dem Objekt abzurufen. Sie benötigen jedoch die Basisadresse des Objekts. Und diese Informationen befinden sich immer noch im Coredump in der link_map-Struktur.
Zuerst wollen Sie also die Struktur link_map in GDB importieren. Kompilieren Sie also ein Programm damit mit dem Debug-Symbol und fügen Sie es der GDB hinzu.
link.c
#include <link.h>
toto(){struct link_map * s = 0x400;}
get_baseaddr_from_coredump.sh
#!/bin/bash
BINARY=$(which myapplication)
IsBinPIE ()
{
readelf -h $1|grep 'Type' |grep "EXEC">/dev/null || return 0
return 1
}
Hex2Decimal ()
{
export number="`echo "$1" | sed -e 's:^0[xX]::' | tr '[a-f]' '[A-F]'`"
export number=`echo "ibase=16; $number" | bc`
}
GetBinaryLength ()
{
if [ $# != 1 ]; then
echo "Error, no argument provided"
fi
IsBinPIE $1 || (echo "ET_EXEC file, need a base_address"; exit 0)
export totalsize=0
# Get PT_LOAD's size segment out of Program Header Table (ELF format)
export sizes="$(readelf -l $1 |grep LOAD |awk '{print $6}'|tr '\n' ' ')"
for size in $sizes
do Hex2Decimal "$size"; export totalsize=$(expr $number + $totalsize); export totalsize=$(expr $number + $totalsize)
done
return $totalsize
}
if [ $# = 1 ]; then
echo "Using binary $1"
IsBinPIE $1 && (echo "NOT ET_EXEC, need a base_address..."; exit 0)
BINARY=$1
fi
gcc -g3 -fPIC -shared link.c -o link.so
GOTADDR=$(readelf -S $BINARY|grep -E '\.got.plt[ \t]'|awk '{print $4}')
echo "First do the following command :"
echo file $BINARY
echo add-symbol-file ./link.so 0x0
read
echo "Now copy/paste the following into your gdb session with attached coredump"
cat <<EOF
set \$linkmapaddr = *(0x$GOTADDR + 4)
set \$mylinkmap = (struct link_map *) \$linkmapaddr
while (\$mylinkmap != 0)
if (\$mylinkmap->l_addr)
printf "add-symbol-file .%s %#.08x\n", \$mylinkmap->l_name, \$mylinkmap->l_addr
end
set \$mylinkmap = \$mylinkmap->l_next
end
Es wird Ihnen den gesamten link_map-Inhalt innerhalb eines Satzes von GDB-Befehlen drucken.
Es selbst mag unnötig erscheinen, aber mit der base_addr des gemeinsamen Objekts, um das es uns geht, können Sie möglicherweise mehr Informationen aus einer Adresse erhalten, indem Sie das betroffene gemeinsame Objekt direkt in einer anderen GDB-Instanz debuggen. Behalten Sie die erste gdb, um eine Vorstellung von dem Symbol zu haben.
HINWEIS: Das Skript ist ziemlich unvollständig, ich vermute, Sie können es hinzufügen Zum zweiten Parameter von add-symbol-file wurde die Summe mit diesem Wert gedruckt:
readelf -S $SO_PATH|grep -E '\.text[ \t]'|awk '{print $5}'
wobei $SO_PATH die ist Erste Argument der Add-Symbol-Datei
Ich hoffe es hilft
Hinzugefügt [unix] [segmentation-fault] [syslog] Stichworte.
– Emil Cormier
1. Februar 2010 um 19:41 Uhr
Hallo, haben Sie nützliche Informationen gefunden? Ich stecke fest.
– Baroudi Safwen
11. Januar 2018 um 18:22 Uhr