这是简短的控制台应用程序示例
static char buffer[4096];
int main() {
for(int i=0;i<4096;i++) {
buffer[i] = 1234;
}
return 0;
}
据我了解,&#39; exe&#39;编译器生成的文件应该包含.bss部分来存储&#39; buffer&#39;变量
我使用的是Tiny C Compiler,结果文件中没有任何对.bss的引用。
DOS Header
Magic number: 0x5a4d (MZ)
Bytes in last page: 144
Pages in file: 3
Relocations: 0
Size of header in paragraphs: 4
Minimum extra paragraphs: 0
Maximum extra paragraphs: 65535
Initial (relative) SS value: 0
Initial SP value: 0xb8
Initial IP value: 0
Initial (relative) CS value: 0
Address of relocation table: 0x40
Overlay number: 0
OEM identifier: 0
OEM information: 0
PE header offset: 0x80
COFF/File header
Machine: 0x14c IMAGE_FILE_MACHINE_I386
Number of sections: 2
Date/time stamp: 0 (Thu, 01 Jan 1970 00:00:00 UTC)
Symbol Table offset: 0
Number of symbols: 0
Size of optional header: 0xe0
Characteristics: 0x30f
IMAGE_FILE_RELOCS_STRIPPED
IMAGE_FILE_EXECUTABLE_IMAGE
IMAGE_FILE_LINE_NUMS_STRIPPED
IMAGE_FILE_LOCAL_SYMS_STRIPPED
IMAGE_FILE_32BIT_MACHINE
IMAGE_FILE_DEBUG_STRIPPED
Optional/Image header
Magic number: 0x10b (PE32)
Linker major version: 6
Linker minor version: 0
Size of .text section: 0
Size of .data section: 0
Size of .bss section: 0
Entrypoint: 0x1060
Address of .text section: 0x1000
Address of .data section: 0x2000
ImageBase: 0x400000
Alignment of sections: 0x1000
Alignment factor: 0x200
Major version of required OS: 4
Minor version of required OS: 0
Major version of image: 0
Minor version of image: 0
Major version of subsystem: 4
Minor version of subsystem: 0
Size of image: 0x4000
Size of headers: 0x200
Checksum: 0x95d5
Subsystem required: 0x3 (IMAGE_SUBSYSTEM_WINDOWS_CUI)
DLL characteristics: 0
Size of stack to reserve: 0x100000
Size of stack to commit: 0x1000
Size of heap space to reserve: 0x100000
Size of heap space to commit: 0x1000
Data directories
IMAGE_DIRECTORY_ENTRY_IMPORT: 0x2000 (40 bytes)
IMAGE_DIRECTORY_ENTRY_IAT: 0x2028 (32 bytes)
Imported functions
msvcrt.dll
_controlfp
__set_app_type
__getmainargs
exit
_XcptFilter
_exit
_except_handler3
export directory not found
Sections
Name: .text
Virtual Address: 0x1000
Physical Address: 0x1e8
Size: 0x200 (512 bytes)
Pointer To Data: 0x200
Relocations: 0
Characteristics: 0x60000020
IMAGE_SCN_CNT_CODE
IMAGE_SCN_MEM_EXECUTE
IMAGE_SCN_MEM_READ
Name: .data
Virtual Address: 0x2000
Physical Address: 0x10e0
Size: 0x200 (512 bytes)
Pointer To Data: 0x400
Relocations: 0
Characteristics: 0xc0000040
IMAGE_SCN_CNT_INITIALIZED_DATA
IMAGE_SCN_MEM_READ
IMAGE_SCN_MEM_WRITE
可执行参考的反汇编版本&#39;缓冲区&#39;变量好像它位于.data部分之后。这个怎么运作 ? PE加载器如何知道它应该在.data节之后保留特定区域?
可执行文件:https://www.dropbox.com/s/99bpil11j7396ej/test-bss.exe?dl=0
PEDUMP在线:http://pedump.me/40c40172cf08c89c3d97bd6840dbd3a0/
答案 0 :(得分:6)
根据现在已知的.data部分的实际内存和磁盘大小,我认为可以解释buffer
的位置以及它是如何到达的。
为了保持一致性,我使用Microsoft Portable Executable and Common Object File Format Specification中的术语。
所以这就是我们对.data部分的了解,它的VirtualSize是4320(0x10E0),它的SizeOfRawData是512(0x200)。这意味着.data部分在磁盘上有512个字节,但在内存中填充为零,大小为4320字节。 SizeOfRawData值是可执行文件中初始化数据的大小,当您从VirtualSize中减去该值时,您将获得未初始化数据的大小。如注释中所述,这意味着.data部分有3808个字节的未初始化数据,这个空间不足以包含名为buffer
的4096字节数组。
那么buffer
在哪里?它必须从.data部分的初始化部分的某处开始,并继续进入未初始化的部分。 PECOFF要求将SizeOfRawData值向上舍入为FileAlignment的下一个倍数(512)。这意味着当链接器创建可执行文件的.data部分时,它会使用未初始化的数据填充磁盘上的初始化数据,以便SizeOfRawData最终为512的倍数。换句话说,可执行文件中的实际初始化数据量小于512字节,未初始化数据的实际数量大于3808。
此图试图显示链接器如何布局.data部分。顶部表示内存中相对于.data部分开头的位置,链接器将所有初始化变量和未初始化变量放在可执行文件中。中间部分显示放置buffer
的位置。底部显示.data部分的一部分,作为可执行文件中的初始化数据存在。
+------------------+----------------------------------------+
| Initialized Vars | Uninitialized Variables |
+--------------------+-----------------------------------+--+
| | buffer[4096] | |
+--------------------+---+-------------------------------+--+
| Initialized on Disk | 4320
+------------------------+
0 512
答案 1 :(得分:1)
不需要在exe文件中存储BSS部分,因为它只包含未初始化的数据。它由启动代码分配 - 即在到达main之前执行的代码。 BSS部分通常在RAM的DATA部分之后分配,并且通过启动代码被NORMALLY(并不总是)清零。 相反,DATA部分已初始化(使用要在源中指定的值),因此它必须存储在exe文件映像中。