这是简短的控制台应用程序示例
static char buffer[4096];
int main() {
for(int i=0;i<4096;i++) {
buffer[i] = 1234;
}
return 0;
}
据我了解,编译器生成的“exe”文件应包含 .bss 部分来存储“缓冲区”变量。
我正在使用 Tiny C 编译器,生成的文件不包含任何对 .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
可执行文件的反汇编版本引用“buffer”变量,就好像它位于 .data 部分之后一样。怎么运行的 ? PE加载器如何知道它应该在.data节之后保留特定区域?
可执行文件:https://www.dropbox.com/s/99bpil11j7396ej/test-bss.exe?dl=0
PEDUMP 在线:http://pedump.me/40c40172cf08c89c3d97bd6840dbd3a0/
现在已知 .data 部分的实际内存和磁盘大小,我认为可以解释在哪里buffer
位于何处以及如何到达那里。
为了保持一致性,我使用的术语来自Microsoft 可移植可执行文件和通用对象文件格式规范.
这就是我们对 .data 部分的了解,它的 VirtualSize 是 4320 (0x10E0),它的 SizeOfRawData 是 512 (0x200)。这意味着 .data 部分在磁盘上有 512 字节,但在内存中被零填充到 4320 字节的大小。 SizeOfRawData 值是可执行文件中已初始化数据的大小,当您从 VirtualSize 中减去该值时,您将得到未初始化数据的大小。正如注释中所指出的,这意味着 .data 部分有 3808 字节的未初始化数据,这没有足够的空间来包含名为的 4096 字节数组buffer
.
那么在哪里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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)