사용법 GDB

오늘은 ‘리눅스 디버거’인 GDB의 사용법에 대해 알아보자.

GDB는 코어 파일 분석 또는 프로세스 디버깅에 사용된다.

  1. Core 파일 분석 core file을 분석하기 위해서는 먼저 segmentation fault 발생 시 core file이 생성되도록 설정하여야 한다. core file은 현재 사용자에게 설정되어 있는 최대 core file 사이즈가 0보다 클 경우 core file 이 생성되는데, 이 값은 ulimit 명령을 통해 확인할 수 있다.
  2. ulimit : ulimit is admin access required Linux shell command which is used to see , set , or limit the resource usage of the current user . It is used to return the number of open file descriptors for each process . It is also used to set restrictions on the resources used by a process
  3. ulimit 은 위의 설명과 같이 사용자의 자원 또는 프로세스에 의해 사용되는 자원을 제한하거나 확인하기 위해 사용된다.
  4. ulimit [옵션] 값 (Centos, RHEL 기준)-a : 모든 제한사항 표시.-c:최대 코어 파일 크기-d:프로세스 데이터 세그먼트의 최대 크기-f:shell에 의해 만들어지는 최대 파일 사이즈-s:최대 스택 사이즈-p:파이프 사이즈-n:오픈 파일의 최대 수-u:오픈 파일의 최대 수-v:프로세스 데이터 세그먼트의 최대 수-v:최대 수
  5. 위와 같이 많은 옵션을 통해 여러 값을 설정할 수 있는데, 지금 필요한 것은 core file의 최대 사이즈를 확인하는 것이므로 아래와 같이 ulimit-a를 통해 core file의 최대 사이즈를 확인한다.현재 core file size가 0이므로 segmentation fault가 발생하더라도 core 파일이 생성되지 않는다. core file을 생성하기 위해서 다시 한번 ulimit 명령어로 core file size를 변경한다.변경 후 ulmit에서 다시 조회할 때 아래와 같이 core file size가 unlimited로 변경되었음을 확인할 수 있다.간신히 core file이 생성되도록 설정했기 때문에 실제로 core dump를 만들어 보도록 한다. 쉽게 Initialize가 아닌 string pointer를 참조하는 코드를 삽입했다.실행하면 segmentation fault 에러가 발생함을 확인할 수 있다.Red hat에서 테스트를 한 경우는 해달 폴더 아래에 core.xxx로 파일이 떨어졌는데, 현재 사용하고 있는 centOS는 core 파일명/파일형태/위치가 설정되어 있지 않거나/var/lib/systemd/coredump 경로에 lz4로 압축된 형태로 core dump가 생성되었다.이제 core dump를 gdb를 사용해서 분석해 보자.
  6. gdb [program or core dump file]을 사용하여 core file을 열면 아래와 같이 core dump가 gdb에 의해 열린다.이하의 gdb 명령에 의해 코어 디스크를 분석하는 것이,
  7. ● bt (많이 사용해!!!!!!!!) – call stack, backtrace- stack 정보를 나열, 반대로 추적 가능- full 옵션을 사용하면 더 자세히 제공
  8. ●file [파일의 절대경로] – 해당 파일의 정보를 불러온다. 리스트 명령으로 코드를 보기 위해서는 file 명령으로 파일 정보를 등록해야 한다.
  9. ● frame [framenumber] (자주사용!!!) bt에서 나온 코드블록 중 특정 frame 정보를 확인하기 위한 명령어
  10. ● list(많이 사용!!!) – stack의 소스 코드 표시하기 – frame에서 블럭 선택 후 list를 통해 해당 frame의 코드 확인 가능
  11. ● print [변수](다용!!!)-특정 변수의 값을 확인할 때 사용-frame, list와 함께 사용하면 특정 frame의 코드와 해당 코드에서의 실제 변수 중의 값을 확인할 수 있다.
  12. 위의 방식 등을 활용해 콜스택을 추적하고 에러의 원인을 찾아내면 된다.
  13. 실제 오류가 발생했을 경우 부장들의
  14. 2. Debugging 2-1. Debugging running process Debugging을 위해서는 우선적으로 compile의 경우 -g 옵션을 부여해야 한다. g옵션을 사용하면 gdb에 제공할 바이너리 정보를 생성한다.
  15. Debugging을 하는 방법 중에는 두 가지 방법이 있다. 현재 실행 중인 프로세스에 대해 디버깅을 하거나 프로그램을 gdb 내에서 실행하여 디버깅하는 방법이 있다.
  16. 1) 실행 중인 프로그램 Debugging 쉬운 테스트를 위해 아래와 같이 5초에 한번 cycle 정보를 찍는 코드를 만들었다.이를 실행한 후 ps 명령어를 통해 pid를 확인한다.pid를 확인했으면 아래의 명령어를 통해 gdb를 실행한다.
  17. gdb-p [pid] 또는 gdb를 실행한 후(gdb) attach [pid] 명령을 실행하면, 위 화면과 같이 gdb가 해당 process의 control을 가져오는 것을 볼 수 있다(control을 가져온 상태이므로, 해당 process는 일시 정지된 상태이다).
  18. Debugging 이 필요한 코드에 break 명령을 통해 break point를 파악한다.
  19. (gdb) b [line or file : line] 10 라인에 break point가 들어가는 것을 확인할 수 있다.
  20. 그 후 일시 정지된 프로세스를 다시 실행한다. 이미 구동중이었던 프로그램이기 때문에 run을 할 필요가 없고, continue 명령에 의해서 일시정지된 부분부터 재시작한다.
  21. (gdb) continue continue 와 동시에 process 가 다시 실행되며, 앞서 설정한 break point 에 break 이 있음을 확인할 수 있다.
  22. 이후의 단계 또는 n에 다음 코드로 갈 수 있지만, 단계가 n에는 이하와 같은 차이가 있다.(gdb) step -> 다음 라인 확인 만약 함수라면 함수 내부로 들어간다.(gdb) n -> 함수에 들어가지 않고 다음 라인을 확인한다.
  23. n에서 다음 라인으로 이행하고 print에서 변수가 가지는 실제 값을 확인할 수 있다. 만약 기본 데이터 타입이 아닌 자료형을 사용할 경우, 해당 자료형에서 .data()와 같이 c++ 자료형을 리턴하는 함수가 있다면 gdb 상에서 해당 함수를 다음과 같이 실행하여 값을 확인할 수 있다.
  24. ( gdb ) print var . data ( )
  25. 2-2.Debugging program, 이번에는 실행 중인 프로그램이 아니라 프로그램을 실행하고 디버깅을 해보려고 한다. 2-1로 생성한 프로그램을 이번에는 gdb로 실행시키고 디버깅을 해보려고, 아래의 명령어를 사용해서 gdb를 해당 프로그램과 연결한다.
  26. gdb [ program ]
  27. 이전에는 이미 실행 중인 프로세스에 대한 디버깅이었지만, 이번에는 아직 실행하지 않은 프로그램에 대한 디버깅이므로, run 명령을 통해 연결된 프로그램을 실행시킨다.
  28. ( gdb ) run
  29. run 명령어 실행 시 아래와 같이 프로그램이 실행되는 것을 확인할 수 있다. 단, 주의해야 할 점은 run 명령어를 실행하기 전에 원하는 break point를 걸고 시작해야 debugging이 가능하다.지금까지의 내용은 정말 간단한 것이므로, 보다 복잡한 디버깅은 이하의 gdb 명령어를 참조하여 하면 된다.
  30. 참조: https://blog.naver.com/euclid1001/40179341273

error: Content is protected !!