Wie kann ich die Pause auf UBSan Berichte in gdb, und weiter?
Neueren Versionen von GCC und Clang-Funktion Undefined Behavior Sanitizer (UBSan) das ist ein compile-flag (-fsanitize=undefined
) fügt hinzu, dass Laufzeit-Instrumentierung von code. Auf Fehler, eine Warnung wie diese angezeigt:
packet-ber.c:1917:23: runtime error: Links-shift von 54645397829836991 von 8 stellen dargestellt werden können Typ 'long int'
Nun würde ich gerne Debuggen und erhalten Sie einen debug-break auf der besagten Linie. Für Address Sanitizer (ASAN) es ist ASAN_OPTIONS=abort_on_error=1
die Ergebnisse in ein fataler Fehler, abfangbar. Den nur UBSan option, die scheint brauchbar ist UBSAN_OPTIONS=print_stacktrace=1
die Ergebnisse in einem call-trace-dump für die Berichte. Dies ist jedoch nicht erlauben, mich zu inspizieren die lokalen Variablen und dann das Programm fortzusetzen. Verwendung von -fsanitize-undefined-trap-on-error
daher nicht möglich.
Wie soll ich eine Pause in gdb auf UBSan berichten? Während break __sanitizer::SharedPrintfCode
scheint zu funktionieren, der name sieht ganz interne.
- Ich denke, dass, bis eine API implementiert und dokumentiert sind, ein guter Weg, um zu fangen, einen Aufruf an die UBSan runtime-Bibliothek, mit der Absicht, weiterhin Ihr Programm zu tun
rbreak ^__ubsan_handle_
, die Stoppt die Ausführung vor der Bibliothek ventures in C++ Gebiet, wobei es ordnet Instanzen der Diag-Klasse. Sie kramen alles, was Sie wollen, dann geben Siereturn
weiterhin Ihr Programm. - Für die Zukunft,
abort_on_error
scheint implementierte für UBSAN. Verwenden Sie dieses anstatt:UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1
- Siehe auch How to break im debugger, wenn -fsanitize=undefined druckt so etwas? auf der Clang-Dev-mailing-Liste.
- Welche GCC/Clang version verwenden Sie genau?
- Sehr aktuelle Versionen auf Arch Linux, GCC 5.1.0, Klammerten sich 3.6.1.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beim brechen, der auf die Erkennung von Funktionen (wie beschrieben durch @Mark Plotnick und @Iwillnotexist Idonotexist) ist eine option, ein besserer Ansatz ist zu brechen auf die Funktionen, Bericht diesen Fragen nach der Erkennung. Dieser Ansatz ist auch für ASAN, wo man möchte brechen auf
__asan_report_error
.Zusammenfassung: stoppen Sie auf eine ubsan Bericht über einen Haltepunkt auf
__ubsan::ScopedReport::~ScopedReport
oder__ubsan::Diag::~Diag
. Dies sind die privaten Implementierungsdetails, die möglicherweise in der Zukunft ändern aber. Getestet mit GCC 4.9, 5.1.0, 5.2.0 und Clang 3.3, 3.4, 3.6.2.Für GCC 4.9.2 aus ppa:ubuntu-toolchain-r/test, müssen Sie
libubsan0-dbg
um die oben genannten Haltepunkte zur Verfügung. Ubuntu 14.04 mit Clang 3.3 und 3.4 nicht unterstützen__ubsan::ScopedReport::~ScopedReport
Haltepunkte, so können Sie nur die Pause vor dem drucken die Nachricht mit__ubsan::Diag::~Diag
.Beispiel buggy-source-code und eine gdb-Sitzung:
Detaillierte Analyse folgt. Beachten Sie, dass beide ASAN und ubsan beide stammen aus einem LLVM-Projekt, compiler-rt. Diese wird von Clang und endet in GCC als auch. Links in den folgenden Abschnitten Punkt für den compiler-rt-Projekt-code, Version 3.6.
ASAN hat seine internen
__asan_report_error
Teil der dokumentiert öffentlichen Schnittstelle. Diese Funktion wird immer aufgerufen, wenn eine Verletzung festgestellt wird, die Strömung setzt sich in lib/asan/asan_report.c:938:ubsan auf der anderen Seite hat keine öffentliche Schnittstelle, aber Ihre derzeitige Umsetzung ist auch viel einfacher und begrenzt (weniger Optionen). Bei Fehlern einen stacktrace kann gedruckt werden, wenn die
UBSAN_OPTIONS=print_stacktrace=1
Umgebungsvariable gesetzt ist. So, durch eine Suche im source-code fürprint_stacktrace
findet man die Funktion MaybePrintStackTrace, die aufgerufen wird, wenn die ScopedReport Destruktor:Wie Sie sehen können, gibt es eine Methode, um das Programm zu töten, über die Fehler, aber leider gibt es keinen eingebauten Mechanismus zum auslösen einer debugger-Falle. Lassen Sie s finden Sie einen geeigneten Haltepunkt dann.
Dem GDB-Befehl
info Funktionen <Funktionsname>
machte es möglich, zu identifizierenMaybePrintStackTrace
als Funktion auf, die ein Haltepunkt gesetzt werden kann. Ausführunginfo functions ScopedReport::~ScopedReport
gab eine weitere Funktion:__ubsan::ScopedReport::~ScopedReport
. Wenn keine dieser Funktionen scheinen vorhanden (auch mit debug-Symbole installiert), können Sie versucheninfo functions ubsan
oderinfo functions sanitizer
alle zu erhalten (UndefinedBehavior)Desinfektionsmittel-Funktionen.inline
,extern
-Gestänge,void
-Rücksendung von leeren interne Funktion könnte breakpointed durch einen debugger, und dass diese Funktion aufgerufen werden mit Argumenten nützlich, um den debugger, wenn die Berichterstattung Wahnsinn. Etwas ähnlich wie der JIT-Anmeldung-Schnittstelle.Als @Mark Plotnick Punkte aus, die Art und Weise dies zu tun ist Haltepunkt an UBSan ist Handler.
UBSan hat eine Reihe von Prozeduren, oder die magic-Funktion Einstiegspunkte, die aufgerufen werden, für Undefiniertes Verhalten. Der compiler Instrumente-code durch Einspritzen von Prüfungen als angemessen, Wenn die check-code erkennt, UB, ruft diese Prozeduren. Sie beginnen alle mit
__ubsan_handle_
und sind definiert inlibsanitizer/ubsan/ubsan_handlers.h
. Hier ist ein link zum GCC Kopie vonubsan_handlers.h
.Hier die relevanten bits des UBSan header (breakpoint auf diesen):
ASan ist sogar noch einfacher. Wenn man sich in
libsanitizer/include/sanitizer/asan_interface.h
, die Sie durchsuchen hier, die Sie Lesen können, ein untrügliches Zeichen für einen Kommentar:Zahlreiche weitere Funktionen in diesem header sind explizit kommentiert wurde öffentlich gemacht, so dass callable von einem debugger.
Ich auf jeden Fall raten, Sie zu erkunden, andere Header von
libsanitizer/include/sanitizer
hier. Es gibt zahlreiche goodies, um es musste sein.Haltepunkte für UBSan und ASan Hinzugefügt werden können, wie folgt:
Dieser Haltepunkt wird auf dem Handler und
finish
sofort danach. Dies ermöglicht es der Bericht gedruckt werden, aber der debugger erhält die Kontrolle sofort danach gedruckt werden.gdb
? Es wäre toll, wenn ein Konzept (oder einfachgdbinit
makro), wirkt wie ASAN. Das heißt, die Meldung angezeigt werden und brechen.gdb
/gdbinit
, sicher, ich werde hinzufügen, dass in ein paar Stunden.(gdb) rbreak __asan_report_error
und(gdb) rbreak ^__ubsan
unverblümt Haltepunkt alle Funktionen, die mit denen regexes. Es gibt keine Funktion, die aufgerufen wird, nachdem__asan_report_error
gibt, so scheint es mir, dass man es irgendwie Programmieren müssengdb
sofort(gdb) finish
nach der Kollision mit einem dieser Haltepunkte.UBSAN_OPTIONS
unterstützt libsanitizer (nicht gdb oder so), die vars die ich mich beziehe, indem Sie "Umgebungsvariablen". Als für den Haltepunkt habe ich versuchtrbreak ^__ubsan_handle_
commands
finish
end
, aber irgendwie verhält sich seltsam mit einem sehr einfachen test-Programm (Funktion ist noch immer in der__ubsan_handle_...
frame), während eine folgendeinfo breakpoints
irgendwie löst das drucken und änderungen des Rahmens. (GDB 7.9.1)UINTMAX+1
. Aber vielleicht könnten Sie versuchen-fno-sanitize=unsigned-integer-overflow
? Ich glaube nicht, dass es möglich zu bestimmen, dass mit einem speziellen - Anweisung ignoriert werden, es sei denn, Sie ziehen es in eine Funktion und kompilieren Sie es in eine andere Datei mit verschiedenen Flaggen.unsigned-integer-overflow
überprüfen, die Sie verwenden können, um überprüfen Sie Ihren code. Diese Prüfung gefunden hat Tonnen von bugs in unseren Anwendungen. Nur weil Ihr Verhalten definiert ist, bedeutet nicht, dass es das macht, was Sie denken, es tut. Unsigned-integer-Arithmetik ist wirklich voll von fallen und Fällen Ecke.__attribute__
zu ändern, die compile-flags für eine bestimmte Funktion. Ich vergaß!__ubsan_handle*
. Durch das setzen von mehreren breakpoints, fand ich heraus, dass die Bindung einer Referenz annullptr
löst__ubsan_handle_type_mismatch
zum Beispiel.Einen Haltepunkt setzen an
__asan_report_error
ist nicht der hit für mich und das Programm existiert einfach nach dem drucken die Diagnose ohne den debugger auslösen.__asan::ReportGenericError
vor dem Druck der Diagnostik und__sanitizer::Die
nach dem drucken die Diagnose bekommen, Treffer, wie beschrieben, in die asan-wiki.