diff options
Diffstat (limited to 'test/ELF/linkerscript')
116 files changed, 4245 insertions, 0 deletions
diff --git a/test/ELF/linkerscript/Inputs/comdat-gc.s b/test/ELF/linkerscript/Inputs/comdat-gc.s new file mode 100644 index 000000000000..da29d5b3830b --- /dev/null +++ b/test/ELF/linkerscript/Inputs/comdat-gc.s @@ -0,0 +1,5 @@ +.file 1 "test/ELF/linkerscript/Inputs/comdat_gc.s" + +.section .text._Z3fooIiEvv,"axG",@progbits,_Z3fooIiEvv,comdat +.loc 1 5 + ret diff --git a/test/ELF/linkerscript/Inputs/exclude-multiple1.s b/test/ELF/linkerscript/Inputs/exclude-multiple1.s new file mode 100644 index 000000000000..1e0f741df40f --- /dev/null +++ b/test/ELF/linkerscript/Inputs/exclude-multiple1.s @@ -0,0 +1,8 @@ +.section .foo.1,"a" + .quad 4 + +.section .foo.2,"a" + .quad 5 + +.section .foo.3,"a" + .quad 6 diff --git a/test/ELF/linkerscript/Inputs/exclude-multiple2.s b/test/ELF/linkerscript/Inputs/exclude-multiple2.s new file mode 100644 index 000000000000..60f790fa2356 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/exclude-multiple2.s @@ -0,0 +1,8 @@ +.section .foo.1,"a" + .quad 7 + +.section .foo.2,"a" + .quad 8 + +.section .foo.3,"a" + .quad 9 diff --git a/test/ELF/linkerscript/Inputs/filename-spec.s b/test/ELF/linkerscript/Inputs/filename-spec.s new file mode 100644 index 000000000000..a688b4db4b60 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/filename-spec.s @@ -0,0 +1,2 @@ +.section .foo,"a" + .quad 0x11 diff --git a/test/ELF/linkerscript/Inputs/implicit-program-header.script b/test/ELF/linkerscript/Inputs/implicit-program-header.script new file mode 100644 index 000000000000..27dbea84c4e4 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/implicit-program-header.script @@ -0,0 +1,12 @@ +PHDRS +{ + ph_write PT_LOAD FLAGS(2); + ph_exec PT_LOAD FLAGS(1); +} + +SECTIONS +{ + .bar : { *(.bar) } : ph_exec + .foo : { *(.foo) } + .text : { *(.text) } : ph_write +} diff --git a/test/ELF/linkerscript/Inputs/include.s b/test/ELF/linkerscript/Inputs/include.s new file mode 100644 index 000000000000..a2f809b522f3 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/include.s @@ -0,0 +1,5 @@ +.section .text +.globl _potato +_potato: + nop + nop diff --git a/test/ELF/linkerscript/Inputs/keep.s b/test/ELF/linkerscript/Inputs/keep.s new file mode 100644 index 000000000000..20fa41c1adff --- /dev/null +++ b/test/ELF/linkerscript/Inputs/keep.s @@ -0,0 +1,2 @@ +.section .keep, "a" + .long 0x41414141 diff --git a/test/ELF/linkerscript/Inputs/libsearch-dyn.s b/test/ELF/linkerscript/Inputs/libsearch-dyn.s new file mode 100644 index 000000000000..091b3b9b6ece --- /dev/null +++ b/test/ELF/linkerscript/Inputs/libsearch-dyn.s @@ -0,0 +1,3 @@ +.globl _bar,_dynamic +_bar: +_dynamic: diff --git a/test/ELF/linkerscript/Inputs/libsearch-st.s b/test/ELF/linkerscript/Inputs/libsearch-st.s new file mode 100644 index 000000000000..6da62f79d52f --- /dev/null +++ b/test/ELF/linkerscript/Inputs/libsearch-st.s @@ -0,0 +1,3 @@ +.globl _bar,_static +_bar: +_static: diff --git a/test/ELF/linkerscript/Inputs/merge-sections-reloc.s b/test/ELF/linkerscript/Inputs/merge-sections-reloc.s new file mode 100644 index 000000000000..07e599b2820f --- /dev/null +++ b/test/ELF/linkerscript/Inputs/merge-sections-reloc.s @@ -0,0 +1,3 @@ +.globl _start +_start: + .quad 0x11223344 diff --git a/test/ELF/linkerscript/Inputs/notinclude.s b/test/ELF/linkerscript/Inputs/notinclude.s new file mode 100644 index 000000000000..46c0509b56cc --- /dev/null +++ b/test/ELF/linkerscript/Inputs/notinclude.s @@ -0,0 +1,4 @@ +.section .text +.globl tomato +tomato: + movl $1, %eax diff --git a/test/ELF/linkerscript/Inputs/segment-start.script b/test/ELF/linkerscript/Inputs/segment-start.script new file mode 100644 index 000000000000..9f1a59360105 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/segment-start.script @@ -0,0 +1,7 @@ +SECTIONS +{ + PROVIDE (foobar1 = SEGMENT_START("text-segment", 0x8001)); + PROVIDE (foobar2 = SEGMENT_START("data-segment", 0x8002)); + PROVIDE (foobar3 = SEGMENT_START("bss-segment", 0x8000 + (4 - 1))); + PROVIDE (foobar4 = SEGMENT_START("abc-segment", 0x8004)); +} diff --git a/test/ELF/linkerscript/Inputs/shared.s b/test/ELF/linkerscript/Inputs/shared.s new file mode 100644 index 000000000000..c3c22fe4b4fb --- /dev/null +++ b/test/ELF/linkerscript/Inputs/shared.s @@ -0,0 +1,10 @@ +.global bar +.type bar, @function +bar: + +.global bar2 +.type bar2, @function +bar2: + +.global zed +zed: diff --git a/test/ELF/linkerscript/Inputs/sort-nested.s b/test/ELF/linkerscript/Inputs/sort-nested.s new file mode 100644 index 000000000000..c42fa9cd7ed8 --- /dev/null +++ b/test/ELF/linkerscript/Inputs/sort-nested.s @@ -0,0 +1,7 @@ +.section .aaa.1, "a" +.align 16 +.quad 0x11 + +.section .aaa.2, "a" +.align 4 +.quad 0x22 diff --git a/test/ELF/linkerscript/Inputs/sort.s b/test/ELF/linkerscript/Inputs/sort.s new file mode 100644 index 000000000000..22e65ad19e1e --- /dev/null +++ b/test/ELF/linkerscript/Inputs/sort.s @@ -0,0 +1,19 @@ +.section .aaa.5, "a" +.align 2 +.quad 0x55 + +.section .aaa.1, "a" +.align 32 +.quad 0x11 + +.section .aaa.3, "a" +.align 8 +.quad 0x33 + +.section .aaa.2, "a" +.align 16 +.quad 0x22 + +.section .aaa.4, "a" +.align 4 +.quad 0x44 diff --git a/test/ELF/linkerscript/absolute-expr.s b/test/ELF/linkerscript/absolute-expr.s new file mode 100644 index 000000000000..a9a674b859f4 --- /dev/null +++ b/test/ELF/linkerscript/absolute-expr.s @@ -0,0 +1,82 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: .text : { \ +# RUN: bar1 = ALIGNOF(.text); \ +# RUN: bar2 = CONSTANT (MAXPAGESIZE); \ +# RUN: bar3 = SIZEOF (.text); \ +# RUN: bar4 = SIZEOF_HEADERS; \ +# RUN: bar5 = 0x42; \ +# RUN: bar6 = foo + 1; \ +# RUN: *(.text) \ +# RUN: } \ +# RUN: };" > %t.script +# RUN: ld.lld -o %t.so --script %t.script %t.o -shared +# RUN: llvm-readobj -t %t.so | FileCheck %s + +.global foo +foo = 0x123 + +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: 0x123 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute (0xFFF1) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar1 +# CHECK-NEXT: Value: 0x4 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar2 +# CHECK-NEXT: Value: 0x1000 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar3 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar4 +# CHECK-NEXT: Value: 0x190 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar5 +# CHECK-NEXT: Value: 0x42 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: bar6 +# CHECK-NEXT: Value: 0x124 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute (0xFFF1) +# CHECK-NEXT: } diff --git a/test/ELF/linkerscript/absolute.s b/test/ELF/linkerscript/absolute.s new file mode 100644 index 000000000000..e4b156e2f012 --- /dev/null +++ b/test/ELF/linkerscript/absolute.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { foo = ABSOLUTE(.) + 1; };" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj --symbols %t | FileCheck %s + +# CHECK: Name: foo +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } + +.text +.globl _start +_start: diff --git a/test/ELF/linkerscript/addr.s b/test/ELF/linkerscript/addr.s new file mode 100644 index 000000000000..2d3a7ab35767 --- /dev/null +++ b/test/ELF/linkerscript/addr.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; \ +# RUN: .text : { *(.text*) } \ +# RUN: .foo.1 : { *(.foo.1) } \ +# RUN: .foo.2 ADDR(.foo.1) + 0x100 : { *(.foo.2) } \ +# RUN: .foo.3 : { *(.foo.3) } \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t1 +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000000 0000000000001000 TEXT DATA +# CHECK-NEXT: 2 .foo.1 00000008 0000000000001000 DATA +# CHECK-NEXT: 3 .foo.2 00000008 0000000000001100 DATA +# CHECK-NEXT: 4 .foo.3 00000008 0000000000001108 DATA + +.text +.globl _start +_start: + +.section .foo.1,"a" + .quad 1 + +.section .foo.2,"a" + .quad 2 + +.section .foo.3,"a" + .quad 3 diff --git a/test/ELF/linkerscript/align-empty.s b/test/ELF/linkerscript/align-empty.s new file mode 100644 index 000000000000..3ff71578410a --- /dev/null +++ b/test/ELF/linkerscript/align-empty.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: abc : { } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: foo : { *(foo) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 foo 00000001 0000000000001000 + + .section foo, "a" + .byte 0 diff --git a/test/ELF/linkerscript/align.s b/test/ELF/linkerscript/align.s new file mode 100644 index 000000000000..1e50fed3fa83 --- /dev/null +++ b/test/ELF/linkerscript/align.s @@ -0,0 +1,83 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Check that ALIGN command workable using location counter +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000; \ +# RUN: .aaa : \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: . = ALIGN(4096); \ +# RUN: .bbb : \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: . = ALIGN(4096 * 4); \ +# RUN: .ccc : \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +## Check that the two argument version of ALIGN command works +# RUN: echo "SECTIONS { \ +# RUN: . = ALIGN(0x1234, 0x10000); \ +# RUN: .aaa : \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: . = ALIGN(., 4096); \ +# RUN: .bbb : \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: . = ALIGN(., 4096 * 4); \ +# RUN: .ccc : \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA +# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA +# CHECK-NEXT: 3 .ccc 00000008 0000000000014000 DATA + +## Check output sections ALIGN modificator +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000; \ +# RUN: .aaa : \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: .bbb : ALIGN(4096) \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: .ccc : ALIGN(4096 * 4) \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +.global _start +_start: + nop + +.section .aaa, "a" +.quad 0 + +.section .bbb, "a" +.quad 0 + +.section .ccc, "a" +.quad 0 diff --git a/test/ELF/linkerscript/alignof.s b/test/ELF/linkerscript/alignof.s new file mode 100644 index 000000000000..8880634df243 --- /dev/null +++ b/test/ELF/linkerscript/alignof.s @@ -0,0 +1,41 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: .aaa : { *(.aaa) } \ +# RUN: .bbb : { *(.bbb) } \ +# RUN: .ccc : { *(.ccc) } \ +# RUN: _aaa = ALIGNOF(.aaa); \ +# RUN: _bbb = ALIGNOF(.bbb); \ +# RUN: _ccc = ALIGNOF(.ccc); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s +# CHECK: SYMBOL TABLE: +# CHECK: 0000000000000008 *ABS* 00000000 _aaa +# CHECK-NEXT: 0000000000000010 *ABS* 00000000 _bbb +# CHECK-NEXT: 0000000000000020 *ABS* 00000000 _ccc + +## Check that we error out if trying to get alignment of +## section that does not exist. +# RUN: echo "SECTIONS { \ +# RUN: _aaa = ALIGNOF(.foo); \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR %s +# ERR: {{.*}}.script:1: undefined section .foo +.global _start +_start: + nop + +.section .aaa,"a" + .align 8 + .quad 0 + +.section .bbb,"a" + .align 16 + .quad 0 + +.section .ccc,"a" + .align 32 + .quad 0 diff --git a/test/ELF/linkerscript/alternate-sections.s b/test/ELF/linkerscript/alternate-sections.s new file mode 100644 index 000000000000..6d3004af9a80 --- /dev/null +++ b/test/ELF/linkerscript/alternate-sections.s @@ -0,0 +1,34 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { abc : { *(foo) *(bar) *(zed) } }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o -shared +# RUN: llvm-readobj -s -section-data %t | FileCheck %s + +# This test shows an oddity in lld. When a linker script alternates among +# different types of output section in the same command, the sections are +# reordered. +# In this test we go from regular, to merge and back to regular. The reason +# for the reordering is that we need two create two output sections and +# one cannot be in the middle of another. +# If this ever becomes a problem, some options would be: +# * Adding an extra layer in between input section and output sections (Chunk). +# With that this example would have 3 chunks, but only one output section. +# This would unfortunately complicate the non-script case too. +# * Just create three output sections. +# * If having three output sections causes problem, have linkerscript specific +# code to write the section table and section indexes. That way we could +# keep 3 sections internally but not expose that. + +# CHECK: Name: abc +# CHECK: 0000: 01000000 00000000 02000000 00000000 | +# CHECK: Name: abc +# CHECK: 0000: 61626331 323300 |abc123.| + + .section foo, "a" + .quad 1 + + .section bar,"aMS",@progbits,1 + .asciz "abc123" + + .section zed, "a" + .quad 2 diff --git a/test/ELF/linkerscript/arm-exidx-phdrs.s b/test/ELF/linkerscript/arm-exidx-phdrs.s new file mode 100644 index 000000000000..971702f55d7b --- /dev/null +++ b/test/ELF/linkerscript/arm-exidx-phdrs.s @@ -0,0 +1,16 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: echo "PHDRS { ph_text PT_LOAD; } \ +// RUN: SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text : { *(.text) } : ph_text \ +// RUN: }" > %t.script +// RUN: ld.lld -T %t.script %t.o -shared -o %t.so +// RUN: llvm-readobj --program-headers %t.so | FileCheck %s + +// CHECK: Type: PT_ARM_EXIDX + +.fnstart +bx lr +.cantunwind +.fnend diff --git a/test/ELF/linkerscript/assert.s b/test/ELF/linkerscript/assert.s new file mode 100644 index 000000000000..06eeaeec3b99 --- /dev/null +++ b/test/ELF/linkerscript/assert.s @@ -0,0 +1,43 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o + +# RUN: echo "SECTIONS { ASSERT(1, fail) }" > %t1.script +# RUN: ld.lld -shared -o %t1 --script %t1.script %t1.o +# RUN: llvm-readobj %t1 > /dev/null + +# RUN: echo "SECTIONS { ASSERT(ASSERT(42, fail) == 42, fail) }" > %t2.script +# RUN: ld.lld -shared -o %t2 --script %t2.script %t1.o +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "SECTIONS { ASSERT(0, fail) }" > %t3.script +# RUN: not ld.lld -shared -o %t3 --script %t3.script %t1.o > %t.log 2>&1 +# RUN: FileCheck %s -check-prefix=FAIL < %t.log +# FAIL: fail + +# RUN: echo "SECTIONS { . = ASSERT(0x1000, fail); }" > %t4.script +# RUN: ld.lld -shared -o %t4 --script %t4.script %t1.o +# RUN: llvm-readobj %t4 > /dev/null + +# RUN: echo "SECTIONS { .foo : { *(.foo) } }" > %t5.script +# RUN: echo "ASSERT(SIZEOF(.foo) == 8, fail);" >> %t5.script +# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o +# RUN: llvm-readobj %t5 > /dev/null + +## Even without SECTIONS block we still use section names +## in expressions +# RUN: echo "ASSERT(SIZEOF(.foo) == 8, fail);" > %t5.script +# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o +# RUN: llvm-readobj %t5 > /dev/null + +## Test assertions inside of output section decriptions. +# RUN: echo "SECTIONS { .foo : { *(.foo) ASSERT(SIZEOF(.foo) == 8, \"true\"); } }" > %t6.script +# RUN: ld.lld -shared -o %t6 --script %t6.script %t1.o +# RUN: llvm-readobj %t6 > /dev/null + +# RUN: echo "SECTIONS { .foo : { ASSERT(1, \"true\") } }" > %t7.script +# RUN: not ld.lld -shared -o %t7 --script %t7.script %t1.o > %t.log 2>&1 +# RUN: FileCheck %s -check-prefix=CHECK-SEMI < %t.log +# CHECK-SEMI: error: {{.*}}.script:1: ; expected, but got } + +.section .foo, "a" + .quad 0 diff --git a/test/ELF/linkerscript/at.s b/test/ELF/linkerscript/at.s new file mode 100644 index 000000000000..a6b6198710ea --- /dev/null +++ b/test/ELF/linkerscript/at.s @@ -0,0 +1,119 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; \ +# RUN: .aaa : AT(0x2000) \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: .bbb : \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: .ccc : AT(0x3000) \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: .ddd : AT(0x4000) \ +# RUN: { \ +# RUN: *(.ddd) \ +# RUN: } \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_PHDR +# CHECK-NEXT: Offset: 0x40 +# CHECK-NEXT: VirtualAddress: 0x40 +# CHECK-NEXT: PhysicalAddress: 0x40 +# CHECK-NEXT: FileSize: +# CHECK-NEXT: MemSize: +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 8 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x0 +# CHECK-NEXT: PhysicalAddress: 0x0 +# CHECK-NEXT: FileSize: +# CHECK-NEXT: MemSize: +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x2000 +# CHECK-NEXT: FileSize: 16 +# CHECK-NEXT: MemSize: 16 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x1010 +# CHECK-NEXT: VirtualAddress: 0x1010 +# CHECK-NEXT: PhysicalAddress: 0x3000 +# CHECK-NEXT: FileSize: 8 +# CHECK-NEXT: MemSize: 8 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x1018 +# CHECK-NEXT: VirtualAddress: 0x1018 +# CHECK-NEXT: PhysicalAddress: 0x4000 +# CHECK-NEXT: FileSize: 9 +# CHECK-NEXT: MemSize: 9 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_GNU_STACK +# CHECK-NEXT: Offset: +# CHECK-NEXT: VirtualAddress: 0x0 +# CHECK-NEXT: PhysicalAddress: 0x0 +# CHECK-NEXT: FileSize: +# CHECK-NEXT: MemSize: +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.global _start +_start: + nop + +.section .aaa, "a" +.quad 0 + +.section .bbb, "a" +.quad 0 + +.section .ccc, "a" +.quad 0 + +.section .ddd, "a" +.quad 0 diff --git a/test/ELF/linkerscript/comdat-gc.s b/test/ELF/linkerscript/comdat-gc.s new file mode 100644 index 000000000000..63dcf85c5a67 --- /dev/null +++ b/test/ELF/linkerscript/comdat-gc.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/comdat-gc.s -o %t1 +# RUN: echo "SECTIONS { .text : { *(.text*) } }" > %t.script +# RUN: ld.lld --gc-sections --script %t.script %t %t1 -o %t2 +# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC1 %s + +# GC1: Name: .debug_line + +.file 1 "test/ELF/linkerscript/comdat_gc.s" +.section .text._Z3fooIiEvv,"axG",@progbits,_Z3fooIiEvv,comdat +.loc 1 14 + ret diff --git a/test/ELF/linkerscript/common.s b/test/ELF/linkerscript/common.s new file mode 100644 index 000000000000..2e5972d52379 --- /dev/null +++ b/test/ELF/linkerscript/common.s @@ -0,0 +1,49 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .common : { *(COMMON) } }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -s -t %t1 | FileCheck %s + +# q2 alignment is greater than q1, so it should have smaller offset +# because of sorting +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .common +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x200 +# CHECK-NEXT: Offset: 0x +# CHECK-NEXT: Size: 256 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 256 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK: Symbol { +# CHECK: Name: q1 +# CHECK-NEXT: Value: 0x280 +# CHECK-NEXT: Size: 128 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Object +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .common +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: q2 +# CHECK-NEXT: Value: 0x200 +# CHECK-NEXT: Size: 128 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Object +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .common +# CHECK-NEXT: } + +.globl _start +_start: + jmp _start + +.comm q1,128,8 +.comm q2,128,256 diff --git a/test/ELF/linkerscript/data-commands.s b/test/ELF/linkerscript/data-commands.s new file mode 100644 index 000000000000..ef154eda9f83 --- /dev/null +++ b/test/ELF/linkerscript/data-commands.s @@ -0,0 +1,81 @@ +# REQUIRES: x86,mips +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS \ +# RUN: { \ +# RUN: .foo : { \ +# RUN: *(.foo.1) \ +# RUN: BYTE(0x11) \ +# RUN: *(.foo.2) \ +# RUN: SHORT(0x1122) \ +# RUN: *(.foo.3) \ +# RUN: LONG(0x11223344) \ +# RUN: *(.foo.4) \ +# RUN: QUAD(0x1122334455667788) \ +# RUN: } \ +# RUN: .bar : { \ +# RUN: *(.bar.1) \ +# RUN: BYTE(a + 1) \ +# RUN: *(.bar.2) \ +# RUN: SHORT(b) \ +# RUN: *(.bar.3) \ +# RUN: LONG(c + 2) \ +# RUN: *(.bar.4) \ +# RUN: QUAD(d) \ +# RUN: } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t %t.o --script %t.script +# RUN: llvm-objdump -s %t | FileCheck %s + +# CHECK: Contents of section .foo: +# CHECK-NEXT: ff11ff22 11ff4433 2211ff88 77665544 +# CHECK-NEXT: 332211 + +# CHECK: Contents of section .bar: +# CHECK-NEXT: ff12ff22 11ff4633 2211ff88 77665544 +# CHECK-NEXT: 332211 + +# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %tmips64be +# RUN: ld.lld --script %t.script %tmips64be -o %t2 +# RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=BE +# BE: Contents of section .foo: +# BE-NEXT: ff11ff11 22ff1122 3344ff11 22334455 +# BE-NEXT: 667788 +# BE-NEXT: Contents of section .bar: +# BE-NEXT: ff12ff11 22ff1122 3346ff11 22334455 +# BE-NEXT: 667788 + +.global a +a = 0x11 + +.global b +b = 0x1122 + +.global c +c = 0x11223344 + +.global d +d = 0x1122334455667788 + +.section .foo.1, "a" + .byte 0xFF + +.section .foo.2, "a" + .byte 0xFF + +.section .foo.3, "a" + .byte 0xFF + +.section .foo.4, "a" + .byte 0xFF + +.section .bar.1, "a" + .byte 0xFF + +.section .bar.2, "a" + .byte 0xFF + +.section .bar.3, "a" + .byte 0xFF + +.section .bar.4, "a" + .byte 0xFF diff --git a/test/ELF/linkerscript/data-segment-relro.s b/test/ELF/linkerscript/data-segment-relro.s new file mode 100644 index 000000000000..7f69319dde7a --- /dev/null +++ b/test/ELF/linkerscript/data-segment-relro.s @@ -0,0 +1,70 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .plt : { *(.plt) } \ +# RUN: .text : { *(.text) } \ +# RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ +# RUN: .dynamic : { *(.dynamic) } \ +# RUN: .got : { *(.got) } \ +# RUN: . = DATA_SEGMENT_RELRO_END (1 ? 24 : 0, .); \ +# RUN: .got.plt : { *(.got.plt) } \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss) } \ +# RUN: . = DATA_SEGMENT_END (.); \ +# RUN: }" > %t.script + +## With relro or without DATA_SEGMENT_RELRO_END just aligns to +## page boundary. +# RUN: ld.lld -z norelro %t1.o %t2.so --script %t.script -o %t +# RUN: llvm-readobj -s %t | FileCheck %s +# RUN: ld.lld -z relro %t1.o %t2.so --script %t.script -o %t2 +# RUN: llvm-readobj -s %t2 | FileCheck %s + +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .got +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x10F0 +# CHECK-NEXT: Offset: 0x10F0 +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .got.plt +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2000 +# CHECK-NEXT: Offset: 0x2000 +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } + +.global _start +_start: + .long bar + jmp *bar2@GOTPCREL(%rip) + +.section .data,"aw" +.quad 0 + +.zero 4 +.section .foo,"aw" +.section .bss,"",@nobits diff --git a/test/ELF/linkerscript/define.s b/test/ELF/linkerscript/define.s new file mode 100644 index 000000000000..b5f0b76e9e6b --- /dev/null +++ b/test/ELF/linkerscript/define.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS \ +# RUN: { \ +# RUN: . = DEFINED(defined) ? 0x11000 : .; \ +# RUN: .foo : { *(.foo*) } \ +# RUN: . = DEFINED(notdefined) ? 0x12000 : 0x13000; \ +# RUN: .bar : { *(.bar*) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: 1 .foo 00000008 0000000000011000 DATA +# CHECK: 2 .bar 00000008 0000000000013000 DATA +# CHECK: 3 .text 00000000 0000000000013008 TEXT DATA + +.global defined +defined = 0 + +.section .foo,"a" +.quad 1 + +.section .bar,"a" +.quad 1 diff --git a/test/ELF/linkerscript/diagnostic.s b/test/ELF/linkerscript/diagnostic.s new file mode 100644 index 000000000000..bd1ebd01b5d2 --- /dev/null +++ b/test/ELF/linkerscript/diagnostic.s @@ -0,0 +1,106 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Take some valid script with multiline comments +## and check it actually works: +# RUN: echo "SECTIONS {" > %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: ld.lld -shared %t -o %t1 --script %t.script + +## Change ":" to "+" at line 2, check that error +## message starts from correct line number: +# RUN: echo "SECTIONS {" > %t.script +# RUN: echo ".text + { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR1 %s +# ERR1: {{.*}}.script:2: + +## Change ":" to "+" at line 3 now, check correct error line number: +# RUN: echo "SECTIONS {" > %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep + { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR2 %s +# ERR2: {{.*}}.script:3: + +## Change ":" to "+" at line 6, after multiline comment, +## check correct error line number: +# RUN: echo "SECTIONS {" > %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp + { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR5 %s +# ERR5: {{.*}}.script:6: + +## Check that text of lines and pointer to 'bad' token are working ok. +# RUN: echo "UNKNOWN_TAG {" > %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) }" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR6 -strict-whitespace %s +# ERR6: error: {{.*}}.script:1: +# ERR6-NEXT: error: {{.*}}.script:1: UNKNOWN_TAG { +# ERR6-NEXT: error: {{.*}}.script:1: ^ + +## One more check that text of lines and pointer to 'bad' token are working ok. +# RUN: echo "SECTIONS {" > %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) }" >> %t.script +# RUN: echo "boom .temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR7 -strict-whitespace %s +# ERR7: error: {{.*}}.script:4: malformed number: .temp +# ERR7-NEXT: error: {{.*}}.script:4: boom .temp : { *(.temp) } } +# ERR7-NEXT: error: {{.*}}.script:4: ^ + +## Check tokenize() error +# RUN: echo "SECTIONS {}" > %t.script +# RUN: echo "\"" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR8 -strict-whitespace %s +# ERR8: {{.*}}.script:2: unclosed quote + +## Check tokenize() error in included script file +# RUN: echo "SECTIONS {}" > %t.script.inc +# RUN: echo "\"" >> %t.script.inc +# RUN: echo "INCLUDE \"%t.script.inc\"" > %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR9 -strict-whitespace %s +# ERR9: {{.*}}.script.inc:2: unclosed quote + +## Check error reporting correctness for included files. +# RUN: echo "SECTIONS {" > %t.script.inc +# RUN: echo ".text : { *(.text) }" >> %t.script.inc +# RUN: echo ".keep : { *(.keep) }" >> %t.script.inc +# RUN: echo "boom .temp : { *(.temp) } }" >> %t.script.inc +# RUN: echo "INCLUDE \"%t.script.inc\"" > %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR10 -strict-whitespace %s +# ERR10: error: {{.*}}.script.inc:4: malformed number: .temp +# ERR10-NEXT: error: {{.*}}.script.inc:4: boom .temp : { *(.temp) } } +# ERR10-NEXT: error: {{.*}}.script.inc:4: ^ + +## Check error reporting in script with INCLUDE directive. +# RUN: echo "SECTIONS {" > %t.script.inc +# RUN: echo ".text : { *(.text) }" >> %t.script.inc +# RUN: echo ".keep : { *(.keep) }" >> %t.script.inc +# RUN: echo ".temp : { *(.temp) } }" >> %t.script.inc +# RUN: echo "/* One line before INCLUDE */" > %t.script +# RUN: echo "INCLUDE \"%t.script.inc\"" >> %t.script +# RUN: echo "/* One line ater INCLUDE */" >> %t.script +# RUN: echo "Error" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR11 -strict-whitespace %s +# ERR11: error: {{.*}}.script:4: unexpected EOF diff --git a/test/ELF/linkerscript/discard-interp.s b/test/ELF/linkerscript/discard-interp.s new file mode 100644 index 000000000000..261509e2e76b --- /dev/null +++ b/test/ELF/linkerscript/discard-interp.s @@ -0,0 +1,12 @@ +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/../Inputs/shared.s -o %t2.o +// RUN: ld.lld -shared %t2.o -o %t2.so +// RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; } \ +// RUN: SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } : text }" > %t.script +// RUN: ld.lld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --script %t.script --export-dynamic %t.o %t2.so -o %t +// RUN: llvm-readobj -s %t | FileCheck %s + +// CHECK-NOT: Name: .interp + +.global _start +_start: diff --git a/test/ELF/linkerscript/discard-section.s b/test/ELF/linkerscript/discard-section.s new file mode 100644 index 000000000000..a5af90806829 --- /dev/null +++ b/test/ELF/linkerscript/discard-section.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { /DISCARD/ : { *(.aaa*) } }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK-NOT: .aaa + +.section .aaa,"a" +aab: + .quad 0 + +.section .zzz,"a" + .quad aab diff --git a/test/ELF/linkerscript/dot-is-not-abs.s b/test/ELF/linkerscript/dot-is-not-abs.s new file mode 100644 index 000000000000..4532cd59f2a1 --- /dev/null +++ b/test/ELF/linkerscript/dot-is-not-abs.s @@ -0,0 +1,53 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { .text : { *(.text) } \ +# RUN: foo = .; \ +# RUN: .bar : { *(.bar) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared +# RUN: llvm-readobj -t -s -section-data %t1 | FileCheck %s + +.hidden foo +.long foo - . + +.section .bar, "a" +.long 0 + +# The symbol foo is defined as a position in the file. This means that it is +# not absolute and it is possible to compute the distance from foo to some other +# position in the file. The symbol is not really in any output section, but +# ELF has no magic constant for not absolute, but not in any section. +# Fortunately the value of a symbol in a non relocatable file is a virtual +# address, so the section can be arbitrary. + +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .text +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 04000000 | +# CHECK-NEXT: ) +# CHECK-NEXT: } + +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: 0x4 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other [ +# CHECK-NEXT: STV_HIDDEN +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } diff --git a/test/ELF/linkerscript/double-bss.s b/test/ELF/linkerscript/double-bss.s new file mode 100644 index 000000000000..c24332f5e5a6 --- /dev/null +++ b/test/ELF/linkerscript/double-bss.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; " > %t.script +# RUN: echo ".text : { *(.text*) }" >> %t.script +# RUN: echo ".bss1 : { *(.bss) }" >> %t.script +# RUN: echo ".bss2 : { *(COMMON) }" >> %t.script +# RUN: echo "}" >> %t.script + +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s +# CHECK: .bss1 00000004 0000000000000122 BSS +# CHECK-NEXT: .bss2 00000080 0000000000000128 BSS + +.globl _start +_start: + jmp _start + +.bss +.zero 4 + +.comm q,128,8 diff --git a/test/ELF/linkerscript/dynamic-sym.s b/test/ELF/linkerscript/dynamic-sym.s new file mode 100644 index 000000000000..e3193b1a765d --- /dev/null +++ b/test/ELF/linkerscript/dynamic-sym.s @@ -0,0 +1,17 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "_DYNAMIC = 0x123;" > %t.script +# RUN: ld.lld -T %t.script %t.o -shared -o %t.so +# RUN: llvm-readobj -t %t.so | FileCheck %s + +# CHECK: Symbol { +# CHECK: Name: _DYNAMIC +# CHECK-NEXT: Value: 0x123 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other [ +# CHECK-NEXT: STV_HIDDEN +# CHECK-NEXT: ] +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } diff --git a/test/ELF/linkerscript/dynamic.s b/test/ELF/linkerscript/dynamic.s new file mode 100644 index 000000000000..ab65ab831f8f --- /dev/null +++ b/test/ELF/linkerscript/dynamic.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so + +# RUN: echo "SECTIONS { }" > %t.script +# RUN: ld.lld %t1.o %t2.so -o %t +# RUN: llvm-readobj -dynamic-table %t | FileCheck %s + +# CHECK: DynamicSection [ +# CHECK-NEXT: Tag Type Name/Value +# CHECK: 0x0000000000000021 PREINIT_ARRAYSZ 9 (bytes) +# CHECK: 0x000000000000001B INIT_ARRAYSZ 8 (bytes) +# CHECK: 0x000000000000001C FINI_ARRAYSZ 10 (bytes) + +.globl _start +_start: + +.section .init_array,"aw",@init_array + .quad 0 + +.section .preinit_array,"aw",@preinit_array + .quad 0 + .byte 0 + +.section .fini_array,"aw",@fini_array + .quad 0 + .short 0 diff --git a/test/ELF/linkerscript/edata-etext.s b/test/ELF/linkerscript/edata-etext.s new file mode 100644 index 000000000000..fdf5ec1f5671 --- /dev/null +++ b/test/ELF/linkerscript/edata-etext.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { }" > %t.script +# RUN: not ld.lld %t.o -script %t.script -o %t 2>&1 | FileCheck %s +# CHECK: error: {{.*}}:(.text+0x0): undefined symbol '_edata' +# CHECK: error: {{.*}}:(.text+0x8): undefined symbol '_etext' +# CHECK: error: {{.*}}:(.text+0x10): undefined symbol '_end' + +.global _start,_end,_etext,_edata +.text +_start: + .quad _edata + 0x1 + .quad _etext + 0x1 + .quad _end + 0x1 + +.data + .word 1 +.bss + .align 4 + .space 6 diff --git a/test/ELF/linkerscript/eh-frame-hdr.s b/test/ELF/linkerscript/eh-frame-hdr.s new file mode 100644 index 000000000000..d1545be632a3 --- /dev/null +++ b/test/ELF/linkerscript/eh-frame-hdr.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .eh_frame_hdr : {} \ +# RUN: .eh_frame : {} \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -s -section=".eh_frame_hdr" %t1 | FileCheck %s + +# CHECK: 011b033b 14000000 01000000 49000000 +# CHECK-NEXT: 30000000 + +.global _start +_start: + nop + +.section .dah,"ax",@progbits +.cfi_startproc + nop +.cfi_endproc diff --git a/test/ELF/linkerscript/ehdr_start.s b/test/ELF/linkerscript/ehdr_start.s new file mode 100644 index 000000000000..0ae4a4dcfbc9 --- /dev/null +++ b/test/ELF/linkerscript/ehdr_start.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { }" > %t.script +# RUN: not ld.lld %t.o -script %t.script -o %t 2>&1 | FileCheck %s +# CHECK: error: {{.*}}:(.text+0x0): undefined symbol '__ehdr_start' + +.text +.global _start, __ehdr_start +_start: + .quad __ehdr_start diff --git a/test/ELF/linkerscript/empty-load.s b/test/ELF/linkerscript/empty-load.s new file mode 100644 index 000000000000..0a87d5727474 --- /dev/null +++ b/test/ELF/linkerscript/empty-load.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { .rw : { *(.rw) } .text : { *(.text) } }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -private-headers %t1 | FileCheck %s + +## We expect 2 PT_LOAD segments +# CHECK: PHDR +# CHECK-NEXT: filesz {{0x[0-9a-f]+}} memsz {{0x[0-9a-f]+}} flags r-- +# CHECK-NEXT: LOAD +# CHECK-NEXT: filesz {{0x[0-9a-f]+}} memsz {{0x[0-9a-f]+}} flags rw- +# CHECK-NEXT: LOAD +# CHECK-NEXT: filesz {{0x[0-9a-f]+}} memsz {{0x[0-9a-f]+}} flags r-x +# CHECK-NEXT: STACK +# CHECK-NEXT: filesz + +.globl _start +_start: + jmp _start + +.section .rw, "aw" + .quad 0 diff --git a/test/ELF/linkerscript/empty-tls.s b/test/ELF/linkerscript/empty-tls.s new file mode 100644 index 000000000000..919ccbffbe43 --- /dev/null +++ b/test/ELF/linkerscript/empty-tls.s @@ -0,0 +1,14 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: echo "PHDRS { ph_tls PT_TLS; }" > %t.script +// RUN: ld.lld -o %t.so -T %t.script %t.o -shared +// RUN: llvm-readobj -l %t.so | FileCheck %s + +// test that we don't crash with an empty PT_TLS + +// CHECK: Type: PT_TLS +// CHECK-NEXT: Offset: 0x0 +// CHECK-NEXT: VirtualAddress: 0x0 +// CHECK-NEXT: PhysicalAddress: 0x0 +// CHECK-NEXT: FileSize: 0 +// CHECK-NEXT: MemSize: 0 diff --git a/test/ELF/linkerscript/entry.s b/test/ELF/linkerscript/entry.s new file mode 100644 index 000000000000..d75b1345a8aa --- /dev/null +++ b/test/ELF/linkerscript/entry.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "ENTRY(_label)" > %t.script +# RUN: ld.lld -o %t2 %t.script %t +# RUN: llvm-readobj %t2 > /dev/null + +# The entry symbol should not cause an undefined error. +# RUN: echo "ENTRY(_wrong_label)" > %t.script +# RUN: ld.lld -o %t2 %t.script %t +# RUN: ld.lld --entry=abc -o %t2 %t + +# -e has precedence over linker script's ENTRY. +# RUN: echo "ENTRY(_label)" > %t.script +# RUN: ld.lld -e _start -o %t2 %t.script %t +# RUN: llvm-readobj -file-headers -symbols %t2 | \ +# RUN: FileCheck -check-prefix=OVERLOAD %s + +# OVERLOAD: Entry: [[ENTRY:0x[0-9A-F]+]] +# OVERLOAD: Name: _start +# OVERLOAD-NEXT: Value: [[ENTRY]] + +# The entry symbol can be a linker-script-defined symbol. +# RUN: echo "ENTRY(foo); foo = 1;" > %t.script +# RUN: ld.lld -o %t2 %t.script %t +# RUN: llvm-readobj -file-headers -symbols %t2 | \ +# RUN: FileCheck -check-prefix=SCRIPT %s + +# SCRIPT: Entry: 0x1 + +# RUN: echo "ENTRY(no_such_symbol);" > %t.script +# RUN: ld.lld -o %t2 %t.script %t 2>&1 | \ +# RUN: FileCheck -check-prefix=MISSING %s + +# MISSING: warning: cannot find entry symbol no_such_symbol + +.globl _start, _label +_start: + ret +_label: + ret diff --git a/test/ELF/linkerscript/exclude-multiple.s b/test/ELF/linkerscript/exclude-multiple.s new file mode 100644 index 000000000000..46ec18cfa125 --- /dev/null +++ b/test/ELF/linkerscript/exclude-multiple.s @@ -0,0 +1,37 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple1.s -o %tfile2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple2.s -o %tfile3.o +# RUN: echo "SECTIONS { \ +# RUN: .foo : { *(.foo.1 EXCLUDE_FILE (*file1.o) .foo.2 EXCLUDE_FILE (*file2.o) .foo.3) } \ +# RUN: }" > %t1.script +# RUN: ld.lld -script %t1.script %tfile1.o %tfile2.o %tfile3.o -o %t1.o +# RUN: llvm-objdump -s %t1.o | FileCheck %s + +# CHECK: Contents of section .foo: +# CHECK-NEXT: 01000000 00000000 04000000 00000000 +# CHECK-NEXT: 07000000 00000000 05000000 00000000 +# CHECK-NEXT: 08000000 00000000 03000000 00000000 +# CHECK-NEXT: 09000000 00000000 +# CHECK-NEXT: Contents of section .foo.2: +# CHECK-NEXT: 02000000 00000000 +# CHECK-NEXT: Contents of section .foo.3: +# CHECK-NEXT: 06000000 00000000 + +# RUN: echo "SECTIONS { .foo : { *(EXCLUDE_FILE (*file1.o) EXCLUDE_FILE (*file2.o) .foo.3) } }" > %t2.script +# RUN: not ld.lld -script %t2.script %tfile1.o %tfile2.o %tfile3.o -o %t2.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR +# ERR: section pattern is expected + +# RUN: echo "SECTIONS { .foo : { *(EXCLUDE_FILE (*file1.o)) } }" > %t3.script +# RUN: not ld.lld -script %t3.script %tfile1.o %tfile2.o %tfile3.o -o %t2.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR + +.section .foo.1,"a" + .quad 1 + +.section .foo.2,"a" + .quad 2 + +.section .foo.3,"a" + .quad 3 diff --git a/test/ELF/linkerscript/excludefile.s b/test/ELF/linkerscript/excludefile.s new file mode 100644 index 000000000000..8a154354dbc2 --- /dev/null +++ b/test/ELF/linkerscript/excludefile.s @@ -0,0 +1,46 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/include.s -o %t2 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/notinclude.s -o %t3.notinclude + +# RUN: echo "SECTIONS {} " > %t.script +# RUN: ld.lld -o %t --script %t.script %t1 %t2 %t3.notinclude +# RUN: llvm-objdump -d %t | FileCheck %s + +# CHECK: Disassembly of section .text: +# CHECK: _start: +# CHECK-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax +# CHECK-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi +# CHECK-NEXT: : 00 00 addb %al, (%rax) +# CHECK: _potato: +# CHECK-NEXT: : 90 nop +# CHECK-NEXT: : 90 nop +# CHECK-NEXT: : 00 00 addb %al, (%rax) +# CHECK: tomato: +# CHECK-NEXT: : b8 01 00 00 00 movl $1, %eax + +# RUN: echo "SECTIONS { .patatino : \ +# RUN: { KEEP(*(EXCLUDE_FILE(*notinclude) .text)) } }" \ +# RUN: > %t.script +# RUN: ld.lld -o %t4 --script %t.script %t1 %t2 %t3.notinclude +# RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=EXCLUDE + +# EXCLUDE: Disassembly of section .patatino: +# EXCLUDE: _start: +# EXCLUDE-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax +# EXCLUDE-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi +# EXCLUDE-NEXT: : 00 00 addb %al, (%rax) +# EXCLUDE: _potato: +# EXCLUDE-NEXT: : 90 nop +# EXCLUDE-NEXT: : 90 nop +# EXCLUDE: Disassembly of section .text: +# EXCLUDE: tomato: +# EXCLUDE-NEXT: : b8 01 00 00 00 movl $1, %eax + +.section .text +.globl _start +_start: + mov $60, %rax + mov $42, %rdi diff --git a/test/ELF/linkerscript/extend-pt-load.s b/test/ELF/linkerscript/extend-pt-load.s new file mode 100644 index 000000000000..f9a77c8c12bf --- /dev/null +++ b/test/ELF/linkerscript/extend-pt-load.s @@ -0,0 +1,69 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# This test demonstrates an odd consequence of the way we handle sections with just symbol +# assignments. + +# First, run a test with no such section. + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .dynsym : { } \ +# RUN: .hash : { } \ +# RUN: .dynstr : { } \ +# RUN: .text : { *(.text) } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: .data.rel.ro : { *(.data.rel.ro) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t.o -shared +# RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck --check-prefix=CHECK1 %s + +# CHECK1: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX +# CHECK1-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA + +# CHECK1: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0001bd 0x0001bd R E +# CHECK1-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW + +# Then add the section bar. Note how bar is given AX flags, which causes the PT_LOAD to now +# cover the padding bits created by ALIGN. + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .dynsym : { } \ +# RUN: .hash : { } \ +# RUN: .dynstr : { } \ +# RUN: .text : { *(.text) } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: bar : { HIDDEN(bar_sym = .); } \ +# RUN: .data.rel.ro : { *(.data.rel.ro) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t2 --script %t.script %t.o -shared +# RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck --check-prefix=CHECK2 %s + +# CHECK2: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX +# CHECK2-NEXT: bar PROGBITS 0000000000001000 001000 000000 00 AX +# CHECK2-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA + +# CHECK2: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001000 0x001000 R E +# CHECK2-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW + +# If the current behavior becomes a problem we should consider just moving the commands out +# of the section. That is, handle the above like the following test. + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .dynsym : { } \ +# RUN: .hash : { } \ +# RUN: .dynstr : { } \ +# RUN: .text : { *(.text) } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: HIDDEN(bar_sym = .); \ +# RUN: .data.rel.ro : { *(.data.rel.ro) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t3 --script %t.script %t.o -shared +# RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck --check-prefix=CHECK1 %s + +nop + +.section .data.rel.ro, "aw" +.byte 0 diff --git a/test/ELF/linkerscript/filename-spec.s b/test/ELF/linkerscript/filename-spec.s new file mode 100644 index 000000000000..d4bc495efb81 --- /dev/null +++ b/test/ELF/linkerscript/filename-spec.s @@ -0,0 +1,59 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfirst.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/filename-spec.s -o %tsecond.o + +# RUN: echo "SECTIONS { .foo : { \ +# RUN: KEEP(*first.o(.foo)) \ +# RUN: KEEP(*second.o(.foo)) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %tfirst.o %tsecond.o +# RUN: llvm-objdump -s %t1 | FileCheck --check-prefix=FIRSTSECOND %s +# FIRSTSECOND: Contents of section .foo: +# FIRSTSECOND-NEXT: 01000000 00000000 11000000 00000000 + +# RUN: echo "SECTIONS { .foo : { \ +# RUN: KEEP(*second.o(.foo)) \ +# RUN: KEEP(*first.o(.foo)) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %tfirst.o %tsecond.o +# RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=SECONDFIRST %s +# SECONDFIRST: Contents of section .foo: +# SECONDFIRST-NEXT: 11000000 00000000 01000000 00000000 + +## Now the same tests but without KEEP. Checking that file name inside +## KEEP is parsed fine. +# RUN: echo "SECTIONS { .foo : { \ +# RUN: *first.o(.foo) \ +# RUN: *second.o(.foo) } }" > %t3.script +# RUN: ld.lld -o %t3 --script %t3.script %tfirst.o %tsecond.o +# RUN: llvm-objdump -s %t3 | FileCheck --check-prefix=FIRSTSECOND %s + +# RUN: echo "SECTIONS { .foo : { \ +# RUN: *second.o(.foo) \ +# RUN: *first.o(.foo) } }" > %t4.script +# RUN: ld.lld -o %t4 --script %t4.script %tfirst.o %tsecond.o +# RUN: llvm-objdump -s %t4 | FileCheck --check-prefix=SECONDFIRST %s + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %T/filename-spec1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/filename-spec.s -o %T/filename-spec2.o + +# RUN: echo "SECTIONS { .foo : { \ +# RUN: filename-spec2.o(.foo) \ +# RUN: filename-spec1.o(.foo) } }" > %t5.script +# RUN: ld.lld -o %t5 --script %t5.script \ +# RUN: %T/filename-spec1.o %T/filename-spec2.o +# RUN: llvm-objdump -s %t5 | FileCheck --check-prefix=SECONDFIRST %s + +# RUN: echo "SECTIONS { .foo : { \ +# RUN: filename-spec1.o(.foo) \ +# RUN: filename-spec2.o(.foo) } }" > %t6.script +# RUN: ld.lld -o %t6 --script %t6.script \ +# RUN: %T/filename-spec1.o %T/filename-spec2.o +# RUN: llvm-objdump -s %t6 | FileCheck --check-prefix=FIRSTSECOND %s + +.global _start +_start: + nop + +.section .foo,"a" + .quad 1 diff --git a/test/ELF/linkerscript/fill.s b/test/ELF/linkerscript/fill.s new file mode 100644 index 000000000000..57a19e0943d0 --- /dev/null +++ b/test/ELF/linkerscript/fill.s @@ -0,0 +1,30 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: .out : { \ +# RUN: FILL(0x11111111); \ +# RUN: *(.aaa) \ +# RUN: . += 4; \ +# RUN: *(.bbb) \ +# RUN: . += 4; \ +# RUN: FILL(0x22222222); \ +# RUN: . += 4; \ +# RUN: } \ +# RUN: }; " > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-objdump -s %t | FileCheck %s + +# CHECK: Contents of section .out: +# CHECK-NEXT: aa222222 22bb2222 22222222 2222 + +.text +.globl _start +_start: + +.section .aaa, "a" +.align 1 +.byte 0xAA + +.section .bbb, "a" +.align 1 +.byte 0xBB diff --git a/test/ELF/linkerscript/group.s b/test/ELF/linkerscript/group.s new file mode 100644 index 000000000000..53a1c89ebfe3 --- /dev/null +++ b/test/ELF/linkerscript/group.s @@ -0,0 +1,56 @@ +# REQUIRES: x86 + +# RUN: mkdir -p %t.dir +# RUN: rm -f %t.dir/libxyz.a +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/libsearch-st.s -o %t2.o +# RUN: llvm-ar rcs %t.dir/libxyz.a %t2.o + +# RUN: echo "GROUP(\"%t\")" > %t.script +# RUN: ld.lld -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "INPUT(\"%t\")" > %t.script +# RUN: ld.lld -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t\" libxyz.a )" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>/dev/null +# RUN: ld.lld -o %t2 %t.script -L%t.dir +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t\" =libxyz.a )" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>/dev/null +# RUN: ld.lld -o %t2 %t.script --sysroot=%t.dir +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t\" -lxyz )" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>/dev/null +# RUN: ld.lld -o %t2 %t.script -L%t.dir +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t\" libxyz.a )" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>/dev/null +# RUN: ld.lld -o %t2 %t.script -L%t.dir +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t\" /libxyz.a )" > %t.script +# RUN: echo "GROUP(\"%t\" /libxyz.a )" > %t.dir/xyz.script +# RUN: not ld.lld -o %t2 %t.script 2>/dev/null +# RUN: not ld.lld -o %t2 %t.script --sysroot=%t.dir 2>/dev/null +# RUN: ld.lld -o %t2 %t.dir/xyz.script --sysroot=%t.dir +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(\"%t.script2\")" > %t.script1 +# RUN: echo "GROUP(\"%t\")" > %t.script2 +# RUN: ld.lld -o %t2 %t.script1 +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "GROUP(AS_NEEDED(\"%t\"))" > %t.script +# RUN: ld.lld -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +.globl _start +_start: + ret diff --git a/test/ELF/linkerscript/header-addr.s b/test/ELF/linkerscript/header-addr.s new file mode 100644 index 000000000000..f37d319aaabe --- /dev/null +++ b/test/ELF/linkerscript/header-addr.s @@ -0,0 +1,47 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "PHDRS {all PT_LOAD PHDRS;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x2000; \ +# RUN: .text : {*(.text)} :all \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t.so --script %t.script %t.o -shared +# RUN: llvm-readobj -program-headers %t.so | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x40 +# CHECK-NEXT: VirtualAddress: 0x1040 +# CHECK-NEXT: PhysicalAddress: 0x1040 +# CHECK-NEXT: FileSize: 4176 +# CHECK-NEXT: MemSize: 4176 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# RUN: ld.lld -o %t2.so --script %t.script %t.o -shared -z max-page-size=0x2000 +# RUN: llvm-readobj -program-headers %t2.so \ +# RUN: | FileCheck --check-prefix=MAXPAGE %s + +# MAXPAGE: ProgramHeaders [ +# MAXPAGE-NEXT: ProgramHeader { +# MAXPAGE-NEXT: Type: PT_LOAD +# MAXPAGE-NEXT: Offset: 0x40 +# MAXPAGE-NEXT: VirtualAddress: 0x40 +# MAXPAGE-NEXT: PhysicalAddress: 0x40 +# MAXPAGE-NEXT: FileSize: 8272 +# MAXPAGE-NEXT: MemSize: 8272 +# MAXPAGE-NEXT: Flags [ +# MAXPAGE-NEXT: PF_R +# MAXPAGE-NEXT: PF_W +# MAXPAGE-NEXT: PF_X +# MAXPAGE-NEXT: ] +# MAXPAGE-NEXT: Alignment: 8192 +# MAXPAGE-NEXT: } +# MAXPAGE-NEXT: ] diff --git a/test/ELF/linkerscript/implicit-program-header.s b/test/ELF/linkerscript/implicit-program-header.s new file mode 100644 index 000000000000..9598a6abebb0 --- /dev/null +++ b/test/ELF/linkerscript/implicit-program-header.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld -o %t1 --script %S/Inputs/implicit-program-header.script \ +# RUN: %t.o -shared +# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s + +# CHECK: Segment Sections... +# CHECK-NEXT: 00 .text .dynsym .hash .dynstr .dynamic +# CHECK-NEXT: 01 .foo + +.quad 0 +.section .foo,"ax" +.quad 0 diff --git a/test/ELF/linkerscript/input-order.s b/test/ELF/linkerscript/input-order.s new file mode 100644 index 000000000000..cb9ea354cdbf --- /dev/null +++ b/test/ELF/linkerscript/input-order.s @@ -0,0 +1,38 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# This test case should place input sections in script order: +# .foo.1 .foo.2 .bar.1 .bar.2 +# RUN: echo "SECTIONS { . = 0x1000; .foo : {*(.foo.*) *(.bar.*) } }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section=.foo -s %t1 | FileCheck --check-prefix=SCRIPT_ORDER %s +# SCRIPT_ORDER: Contents of section .foo: +# SCRIPT_ORDER-NEXT: 1000 00000000 00000000 ffffffff eeeeeeee + +# This test case should place input sections in native order: +# .bar.1 .foo.1 .bar.2 .foo.2 +# RUN: echo "SECTIONS { . = 0x1000; .foo : {*(.foo.* .bar.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section=.foo -s %t1 | FileCheck --check-prefix=FILE_ORDER %s +# FILE_ORDER: Contents of section .foo: +# FILE_ORDER-NEXT: 1000 ffffffff 00000000 eeeeeeee 00000000 + +.global _start +_start: + nop + +.section .bar.1,"a" +bar1: + .long 0xFFFFFFFF + +.section .foo.1,"a" +foo1: + .long 0 + +.section .bar.2,"a" +bar2: + .long 0xEEEEEEEE + +.section .foo.2,"a" +foo2: + .long 0 diff --git a/test/ELF/linkerscript/input-sec-dup.s b/test/ELF/linkerscript/input-sec-dup.s new file mode 100644 index 000000000000..fd889393c74c --- /dev/null +++ b/test/ELF/linkerscript/input-sec-dup.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS {.foo : { *(.foo) *(.foo) } }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size +# CHECK-NEXT: 0 00000000 +# CHECK-NEXT: 1 .foo 00000004 +# CHECK-NEXT: 2 .text 00000001 + +.global _start +_start: + nop + +.section .foo,"a" + .long 0 diff --git a/test/ELF/linkerscript/linkerscript.s b/test/ELF/linkerscript/linkerscript.s new file mode 100644 index 000000000000..cac902af4270 --- /dev/null +++ b/test/ELF/linkerscript/linkerscript.s @@ -0,0 +1,54 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/libsearch-st.s -o %t2.o + +# RUN: echo "EXTERN( undef undef2 )" > %t.script +# RUN: ld.lld %t -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "OUTPUT_FORMAT(elf64-x86-64) /*/*/ GROUP(\"%t\" )" > %t.script +# RUN: ld.lld -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: rm -f %t.out +# RUN: echo "OUTPUT(\"%t.out\")" > %t.script +# RUN: ld.lld %t.script %t +# RUN: llvm-readobj %t.out > /dev/null + +# RUN: echo "SEARCH_DIR(/lib/foo/blah)" > %t.script +# RUN: ld.lld %t.script %t +# RUN: llvm-readobj %t.out > /dev/null + +# RUN: echo ";SEARCH_DIR(x);SEARCH_DIR(y);" > %t.script +# RUN: ld.lld %t.script %t +# RUN: llvm-readobj %t.out > /dev/null + +# RUN: echo ";" > %t.script +# RUN: ld.lld %t.script %t +# RUN: llvm-readobj %t.out > /dev/null + +# RUN: echo "INCLUDE \"%t.script2\" OUTPUT(\"%t.out\")" > %t.script1 +# RUN: echo "GROUP(\"%t\")" > %t.script2 +# RUN: ld.lld %t.script1 +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "INCLUDE \"foo.script\"" > %t.script +# RUN: echo "OUTPUT(\"%t.out\")" > %T/foo.script +# RUN: not ld.lld %t.script > %t.log 2>&1 +# RUN: FileCheck -check-prefix=INCLUDE_ERR %s < %t.log +# INCLUDE_ERR: error: {{.+}}.script:1: cannot open foo.script +# INCLUDE_ERR-NEXT: error: {{.+}}.script:1: INCLUDE "foo.script" +# RUN: ld.lld -L %T %t.script %t + +# RUN: echo "FOO(BAR)" > %t.script +# RUN: not ld.lld -o foo %t.script > %t.log 2>&1 +# RUN: FileCheck -check-prefix=ERR1 %s < %t.log + +# ERR1: unknown directive: FOO + +.globl _start, _label +_start: + ret +_label: + ret diff --git a/test/ELF/linkerscript/loadaddr.s b/test/ELF/linkerscript/loadaddr.s new file mode 100644 index 000000000000..33c5f21b52ba --- /dev/null +++ b/test/ELF/linkerscript/loadaddr.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; \ +# RUN: .aaa : AT(0x2000) { *(.aaa) } \ +# RUN: .bbb : { *(.bbb) } \ +# RUN: .ccc : AT(0x3000) { *(.ccc) } \ +# RUN: .ddd : AT(0x4000) { *(.ddd) } \ +# RUN: .text : { *(.text) } \ +# RUN: aaa_lma = LOADADDR(.aaa); \ +# RUN: bbb_lma = LOADADDR(.bbb); \ +# RUN: ccc_lma = LOADADDR(.ccc); \ +# RUN: ddd_lma = LOADADDR(.ddd); \ +# RUN: txt_lma = LOADADDR(.text); \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-objdump -t %t2 | FileCheck %s +# RUN: echo "SECTIONS { v = LOADADDR(.zzz); }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | FileCheck --check-prefix=ERROR %s + +# CHECK: 0000000000002000 *ABS* 00000000 aaa_lma +# CHECK-NEXT: 0000000000002008 *ABS* 00000000 bbb_lma +# CHECK-NEXT: 0000000000003000 *ABS* 00000000 ccc_lma +# CHECK-NEXT: 0000000000004000 *ABS* 00000000 ddd_lma +# CHECK-NEXT: 0000000000004008 *ABS* 00000000 txt_lma +# ERROR: {{.*}}.script:1: undefined section .zzz + +.global _start +_start: + nop + +.section .aaa, "a" +.quad 0 + +.section .bbb, "a" +.quad 0 + +.section .ccc, "a" +.quad 0 + +.section .ddd, "a" +.quad 0 diff --git a/test/ELF/linkerscript/locationcounter.s b/test/ELF/linkerscript/locationcounter.s new file mode 100644 index 000000000000..c57a17c5c9cb --- /dev/null +++ b/test/ELF/linkerscript/locationcounter.s @@ -0,0 +1,189 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0xFFF0; \ +# RUN: . = . + 0x10; \ +# RUN: .plus : { *(.plus) } \ +# RUN: . = 0x11010 - 0x10; \ +# RUN: .minus : { *(.minus) } \ +# RUN: . = 0x24000 / 0x2; \ +# RUN: .div : { *(.div) } \ +# RUN: . = 0x11000 + 0x1000 * 0x2; \ +# RUN: .mul : { *(.mul) } \ +# RUN: . = 0x10000 + (0x1000 + 0x1000) * 0x2; \ +# RUN: .bracket : { *(.bracket) } \ +# RUN: . = 0x17000 & 0x15000; \ +# RUN: .and : { *(.and) } \ +# RUN: . = 0x1 ? 0x16000 : 0x999999; \ +# RUN: .ternary1 : { *(.ternary1) } \ +# RUN: . = 0x0 ? 0x999999 : 0x17000; \ +# RUN: .ternary2 : { *(.ternary2) } \ +# RUN: . = 0x0 < 0x1 ? 0x18000 : 0x999999; \ +# RUN: .less : { *(.less) } \ +# RUN: . = 0x1 <= 0x1 ? 0x19000 : 0x999999; \ +# RUN: .lesseq : { *(.lesseq) } \ +# RUN: . = 0x1 > 0x0 ? 0x20000 : 0x999999; \ +# RUN: .great : { *(.great) } \ +# RUN: . = 0x1 >= 0x1 ? 0x21000 : 0x999999; \ +# RUN: .greateq : { *(.greateq) } \ +# RUN: . = 0x1 == 0x1 ? 0x22000 : 0x999999; \ +# RUN: .eq : { *(.eq) } \ +# RUN: . = 0x2 != 0x1 ? 0x23000 : 0x999999; \ +# RUN: .neq : { *(.neq) } \ +# RUN: . = CONSTANT (MAXPAGESIZE) * 0x24; \ +# RUN: .maxpagesize : { *(.maxpagesize) } \ +# RUN: . = CONSTANT (COMMONPAGESIZE) * 0x25; \ +# RUN: .commonpagesize : { *(.commonpagesize) } \ +# RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ +# RUN: .datasegmentalign : { *(.datasegmentalign) } \ +# RUN: . = DATA_SEGMENT_END (.); \ +# RUN: . = 0x27000; \ +# RUN: . += 0x1000; \ +# RUN: .plusassign : { *(.plusassign) } \ +# RUN: . = ((. + 0x1fff) & ~(0x1000 + -1)); \ +# RUN: .unary : { *(.unary) } \ +# RUN: . = 0x30000 + (1 + 1 << 5); \ +# RUN: .shiftl : { *(.shiftl) } \ +# RUN: . = 0x30000 + (1 + 1023 >> 2); \ +# RUN: .shiftr : { *(.shiftr) } \ + +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s + +# CHECK: .plus {{.*}} 0000000000010000 +# CHECK: .minus {{.*}} 0000000000011000 +# CHECK: .div {{.*}} 0000000000012000 +# CHECK: .mul {{.*}} 0000000000013000 +# CHECK: .bracket {{.*}} 0000000000014000 +# CHECK: .and {{.*}} 0000000000015000 +# CHECK: .ternary1 {{.*}} 0000000000016000 +# CHECK: .ternary2 {{.*}} 0000000000017000 +# CHECK: .less {{.*}} 0000000000018000 +# CHECK: .lesseq {{.*}} 0000000000019000 +# CHECK: .great {{.*}} 0000000000020000 +# CHECK: .greateq {{.*}} 0000000000021000 +# CHECK: .eq {{.*}} 0000000000022000 +# CHECK: .neq {{.*}} 0000000000023000 +# CHECK: .maxpagesize {{.*}} 0000000000024000 +# CHECK: .commonpagesize {{.*}} 0000000000025000 +# CHECK: .datasegmentalign {{.*}} 0000000000026000 +# CHECK: .plusassign {{.*}} 0000000000028000 +# CHECK: .unary {{.*}} 000000000002a000 +# CHECK: .shiftl {{.*}} 0000000000030040 +# CHECK: .shiftr {{.*}} 0000000000030100 + +## Mailformed number error. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x12Q41; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=NUMERR %s +# NUMERR: malformed number: 0x12Q41 + +## Missing closing bracket. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000 + (0x1000 + 0x1000 * 0x2; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=BRACKETERR %s +# BRACKETERR: ) expected, but got ; + +## Missing opening bracket. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000 + 0x1000 + 0x1000) * 0x2; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=BRACKETERR2 %s +# BRACKETERR2: ; expected, but got ) + +## Empty expression. +# RUN: echo "SECTIONS { \ +# RUN: . = ; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=ERREXPR %s +# ERREXPR: malformed number: ; + +## Div by zero error. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000 / 0x0; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=DIVZERO %s +# DIVZERO: division by zero + +## Broken ternary operator expression. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1 ? 0x2; \ +# RUN: }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=TERNERR %s +# TERNERR: : expected, but got ; + +.globl _start +_start: +nop + +.section .plus, "a" +.quad 0 + +.section .minus, "a" +.quad 0 + +.section .div, "a" +.quad 0 + +.section .mul, "a" +.quad 0 + +.section .bracket, "a" +.quad 0 + +.section .and, "a" +.quad 0 + +.section .ternary1, "a" +.quad 0 + +.section .ternary2, "a" +.quad 0 + +.section .less, "a" +.quad 0 + +.section .lesseq, "a" +.quad 0 + +.section .great, "a" +.quad 0 + +.section .greateq, "a" +.quad 0 + +.section .eq, "a" +.quad 0 + +.section .neq, "a" +.quad 0 + +.section .maxpagesize, "a" +.quad 0 + +.section .commonpagesize, "a" +.quad 0 + +.section .datasegmentalign, "a" +.quad 0 + +.section .plusassign, "a" +.quad 0 + +.section .unary, "a" +.quad 0 + +.section .shiftl, "a" +.quad 0 + +.section .shiftr, "a" +.quad 0 diff --git a/test/ELF/linkerscript/locationcountererr.s b/test/ELF/linkerscript/locationcountererr.s new file mode 100644 index 000000000000..7664d8d46917 --- /dev/null +++ b/test/ELF/linkerscript/locationcountererr.s @@ -0,0 +1,9 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { .text 0x2000 : {. = 0x10 ; *(.text) } }" > %t.script +# RUN: not ld.lld %t --script %t.script -o %t1 2>&1 | FileCheck %s +# CHECK: unable to move location counter backward for: .text + +.globl _start +_start: +nop diff --git a/test/ELF/linkerscript/merge-sections-reloc.s b/test/ELF/linkerscript/merge-sections-reloc.s new file mode 100644 index 000000000000..639341540350 --- /dev/null +++ b/test/ELF/linkerscript/merge-sections-reloc.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/merge-sections-reloc.s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o +# RUN: echo "SECTIONS {}" > %t.script +# RUN: ld.lld -o %t --script %t.script %t1.o %t2.o +# RUN: llvm-objdump -s %t | FileCheck %s + +## Check that sections content is not corrupted. +# CHECK: Contents of section .text: +# CHECK-NEXT: 44332211 00000000 44332211 00000000 +# CHECK-NEXT: f0ffffff ffffffff + +.globl _start +_foo: + .quad 0x11223344 + .quad _start - . diff --git a/test/ELF/linkerscript/merge-sections.s b/test/ELF/linkerscript/merge-sections.s new file mode 100644 index 000000000000..7252fe576674 --- /dev/null +++ b/test/ELF/linkerscript/merge-sections.s @@ -0,0 +1,94 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .foo : { begin = .; *(.foo.*) end = .;} \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-readobj -s -t %t1 | FileCheck %s + +# CHECK: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_MERGE +# CHECK-NEXT: SHF_STRINGS +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x[[ADDR1:.*]] +# CHECK-NEXT: Offset: 0x[[ADDR1]] +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_MERGE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x +# CHECK-NEXT: Offset: 0x +# CHECK-NEXT: Size: 1 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_MERGE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x +# CHECK-NEXT: Offset: 0x +# CHECK-NEXT: Size: 2 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 2 +# CHECK-NEXT: EntrySize: 2 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: +# CHECK-NEXT: Type: +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x[[ADDR2:.*]] +# CHECK-NEXT: Offset: 0x[[ADDR2]] + + +# CHECK: Name: begin +# CHECK-NEXT: Value: 0x[[ADDR1]] + +# CHECK: Name: end +# CHECK-NEXT: Value: 0x[[ADDR2]] + +.section .foo.1a,"aMS",@progbits,1 +.asciz "foo" + +.section .foo.1b,"aMS",@progbits,1 +.asciz "foo" + +.section .foo.2a,"aM",@progbits,1 +.byte 42 + +.section .foo.2b,"aM",@progbits,1 +.byte 42 + +.section .foo.3a,"aM",@progbits,2 +.align 2 +.short 42 + +.section .foo.3b,"aM",@progbits,2 +.align 2 +.short 42 diff --git a/test/ELF/linkerscript/multi-sections-constraint.s b/test/ELF/linkerscript/multi-sections-constraint.s new file mode 100644 index 000000000000..bfedd10fc285 --- /dev/null +++ b/test/ELF/linkerscript/multi-sections-constraint.s @@ -0,0 +1,34 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: . = 0x1000; .aaa : ONLY_IF_RO { *(.aaa.*) } \ +# RUN: . = 0x2000; .aaa : ONLY_IF_RW { *(.aaa.*) } } " > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK: .aaa 00000010 0000000000002000 DATA + + +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: . = 0x1000; .aaa : ONLY_IF_RW { *(.aaa.*) } \ +# RUN: . = 0x2000; .aaa : ONLY_IF_RO { *(.aaa.*) } } " > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=REV + +# REV: Sections: +# REV-NEXT: Idx Name Size Address Type +# REV: .aaa 00000010 0000000000001000 DATA + +.global _start +_start: + nop + +.section .aaa.1, "aw" +.quad 1 + +.section .aaa.2, "aw" +.quad 1 diff --git a/test/ELF/linkerscript/multiple-tbss.s b/test/ELF/linkerscript/multiple-tbss.s new file mode 100644 index 000000000000..6bbbca92c239 --- /dev/null +++ b/test/ELF/linkerscript/multiple-tbss.s @@ -0,0 +1,45 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { }" > %t.script +# RUN: ld.lld -T %t.script %t.o -o %t +# RUN: llvm-readobj -l -s %t | FileCheck %s + +# CHECK: Name: .tbss +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_TLS +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: foo +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_TLS +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 1 + +# CHECK: Type: PT_TLS +# CHECK-NEXT: Offset: +# CHECK-NEXT: VirtualAddress: +# CHECK-NEXT: PhysicalAddress: +# CHECK-NEXT: FileSize: 0 +# CHECK-NEXT: MemSize: 9 + +.section .tbss,"awT",@nobits +.quad 0 +.section foo,"awT",@nobits +.byte 0 diff --git a/test/ELF/linkerscript/no-pt-load.s b/test/ELF/linkerscript/no-pt-load.s new file mode 100644 index 000000000000..c70402501391 --- /dev/null +++ b/test/ELF/linkerscript/no-pt-load.s @@ -0,0 +1,5 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "PHDRS {foo PT_DYNAMIC ;} " \ +# RUN: "SECTIONS { .text : { *(.text) } : foo }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t.o diff --git a/test/ELF/linkerscript/no-space.s b/test/ELF/linkerscript/no-space.s new file mode 100644 index 000000000000..a96797269e43 --- /dev/null +++ b/test/ELF/linkerscript/no-space.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS {foo 0 : {*(foo*)} }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o -shared +# RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s + +# RUN: echo "SECTIONS {foo : {*(foo*)} }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o -shared +# RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s + +# There is not enough address space available for the header, so just start the PT_LOAD +# after it. + +# CHECK: Program Headers: +# CHECK-NEXT: Type Offset VirtAddr PhysAddr +# CHECK-NEXT: PHDR +# CHECK-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 + +# CHECK: Section to Segment mapping: +# CHECK-NEXT: Segment Sections... +# CHECK-NEXT: 00 +# CHECK-NEXT: 01 foo .text .dynsym .hash .dynstr + +.section foo, "a" +.quad 0 diff --git a/test/ELF/linkerscript/non-alloc.s b/test/ELF/linkerscript/non-alloc.s new file mode 100644 index 000000000000..2060129a8020 --- /dev/null +++ b/test/ELF/linkerscript/non-alloc.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t + +# RUN: echo "SECTIONS { .foo 0 : {*(foo)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t1 | FileCheck %s + +# Test that we create all necessary PT_LOAD. We use to stop at the first +# non-alloc, causing us to not create PT_LOAD for linker generated sections. + +# CHECK: Program Headers: +# CHECK-NEXT: Type +# CHECK-NEXT: PHDR +# CHECK-NEXT: LOAD {{.*}} R E +# CHECK-NEXT: LOAD {{.*}} RW + +# CHECK: Section to Segment mapping: +# CHECK-NEXT: Segment Sections... +# CHECK-NEXT: 00 +# CHECK-NEXT: 01 .text .dynsym .hash .dynstr +# CHECK-NEXT: 02 .dynamic + +nop +.section foo +.quad 0 diff --git a/test/ELF/linkerscript/numbers.s b/test/ELF/linkerscript/numbers.s new file mode 100644 index 000000000000..653f94bd4e6e --- /dev/null +++ b/test/ELF/linkerscript/numbers.s @@ -0,0 +1,72 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 1000h; \ +# RUN: .hex1 : { *(.hex.1) } \ +# RUN: . = 1010H; \ +# RUN: .hex2 : { *(.hex.2) } \ +# RUN: . = 10k; \ +# RUN: .kilo1 : { *(.kilo.1) } \ +# RUN: . = 11K; \ +# RUN: .kilo2 : { *(.kilo.2) } \ +# RUN: . = 1m; \ +# RUN: .mega1 : { *(.mega.1) } \ +# RUN: . = 2M; \ +# RUN: .mega2 : { *(.mega.2) } \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .hex1 00000008 0000000000001000 +# CHECK-NEXT: 2 .hex2 00000008 0000000000001010 +# CHECK-NEXT: 3 .kilo1 00000008 0000000000002800 +# CHECK-NEXT: 4 .kilo2 00000008 0000000000002c00 +# CHECK-NEXT: 5 .mega1 00000008 0000000000100000 +# CHECK-NEXT: 6 .mega2 00000008 0000000000200000 + +## Mailformed number errors. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x11h; \ +# RUN: }" > %t2.script +# RUN: not ld.lld %t --script %t2.script -o %t3 2>&1 | \ +# RUN: FileCheck --check-prefix=ERR1 %s +# ERR1: malformed number: 0x11h + +# RUN: echo "SECTIONS { \ +# RUN: . = 0x11k; \ +# RUN: }" > %t3.script +# RUN: not ld.lld %t --script %t3.script -o %t4 2>&1 | \ +# RUN: FileCheck --check-prefix=ERR2 %s +# ERR2: malformed number: 0x11k + +# RUN: echo "SECTIONS { \ +# RUN: . = 0x11m; \ +# RUN: }" > %t4.script +# RUN: not ld.lld %t --script %t4.script -o %t5 2>&1 | \ +# RUN: FileCheck --check-prefix=ERR3 %s +# ERR3: malformed number: 0x11m + +.globl _start +_start: +nop + +.section .hex.1, "a" +.quad 0 + +.section .kilo.1, "a" +.quad 0 + +.section .mega.1, "a" +.quad 0 + +.section .hex.2, "a" +.quad 0 + +.section .kilo.2, "a" +.quad 0 + +.section .mega.2, "a" +.quad 0 diff --git a/test/ELF/linkerscript/openbsd-bootdata.s b/test/ELF/linkerscript/openbsd-bootdata.s new file mode 100644 index 000000000000..3e90574bb3a3 --- /dev/null +++ b/test/ELF/linkerscript/openbsd-bootdata.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +# RUN: echo "PHDRS { boot PT_OPENBSD_BOOTDATA; }" > %t.script +# RUN: ld.lld --script %t.script %t.o -o %t +# RUN: llvm-readobj --program-headers -s %t | FileCheck %s + +# CHECK: ProgramHeader { +# CHECK: Type: PT_OPENBSD_BOOTDATA (0x65A41BE6) diff --git a/test/ELF/linkerscript/openbsd-randomize.s b/test/ELF/linkerscript/openbsd-randomize.s new file mode 100644 index 000000000000..bf885f423b02 --- /dev/null +++ b/test/ELF/linkerscript/openbsd-randomize.s @@ -0,0 +1,23 @@ +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +# RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; rand PT_OPENBSD_RANDOMIZE; } \ +# RUN: SECTIONS { . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ +# RUN: .openbsd.randomdata : { *(.openbsd.randomdata) } : rand }" > %t.script +# RUN: ld.lld --script %t.script %t.o -o %t +# RUN: llvm-readobj --program-headers -s %t | FileCheck %s + +# CHECK: ProgramHeader { +# CHECK: Type: PT_OPENBSD_RANDOMIZE (0x65A3DBE6) +# CHECK-NEXT: Offset: 0x74 +# CHECK-NEXT: VirtualAddress: 0x74 +# CHECK-NEXT: PhysicalAddress: 0x74 +# CHECK-NEXT: FileSize: 8 +# CHECK-NEXT: MemSize: 8 +# CHECK-NEXT: Flags [ (0x4) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 1 +# CHECK-NEXT: } + +.section .openbsd.randomdata, "a" +.quad 0 diff --git a/test/ELF/linkerscript/openbsd-wxneeded.s b/test/ELF/linkerscript/openbsd-wxneeded.s new file mode 100644 index 000000000000..d371da9d8645 --- /dev/null +++ b/test/ELF/linkerscript/openbsd-wxneeded.s @@ -0,0 +1,17 @@ +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +# RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; wxneeded PT_OPENBSD_WXNEEDED; }" > %t.script +# RUN: ld.lld -z wxneeded --script %t.script %t.o -o %t +# RUN: llvm-readobj --program-headers %t | FileCheck %s + +# CHECK: ProgramHeader { +# CHECK: Type: PT_OPENBSD_WXNEEDED (0x65A3DBE7) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x0 +# CHECK-NEXT: PhysicalAddress: 0x0 +# CHECK-NEXT: FileSize: 0 +# CHECK-NEXT: MemSize: 0 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 0 +# CHECK-NEXT: } diff --git a/test/ELF/linkerscript/orphan-align.s b/test/ELF/linkerscript/orphan-align.s new file mode 100644 index 000000000000..edd637b92820 --- /dev/null +++ b/test/ELF/linkerscript/orphan-align.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: .data.rel.ro : { *(.data.rel.ro) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t -T %t.script %t.o -shared +# RUN: llvm-readobj -l %t | FileCheck %s + + +# Test that the orphan section foo is placed before the ALIGN and so the second +# PT_LOAD is aligned. + + +# CHECK: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x0 + +# CHECK: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x1000 + +nop +.section .data.rel.ro, "aw" +.byte 0 + +.section foo, "ax" +nop diff --git a/test/ELF/linkerscript/orphan-first-cmd.s b/test/ELF/linkerscript/orphan-first-cmd.s new file mode 100644 index 000000000000..3fb3b31b9a40 --- /dev/null +++ b/test/ELF/linkerscript/orphan-first-cmd.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: foo = 123; \ +# RUN: . = 0x1000; \ +# RUN: . = 0x2000; \ +# RUN: .bar : { . = . + 1; } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t -T %t.script %t.o -shared +# RUN: llvm-readobj -s %t | FileCheck %s + +# CHECK: Name: .text +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x1000 diff --git a/test/ELF/linkerscript/orphan.s b/test/ELF/linkerscript/orphan.s new file mode 100644 index 000000000000..3daa6fbf63c9 --- /dev/null +++ b/test/ELF/linkerscript/orphan.s @@ -0,0 +1,36 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .rw1 : { *(.rw1) } \ +# RUN: .rw2 : { *(.rw2) } \ +# RUN: .rw3 : { *(.rw3) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +## .jcr is a relro section and should be placed before other RW sections. +## .bss is SHT_NOBITS section and should be last RW section, so some space +## in ELF file could be saved. +# CHECK: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000000 0000000000000000 TEXT DATA +# CHECK-NEXT: 2 .jcr 00000008 0000000000000000 DATA +# CHECK-NEXT: 3 .rw1 00000008 0000000000000008 DATA +# CHECK-NEXT: 4 .rw2 00000008 0000000000000010 DATA +# CHECK-NEXT: 5 .rw3 00000008 0000000000000018 DATA +# CHECK-NEXT: 6 .bss 00000008 0000000000000020 BSS + +.section .rw1, "aw" + .quad 0 + +.section .rw2, "aw" + .quad 0 + +.section .rw3, "aw" + .quad 0 + +.section .jcr, "aw" + .quad 0 + +.section .bss, "aw",@nobits + .quad 0 diff --git a/test/ELF/linkerscript/orphans.s b/test/ELF/linkerscript/orphans.s new file mode 100644 index 000000000000..0a8c7ab1129b --- /dev/null +++ b/test/ELF/linkerscript/orphans.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { .writable : { *(.writable) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=TEXTORPHAN %s + +# RUN: echo "SECTIONS { .text : { *(.text) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=WRITABLEORPHAN %s + +# TEXTORPHAN: Sections: +# TEXTORPHAN-NEXT: Idx Name +# TEXTORPHAN-NEXT: 0 +# TEXTORPHAN-NEXT: 1 .text +# TEXTORPHAN-NEXT: 2 .writable + +# WRITABLEORPHAN: Sections: +# WRITABLEORPHAN-NEXT: Idx Name +# WRITABLEORPHAN-NEXT: 0 +# WRITABLEORPHAN-NEXT: 1 .text +# WRITABLEORPHAN-NEXT: 2 .writable + +.global _start +_start: + nop + +.section .writable,"aw" + .zero 4 diff --git a/test/ELF/linkerscript/ouputformat.s b/test/ELF/linkerscript/ouputformat.s new file mode 100644 index 000000000000..7d4402a557a0 --- /dev/null +++ b/test/ELF/linkerscript/ouputformat.s @@ -0,0 +1,9 @@ +# REQUIRES: x86 +# RUN: echo "OUTPUT_FORMAT(x, y, z)" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 +# RUN: ld.lld -shared -o %t2 %t1 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "OUTPUT_FORMAT(x, y)" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 +# RUN: not ld.lld -shared -o %t2 %t1 %t.script diff --git a/test/ELF/linkerscript/outputarch.s b/test/ELF/linkerscript/outputarch.s new file mode 100644 index 000000000000..99089615cb17 --- /dev/null +++ b/test/ELF/linkerscript/outputarch.s @@ -0,0 +1,10 @@ +# REQUIRES: x86 +# RUN: echo "OUTPUT_ARCH(x)" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 +# RUN: ld.lld -shared -o %t2 %t1 %t.script +# RUN: llvm-readobj %t2 > /dev/null + +# RUN: echo "OUTPUT_ARCH(x, y)" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 +# RUN: not ld.lld -shared -o %t2 %t1 %t.script +# RUN: llvm-readobj %t2 > /dev/null diff --git a/test/ELF/linkerscript/outsections-addr.s b/test/ELF/linkerscript/outsections-addr.s new file mode 100644 index 000000000000..003b2771c336 --- /dev/null +++ b/test/ELF/linkerscript/outsections-addr.s @@ -0,0 +1,122 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .aaa 0x2000 : \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: .bbb 0x1 ? 0x3000 : 0x4000 : \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: .ccc ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: .ddd 0x5001 : \ +# RUN: { \ +# RUN: *(.ddd) \ +# RUN: } \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %tout +# RUN: llvm-readobj -s %tout | FileCheck %s + +## Check: +## 1) Simple constant as address. +## 2) That something that contains ":" character, like ternary +## operator works as expression. +## 3) That complex expressions work. +## 4) That section alignment still applied to explicitly specified address. + +#CHECK:Sections [ +#CHECK: Section { +#CHECK: Index: 0 +#CHECK: Name: +#CHECK: Type: SHT_NULL +#CHECK: Flags [ +#CHECK: ] +#CHECK: Address: 0x0 +#CHECK: Offset: 0x0 +#CHECK: Size: 0 +#CHECK: Link: 0 +#CHECK: Info: 0 +#CHECK: AddressAlignment: 0 +#CHECK: EntrySize: 0 +#CHECK: } +#CHECK: Section { +#CHECK: Index: 1 +#CHECK: Name: .aaa +#CHECK: Type: SHT_PROGBITS +#CHECK: Flags [ +#CHECK: SHF_ALLOC +#CHECK: ] +#CHECK: Address: 0x2000 +#CHECK: Offset: 0x1000 +#CHECK: Size: 8 +#CHECK: Link: 0 +#CHECK: Info: 0 +#CHECK: AddressAlignment: 1 +#CHECK: EntrySize: 0 +#CHECK: } +#CHECK: Section { +#CHECK: Index: 2 +#CHECK: Name: .bbb +#CHECK: Type: SHT_PROGBITS +#CHECK: Flags [ +#CHECK: SHF_ALLOC +#CHECK: ] +#CHECK: Address: 0x3000 +#CHECK: Offset: 0x2000 +#CHECK: Size: 8 +#CHECK: Link: 0 +#CHECK: Info: 0 +#CHECK: AddressAlignment: 1 +#CHECK: EntrySize: 0 +#CHECK: } +#CHECK: Section { +#CHECK: Index: 3 +#CHECK: Name: .ccc +#CHECK: Type: SHT_PROGBITS +#CHECK: Flags [ +#CHECK: SHF_ALLOC +#CHECK: ] +#CHECK: Address: 0x4008 +#CHECK: Offset: 0x3008 +#CHECK: Size: 8 +#CHECK: Link: 0 +#CHECK: Info: 0 +#CHECK: AddressAlignment: 1 +#CHECK: EntrySize: 0 +#CHECK: } +#CHECK: Section { +#CHECK: Index: 4 +#CHECK: Name: .ddd +#CHECK: Type: SHT_PROGBITS +#CHECK: Flags [ +#CHECK: SHF_ALLOC +#CHECK: ] +#CHECK: Address: 0x5010 +#CHECK: Offset: 0x4010 +#CHECK: Size: 8 +#CHECK: Link: 0 +#CHECK: Info: 0 +#CHECK: AddressAlignment: 16 +#CHECK: EntrySize: 0 +#CHECK: } + +.globl _start +_start: +nop + +.section .aaa, "a" +.quad 0 + +.section .bbb, "a" +.quad 0 + +.section .ccc, "a" +.quad 0 + +.section .ddd, "a" +.align 16 +.quad 0 diff --git a/test/ELF/linkerscript/page-size-align.s b/test/ELF/linkerscript/page-size-align.s new file mode 100644 index 000000000000..771bb13a8e6d --- /dev/null +++ b/test/ELF/linkerscript/page-size-align.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ +# RUN: . = ALIGN(CONSTANT(MAXPAGESIZE)); \ +# RUN: . = . + 0x3000; \ +# RUN: .dynamic : { *(.dynamic) } \ +# RUN: }" > %t.script + +# RUN: ld.lld -T %t.script -z max-page-size=0x4000 %t.o -o %t.so -shared +# RUN: llvm-readobj -s %t.so | FileCheck %s + +# CHECK: Name: .dynamic +# CHECK-NEXT: Type: SHT_DYNAMIC +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x7000 +# CHECK-NEXT: Offset: 0x3000 diff --git a/test/ELF/linkerscript/page-size.s b/test/ELF/linkerscript/page-size.s new file mode 100644 index 000000000000..3d97816a68ee --- /dev/null +++ b/test/ELF/linkerscript/page-size.s @@ -0,0 +1,68 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: ld.lld -z max-page-size=0x4000 %t -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK: ProgramHeader { +# CHECK: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x200000 +# CHECK-NEXT: PhysicalAddress: 0x200000 +# CHECK-NEXT: FileSize: 344 +# CHECK-NEXT: MemSize: 344 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x4000 +# CHECK-NEXT: VirtualAddress: 0x204000 +# CHECK-NEXT: PhysicalAddress: 0x204000 +# CHECK-NEXT: FileSize: 1 +# CHECK-NEXT: MemSize: 1 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x8000 +# CHECK-NEXT: VirtualAddress: 0x208000 +# CHECK-NEXT: PhysicalAddress: 0x208000 +# CHECK-NEXT: FileSize: 8 +# CHECK-NEXT: MemSize: 8 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: } + +# RUN: echo "SECTIONS { \ +# RUN: symbol = CONSTANT(MAXPAGESIZE); \ +# RUN: }" > %t.script +# RUN: ld.lld -z max-page-size=0x4000 -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck -check-prefix CHECK-SCRIPT %s + +# CHECK-SCRIPT: 0000000000004000 *ABS* 00000000 symbol + +# RUN: not ld.lld -z max-page-size=0x1001 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR1 %s +# ERR1: max-page-size: value isn't a power of 2 + +# RUN: not ld.lld -z max-page-size=-0x1000 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR2 %s +# ERR2: invalid max-page-size: -0x1000 + +.global _start +_start: + nop + +.section .a, "aw" +.quad 0 diff --git a/test/ELF/linkerscript/phdr-check.s b/test/ELF/linkerscript/phdr-check.s new file mode 100644 index 000000000000..c7229ed3312c --- /dev/null +++ b/test/ELF/linkerscript/phdr-check.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck %s +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_PHDR (0x6) +# CHECK-NEXT: Offset: 0x40 +# CHECK-NEXT: VirtualAddress: 0xFFFF040 + +.global _start +_start: + nop diff --git a/test/ELF/linkerscript/phdrs-flags.s b/test/ELF/linkerscript/phdrs-flags.s new file mode 100644 index 000000000000..3cb6432db09c --- /dev/null +++ b/test/ELF/linkerscript/phdrs-flags.s @@ -0,0 +1,58 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (1 | 1 + 0x1);} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} :all \ +# RUN: .data : {*(.data.*)} :all}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck %s + +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (0x1);} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} \ +# RUN: .data : {*(.data.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000000 +# CHECK-NEXT: PhysicalAddress: 0x10000000 +# CHECK-NEXT: FileSize: 521 +# CHECK-NEXT: MemSize: 521 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] + +# DEFHDR: ProgramHeaders [ +# DEFHDR-NEXT: ProgramHeader { +# DEFHDR-NEXT: Type: PT_LOAD (0x1) +# DEFHDR-NEXT: Offset: 0x0 +# DEFHDR-NEXT: VirtualAddress: 0x10000000 +# DEFHDR-NEXT: PhysicalAddress: 0x10000000 +# DEFHDR-NEXT: FileSize: 521 +# DEFHDR-NEXT: MemSize: 521 +# DEFHDR-NEXT: Flags [ (0x1) +# DEFHDR-NEXT: PF_X (0x1) +# DEFHDR-NEXT: ] +# DEFHDR-NEXT: Alignment: 4096 +# DEFHDR-NEXT: } + +.global _start +_start: + nop + +.section .foo.1,"a" +foo1: + .long 0 + +.section .foo.2,"aw" +foo2: + .long 0 diff --git a/test/ELF/linkerscript/phdrs.s b/test/ELF/linkerscript/phdrs.s new file mode 100644 index 000000000000..a7476e802341 --- /dev/null +++ b/test/ELF/linkerscript/phdrs.s @@ -0,0 +1,143 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} :all \ +# RUN: .data : {*(.data.*)} :all}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck %s + +## Check that program headers are not written, unless we explicitly tell +## lld to do this. +# RUN: echo "PHDRS {all PT_LOAD;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: /DISCARD/ : {*(.text*)} \ +# RUN: .foo : {*(.foo.*)} :all \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=NOPHDR %s + +## Check the AT(expr) +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS AT(0x500 + 0x500) ;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} :all \ +# RUN: .data : {*(.data.*)} :all}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s + +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} \ +# RUN: .data : {*(.data.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s + +## Check that error is reported when trying to use phdr which is not listed +## inside PHDRS {} block +## TODO: If script doesn't contain PHDRS {} block then default phdr is always +## created and error is not reported. +# RUN: echo "PHDRS { all PT_LOAD; } \ +# RUN: SECTIONS { .baz : {*(.foo.*)} :bar }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 | FileCheck --check-prefix=BADHDR %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000000 +# CHECK-NEXT: PhysicalAddress: 0x10000000 +# CHECK-NEXT: FileSize: 521 +# CHECK-NEXT: MemSize: 521 +# CHECK-NEXT: Flags [ (0x7) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] + +# NOPHDR: ProgramHeaders [ +# NOPHDR-NEXT: ProgramHeader { +# NOPHDR-NEXT: Type: PT_LOAD (0x1) +# NOPHDR-NEXT: Offset: 0x200 +# NOPHDR-NEXT: VirtualAddress: 0x10000200 +# NOPHDR-NEXT: PhysicalAddress: 0x10000200 +# NOPHDR-NEXT: FileSize: 8 +# NOPHDR-NEXT: MemSize: 8 +# NOPHDR-NEXT: Flags [ (0x6) +# NOPHDR-NEXT: PF_R (0x4) +# NOPHDR-NEXT: PF_W (0x2) +# NOPHDR-NEXT: ] +# NOPHDR-NEXT: Alignment: 4096 +# NOPHDR-NEXT: } +# NOPHDR-NEXT: ] + +# AT: ProgramHeaders [ +# AT-NEXT: ProgramHeader { +# AT-NEXT: Type: PT_LOAD (0x1) +# AT-NEXT: Offset: 0x0 +# AT-NEXT: VirtualAddress: 0x10000000 +# AT-NEXT: PhysicalAddress: 0xA00 +# AT-NEXT: FileSize: 521 +# AT-NEXT: MemSize: 521 +# AT-NEXT: Flags [ (0x7) +# AT-NEXT: PF_R (0x4) +# AT-NEXT: PF_W (0x2) +# AT-NEXT: PF_X (0x1) +# AT-NEXT: ] + +## Check the numetic values for PHDRS. +# RUN: echo "PHDRS {text PT_LOAD FILEHDR PHDRS; foo 0x11223344; } \ +# RUN: SECTIONS { . = SIZEOF_HEADERS; .foo : { *(.*) } : text : foo}" > %t1.script +# RUN: ld.lld -o %t2 --script %t1.script %t +# RUN: llvm-readobj -program-headers %t2 | FileCheck --check-prefix=INT-PHDRS %s + +# INT-PHDRS: ProgramHeaders [ +# INT-PHDRS: ProgramHeader { +# INT-PHDRS: Type: (0x11223344) +# INT-PHDRS-NEXT: Offset: 0xB0 +# INT-PHDRS-NEXT: VirtualAddress: 0xB0 +# INT-PHDRS-NEXT: PhysicalAddress: 0xB0 +# INT-PHDRS-NEXT: FileSize: +# INT-PHDRS-NEXT: MemSize: +# INT-PHDRS-NEXT: Flags [ +# INT-PHDRS-NEXT: PF_R +# INT-PHDRS-NEXT: PF_W +# INT-PHDRS-NEXT: PF_X +# INT-PHDRS-NEXT: ] +# INT-PHDRS-NEXT: Alignment: +# INT-PHDRS-NEXT: } +# INT-PHDRS-NEXT: ] + +# DEFHDR: ProgramHeaders [ +# DEFHDR-NEXT: ProgramHeader { +# DEFHDR-NEXT: Type: PT_LOAD (0x1) +# DEFHDR-NEXT: Offset: 0x0 +# DEFHDR-NEXT: VirtualAddress: 0x10000000 +# DEFHDR-NEXT: PhysicalAddress: 0x10000000 +# DEFHDR-NEXT: FileSize: 521 +# DEFHDR-NEXT: MemSize: 521 +# DEFHDR-NEXT: Flags [ (0x7) +# DEFHDR-NEXT: PF_R (0x4) +# DEFHDR-NEXT: PF_W (0x2) +# DEFHDR-NEXT: PF_X (0x1) +# DEFHDR-NEXT: ] + +# BADHDR: {{.*}}.script:1: section header 'bar' is not listed in PHDRS + +.global _start +_start: + nop + +.section .foo.1,"a" +foo1: + .long 0 + +.section .foo.2,"aw" +foo2: + .long 0 diff --git a/test/ELF/linkerscript/repsection-symbol.s b/test/ELF/linkerscript/repsection-symbol.s new file mode 100644 index 000000000000..6786ac47255c --- /dev/null +++ b/test/ELF/linkerscript/repsection-symbol.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ +# RUN: .foo : {foo1 = .; *(.foo.*) foo2 = .; *(.bar) foo3 = .;} \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-readobj -t %t1 | FileCheck %s + +# CHECK: Name: foo1 +# CHECK-NEXT: Value: 0x288 + +# CHECK: Name: foo2 +# CHECK-NEXT: Value: 0x290 + +# CHECK: Name: foo3 +# CHECK-NEXT: Value: 0x294 + +.section .foo.1,"a" + .long 1 + +.section .foo.2,"aw" + .long 2 + + .section .bar,"aw" + .long 3 diff --git a/test/ELF/linkerscript/repsection-va.s b/test/ELF/linkerscript/repsection-va.s new file mode 100644 index 000000000000..8a50fc0998f9 --- /dev/null +++ b/test/ELF/linkerscript/repsection-va.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS {.foo : {*(.foo.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NOT: .foo +# CHECK: .foo 00000008 {{.*}} DATA +# CHECK-NOT: .foo + + +.global _start +_start: + nop + +.section .foo.1,"a" +foo1: + .long 0 + +.section .foo.2,"aw" +foo2: + .long 0 diff --git a/test/ELF/linkerscript/rosegment.s b/test/ELF/linkerscript/rosegment.s new file mode 100644 index 000000000000..3201b8bda9fb --- /dev/null +++ b/test/ELF/linkerscript/rosegment.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Test that with linker scripts we don't create a RO PT_LOAD. + +# RUN: echo "SECTIONS {}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-readobj -l %t1 | FileCheck %s + +# CHECK-NOT: Type: PT_LOAD + +# CHECK: Type: PT_LOAD +# CHECK: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] + +# CHECK: Type: PT_LOAD +# CHECK: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] + +# CHECK-NOT: Type: PT_LOAD diff --git a/test/ELF/linkerscript/searchdir.s b/test/ELF/linkerscript/searchdir.s new file mode 100644 index 000000000000..9fc1a6a49a90 --- /dev/null +++ b/test/ELF/linkerscript/searchdir.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd \ +# RUN: %p/Inputs/libsearch-dyn.s -o %tdyn.o +# RUN: mkdir -p %t.dir +# RUN: ld.lld -shared %tdyn.o -o %t.dir/libls.so +# RUN: echo "SEARCH_DIR(\"%t.dir\")" > %t.script +# RUN: ld.lld -o %t2 --script %t.script -lls %t + +.globl _start,_bar +_start: diff --git a/test/ELF/linkerscript/sections-constraint.s b/test/ELF/linkerscript/sections-constraint.s new file mode 100644 index 000000000000..4d95ec18336c --- /dev/null +++ b/test/ELF/linkerscript/sections-constraint.s @@ -0,0 +1,46 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .writable : ONLY_IF_RW { *(.writable) } \ +# RUN: .readable : ONLY_IF_RO { *(.readable) }}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | \ +# RUN: FileCheck -check-prefix=BASE %s +# BASE: Sections: +# BASE-NEXT: Idx Name Size +# BASE-NEXT: 0 00000000 +# BASE: .writable 00000004 +# BASE: .readable 00000004 + +# RUN: echo "SECTIONS { \ +# RUN: .foo : ONLY_IF_RO { *(.foo.*) } \ +# RUN: .writable : ONLY_IF_RW { *(.writable) } \ +# RUN: .readable : ONLY_IF_RO { *(.readable) }}" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t2 | \ +# RUN: FileCheck -check-prefix=NO1 %s +# NO1: Sections: +# NO1-NEXT: Idx Name Size +# NO1-NEXT: 0 00000000 +# NO1: .writable 00000004 +# NO1: .foo.2 00000004 +# NO1: .readable 00000004 +# NO1: .foo.1 00000004 + +.global _start +_start: + nop + +.section .writable, "aw" +writable: + .long 1 + +.section .readable, "a" +readable: + .long 2 + +.section .foo.1, "awx" + .long 0 + +.section .foo.2, "aw" + .long 0 diff --git a/test/ELF/linkerscript/sections-constraint2.s b/test/ELF/linkerscript/sections-constraint2.s new file mode 100644 index 000000000000..e726365582d8 --- /dev/null +++ b/test/ELF/linkerscript/sections-constraint2.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { zed : ONLY_IF_RO { *(foo) *(bar) } }" > %t.script +# RUN: ld.lld -T %t.script %t.o -o %t.so -shared +# RUN: llvm-readobj -s %t.so | FileCheck %s + +# CHECK: Sections [ +# CHECK-NOT: zed + +.section foo,"aw" +.quad 1 + +.section bar, "a" +.quad 2 diff --git a/test/ELF/linkerscript/sections-constraint3.s b/test/ELF/linkerscript/sections-constraint3.s new file mode 100644 index 000000000000..259f11e91dd1 --- /dev/null +++ b/test/ELF/linkerscript/sections-constraint3.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { zed : ONLY_IF_RO { abc = 1; *(foo) } }" > %t.script +# RUN: ld.lld -T %t.script %t.o -o %t.so -shared +# RUN: llvm-readobj -t %t.so | FileCheck %s + +# CHECK: Symbols [ +# CHECK-NOT: abc + +.section foo,"aw" +.quad 1 diff --git a/test/ELF/linkerscript/sections-constraint4.s b/test/ELF/linkerscript/sections-constraint4.s new file mode 100644 index 000000000000..6c2d4c8e1ee4 --- /dev/null +++ b/test/ELF/linkerscript/sections-constraint4.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .foo : ONLY_IF_RO { *(.foo) } \ +# RUN: .bar : {bar1 = .; *(.bar) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t +# RUN: llvm-readobj -t %t1 | FileCheck %s + +# CHECK: Name: bar1 + +.global _start +_start: + nop + +.section .bar, "aw" +bar: + .long 1 + +.section .foo, "aw" + .long 0 diff --git a/test/ELF/linkerscript/sections-constraint5.s b/test/ELF/linkerscript/sections-constraint5.s new file mode 100644 index 000000000000..ea14aad5247e --- /dev/null +++ b/test/ELF/linkerscript/sections-constraint5.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: bar : ONLY_IF_RO { sym1 = .; *(foo*) } \ +# RUN: bar : ONLY_IF_RW { sym2 = .; *(foo*) } \ +# RUN: }" > %t.script + +# RUN: ld.lld -o %t -T %t.script %t.o +# RUN: llvm-readobj -s -t %t | FileCheck %s + +# CHECK: Sections [ +# CHECK: Name: bar +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 2 + +# CHECK: Symbols [ +# CHECK-NOT: sym1 +# CHECK: sym2 +# CHECK-NOT: sym1 + +.section foo1,"a" +.byte 0 + +.section foo2,"aw" +.byte 0 + diff --git a/test/ELF/linkerscript/sections-keep.s b/test/ELF/linkerscript/sections-keep.s new file mode 100644 index 000000000000..feb0baca9c3d --- /dev/null +++ b/test/ELF/linkerscript/sections-keep.s @@ -0,0 +1,95 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/keep.s -o %t2.o + +## First check that section "keep" is garbage collected without using KEEP +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .keep : { *(.keep) } \ +# RUN: .temp : { *(.temp) }}" > %t.script +# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | \ +# RUN: FileCheck -check-prefix=SECGC %s +# SECGC: Sections: +# SECGC-NEXT: Idx Name Size +# SECGC-NEXT: 0 00000000 +# SECGC-NEXT: 1 .text 00000007 +# SECGC-NEXT: 2 .temp 00000004 + +## Now apply KEEP command to preserve the section. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .keep : { KEEP(*(.keep)) } \ +# RUN: .temp : { *(.temp) }}" > %t.script +# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | \ +# RUN: FileCheck -check-prefix=SECNOGC %s +# SECNOGC: Sections: +# SECNOGC-NEXT: Idx Name Size +# SECNOGC-NEXT: 0 00000000 +# SECNOGC-NEXT: 1 .text 00000007 +# SECNOGC-NEXT: 2 .keep 00000004 +# SECNOGC-NEXT: 3 .temp 00000004 + +## A section name matches two entries in the SECTIONS directive. The +## first one doesn't have KEEP, the second one does. If section that have +## KEEP is the first in order then section is NOT collected. +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .keep : { KEEP(*(.keep)) } \ +# RUN: .nokeep : { *(.keep) }}" > %t.script +# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED1 %s +# MIXED1: Sections: +# MIXED1-NEXT: Idx Name Size +# MIXED1-NEXT: 0 00000000 +# MIXED1-NEXT: 1 .keep 00000004 +# MIXED1-NEXT: 2 .text 00000007 00000000000000ec TEXT DATA +# MIXED1-NEXT: 3 .temp 00000004 00000000000000f3 DATA +# MIXED1-NEXT: 4 .comment 00000008 0000000000000000 +# MIXED1-NEXT: 5 .symtab 00000060 0000000000000000 +# MIXED1-NEXT: 6 .shstrtab 00000036 0000000000000000 +# MIXED1-NEXT: 7 .strtab 00000012 0000000000000000 + +## The same, but now section without KEEP is at first place. +## gold and bfd linkers disagree here. gold collects .keep while +## bfd keeps it. Our current behavior is compatible with bfd although +## we can choose either way. +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .nokeep : { *(.keep) } \ +# RUN: .keep : { KEEP(*(.keep)) }}" > %t.script +# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED2 %s +# MIXED2: Sections: +# MIXED2-NEXT: Idx Name Size +# MIXED2-NEXT: 0 00000000 +# MIXED2-NEXT: 1 .nokeep 00000004 00000000000000e8 DATA +# MIXED2-NEXT: 2 .text 00000007 00000000000000ec TEXT DATA +# MIXED2-NEXT: 3 .temp 00000004 00000000000000f3 DATA +# MIXED2-NEXT: 4 .comment 00000008 0000000000000000 +# MIXED2-NEXT: 5 .symtab 00000060 0000000000000000 +# MIXED2-NEXT: 6 .shstrtab 00000038 0000000000000000 +# MIXED2-NEXT: 7 .strtab 00000012 0000000000000000 + +# Check file pattern for kept sections. +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .keep : { KEEP(*2.o(.keep)) } \ +# RUN: }" > %t.script +# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t2.o %t +# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=FILEMATCH %s +# FILEMATCH: Contents of section .keep: +# FILEMATCH-NEXT: 00e8 41414141 AAAA + +.global _start +_start: + mov temp, %eax + +.section .keep, "a" +keep: + .long 1 + +.section .temp, "a" +temp: + .long 2 diff --git a/test/ELF/linkerscript/sections-padding.s b/test/ELF/linkerscript/sections-padding.s new file mode 100644 index 000000000000..51d3a88fadf6 --- /dev/null +++ b/test/ELF/linkerscript/sections-padding.s @@ -0,0 +1,49 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Check that padding value works: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1122 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s +# YES: 66001122 00001122 00001122 00001122 + +## Confirming that address was correct: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99887766 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s +# YES2: 66887766 99887766 99887766 99887766 + +## Default padding value is 0x00: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=NO %s +# NO: 66000000 00000000 00000000 00000000 + +## Decimal value. +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =777 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=DEC %s +# DEC: 66000309 00000309 00000309 00000309 + +## Invalid hex value: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script +# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \ +# RUN: | FileCheck --check-prefix=ERR2 %s +# ERR2: invalid filler expression: 0x99XX + +## Check case with space between '=' and expression: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } = 0x1122 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s + +.section .mysec.1,"a" +.align 16 +.byte 0x66 + +.section .mysec.2,"a" +.align 16 +.byte 0x66 + +.globl _start +_start: + nop diff --git a/test/ELF/linkerscript/sections-sort.s b/test/ELF/linkerscript/sections-sort.s new file mode 100644 index 000000000000..cf1fd3e57827 --- /dev/null +++ b/test/ELF/linkerscript/sections-sort.s @@ -0,0 +1,30 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: foo : { *(foo) } \ +# RUN: } " > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o -shared +# RUN: llvm-objdump --section-headers %t | FileCheck %s + +# Test the section order. This is a case where at least with libstdc++'s +# stable_sort we used to get a different result. + +nop + +.section foo, "a" +.byte 0 + +# CHECK: Id +# CHECK-NEXT: 0 +# CHECK-NEXT: 1 .text +# CHECK-NEXT: 2 foo +# CHECK-NEXT: 3 .dynsym +# CHECK-NEXT: 4 .hash +# CHECK-NEXT: 5 .dynstr +# CHECK-NEXT: 6 .dynamic +# CHECK-NEXT: 7 .comment +# CHECK-NEXT: 8 .symtab +# CHECK-NEXT: 9 .shstrtab +# CHECK-NEXT: 10 .strtab diff --git a/test/ELF/linkerscript/sections.s b/test/ELF/linkerscript/sections.s new file mode 100644 index 000000000000..416e77346a59 --- /dev/null +++ b/test/ELF/linkerscript/sections.s @@ -0,0 +1,124 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Empty SECTIONS command. +# RUN: echo "SECTIONS {}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | \ +# RUN: FileCheck -check-prefix=SEC-DEFAULT %s + +# SECTIONS command with the same order as default. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .data : { *(.data) } }" > %t.script +# RUN: ld.lld -o %t2 --script %t.script %t +# RUN: llvm-objdump -section-headers %t2 | \ +# RUN: FileCheck -check-prefix=SEC-DEFAULT %s + +# Idx Name Size +# SEC-DEFAULT: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA +# SEC-DEFAULT: 2 .data 00000020 {{[0-9a-f]*}} DATA +# SEC-DEFAULT: 3 other 00000003 {{[0-9a-f]*}} DATA +# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS +# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}} +# SEC-DEFAULT: 6 .comment 00000008 {{[0-9a-f]*}} +# SEC-DEFAULT: 7 .symtab 00000030 {{[0-9a-f]*}} +# SEC-DEFAULT: 8 .shstrtab 0000003b {{[0-9a-f]*}} +# SEC-DEFAULT: 9 .strtab 00000008 {{[0-9a-f]*}} + +# Sections are put in order specified in linker script, other than alloc +# sections going first. +# RUN: echo "SECTIONS { \ +# RUN: .bss : { *(.bss) } \ +# RUN: other : { *(other) } \ +# RUN: .shstrtab : { *(.shstrtab) } \ +# RUN: .symtab : { *(.symtab) } \ +# RUN: .strtab : { *(.strtab) } \ +# RUN: .data : { *(.data) } \ +# RUN: .text : { *(.text) } }" > %t.script +# RUN: ld.lld -o %t3 --script %t.script %t +# RUN: llvm-objdump -section-headers %t3 | \ +# RUN: FileCheck -check-prefix=SEC-ORDER %s + +# Idx Name Size +# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS +# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA +# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}} +# SEC-ORDER: 4 .shstrtab 0000003b {{[0-9a-f]*}} +# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}} +# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}} +# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA +# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT DATA + +# .text and .data have swapped names but proper sizes and types. +# RUN: echo "SECTIONS { \ +# RUN: .data : { *(.text) } \ +# RUN: .text : { *(.data) } }" > %t.script +# RUN: ld.lld -o %t4 --script %t.script %t +# RUN: llvm-objdump -section-headers %t4 | \ +# RUN: FileCheck -check-prefix=SEC-SWAP-NAMES %s + +# Idx Name Size +# SEC-SWAP-NAMES: 1 .data 0000000e {{[0-9a-f]*}} TEXT DATA +# SEC-SWAP-NAMES: 2 .text 00000020 {{[0-9a-f]*}} DATA +# SEC-SWAP-NAMES: 3 other 00000003 {{[0-9a-f]*}} DATA +# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS +# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 6 .comment 00000008 {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 7 .symtab 00000030 {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 8 .shstrtab 0000003b {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 9 .strtab 00000008 {{[0-9a-f]*}} + +# .shstrtab from the input object file is discarded. +# RUN: echo "SECTIONS { \ +# RUN: /DISCARD/ : { *(.shstrtab) } }" > %t.script +# RUN: ld.lld -o %t5 --script %t.script %t +# RUN: llvm-objdump -section-headers %t5 | \ +# RUN: FileCheck -check-prefix=SEC-DISCARD %s + +# Idx Name Size +# SEC-DISCARD: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA +# SEC-DISCARD: 2 .data 00000020 {{[0-9a-f]*}} DATA +# SEC-DISCARD: 3 other 00000003 {{[0-9a-f]*}} DATA +# SEC-DISCARD: 4 .bss 00000002 {{[0-9a-f]*}} BSS +# SEC-DISCARD: 5 .comment 00000008 {{[0-9a-f]*}} +# SEC-DISCARD: 6 .symtab 00000030 {{[0-9a-f]*}} +# SEC-DISCARD: 7 .shstrtab 0000003b {{[0-9a-f]*}} +# SEC-DISCARD: 8 .strtab 00000008 {{[0-9a-f]*}} + +# Multiple SECTIONS command specifying additional input section descriptions +# for the same output section description - input sections are merged into +# one output section. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .data : { *(.data) } } \ +# RUN: SECTIONS { \ +# RUN: .data : { *(other) } }" > %t.script +# RUN: ld.lld -o %t6 --script %t.script %t +# RUN: llvm-objdump -section-headers %t6 | \ +# RUN: FileCheck -check-prefix=SEC-MULTI %s + +# Idx Name Size +# SEC-MULTI: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA +# SEC-MULTI: 2 .data 00000023 {{[0-9a-f]*}} DATA +# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS +# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}} +# SEC-MULTI: 5 .comment 00000008 {{[0-9a-f]*}} +# SEC-MULTI: 6 .symtab 00000030 {{[0-9a-f]*}} +# SEC-MULTI: 7 .shstrtab 00000035 {{[0-9a-f]*}} +# SEC-MULTI: 8 .strtab 00000008 {{[0-9a-f]*}} + +.globl _start +_start: + mov $60, %rax + mov $42, %rdi + +.section .data,"aw" +.quad 10, 10, 20, 20 +.section other,"aw" +.short 10 +.byte 20 +.section .shstrtab,"" +.short 20 +.section .bss,"",@nobits +.short 0 diff --git a/test/ELF/linkerscript/segment-start.s b/test/ELF/linkerscript/segment-start.s new file mode 100644 index 000000000000..e46c398f63f9 --- /dev/null +++ b/test/ELF/linkerscript/segment-start.s @@ -0,0 +1,27 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld %t.o %S/Inputs/segment-start.script -shared -o %t.so +// RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s + +// CHECK: Name: foobar1 +// CHECK-NEXT: Value: 0x8001 + +// CHECK: Name: foobar2 +// CHECK-NEXT: Value: 0x8002 + +// CHECK: Name: foobar3 +// CHECK-NEXT: Value: 0x8003 + +// CHECK: Name: foobar4 +// CHECK-NEXT: Value: 0x8004 + +.data +.quad foobar1 +.quad foobar2 +.quad foobar3 +.quad foobar4 + +// RUN: echo "SECTIONS { . = SEGMENT_START(\"foobar\", foo); }" > %t.script +// RUN: not ld.lld %t.o %t.script -shared -o %t2.so 2>&1 \ +// RUN: | FileCheck --check-prefix=ERR %s +// ERR: {{.*}}.script:1: symbol not found: foo diff --git a/test/ELF/linkerscript/sizeof.s b/test/ELF/linkerscript/sizeof.s new file mode 100644 index 000000000000..4618f79d3db6 --- /dev/null +++ b/test/ELF/linkerscript/sizeof.s @@ -0,0 +1,53 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: .aaa : { *(.aaa) } \ +# RUN: .bbb : { *(.bbb) } \ +# RUN: .ccc : { *(.ccc) } \ +# RUN: _aaa = SIZEOF(.aaa); \ +# RUN: _bbb = SIZEOF(.bbb); \ +# RUN: _ccc = SIZEOF(.ccc); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t -section-headers %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size +# CHECK-NEXT: 0 00000000 +# CHECK-NEXT: 1 .aaa 00000008 +# CHECK-NEXT: 2 .bbb 00000010 +# CHECK-NEXT: 3 .ccc 00000018 +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: 0000000000000000 *UND* 00000000 +# CHECK-NEXT: .text 00000000 _start +# CHECK-NEXT: 0000000000000008 *ABS* 00000000 _aaa +# CHECK-NEXT: 0000000000000010 *ABS* 00000000 _bbb +# CHECK-NEXT: 0000000000000018 *ABS* 00000000 _ccc + +## SIZEOF(.nonexistent_section) should return 0. +# RUN: echo "SECTIONS { \ +# RUN: .aaa : { *(.aaa) } \ +# RUN: .bbb : { *(.bbb) } \ +# RUN: .ccc : { *(.ccc) } \ +# RUN: _aaa = SIZEOF(.foo); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t -section-headers %t1 | FileCheck -check-prefix=CHECK2 %s + +# CHECK2: 0000000000000000 *ABS* 00000000 _aaa + +.global _start +_start: + nop + +.section .aaa,"a" + .quad 0 + +.section .bbb,"a" + .quad 0 + .quad 0 + +.section .ccc,"a" + .quad 0 + .quad 0 + .quad 0 diff --git a/test/ELF/linkerscript/sizeofheaders.s b/test/ELF/linkerscript/sizeofheaders.s new file mode 100644 index 000000000000..3cc70747280c --- /dev/null +++ b/test/ELF/linkerscript/sizeofheaders.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo " SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: _size = SIZEOF_HEADERS; \ +# RUN: .text : {*(.text*)} \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +#CHECK: SYMBOL TABLE: +#CHECK-NEXT: 0000000000000000 *UND* 00000000 +#CHECK-NEXT: 00000000000000e8 .text 00000000 _start +#CHECK-NEXT: 00000000000000e8 *ABS* 00000000 _size + +.global _start +_start: + nop diff --git a/test/ELF/linkerscript/sort-constructors.s b/test/ELF/linkerscript/sort-constructors.s new file mode 100644 index 000000000000..a0c23af6de79 --- /dev/null +++ b/test/ELF/linkerscript/sort-constructors.s @@ -0,0 +1,5 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: echo "SECTIONS { .aaa : { SORT(CONSTRUCTORS) } }" > %t1.script +# RUN: ld.lld -shared -o %t1 --script %t1.script %t1.o +# RUN: llvm-readobj %t1 > /dev/null diff --git a/test/ELF/linkerscript/sort-init.s b/test/ELF/linkerscript/sort-init.s new file mode 100644 index 000000000000..894b8ae882b7 --- /dev/null +++ b/test/ELF/linkerscript/sort-init.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: echo "SECTIONS { .init_array : { *(SORT_BY_INIT_PRIORITY(.init_array.*)) } }" > %t1.script +# RUN: ld.lld --script %t1.script %t1.o -o %t2 +# RUN: llvm-objdump -s %t2 | FileCheck %s + +# CHECK: Contents of section .init_array: +# CHECK-NEXT: 03020000 00000000 010405 + +.globl _start +_start: + nop + +.section .init_array, "aw", @init_array + .align 8 + .byte 1 +.section .init_array.100, "aw", @init_array + .long 2 +.section .init_array.5, "aw", @init_array + .byte 3 +.section .init_array, "aw", @init_array + .byte 4 +.section .init_array, "aw", @init_array + .byte 5 diff --git a/test/ELF/linkerscript/sort-nested.s b/test/ELF/linkerscript/sort-nested.s new file mode 100644 index 000000000000..fb1d1a3dd070 --- /dev/null +++ b/test/ELF/linkerscript/sort-nested.s @@ -0,0 +1,50 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/sort-nested.s -o %t2.o + +## Check sorting first by alignment and then by name. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.aaa.*))) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t1.o %t2.o +# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=SORTED_AN %s +# SORTED_AN: Contents of section .aaa: +# SORTED_AN-NEXT: 01000000 00000000 00000000 00000000 +# SORTED_AN-NEXT: 11000000 00000000 00000000 00000000 +# SORTED_AN-NEXT: 55000000 00000000 22000000 00000000 +# SORTED_AN-NEXT: 02000000 00000000 + +## Check sorting first by name and then by alignment. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(SORT_BY_ALIGNMENT(.aaa.*))) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t1.o %t2.o +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SORTED_NA %s +# SORTED_NA: Contents of section .aaa: +# SORTED_NA: 01000000 00000000 00000000 00000000 +# SORTED_NA: 11000000 00000000 22000000 00000000 +# SORTED_NA: 02000000 00000000 00000000 00000000 +# SORTED_NA: 55000000 00000000 + +## If the section sorting command in linker script isn't nested, the +## command line option will make the section sorting command to be treated +## as nested sorting command. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(.aaa.*)) } }" > %t3.script +# RUN: ld.lld --sort-section name -o %t3 --script %t3.script %t1.o %t2.o +# RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_AN %s +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(.aaa.*)) } }" > %t4.script +# RUN: ld.lld --sort-section alignment -o %t4 --script %t4.script %t1.o %t2.o +# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SORTED_NA %s + +.global _start +_start: + nop + +.section .aaa.1, "a" +.align 32 +.quad 1 + +.section .aaa.2, "a" +.align 2 +.quad 2 + +.section .aaa.5, "a" +.align 16 +.quad 0x55 diff --git a/test/ELF/linkerscript/sort-non-script.s b/test/ELF/linkerscript/sort-non-script.s new file mode 100644 index 000000000000..75a2d450adcc --- /dev/null +++ b/test/ELF/linkerscript/sort-non-script.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t + +# RUN: echo "SECTIONS { foo : {*(foo)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-readobj -elf-output-style=GNU -s %t1 | FileCheck %s + +# CHECK: .text {{.*}} AX +# CHECK-NEXT: .dynsym {{.*}} A +# CHECK-NEXT: .hash {{.*}} A +# CHECK-NEXT: .dynstr {{.*}} A +# CHECK-NEXT: .dynamic {{.*}} WA +# CHECK-NEXT: foo {{.*}} WA + +.section foo, "aw" +.byte 0 diff --git a/test/ELF/linkerscript/sort.s b/test/ELF/linkerscript/sort.s new file mode 100644 index 000000000000..6390ced12289 --- /dev/null +++ b/test/ELF/linkerscript/sort.s @@ -0,0 +1,120 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/sort.s -o %t2.o + +# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t2.o %t1.o +# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=UNSORTED %s +# UNSORTED: Contents of section .aaa: +# UNSORTED-NEXT: 55000000 00000000 00000000 00000000 +# UNSORTED-NEXT: 00000000 00000000 00000000 00000000 +# UNSORTED-NEXT: 11000000 00000000 33000000 00000000 +# UNSORTED-NEXT: 22000000 00000000 44000000 00000000 +# UNSORTED-NEXT: 05000000 00000000 01000000 00000000 +# UNSORTED-NEXT: 03000000 00000000 02000000 00000000 +# UNSORTED-NEXT: 04000000 00000000 + +## Check that SORT works (sorted by name of section). +# RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t2.o %t1.o +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SORTED_A %s +# SORTED_A: Contents of section .aaa: +# SORTED_A-NEXT: 11000000 00000000 01000000 00000000 +# SORTED_A-NEXT: 22000000 00000000 02000000 00000000 +# SORTED_A-NEXT: 33000000 00000000 03000000 00000000 +# SORTED_A-NEXT: 44000000 00000000 00000000 00000000 +# SORTED_A-NEXT: 04000000 00000000 55000000 00000000 +# SORTED_A-NEXT: 00000000 00000000 00000000 00000000 +# SORTED_A-NEXT: 05000000 00000000 + +## When we switch the order of files, check that sorting by +## section names is stable. +# RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t3.script +# RUN: ld.lld -o %t3 --script %t3.script %t1.o %t2.o +# RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_B %s +# SORTED_B: Contents of section .aaa: +# SORTED_B-NEXT: 01000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 00000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 11000000 00000000 02000000 00000000 +# SORTED_B-NEXT: 22000000 00000000 03000000 00000000 +# SORTED_B-NEXT: 33000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 04000000 00000000 44000000 00000000 +# SORTED_B-NEXT: 05000000 00000000 55000000 00000000 + +## Check that SORT surrounded with KEEP also works. +# RUN: echo "SECTIONS { .aaa : { KEEP (*(SORT(.aaa.*))) } }" > %t3.script +# RUN: ld.lld -o %t3 --script %t3.script %t2.o %t1.o +# RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_A %s + +## Check that SORT_BY_NAME works (SORT is alias). +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(.aaa.*)) } }" > %t4.script +# RUN: ld.lld -o %t4 --script %t4.script %t2.o %t1.o +# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SORTED_A %s + +## Check that sections ordered by alignment. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(.aaa.*)) } }" > %t5.script +# RUN: ld.lld -o %t5 --script %t5.script %t1.o %t2.o +# RUN: llvm-objdump -s %t5 | FileCheck -check-prefix=SORTED_ALIGNMENT %s +# SORTED_ALIGNMENT: Contents of section .aaa: +# SORTED_ALIGNMENT-NEXT: 05000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 00000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 11000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 04000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 22000000 00000000 03000000 00000000 +# SORTED_ALIGNMENT-NEXT: 33000000 00000000 02000000 00000000 +# SORTED_ALIGNMENT-NEXT: 44000000 00000000 01000000 00000000 +# SORTED_ALIGNMENT-NEXT: 55000000 00000000 + +## SORT_NONE itself does not sort anything. +# RUN: echo "SECTIONS { .aaa : { *(SORT_NONE(.aaa.*)) } }" > %t6.script +# RUN: ld.lld -o %t7 --script %t6.script %t2.o %t1.o +# RUN: llvm-objdump -s %t7 | FileCheck -check-prefix=UNSORTED %s + +## Check --sort-section alignment option. +# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t7.script +# RUN: ld.lld --sort-section alignment -o %t8 --script %t7.script %t1.o %t2.o +# RUN: llvm-objdump -s %t8 | FileCheck -check-prefix=SORTED_ALIGNMENT %s + +## Check --sort-section= form. +# RUN: ld.lld --sort-section=alignment -o %t8_1 --script %t7.script %t1.o %t2.o +# RUN: llvm-objdump -s %t8_1 | FileCheck -check-prefix=SORTED_ALIGNMENT %s + +## Check --sort-section name option. +# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t8.script +# RUN: ld.lld --sort-section name -o %t9 --script %t8.script %t1.o %t2.o +# RUN: llvm-objdump -s %t9 | FileCheck -check-prefix=SORTED_B %s + +## SORT_NONE disables the --sort-section. +# RUN: echo "SECTIONS { .aaa : { *(SORT_NONE(.aaa.*)) } }" > %t9.script +# RUN: ld.lld --sort-section name -o %t10 --script %t9.script %t2.o %t1.o +# RUN: llvm-objdump -s %t10 | FileCheck -check-prefix=UNSORTED %s + +## SORT_NONE as a inner sort directive. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(SORT_NONE(.aaa.*))) } }" > %t10.script +# RUN: ld.lld -o %t11 --script %t10.script %t2.o %t1.o +# RUN: llvm-objdump -s %t11 | FileCheck -check-prefix=SORTED_A %s + +.global _start +_start: + nop + +.section .aaa.5, "a" +.align 32 +.quad 5 + +.section .aaa.1, "a" +.align 2 +.quad 1 + +.section .aaa.3, "a" +.align 8 +.quad 3 + +.section .aaa.2, "a" +.align 4 +.quad 2 + +.section .aaa.4, "a" +.align 16 +.quad 4 diff --git a/test/ELF/linkerscript/sort2.s b/test/ELF/linkerscript/sort2.s new file mode 100644 index 000000000000..1d42093d5aa0 --- /dev/null +++ b/test/ELF/linkerscript/sort2.s @@ -0,0 +1,39 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile1.o + +# RUN: echo "SECTIONS { .abc : { *(SORT(.foo.*) .bar.*) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %tfile1.o +# RUN: llvm-objdump -s %t1 | FileCheck %s + +# CHECK: Contents of section .abc: +# CHECK: 01000000 00000000 02000000 00000000 +# CHECK: 03000000 00000000 04000000 00000000 +# CHECK: 06000000 00000000 05000000 00000000 + +# RUN: echo "SECTIONS { \ +# RUN: .abc : { *(SORT(.foo.* EXCLUDE_FILE (*file1.o) .bar.*) .bar.*) } \ +# RUN: }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %tfile1.o +# RUN: llvm-objdump -s %t2 | FileCheck %s + +.text +.globl _start +_start: + +.section .foo.2,"a" + .quad 2 + +.section .foo.3,"a" + .quad 3 + +.section .foo.1,"a" + .quad 1 + +.section .bar.4,"a" + .quad 4 + +.section .bar.6,"a" + .quad 6 + +.section .bar.5,"a" + .quad 5 diff --git a/test/ELF/linkerscript/start-end.s b/test/ELF/linkerscript/start-end.s new file mode 100644 index 000000000000..b68606abc181 --- /dev/null +++ b/test/ELF/linkerscript/start-end.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: .init_array : { \ +# RUN: __init_array_start = .; \ +# RUN: *(.init_array) \ +# RUN: __init_array_end = .; } }" > %t.script +# RUN: ld.lld %t.o -script %t.script -o %t 2>&1 + +.globl _start +.text +_start: + nop + +.section .init_array, "aw" + .quad 0 diff --git a/test/ELF/linkerscript/subalign.s b/test/ELF/linkerscript/subalign.s new file mode 100644 index 000000000000..8b441d440b0e --- /dev/null +++ b/test/ELF/linkerscript/subalign.s @@ -0,0 +1,43 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o + +# RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t1.o +# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=NOALIGN %s +# NOALIGN: Contents of section .aaa: +# NOALIGN-NEXT: 01000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 00000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 02000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 00000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 03000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 00000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 00000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 00000000 00000000 00000000 00000000 +# NOALIGN-NEXT: 04000000 00000000 + +# RUN: echo "SECTIONS { .aaa : SUBALIGN(1) { *(.aaa.*) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t1.o +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SUBALIGN %s +# SUBALIGN: Contents of section .aaa: +# SUBALIGN: 01000000 00000000 02000000 00000000 +# SUBALIGN: 03000000 00000000 04000000 00000000 + +.global _start +_start: + nop + +.section .aaa.1, "a" +.align 16 +.quad 1 + +.section .aaa.2, "a" +.align 32 +.quad 2 + +.section .aaa.3, "a" +.align 64 +.quad 3 + +.section .aaa.4, "a" +.align 128 +.quad 4 diff --git a/test/ELF/linkerscript/symbol-assignexpr.s b/test/ELF/linkerscript/symbol-assignexpr.s new file mode 100644 index 000000000000..b988abcdfe98 --- /dev/null +++ b/test/ELF/linkerscript/symbol-assignexpr.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: symbol = CONSTANT(MAXPAGESIZE); \ +# RUN: symbol2 = symbol + 0x1234; \ +# RUN: symbol3 = symbol2; \ +# RUN: symbol4 = symbol + -4; \ +# RUN: symbol5 = symbol - ~ 0xfffb; \ +# RUN: symbol6 = symbol - ~(0xfff0 + 0xb); \ +# RUN: symbol7 = symbol - ~ 0xfffb + 4; \ +# RUN: symbol8 = ~ 0xffff + 4; \ +# RUN: symbol9 = - 4; \ +# RUN: symbol10 = 0xfedcba9876543210; \ +# RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: 0000000000000000 *UND* 00000000 +# CHECK-NEXT: .text 00000000 _start +# CHECK-NEXT: .text 00000000 foo +# CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol +# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2 +# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3 +# CHECK-NEXT: 0000000000000ffc *ABS* 00000000 symbol4 +# CHECK-NEXT: 0000000000010ffc *ABS* 00000000 symbol5 +# CHECK-NEXT: 0000000000010ffc *ABS* 00000000 symbol6 +# CHECK-NEXT: 0000000000011000 *ABS* 00000000 symbol7 +# CHECK-NEXT: ffffffffffff0004 *ABS* 00000000 symbol8 +# CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9 +# CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10 +# CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11 + +# RUN: echo "SECTIONS { \ +# RUN: symbol2 = symbol; \ +# RUN: }" > %t2.script +# RUN: not ld.lld -o %t2 --script %t2.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR %s +# ERR: {{.*}}.script:1: symbol not found: symbol + +.global _start +_start: + nop + +.global foo +foo: diff --git a/test/ELF/linkerscript/symbol-conflict.s b/test/ELF/linkerscript/symbol-conflict.s new file mode 100644 index 000000000000..dcca7c13de6e --- /dev/null +++ b/test/ELF/linkerscript/symbol-conflict.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : {*(.text.*)} end = .;}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s +# CHECK: 00000000000000e9 .text 00000000 end + +.global _start +_start: + nop diff --git a/test/ELF/linkerscript/symbol-only.s b/test/ELF/linkerscript/symbol-only.s new file mode 100644 index 000000000000..76d54f01cdc7 --- /dev/null +++ b/test/ELF/linkerscript/symbol-only.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: abc : { foo = .; } \ +# RUN: . = ALIGN(0x1000); \ +# RUN: bar : { *(bar) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t -shared +# RUN: llvm-objdump -section-headers -t %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK: abc 00000000 [[ADDR:[0-9a-f]*]] BSS +# CHECK-NEXT: bar 00000000 0000000000001000 DATA + +# CHECK: SYMBOL TABLE: +# CHECK: [[ADDR]] abc 00000000 foo + +.section bar, "a" diff --git a/test/ELF/linkerscript/symbolreferenced.s b/test/ELF/linkerscript/symbolreferenced.s new file mode 100644 index 000000000000..c2925b179ad5 --- /dev/null +++ b/test/ELF/linkerscript/symbolreferenced.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Provide new symbol. The value should be 1, like set in PROVIDE() +# RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s +# PROVIDE1: 0000000000000001 *ABS* 00000000 newsym + +# Provide new symbol (hidden). The value should be 1 +# RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s +# HIDDEN1: 0000000000000001 *ABS* 00000000 .hidden newsym + +.global _start +_start: + nop + +.globl patatino +patatino: + movl newsym, %eax diff --git a/test/ELF/linkerscript/symbols-synthetic.s b/test/ELF/linkerscript/symbols-synthetic.s new file mode 100644 index 000000000000..95cdae9a929e --- /dev/null +++ b/test/ELF/linkerscript/symbols-synthetic.s @@ -0,0 +1,98 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# Simple symbol assignment within input section list. The '.' symbol +# is not location counter but offset from the beginning of output +# section .foo +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .foo : { \ +# RUN: begin_foo = .; \ +# RUN: PROVIDE(_begin_sec = .); \ +# RUN: *(.foo) \ +# RUN: end_foo = .; \ +# RUN: PROVIDE_HIDDEN(_end_sec = .); \ +# RUN: PROVIDE(_end_sec_abs = ABSOLUTE(.)); \ +# RUN: size_foo_1 = SIZEOF(.foo); \ +# RUN: size_foo_1_abs = ABSOLUTE(SIZEOF(.foo)); \ +# RUN: . = ALIGN(0x1000); \ +# RUN: begin_bar = .; \ +# RUN: *(.bar) \ +# RUN: end_bar = .; \ +# RUN: size_foo_2 = SIZEOF(.foo); } \ +# RUN: size_foo_3 = SIZEOF(.foo); \ +# RUN: .eh_frame_hdr : { \ +# RUN: __eh_frame_hdr_start = .; \ +# RUN: __eh_frame_hdr_start2 = ABSOLUTE(ALIGN(0x10)); \ +# RUN: *(.eh_frame_hdr) \ +# RUN: __eh_frame_hdr_end = .; \ +# RUN: __eh_frame_hdr_end2 = ABSOLUTE(ALIGN(0x10)); } \ +# RUN: .eh_frame : { } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s + +# Check that the following script is processed without errors +# RUN: echo "SECTIONS { \ +# RUN: .eh_frame_hdr : { \ +# RUN: PROVIDE_HIDDEN(_begin_sec = .); \ +# RUN: *(.eh_frame_hdr) \ +# RUN: *(.eh_frame_hdr) \ +# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \ +# RUN: PROVIDE_HIDDEN(_end_sec = .); } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t + +# Check that we can specify synthetic symbols without defining SECTIONS. +# RUN: echo "PROVIDE_HIDDEN(_begin_sec = _start); \ +# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text));" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=NO-SEC %s + +# Check that we can do the same as above inside SECTIONS block. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x201000; \ +# RUN: .text : { *(.text) } \ +# RUN: PROVIDE_HIDDEN(_begin_sec = ADDR(.text)); \ +# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text)); }" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=IN-SEC %s + +# SIMPLE: 0000000000000128 .foo 00000000 .hidden _end_sec +# SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec +# SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs +# SIMPLE-NEXT: 0000000000001048 .text 00000000 _start +# SIMPLE-NEXT: 0000000000000120 .foo 00000000 begin_foo +# SIMPLE-NEXT: 0000000000000128 .foo 00000000 end_foo +# SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1 +# SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1_abs +# SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar +# SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar +# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_2 +# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 +# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start +# SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2 +# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end +# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2 + +# NO-SEC: 0000000000201000 .text 00000000 .hidden _begin_sec +# NO-SEC-NEXT: 0000000000201001 .text 00000000 .hidden _end_sec + +# IN-SEC: 0000000000201000 .text 00000000 .hidden _begin_sec +# IN-SEC-NEXT: 0000000000201001 .text 00000000 .hidden _end_sec + +.global _start +_start: + nop + +.section .foo,"a" + .quad 0 + +.section .bar,"a" + .long 0 + +.section .dah,"ax",@progbits + .cfi_startproc + nop + .cfi_endproc + +.global _begin_sec, _end_sec, _end_sec_abs diff --git a/test/ELF/linkerscript/symbols.s b/test/ELF/linkerscript/symbols.s new file mode 100644 index 000000000000..4656635171c8 --- /dev/null +++ b/test/ELF/linkerscript/symbols.s @@ -0,0 +1,84 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Simple symbol assignment. Should raise conflict in case we +# have duplicates in any input section, but currently simply +# replaces the value. +# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s +# SIMPLE: .text 00000000 text_end + +# The symbol is not referenced. Don't provide it. +# RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s +# PROVIDE1-NOT: 0000000000000001 *ABS* 00000000 newsym + +# The symbol is not referenced. Don't provide it. +# RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s +# HIDDEN1-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE() +# RUN: echo "SECTIONS { PROVIDE(somesym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE2 %s +# PROVIDE2: 0000000000000000 *ABS* 00000000 somesym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE_HIDDEN(). Visibility should not change +# RUN: echo "SECTIONS { PROVIDE_HIDDEN(somesym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN2 %s +# HIDDEN2: 0000000000000000 *ABS* 00000000 somesym + +# Hidden symbol assignment. +# RUN: echo "SECTIONS { HIDDEN(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN3 %s +# HIDDEN3: 0000000000000001 *ABS* 00000000 .hidden newsym + +# The symbol is not referenced. Don't provide it. +# RUN: echo "PROVIDE(newsym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE4 %s +# PROVIDE4-NOT: 0000000000000001 *ABS* 00000000 newsym + +# The symbol is not referenced. Don't provide it. +# RUN: echo "PROVIDE_HIDDEN(newsym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN4 %s +# HIDDEN4-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE() +# RUN: echo "PROVIDE(somesym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE5 %s +# PROVIDE5: 0000000000000000 *ABS* 00000000 somesym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE_HIDDEN(). Visibility should not change +# RUN: echo "PROVIDE_HIDDEN(somesym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN5 %s +# HIDDEN5: 0000000000000000 *ABS* 00000000 somesym + +# Simple symbol assignment. All three symbols should have the +# same value. +# RUN: echo "foo = 0x100; SECTIONS { bar = foo; } baz = bar;" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE2 %s +# SIMPLE2: 0000000000000100 *ABS* 00000000 foo +# SIMPLE2: 0000000000000100 *ABS* 00000000 bar +# SIMPLE2: 0000000000000100 *ABS* 00000000 baz + +.global _start +_start: + nop + +.global somesym +somesym = 0 diff --git a/test/ELF/linkerscript/tbss.s b/test/ELF/linkerscript/tbss.s new file mode 100644 index 000000000000..de8ed50cb4a4 --- /dev/null +++ b/test/ELF/linkerscript/tbss.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ +# RUN: foo : { *(foo) } \ +# RUN: bar : { *(bar) } \ +# RUN: }" > %t.script +# RUN: ld.lld -T %t.script %t.o -o %t +# RUN: llvm-readobj -s %t | FileCheck %s + +# test that a tbss section doesn't use address space. + +# CHECK: Name: foo +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_TLS +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x[[ADDR:.*]] +# CHECK-NEXT: Offset: 0x[[ADDR]] +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: bar +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x[[ADDR]] + + .section foo,"awT",@nobits + .long 0 + .section bar, "aw" + .long 0 diff --git a/test/ELF/linkerscript/undef.s b/test/ELF/linkerscript/undef.s new file mode 100644 index 000000000000..85ad0767b5ed --- /dev/null +++ b/test/ELF/linkerscript/undef.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { patatino = 0x1234; }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s +# CHECK: 0000000000001234 *ABS* 00000000 patatino + +.global _start +_start: + call patatino diff --git a/test/ELF/linkerscript/va.s b/test/ELF/linkerscript/va.s new file mode 100644 index 000000000000..854ebcef0146 --- /dev/null +++ b/test/ELF/linkerscript/va.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS {}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000001 0000000000000000 TEXT DATA +# CHECK-NEXT: 2 .foo 00000004 0000000000000001 DATA +# CHECK-NEXT: 3 .boo 00000004 0000000000000005 DATA + +.global _start +_start: + nop + +.section .foo, "a" +foo: + .long 0 + +.section .boo, "a" +boo: + .long 0 diff --git a/test/ELF/linkerscript/visibility.s b/test/ELF/linkerscript/visibility.s new file mode 100644 index 000000000000..9d9fcf0c5cdc --- /dev/null +++ b/test/ELF/linkerscript/visibility.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { foo = .; }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared +# RUN: llvm-readobj -t %t1 | FileCheck %s + +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: +# CHECK-NEXT: Other [ +# CHECK-NEXT: STV_HIDDEN +# CHECK-NEXT: ] +# CHECK-NEXT: Section: +# CHECK-NEXT: } + + .data + .hidden foo + .long foo diff --git a/test/ELF/linkerscript/wildcards.s b/test/ELF/linkerscript/wildcards.s new file mode 100644 index 000000000000..4e9469e40773 --- /dev/null +++ b/test/ELF/linkerscript/wildcards.s @@ -0,0 +1,83 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Default case: abc and abx included in text. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.abc .abx) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=SEC-DEFAULT %s +# SEC-DEFAULT: Sections: +# SEC-DEFAULT-NEXT: Idx Name Size +# SEC-DEFAULT-NEXT: 0 00000000 +# SEC-DEFAULT-NEXT: 1 .text 00000008 +# SEC-DEFAULT-NEXT: 2 .abcd 00000004 +# SEC-DEFAULT-NEXT: 3 .ad 00000004 +# SEC-DEFAULT-NEXT: 4 .ag 00000004 +# SEC-DEFAULT-NEXT: 5 .comment 00000008 {{[0-9a-f]*}} +# SEC-DEFAULT-NEXT: 6 .symtab 00000030 +# SEC-DEFAULT-NEXT: 7 .shstrtab 00000038 +# SEC-DEFAULT-NEXT: 8 .strtab 00000008 + +## Now replace the symbol with '?' and check that results are the same. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.abc .ab?) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=SEC-DEFAULT %s + +## Now see how replacing '?' with '*' will consume whole abcd. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.abc .ab*) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=SEC-ALL %s +# SEC-ALL: Sections: +# SEC-ALL-NEXT: Idx Name Size +# SEC-ALL-NEXT: 0 00000000 +# SEC-ALL-NEXT: 1 .text 0000000c +# SEC-ALL-NEXT: 2 .ad 00000004 +# SEC-ALL-NEXT: 3 .ag 00000004 +# SEC-ALL-NEXT: 4 .comment 00000008 +# SEC-ALL-NEXT: 5 .symtab 00000030 +# SEC-ALL-NEXT: 6 .shstrtab 00000032 +# SEC-ALL-NEXT: 7 .strtab 00000008 + +## All sections started with .a are merged. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.a*) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=SEC-NO %s +# SEC-NO: Sections: +# SEC-NO-NEXT: Idx Name Size +# SEC-NO-NEXT: 0 00000000 +# SEC-NO-NEXT: 1 .text 00000014 +# SEC-NO-NEXT: 2 .comment 00000008 +# SEC-NO-NEXT: 3 .symtab 00000030 +# SEC-NO-NEXT: 4 .shstrtab 0000002a +# SEC-NO-NEXT: 5 .strtab 00000008 + +.text +.section .abc,"ax",@progbits +.long 0 + +.text +.section .abx,"ax",@progbits +.long 0 + +.text +.section .abcd,"ax",@progbits +.long 0 + +.text +.section .ad,"ax",@progbits +.long 0 + +.text +.section .ag,"ax",@progbits +.long 0 + + +.globl _start +_start: diff --git a/test/ELF/linkerscript/wildcards2.s b/test/ELF/linkerscript/wildcards2.s new file mode 100644 index 000000000000..5e8d6a3d309a --- /dev/null +++ b/test/ELF/linkerscript/wildcards2.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +## Check that aabc is not included in text. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.abc) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size +# CHECK-NEXT: 0 00000000 +# CHECK-NEXT: 1 .text 00000004 +# CHECK-NEXT: 2 aabc 00000004 + +.text +.section .abc,"ax",@progbits +.long 0 + +.text +.section aabc,"ax",@progbits +.long 0 + +.globl _start +_start: |
