반응형

GDB를 사용하여 원격 디버깅하는 방법을 다룹니다. 

진행을 위해 호스트는 윈도우가 설치된 노트북, 타겟은 라즈베리파이3를 사용했습니다.

 

2021. 2. 28  최초작성

 

GDB는 대부분의 Linux 시스템에 사용되는 텍스트 기반의 디버거입니다.

리모트 디버깅을 하려면 타겟에는 gdbserver를 실행하고 호스트에는 크로스 디버거 gdb를 실행해야 합니다.



0. 호스트에 크로스 GDB를 설치해야 합니다.

 

아래 링크에서 raspberry-gcc8.3.0-r3.exe를 다운로드하여 설치합니다. 

설치되는 디폴트 경로는 C:\SysGCC\raspberry입니다.

 

https://gnutoolchains.com/raspberry/

 

 

C:\SysGCC\raspberry\bin 경로에 필요한 gdb가 arm-linux-gnueabihf-gdb.exe라는 이름으로 있습니다. 




리눅스라면 다음처럼 크로스 GDB를 설치합니다. 이 경우 실행파일 이름이 gdb-multiarch입니다. 

 

$ sudo apt install gdb-multiarch

 

본 글에서는 호스트가 윈도우라고 가정하고 진행합니다.




1. 다음 파일들을 윈도우에서 작성해야 합니다. 

편의상 명령 프롬프트가 실행되는 위치인 C:\Users\사용자 이름에 test 폴더를 생성하여 진행합니다. 



test 폴더를 생성하고 해당 폴더로 이동합니다. 

 

C:\Users\webnautes>mkdir test

 

C:\Users\webnautes>cd test



다음처럼 명령 프롬프트에서 메모장을 실행하여 원하는 파일을 생성할 수 있습니다. 

 

C:\Users\webnautes\test>notepad helloWorld.cpp

 

C:\Users\webnautes\test>notepad Makefile



메모장을 사용한 경우 이름을 다음처럼 바꾸어줘야 합니다.

 

C:\Users\webnautes\test>rename Makefile.txt Makefile

 

 

작성해야하는 두 개의 파일입니다.

 

helloWorld.cpp

 

#include <iostream>


int main()

{

    int a = 1;

    int b = 2;


    int c = a + b;


   std::cout << c << std::endl;

}



Makefile

Makefile의 CFLAGS 옵션에 -g 옵션을 추가해야 합니다.

 

CC=arm-linux-gnueabihf-g++.exe

CFLAGS=-g


all: helloWorld.cpp

$(CC) helloWorld.cpp $(CFLAGS) -o helloWorld

clean:

rm -f helloWorld



다음 명령으로 컴파일합니다.

 

$ make

 

C:\Users\webnautes\test>make

arm-linux-gnueabihf-g++.exe helloWorld.cpp -g -o helloWorld



다음처럼 helloWorld 파일이 생성됩니다.

 

C:\Users\webnautes\test>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: 0453-0188

 

 C:\Users\webnautes\test 디렉터리

 

2021-02-28  오전 11:44    <DIR>          .

2021-02-28  오전 11:44    <DIR>          ..

2021-02-28  오전 11:44            29,880 helloWorld

2021-02-28  오전 11:40               130 helloWorld.cpp

2021-02-28  오전 11:44               140 Makefile

               3개 파일              30,150 바이트

               2개 디렉터리   3,828,408,320 바이트 남음



다음과 같은 에러가 난 경우 Makefile에서 들여쓰기 한 부분을 tab 키 입력 한번으로 수정해주세요. 

 

C:\Users\webnautes\test>make

Makefile:5: *** missing separator.  Stop.




2. 라즈베리파이에 SSH 접속해둡니다. 

윈도우에서 진행한다면 MobaXterm을 사용하는 것을 권장합니다. 



사용 방법은 “Raspberry Pi 4 처음 사용하기”(https://webnautes.tistory.com/899 )의  “5. SSH 클라이언트 사용하여 라즈베리파이에 접속”를 참고하세요. 

 

 

 

 

3. 호스트에서 scp를 사용하여 프로그램을 타겟에 복사합니다.

192.168.43.141는 라즈베리파이의 IP 주소로 변경하세요. 

 

scp helloWorld pi@192.168.43.141:/home/pi

 

C:\Users\webnautes\test>scp helloWorld pi@192.168.43.141:/home/pi

The authenticity of host '192.168.43.141 (192.168.43.141)' can't be established.

ECDSA key fingerprint is SHA256:+6cV62o5n6gooW0bKVwN7izWF9hIy8yYTTf8oK+NcGc.

Are you sure you want to continue connecting (yes/no)?  yes를 입력하세요. 입력한 문자가 보이지 않습니다.

Warning: Permanently added '192.168.43.141' (ECDSA) to the list of known hosts.

pi@192.168.43.141's password:  라즈베리파이 패스워드를 입력하세요. 입력한 문자가 보이지 않습니다.

helloWorld                                                                            100%   29KB 843.0KB/s   00:00



scp가 없는 경우 다음 경로에서 pscp.exe를 다운로드하여 C:\SysGCC\raspberry\bin에 복사해줍니다. 

https://the.earth.li/~sgtatham/putty/latest/w64/pscp.exe 

 

pscp를 사용하여 프로그램을 타겟에 복사합니다.

 

pscp -P 22  helloWorld pi@192.168.43.141:/home/pi 



C:\Users\webnautes\test>pscp -P 22  pi@192.168.43.141:/home/pi helloWorld

The server's host key is not cached in the registry. You

have no guarantee that the server is the computer you

think it is.

The server's ssh-ed25519 key fingerprint is:

ssh-ed25519 255 f2:e2:54:34:ab:34:de:d3:dd:50:93:96:17:c5:3d:84

If you trust this host, enter "y" to add the key to

PuTTY's cache and carry on connecting.

If you want to carry on connecting just once, without

adding the key to the cache, enter "n".

If you do not trust this host, press Return to abandon the

connection.

Store key in cache? (y/n) y   y를 입력하고 엔터키를 누릅니다.

pi@192.168.43.141's password:  패스워드를 입력합니다. 입력한 문자가 보이지 않습니다.

 

helloWorld                | 29 kB |  29.2 kB/s | ETA: 00:00:00 | 100%




4. 라즈베리파이와 연결된 ssh 터미널에서 프로그램을 실행시켜봅니다. 

실행하기 위해 퍼미션을 추가해주는 것이 필요합니다.

 

pi@raspberrypi:~ $ chmod +x helloWorld

pi@raspberrypi:~ $ ./helloWorld

3




5. 타겟에 gdbserver를 설치합니다.

 

$ sudo apt-get install gdbserver




6. gdbserver를 다음처럼 실행합니다.

 

포트번호 2001는 바꿀 수 있습니다.

여기에선 프로그램 이름이 helloWorld라고 가정합니다.

 

문제없다면 pid와 Listening port가 출력됩니다.

 

 gdbserver localhost:2001 helloWorld

 

pi@raspberrypi:~ $ gdbserver localhost:2001 helloWorld

Process /home/pi/helloWorld created; pid = 1423

Listening on port 2001




7. 호스트에서 helloWorld 프로그램이 있는 위치에서 다음처럼 크로스 디버거를 실행합니다.

 

윈도우라면

$ arm-linux-gnueabihf-gdb helloWorld

 

리눅스라면

$ gdb-multiarch helloWorld



C:\Users\webnautes\test>arm-linux-gnueabihf-gdb helloWorld

GNU gdb (Raspbian 8.2.1-2) 8.2.1

Copyright (C) 2018 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Type "show copying" and "show warranty" for details.

This GDB was configured as "--host=i686-w64-mingw32 --target=arm-linux-gnueabihf".

Type "show configuration" for configuration details.

For bug reporting instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>.

Find the GDB manual and other documentation resources online at:

    <http://www.gnu.org/software/gdb/documentation/>.

 

For help, type "help".

Type "apropos word" to search for commands related to "word"...

Reading symbols from helloWorld...done.

(gdb)




8. 호스트의 GDB 프롬프트 "(gdb)"에서 다음 명령을 사용하여 타겟에 접속합니다.

 

IP 주소는 타겟의 주소로 변경하세요. 

포트 번호는 gdbserver 실행시 지정한 것과 같아야 합니다.

 

(gdb) target remote 192.168.43.141:2001




9. 타겟에 다음 메시지가 출력됩니다.

 

Remote debugging from host 192.168.43.50




10. 호스트에서 디버깅을 해봅니다. 

 

(gdb) l  소스코드를 확인해봅니다. 

1       #include <iostream>

2

3       int main()

4       {

5           int a = 1;

6           int b = 2;

7

8           int c = a + b;

9

10         std::cout << c << std::endl;

(gdb) b 8  8번째 줄에 브레이크 포인트를 겁니다.

Breakpoint 1 at 0x106cc: file helloWorld.cpp, line 8.

 

(gdb) continue  실행시켜봅니다.

Continuing.

 

Breakpoint 1, main () at helloWorld.cpp:8  브레이크 포인트를 걸었던 8번쨰 줄에서 멈추었습니다.

8           int c = a + b;

(gdb) p a  변수 a의 값입니다. 

$1 = 1

(gdb) p b  변수 b의 값입니다. 

$2 = 2

(gdb) p c  변수 c의 값입니다. 아직 변수 c에 대입되기 전이라 c의 값은 0입니다. 

$3 = 0

(gdb) n  한줄 더 실행해봅니다.

10         std::cout << c << std::endl;

(gdb) p c   변수 c에 3이 대입되었습니다.

$4 = 3

(gdb) n    한줄 더 실행해보면 타겟에 3이 출력됩니다.

11      }

(gdb) q    디버깅을 중지합니다. 

A debugging session is active.

 

        Inferior 1 [process 1423] will be killed.

 

Quit anyway? (y or n) y

 

C:\Users\webnautes\test>



타겟에 출력된 메시지입니다.  3이 출력되어 있는 것을 볼 수 있습니다. 

 

pi@raspberrypi:~ $ gdbserver localhost:2001 helloWorld

Process /home/pi/helloWorld created; pid = 1423

Listening on port 2001

Remote debugging from host 192.168.43.50

3

pi@raspberrypi:~ $




터미널에서 GDB를 사용하여 디버깅하는 건 쉽지 않습니다. 



Visual Studio Code에서 디버깅을 해보세요. 

 

Visual Studio Code에서 GDB 원격 디버깅하는 방법

https://webnautes.tistory.com/1470

 

 

 

GDB 자세한 사용방법은 아래 링크를 참고하세요.

 

gdb 를 통한 디버깅 따라하기

http://psyoblade.egloos.com/2653919 

 

 

 

참고

https://opencoursehub.cs.sfu.ca/bfraser/grav-cms/cmpt433/guides/files/DebuggingGuide.pdf

 

https://medium.com/@karel.l.vermeiren/cross-architecture-remote-debugging-using-gdb-with-visual-studio-code-vscode-on-linux-c0572794b4ef

 

반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
질문을 남겨주면 가능한 빨리 답변드립니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 ~~

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts