1

I have write a very simple c program as follow:

// main.c
int main(void){
    while(1);
    return 0;
}

Then I tried to compile and link it into a 32-bits binary file, and I also want to specify the linear address of the program entry point during the link stage. I run following commands on Ubuntu 20.04 (x86_64):

# get obejct file
gcc -m32 -c -o main.o main.c
# link
ld main.o -melf_i386 -Ttext 0xc0001500 -e main -o main.bin

However, when I tried to check the produced ELF file, I found several program headers that out of my expectation:

readelf -e ./main.bin
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0xc0001500
  Start of program headers:          52 (bytes into file)
  Start of section headers:          8636 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         9
  Section header string table index: 8

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.propert NOTE            08048114 000114 00001c 00   A  0   0  4
  [ 2] .text             PROGBITS        c0001500 000500 000017 00  AX  0   0  1
  [ 3] .eh_frame         PROGBITS        c0002000 001000 000048 00   A  0   0  4
  [ 4] .got.plt          PROGBITS        c0004000 002000 00000c 04  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 00200c 00002a 01  MS  0   0  1
  [ 6] .symtab           SYMTAB          00000000 002038 0000e0 10      7   9  4
  [ 7] .strtab           STRTAB          00000000 002118 000051 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 002169 000050 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x00130 0x00130 R   0x1000
  LOAD           0x000500 0xc0001500 0xc0001500 0x00017 0x00017 R E 0x1000
  LOAD           0x001000 0xc0002000 0xc0002000 0x00048 0x00048 R   0x1000
  LOAD           0x002000 0xc0004000 0xc0004000 0x0000c 0x0000c RW  0x1000
  NOTE           0x000114 0x08048114 0x08048114 0x0001c 0x0001c R   0x4
  GNU_PROPERTY   0x000114 0x08048114 0x08048114 0x0001c 0x0001c R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10

Besides the second program header which essentialy is my executable c program above, what're these other segments?

Really thanks for your help!

  • 1
    `.text` and `.data`/`.bss` go in different segments of course, and modern `ld` puts `.rodata` in a separate segment too so it can be read without exec. IIRC, the first program-header entry is so the dynamic linker can read the ELF metadata, and unfortunately that doesn't use the same mapping as `.rodata`. – Peter Cordes Oct 04 '21 at 04:31

0 Answers0