LLDB

Judy·2022년 5월 23일
0

iOS

목록 보기
10/28

Low Level Debuger

Command-Line Debug 환경

  • 실행중인 프로세스의 값을 변경하거나 흐름을 제어
  • 다양한 디버깅 작업 가능


LLVM

Apple이 진행한 컴파일러에 필요한 Toolchain 개발 프로젝트

  • 컴포넌트 재사용을 중시
  • 모듈화가 잘 되어있음

이렇게 잘 모듈화 되어있는 컴포넌트들을 이용해 진행된 주요 서브츠로젝트들

  • LLVM Core
  • Clang
  • libc++
  • LLDB


LLDB

LLVM의 디버거 컴포넌트를 개발하는 서브 프로젝트

  • Low-Level 컨트롤이 가능한 모듈로 이루어짐
  • 기계어에 가까운 영역까지 디버깅 가능
  • 실제 프로그램이 어떤 식으로 동작하는지 이해할 수 있음
  • C, C++, Objective-C, Swift 지원 (Xcode의 기본 디버거로 내장)


LLDB 시작 방법

시작

실행중인 프로젝트의 프로세스가 Breakpoint에서 멈추거나, pause 버튼으로 일시정지되면 디버그 콘솔에 LLDB 콘솔이 나타남

( 터미널에서 lldb -n Finder로도 사용 가능 - cstrutil status를 통해 System Integrity Protection을 disable한 후에)

기초 문법

(lldb) command [subcommand] -option "this is argument"

  • Command, Subcommand : LLDB 내 Object 이름 (breakpoint, set, list..)
  • Option : -으로 시작
  • Argument : ""으로 묶어줄 수 있음

<예시>

  • (lldb) breakpoint set --file test.c --line 12
    : breakpoint(Command)와 set(Subcommand)를 이용해
    (Option) --file -> test.c 파일 내
    (Option) --line -> 12번째 라인에
    set을 해준다.


Help

사용 가능한 Subcommand, Option 리스트나 사용법을 보여줌

<예시>

  • (lldb) belp : LLDB에서 가능한 Command
  • (lldb) help breakpoint : breakpoint의 Subcommand나 Option


Apropos

원하는 명령어를 키워드로 검색

<예시>

  • (lldb) apropos "reference count" : reference count와 관련된 명령어가 있나?
    -> The following commands may relate to 'reference count':
    refcount -- Inspect the reference count data for a Swift object


Breakpoint

프로그램에서 문제가 되는 지점에서 문제가 되는 지접을 찾아 멈추거나 여러 조건을 바꾸며 테스트하기 위한 지점

  • (lldb) breakpoint set [option] "argument"
    = br s [option] "argument
    (대부분의 명령어는 앞 글자 한 두개로 축약해서 사용가능)


1. 함수의 이름으로 지정

  • (lldb) breakpoint set --name viewDidLoad (= b -n viewDidLoad)
    : viewDidLoad인 함수에 breakpoint 지정

2. 정규표현식 활용

  • (lldb) breakpoint set --func-regex '^hello (= rb '^hello)

3. File의 이름과 라인 번호로 지정

  • (lldb) br s --file ViewController.swift --line 20
    : ViewController 파일의 20번 째 줄에 breakpoint 지정
    = br s -f ViewContoller.swift -l 20

4. breakpoint에 원하는 조건 걸기

  • --condition(-c) 뒤에 조건을 걸어 true인 경우만 breakpoint에서 멈춤
  • (lldb) breakpoint set --name "viewWillAppear" --condition animated
    = br s -n "viewWillAppear" -c animated

5. break 시 원하는 명령어 실행시키기

  • --command(-C)를 이용
  • (lldb) breakpoint set -n "viewDidLoad" --command "po $arg1" -G1
    = ( br s -n "viewDidLoad" -C "po $arg1" G!
    ( -auto-continue(-G)는 break에 걸려있지 않고 프로그램을 자동 진행)

6. breakPoint 리스트 확인

  • (lldb) breakpoint list
  • breakPoint의 id, 이름, hir-count 정보, enable 정보, source 상 위치, 주소값 등등
    (hit count = breakpoint 지점이 실행되면 disable 상태가 아니면 하나씩 늘림)

7. breakpoint 삭제나 비활성화

  • (lldb) breakpoint delete (= br de) : breakpoint 전체 삭제
  • (lldb) breakpoint disable (= br di) : 전체 비활성화


Stepping

프로세스를 단계별로 진행하는 기능


1. Stepping Over

  • (lldb) next 커맨드 (= n) : 현재 브레이크 지접에서 다름 문장으로 이동

2. Stepping In

  • (lldb) step 커맨드 (= s) : 다음 문장이 함수 호출인 경우 해당 함수의 시작 지점으로 이동

3. Stepping Out

  • (lldb) finish 커맨드 : 현재 함수가 return 될 때까지 진행 후 Brake를 걸어줌
  • run - 현재 프로그램을 중단하고 새로운 Build/Run 실행
  • continue - 다음 Breakpoint가지 실행)


Expression

멈춰있는 동안 새로운 동작 실행

  • (lldb) expression

1. po

객체에 대한 다양한 정보를 콘솔에 출력

  • (lldb) po = (lldb) expression -O -- -> 실무에서 가장 많이 사용되는 Command
    (-O는 object의 description을 출력하는 옵션)
  • NSObject의 debugDescription을 출력
override var debugDescription: String {
	return "이 객체의 debugDescription은 \(super.debugDescription) 입니다."
}
// (lldb) po slef -> 이 객체의 debugDescription은 <UpDownGame.MainViewController: 0x13be07bd0> 입니다.
  • debugDescription을 오버라이드해서 사용 가능

2. 값 출력 및 변경하기

  • LLDB는 내부적으로 값 출력마다 local variable을 $R- 형태로 만드로 저장
  • 해당 break를 벗어나도 사용 가능(수정해서 사용도 가능)

<예시>

  • (lldb) expression self.view = (e self.view) : 현재 뷰의 정보 출력
    -> $R(숫자)라는 변수로 self.view가 저장
    -> (lldb) e $R(숫자).backgroundColor = UIColor.Blue로 배경색 변경 가능
    -> (lldb) continue 이어서 실행(배경색이 변경됨)

3. 변수를 선언해서 사용

사용하고자 하는 변수명 앞에 $를 붙임

<예시>

  • (llbd) expr let $someNumber = 10

  • (llbd) expr var $someString = "some string"

  • (llbd) expression 입력 후 엔터를 누르면 여러 줄 명령을 입력할 수 있음 (다시 엔터 키로 완료)

4. break 옵션

  • --ignore-breakpoints : expression 실행 중 만나는 breakpoint를 무시할지 선택(기본은 true)
  • (lldb) expression --ignore-breakpoints true -- =(ex -i 1 --) : 그냥 진행
  • (lldb) expression --ignore-breakpoints false -- =(ex -i 0 --) : 멈춤

5. 주소값으로 변수 사용

  • unsafeBitCast(to:) 함수 이용

<예시> 버튼의 레이블 주소를 알 때

  • expr -l swift -- var $myLable = unsafeBitCast(to: 레이블 주소)
    -> unsafeBitCast 함수를 이용해 주소값의 UILable을 $myLable에 할당
    (UILable을 사용하려면 UIKit를 import해줘야 함)


Image

Module에서 나타나는 Symbol에 대한 자세한 정보를 알아낼 수 있음

ex) 프레임퉈크에 대한 private한 정보들(private class, method 등)

  • Modeule : 프로세스의 로드되어 실행되는 코드 (프레임워크, 라이브러리, 플러그인 등)
  • Sumbol : 메서드, 변수, 클래스 등 사람의 눈으로 구별할 수 있는 소스 코드의 작은 단위의 Symbol
  • Symbol Table : 컴파일된 Binary를 메서드, 변수, 클래스 등으로 상호 Mapping하는 역할
  • Symbolicate : Binary가 Symbol로 변역되는 것


1. 정보 출력

  • (lldb) image list : 현재 프로세스에 Load된 모든 모듈의 정보를 출력
  • 현재 모듈의 UUID, 메모리 주소값, Disk 내에서 Binary가 존재하는 Path 정보 등

2. 세부적인 정보 출력

  • (lldb) image dump : 모듈의 세부적인 정보를 dumpling(기억장치의 내용을 기록)
    <예시>
  • (lldb) image dump symtab UIKitCore -s address
    : UIKitCore Library에 대한 구체적인 내용을 알고 싶을 때
  • Symbol Table에 모듈에 포함된 변수, 메서드, 메타데이터, 프로토콜 등 모든 Symbol이 들어있음

3. 필터링한 정보 출력

  • (lldb) image lookup : Module 정보를 필터링해서 출력

필터링 옵션

  • (lldb) image lookup -F "함수이름"
    -> -a "주소값"
    -> -f "파일이름"
    -> -f "파일이름" -l 15
    -> -rn "정규식 표현"

4. Crash Log 보기

  • (lldb) image lookup : Symbolicate 되지 않은 Crash Log 출력
  • Binary Image Name
  • Stack Address : Symbol의 스택 메모리 주소값
  • Load Address : Application이 Load된 주소값
  • Offset : Stack Address와 Load Address 사이의 오프셋
  • symbol address = slide + stack address - load address
    = slide + offset

문제가 생긴 지점을 찾았다면?
1. 터미널에 (lldb) target create "dSYM 경로" : lldb를 통해 dYSM 파일에 접근
2. (lldb) image lookup --address 크래시 주소 : 문제의 Symbol 위치 검색
3. 어디서 Crash가 발생했는지 확인


Alias

반복해서 사용할 명령어에 별명 붙이기

  • (lldb) alias 별명 "줄이고 싶은 Command"

<예시>

  • (lldb) expression -l objc -O -- : Swift에서 Objective-C expression을 출력하는 명령어
    -> (lldb) command alias pojc expression -l objc -O -- : pojc로 별명 지정
    -> (lldb) pojc "[Objective-C Expression] 형태로 사용 가능


오픈소스 LLDB Script

Derek Selander

Chisel

profile
iOS Developer

0개의 댓글