Skip to content
This repository has been archived by the owner on Nov 10, 2022. It is now read-only.

Use lld as the linker and add a linker script #2

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

npmccallum
Copy link
Collaborator

@npmccallum npmccallum commented Jul 17, 2021

This patch aims only to add linker script semantics and should retain
linking equivalence. It does not aim to produce address for address
equality with ld. Functional changes in linker output should follow in
additional patches.

Before this patch, ld produced the following:

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000002898 0x0000000000002898  R      0x1000
  LOAD           0x0000000000003000 0x0000000000003000 0x0000000000003000
                 0x00000000000340ae 0x00000000000340ae  RWE    0x1000
  LOAD           0x0000000000038000 0x0000000000038000 0x0000000000038000
                 0x0000000000007520 0x0000000000007520  R      0x1000
  LOAD           0x000000000003f728 0x0000000000040728 0x0000000000040728
                 0x00000000000018d8 0x00000000000020d8  RW     0x1000
  DYNAMIC        0x00000000000408c0 0x00000000000418c0 0x00000000000418c0
                 0x0000000000000110 0x0000000000000110  RW     0x8
  NOTE           0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_EH_FRAME   0x000000000003c638 0x000000000003c638 0x000000000003c638
                 0x0000000000000a04 0x0000000000000a04  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000003f728 0x0000000000040728 0x0000000000040728
                 0x00000000000018d8 0x00000000000018d8  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn
   01     .init .text
   02     .rodata .eh_frame_hdr .eh_frame
   03     .data.rel.ro .dynamic .got .bss
   04     .dynamic
   05     .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .data.rel.ro .dynamic .got

After this patch, lld + linker script produce the following:

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000003830 0x0000000000003830  R      0x1000
  LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                 0x00000000000340ae 0x00000000000340ae  RWE    0x1000
  LOAD           0x0000000000039000 0x0000000000039000 0x0000000000039000
                 0x0000000000007464 0x0000000000007464  R      0x1000
  LOAD           0x0000000000041000 0x0000000000041000 0x0000000000041000
                 0x0000000000001920 0x0000000000002800  RW     0x1000
  DYNAMIC        0x0000000000042198 0x0000000000042198 0x0000000000042198
                 0x00000000000000d0 0x00000000000000d0  RW     0x8
  NOTE           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x0000000000000018 0x0000000000000018  R      0x4
  GNU_EH_FRAME   0x000000000003d42c 0x000000000003d42c 0x000000000003d42c
                 0x0000000000000a04 0x0000000000000a04  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  GNU_RELRO      0x0000000000041000 0x0000000000041000 0x0000000000041000
                 0x0000000000001920 0x0000000000002000  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn 
   01     .init .text 
   02     .rodata .eh_frame_hdr .eh_frame 
   03     .data.rel.ro .dynamic .got .bss 
   04     .dynamic 
   05     .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .data.rel.ro .dynamic .got

Signed-off-by: Nathaniel McCallum [email protected]

@npmccallum npmccallum requested a review from haraldh as a code owner July 17, 2021 18:57
@npmccallum
Copy link
Collaborator Author

@haraldh @wgwoods Review please!

@haraldh
Copy link
Contributor

haraldh commented Jul 17, 2021

why lld?

@npmccallum
Copy link
Collaborator Author

why lld?

Unfortunately, ‘ld‘ asserts on ‘GNU_RELRO‘. I haven't figured out why. Also, that section of GNU ‘ld‘ was rewritten in master, but that requires rawhide.

@npmccallum
Copy link
Collaborator Author

why lld?

Unfortunately, ‘ld‘ asserts on ‘GNU_RELRO‘. I haven't figured out why. Also, that section of GNU ‘ld‘ was rewritten in master, but that requires rawhide.

Specifically:

  = note: /usr/bin/ld: BFD version 2.35.2-3.fc34 assertion fail elf.c:6278
          collect2: error: ld returned 1 exit status

Because we are skipping tests on this non-standard ELF binary, we need
to test building instead.

Signed-off-by: Nathaniel McCallum <[email protected]>
This patch aims only to add linker script semantics and should retain
linking equivalence. It does not aim to produce address for address
equality with `ld`. Functional changes in linker output should follow in
additional patches.

Before this patch, `ld` produced the following:

```
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000002898 0x0000000000002898  R      0x1000
  LOAD           0x0000000000003000 0x0000000000003000 0x0000000000003000
                 0x00000000000340ae 0x00000000000340ae  RWE    0x1000
  LOAD           0x0000000000038000 0x0000000000038000 0x0000000000038000
                 0x0000000000007520 0x0000000000007520  R      0x1000
  LOAD           0x000000000003f728 0x0000000000040728 0x0000000000040728
                 0x00000000000018d8 0x00000000000020d8  RW     0x1000
  DYNAMIC        0x00000000000408c0 0x00000000000418c0 0x00000000000418c0
                 0x0000000000000110 0x0000000000000110  RW     0x8
  NOTE           0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x0000000000000024 0x0000000000000024  R      0x4
  GNU_EH_FRAME   0x000000000003c638 0x000000000003c638 0x000000000003c638
                 0x0000000000000a04 0x0000000000000a04  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000003f728 0x0000000000040728 0x0000000000040728
                 0x00000000000018d8 0x00000000000018d8  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn
   01     .init .text
   02     .rodata .eh_frame_hdr .eh_frame
   03     .data.rel.ro .dynamic .got .bss
   04     .dynamic
   05     .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .data.rel.ro .dynamic .got
```

After this patch, `lld` + linker script produce the following:

```
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000003830 0x0000000000003830  R      0x1000
  LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                 0x00000000000340ae 0x00000000000340ae  RWE    0x1000
  LOAD           0x0000000000039000 0x0000000000039000 0x0000000000039000
                 0x0000000000007464 0x0000000000007464  R      0x1000
  LOAD           0x0000000000041000 0x0000000000041000 0x0000000000041000
                 0x0000000000001920 0x0000000000002800  RW     0x1000
  DYNAMIC        0x0000000000042198 0x0000000000042198 0x0000000000042198
                 0x00000000000000d0 0x00000000000000d0  RW     0x8
  NOTE           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x0000000000000018 0x0000000000000018  R      0x4
  GNU_EH_FRAME   0x000000000003d42c 0x000000000003d42c 0x000000000003d42c
                 0x0000000000000a04 0x0000000000000a04  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  GNU_RELRO      0x0000000000041000 0x0000000000041000 0x0000000000041000
                 0x0000000000001920 0x0000000000002000  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn
   01     .init .text
   02     .rodata .eh_frame_hdr .eh_frame
   03     .data.rel.ro .dynamic .got .bss
   04     .dynamic
   05     .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .data.rel.ro .dynamic .got
```

Signed-off-by: Nathaniel McCallum <[email protected]>
@haraldh
Copy link
Contributor

haraldh commented Jul 19, 2021

This reduced version works for me without lld:

ENTRY(_start)

PHDRS {
  text PT_LOAD;
  rodata PT_LOAD;
  data PT_LOAD;

  dynamic PT_DYNAMIC;
}

SECTIONS {
  . = ALIGN(CONSTANT(MAXPAGESIZE));
  .init               : { KEEP (*(SORT_NONE(.init))) } :text
  .text               : { *(.text .text.*) } :text
  .rela.dyn           : { *(.rela.*) } :text

  . = ALIGN(CONSTANT(MAXPAGESIZE));
  .rodata             : { *(.rodata .rodata.*) } :rodata
  .dynsym             : { *(.dynsym) } :rodata
  .dynstr             : { *(.dynstr) } :rodata
  .gnu.hash           : { *(.gnu.hash) } :rodata

  . = ALIGN(CONSTANT(MAXPAGESIZE));
  .dynamic            : { *(.dynamic) } :data :dynamic
  .data.rel.ro        : { *(.data.rel.ro .data.rel.ro.*) } :data
  .got                : { *(.got) } :data
  .data               : { *(.data .data.*) } :data
  .bss                : { *(.bss .bss.*) } :data

  /DISCARD/ : {
      *(.eh_frame*)
      *(.note.GNU-stack)
      *(.gnu_debuglink)
      *(.interp)
      *(.gnu.hash)
      *(.hash)
      *(.comment)
      *(COMMON)
      *(.note.gnu.build-id)
  }
}

@npmccallum
Copy link
Collaborator Author

@haraldh That is somewhat equivalent. However, without GNU_RELRO we can't remap the pages after relocation. We can't do that anyway under SGX today. So that's probably not a huge loss. But we will eventually be able to do it.

I remain worried about the presence of the .init section. We don't currently do anything with it and I have no idea what kind of time bombs are in there.

@haraldh
Copy link
Contributor

haraldh commented Jul 19, 2021

@npmccallum

I remain worried about the presence of the .init section. We don't currently do anything with it and I have no idea what kind of time bombs are in there.

I stuffed the __SALLYPORT_ABI symbols in there :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants