国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 課堂 > 電腦知識 > 正文

Mac OS X應用程序格式詳解

2024-05-08 15:53:29
字體:
來源:轉載
供稿:網友

  OS X 應用程序 格式講解

  OS X 如何執行應用程序

  譯者:51test2003 譯自http://0xfe.blogspot.com/2006/03 ... s-applications.html

  作為長期的 UNIX 用戶, 我通常有一些排除系統故障的工具. 最近, 我正在開發軟件并新增了Apple's OS X 系統支持; 但是和其他傳統UNIX 變種不同, OS X 不支持許多與加載,鏈接和執行程序相關的工具.

  例如, 當共享庫重定位出錯時, 我所做的首要事情就是對可執行文件運行ldd. ldd工具列出了可執行文件所依賴的共享庫(包括所在路徑)。但是在OS X , 試圖運行ldd將報錯.

  evil:~ mohit$ ldd /bin/ls

  -bash: ldd: command not found

  沒找到? 但在所有的UNIX上基本上都有的啊. 我想知道objdump是否可用.

  $ objdump -x /bin/ls

  -bash: objdump: command not found

  命令未找到. 怎么回事?

  問題在于與linux, Solaris, HP-UX, 和其他許多UNIX 變種不同, OS X 不使用 ELF二進制文件. 另外, OS X 不屬于GNU 項目的一部分。該項目包含想ldd和objdump這樣的工具.

  為了在OS X獲得可執行文件所依賴的共享庫列表,需要使用 otool 工具.

  evil:~ mohit$ otool /bin/ls

  otool: one of -fahlLtdoOrTMRIHScis must be specified

  Usage: otool [-fahlLDtdorSTMRIHvVcXm] object_file ...

  -f PRint the fat headers

  -a print the archive header

  -h print the mach header

  -l print the load commands

  -L print shared libraries used

  -D print shared library id name

  -t print the text section (disassemble with -v)

  -p start dissassemble from routine name

  -s print contents of section

  -d print the data section

  -o print the Objective-C segment

  -r print the relocation entries

  -S print the table of contents of a library

  -T print the table of contents of a dynamic shared library

  -M print the module table of a dynamic shared library

  -R print the reference table of a dynamic shared library

  -I print the indirect symbol table

  -H print the two-level hints table

  -v print verbosely (symbolicly) when possible

  -V print disassembled Operands symbolicly

  -c print argument strings of a core file

  -X print no leading addresses or headers

  -m don't use archive(member) syntax

  evil:~ mohit$ otool -L /bin/ls

  /bin/ls:

  /usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)

  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.0.0)

  好多了. 我們可以看見/bin/ls引用了兩個動態庫. 盡管, 文件擴展名我們根本不熟悉.

  我相信許多UNIX / Linux 用戶使用OS X系統時有類似的經歷,所以我決定寫一點目前我所知道的關于 OS X 可執行文件的知識.

  OS X 運行時架構運行時環境是OS X上代碼擴展的一個框架。它一組定義代碼如何被加載,被管理,被執行的集合組成。一旦應用程序運行, 合適的運行時環境就加載程序到內存, 解決外部庫的引用, 并為執行準備代碼.

  OS X 支持三種運行時環境:

  dyld 運行時環境:基于 dyld庫管理器的推薦環境.

  CFM 運行時環境: OS 9遺留環境. 實際用來設計需要使用 OS X新特色, 但還沒完全移植到dyld的應用程序.

  The Classic環境: OS 9 (9.1 or 9.2) 程序無需修改直接在OS X運行.

  本文主要關注于Dyld 運行時環境.

  Mach-O 可執行文件格式在 OS X, 幾乎所有的包含可執行代碼的文件,如:應用程序、框架、庫、內核擴展……, 都是以Mach-O文件實現. Mach-O 是一種文件格式,也是一種描述可執行文件如何被內核加載并運行的ABI (應用程序二進制接口). 專業一點講, 它告訴系統:

  使用哪個動態庫加載器

  加載哪個共享庫.

  如何組織進程地址空間.

  函數入口點地址,等.

  Mach-O 不是新事物. 最初由開放軟件基金會 (OSF) 用于設計基于 Mach 微內核OSF/1 操作系統. 后來移植到 x86 系統OpenStep.

  為了支持Dyld 運行時環境, 所有文件應該編譯成Mach-O 可執行文件格式.

  Mach-O 文件的組織

  Mach-O 文件分為三個區域: 頭部、載入命令區Section和原始段數據. 頭部和載入命令區描述文件功能、布局和其他特性;原始段數據包含由載入命令引用的字節序列。為了研究和檢查 Mach-O 文件的各部分, OS X 自帶了一個很有用的程序otool,其位于/usr/bin目錄下.

  接下來, 將使用 otool來了解 Mach-O 文件如何組織的.

  頭部查看文件的 Mach-O頭部, 使用otool 命令的 -h參數

  evil:~ mohit$ otool -h /bin/ls

  /bin/ls:

  Mach header

  magic cputype cpusubtype filetype ncmds sizeofcmds flags

  0xfeedface 18 0 2 11 1608 0x00000085

  頭部首先指定的是魔數(magic number). 魔數標明文件是32位還是64位的Mach-O 文件. 也標明 CPU字節順序. 魔數的解釋,參看/usr/include/mach-o/loader.h.

  頭部也指定文件的目標架構. 這樣就允許內核確保該代碼不會在不是為此處理器編寫的CPU上運行。例如, 在上面的輸出, cputype 設成18, 它代表CPU_TYPE_POWERPC, 在 /usr/include/mach/machine.h中定義.

  從上兩項信息,我們推斷出此二進制文件用于32-位基于PowerPC 的系統.

  有時二進制文件可能包含不止一個體系的代碼。通常稱為Universal Binaries, 通常以 fat_header這額外的頭部開始。檢查 fat_header內容, 使用otool命令的 -f開關參數.

  cpusubtype 屬性制定了CPU確切模型, 通常設成CPU_SUBTYPE_POWERPC_ALL 或 CPU_SUBTYPE_I386_ALL.

  filetype 指出文件如何對齊如何使用。實際上它告訴你文件是庫、靜態可執行文件、core file等。上面的 filetype等于MH_EXECUTE, 指出demand paged executable file. 下面是從/usr/include/mach-o/loader.h截取的片段,列出了不同的文件類型。

  #define MH_OBJECT 0x1 /* relocatable object file */

  #define MH_EXECUTE 0x2 /* demand paged executable file */

  #define MH_FVMLIB 0x3 /* fixed VM shared library file */

  #define MH_CORE 0x4 /* core file */

  #define MH_PRELOAD 0x5 /* preloaded executable file */

  #define MH_DYLIB 0x6 /* dynamically bound shared library */

  #define MH_DYLINKER 0x7 /* dynamic link editor */

  #define MH_BUNDLE 0x8 /* dynamically bound bundle file */

  #define MH_DYLIB_STUB 0x9 /* shared library stub for static */

  /* linking only, no section contents */

  接下來的兩個屬性涉及到載入命令區段, 指定了命令的數目和大小.

  最后, 獲得了狀態信息, 這些可能在裝載和執行時被內核使用。

  載入命令載入命令區段包含一個告知內核如何載入文件中的各個原始段的命令列表。典型的描述如何對齊,保護每個段及各段在內存中的布局.

  查看文件中的載入命令列表, 使用otool 命令的 -l開關參數.

  evil:~/Temp mohit$ otool -l /bin/ls

  /bin/ls:

  Load command 0

  cmd LC_SEGMENT

  cmdsize 56

  segname __PAGEZERO

  vmaddr 0x00000000

  vmsize 0x00001000

  fileoff 0

  filesize 0

  maxprot 0x00000000

  initprot 0x00000000

  nsects 0

  flags 0x4

  Load command 1

  cmd LC_SEGMENT

  cmdsize 600

  segname __TEXT

  vmaddr 0x00001000

  vmsize 0x00006000

  fileoff 0

  filesize 24576

  maxprot 0x00000007

  initprot 0x00000005

  nsects 8

  flags 0x0

  Section

  sectname __text

  segname __TEXT

  addr 0x00001ac4

  size 0x000046e8

  offset 2756

  align 2^2 (4)

  reloff 0

  nreloc 0

  flags 0x80000400

  reserved1 0

  reserved2 0

  [ ___SNIPPED FOR BREVITY___ ]

  Load command 4

  cmd LC_LOAD_DYLINKER

  cmdsize 28

  name /usr/lib/dyld (offset 12)

  Load command 5

  cmd LC_LOAD_DYLIB

  cmdsize 56

  name /usr/lib/libncurses.5.4.dylib (offset 24)

  time stamp 1111407638 Mon Mar 21 07:20:38 2005

  current version 5.4.0

  compatibility version 5.4.0

  Load command 6

  cmd LC_LOAD_DYLIB

  cmdsize 52

  name /usr/lib/libSystem.B.dylib (offset 24)

  time stamp 1111407267 Mon Mar 21 07:14:27 2005

  current version 88.0.0

  compatibility version 1.0.0

  Load command 7

  cmd LC_SYMTAB

  cmdsize 24

  symoff 28672

  nsyms 101

  stroff 31020

  strsize 1440

  Load command 8

  cmd LC_DYSYMTAB

  cmdsize 80

  ilocalsym 0

  nlocalsym 0

  iextdefsym 0

  nextdefsym 18

  iundefsym 18

  nundefsym 83

  tocoff 0

  ntoc 0

  modtaboff 0

  nmodtab 0

  extrefsymoff 0

  nextrefsyms 0

  indirectsymoff 30216

  nindirectsyms 201

  extreloff 0

  nextrel 0

  locreloff 0

  nlocrel 0

  Load command 9

  cmd LC_TWOLEVEL_HINTS

  cmdsize 16

  offset 29884

  nhints 83

  Load command 10

  cmd LC_UNIXTHREAD

  cmdsize 176 flavor PPC_THREAD_STATE

  count PPC_THREAD_STATE_COUNT

  r0 0x00000000 r1 0x00000000 r2 0x00000000 r3 0x00000000 r4 0x00000000

  r5 0x00000000 r6 0x00000000 r7 0x00000000 r8 0x00000000 r9 0x00000000

  r10 0x00000000 r11 0x00000000 r12 0x00000000 r13 0x00000000 r14 0x00000000

  r15 0x00000000 r16 0x00000000 r17 0x00000000 r18 0x00000000 r19 0x00000000

  r20 0x00000000 r21 0x00000000 r22 0x00000000 r23 0x00000000 r24 0x00000000

  r25 0x00000000 r26 0x00000000 r27 0x00000000 r28 0x00000000 r29 0x00000000

  r30 0x00000000 r31 0x00000000 cr 0x00000000 xer 0x00000000 lr 0x00000000

  ctr 0x00000000 mq 0x00000000 vrsave 0x00000000 srr0 0x00001ac4 srr1 0x00000000

  上面的文件在頭部下有11 加載命令直接定位, 從 0 到 10.

  前四個命令(LC_SEGMENT), 從 0 到 3, 定義了文件中的段如何映射到內存中去。段定義了Mach-O binary 二進制文件中的字節序列, 可以包含零個或更多的 sections. 稍候我們談談段。

  Load command 4 (LC_LOAD_DYLINKER) 指定使用哪個動態鏈接器. 幾乎總是設成OS X默認動態鏈接器 /usr/lib/dyld。

  Commands 5 and 6 (LC_LOAD_DYLIB) 指定文件需要鏈接的共享庫。它們由command 4規定的動態鏈接器載入。

  Commands 7 and 8 (LC_SYMTAB, LC_DYNSYMTAB) 指定由文件和動態鏈接器分別使用的符號表. Command 9 (LC_TWOLEVEL_HINTS) 包含兩級名稱空間的hint table。最后, command 10 (LC_UNIXTHREAD), 定義進程主線程的初始狀態. 該命令僅僅包含在可執行文件里。

  Segments and Sections

  上面涉及到的大多數加載命令都引用了文件中的段. 段是Mach-O文件直接被內核和動態鏈接器映射到虛擬內存中的一系列字符序列. 頭部和加載命令區域認為是文件的首段。一個典型的 OS X 可執行文件通常由下列五段::

  __PAGEZERO : 定位于虛擬地址0,無任何保護權利。此段在文件中不占用空間,訪問NULL導致立即崩潰.

  __TEXT : 包含只讀數據和可執行代碼.

  __DATA : 包含可寫數據. 這些 section通常由內核標志為copy-on-write .

  __OBJC : 包含Objective C 語言運行時環境使用的數據。

  __LINKEDIT :包含動態鏈接器用的原始數據.

  __TEXT和 __DATA段可能包含0或更多的section. 每個section由指定類型的數據, 如, 可執行代碼, 常量, C 字符串等組成.

  查看某section內容, 使用otool命令 -s選項.

  evil:~/Temp mohit$ otool -sv __TEXT __cstring /bin/ls

  /bin/ls:

  Contents of (__TEXT,__cstring) section

  00006320 00000000 5f5f6479 6c645f6d 6f645f74

  00006330 65726d5f 66756e63 73000000 5f5f6479

  00006340 6c645f6d 616b655f 64656c61 7965645f

  00006350 6d6f6475 6c655f69 6e697469 616c697a

  __SNIP__

  反匯編__text section, 使用 the -tv 開關參數.

  evil:~/Temp mohit$ otool -tv /bin/ls

  /bin/ls:

  (__TEXT,__text) section

  00001ac4 or r26,r1,r1

  00001ac8 addi r1,r1,0xfffc

  00001acc rlwinm r1,r1,0,0,26

  00001ad0 li r0,0x0

  00001ad4 stw r0,0x0(r1)

  00001ad8 stwu r1,0xffc0(r1)

  00001adc lwz r3,0x0(r26)

  00001ae0 addi r4,r26,0x4

  __SNIP__

  在 __TEXT段里, 存在四個主要的 section:

  __text : 編譯后的機器碼。

  __const : 通用常量數據.

  __cstring : 字面量字符串常量.

  __picsymbol_stub : 動態鏈接器使用的位置無關碼stub 路由.

  這樣保持了可執行的和不可執行的代碼在段里的明顯隔離.

  運行應用程序既然知道了Mach-O 文件的格式, 接下來看看OS X 如何載入并運行應用程序的。運行應用程序時, shell首先調用fork()系統調用. fork 創建調用進程(shell) 邏輯拷貝并準備好執行. 子進程然后調用execve()系統調用,當然需要提供要執行的程序路徑.

  內核載入指定的文件, 檢查其頭部驗證是否是合法的Mach-O 文件. 然后開始解釋載入命令,將子進程地址空間替換成文件中的各段。同時,內核也執行有二進制文件指定的動態鏈接器, 著手加載、鏈接所有依賴庫。在綁定了運行所必備的各個符號后,調用entry-point 函數.

  在build應用程序時entry-point 函數通常從/usr/lib/crt1.o靜態鏈接(標準函數). 此函數初始化內核環境,調用可執行文件的main()函數.

  應用程序現在運行了.

  動態鏈接器

  OS X 動態鏈接器/usr/lib/dyld, 負責加載依賴的共享庫, 導入變量符號和函數,與當前進程的綁定。進程首次運行時, 鏈接器所做的就是把共享庫導入到進程地址空間。取決于程序的build方式, 實際綁定也足執行不同的方式。

  載入后立即綁定—— load-time綁定.

  當符號引用時—— just-in-time綁定.

  預綁定

  如未指定綁定類型, 使用 just-in-time綁定.

  應用程序僅僅當所有需要的符號和段從不同的目標文件解決是才能繼續運行。為了尋找庫和框架, 標準動態鏈接器/usr/bin/dyld, 將搜索預定義的目錄集合. 要修改目錄, 或提供回滾路徑, 可以設置DYLD_LIBRARY_PATH或DYLD_FALLBACK_LIBRARY_PATH環境變量


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 都江堰市| 囊谦县| 广安市| 无极县| 密山市| 辽宁省| 玛纳斯县| 安化县| 赞皇县| 恩施市| 南昌市| 万安县| 芦山县| 普定县| 临泽县| 剑川县| 宁乡县| 永顺县| 和田县| 元江| 桂林市| 莱阳市| 剑河县| 安丘市| 太仓市| 泽库县| 通城县| 讷河市| 兴宁市| 和田县| 峨边| 额尔古纳市| 灵山县| 渑池县| 安义县| 姚安县| 四平市| 汕头市| 玛纳斯县| 遂川县| 鹤庆县|