2014-07-15 9 views
5

Temat linii mówi wszystko.W GDB można podać adres względny (w liniach) od początku funkcji?

Jeśli podaję lokalizację na podstawie pliku i numeru linii, ta wartość może się zmienić, jeśli edytuję plik. W rzeczywistości zmienia się dość często iw niewygodny sposób, jeśli edytuję więcej niż jedną funkcję podczas refaktoryzacji. Jest jednak mniej prawdopodobne, że zmieni się, jeśli jest (linia) względem początku funkcji.

Jeśli nie można podać przesunięcia linii od początku funkcji, czy możliwe jest użycie emulatora wygodnych zmiennych? To znaczy. czy zadeklarowałbym zmienne wygody, które są mapowane na początek danej funkcji (lista, którą chciałbym aktualizować)?

Według help break żaden z nich nie jest dostępny, ale pomyślałem, że powinienem zapytać o to.


(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. 

Odpowiedz

5

Jest to dawna prośba o dodanie tego do gdb. Jednak obecnie nie istnieje. Być może jest to możliwe z Pythonem, ale być może nie całkowicie, ponieważ Python nie ma obecnie dostępu do wszystkich ponownie zdefiniowanych zdarzeń punktu przerwania (aby punkt przerwania działał tylko raz, ale nie po ponownym uruchomieniu lub załadowaniu biblioteki lub innej niższej zmianie).

Jednak cytowany tekst przedstawia ładniejszy sposób - użyj punktu próbkowania. Są to tak zwane "punkty sond SystemTap", ale w rzeczywistości są bardziej podobne do ogólnej cechy ELF + GCC - pochodzą z projektu SystemTap, ale nie od niego zależą. Pozwalają one na zaznaczenie miejsca w źródle i łatwe umieszczenie na nim punktu przerwania, niezależnie od innych zmian wprowadzanych do źródła. Są już używane w dystrybucji Linuksa do oznaczania specjalnych miejsc w procedurach uruchomieniowych odwijających i wykonawczych longjump, aby debugowanie działało dobrze w ich obecności.

+0

Oprócz punktów sondowania, użyłem także składni "break function: label", aby uzyskać taki sam efekt w przeszłości. która również może być opcją. – matt

+0

@TomTromey: SystemTap jest również zależny od systemu Linux, prawda? Podczas gdy ELF, GCC i GDB nie są. – 0xC0000022L

+0

Tak, SystemTap jest zależny od systemu Linux. Możliwe jest jednak użycie sdt.h sond w innych systemach. Nie próbowałem, ale nie rozumiem, dlaczego nie. Cała strona sondy to tylko jeden plik nagłówkowy ... –

0

Rozumiem, że jest to stare pytanie, ale nadal nie mogłem znaleźć lepszego rozwiązania nawet teraz w 2017 roku. Oto rozwiązanie Python.Może to nie jest najbardziej wytrzymałe/najczystszym jeden, ale działa bardzo dobrze w wielu praktycznych scenariuszy:

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) 

ZASTOSOWANIE:

podstawowy:

RelativeFunctionBreakpoint("yourFunctionName", lineOffset=5) 

zwyczaj przerwania:

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 

Zalety roztworu

  • stosunkowo szybko, ponieważ punkt przerwania jest ustawiony tylko raz, przed rozpoczęciem wykonanie
  • odporny na zmiany w pliku źródłowym, jeżeli nie mają one wpływu na funkcję

Disadvatages

  • oczywiście, to nie jest solidna do edycji w funkcji samego
  • Niezbyt odporny na zmiany w składni wyjściowej poleceniagdb infofilm (prawdopodobnie istnieje lepszy sposób wyodrębnienia nazwy pliku i numeru linii)
  • inne? można wskazać