Skip to content

GDB

보통은 GDB라고 부르는 GNU 디버거는 GNU 소프트웨어 시스템을 위한 기본 디버거이다. GDB는 다양한 유닉스 기반의 시스템에서 동작하는 이식성있는 디버거로, 에이다, C/C++, 포트란 등의 여러 프로그래밍 언어를 지원한다.

Categories

How to use

GCC컴파일-g옵션을 추가한다.

$ gcc -g -o main main.c

컴파일이 정상 종료 되면 GDB를 실행한다.

## gdb [프로그램명] 또는 gdb [프로그램명] [프로세스PID]
$ gdb main
## or
$ gdb main 1928

Breakpoint 예제

Breaking point 설정.

b (breaking) 3
b main
b file.c:10

Breaking point 설정. - 현재 라인으부터 두줄 전에 브레이크. -

b -2

Breaking point 설정. - 10라인에 브레이크를 거는데 tmp 가 0 일때만 브레이크. -

b 10 if tmp ==0

Breaking point 삭제.

cl (clear) 10
cl hello
cl file.c:2

Breaking point 보기.

info breakpoints

Breaking points 활성/비활성.

enable 2
disable 2

StackTrace (BackTrace) 예제

(gdb) bt
Display all 200 possibilities? (y or n)
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140696826032128) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140696826032128) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140696826032128, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ff688e05476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ff688deb7f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ff68945a7c2 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#6  0x00007ff68945a9f1 in g_private_set () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#7  0x00007ff68942bdec in g_slice_alloc () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#8  0x00007ff68942e838 in g_string_sized_new () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#9  0x00007ff6893f5091 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#10 0x00007ff6893f553c in g_build_filename () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#11 0x00007ff6895fa1ec in  () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#12 0x00007ff6895fa472 in  () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#13 0x00007ff6895faa30 in  () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#14 0x00007ff6895fcfe1 in gst_update_registry () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#15 0x00007ff68958edda in  () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#16 0x00007ff689419a48 in g_option_context_parse () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#17 0x00007ff689586877 in gst_init_check () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#18 0x00007ff689586908 in gst_init () at /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
#19 0x000055b1c0a98715 in main(int, char**) (argc=1, argv=0x7ffc777a01b8) at /root/Project/answer-jet/src/answer_jet.cpp:140
(gdb) frame 19
#19 0x000055b1c0a98715 in main (argc=1, argv=0x7ffc777a01b8) at /root/Project/answer-jet/src/answer_jet.cpp:140
140       gst_init(&argc, &argv);
(gdb) l
135     }
136
137     }
138
139     int main(int argc, char *argv[]) {
140       gst_init(&argc, &argv);
141
142       answer_jet::AnswerJet jet_main;
143       jet_main.Run();
144
(gdb) frame 18
#18 0x00007ff689586908 in gst_init () from /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0
(gdb) l
145       return 0;
146     }
(gdb)

How to build for MinGW

GDB에 --with-python옵션이 추가된 MinGW컴파일 방법은 아래와 같다.

$ ./configure --with-python --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --enable-static
$ make
$ make install

How to save breakpoint list

GDB에서 브레이크포인트를 저장하고 불러오는 방법은 아래와 같다.

  • Save: save breakpoints {filename}
  • Load: source {filename}

If the break points are not yet loaded, you may want to tell gdb to allow loading those breakpoints later: set breakpoint pending on

Installing GDB on OS X

gcc-program using lldb or clang-program using gdb

질문: GCC로 컴파일한 프로그램을 lldb에서 디버깅할 수 있나요? 또는 clang에서 컴파일한 프로그램을 gdb에서 디버깅할 수 있나요? 답변은 아래와 같다.

In theory you should be able to debug a GCC-built program with lldb and an LLVM-built program with gdb. In both cases you should compile with -g.

This is because both compilers generate object files in the same format (e.g., on Linux, both will generate ELF files with DWARF debug info) and both debuggers know how to parse that format.

In practice, both compilers push some data into the debug info that only their respective debugger knows how to consume. However:

* LLVM-generated data should not hinder gdb in any way.
* GCC-generated data should not hinder lldb, but if it does you can specifically ask gcc to not add non-standard data. For example, on Linux, using -gdwarf-2 over -g should only generate standard-compliant DWARF.

Notice that you can also debug programs without debug info (not compiled with -g), but you'll be limited to low-level information in the debugger - assembly code, memory and registers - and will not be able to see high level constructs such as line numbers, function names, mapping between variable names and their content, etc.

Avoiding gdb signal noise

(gdb) info signal SIGUSR1
Signal        Stop      Print   Pass to program Description
SIGUSR1       Yes       Yes     Yes             User defined signal 1

And if deemed to not be of interest, where you just want your program to continue without prompting or spamming, something like the following does the trick:

(gdb) handle SIGUSR1 noprint nostop
Signal        Stop      Print   Pass to program Description
SIGUSR1       No        No      Yes             User defined signal 1

디버깅 심볼 확인하는 방법

objdump를 사용하면 된다:

objdump --syms {OBJECT_PATH}

이렇게 하면 debug 라는 이름이 붙은 Section 들이 있다. 만약 관련 내용이 있다면 다음과 같이 출력된다:

$ objdump --syms ./modules/lib/modules/3.12.6/kernel/drivers/i2c/busses/i2c-at91.ko | grep debug
00000000 l    d  .debug_frame   00000000 .debug_frame
00000000 l    d  .debug_info    00000000 .debug_info
00000000 l    d  .debug_abbrev  00000000 .debug_abbrev
00000000 l    d  .debug_loc     00000000 .debug_loc
00000000 l    d  .debug_aranges 00000000 .debug_aranges
00000000 l    d  .debug_ranges  00000000 .debug_ranges
00000000 l    d  .debug_line    00000000 .debug_line
00000000 l    d  .debug_str     00000000 .debug_str
00000010 l       .debug_frame   00000000 $d

Debugging stripped binaries

Memory dump

Intel syntax

set dissassembly-flaver intel

Working Directory

Each time you start your program with run, the inferior will be initialized with the current working directory specified by the set cwd command. If no directory has been specified by this command, then the inferior will inherit GDB’s current working directory as its working directory if native debugging, or it will inherit the remote server’s current working directory if remote debugging.

set cwd [directory]
Set the inferior’s working directory to directory, which will be glob-expanded in order to resolve tildes (~).
show cwd
Show the inferior’s working directory.
cd [directory]
Set the GDB working directory to directory. If not given, directory uses '~'.
pwd
Print the GDB working directory.

Python gdb debugging

Dgb에서 Python BackTrace 출력을 위한 libpython.py 스크립트 다운로드.

## Python 2.x 일 경우 별도 확인 필요.
$ curl -O https://raw.githubusercontent.com/python/cpython/master/Tools/gdb/libpython.py

.gdbinit 파일 수정:

python
import gdb
import sys
import os
sys.path.insert(0, os.path.expanduser("~/.config/gdb"))
def setup_python(event):
    import libpython
gdb.events.new_objfile.connect(setup_python)
end

gdb 명령으로 py-bt으로 Python의 Backtrace를 확인할 수 있다. 또한, py-list 명령으로 마지막 오류 발생 스크립트를 확인할 수 있다.

Example

Attach Process Debugging

answer에서 Task를 자식 프로세스로 띄었을 경우 다음과 같은 에러가 발생되었다.

Python CALL on_loop_begin()
D 2020-08-26T17:09:11.985586212 @140737353837056 T<default> Loop#14 recv ok: 48byte, 1737ms
N 2020-08-26T17:09:11.985657156 @140737353837056 T<default> InfoTasksQ(i=1,c=0)
I 2020-08-26T17:09:11.985930275 @140737353837056 T<default> | Send 'InfoTasksA' message successful. 0ms
D 2020-08-26T17:09:11.985957996 @140737353837056 T<default> Loop#14 route ok: 0ms
[001|E] munmap_chunk(): invalid pointer
[001|E] SIGABRT (6):
[001|E]  #00 0x00007FFFF7A37E1E +4128286 [/home/serverid/Project/c2core/cmake-build-debug/libc2deep.so.1]
[001|E]  #01 0x00007FFFF7A37F16 c2deepMain+0 [/home/serverid/Project/c2core/cmake-build-debug/libc2deep.so.1]
[001|E]  #02 0x00007FFFF7A39940 std::_Function_handler<void (int), void (*)(int)>::_M_invoke(std::_Any_data const&, int&&)+50 [/home/serverid/Project/c2core/cmake-build-debug/libc2deep.so.1]
[001|E]  #03 0x00007FFFF7B2B5C2 std::function<void (int)>::operator()(int) const+72 [/home/serverid/Project/c2core/cmake-build-debug/libc2deep.so.1]
[001|E]  #04 0x00007FFFF4AA1668 +9012840 [/home/serverid/Project/tbag/cmake-build-debug/libtbag.so.0]
[001|E]  #05 0x00007FFFF4AA1E4F +9014863 [/home/serverid/Project/tbag/cmake-build-debug/libtbag.so.0]
[001|E]  #06 0x00007FFFF4AA1F2A +9015082 [/home/serverid/Project/tbag/cmake-build-debug/libtbag.so.0]
[001|E]  #07 0x00007FFFF4AA1154 +9011540 [/home/serverid/Project/tbag/cmake-build-debug/libtbag.so.0]
[001|E]  #08 0x00007FFFF7295FD0 +258000 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #09 0x00007FFFF7295F47 gsignal+199 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #10 0x00007FFFF72978B1 abort+321 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #11 0x00007FFFF72E0907 +563463 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #12 0x00007FFFF72E797A +592250 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #13 0x00007FFFF72EEF3C cfree+1404 [/lib/x86_64-linux-gnu/libc.so.6]
[001|E]  #14 0x00007FFFB4D9C206 std::__detail::_Compiler<std::regex_traits<char> >::_Compiler(char const*, char const*, std::locale const&, std::regex_constants::syntax_option_type)+1702 [/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/lib/libtorch_cpu.so]
[001|E]  #15 0x00007FFFEE4ECB60 c10::Device::Device(std::string const&)+1520 [/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packa
ges/torch/lib/libc10.so]
[001|E]  #16 0x00007FFFD895E13A +2543930 [/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/lib/libtorch_python.so]
[001|E]  #17 0x00007FFFD8B22702 THPDevice_pynew(_typeobject*, _object*, _object*)+226 [/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/s
ite-packages/torch/lib/libtorch_python.so]
[001|E]  #18 0x00007FFFF3DA9C15 +1072149 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #19 0x00007FFFF3D3ECB3 _PyObject_FastCallKeywords+195 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #20 0x00007FFFF3D14E78 _PyEval_EvalFrameDefault+30600 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #21 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #22 0x00007FFFF3D3E69F _PyFunction_FastCallKeywords+143 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #23 0x00007FFFF3D15FC7 _PyEval_EvalFrameDefault+35031 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #24 0x00007FFFF3D0C5DF +427487 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #25 0x00007FFFF3D140BF _PyEval_EvalFrameDefault+27087 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #26 0x00007FFFF3D0C5DF +427487 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #27 0x00007FFFF3D140BF _PyEval_EvalFrameDefault+27087 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #28 0x00007FFFF3D0C5DF +427487 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #29 0x00007FFFF3D140BF _PyEval_EvalFrameDefault+27087 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #30 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #31 0x00007FFFF3D3E69F _PyFunction_FastCallKeywords+143 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #32 0x00007FFFF3D140BF _PyEval_EvalFrameDefault+27087 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #33 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #34 0x00007FFFF3D3E50F _PyFunction_FastCallDict+463 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #35 0x00007FFFF3D3FA72 +637554 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #36 0x00007FFFF3D3FE79 PyObject_CallFunctionObjArgs+153 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #37 0x00007FFFE31223FD +74749 [/usr/local/c2core/lib/python3.7/lib-dynload/_pickle.cpython-37m-x86_64-linux-gnu.so]
[001|E]  #38 0x00007FFFF3D3EABA _PyMethodDef_RawFastCallKeywords+522 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #39 0x00007FFFF3D4776A _PyMethodDescr_FastCallKeywords+74 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #40 0x00007FFFF3D167FB _PyEval_EvalFrameDefault+37131 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #41 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #42 0x00007FFFF3D3E48A _PyFunction_FastCallDict+330 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #43 0x00007FFFF3D126B5 _PyEval_EvalFrameDefault+20421 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #44 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #45 0x00007FFFF3D3E69F _PyFunction_FastCallKeywords+143 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #46 0x00007FFFF3D143AE _PyEval_EvalFrameDefault+27838 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #47 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #48 0x00007FFFF3D3E69F _PyFunction_FastCallKeywords+143 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #49 0x00007FFFF3D140BF _PyEval_EvalFrameDefault+27087 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #50 0x00007FFFF3E2DDDE _PyEval_EvalCodeWithName+2718 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #51 0x00007FFFF3D3E50F _PyFunction_FastCallDict+463 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #52 0x00007FFFF3D3F6BC _PyObject_Call_Prepend+204 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #53 0x00007FFFF3DAF641 +1095233 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #54 0x00007FFFF3DA9C62 +1072226 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #55 0x00007FFFF3D3ECB3 _PyObject_FastCallKeywords+195 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #56 0x00007FFFF3D14E78 _PyEval_EvalFrameDefault+30600 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #57 0x00007FFFF3D0C5DF +427487 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #58 0x00007FFFF3D15FC7 _PyEval_EvalFrameDefault+35031 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #59 0x00007FFFF3D0C5DF +427487 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
[001|E]  #60 0x00007FFFF3D3E5F7 _PyFunction_FastCallDict+695 [/usr/local/c2core/lib/libpython3.7m.so.1.0]
N 2020-08-26T17:09:12.278744686 @140736823338752 /home/serverid/Project/c2core/libc2deep/task/TaskManager.cpp:869 [TaskManager] Exit Task(id=1,exit=1,signum=0)
E 2020-08-26T17:09:12.278820233 @140736823338752 T<default> TASK(id=1)|exit(exit=1,signal=0) Error Done!

#Python gdb debugging 항목의 설정을 완료한 후, 프로그램을 기동한다. (자식테스크에게 Kill 신호를 주지 않도돍 해야 하기 때문에 gdb 에서 인터럽트를 걸어준다)

Parent process:

$ gdb --args ./c2node -v node

## child process 에서 정상적으로 attach 되었다면 Kill 신호를 보내지 못하도록, 인터럽트(Ctrl+C)를 걸어준다.

Child process:

$ gdb --pid=5141 ./c2node

## 정상적으로 attach 되었다면 곧바로 break가 걸린다. 바로 continue 해주면 된다.

WARNING

만약 정상적으로 attach 되지 않는다면 sudo를 사용하여 관리자 권한으로 접속하면 된다.

이후, py-bt 명령을 날리면 다음과 같이 출력된다.

Traceback (most recent call first):
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/cuda/_utils.py", line 21, in _get_device_index
    device = torch.device(device)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 131, in validate_cuda_device
    device = torch.cuda._utils._get_device_index(location, True)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 150, in _cuda_deserialize
    device = validate_cuda_device(location)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 174, in default_restore_location
    result = fn(storage, location)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 800, in restore_location
    return default_restore_location(storage, map_location)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 721, in persistent_load
    deserialized_objects[root_key] = restore_location(obj, location)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 765, in _legacy_load
    result = unpickler.load()
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/torch/serialization.py", line 585, in load
    return _legacy_load(opened_file, map_location, pickle_module, **pickle_load_args)
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/easyocr/detection.py", line 61, in get_detector
    net.load_state_dict(copyStateDict(torch.load(trained_model, map_location=device)))
  File "/home/serverid/Project/c2core/storage/venv/easyocr/lib/python3.7/site-packages/easyocr/easyocr.py", line 286, in __init__
    self.detector = get_detector(detector_path, self.device)
  File "/home/serverid/Project/c2core/storage/python/answer-lambda-ocr/easyocr_tools.py", line 7, in init_recognizer
    return easyocr.Reader(lang_list)
  File "<string>", line 167, in on_init

Plugins

Text User Interface

Troubleshooting

Python scripting is not supported

아래와 같은 메시지가 출력될 수 있다.

Error in sourced command file:
Python scripting is not supported in this copy of GDB

이 경우 --with-python옵션을 추가하여 GDB를 다시 컴파일 해야 한다.

See also

Favorite site

Build

Guide

DataSheet

with vim

References


  1. GDB_–_Debugging_stripped_binaries.pdf 

  2. Brunch.co.kr_-_gdb_memory_dump.pdf 

  3. Mcchae-python-segfault-gdb-stacktrace.pdf 

  4. Fifth_Edition_for_GDB_version.zip 

  5. Korea_gnu-gdb_debugging-fifth_edition.pdf 

  6. KLDP-How_to_nice_use_the_gdb_1.pdf 

  7. KLDP-How_to_nice_use_the_gdb_2.pdf 

  8. Sourceware.org_-_gdb.pdf 

  9. Sourceware.org_-_gdbint.pdf 

  10. Reverse_engineering_-_Understanding_what_a_Linux_binary_is_doing.pdf