.text 段大于可执行文件中的 .text 段。为什么?

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 部分有关?

vit*_*oft 5

请注意,文件地址 0 处的第一个程序段从虚拟地址 开始,而不是从与.text部分对应的0x08048000VA 开始。0x08048080

事实上,readelf 显示的段涵盖00 .text了 ELF 文件头(52 字节)、对齐方式、两个程序头(2*32 字节)和.text部分的 netto 内容,全部从文件地址 0 映射到 VA 0x08048000