개요
프로그램 비정상 종료(Segmentation Fault)나 코어 덤프 발생 시 메모리 주소만으로는 원인을 파악하기 어렵습니다. 이 글에서는 바이너리 메모리 주소를 소스 코드의 정확한 파일명과 라인 번호로 즉각 변환해 주는 addr2line 명령어의 핵심 사용법을 실습합니다. 디버깅 심볼(-g)을 포함한 빌드부터 함수명 디맨글링(-C), 인라인 함수 추적(-i)까지 실무 디버깅 과정을 단계별로 다룹니다.
1. addr2line 필수 패키지(binutils 및 gcc) 설치 및 버전 확인
addr2line 도구 사용과 실습 예제 컴파일에 필요한 binutils 및 gcc 패키지를 설치하기 위해 sudo apt-get update -qq && sudo apt-get install -y binutils gcc 명령어를 실행합니다.

addr2line -v 명령어를 실행하여 도구가 정상적으로 설치되었는지 확인하고 버전 정보를 확인합니다.addr2line은 프로그램 크래시나 세그폴트 발생 시 출력되는 메모리 주소를 소스 코드의 파일명과 라인 번호로 변환해 주는 명령어입니다.
⚙️ [주요 옵션]
-e : 분석할 바이너리 실행 파일의 경로를 지정합니다.-f : 코드 라인 번호와 함께 에러가 발생한 함수 이름을 출력합니다.-C : 맹글링된 심볼 이름을 사람이 읽기 쉬운 원래 형태로 디맹글링하여 표시합니다.-p : 파일명, 라인 번호, 함수명을 한 줄로 읽기 편하게 정리하여 출력합니다.-a : 변환 결과 앞에 입력된 메모리 주소를 함께 표시합니다.-i : 인라인 처리된 함수의 호출 위치까지 역추적하여 표시합니다.

2. 실습용 디버그 심볼(-g) 포함 샘플 프로그램 생성 및 컴파일
addr2line 실습을 진행할 전용 디렉터리를 생성하고 해당 위치로 이동하기 위해 mkdir -p ~/addr2line_lab && cd ~/addr2line_lab 명령어를 실행합니다.

크래시 발생 상황을 재현하고 디버깅을 테스트하기 위해 faulty_function 함수가 포함된 샘플 C 소스 코드 파일 test_crash.c를 생성합니다.

addr2line 분석에 필수적인 디버그 심볼 정보를 포함하고 컴파일러 최적화를 방지하기 위해 gcc -g -O0 test_crash.c -o test_crash 명령어로 바이너리를 빌드합니다.

빌드된 실행 파일의 심볼 테이블에서 faulty_function 함수의 시작 가상 메모리 주소를 확인하기 위해 nm test_crash | grep faulty_function 명령어를 실행합니다.
출력 결과를 통해 해당 함수가 0000000000001149 주소에 위치하고 있음을 확인할 수 있습니다.

3. 메모리 주소로 파일명과 코드 라인 번호 추적 (-e, -f 옵션)
faulty_function 함수의 메모리 주소를 변수에 저장하여 분석 시 편리하게 재사용하기 위해 FUNC_ADDR=$(nm test_crash | grep faulty_function | awk '{print $1}') 명령어를 실행합니다.

-e 옵션으로 바이너리 경로를 지정하고 함수의 메모리 주소를 전달하여 소스 코드 파일명과 라인 번호(test_crash.c:3)를 확인합니다.

-f 옵션을 추가하여 파일명 및 라인 번호와 함께 해당 주소의 함수 이름(faulty_function)을 함께 출력합니다.

4. C++ 심볼 디맨글링(-C) 및 인라인 함수 추적(-i, -p 옵션) 활용
C++ 소스 코드 컴파일과 심볼 분석 실습을 진행하기 위해 sudo apt-get install -y g++ 명령어로 C++ 컴파일러를 설치합니다.

인라인 함수 호출 구조를 재현하고 디버깅을 테스트하기 위해 샘플 C++ 소스 코드 파일 test_cpp.cpp를 생성합니다.

디버그 심볼 정보를 포함하고 컴파일러 최적화에 따른 인라인 함수 확장을 유도하기 위해 g++ -g -O2 test_cpp.cpp -o test_cpp 명령어로 바이너리를 빌드합니다.

실행 파일의 심볼 테이블에서 main 함수의 메모리 주소를 추출하여 분석에 활용할 수 있도록 MAIN_ADDR 환경 변수에 저장합니다.

-C 옵션으로 심볼을 디맨글링하고 -i 및 -p 옵션을 지정하여 인라인 함수 호출 위치를 가독성 높은 한 줄 형식으로 추적합니다.
출력된 ??:0 결과는 컴파일러 최적화나 위치 독립 실행 파일(PIE) 주소 매핑 특성 등으로 인해 지정한 메모리 주소의 소스 코드 라인을 직접 참조하지 못했음을 나타냅니다.

지금까지 리눅스 환경에서 세그폴트 발생 시 addr2line 명령어를 활용해 크래시가 난 코드 라인을 신속하게 추적하는 방법을 살펴보았습니다.
예기치 못한 에러 로그와 메모리 주소를 마주했을 때 당황하지 마시고, addr2line을 적극 활용해 디버깅 시간을 획기적으로 줄여보시기 바랍니다.