DYLD

822 阅读6分钟

dyld的调试与作用

如果想调试dyld源代码,需要准备带调试信息的dyld/libdyld.dylib/ libclosured.dylib,与系统做替换,⻛险较大。

lldb保留了 一个库列表,避免在按名称设置断点时出现问题,而dyld与 libdyld.dylib就在该列表上。

有两种方式在可以强制在dyld上设置断点:

br set -n dyldbootstrap::start -s dyld //在哪个二进制文件里设置断点
set set target.breakpoints-use-platform-avoid-list 0 //禁掉白名单

第二种方式无需查看代码、二进制文件,而是通过dyld提供的环境变量来控 制dyld在运行过程中输出有用信息。

DYLD_PRINT_APIS:打印dyld内部几乎所有发生的调用;
DYLD_PRINT_LIBRARIES:打印在应用程序启动期间正在加载的所有动态库;
DYLD_PRINT_WARNINGS:打印dyld运行过程中的辅助信息;
DYLD_*_PATH:显示dyld搜索动态库的目录顺序;
DYLD_PRINT_ENV:显示dyld初始化的环境变量;
DYLD_PRINT_SEGMENTS:打印当前程序的segment信息;
DYLD_PRINT_STATISTICS:打印pre-main time;
DYLD_PRINT_INITIALIZERS:显示都有initialiser。
lldb -file test
(lldb) target create "test"
Current executable set to '/Users/tangge/Downloads/第十节、MachO与lldb/上课代码/1-mach-o分析/test' (x86_64).

(lldb) b main//在main函数那里打断点

Breakpoint 1: where = test`main + 15 at test.m:10:12, address = 0x0000000100003f8f

(lldb) setting set target.env-vars DYLD_PRINT_APIS=YES
(lldb) r

Process 27452 launched: '/Users/tangge/Downloads/第十节、MachO与lldb/上课代码/1-mach-o分析/test' (x86_64)

_dyld_register_func_for_add_image(0x7fff20517506)
_dyld_register_for_bulk_image_loads(0x7fff20249cf3)
_NSGetExecutablePath(...)
_dyld_is_memory_immutable(0x7fff20293d3b, 36)
Process 27452 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003f8f test`main at test.m:10:12
Target 0: (test) stopped

image.png

插入动态库与插入函数

dyld到底做了什么?

dyld:动态链接程序(链接可执行文件) libdyld.dylib 使我们的程序在Runtime期间具有动态链接功能(即应用程序通过libdyld.dylib库调用dyld)

objdump --macho --private-headers test

test:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00     EXECUTE    16       1048   NOUNDEFS DYLDLINK TWOLEVEL PIE

Load command 0
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __PAGEZERO
   vmaddr 0x0000000000000000
   vmsize 0x0000000100000000
  fileoff 0
 filesize 0
  maxprot ---
 initprot ---
   nsects 0
    flags (none)

Load command 1
      cmd LC_SEGMENT_64
  cmdsize 232
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000000004000
  fileoff 0
 filesize 16384
  maxprot r-x
 initprot r-x
   nsects 2
    flags (none)

Section
  sectname __text
   segname __TEXT
      addr 0x0000000100003f60
      size 0x0000000000000055
    offset 16224
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
 reserved1 0
 reserved2 0

Section
  sectname __unwind_info
   segname __TEXT
      addr 0x0000000100003fb8
      size 0x0000000000000048
    offset 16312
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 152
  segname __DATA_CONST
   vmaddr 0x0000000100004000
   vmsize 0x0000000000004000
  fileoff 16384
 filesize 16384
  maxprot rw-
 initprot rw-
   nsects 1
    flags 0x00000010 (unknown flags)

Section
  sectname __objc_imageinfo
   segname __DATA_CONST
      addr 0x0000000100004000
      size 0x0000000000000008
    offset 16384
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0

Load command 3
      cmd LC_SEGMENT_64
  cmdsize 152

  segname __DATA
   vmaddr 0x0000000100008000
   vmsize 0x0000000000004000
  fileoff 32768
 filesize 16384
  maxprot rw-
 initprot rw-
   nsects 1
    flags (none)

Section
  sectname __data
   segname __DATA
      addr 0x0000000100008000
      size 0x0000000000000004
    offset 32768
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0

Load command 4
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __LINKEDIT
   vmaddr 0x000000010000c000
   vmsize 0x0000000000004000
  fileoff 49152
 filesize 704
  maxprot r--
 initprot r--
   nsects 0
    flags (none)

Load command 5
            cmd LC_DYLD_INFO_ONLY
        cmdsize 48
     rebase_off 0
    rebase_size 0
       bind_off 0
      bind_size 0
  weak_bind_off 0
 weak_bind_size 0
  lazy_bind_off 0
 lazy_bind_size 0
     export_off 49152
    export_size 80

Load command 6
     cmd LC_SYMTAB
 cmdsize 24
  symoff 49240
   nsyms 23
  stroff 49608
 strsize 248

Load command 7
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 17
     iextdefsym 17
     nextdefsym 5
      iundefsym 22
      nundefsym 1
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 0
  nindirectsyms 0
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0
        
Load command 8
          cmd LC_LOAD_DYLINKER
      cmdsize 32
         name /usr/lib/dyld (offset 12)

Load command 9
     cmd LC_UUID
 cmdsize 24
    uuid BE09DDA7-40E7-33AD-89D6-BBD82D8AE113

Load command 10
       cmd LC_BUILD_VERSION
   cmdsize 32

  platform macos
       sdk 11.1
     minos 11.0
    ntools 1
      tool ld
   version 609.8

Load command 11
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0

Load command 12
       cmd LC_MAIN
   cmdsize 24
  entryoff 16256
 stacksize 0

Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 1292.60.1
compatibility version 1.0.0

Load command 14
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 49232
 datasize 8
 
Load command 15
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 49240
 datasize 0
  1. 执行自身初始化配置加载环境; ----> LC_DYLD_INFO_ONLY
  2. 加载当前程序链接的所有动态库到指定的内存中; ----> LC_LOAD_DYLIB
  3. 搜索所有的动态库,绑定需要在调用程序之前用的符号(非懒加载符号); ----> LC_DYSYMTAB
  4. 在indirect symbol table中将需要绑定的导入符号真实地址替换; ----> LC_DYSYMTAB
  5. 向程序提供在Runtime时使用dyld的接口函数(存在libdyld.dylib中,由LC_LOAD_DYLIB提供);
  6. 配置Runtime,执行所有动态库/image中使用的全局构造函数;
  7. dyld调用程序入口函数,开始执行程序。 ----> LC_MAIN

image.png

//给_dyld_start打断点
lldb -file test
(lldb) target create "test"
Current executable set to '/Users/tangge/Downloads/第十节、MachO与lldb/上课代码/1-mach-o分析/test' (x86_64).

(lldb) br set -r (.*)dyld_start$ -s dyld
Breakpoint 1: where = dyld`_dyld_start, address = 0x0000000000001000
(lldb) b main

Breakpoint 2: where = test`main + 15 at test.m:10:12, address = 0x0000000100003f8f

(lldb) r

Process 29402 launched: '/Users/tangge/Downloads/第十节、MachO与lldb/上课代码/1-mach-o分析/test' (x86_64)

Process 29402 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1

    frame #0: 0x0000000100003f8f test`main at test.m:10:12

Target 0: (test) stopped.

(lldb) bt

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1

  * frame #0: 0x0000000100003f8f test`main at test.m:10:12

    frame #1: 0x00007fff2052b621 libdyld.dylib`start + 1

(lldb)

image.png