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

Commit

Permalink
Use lld as the linker and add a linker script
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
npmccallum committed Jul 17, 2021
1 parent f7f2e60 commit 3c1a130
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .cargo/config
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ rustflags = [
"-C", "relocation-model=pic",
"-C", "link-args=-Wl,--sort-section=alignment -nostartfiles",
"-C", "link-self-contained=no",
"-C", "link-arg=-Tlink.script",

# Using GNU ld on Fedora 34 produces this assertion:
# = note: /usr/bin/ld: BFD version 2.35.2-3.fc34 assertion fail elf.c:6278
# collect2: error: ld returned 1 exit status
#"-C", "link-arg=-fuse-ld=lld",
]
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jobs:
with:
toolchain: ${{ matrix.toolchain }}
override: true
- name: Install lld
run: sudo apt install lld
- uses: actions-rs/cargo@v1
with:
command: build
Expand Down
58 changes: 58 additions & 0 deletions link.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
ENTRY(_start)

PHDRS {
preamble PT_LOAD FILEHDR PHDRS;
text PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;

dynamic PT_DYNAMIC;
note PT_NOTE;

frame 0x6474e550; /* GNU_EH_FRAME */
stack 0x6474e551 FLAGS(6); /* GNU_STACK */
relro 0x6474e552 FLAGS(4); /* GNU_RELRO */
}

SECTIONS {
. = SIZEOF_HEADERS;

. = ALIGN(CONSTANT(MAXPAGESIZE));
.interp : { *(.interp) } :preamble
.note.gnu.build-id : { *(.note.gnu.build-id) } :preamble :note
.hash : { *(.hash) } :preamble
.gnu.hash : { *(.gnu.hash) } :preamble
.dynsym : { *(.dynsym) } :preamble
.dynstr : { *(.dynstr) } :preamble
.gnu.version : { *(.gnu.version) } :preamble
.gnu.version_d : { *(.gnu.version_d) } :preamble
.gnu.version_r : { *(.gnu.version_r) } :preamble
.rela.dyn : { *(.rela.*) } :preamble
.rela.plt : { *(.rela.plt) *(.rela.iplt) } :preamble

. = ALIGN(CONSTANT(MAXPAGESIZE));
.init : { KEEP (*(SORT_NONE(.init))) } :text
.fini : { KEEP (*(SORT_NONE(.fini))) } :text
.text : { *(.text .text.*) } :text
.plt : { *(.plt) *(.iplt) } :text
.plt.got : { *(.plt.got) } :text
.plt.sec : { *(.plt.sec) } :text

. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : { *(.rodata .rodata.*) } :rodata
.rodata1 : { *(.rodata1) } :rodata
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } :rodata :frame
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :rodata

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

. = ALIGN(CONSTANT(MAXPAGESIZE)); /* Align here? New section? */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } :data
.data : { *(.data .data.*) } :data
.data1 : { *(.data1) } :data
.bss : { *(.bss .bss.*) } :data
}

0 comments on commit 3c1a130

Please sign in to comment.