Nic*_*k_h 2 linux x86 assembly elf
我在 NASM 中有以下“uppercaser.asm”汇编程序,它将用户输入的所有小写字母转换为大写:
section .bss
Buff resb 1
section .data
section .text
global _start
_start:
nop ; This no-op keeps the debugger happy
Read: mov eax,3 ; Specify sys_read call
mov ebx,0 ; Specify File Descriptor 0: Standard Input
mov ecx,Buff ; Pass offset of the buffer to read to
mov edx,1 ; Tell sys_read to read one char from stdin
int 80h ; Call sys_read
cmp eax,0 ; Look at sys_read's return value in EAX
je Exit ; Jump If Equal to 0 (0 means EOF) to Exit
; or fall through to test for lowercase
cmp byte [Buff],61h ; Test input char against lowercase 'a'
jb Write ; If below 'a' in ASCII chart, not lowercase
cmp byte [Buff],7Ah ; Test input char against lowercase 'z'
ja Write ; If above 'z' in ASCII chart, not lowercase
; At this point, we have a lowercase character
sub byte [Buff],20h ; Subtract 20h from lowercase to give uppercase...
; ...and then write out the char to stdout
Write: mov eax,4 ; Specify sys_write call
mov ebx,1 ; Specify File Descriptor 1: Standard output
mov ecx,Buff ; Pass address of the character to write
mov edx,1 ; Pass number of chars to write
int 80h ; Call sys_write...
jmp Read ; ...then go to the beginning to get another character
Exit: mov eax,1 ; Code for Exit Syscall
mov ebx,0 ; Return a code of zero to Linux
int 80H ; Make kernel call to exit program
Run Code Online (Sandbox Code Playgroud)
然后使用调试器选项对该程序进行汇编-g -F stabs,并链接为 ubuntu 18.04 中的 32 位可执行文件。
运行readelf --segments uppercaser段和readelf -S uppercaser部分时,我发现文本段和文本部分的大小存在差异。
readelf --segments uppercaser
Elf file type is EXEC (Executable file)
Entry point 0x8048080
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x000db 0x000db R E 0x1000
LOAD 0x0000dc 0x080490dc 0x080490dc 0x00000 0x00004 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text
01 .bss
Run Code Online (Sandbox Code Playgroud)
readelf -S uppercaser
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 08048080 000080 00005b 00 AX 0 0 16
[ 2] .bss NOBITS 080490dc 0000dc 000004 00 WA 0 0 4
[ 3] .stab PROGBITS 00000000 0000dc 000120 0c 4 0 4
[ 4] .stabstr STRTAB 00000000 0001fc 000011 00 0 0 1
[ 5] .comment PROGBITS 00000000 00020d 00001f 00 0 0 1
[ 6] .shstrtab STRTAB 00000000 00022c 00003e 00 0 0 1
[ 7] .symtab SYMTAB 00000000 0003d4 0000f0 10 8 11 4
[ 8] .strtab STRTAB 00000000 0004c4 000045 00 0 0 1
Run Code Online (Sandbox Code Playgroud)
在节描述中,我们可以看到 .text 节的大小为5Bh=91 字节(与命令获取的数字相同size),而在段描述中,我们看到大小为0x000DB,相差 128 字节。这是为什么?
来自 Elf 手册页中的 Elf32_Phdr(程序头)结构:
p_filesz 该成员保存段的文件映像中的字节数。它可能为零。
p_memsz 该成员保存段内存映像中的字节数。它可能为零。
差异是否与 .bss 部分有关?
请注意,文件地址 0 处的第一个程序段从虚拟地址 开始,而不是从与.text部分对应的0x08048000VA 开始。0x08048080
事实上,readelf 显示的段涵盖00 .text了 ELF 文件头(52 字节)、对齐方式、两个程序头(2*32 字节)和.text部分的 netto 内容,全部从文件地址 0 映射到 VA 0x08048000。