Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1014,6 +1014,15 @@ for (StringRef Sym : Script->Opt.ReferencedSymbols) Symtab->addUndefined(Sym); + // Add dummy symbols defined in linker scripts early because otherwise version + // scripts referring script-synthesized symbols wouldn't work due to + // undefined symbol error. (Version scripts are processed earlier than linker + // scripts.) + for (BaseCommand *Base : Script->Opt.Commands) + if (SymbolAssignment *Cmd = dyn_cast(Base)) + if (Cmd->Name != "." && !Symtab->find(Cmd->Name) && !Cmd->Provide) + Symtab->addAbsolute(Cmd->Name, STV_DEFAULT); + // If an entry symbol is in a static archive, pull out that file now // to complete the symbol table. After this, no new names except a // few linker-synthesized ones will be added to the symbol table. Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -791,21 +791,31 @@ // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); + SymbolBody *Gp = Symtab->find("_gp"); + if (!Gp || !isa(Gp)) + ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); + else + ElfSym::MipsGp = dyn_cast(Gp); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. - if (Symtab->find("_gp_disp")) + SymbolBody *GpDisp = Symtab->find("_gp_disp"); + if (GpDisp && !isa(GpDisp)) ElfSym::MipsGpDisp = Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL); + else + ElfSym::MipsGpDisp = dyn_cast_or_null(GpDisp); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html - if (Symtab->find("__gnu_local_gp")) + SymbolBody *LocalGp = Symtab->find("__gnu_local_gp"); + if (LocalGp && !isa(LocalGp)) ElfSym::MipsLocalGp = Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); + else + ElfSym::MipsLocalGp = dyn_cast_or_null(LocalGp); } // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to Index: test/ELF/linkerscript/mips-symbols-assign.s =================================================================== --- test/ELF/linkerscript/mips-symbols-assign.s +++ test/ELF/linkerscript/mips-symbols-assign.s @@ -0,0 +1,82 @@ +# REQUIRES: mips +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: _gp = ABSOLUTE(.) + 0x100; \ +# RUN: __gnu_local_gp = ABSOLUTE(.) + 0x200; \ +# RUN: _gp_disp = ABSOLUTE(.) + 0x300; }"> %t.script +# RUN: ld.lld -shared -o %t.so --script %t.script %t.o +# RUN: llvm-readobj -symbols %t.so | FileCheck %s + +## FIXME: _gp_disp and __gnu_local_gp should be global +## and have default visibility in case below. +# CHECK: Symbol { +# CHECK: Name: __gnu_local_gp +# CHECK-NEXT: Value: 0x200 +# 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: } +# CHECK: Symbol { +# CHECK: Name: _gp_disp +# CHECK-NEXT: Value: 0x300 +# 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: } +# CHECK: Symbol { +# CHECK: Name: _gp +# CHECK-NEXT: Value: 0x100 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } + +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t.o < /dev/null +# RUN: ld.lld -shared -o %t.so --script %t.script %t.o +# RUN: llvm-readobj -symbols %t.so | FileCheck %s -check-prefix=SCRIPT + +# SCRIPT: Symbol { +# SCRIPT: Name: _gp +# SCRIPT-NEXT: Value: 0x100 +# SCRIPT-NEXT: Size: 0 +# SCRIPT-NEXT: Binding: Global +# SCRIPT-NEXT: Type: None +# SCRIPT-NEXT: Other: 0 +# SCRIPT-NEXT: Section: Absolute +# SCRIPT-NEXT: } +# SCRIPT: Symbol { +# SCRIPT: Name: __gnu_local_gp +# SCRIPT-NEXT: Value: 0x200 +# SCRIPT-NEXT: Size: 0 +# SCRIPT-NEXT: Binding: Global +# SCRIPT-NEXT: Type: None +# SCRIPT-NEXT: Other: 0 +# SCRIPT-NEXT: Section: Absolute +# SCRIPT-NEXT: } +# SCRIPT: Symbol { +# SCRIPT: Name: _gp_disp +# SCRIPT-NEXT: Value: 0x300 +# SCRIPT-NEXT: Size: 0 +# SCRIPT-NEXT: Binding: Global +# SCRIPT-NEXT: Type: None +# SCRIPT-NEXT: Other: 0 +# SCRIPT-NEXT: Section: Absolute +# SCRIPT-NEXT: } + +.text +.globl __start +__start: + lui $t0,%hi(__gnu_local_gp) + addi $t0,$t0,%lo(__gnu_local_gp) + lui $t0,%hi(_gp_disp) + addi $t0,$t0,%lo(_gp_disp) Index: test/ELF/linkerscript/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -61,6 +61,7 @@ # SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec # SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs # SIMPLE-NEXT: 0000000000001048 .text 00000000 _start +# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000000120 .foo 00000000 begin_foo # SIMPLE-NEXT: 0000000000000128 .foo 00000000 end_foo # SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1 @@ -68,7 +69,6 @@ # 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 Index: test/ELF/linkerscript/version-script.s =================================================================== --- test/ELF/linkerscript/version-script.s +++ test/ELF/linkerscript/version-script.s @@ -0,0 +1,37 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo "bar = foo; VERSION { V { global: foo; bar; local: *; }; }" > %t.script +# RUN: ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so +# RUN: llvm-readobj -V %t.so | FileCheck %s + +# CHECK: Symbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: Name: @ +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 2 +# CHECK-NEXT: Name: foo@@V +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: Name: und@ +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 2 +# CHECK-NEXT: Name: bar@@V +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# RUN: echo "bar = und; VERSION { V { global: foo; bar; local: *; }; }" > %t.script +# RUN: not ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so \ +# RUN: 2>&1 | FileCheck --check-prefix=ERR %s +# ERR: symbol not found: und + +.global und + +.text +.globl foo +.type foo,@function +foo: Index: test/ELF/mips-gp-ext.s =================================================================== --- test/ELF/mips-gp-ext.s +++ test/ELF/mips-gp-ext.s @@ -20,10 +20,10 @@ # REQUIRES: mips # REL: Contents of section .text: -# REL-NEXT: 0000 3c080000 2108010c 8f82fffc +# REL-NEXT: 0000 3c080000 2108010c 8f82001c # ^-- %hi(_gp_disp) # ^-- %lo(_gp_disp) -# ^-- 8 - (0x10c - 0x100) +# ^-- 8 - (0x10c - 0x120) # G - (GP - .got) # REL: Contents of section .reginfo: @@ -32,18 +32,18 @@ # ^-- _gp # REL: Contents of section .data: -# REL-NEXT: 00f0 fffffef4 +# REL-NEXT: 0110 fffffef4 # ^-- 0-0x10c # REL: 00000000 .text 00000000 foo # REL: 00000000 *ABS* 00000000 .hidden _gp_disp -# REL: 0000010c *ABS* 00000000 .hidden _gp +# REL: 0000010c *ABS* 00000000 _gp # ABS: Contents of section .text: -# ABS-NEXT: 0000 3c080000 21080200 8f82ff08 +# ABS-NEXT: 0000 3c080000 21080200 8f82ff28 # ^-- %hi(_gp_disp) # ^-- %lo(_gp_disp) -# ^-- 8 - (0x200 - 0x100) +# ^-- 8 - (0x200 - 0x120) # G - (GP - .got) # ABS: Contents of section .reginfo: @@ -52,12 +52,12 @@ # ^-- _gp # ABS: Contents of section .data: -# ABS-NEXT: 00f0 fffffe00 +# ABS-NEXT: 0110 fffffe00 # ^-- 0-0x200 # ABS: 00000000 .text 00000000 foo # ABS: 00000000 *ABS* 00000000 .hidden _gp_disp -# ABS: 00000200 *ABS* 00000000 .hidden _gp +# ABS: 00000200 *ABS* 00000000 _gp .text foo: