程序员的自我修养学习笔记——第五章
PE: Portable Executable
COFF: Common Object File Format
?
跟ELF一樣,PE中也允許程序員將變量后函數放到自定義段。在GCC中使用“__attribute__((section)("name"))”,在VISUAL C++中可以使用 “#pragma”編譯器指示。
#pragma? data_seg("FOO")
int?? global = 1;
#pragma? data_seg(".data")
?
使用cl 編譯器:
開始 –> 所有程序 -> Microsoft Visual Studio ->
Visual Studio Tools -> Developer Command Prompt
?
cl /c /Za SimpleSectionc.c
/c參數表示只編譯,不鏈接,生成SimpleSection.obj
/Za 參數禁用這些擴展,使得我們的程序跟標準的C/C++ 兼容,使用/Za參數時,編譯器自動定義了__STDC__這個宏,我們可以再程序里通過判斷這個宏是否被定義而確定編譯器是否禁用了Microsoft C/C++ 語法擴展。
?
Windows下查看可執行文件和目標文件的工具:dumpbin
查看SimpleSection.obj:
dumpbin? /ALL SimpleSection.obj? > SimpleSection.txt
該命令打印出所以目標文件的相關信息,輸出到SimpleSection.txt中。
查看基本信息:
D:\Program Files\...>dumpbin SimpleSection.obj /SUMMARY
Microsoft (R) COFF/PE Dumper Version 11.00.50214.1
Copyright (C) Microsoft Corporation.? All rights reserved.
?
Dump of file SimpleSection.obj
File Type: COFF OBJECT
?
? Summary
?
?????????? 4 .bss
?????????? C .data
????????? 84 .debug$S
????????? 18 .drectve
????????? 4E .text
?
COFF文件結構:
COFF文件頭包括兩部分:一個是描述文件總體和屬性的映像頭,另外一個是描述該文件中包含的段屬性的段表
typedef struct _IMAGE_FILE_HEADER {
WORD??? Machine;?????????????????? //運行平臺
WORD??? NumberOfSections;????????? //區塊數目
DWORD?? TimeDateStamp;??????????? //文件日期時間戳
DWORD?? PointerToSymbolTable;????? //指向符號表
DWORD?? NumberOfSymbols;????????? //符號表中的符號數量
WORD??? SizeOfOptionalHeader;????? //映像可選頭結構的大小
WORD??? Characteristics;????????? //文件特征值
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
?
對應“SimpleSection.txt”中的輸出信息,“FILE HEADER VALUES”中的內容跟COFF映像頭中的成員是一一對應的:
Dump of file SimpleSection.obj
?
File Type: COFF OBJECT
?
FILE HEADER VALUES
???????????? ??????14C machine (x86)
????????????? ????5 number of sections
?????? ??????4F84D87A time date stamp Wed Apr 11 09:03:54 2012
?????????? ?????204 file pointer to symbol table
????????????? ??14 number of symbols
?????????????? ?0 size of optional header
????????????? ??0 characteristics
?
映像頭后面緊跟著的是COFF文件的段表,是一個類型為“IMGAE_SECTION_HEADER”結構的數組,數組中每個元素代表一個段,跟ELF文件中的“Elf32_Shdr”很相似。
typedef struct _IMAGE_SECTION_HEADER {
???? BYTE???? Name[IMAGE_SIZEOF_SHORT_NAME];
???? union {
???????????? DWORD??? PhysicalAddress;
???????????? DWORD??? VirtualSize;
???? } Misc;
???? DWORD??? VirtualAddress;
???? DWORD??? SizeOfRawData;
???? DWORD??? PointerToRawData;
???? DWORD??? PointerToRelocations;
???? DWORD??? PointerToLinenumbers;
???? WORD???? NumberOfRelocations;
???? WORD???? NumberOfLinenumbers;
???? DWORD??? Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
?
每個段擁有的屬性包括:段名(Section Name)、物理地址(Physical address)、虛擬地址(Virtual address)、原始數據大小(Size of raw data)、段在文件中的位置(File pointer to raw data)、該段的重定位表在文件中的位置(File pointer to relocation table)、該段的行號表在文件中的位置(File pointer to line numbers)、標志位(Characteristics)等。
?
符號表:
?
“SimpleSection.txt”的最后一部分是COFF符號表(Symbol table),COFF文件的符號表包含的內容幾乎跟ELF文件的符號表一樣,主要就是符號名、、符號的類型、所在的位置。
SimpleSection.obj的符號表:
?
COFF SYMBOL TABLE
000 00CEC426 ABS??? notype?????? Static?????? | @comp.id
001 80000191 ABS??? notype?????? Static?????? | @feat.00
002 00000000 SECT1? notype?????? Static?????? | .drectve
??? Section length?? 18, #relocs??? 0, #linenums??? 0, checksum??????? 0
004 00000000 SECT2? notype?????? Static?????? | .debug$S
??? Section length?? 84, #relocs??? 0, #linenums??? 0, checksum??????? 0
006 00000000 SECT3? notype?????? Static?????? | .data
??? Section length??? C, #relocs??? 0, #linenums??? 0, checksum AC5AB941
008 00000000 SECT3? notype?????? External???? | _global_init_var
009 00000004 UNDEF? notype?????? External???? | _global_uninit_var
00A 00000004 SECT3? notype?????? Static?????? | $SG1281
00B 00000008 SECT3? notype?????? Static?????? | ?static_var@?1??main@@9@9 (`main'::`2'::static_var)
00C 00000000 UNDEF? notype ()??? External???? | _printf
00D 00000000 SECT4? notype?????? Static?????? | .text
??? Section length?? 4E, #relocs??? 5, #linenums??? 0, checksum CC61DB94
00F 00000000 SECT4? notype ()??? External???? | _func1
010 00000020 SECT4? notype ()??? External???? | _main
011 00000000 SECT5? notype?????? Static?????? | .bss
??? Section length??? 4, #relocs??? 0, #linenums??? 0, checksum??????? 0
013 00000000 SECT5? notype?????? Static?????? | ?static_var2@?1??main@@9@9 (`main'::`2'::static_var2)
?
String Table Size = 0x5D bytes
?
第三列是符號所在的位置,“ABS”表示符號的絕對值,它不存在于任何段中;SECT1(Section#1)表示符號所表示的對象定義在COFF文件的第一個段中,即本例中的.drectve段;UNDEF(Undefined)表示符號是未定義的,即這個符號被定義在其他目標文件中的。Static表示絕不變量,External表示全局變量。
“_global_init_varabal”這個符號位于Section#3即 .data段,它的長度是4個字節,可見范圍是全局的。
?
PE文件是基于COFF擴展,比COFF文件多了幾個結構。最主要的變化有兩個:第一個是文件最開始部分不是COFF文件頭,而是DOS MZ可執行文件格式的文件頭和樁代碼,第二個變化是原來的COFF文件頭中的“IMAGE_FILE_HEADER”被擴展成為了PE文件頭結構“IMGAE_NT_HEADERS”
?
PE 文件格式
?
總結
以上是生活随笔為你收集整理的程序员的自我修养学习笔记——第五章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BOS新建连接属性
- 下一篇: 点是否在面内算法(Point-In-Po