Today, I will

[Pintos] 벌레를 잡기 위한 GDB 본문

Computer Science/핀토스

[Pintos] 벌레를 잡기 위한 GDB

Lv.Forest 2023. 5. 11. 23:13

<요약>

<빌드폴더> pintos --gdb -m 20   --fs-disk=10 -p tests/userprog/halt:halt --swap-disk=4 -- -q   -f run halt
혹은, pintos --gdb -m 20   --fs-disk=10 -p tests/userprog/args-multiple:args-multiple --swap-disk=4 -- -q   -f run 'args-multiple some arguments for you!'
<다른 터미널의 빌드폴더>gdb kernel.o
(gdb) target remote localhost:1234

😃 개별 테스트 결과 확인 :
<첫번쨰 터미널>
개별 테스트 예시1 : make tests/vm/mmap-clean.result VERBOSE=1
개별 테스트 예시2: make tests/userprog/args-multiple.result VERBOSE=1
개별테스트 gdb 돌리는 법 :pintos --gdb +  -m 20에서부터 긁어서 복붙
<두번째 터미널>
gdb kernel.o
디버깅 : target remote localhost:1234
b process.c:345 (브레이크 포인트)
p file(변수)
display는 p 같은 것으로 enter 치면서 추적할떄 편함!
n : 넥스트
엔터는 위 명령어 반복
s: 함수 진입
delete : 했던 브레이크 포인트 싹 다 지움
c c는 다음 브레이크 포인트까지 쭉 보는거
bt : 함수 콜스택

 

1. 기본 세팅

 

1. 테스트 케이스를 보고 싶은 폴더에 가서, make clean 후 make check

 

2. 다양한 테이트 케이스들이 나온다.

ubuntu@ip-172-31-32-179:~/final_complete/jungle-pintos/vm$ make check
cd build && make check
make[1]: Entering directory '/home/ubuntu/final_complete/jungle-pintos/vm/build'
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/args-none:args-none --swap-disk=4 -- -q   -f run args-none < /dev/null 2> tests/userprog/args-none.errors > tests/userprog/args-none.output
perl -I../.. ../../tests/userprog/args-none.ck tests/userprog/args-none tests/userprog/args-none.result
FAIL tests/userprog/args-none
Test output failed to match any acceptable form.

Acceptable output:
  (args) begin
  (args) argc = 1
  (args) argv[0] = 'args-none'
  (args) argv[1] = null
  (args) end
  args-none: exit(0)
Differences in `diff -u' format:
- (args) begin
- (args) argc = 1
- (args) argv[0] = 'args-none'
- (args) argv[1] = null
- (args) end
- args-none: exit(0)
+ phdr: 56
+ file offs: 0
+ phdr: 56
+ file offs: 4000
+ phdr: 56
+ args-none: exit(-1)
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/args-single:args-single --swap-disk=4 -- -q   -f run 'args-single onearg' < /dev/null 2> tests/userprog/args-single.errors > tests/userprog/args-single.output
perl -I../.. ../../tests/userprog/args-single.ck tests/userprog/args-single tests/userprog/args-single.result
FAIL tests/userprog/args-single
Test output failed to match any acceptable form.

Acceptable output:
  (args) begin
  (args) argc = 2
  (args) argv[0] = 'args-single'
  (args) argv[1] = 'onearg'
  (args) argv[2] = null
  (args) end
  args-single: exit(0)
Differences in `diff -u' format:
- (args) begin
- (args) argc = 2
- (args) argv[0] = 'args-single'
- (args) argv[1] = 'onearg'
- (args) argv[2] = null
- (args) end
- args-single: exit(0)
+ phdr: 56
+ file offs: 0
+ phdr: 56
+ file offs: 4000
+ phdr: 56
+ args-single: exit(-1)
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/args-multiple:args-multiple --swap-disk=4 -- -q   -f run 'args-multiple some arguments for you!' < /dev/null 2> tests/userprog/args-multiple.errors > tests/userprog/args-multiple.output
perl -I../.. ../../tests/userprog/args-multiple.ck tests/userprog/args-multiple tests/userprog/args-multiple.result
FAIL tests/userprog/args-multiple
Test output failed to match any acceptable form.

Acceptable output:
  (args) begin
  (args) argc = 5
  (args) argv[0] = 'args-multiple'
  (args) argv[1] = 'some'
  (args) argv[2] = 'arguments'
  (args) argv[3] = 'for'
  (args) argv[4] = 'you!'
  (args) argv[5] = null
  (args) end
  args-multiple: exit(0)
Differences in `diff -u' format:
- (args) begin
- (args) argc = 5
- (args) argv[0] = 'args-multiple'
- (args) argv[1] = 'some'
- (args) argv[2] = 'arguments'
- (args) argv[3] = 'for'
- (args) argv[4] = 'you!'
- (args) argv[5] = null
- (args) end
- args-multiple: exit(0)
+ phdr: 56
+ file offs: 0
+ phdr: 56
+ file offs: 4000
+ phdr: 56
+ args-multiple: exit(-1)
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/args-many:args-many --swap-disk=4 -- -q   -f run 'args-many a b c d e f g h i j k l m n o p q r s t u v' < /dev/null 2> tests/userprog/args-many.errors > tests/userprog/args-many.output
perl -I../.. ../../tests/userprog/args-many.ck tests/userprog/args-many tests/userprog/args-many.result
FAIL tests/userprog/args-many
Test output failed to match any acceptable form.

Acceptable output:
  (args) begin
  (args) argc = 23
  (args) argv[0] = 'args-many'
  (args) argv[1] = 'a'
  (args) argv[2] = 'b'
  (args) argv[3] = 'c'
  (args) argv[4] = 'd'
  (args) argv[5] = 'e'
  (args) argv[6] = 'f'
  (args) argv[7] = 'g'
  (args) argv[8] = 'h'
  (args) argv[9] = 'i'
  (args) argv[10] = 'j'
  (args) argv[11] = 'k'
  (args) argv[12] = 'l'
  (args) argv[13] = 'm'
  (args) argv[14] = 'n'
  (args) argv[15] = 'o'
  (args) argv[16] = 'p'
  (args) argv[17] = 'q'
  (args) argv[18] = 'r'
  (args) argv[19] = 's'
  (args) argv[20] = 't'
  (args) argv[21] = 'u'
  (args) argv[22] = 'v'
  (args) argv[23] = null
  (args) end
  args-many: exit(0)
Differences in `diff -u' format:
- (args) begin
- (args) argc = 23
- (args) argv[0] = 'args-many'
- (args) argv[1] = 'a'
- (args) argv[2] = 'b'
- (args) argv[3] = 'c'
- (args) argv[4] = 'd'
- (args) argv[5] = 'e'
- (args) argv[6] = 'f'
- (args) argv[7] = 'g'
- (args) argv[8] = 'h'
- (args) argv[9] = 'i'
- (args) argv[10] = 'j'
- (args) argv[11] = 'k'
- (args) argv[12] = 'l'
- (args) argv[13] = 'm'
- (args) argv[14] = 'n'
- (args) argv[15] = 'o'
- (args) argv[16] = 'p'
- (args) argv[17] = 'q'
- (args) argv[18] = 'r'
- (args) argv[19] = 's'
- (args) argv[20] = 't'
- (args) argv[21] = 'u'
- (args) argv[22] = 'v'
- (args) argv[23] = null
- (args) end
- args-many: exit(0)
+ phdr: 56
+ file offs: 0
+ phdr: 56
+ file offs: 4000
+ phdr: 56
+ args-many: exit(-1)
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/args-dbl-space:args-dbl-space --swap-disk=4 -- -q   -f run 'args-dbl-space two  spaces!' < /dev/null 2> tests/userprog/args-dbl-space.errors > tests/userprog/args-dbl-space.output
perl -I../.. ../../tests/userprog/args-dbl-space.ck tests/userprog/args-dbl-space tests/userprog/args-dbl-space.result
FAIL tests/userprog/args-dbl-space
Test output failed to match any acceptable form.

Acceptable output:
  (args) begin
  (args) argc = 3
  (args) argv[0] = 'args-dbl-space'
  (args) argv[1] = 'two'
  (args) argv[2] = 'spaces!'
  (args) argv[3] = null
  (args) end
  args-dbl-space: exit(0)
Differences in `diff -u' format:
- (args) begin
- (args) argc = 3
- (args) argv[0] = 'args-dbl-space'
- (args) argv[1] = 'two'
- (args) argv[2] = 'spaces!'
- (args) argv[3] = null
- (args) end
- args-dbl-space: exit(0)
+ phdr: 56
+ file offs: 0
+ phdr: 56
+ file offs: 4000
+ phdr: 56
+ args-dbl-space: exit(-1)
pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/halt:halt --swap-disk=4 -- -q   -f run halt < /dev/null 2> tests/userprog/halt.errors > tests/userprog/halt.output
^Cmake[1]: *** Deleting file 'tests/userprog/halt.output'
../../tests/Make.tests:75: recipe for target 'tests/userprog/halt.output' failed
make[1]: *** [tests/userprog/halt.output] Interrupt
../Makefile.kernel:10: recipe for target 'check' failed
make: *** [check] Interrupt

3. 예시로 하나의 테스트 케이스를 긁어서 복사한다. < /dev/null 2> 앞까지!

pintos -v -k -T 60 -m 20   --fs-disk=10 -p tests/userprog/halt:halt --swap-disk=4 -- -q   -f run halt < /dev/null 2> tests/userprog/halt.errors > tests/userprog/halt.output

4. build 폴더로 파고든다.

5. 아래와 같이 변경하고 첫번째 터미널에 작성해주고 엔터

(1) v -k -T 60를 삭제해준다. (T 60는 타이머 60이라는 뜻이다.)

(2) --gdb를 추가한다.

pintos --gdb -m 20   --fs-disk=10 -p tests/userprog/halt:halt --swap-disk=4 -- -q   -f run halt

(3) qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5] 이런 문자열이 떠야 1차 성공

6. 두번째 터미널을 준비한다.

(1) 역시 build 폴더여야 한다.

7. 아래와 같이 작성하고 엔터

gdb kernel.o

8. 아래와 같이 작성하고 엔터

(gdb) target remote localhost:1234

 

2. GDB 돌려보기

target remote localhost:1234

 

b process.c:345 (브레이크 포인트)

p file(변수)

display p 같은 것으로 enter 치면서 추적할떄 편함!

n : 넥스트

엔터는 위 명령어 반복

s: 함수 진입

delete : 했던 브레이크 포인트 싹 다 지움

c c는 다음 브레이크 포인트까지 쭉 보는거

bt : 함수 콜스택

 

quit -> yes 하면 종료

 
 

 

기타 잘 참고할만한 블로그!

https://velog.io/@phw1996/gdb-사용법

 

gdb 사용법

우선 gdb 를 설치한다. ubuntu 터미널에서 다음 명령어를 입력하면 된다. 내가 테스트 하고 싶은 파일들이 있는 폴더 (내 경우에는 /pintos/threads/build) 에 들어가서 원래 핀토스 테스트를 실행할때 쓰

velog.io

https://east-shine.tistory.com/2

 

Pintos Tip

19년 봄 OS수업을 들으며 진행한 Project Pintos에 대 고민했던, 힘들었던 정보들을 적어 나눠보려합니다. Project 1을 시작하기 전에 보면 좋았던 사실들입니다. 1. 에디터 본래 다른 에디터보다 terminal

east-shine.tistory.com

 

 

<처음 세팅>

 

 

gdb 를 설치. ubuntu 터미널에서 다음 명령어를 입력

sudo apt install gdb

테스트 하고 싶은 파일들이 있는 폴더 (내 경우에는 /pintos/threads/build) 에 들어가서

원래 핀토스 테스트를 실행할때 쓰는 명령어는

pintos -- -q run ${실행하려는 테스트이름}

개별 실행은

src/threads 에서 make 한 후 생성되는 build 폴더에서 make check을 실행하면 각종 실행 문구와 함께 test case가 실행

여기서 pintos -v -k -T ~~~~~ args-none < /dev/null 2 > 의 pintos 부터 args-none까지 복사하여 VScode Terminal에서 실행하면 개별실행이 가능

 

 

gdb로 실행하기위해서는

pintos --gdb -- -q run ${실행하려는 테스트이름}

로 실행을. 실행하면 중단점을 따로 지정해놓지 않았기 때문에 우선 맨 처음으로 포인터가 가서 대기


이상태에서 터미널을 하나 새로 연다.

동일하게 테스트 파일을 만들어놓은 폴더로 이동
(cd /pintos/threads/build)

gdb kernel.o

이 명령어를 실행하면 gdb가 실행

그다음 그 상태에서

target remote localhost:1234

명령어를 사용하면 gdb와 연결

이후 일반 GDB명령을 실행

기본적인 gdb 명령어

b {$파일이름}:785  // 파일의 785번째 라인에 중단점을 잡는다.

c // continue 라는 의미로 중단점까지 쭉 진행한다. 

n // next 라는 의미로 함수를 만나면 호출하고 지나간다. (함수안으로 안들어감)

s // step 이라는 의미로 함수를 만나면 안으로 들어간다. 

p {$각종 변수, 포인터} // 해당 변수, 포인터들이 담고있는 내용을 보여준다. 

d // 잡혀있는 모든 중단점을 없앤다. 
 

<최종 정리>

 

GDB

VScode에서 2개의 terminal을 준비(각각 Ter1과 Ter2)

 

두 terminal 모두 build폴더에서 진행

 

Ter1에서 2.에서 말한 개별 실행 문구에 pintos --gdb -v -k 로 --gdb라는 걸 넣어준 후 실행

 

이후 Ter2에서 gdb kernel.o 라고 치고 엔터

 

그렇게 되면 Ter2에서 (gdb) $ 로 들어간 것을 볼 수 있다

 

여기서 Ter1과 연동을 해주기 위해 target remote localhost:1234 를 지정(port 를 변경하지 않아도 되지만 하고싶다면 Utils/pintos line 566, 과 Misc/gdb-macros line 163 을 변경)

 

이후 Ter2에서 break point 를 잡으면서 계속 진행하시면 Ter1에 결과가 나오면서 진행

 

정리하자면

(0). Ter1, Ter2 모두 build 폴더

(1). Ter1 에서 pintos --gdb -v -k -T ~~ 로 gdb 옵션을 킨 명령어를 개별 실행

(2). Ter2 에서 gdb kernel.o 로 gdb 접속

(3). Ter2 에서 target remote localhost:1234 로 Ter1과 연결

(4). Ter2 에서 진행