2014-07-15 11 views
5

Die Betreffzeile sagt im Grunde alles.In GDB ist es möglich, eine relative Adresse (in Zeilen) vom Anfang einer Funktion zu geben?

Wenn ich den Speicherort basierend auf der Datei und einer Zeilennummer gebe, kann sich dieser Wert ändern, wenn ich die Datei bearbeite. Tatsächlich neigt es dazu, sich ziemlich oft und auf unbequeme Weise zu ändern, wenn ich während des Refactorings mehr als eine einzige Funktion bearbeite. Es ist jedoch weniger wahrscheinlich, dass es sich ändert, wenn es (line-) relativ zum Anfang einer Funktion wäre.

Wenn es nicht möglich ist, den Zeilenoffset vom Anfang einer Funktion zu geben, ist es dann vielleicht möglich, Convenience-Variablen zu verwenden, um sie zu emulieren? I.e. wenn ich Convenience-Variablen deklarieren würde, die dem Beginn einer bestimmten Funktion zugeordnet sind (eine Liste, die ich auf dem neuesten Stand halten würde)?

Laut help break scheint keiner verfügbar zu sein, aber ich dachte, ich sollte besser fragen, um sicher zu sein.


(gdb) help break 
Set breakpoint at specified line or function. 
break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION] 
PROBE_MODIFIER shall be present if the command is to be placed in a 
probe point. Accepted values are `-probe' (for a generic, automatically 
guessed probe type) or `-probe-stap' (for a SystemTap probe). 
LOCATION may be a line number, function name, or "*" and an address. 
If a line number is specified, break at start of code for that line. 
If a function is specified, break at start of code for that function. 
If an address is specified, break at that exact address. 
With no LOCATION, uses current execution address of the selected 
stack frame. This is useful for breaking on return to a stack frame. 

THREADNUM is the number from "info threads". 
CONDITION is a boolean expression. 

Multiple breakpoints at one place are permitted, and useful if their 
conditions are different. 

Do "help breakpoints" for info on other commands dealing with breakpoints. 

Antwort

5

Es ist ein langjähriger Wunsch, dies zu gdb hinzuzufügen. Es existiert jedoch momentan nicht. Es ist vielleicht möglich mit Python, aber vielleicht nicht vollständig, da Python momentan keinen Zugriff auf alle gesetzten Breakpoint-Ereignisse hat (also könnte der Breakpoint einmal funktionieren, aber nicht beim erneuten Ausführen oder Laden von Bibliotheken oder anderen minderwertigen Änderungen)).

Der zitierte Text zeigt jedoch einen schöneren Weg - verwenden Sie einen Prüfpunkt. Dies sind sogenannte "SystemTap-Prüfpunkte", aber in Wirklichkeit sind sie mehr wie eine generische ELF + GCC-Funktion - sie stammen aus dem SystemTap-Projekt, sind aber nicht davon abhängig. Dadurch können Sie einen Punkt in der Quelle markieren und problemlos einen Haltepunkt darauf setzen, unabhängig von anderen Änderungen an der Quelle. Sie werden bereits auf Linux-Distributionen verwendet, um spezielle Punkte in den Abwicklungs- und Longjump-Laufzeitroutinen zu markieren, damit das Debugging in diesen Umgebungen reibungslos funktioniert.

+0

Zusätzlich zu den Prüfpunkten habe ich auch die 'Break-Funktion: Label' Syntax zu den gleichen Effekt in der Vergangenheit verwendet. das könnte auch eine Option sein. – matt

+0

10 @TomTromey: SystemTap ist auch Linux-spezifisch, oder? Während ELF, GCC und GDB nicht sind. – 0xC0000022L

+0

Ja, SystemTap ist Linux-spezifisch. Es ist jedoch möglich, sdt.h-Tests auf anderen Systemen zu verwenden. Ich habe es nicht versucht, aber ich verstehe nicht warum. Die gesamte Entwicklung der Sonden ist nur eine einzige Header-Datei ... –

0

Ich verstehe, dass dies eine alte Frage ist, aber ich konnte auch 2017 keine bessere Lösung finden. Hier ist eine Python-Lösung.Vielleicht ist es nicht die robusteste/sauberste, aber es funktioniert sehr gut in vielen praktischen Szenarien:

class RelativeFunctionBreakpoint (gdb.Breakpoint): 
    def __init__(self, functionName, lineOffset): 
     super().__init__(RelativeFunctionBreakpoint.calculate(functionName, lineOffset)) 

    def calculate(functionName, lineOffset): 
     """ 
     Calculates an absolute breakpoint location (file:linenumber) 
     based on functionName and lineOffset 
     """ 
     # get info about the file and line number where the function is defined 
     info = gdb.execute("info line "+functionName, to_string=True) 
     # extract file name and line number 
     m = re.match(r'Line[^\d]+(\d+)[^"]+"([^"]+)', info) 
     if not m: 
      raise Exception('Failed to find function %s.' % functionName) 
     line = int(m.group(1))+lineOffset #add the lineOffset 
     fileName = m.group(2) 
     return "%s:%d" % (fileName, line) 

USAGE:

basic:

RelativeFunctionBreakpoint("yourFunctionName", lineOffset=5) 

benutzerdefinierten Haltepunkt:

class YourCustomBreakpoint (RelativeFunctionBreakpoint): 
    def __init__(self, funcName, lineOffset, customData): 
     super().__init__(funcName, lineOffset) 
     self.customData = customData 
    def stop(self): 
     # do something 
     # here you can access self.customData 
     return False #or True if you want the execution to stop 

Vorteile die Lösung

  • relativ schnell, da der Breakpoint nur einmal festgelegt ist, bevor die Ausführung
  • robust auf Änderungen in der Quelldatei beginnt, wenn sie nicht die Funktion beeinflussen

Disadvatages

  • natürlich ist es zu den Änderungen in der Funktion nicht robust ist selbst
  • Nicht robust gegenüber den Änderungen in der Ausgabesyntax der Infozeile funcName gdb Befehl (wahrscheinlich gibt es eine bessere Möglichkeit, den Dateinamen und die Zeilennummer zu extrahieren)
  • andere? Sie weisen darauf hin