error: PHDR segment not covered by LOAD segment
Asked Answered
A

1

6

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?

Anh answered 14/8, 2020 at 21:7 Comment(3)
After checking binutils version 2.34 new changes, it states, " The ld check for "PHDR segment not covered by LOAD segment" is more effective, catching cases that were wrongly allowed by previous versions of ld. If you see this error it is likely you are linking with a bad linker script or the binary you are building is not intended to be loaded by a dynamic loader. In the latter case --no-dynamic-linker is appropriate.", also oracle docs state PT_PHDR can only occur if ". Moreover, it can occur only if the program header table is part of the memory image of the program."Anh
Is this why PT_LOAD required the phdrs keyword, so that the program header table is loaded into memory?Anh
I may have found a partial explanation, patches.linaro.org/patch/87237, although i'm not sure why the textbook does not explain this...Anh
R
1

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.

Rorry answered 10/9, 2020 at 18:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.