LLDB (디버거)
1. 개요
LLDB는 C, Objective-C, C++, Swift로 작성된 프로그램의 디버깅을 지원하는 디버거이다. macOS, Linux, FreeBSD, NetBSD, Windows 운영체제에서 작동하며, i386, x86-64, ARM 아키텍처를 지원한다. Xcode, Android Studio, Visual Studio Code, C++Builder, Eclipse, CLion 등 다양한 IDE에서 사용 가능하다. LLDB는 백트레이싱, 중단점, 표현식 평가, 명령어 인터페이스 등 다양한 기능을 제공한다.
-
디버거 -
Valgrind
Valgrind는 동적 분석 도구들의 프레임워크로, 가상 머신 기반으로 작동하며 메모리 오류 감지, 멀티스레드 코드 분석 등 다양한 기능을 제공하지만, 정적 또는 스택 할당 데이터의 경계 오류는 모두 감지하지 못한다. -
디버거 -
Eclipse (소프트웨어)
이클립스는 IBM에서 개발한 자바 기반의 통합 개발 환경으로, OSGi 서비스 플랫폼을 런타임 아키텍처로 사용하며, 플러그인을 통해 기능을 확장할 수 있고, 이클립스 퍼블릭 라이선스를 따르며, 한국어를 지원한다. -
C++로 작성된 자유 소프트웨어 -
클램윈
클램윈은 ClamAV 엔진 기반의 오픈 소스 백신 소프트웨어로, 트로이 목마, 바이러스, 멀웨어 등 다양한 악성 위협 분석 자료를 제공하며 예약 검사, 수동 검사, 컨텍스트 메뉴 통합 등의 기능을 지원하지만 실시간 감시 기능은 제공하지 않는다. -
C++로 작성된 자유 소프트웨어 -
VirtualDub
VirtualDub은 윈도우 운영 체제에서 실행되는 무료 오픈 소스 비디오 캡처 및 처리 유틸리티이며, AVI 파일을 주로 처리하고 플러그인을 통해 다른 파일 형식도 지원하며, 동영상 캡처, 편집, 비디오 처리 및 필터 기능을 제공한다. -
공식 웹사이트에 알 수 없는 변수를 사용한 문서 -
브루클린 미술관
브루클린 미술관은 1823년 브루클린 견습생 도서관으로 시작하여 현재 약 50만 점의 소장품을 보유한 뉴욕 브루클린 소재의 미술관으로, 다양한 분야의 예술 작품을 전시하며 특히 아프리카 미술과 여성주의 미술에 대한 기여가 크다. -
공식 웹사이트에 알 수 없는 변수를 사용한 문서 -
광주지방기상청
광주지방기상청은 광주광역시와 전라남도 지역의 기상 예보, 특보, 관측, 기후 정보 제공 등의 업무를 수행하는 기상청 소속 기관으로, 1949년 광주측후소로 설치되어 1992년 광주지방기상청으로 개편되었으며, 기획운영과, 예보과, 관측과, 기후서비스과와 전주기상지청, 목포기상대를 두고 있다.
2. 현황
LLDB는 개발 초기 단계에 있지만, C, Objective-C, C++, Swift 언어로 작성된 프로그램의 기본적인 디버깅을 지원할 정도로 성숙해 있다.
LLDB는 macOS, Linux, FreeBSD, NetBSD, Windows에서 작동하는 것으로 알려져 있으며, i386, x86-64, ARM 명령 집합을 지원한다. Xcode 5 이후 버전부터는 기본 디버거로 사용되고 있다.
2.1. 지원 환경
LLDB는 OS X, 리눅스, FreeBSD, 윈도우에서 작동하며 i386, x86-64, ARM 명령어 집합을 지원한다. Xcode 4.3 이후 버전의 기본 디버거이다. 안드로이드 스튜디오 역시 디버깅에 LLDB를 사용한다.
2.2. 기능
LLDB는 초기 개발 단계이지만, C, 오브젝티브-C, C++, 스위프트로 작성된 프로그램의 기본적인 디버깅을 지원한다.
LLDB는 OS X, 리눅스, FreeBSD, 윈도우에서 동작하며 i386, x86-64, ARM 명령어 집합을 지원한다. Xcode 4.3 이상 버전의 기본 디버거이다. 스위프트 커뮤니티는 해당 언어를 지원하는 버전을 유지 관리하며, Free Pascal 및 Lazarus IDE는 자체 FpDebug 엔진의 백엔드로 LLDB를 사용할 수 있다.
LLDB 디버거는 macOS, 리눅스, FreeBSD, NetBSD 및 Windows에서 작동하며, i386, x86-64, 및 ARM 명령 집합을 지원한다. Xcode 5 및 이후 버전의 기본 디버거이며, 안드로이드 스튜디오 역시 디버깅에 LLDB를 사용한다. LLDB는 Visual Studio Code, C++Builder, 이클립스, 및 CLion을 포함한 다른 IDE에서도 사용할 수 있다.
3. 명령어 예시
| 명령어 | 설명 |
|---|---|
| `lldb 프로그램` | 셸에서 "프로그램" 디버그 |
| `run` | 로드된 프로그램 실행 |
| `break set -n main` | "main" 함수 시작 지점에 중단점 설정 |
| `bt` | 백트레이스 (프로그램이 충돌한 경우) |
| `register read` | 모든 레지스터 덤프 |
| `di -n main` | "main" 함수 디스어셈블 |
4. 디버깅 예시
다음은 C로 작성된, 잘못된 프로그램의 예시이다.
```c
#include
int main(void)
{
char msg = "Hello, world!\n";
printf("%s", msg);
return 0;
}
```
macOS에서 clang 컴파일러를 사용하면 위 코드를 `-g` 플래그를 사용하여 컴파일하여 생성된 바이너리에 적절한 디버그 정보(소스 코드 포함)를 포함시킬 수 있으며, 이를 통해 LLDB를 사용하여 더 쉽게 검사할 수 있다. 위 코드를 포함하는 파일의 이름이 `test.c`라고 가정하면, 컴파일에 사용되는 명령은 다음과 같다.
```console
$ clang -Wno-error=int-conversion -g test.c -o test
```
이제 바이너리를 실행할 수 있다.
```console
$ ./test
Segmentation fault
```
예제 코드가 실행될 때 세그멘테이션 오류를 생성하므로, LLDB를 사용하여 문제를 검사할 수 있다.
```console
$ lldb test
(lldb) target create "test"
Current executable set to 'test' (x86_64).
(lldb) run
Process 70716 launched: '/Users/wikipedia/test' (x86_64)
Process 70716 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xffffff90)
frame #0: 0x00007fff6c7c46f2 libsystem_platform.dylib`_platform_strlen + 18
libsystem_platform.dylib`_platform_strlen:
-> 0x7fff6c7c46f2 <+18>: pcmpeqb xmm0, xmmword ptr [rdi]
0x7fff6c7c46f6 <+22>: pmovmskb esi, xmm0
0x7fff6c7c46fa <+26>: and rcx, 0xf
0x7fff6c7c46fe <+30>: or rax, -0x1
Target 0: (test) stopped.
```
문제는 함수 `strlen`을 호출할 때 발생하지만, 백트레이스를 실행하여 문제의 원인이 되는 정확한 코드 줄을 식별할 수 있다.
```console
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xffffff90)
* frame #0: 0x00007fff6c7c46f2 libsystem_platform.dylib`_platform_strlen + 18
frame #1: 0x00007fff6c66b16a libsystem_c.dylib`__vfprintf + 8812
frame #2: 0x00007fff6c6911c3 libsystem_c.dylib`__v2printf + 475
frame #3: 0x00007fff6c668e22 libsystem_c.dylib`vfprintf_l + 54
frame #4: 0x00007fff6c666f72 libsystem_c.dylib`printf + 174
frame #5: 0x0000000100000f6d test`main at test.c:5:2
frame #6: 0x00007fff6c5dc3d5 libdyld.dylib`start + 1
(lldb) source list
3 int main(void) {
4 char msg = "Hello, world!\n";
5 printf("%s", msg);
6 return 0;
7 }
```
`frame #5`로 시작하는 줄에서 LLDB는 오류가 `test.c`의 5번째 줄에 있음을 나타낸다. `source list`를 실행하면 이것이 `printf` 호출을 참조한다는 것을 알 수 있다. 백트레이스의 예외 코드 `EXC_BAD_ACCESS`에 따르면, `strlen`은 유효하지 않은 포인터를 역참조하여 접근 권한이 없는 메모리 영역에서 읽으려고 한다. 소스 코드로 돌아가서, 변수 `msg`의 타입이 `char`이지만 문자 대신 문자열을 포함하고 있음을 알 수 있다. 이 문제를 해결하려면, `msg`가 `char`의 문자열에 대한 포인터임을 나타내기 위해 `*` 연산자를 추가하여 코드를 수정한다.
```c
#include
int main(void)
{
char* msg = "Hello, world!\n";
printf("%s", msg);
return 0;
}
```
다시 컴파일하고 실행 파일을 다시 실행하면 LLDB가 이제 올바른 결과를 제공한다.
```console
(lldb) target create "test"
Current executable set to 'test' (x86_64).
(lldb) run
Process 93319 launched: '/Users/wikipedia/test' (x86_64)
Hello, world!
Process 93319 exited with status = 0 (0x00000000)
(lldb)
```
LLDB는 프로그램을 실행하여 `printf`의 출력을 화면에 인쇄한다. 프로그램이 정상적으로 종료된 후, LLDB는 프로그램을 실행하는 프로세스가 완료되었음을 나타내고 종료 상태를 인쇄한다.