Pobranie GDB w celu zapisania listy punktów przerwania


130

OK, info break wyświetla punkty przerwania, ale nie w formacie, który dobrze by działał przy ich ponownym użyciu za pomocą --command, jak w tym pytaniu . Czy GDB ma metodę zrzucania ich do pliku, który można ponownie wprowadzić? Czasami podczas sesji debugowania konieczne jest ponowne uruchomienie GDB po utworzeniu zestawu punktów przerwania do testowania.

Plik .gdbinit ma ten sam problem co --command. Polecenie info break nie wyświetla poleceń, ale raczej tabelę do spożycia przez ludzi.

Aby rozwinąć, oto próbka z przerwy informacyjnej :

(gdb) przerwa informacyjna
Num Type Disp Enb Address What
1 punkt przerwania zachowaj y 0x08048517 <foo :: bar (void) +7>

Odpowiedzi:


207

Począwszy od GDB 7.2 (2011-08-23) można teraz używać komendy save breakpoints .

save breakpoints <filename>
  Save all current breakpoint definitions to a file suitable for use
  in a later debugging session.  To read the saved breakpoint
  definitions, use the `source' command.

Służy source <filename>do przywracania zapisanych punktów przerwania z pliku.


2
a co jeśli pochodzą ze współdzielonego obciążenia biblioteki? Domyślnie odpowiada na N, wydaje się ...Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
bjackfly


Zwróć uwagę, że jeśli masz warunek punktu przerwania, którego nie można rozwiązać podczas uruchamiania ( break g_log if log_level==G_LOG_LEVEL_CRITICAL), co najmniej gdb 7.8.1 przestanie analizować dalsze polecenia. Jeśli masz dodatkowe polecenia, które powinny być wykonane dla tego punktu przerwania, umieść tę commandslinię przed conditionlinią.
Lekensteyn

@Andry Przywróciłem twoją edycję do mojego oryginalnego cytatu blokowego, ponieważ tekst jest dosłownym cytatem z dokumentacji ... W przeciwnym razie zgodziłbym się z twoją zmianą, gdyby były to moje własne słowa.
aculich

@aculich: Rozumiem. W każdym przypadku zalecałbym użycie stylu cytowania zamiast stylu kodu.
Andry,

26

Ta odpowiedź jest nieaktualna. GDB obsługuje teraz bezpośrednie zapisywanie. Zobacz tę odpowiedź .

Możesz użyć logowania:

(gdb) b main
Breakpoint 1 at 0x8049329
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) set logging file breaks.txt
(gdb) set logging on
Copying output to breaks.txt.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) q

Plik breaks.txt zawiera teraz:

Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>

Napisanie skryptu AWK, który przekształci go w format przydatny dla pliku .gdbinitlub --command, jest łatwe. Lub możesz nawet sprawić, by skrypt emitował oddzielne komunikaty --eval-commanddo wiersza poleceń GDB ...

Dodanie tego małego makra do .gdbinit pomoże ci to zrobić:

# Call with dump_breaks file.txt
define dump_breaks
    set logging file $arg0
    set logging redirect on
    set logging on
    info breakpoints
    set logging off
    set logging redirect off
end

Równie łatwo można by użyć wycinania i wklejania, ale metoda skryptowa wydaje się być właściwą drogą.
casualcoder

1
nie sądzę, żeby metoda „wytnij i wklej” była łatwiejsza niż jednorazowe napisanie skryptu, a następnie używanie go za każdym razem :) w końcu to był właśnie powód, dla którego zadałeś to pytanie w pierwszej kolejności, myślę, że :)
Johannes Schaub - litb

Miałem na myśli użycie wycinania i wklejania zamiast metody logowania. Skrypty to na pewno to.
casualcoder

łał! gdb fail! Używam go codziennie i uwielbiam wiele jego funkcji. Ale brak jest po prostu głupi.
deft_code,

4
Ta odpowiedź ma już ponad 2 lata, więc może być nieaktualna, jeśli używasz nowszej wersji gdb. Od wersji gdb 7.2 możesz teraz używać save breakpointspolecenia.
aculich

11

Umieść swoje polecenia i punkty przerwania GDB w pliku .gdbinit w taki sam sposób, w jaki możesz je wpisać w gdb>monicie, a GDB automatycznie załaduje i uruchomi je podczas uruchamiania. To jest plik dla poszczególnych katalogów, więc możesz mieć różne pliki dla różnych projektów.


1
To faktycznie nie działa, otrzymuję „ostrzeżenie: zapisz-punkty śledzenia: brak punktów śledzenia do zapisania”. Dzieje się tak pomimo ustawiania punktów przerwania Korzystanie z gdb 6.8.
casualcoder

To działa dla mnie. GDB potrzebuje globalnego pliku .gdbinit w twoim $ HOME / .gdbinit z zawartością 'add-auto-load-safe-path /home/johnny/src/.gdbinit', a zatem folder src / ma również oddzielny .gdbinit
eigenfield

9

Rozszerzenie do rozszerzenia Anon jest do odpowiedzi Johannes' :

.gdbinit:

define bsave
    shell rm -f brestore.txt
    set logging file brestore.txt
    set logging on
    info break
    set logging off
    # Reformat on-the-fly to a valid GDB command file
    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

define brestore
  source brestore.gdb
end
document brestore
  restore breakpoints saved by bsave
end

Dzięki brestoremożesz następnie przywrócić punkty przerwania zapisane za pomocą bsave.


Oto lepsze wyrażenie regularne: perl -ne "print \" break \ $ 1 \ n \ "if /at\s(.*:\d+)/" brestore.txt
George Godik

6

Rozszerzenie odpowiedzi od Johannesa : możesz automatycznie przeformatować dane wyjściowe info breakdo prawidłowego pliku poleceń GDB:

.gdbinit:

define bsave
   shell rm -f brestore.txt
   set logging file brestore.txt
   set logging on
   info break
   set logging off
   # Reformat on-the-fly to a valid gdb command file
   shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

Następnie masz prawidłowy plik poleceń w brestore.gdb.

To zadziałało, gdy aplikacja jest kompilowana z -g.

Z powodzeniem przetestowałem go również z GDB v6.8 na Ubuntu 9.10 (Karmic Koala).


1
Dziękuję za ten fragment! Działa świetnie. Pomyślnie przetestowano z GNU gdb 6.3.50-20050815 (wersja Apple gdb-966) w CarbonEmacs GNU Emacs 22.3.1 (i386-apple-darwin9.6.0, Carbon wersja 1.6.0) w systemie Mac OS 10.5.8.
pestofagiczny


3

Umieść poniższy kod w ~ / .gdbinit, aby zdefiniować bsave i brestore jako polecenia GDB do zapisywania i przywracania punktów przerwania.

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end

1

ostrzeżenie: Bieżący protokół wyjściowy nie obsługuje przekierowania

Ten błąd / ostrzeżenie pojawia się również w GDB podczas próby włączenia logowania w trybie TUI . Jednak logowanie wydaje się działać w trybie „non-TUI”. Dlatego wychodzę z trybu TUI, gdy chcę coś zarejestrować. (Przełączaj się w tryb TUI za pomocąCtrl +X , Ctrl+A ).

Oto jak pracuję:

  1. uruchom GDB (w trybie normalnym)
  2. włącz logowanie: set logging on- teraz nie powinien narzekać.
  3. przełączaj się tam / z powrotem do trybu TUI i rób rzeczy GDB
  4. zawsze, gdy chcę coś zarejestrować (jak ogromny zrzut śladu) - przełącz się do trybu normalnego

Aha, i jeśli lubisz używać "screen" (tak jak ja), będzie to trochę bałagan, ponieważ używa tych samych skrótów klawiszowych.
Magnux

1

Znalazłem następujący dodatek do poprzedniej odpowiedzi przydatny do zapisywania / ładowania punktów przerwania do określonego pliku.

  • Zapisz punkty przerwania: bsave {filename}
  • Załaduj punkty przerwania: bload {filename}

Podobnie jak w poprzedniej odpowiedzi, dodaj następujący kod do pliku ~ / .gdbinit

# Save breakpoints to a file
define bsave
    if $argc != 1
        help bsave
    else
    save breakpoints $arg0
    end
end
document bsave
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsave <filename>
end

# Loads breakpoints from a file
define bload
    if $argc != 1
        help bload
    else
        source $arg0
    end
end
document bload
Loads all breakpoints from the defined file in the PWD
Usage: bload <filename>
end

0

Problem polega na tym, że ustawienie punktu przerwania jest zależne od kontekstu. A jeśli masz dwie statyczne funkcje o nazwie foo ?

Jeśli już debugujesz jeden z modułów, który definiuje foo, GDB przyjmie, że miałeś na myśli ten. Ale jeśli po prostu zrzucić „break foo” do pliku, a następnie odczytać ten plik przy rozruchu, to nie będzie jasne, które funkcja foo masz na myśli.


0

Jakieś inne pomysły? mam

warning: Current output protocol does not support redirection

po

set logging on

EDYTOWAĆ:

Wiem, że pytanie brzmi "jak zapisać listę punktów przerwania", jednak właśnie odkryłem, że z GDB możemy po prostu ustawić punkty przerwania "zapisane w pliku" przez

gdb> source breakpoints.txt

gdzie breakpoints.txtjest taki plik:

break main.cpp:25
break engine.cpp:465
break wheel.cpp:57
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.