☑️ 개요
소프트웨어 개발에서 디버깅은 개발자가 프로그램의 동작을 분석하고 문제를 해결하며, 최종적으로 안정적인 제품을 만들기 위해 꼭 필요한 과정입니다. 일반적으로 소프트웨어 디버깅에서는 IDE(통합 개발 환경)를 통해 소스 코드를 단계별로 실행하고 변수 값을 확인하거나 로그를 출력해 오류의 원인을 찾아냅니다.
예를 들어, 데스크톱 애플리케이션을 개발할 때는 Visual Studio나 Eclipse와 같은 IDE에서 브레이크포인트를 설정하고 코드를 한 줄씩 실행하며 변수와 메모리 상태를 확인할 수 있습니다. 이러한 과정은 주로 소프트웨어 레벨에서 이루어지며, 소스 코드가 제대로 작동하는지 점검하는 데 집중됩니다.
하지만 IoT 및 Embedded 장치에서는 이런 방식의 소프트웨어 디버깅만으로는 한계가 있습니다. IoT 및 Embedded 장치는 펌웨어가 직접 하드웨어를 제어하고, 장치의 동작이 소프트웨어와 하드웨어의 결합에 의해 결정되기 때문입니다.
센서 데이터가 제대로 입력되지 않거나 특정 GPIO 핀 설정이 잘못되었거나 메모리 액세스가 비정상적으로 작동할 경우, 소프트웨어 디버깅 도구만으로는 문제를 파악하기 어렵습니다. 이러한 이유로 Debug Interface는 IoT 및 Embedded 장치 개발에서 필수적인 도구로 자리 잡고 있습니다. IoT 및 Embedded 개발자는 Debug Interface를 통해 내부 상태(메모리, 레지스터, 클록 설정 등)를 실시간으로 확인하고, 하드웨어와 소프트웨어 간의 문제를 함께 분석할 수 있습니다.
일반 소프트웨어 디버깅과 IoT 및 Embedded 디버깅의 차이점

일반 소프트웨어 디버깅과 IoT 및 Embedded 디버깅의 차이점
IoT와 Embedded 디바이스는 물리적 환경과 밀접하게 상호작용합니다. 이 때문에 아래와 같은 복잡한 문제를 해결하기 위해 Debug Interface가 필요합니다:
펌웨어 디버깅
MCU에서 실행 중인 펌웨어의 코드 흐름, 변수 값, 하드웨어 제어 상태 확인센서 데이터를 처리하는 함수의 정상 동작 확인
하드웨어 통합 문제 해결
외부 하드웨어(센서, 액추에이터, 통신 모듈)와의 상호작용에서 발생하는 오류 분석장치 상태 분석 및 복구
디바이스가 부팅되지 않거나 작동하지 않을 때 내부 상태 확인 및 복구펌웨어가 손상되었거나 초기화 루틴에서 문제가 발생한 경우 포함
보안 취약점 분석
디버깅 도구를 사용해 장치의 메모리 덤프, 펌웨어 추출 등을 통해 취약점 연구SWD를 통해 플래시 메모리에서 암호화 키를 찾거나, 부트로더의 인증 우회 방법 확인
Debug Interface는 단순한 디버깅 도구가 아닌, IoT 및 Embedded 장비의 동작을 이해하고 문제를 해결하며 보안을 연구하는 데 있어 핵심적인 역할을 합니다.
이번 글에서는 SWD와 J-Link를 활용해 ARM 기반 디바이스에 접근하고 이를 활용하는 방법을 소개하겠습니다.
☑️ IoT 및 Embedded Debug Interface - JTAG, SWD
JTAG(Joint Test Action Group)
JTAG은 앞서 작성된 테크 블로그 "IoT 해킹을 위한 하드웨어 분석 프로세스 - 2"에서 소개된 바와 같이 Debug Interface입니다.
하드웨어나 펌웨어는 설계 및 개발 단계에서 오류나 버그가 발생하기 쉽습니다. 이를 해결하기 위해 장치 내부 상태를 확인할 수 있는 방법이 필요하며, 이때 Debug Interface를 활용하여 확인하게 됩니다.
Debug Interface는 저수준 하드웨어 접근을 가능하게 하여 내부 메모리 상태, 레지스터 값, 코드 실행 흐름 등을 확인할 수 있는 기능을 제공합니다. 이는 제품 제조 단계에서 제품의 정상 동작을 확인하고 버그를 수정하는 데 사용됩니다. 하지만 제품 출시 단계에서 이러한 Debug Interface가 제거되지 않으면 IoT 및 Embedded 취약점을 연구하는 입장에서 유용한 정보를 얻을 수 있는 귀중한 자원이 됩니다.
JTAG은 Joint Test Action Group의 약자로, 일반적으로 표준 20핀을 사용하지만, 현대의 JTAG은 아래 그림 1과 같이 10핀, 14핀 등 다양한 형태로 존재합니다.

<그림 1>
JTAG에는 여러 핀 맵이 존재하지만, 주요 핀은 다음과 같습니다.
TDI (Test Data In)
테스트 장치로 데이터를 입력하는 핀으로, 테스트 명령어 또는 데이터 전송
TDO (Test Data Out)
테스트 장치에서 데이터를 출력하는 핀으로, 테스트 결과 및 데이터 출력
TCK (Test Clock)
JTAG 작업을 위한 데이터 전송을 동기화하는 클록 신호 제공
TMS (Test Mode Select)
JTAG 상태(명령어 레지스터와 데이터 레지스터 사이)를 전환하는 데 사용
TRST (Test Reset) - Optional
JTAG 상태 머신을 리셋하는 핀으로, 모든 장치가 해당 핀을 사용하지 않음 (옵션 사항)
GND (Ground)
접지 핀
VCC (Voltage of Common Collector)
대상 장치의 전압 레벨을 감지하여 호환성을 확인하는 데 사용
주요 핀 구성
입출력 (TDI, TDO)
타이밍 제어 (TCK)
접지 및 전원(GND, VCC)
SWD
SWD(Serial Wire Debug)는 ARM에서 개발한 Debug Interface로, JTAG의 대안으로 사용됩니다. 최소 2개의 핀만으로 통신이 가능하다는 장점이 있습니다.
SWD는 간단한 구성과 효율성 덕분에 ARM 기반 시스템에서 널리 사용되며, 특히 공간이 제한된 Embedded 시스템에서 유용합니다. SWD는 ARM 디바이스에 한정된다는 단점이 있지만, JTAG에 비해 간편한 방식으로 사용할 수 있어 ARM 디바이스가 분석 대상이라면 SWD를 통한 Debug Interface 접근 또한 좋은 방법입니다.
SWD의 PIN MAP은 그림 2와 같이 구성되어 있습니다.

<그림 2>
핀 구성
Vref 또는 VTref (Voltage Reference)
SWD 라인의 전압 설정 담당 (일부 J-Link와 같은 JTAG 어댑터는 Vref 전압 필요)
SWDIO (Serial Wire Data Input/Output)
단일 양방향 데이터 핀
SWCLK (Serial Wire Clock)
클록 신호 제공
GND (Ground)
접지 핀
SWO (Serial Wire Output) - Optional
실시간 추적 데이터를 내보내는 SWD와 함께 사용
RESET - Optional
타겟 CPU 리셋 신호 핀
주요 핀 구성
SWCLK (Serial Wire Clock)
클록 신호를 전송하는 핀으로, 디버깅 장치와 MCU 간의 동기화 역할
SWDIO (Serial Wire Data I/O)
양방향 데이터 전송을 담당하는 핀으로, 디버깅 명령, 데이터 및 응답 전송
J-link
J-Link는 SEGGER에서 개발한 Debug Probe로, Embedded 시스템 개발에서 디버깅 및 플래시 프로그래밍에 널리 사용됩니다. 주요 특징은 다음과 같습니다.

<그림 3>
지원 인터페이스
JTAG
SWD
cJTAG
FINE
SPD
ICSP
지원 프로세서
J-Link는 8051부터 ARM Cortex-M, Cortex-A 시리즈 등 다양한 CPU 및 MCU를 지원합니다.
연결 방식
J-Link는 20핀 JTAG 커넥터를 사용하며, ARM의 Multi-ICE와 호환됩니다. SWD의 경우 JTAG의 5핀 대신 SWDCLK와 SWDIO 두 개의 핀만 사용합니다.
소프트웨어
J-Link 소프트웨어를 설치하여 사용할 수 있습니다.
SWD 핀 매칭
J-Link의 SWD는 앞서 설명한 SWD의 모든 핀을 사용할 수 있습니다. (SWDIO, SWCLK, Vref, GND, SWO(Optional), RESET(Optional))
☑️ J-Link SWD를 사용한 Main Flash Dump
이번 섹션에서는 J-Link와 SWD를 활용한 Main Flash Dump 과정을 소개하겠습니다.
흐름은 다음과 같습니다:
PCB 기판에서 SWD 식별
J-Link를 통한 하드웨어 간 연결 ( PC - 디바이스 )
디버깅 환경 설정
하드웨어 연결
Datasheet
하드웨어를 연결하기 전에, 먼저 타겟 칩셋을 식별하고 Datasheet를 확인해야 합니다.
Datasheet에서는 칩셋의 기술 사양, Pinout, Pin definition 등 하드웨어 연결에 필요한 정보가 상세히 나와 있으므로 반드시 확인해야 합니다.
이번 글에서 확인할 칩은 GigaDevice사의 GD32F307xx 칩입니다. 해당 칩은 100개의 pinouts으로 구성되어 있습니다.

<그림 4>
그림 4와 5에서 그림 3의 Pin definitions를 확인할 수 있으며, JTAG과 SWD 모두 활용할 수 있음을 확인했습니다.

<그림 5>

<그림 6>
그림 6과 같이 데이터 시트에서 Main Flash 주소 또한 확인할 수 있습니다.

<그림 7>
이제 SWD Interface를 확인합니다. 해당 보드에는 SWD가 식별하기 좋게 표시되어 있습니다.

<그림 8>

<그림 9>
그림 9과 같이 SWD, CLK, GND, 3V3(3.3V, VTref)을 식별할 수 있습니다.

<그림 10, 11>
이제 그림 10의 J-Link Pinout Map과 보드의 SWD, CLK, GND, 3V3를 하단의 그림 12와 같이 매핑합니다.

<그림 12>
이제 본격적으로 J-Link의 SWD를 활용할 수 있습니다.
J-Link 소프트웨어 설치 및 사용 - for Windows
SEGGER 공식 홈페이지에서 J-Flash를 설치합니다.
🔗 링크 : SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace

Create New Project를 선택한 후 Start J-Flash를 클릭합니다.

Target Interface를 SWD로 설정하고, Speed를 1000kHz(대상 장비에 따라 상이)로 설정합니다.

대상 디바이스를 확인한 칩셋으로 설정합니다.
J-Link 소프트웨어 설치 및 사용 - for Linux
Linux에서도 동일하게 J-Flash를 다운로드하여 다음과 같은 방법으로 J-Link를 연결합니다.
GUI 버전도 있지만, 이번 글에서는 CLI 환경으로 설명하겠습니다.
Command : JLinkExe -device GD32F307VC -if SWD -speed 1000 (Option으로 한 번에 실행)

명령어 순서
JLinkExe 실행
Connect
Default Device (칩셋 명 입력) : GD32F307VC
SWD: S
Speed : 1000
위와 같은 순서로 입력을 마치면 연결이 완료되며, 해당 장비의 정보가 출력됩니다.
이제 다양한 J-Link Command를 사용할 수 있습니다.
J-Link Command에 대한 자세한 내용은 다음 링크에서 확인할 수 있습니다: https://wiki.segger.com/J-Link_Commander

<J-link Command Table>
Main Flash Dump
Main Flash에는 펌웨어, 부트로더, 메모리 구조 및 다양한 데이터가 포함되어 있습니다.
대상 장비를 분석하기 위해 Main Flash를 Dump하도록 하겠습니다.
저희는 이 중 savebin 명령어를 사용해 Flash를 Dump합니다.
savebin은 대상 메모리 범위를 바이너리 파일로 저장하는 명령어입니다.
savebin Syntax : savebin <저장할 파일 경로> <읽기 시작할 영역> <오프셋>
Main Flash의 주소는 앞서 그림 6에서 확인한 바와 같이 0x08000000 ~ 0x080FFFFF이므로, 다음과 같이 명령어를 구성합니다.
명령어 : savebin C:\ftp\firmware.bin 0x800000 0x100000

다음과 같이 Main Flash가 Dump된 모습을 확인할 수 있습니다.

☑️ 마치며
IoT 및 Embedded 장치에서 Debug Interface는 단순한 개발 도구 이상의 역할을 합니다. UART, JTAG, 그리고 SWD와 같은 디버깅 인터페이스는 하드웨어와 소프트웨어의 연결 고리를 파악하고, 디바이스의 동작을 세밀하게 분석하며, 문제를 효율적으로 해결할 수 있도록 지원합니다. 특히, SWD는 ARM 기반 시스템의 디버깅 표준으로 자리 잡으며 간소화된 구성과 강력한 기능으로 개발자들에게 중요한 도구가 되고 있습니다.
하지만 이러한 인터페이스는 디버깅 도구인 동시에 보안 취약점의 잠재적 접근 경로가 될 수 있습니다. 제품 출시 전 Debug Interface를 적절히 비활성화하거나 보안 설정을 강화하는 것이 필수적이며, 이를 간과하면 디바이스가 위협에 쉽게 노출될 수 있습니다.
이번 글을 통해 SWD와 같은 Debug Interface의 동작 원리와 활용 방법을 이해하고, 이를 IoT 디바이스의 분석 및 개발에 효과적으로 적용할 수 있길 바랍니다.
앞으로도 다양한 디버깅 기법과 분석 도구를 활용해 IoT 및 Embedded 시스템에 대한 이해를 넓혀가시길 기대합니다. 추후 J-Link GDB-server를 통한 디버깅 포스팅으로 돌아오겠습니다.
<출처>