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
插入动态库与插入函数
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
- 执行自身初始化配置加载环境; ----> LC_DYLD_INFO_ONLY
- 加载当前程序链接的所有动态库到指定的内存中; ----> LC_LOAD_DYLIB
- 搜索所有的动态库,绑定需要在调用程序之前用的符号(非懒加载符号); ----> LC_DYSYMTAB
- 在indirect symbol table中将需要绑定的导入符号真实地址替换; ----> LC_DYSYMTAB
- 向程序提供在Runtime时使用dyld的接口函数(存在libdyld.dylib中,由LC_LOAD_DYLIB提供);
- 配置Runtime,执行所有动态库/image中使用的全局构造函数;
- dyld调用程序入口函数,开始执行程序。 ----> LC_MAIN
//给_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)