作者:陳曦
日期:2012-6-23 14:24:27
環境:[Mac 10.7.1 Lion Intel i3 支援64位指令 gcc4.2.1 xcode4.2]
轉載請註明出處
Q1: 編譯產生的可執行檔內部是如何被執行的?
A: 當然,首先需要知道它的結構。先編寫一個簡單的程式,儲存為testForC.c:
#include <stdio.h>#include <string.h>#define PRINT_D(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));int main(){ printf("hello\n"); return 0;}
編譯產生32位應用程式testForC.使用file命令得到它的資訊:
Q2: Mach-O是什嗎?
A: 它表示mach架構下的目標檔案。我們可以通過工具MachOView來查看:
由可以看到mach-o格式開頭的基本資料,包括開頭的魔數、對應CPU類型等資訊。
Q3: 這些結構在哪裡可以看到?
A: 在mach-o/arch.h標頭檔可以看到如下結構:
typedef struct { const char *name; cpu_type_t cputype; cpu_subtype_t cpusubtype; enum NXByteOrder byteorder; const char *description;} NXArchInfo;
它包含一些架構資訊,在mach-o/loader.h標頭檔中包含mach-o格式檔案頭的格式:
/* * The 32-bit mach header appears at the very beginning of the object file for * 32-bit architectures. */struct mach_header {uint32_tmagic;/* mach magic number identifier */cpu_type_tcputype;/* cpu specifier */cpu_subtype_tcpusubtype;/* machine specifier */uint32_tfiletype;/* type of file */uint32_tncmds;/* number of load commands */uint32_tsizeofcmds;/* the size of all the load commands */uint32_tflags;/* flags */};
/* Constant for the magic field of the mach_header (32-bit architectures) */#defineMH_MAGIC0xfeedface/* the mach magic number */#define MH_CIGAM0xcefaedfe/* NXSwapInt(MH_MAGIC) */
Q4: 上面的cputype是CPU_TYPE_I386表示的是32位吧,有的應用程式套件組合含32位和64位體系的代碼,結構是如何的?
A: 先產生一個這樣的檔案。依然使用文章開頭的代碼,使用如下命令編譯:
gcc -o testForC testForC.c -arch i386 -arch x86_64
繼續使用file命令得到它的資訊:
可以看出,它包含兩種體系代碼。我們同樣使用MachOView工具查看它的內部資訊:
可以看出,它內部包含了兩種架構的資訊,並且它的開頭有一些特定的資訊,之後才是不同架構的資訊。
Q5: 中的Load Commands表示什嗎?
A: 它記錄了檔案中各個段(如程式碼片段,資料區段等)如何映射到記憶體,也包含了檔案使用的動態連結器以及檔案需要的動態庫,同時也包含檔案和動態連結器使用的符號表。Load Commands對應的結構定義如下:
/* * The segment load command indicates that a part of this file is to be * mapped into the task's address space. The size of this segment in memory, * vmsize, maybe equal to or larger than the amount to map from this file, * filesize. The file is mapped starting at fileoff to the beginning of * the segment in memory, vmaddr. The rest of the memory of the segment, * if any, is allocated zero fill on demand. The segment's maximum virtual * memory protection and initial virtual memory protection are specified * by the maxprot and initprot fields. If the segment has sections then the * section structures directly follow the segment command and their size is * reflected in cmdsize. */struct segment_command { /* for 32-bit architectures */uint32_tcmd;/* LC_SEGMENT */uint32_tcmdsize;/* includes sizeof section structs */charsegname[16];/* segment name */uint32_tvmaddr;/* memory address of this segment */uint32_tvmsize;/* memory size of this segment */uint32_tfileoff;/* file offset of this segment */uint32_tfilesize;/* amount to map from the file */vm_prot_tmaxprot;/* maximum VM protection */vm_prot_tinitprot;/* initial VM protection */uint32_tnsects;/* number of sections in segment */uint32_tflags;/* flags */};
比如說,對於testForC的第一個:
_TEXT段的VM Address為0x1000.
對於section __text, 它對應的地址是:
由此,我們可以得到__text在檔案中的真實位置為: 0x1F10 - 0x1000 = 0xF10.
作者:陳曦
日期:2012-6-23 14:24:27
環境:[Mac 10.7.1 Lion Intel i3 支援64位指令 gcc4.2.1 xcode4.2]
轉載請註明出處