欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

对Link Map File的初步认识

程序员文章站 2022-10-16 14:12:55
Link Map File中文直译为链接映射文件,它是在Xcode生成可执行文件的同时生成的链接信息文件,用于描述可执行文件的构造部分,包括了代码段和数据段的分布情况。 ......

link map file中文直译为链接映射文件,它是在xcode生成可执行文件的同时生成的链接信息文件,用于描述可执行文件的构造部分,包括了代码段和数据段的分布情况。xcode在生成可执行文件的时候默认情况下不生成该文件,需要开发者手动设置target --> build setting --> write link map file为yes:
对Link Map File的初步认识
这里还可以设置link map存放的位置,默认的位置为:

$(target_temp_dir)/$(product_name)-linkmap-$(current_variant)-$(current_arch).txt

例如:

/users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/intermediates.noindex/linkmaptest.build/debug-iphonesimulator/linkmaptest.build/linkmaptest-linkmap-normal-x86_64.txt

开发者也可以根据自己的需要自行设置该文件的位置。

打开link map file,里面包含了以下几个部分:

1. path

# path: /users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/products/debug-iphonesimulator/linkmaptest.app/linkmaptest

path是生成可执行文件的路径。

2. arch

# arch: x86_64

arch指代架构类型。

3. object files:

# object files:
[ 0] linker synthesized
[ 1] /users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/intermediates.noindex/linkmaptest.build/debug-iphonesimulator/linkmaptest.build/linkmaptest.app-simulated.xcent
[ 2] /users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/intermediates.noindex/linkmaptest.build/debug-iphonesimulator/linkmaptest.build/objects-normal/x86_64/viewcontroller.o
[ 3] /users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/intermediates.noindex/linkmaptest.build/debug-iphonesimulator/linkmaptest.build/objects-normal/x86_64/main.o
[ 4] /users/zhanggui/library/developer/xcode/deriveddata/linkmaptest-ffnpzjkbsmhwvdcxorqbxpyvjtob/build/intermediates.noindex/linkmaptest.build/debug-iphonesimulator/linkmaptest.build/objects-normal/x86_64/appdelegate.o
[ 5] /applications/xcode.app/contents/developer/platforms/iphonesimulator.platform/developer/sdks/iphonesimulator12.1.sdk/system/library/frameworks//foundation.framework/foundation.tbd
[6]/applications/xcode.app/contents/developer/platforms/iphonesimulator.platform/developer/sdks/iphonesimulator12.1.sdk/usr/lib/libobjc.tbd
[7]/applications/xcode.app/contents/developer/platforms/iphonesimulator.platform/developer/sdks/iphonesimulator12.1.sdk/system/library/frameworks//uikit.framework/uikit.tbd

object files列举了可执行文件里所有的obj以及tbd。每一行代表对文件的编号。例如viewcontroller.o文件,其编号为2。编号的具体作用稍后介绍。

4. sections

# sections:
# address   size        segment section
0x100001730 0x00000333  __text  __text
0x100001a64 0x0000002a  __text  __stubs
0x100001a90 0x00000056  __text  __stub_helper
0x100001ae6 0x00000a27  __text  __objc_methname
0x10000250d 0x0000003c  __text  __objc_classname
0x100002549 0x0000086d  __text  __objc_methtype
0x100002db6 0x0000007a  __text  __cstring
0x100002e30 0x00000182  __text  __entitlements
0x100002fb4 0x00000048  __text  __unwind_info
0x100003000 0x00000010  __data  __nl_symbol_ptr
0x100003010 0x00000010  __data  __got
0x100003020 0x00000038  __data  __la_symbol_ptr
0x100003058 0x00000010  __data  __objc_classlist
0x100003068 0x00000010  __data  __objc_protolist
0x100003078 0x00000008  __data  __objc_imageinfo
0x100003080 0x00000be8  __data  __objc_const
0x100003c68 0x00000010  __data  __objc_selrefs
0x100003c78 0x00000008  __data  __objc_classrefs
0x100003c80 0x00000008  __data  __objc_superrefs
0x100003c88 0x00000008  __data  __objc_ivar
0x100003c90 0x000000a0  __data  __objc_data
0x100003d30 0x000000c0  __data  __data

单从字面含义理解:每个section包含了address、size、segment以及section。介绍之前,这里先简单介绍一下mach-o文件。
上面第一部分的path是可执行文件的路径,使用iterm进去到该文件夹,然后使用file命令即可查看该文件的类型:

file linkmaptest

输出结果为:

linkmaptest: mach-o 64-bit executable x86_64

可以知道该文件是一个mach-o格式的文件,它是ios系统应用执行文件格式。mach-o文件中的虚拟地址最终会被映射到物理地址上,这些地址会被分为不同的段类型:_ _ text 、_ _ data以及_ _ linkedit等。各个段的含义如下:

  1. _ _ text包含了被执行的代码。这些代码是只读、可执行
  2. _ _ data包含了包含了将会被更改的数据,例如全局变量、静态变量等,可读写,但是不可执行
  3. _ _ linkedit 包含了加载程序的元数据,比如函数名称和地址,只读。

segment又被划分成了不同的section,不同的section存储了不同的信息,例如 _ _ objc _ methname 为方法的名称。
再回顾上面的sections,address是起始位置、size是大小、segment是段、section。

5. symbols

# address   size        file  name
0x100001730 0x0000003c  [  2] -[viewcontroller viewdidload]
0x100001770 0x00000092  [  3] _main
0x100001810 0x00000080  [  4] -[appdelegate application:didfinishlaunchingwithoptions:]
0x100001890 0x00000040  [  4] -[appdelegate applicationwillresignactive:]
0x1000018d0 0x00000040  [  4] -[appdelegate applicationdidenterbackground:]
0x100001910 0x00000040  [  4] -[appdelegate applicationwillenterforeground:]
0x100001950 0x00000040  [  4] -[appdelegate applicationdidbecomeactive:]
0x100001990 0x00000040  [  4] -[appdelegate applicationwillterminate:]
0x1000019d0 0x00000020  [  4] -[appdelegate window]
0x1000019f0 0x00000040  [  4] -[appdelegate setwindow:]
0x100001a30 0x00000033  [  4] -[appdelegate .cxx_destruct]
0x100001a64 0x00000006  [  5] _nsstringfromclass
0x100001a6a 0x00000006  [  7] _uiapplicationmain
0x100001a70 0x00000006  [  6] _objc_autoreleasepoolpop
0x100001a76 0x00000006  [  6] _objc_autoreleasepoolpush
0x100001a7c 0x00000006  [  6] _objc_msgsendsuper2
0x100001a82 0x00000006  [  6] _objc_retainautoreleasedreturnvalue
0x100001a88 0x00000006  [  6] _objc_storestrong
0x100001a90 0x00000010  [  0] helper helper
0x100001aa0 0x0000000a  [  5] _nsstringfromclass
0x100001aaa 0x0000000a  [  6] _objc_autoreleasepoolpop
0x100001ab4 0x0000000a  [  6] _objc_autoreleasepoolpush
0x100001abe 0x0000000a  [  6] _objc_msgsendsuper2
0x100001ac8 0x0000000a  [  6] _objc_retainautoreleasedreturnvalue
0x100001ad2 0x0000000a  [  6] _objc_storestrong
0x100001adc 0x0000000a  [  7] _uiapplicationmain
0x100001ae6 0x0000000c  [  2] literal string: viewdidload
. . .

根据sections的起始地址,可以将symbols分为sections个数的组,例如0x100001730到0x100001a64之间,就是 _ _ test代码区。
symbols包含的信息有:

  1. address:起始地址
  2. size:所占内存大小,这里使用16进制表示。
  3. file:该name所在的文件编号,也就是object files部分的中括号的数字,例如-[viewcontroller viewdidload]对应的文件编号为2,根据object files部分可以看到所属的文件为:viewcontroller.o。这样可以计算某个o文件所占内存的大小。只需要把symbols中编号为o编号symbols累加统计即可。
  4. name就是该sybmols的名称。

6. dead stripped symbols

# dead stripped symbols:
#           size        file  name
<<dead>>    0x00000018  [  2] cie
<<dead>>    0x00000018  [  3] cie
<<dead>>    0x00000006  [  4] literal string: class
<<dead>>    0x00000008  [  4] literal string: v16@0:8
<<dead>>    0x00000018  [  4] cie
. . .

上面便是对link map file做了简单的介绍。

zlinkmapparser

花了两天的时间,根据对link map file的学习,使用ruby写了一个脚本文件,可以方便地统计出指定link map file中的组件或者tbd占用内存大小,类似:

appdelegate.o          8.50kb
viewcontroller.o          735b
linkmapdemo.app-simulated.xcent          386b
main.o          192b
 linker synthesized          128b
libobjc.tbd          120b
foundation.tbd          24b
uikit.tbd          24b
总大小为(仅供参考):10.07kb

想了解更多可以访问zlinkmapparser

总结

  1. 苹果开发还是有很多细节的东西需要去学习去了解。
  2. 学习一门脚本语言,也会给平时的开发带来很大的方便。

参考

  1. mach-o可执行文件
  2. ios调优|深入理解link map file
  3. ios app可执行文件的组成

转载请注明出处: