<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/138584>138584</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [lld] Unsorted loadable program headers with `-Ttext=` argument
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          pskrgag
      </td>
    </tr>
</table>

<pre>
    ELF spec say that program headers must be sorted by `p_vaddr` 

> Loadable segment entries in the program header table appear in ascending order,
> sorted on the p_vaddr member

However it does not work if `-Ttext` argument is used. 

Consider following example:

```c
int main(void)
{
 while (1);
}
```

```bash
~/Documents/compiler_ws/lld
paskripkin > ~/Documents/git/llvm-project/build/bin/ld.lld -e main -Ttext=0x800000 test.o -o a.out

~/Documents/compiler_ws/lld
paskripkin > llvm-readelf -l a.out

Elf file type is EXEC (Executable file)
Entry point 0x800000
There are 5 program headers, starting at offset 64

Program Headers:
  Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000200040 0x0000000000200040 0x000118 0x000118 R   0x8
  LOAD           0x000000 0x0000000000200000 0x0000000000200000 0x000158 0x000158 R   0x1000
  LOAD           0x001000 0x0000000000800000 0x0000000000800000 0x00000d 0x00000d R E 0x1000
  LOAD 0x001010 0x0000000000801010 0x0000000000801010 0x00003c 0x00003c R 0x1000
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x0

 Section to Segment mapping:
  Segment Sections...
   00
   01
   02     .text
   03     .eh_frame
   04
 None   .comment .symtab .shstrtab .strtab
```

Note that first loadable segment has a `p_vaddr` less than the second one. (still reproduces on current master c50cba6275271fba69be661b9ec0665b2be88dbc).

## Sort of analysis

The first loadable segment is the one that contains ELF header and program headers. It's added in  `Writer<ELFT>::createPhdrs`. 
```cpp
 // Add the headers. We will remove them if they don't fit.
    // In the other partitions the headers are ordinary sections, so they don't
    // need to be added here.
    if (isMain) {
      load = addHdr(PT_LOAD, flags);
      load->add(ctx.out.elfHeader.get());
 load->add(ctx.out.programHeaders.get());
    }
```

In normal case it gets merged into some of other segments because of the following code

```cpp
    bool sameLMARegion =
        load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion;
    if (load && sec != relroEnd &&
        sec->memRegion == load->firstSec->memRegion &&
 (sameLMARegion || load->lastSec == ctx.out.programHeaders.get()) &&
 (ctx.script->hasSectionsCommand || sec->type == SHT_NOBITS ||
 load->lastSec->type != SHT_NOBITS)) {
      load->p_flags |= newFlags;
 } else {
      load = addHdr(PT_LOAD, newFlags);
      flags = newFlags;
 }

```

However if `-Ttext` is specified, predicate above may fail and new segment will be inserted. Then during `LinkerScript::assignAddresses`, first `PT_LOAD` segment gets assigned to `ctx.target->getImageBase()`, which may be far from the base of `text` (IIUC lld starts calculating from the base passed in `-T`). 

## Note
This is not a synthetic example. It was observed in real life with very strict elf loader.

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJycV01v4zwO_jXKhajh2InjHHJI87EttjNTNJmdvRWyRdvaypYhKU2yh_3tC8rOR9PuvIM1AtiRxIcUST2kuLWybBBnbHzPxssB37lKm1lr30zJy0GmxXG2elqDbTEHy4_gKu6gNbo0vIYKuUBjod5ZBxmC1cahgOwILAnb13cuhGFJCCyc0y9ewZPmgmcKwWJZY-MAG2ckWpANuApvkMH5tbxtkRtawm2OjZBNCdoINCxa9Li9Zt2jdKqhxjpD02l_0Ht8RwPSgdBoodEO9tq8gSzI2rutw4MjY7kpd940aWFnUQS9-QvdWElGFVopvScj8MDrViGL5_0Ok7D75Sycy8ZBzWXDovRdS8GiKa2Y3LNwDvtKKgQWpUMaju_9zPIa4QYw47Zi4fw_LFovde7tsyxa57pupULzuqd_SgkWzltu34xs32QD5JlbkVI6v_S9vmuN_hfm9DfbSSXoTeaulQiUEnCH3n7oXRMvw0Ma0gMOrQs03Gnggd65ztb_wzZvhaFQqwLu1DXaShVQkJPcsUUKxeqfqwV5bHXAfNflBc13bl01zhyh1eTzk5UsnG8rNAjcIIxvc5ZFC7COG0dx5A50UVh0kIw69c_96od-tY8wwJaM-dEtBfiHNG5OeXZ5nqujvRlaS4Ub-W-Ab1j7N6xVCXMly8ZjPj8sX66WhwcyfhT2H90T_X5oOEwvHy8eJPXYTz_my0_Y4Weg3wwNx-nlo8Medt79En54i5V-hv84JC4fL7D6BN-BDm8Rfj8U55ePl2vIv33_-brZzhd__41D_nro8vHyy4N0SQMbzJ0kDtKw6fmt5m0rm_KUQKfhfqUNgsCPQ28fhMP-HXkDA3_0upG4G8HqtTC8xn6UEha-6wZpLte1hw_ssXY8g8BW1pnuy78_U8x37bBj9UIa60DdMnTFLfAbQldoLQl1dGsx1w2RLwZ0Qq2TSoHB1mixy9ESK-c7Yzp3WIcG8nGYZzyJJuNoMiwynkwzTJJhNsU8TJJxFmWYpiLLWTQNeiaMYhbFsNGGzirwhqujlbab3Fb4v6yX1ptI_vGbzHXjuGwsUFXrqwxvxC09BPDoWDSxwIVAQaWHPPDLSIeGxYvV03rL4hVFNZ7nBrnD50oYy5KwKxfnQtC2FB8WrVm0hrkQ3pqzkl8I-85ZtX4nC7GmeuQqPILQDYsmFBbX58gJ5rFzu3YVGmiJw3wuXUN70tNGyIabIwXIr_Ckpz_Af0RuEAVlb4b9xolAT9qpUEaptN98UZtCX8v8Q34HFi9J7EEYFqXP21c6v6SyULy050J3Ebhj8YoLwaI0dwei_gBV0TFuUKJjUUpCZ7mvRfrA9UT9lRxt76vi-thAo03NFeTcIjUGJToLNZrSh9xpsLpGSrfO1X1OWcgw5zvrZ8jnl4Yg1wJvW4EuAwAg01qB5TU-fZu_YElEweLl2SMnJ0YJixJg0dBiTttVNV8dWnOauIxeYcTLs3f8OdjcLLp4ogvitSaLOWkjDIPK6FVzmroyrddaY_3XWq8WnWGIFj7ufLJgk8VZXnEvfoL9g-B-BCcBmxvZOkKruD0R7ELXNZ3vXl-_D99U9Lo2D9vX7z_uH7ebftF1rvV2XWQ6R11kTsZMPqd2--oT36PGS2hwv_YHoYsFmywBlcU_P0ZngI8nqVfypYabXLzphG8aX2l9my8LiYL0tQaFzLlD4BmxU82PUHCpPF82uD9zrKewDEE2FqkND2BbYQNiZ-hMsCR8ks0bmo2PT8eZ3b2DOiW0Fok3PVF4DmdJeNp1Ep6V-LPZX1c8R9HZcofAcVOij3qJ7rHmJd5zi32adLD7SuaVNz9DKLiBwujan9yMd6eYJeHJCyxKHx9_LoA6YN8gWsi5yneK-1bxo2jLre3Kg_ek1zc9XRj6kkUF1tcoacnFdO_gYI-Nq9DJ_HSHoIIDe25BZxbNewdqkCtQsqAq4Sp4R-JyZ2TugDpmyhY0RM8DMYvFNJ7yAc6Gk1EymqSTOBlUM8yKMBsm02g0zoqYR6NkKkbTIY-jVIz5NB_IWRRG43AcjqNwnI6TYIrZNONphqM4HiYiZqMQay5VQM16oE05kNbucDaM03E6GiieobKn66OZ-ZY-25WWjUIlrbMXOSed8hdNuguMl_Cz6W9t56J9e6_0u77kaLy8vp8NdkbNKuda3537-lVKV-0y6oL6K87nm443ni4kvf3vs-i_AQAA__9mOX6H">