読者です 読者をやめる 読者になる 読者になる

OpenSource版swiftでLLDB Debuggerを使ってみました

概要

ここを参考にして、OpenSource版swiftでLLDB Debuggerを使ってみました。GDB風のソースデバッグが可能です。

OSは、Ubuntu14.04です。

$ swift -version
Swift version 2.2-dev (LLVM 46be9ff861, Clang 4deb154edc, Swift 778f82939c)
Target: x86_64-unknown-linux-gnu

デバッグ手順

ソース作成

階乗計算処理を実行するswiftソースを作成します。

$ cat Factorial.swift 
func factorial(n: Int) -> Int {
    if n <= 1 { return n }
    return n * factorial(n - 1)
}
let number = 4
print("\(number)! is equal to \(factorial(number))")

ビルド

デバッグ情報付きでビルドします。

$ swiftc -g Factorial.swift
$ ls -l
合計 32
-rwxrwxr-x 1 unokun unokun 24952 12月 20 16:58 Factorial
-rw-rw-r-- 1 unokun unokun   161 12月 20 16:57 Factorial.swift

デバッグ

ビルドしたモジュールをデバッグします。

$ lldb Factorial
(lldb) target create "Factorial"
Current executable set to 'Factorial' (x86_64).

ソースコードの2行目にブレイクポイントを設定します。

(lldb) b 2
Breakpoint 1: where = Factorial`Factorial.factorial (Swift.Int) -> Swift.Int + 12 at Factorial.swift:2, address = 0x0000000000400f1c

プログラムを実行します。

ブレークポイントにヒットすると、止まっている場所がソースコードと一緒に表示されます。

(lldb) r
Process 3497 launched: '/home/unokun/work/factorial/Factorial' (x86_64)
Process 3497 stopped
* thread #1: tid = 3497, 0x0000000000400f1c Factorial`factorial(n=4) -> Int + 12 at Factorial.swift:2, name = 'Factorial', stop reason = breakpoint 1.1
    frame #0: 0x0000000000400f1c Factorial`factorial(n=4) -> Int + 12 at Factorial.swift:2
   1   	func factorial(n: Int) -> Int {
-> 2   	    if n <= 1 { return n }
   3   	    return n * factorial(n - 1)
   4   	}
   5   	let number = 4
   6   	print("\(number)! is equal to \(factorial(number))")

変数の値を出力します。

(lldb) p n
(Int) $R0 = 4

バックトレースを出力します。

(lldb) bt
* thread #1: tid = 3497, 0x0000000000400f1c Factorial`factorial(n=4) -> Int + 12 at Factorial.swift:2, name = 'Factorial', stop reason = breakpoint 1.1
  * frame #0: 0x0000000000400f1c Factorial`factorial(n=4) -> Int + 12 at Factorial.swift:2
    frame #1: 0x0000000000400e53 Factorial`main + 291 at Factorial.swift:6
    frame #2: 0x00007ffff6be7ec5 libc.so.6`__libc_start_main(main=(Factorial`main at Factorial.swift), argc=1, argv=0x00007fffffffe308, init=, fini=, rtld_fini=, stack_end=0x00007fffffffe2f8) + 245 at libc-start.c:287
    frame #3: 0x0000000000400c69 Factorial

lldbのコマンド一覧

helpと入力するとコマンド一覧が表示されます。

(lldb) help
Debugger commands:

  apropos           -- Find a list of debugger commands related to a particular
                       word/subject.
  breakpoint        -- A set of commands for operating on breakpoints. Also see
                       _regexp-break.
  bugreport         -- Set of commands for creating domain specific bugreports.
  command           -- A set of commands for managing or customizing the
                       debugger commands.
  disassemble       -- Disassemble bytes in the current function, or elsewhere
                       in the executable program as specified by the user.
  expression        -- Evaluate an expression (ObjC++ or Swift) in the current
                       program context, using user defined variables and
                       variables currently in scope.
  frame             -- A set of commands for operating on the current thread's
                       frames.
  gdb-remote        -- Connect to a remote GDB server.  If no hostname is
                       provided, localhost is assumed.
  gui               -- Switch into the curses based GUI mode.
  help              -- Show a list of all debugger commands, or give details
                       about specific commands.
  kdp-remote        -- Connect to a remote KDP server.  udp port 41139 is the
                       default port number.
  language          -- A set of commands for managing language-specific
                       functionality.'.
  log               -- A set of commands for operating on logs.
  memory            -- A set of commands for operating on memory.
  platform          -- A set of commands to manage and create platforms.
  plugin            -- A set of commands for managing or customizing plugin
                       commands.
  process           -- A set of commands for operating on a process.
  quit              -- Quit out of the LLDB debugger.
  register          -- A set of commands to access thread registers.
  script            -- Pass an expression to the script interpreter for
                       evaluation and return the results. Drop into the
                       interactive interpreter if no expression is given.
  settings          -- A set of commands for manipulating internal settable
                       debugger variables.
  source            -- A set of commands for accessing source file information
  target            -- A set of commands for operating on debugger targets.
  thread            -- A set of commands for operating on one or more threads
                       within a running process.
  type              -- A set of commands for operating on the type system
  version           -- Show version of LLDB debugger.
  watchpoint        -- A set of commands for operating on watchpoints.

Current command abbreviations (type 'help command alias' for more info):

  add-dsym  -- ('target symbols add')  Add a debug symbol file to one of the
               target's current modules by specifying a path to a debug symbols
               file, or using the options to specify a module to download
               symbols for.
  attach    -- ('_regexp-attach')  Attach to a process id if in decimal,
               otherwise treat the argument as a process name to attach to.
  b         -- ('_regexp-break')  Set a breakpoint using a regular expression
               to specify the location, where  is in decimal and
               
is in hex. bt -- ('_regexp-bt') Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed. c -- ('process continue') Continue execution of all threads in the current process. call -- ('expression --') Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and variables currently in scope. continue -- ('process continue') Continue execution of all threads in the current process. detach -- ('process detach') Detach from the current process being debugged. di -- ('disassemble') Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user. dis -- ('disassemble') Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user. display -- ('_regexp-display') Add an expression evaluation stop-hook. down -- ('_regexp-down') Go down "n" frames in the stack (1 frame by default). env -- ('_regexp-env') Implements a shortcut to viewing and setting environment variables. exit -- ('quit') Quit out of the LLDB debugger. f -- ('frame select') Select a frame by index from within the current thread and make it the current frame. file -- ('target create') Create a target using the argument as the main executable. finish -- ('thread step-out') Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified). image -- ('target modules') A set of commands for accessing information for one or more target modules. j -- ('_regexp-jump') Sets the program counter to a new address. jump -- ('_regexp-jump') Sets the program counter to a new address. kill -- ('process kill') Terminate the current process being debugged. l -- ('_regexp-list') Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands. list -- ('_regexp-list') Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands. n -- ('thread step-over') Source level single step in specified thread (current thread, if none specified), stepping over calls. next -- ('thread step-over') Source level single step in specified thread (current thread, if none specified), stepping over calls. nexti -- ('thread step-inst-over') Single step one instruction in specified thread (current thread, if none specified), stepping over calls. ni -- ('thread step-inst-over') Single step one instruction in specified thread (current thread, if none specified), stepping over calls. p -- ('expression --') Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and variables currently in scope. po -- ('expression -O -- ') Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and variables currently in scope. print -- ('expression --') Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and variables currently in scope. q -- ('quit') Quit out of the LLDB debugger. r -- ('process launch -X true --') Launch the executable in the debugger. rbreak -- ('breakpoint set -r %1') Sets a breakpoint or set of breakpoints in the executable. repl -- ('expression -r -- ') Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and variables currently in scope. run -- ('process launch -X true --') Launch the executable in the debugger. s -- ('thread step-in') Source level single step in specified thread (current thread, if none specified). si -- ('thread step-inst') Single step one instruction in specified thread (current thread, if none specified). step -- ('thread step-in') Source level single step in specified thread (current thread, if none specified). stepi -- ('thread step-inst') Single step one instruction in specified thread (current thread, if none specified). t -- ('thread select') Select a thread as the currently active thread. tbreak -- ('_regexp-tbreak') Set a one shot breakpoint using a regular expression to specify the location, where is in decimal and
is in hex. undisplay -- ('_regexp-undisplay') Remove an expression evaluation stop-hook. up -- ('_regexp-up') Go up "n" frames in the stack (1 frame by default). x -- ('memory read') Read from the memory of the process being debugged.

参考資料