21.10.4. JTAG/SWD 하드웨어 디버거 및 GDB 연동 타겟 디버깅
앞서 우리는 드론이 추락한 뒤에 남긴 유언장(Crash Dump)을 부검하는 법을 배웠다. 하지만 최고의 의사는 사후 부검을 잘하는 의사가 아니라, 환자가 죽기 전에 몸통 열어젖히고 심장을 직접 주물러 살려내는 의사다.
임베디드 소프트웨어 개발의 정수이자 가장 강력한 흑마법, **온칩 디버깅(On-Chip Debugging)**의 세계로 진입할 시간이다.
픽스호크 펌웨어(NuttX)는 일반적인 리눅스처럼 printf를 덕지덕지 발라가며 에러를 잡기에는 실시간성(Hard Real-time)이 너무도 민감하다. 우리가 원하는 것은 단 하나, “내가 의심하는 142번 줄(Line)에 펌웨어가 도달하는 바로 그 찰나의 순간에 CPU 클럭 점화 플러그를 뽑아서 우주 전체의 시간을 정지시키는 것“이다.
그리고 정지된 우주 속으로 들어가, 메모리 번지수 하나하나에 쓰여있는 변수 값들을 돋보기로 들여다보고 강제로 조작까지 해버리는 것이다.
이 신의 권능을 엔지니어의 손에 쥐여주는 물리적인 열쇠가 바로 **JTAG/SWD 하드웨어 디버거(Hardware Debugger)**다.
1. 하드웨어 디버거 (SEGGER J-Link & ST-Link)
보통 픽스호크 보드의 구석을 잘 찾아보면, 핀이 촘촘하게 박힌 아주 작은 디버그 커넥터(Debug Port)가 숨어있다. 여기에 연결하는 중간 어댑터 장비를 흔히 JTAG 디버거 혹은 SWD 프로그래머라고 부른다. (업계의 표준인 J-Link나, 저렴한 ST-Link V2가 대표적이다.)
이 장비를 픽스호크의 심장(Cortex-M 코어)에 물리적으로 꽂고 USB로 내 컴퓨터 우분투(Ubuntu)에 연결하면, 비로소 내 컴퓨터의 GDB(GNU Debugger) 소프트웨어와 픽스호크의 두뇌가 한 몸으로 연결된다.
2. 펌웨어와 디버거의 교신 원리
이 둘을 연결하는 생태계는 대략 다음과 같이 동작한다.
- GDB Server (J-Link GDB Server / OpenOCD): 내 우분투 컴퓨터에서 백그라운드로 도는 통역사. USB로 들어오는 디버거 장비의 물리적인 전기 신호를 받아 GDB 소프트웨어가 이해할 수 있는 통신 포트(TCP: 2331)로 열어준다.
- GDB Client (
arm-none-eabi-gdb): 개발자가 무시무시한 명령어를 치는 터미널 프로그램. 아까 뽑아둔 디버깅 심벌이 가득한 거대한 파일(px4_fmu-vX_default.elf)을 씹어 먹고, 저 통역사 포트(:2331)로 접속해 픽스호크의 뇌를 장악한다.
명령어 하나로 드론의 프로펠러가 돌다 멈추고, FSM 상태 변수(_current_state)를 강제로 TRIGGER로 바꿔버려 하늘에서 짐을 투하하게 만들 수도 있다.
이 궁극의 해킹 도구를 세팅하고, 메모리 속 한 점을 노려 브레이크포인트(Breakpoint)의 덫을 놓는 치명적인 GDB 명령어 스크립팅 기법을 마지막 21.10.4.1.1장에서 폭발시켜보겠다.