Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1676,8 +1676,9 @@ template <class ELFT> void SharedFile::parse() {

const uint16_t ver = versyms[i], idx = ver & ~VERSYM_HIDDEN;
if (sym.isUndefined()) {
// For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but
// as of binutils 2.34, GNU ld produces VER_NDX_LOCAL.
// Index 0 (VER_NDX_LOCAL) is used for unversioned undefined symbols.
// GNU ld versions between 2.35 and 2.45 also generate VER_NDX_GLOBAL
// for this case (https://sourceware.org/PR33577).
if (ver != VER_NDX_LOCAL && ver != VER_NDX_GLOBAL) {
if (idx >= verneeds.size()) {
ErrAlways(ctx) << "corrupt input file: version need index " << idx
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ class Symbol {
// represents the Verdef index within the input DSO, which will be converted
// to a Verneed index in the output. Otherwise, this represents the Verdef
// index (VER_NDX_LOCAL, VER_NDX_GLOBAL, or a named version).
// VER_NDX_LOCAL indicates a defined symbol that has been localized by a
// version script's local: directive or --exclude-libs.
uint16_t versionId;
LLVM_PREFERRED_TYPE(bool)
uint8_t versionScriptAssigned : 1;
Expand Down
5 changes: 3 additions & 2 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3784,9 +3784,10 @@ void VersionTableSection::writeTo(uint8_t *buf) {
buf += 2;
for (const SymbolTableEntry &s : getPartition(ctx).dynSymTab->getSymbols()) {
// For an unextracted lazy symbol (undefined weak), it must have been
// converted to Undefined and have VER_NDX_GLOBAL version here.
// converted to Undefined.
assert(!s.sym->isLazy());
write16(ctx, buf, s.sym->versionId);
// Undefined symbols should use index 0 when unversioned.
write16(ctx, buf, s.sym->isUndefined() ? 0 : s.sym->versionId);
buf += 2;
}
}
Expand Down
41 changes: 41 additions & 0 deletions lld/test/ELF/dso-undef-extract-lazy.s
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

# CHECK-FETCH: GLOBAL DEFAULT {{[0-9]+}} foo

## Unversioned undefined symbols also extract the archive definitions.
# RUN: yaml2obj %t/ver.yaml -o %t4.so
# RUN: ld.lld %t1.o %t4.so %t2.a -o %t.exe
# RUN: llvm-readelf --dyn-symbols %t.exe | FileCheck %s --check-prefix=CHECK-FETCH

#--- main.s
.text
.globl _start
Expand All @@ -38,3 +43,39 @@ foo:

#--- shlib.s
.global foo

#--- ver.yaml
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .gnu.version
Type: SHT_GNU_versym
Flags: [ SHF_ALLOC ]
Address: 0x0000000000200210
AddressAlign: 0x0000000000000002
EntSize: 0x0000000000000002
## We use both index 0 and 1 for unversioned undefined symbols.
## Index 1 simulates older LLD and GNU ld versions between 2.35 and 2.45.
Entries: [ 0, 0, 1 ]
- Name: .gnu.version_r
Type: SHT_GNU_verneed
Flags: [ SHF_ALLOC ]
Address: 0x0000000000200250
AddressAlign: 0x0000000000000004
Dependencies:
- Version: 1
File: dso.so.0
Entries:
- Name: v1
Hash: 1937
Flags: 0
Other: 3
DynamicSymbols:
- Name: _start
Binding: STB_GLOBAL
- Name: foo
Binding: STB_GLOBAL
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/version-script.s
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# CHECK-NEXT: Name:
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Version: 1
# CHECK-NEXT: Version: 0
# CHECK-NEXT: Name: und
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/version-script-extern-undefined.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# CHECK-NEXT: Name:
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Version: 1
# CHECK-NEXT: Version: 0
# CHECK-NEXT: Name: _Z3abbi
# CHECK-NEXT: }
# CHECK-NEXT: ]
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -1710,8 +1710,8 @@ enum { VER_FLG_BASE = 0x1, VER_FLG_WEAK = 0x2, VER_FLG_INFO = 0x4 };

// Special constants for the version table. (SHT_GNU_versym/.gnu.version)
enum {
VER_NDX_LOCAL = 0, // Unversioned local symbol
VER_NDX_GLOBAL = 1, // Unversioned global symbol
VER_NDX_LOCAL = 0, // Unversioned undefined or localized defined symbol
VER_NDX_GLOBAL = 1, // Unversioned non-local defined symbol
VERSYM_VERSION = 0x7fff, // Version Index mask
VERSYM_HIDDEN = 0x8000 // Hidden bit (non-default version)
};
Expand Down
Loading