- Notifications
You must be signed in to change notification settings - Fork 15.2k
ELF: Use index 0 for unversioned undefined symbols #168189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
ELF: Use index 0 for unversioned undefined symbols #168189
Conversation
Created using spr 1.3.5-bogner
| @llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: Fangrui Song (MaskRay) ChangesThe ELF specification is ambiguous about the version index for unversioned However, this naming is misleading for undefined symbols. As suggested in GNU ld has used index 0 for unversioned undefined symbols both before Full diff: https://github.com/llvm/llvm-project/pull/168189.diff 5 Files Affected:
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c117e3b716c1b..a7d61f48ed3d5 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -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; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 9a70c0d19c41d..0a4888fd0b196 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -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; } } diff --git a/lld/test/ELF/linkerscript/version-script.s b/lld/test/ELF/linkerscript/version-script.s index 52382eeb1245c..6b97fede00c37 100644 --- a/lld/test/ELF/linkerscript/version-script.s +++ b/lld/test/ELF/linkerscript/version-script.s @@ -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 { diff --git a/lld/test/ELF/version-script-extern-undefined.s b/lld/test/ELF/version-script-extern-undefined.s index 38114229e0ce3..010b4d5d6b63d 100644 --- a/lld/test/ELF/version-script-extern-undefined.s +++ b/lld/test/ELF/version-script-extern-undefined.s @@ -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: ] diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 39e9611c7190e..bfcf5dab47722 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -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) }; |
Created using spr 1.3.5-bogner
The GNU documentation is ambiguous about the version index for
unversioned undefined symbols. The current specification at
https://sourceware.org/gnu-gabi/program-loading-and-dynamic-linking.txt
defines VER_NDX_LOCAL (0) as "The symbol is private, and is not
available outside this object."
However, this naming is misleading for undefined symbols. As suggested in
discussions, VER_NDX_LOCAL should conceptually be VER_NDX_NONE and apply
to unversioned undefined symbols as well.
GNU ld has used index 0 for unversioned undefined symbols both before
version 2.35 (see https://sourceware.org/PR26002) and in the upcoming
2.46 release (see https://sourceware.org/PR33577). This change aligns
with GNU ld's behavior by switching from index 1 to index 0.
While here, add a test to dso-undef-extract-lazy.s that undefined
symbols of index 0 in DSO are treated as unversioned symbols.