Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -68,6 +68,8 @@ bool Mips64EL = false; bool NoUndefined; bool NoinhibitExec; + bool Pic; + bool Pie; bool PrintGcSections; bool Rela; bool Relocatable; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -144,6 +144,9 @@ if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty()) error("-e option is not valid for AMDGPU."); + if (Config->Pie && Config->Shared) + error("-shared and -pie may not be used together"); + if (!Config->Relocatable) return; @@ -153,6 +156,8 @@ error("-r and --gc-sections may not be used together"); if (Config->ICF) error("-r and --icf may not be used together"); + if (Config->Pie) + error("-r and -pie may not be used together"); } static StringRef @@ -238,6 +243,7 @@ Config->ICF = Args.hasArg(OPT_icf); Config->NoUndefined = Args.hasArg(OPT_no_undefined); Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); + Config->Pie = Args.hasArg(OPT_pie); Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); Config->Relocatable = Args.hasArg(OPT_relocatable); Config->SaveTemps = Args.hasArg(OPT_save_temps); @@ -261,6 +267,8 @@ Config->ZOrigin = hasZOption(Args, "origin"); Config->ZRelro = !hasZOption(Args, "norelro"); + Config->Pic = Config->Pie || Config->Shared; + if (Config->Relocatable) Config->StripAll = false; Index: lld/trunk/ELF/Options.td =================================================================== --- lld/trunk/ELF/Options.td +++ lld/trunk/ELF/Options.td @@ -97,6 +97,9 @@ def o : JoinedOrSeparate<["-"], "o">, MetaVarName<"">, HelpText<"Path to file to write output">; +def pie : Flag<["-"], "pie">, + HelpText<"Create a position independent executable">; + def print_gc_sections: Flag<["--"], "print-gc-sections">, HelpText<"List removed unused sections">; @@ -159,6 +162,7 @@ def alias_init_init : Joined<["-"], "init=">, Alias; def alias_l__library : Joined<["--"], "library=">, Alias; def alias_o_output : Joined<["--"], "output=">, Alias; +def alias_pie_pic_executable: Flag<["--"], "pic-executable">, Alias; def alias_rpath_rpath : Joined<["-"], "rpath=">, Alias; def alias_relocatable_r : Flag<["-"], "r">, Alias; def alias_shared_Bshareable : Flag<["-"], "Bshareable">, Alias; Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -122,7 +122,7 @@ fatal("target not found: " + ErrMsg); TargetOptions Options; - Reloc::Model R = Config->Shared ? Reloc::PIC_ : Reloc::Static; + Reloc::Model R = Config->Pic ? Reloc::PIC_ : Reloc::Static; std::unique_ptr TM( TheTarget->createTargetMachine(TripleStr, "", "", Options, R)); Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -270,7 +270,7 @@ return false; } -uint64_t TargetInfo::getVAStart() const { return Config->Shared ? 0 : VAStart; } +uint64_t TargetInfo::getVAStart() const { return Config->Pic ? 0 : VAStart; } bool TargetInfo::needsCopyRelImpl(uint32_t Type) const { return false; } @@ -329,7 +329,7 @@ // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, // R_386_JMP_SLOT, etc). if (auto *SS = dyn_cast>(&S)) - if (!Config->Shared && SS->Sym.getType() == STT_FUNC && + if (!Config->Pic && SS->Sym.getType() == STT_FUNC && !refersToGotEntry(Type)) return Plt_Implicit; @@ -439,7 +439,7 @@ void X86TargetInfo::writePltZero(uint8_t *Buf) const { // Executable files and shared object files have // separate procedure linkage tables. - if (Config->Shared) { + if (Config->Pic) { const uint8_t V[] = { 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx) 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx) @@ -471,7 +471,7 @@ memcpy(Buf, Inst, sizeof(Inst)); // jmp *foo@GOT(%ebx) or jmp *foo_in_GOT - Buf[1] = Config->Shared ? 0xa3 : 0x25; + Buf[1] = Config->Pic ? 0xa3 : 0x25; uint32_t Got = UseLazyBinding ? Out::GotPlt->getVA() : Out::Got->getVA(); write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr); Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -82,7 +82,7 @@ return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty(); } bool isOutputDynamic() const { - return !Symtab.getSharedFiles().empty() || Config->Shared; + return !Symtab.getSharedFiles().empty() || Config->Pic; } void ensureBss(); @@ -417,7 +417,7 @@ continue; } - bool Dynrel = Config->Shared && !Target->isRelRelative(Type) && + bool Dynrel = Config->Pic && !Target->isRelRelative(Type) && !Target->isSizeRel(Type); if (Preemptible || Dynrel) { uint32_t DynType; @@ -466,8 +466,7 @@ // We can however do better than just copying the incoming relocation. We // can process some of it and and just ask the dynamic linker to add the // load address. - if (!Config->Shared || Target->isRelRelative(Type) || - Target->isSizeRel(Type)) + if (!Config->Pic || Target->isRelRelative(Type) || Target->isSizeRel(Type)) continue; uintX_t Addend = getAddend(RI); @@ -1439,7 +1438,7 @@ } static uint16_t getELFType() { - if (Config->Shared) + if (Config->Pic) return ET_DYN; if (Config->Relocatable) return ET_REL; Index: lld/trunk/test/ELF/driver.test =================================================================== --- lld/trunk/test/ELF/driver.test +++ lld/trunk/test/ELF/driver.test @@ -37,6 +37,14 @@ # RUN: not ld.lld -r --icf=all %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR4 %s # ERR4: -r and --icf may not be used together +## Attempt to use -r and -pie together +# RUN: not ld.lld -r -pie %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR5 %s +# ERR5: -r and -pie may not be used together + +## Attempt to use -shared and -pie together +# RUN: not ld.lld -shared -pie %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR6 %s +# ERR6: -shared and -pie may not be used together + .globl _start _start: nop Index: lld/trunk/test/ELF/dynsym-pie.s =================================================================== --- lld/trunk/test/ELF/dynsym-pie.s +++ lld/trunk/test/ELF/dynsym-pie.s @@ -0,0 +1,36 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t +# RUN: ld.lld -pie %t -o %t.out +# RUN: llvm-readobj -t -dyn-symbols %t.out | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.text +.globl _start +_start: + +.global default +default: + +.global protected +protected: + +.global hidden +hidden: + +.global internal +internal: + +.global protected_with_hidden +.protected +protected_with_hidden: Index: lld/trunk/test/ELF/local-got-pie.s =================================================================== --- lld/trunk/test/ELF/local-got-pie.s +++ lld/trunk/test/ELF/local-got-pie.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t -pie +// RUN: llvm-readobj -s -r %t | FileCheck %s +// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s + +.globl _start +_start: + call foo@gotpcrel + + .hidden foo + .global foo +foo: + nop + +// 0x20A0 - 1001 - 5 = 4250 +// DISASM: Disassembly of section .text: +// DISASM-NEXT: _start: +// DISASM-NEXT: 1000: {{.*}} callq 4251 +// DISASM: foo: +// DISASM-NEXT: 1005: {{.*}} nop + +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x20A0 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 8 + +// CHECK: Relocations [ +// CHECK-NEXT: Section ({{.*}}) .rela.dyn { +// CHECK-NEXT: 0x20A0 R_X86_64_RELATIVE - 0x1005 +// CHECK-NEXT: } +// CHECK-NEXT: ] Index: lld/trunk/test/ELF/noplt-pie.s =================================================================== --- lld/trunk/test/ELF/noplt-pie.s +++ lld/trunk/test/ELF/noplt-pie.s @@ -0,0 +1,21 @@ +# 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: ld.lld %t1.o %t2.so -o %t.out +# RUN: llvm-readobj -s -r %t.out | FileCheck %s + +# CHECK: Section { +# CHECK-NOT: Name: .plt + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.dyn { +# CHECK-NEXT: 0x120B0 R_X86_64_GLOB_DAT bar 0x0 +# CHECK-NEXT: 0x120B8 R_X86_64_GLOB_DAT zed 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.global _start +_start: + movq bar@GOTPCREL(%rip), %rcx + movq zed@GOTPCREL(%rip), %rcx Index: lld/trunk/test/ELF/pie.s =================================================================== --- lld/trunk/test/ELF/pie.s +++ lld/trunk/test/ELF/pie.s @@ -0,0 +1,102 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: ld.lld -pie %t1.o -o %t +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s + +## Test --pic-executable alias +# RUN: ld.lld --pic-executable %t1.o -o %t +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s + +# CHECK: ElfHeader { +# CHECK-NEXT: Ident { +# CHECK-NEXT: Magic: (7F 45 4C 46) +# CHECK-NEXT: Class: 64-bit +# CHECK-NEXT: DataEncoding: LittleEndian +# CHECK-NEXT: FileVersion: 1 +# CHECK-NEXT: OS/ABI: SystemV +# CHECK-NEXT: ABIVersion: 0 +# CHECK-NEXT: Unused: (00 00 00 00 00 00 00) +# CHECK-NEXT: } +# CHECK-NEXT: Type: SharedObject +# CHECK-NEXT: Machine: EM_X86_64 +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Entry: 0x1000 +# CHECK-NEXT: ProgramHeaderOffset: 0x40 +# CHECK-NEXT: SectionHeaderOffset: 0x1110 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: HeaderSize: 64 +# CHECK-NEXT: ProgramHeaderEntrySize: 56 +# CHECK-NEXT: ProgramHeaderCount: 7 +# CHECK-NEXT: SectionHeaderEntrySize: 64 +# CHECK-NEXT: SectionHeaderCount: 9 +# CHECK-NEXT: StringTableSectionIndex: 7 +# CHECK-NEXT: } + +# 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: 392 +# CHECK-NEXT: MemSize: 392 +# 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: 497 +# CHECK-NEXT: MemSize: 497 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x1000 +# CHECK-NEXT: FileSize: 0 +# CHECK-NEXT: MemSize: 0 +# 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: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x1000 +# CHECK-NEXT: FileSize: 112 +# CHECK-NEXT: MemSize: 112 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_DYNAMIC +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x1000 +# CHECK-NEXT: FileSize: 112 +# CHECK-NEXT: MemSize: 112 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 8 +# CHECK-NEXT: } + +.globl _start +_start: Index: lld/trunk/test/ELF/plt-i686.s =================================================================== --- lld/trunk/test/ELF/plt-i686.s +++ lld/trunk/test/ELF/plt-i686.s @@ -7,7 +7,8 @@ // RUN: ld.lld -shared %t.o %t2.so -o %t // RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECKSHARED %s // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s - +// RUN: ld.lld -pie %t.o %t2.so -o %t +// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMPIE %s // REQUIRES: x86 // CHECK: Name: .plt @@ -147,6 +148,21 @@ // DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8 // DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt> +// DISASMPIE: Disassembly of section .plt: +// DISASMPIE-NEXT: .plt: +// DISASMPIE-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx) +// DISASMPIE-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx) +// DISASMPIE-NEXT: 102c: 90 nop +// DISASMPIE-NEXT: 102d: 90 nop +// DISASMPIE-NEXT: 102e: 90 nop +// DISASMPIE-NEXT: 102f: 90 nop +// DISASMPIE-NEXT: 1030: ff a3 0c 30 00 00 jmpl *12300(%ebx) +// DISASMPIE-NEXT: 1036: 68 00 00 00 00 pushl $0 +// DISASMPIE-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt> +// DISASMPIE-NEXT: 1040: ff a3 10 30 00 00 jmpl *12304(%ebx) +// DISASMPIE-NEXT: 1046: 68 08 00 00 00 pushl $8 +// DISASMPIE-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt> + local: .long 0 Index: lld/trunk/test/ELF/relative-dynamic-reloc-pie.s =================================================================== --- lld/trunk/test/ELF/relative-dynamic-reloc-pie.s +++ lld/trunk/test/ELF/relative-dynamic-reloc-pie.s @@ -0,0 +1,25 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld -pie %t.o -o %t.pie +# RUN: llvm-readobj -r -dyn-symbols %t.pie | FileCheck %s + +## Test that we create R_X86_64_RELATIVE relocations with -pie. +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.dyn { +# CHECK-NEXT: 0x1001 R_X86_64_RELATIVE - 0x1001 +# CHECK-NEXT: 0x1009 R_X86_64_RELATIVE - 0x1009 +# CHECK-NEXT: 0x1011 R_X86_64_RELATIVE - 0x100A +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.globl _start +_start: +nop + +foo: + .quad foo + +.hidden bar +.global bar +bar: + .quad bar + .quad bar + 1 Index: lld/trunk/test/ELF/undef.s =================================================================== --- lld/trunk/test/ELF/undef.s +++ lld/trunk/test/ELF/undef.s @@ -1,5 +1,6 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s +# RUN: not ld.lld -pie %t -o %t2 2>&1 | FileCheck %s # CHECK: undefined symbol: bar in {{.*}} # CHECK: undefined symbol: foo in {{.*}} # REQUIRES: x86