error: PHDR segment not covered by LOAD segment

Viewed 3884

I was learning about linking scripts from the text "Operating Systems from 0 to 1", and in the text they showed an example of using the keyword PHDRS as so;

ENTRY(main);
    
PHDRS
{
    headers PT_PHDR FILEHDR PHDRS;
    code PT_LOAD FILEHDR;
}
    
SECTIONS /*top level command that declares a list of custom program sections, ld provides set of such instructions.*/
{
    . = 0x10000; /* set location counter to address 0x10000, base address for subsequent commands */
    .text : { *(.text) } :code /* final .text section begins at address 0x1000, combines all .text sections from obj files into one final*/
    . = 0x8000000; 
    .data : { *(.data) } /*wildcard means all obj file .data sections*/
    .bss : { *(.bss) }
}

Being used to link a c file; main.c

void test() {}

int main(int argc, char *argv[])
{
    asm("mov %eax, 0x1\n"
         "mov %ebx, 0x0\n"
         "int $0x80");
}

then compiled main.c to object file;

gcc -m32 -g -c main.c

However, when using the linker script;

ld -m elf_i386 -o main -T main.lds main.o
ld: main: error: PHDR segment not covered by LOAD segment

An error is produced, although when I change the PT_LOAD segment to include the PHDRS keyword, then the linker works properly.

Then after inspecting using readelf;

readelf -l main

Elf file type is EXEC (Executable file)
Entry point 0x10010
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000000 0x0000f000 0x0000f000 0x00074 0x00074 R   0x4
  LOAD           0x000000 0x0000f000 0x0000f000 0x7ff100c 0x7ff100c RWE 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .text .text.__x86.get_pc_thunk.ax .eh_frame .got.plt 

The PT_PHDR segment and PT_LOAD segment start at the same VA.

Is there a way to write the linker script so the segments are separated? Also why does this error occur?

1 Answers

The program headers are needed at run time, so they have to be loaded and therefore need to be covered by a PT_LOAD segment.

Most segment types overlap with at least one LOAD segment because they describe locations of loaded data. The only exception I can think of is the PT_GNU_STACK segment.

Related