[lld] 498151d - [ELF] SharedFile::parse: make versym handling more precise

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 4 16:21:27 PDT 2022


Author: Fangrui Song
Date: 2022-09-04T16:21:19-07:00
New Revision: 498151d94461be5516cc9f269d691c894af2452f

URL: https://github.com/llvm/llvm-project/commit/498151d94461be5516cc9f269d691c894af2452f
DIFF: https://github.com/llvm/llvm-project/commit/498151d94461be5516cc9f269d691c894af2452f.diff

LOG: [ELF] SharedFile::parse: make versym handling more precise

VER_NDX_LOCAL/VER_NDX_GLOBAL cannot be hidden, so we can compare them with
versyms[i] instead of versyms[i] & ~VERSYM_HIDDEN. In the presence of an error,
we can suppress addSymbol.

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 0290244efe2f..4c9846d7fff8 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1461,11 +1461,11 @@ template <class ELFT> void SharedFile::parse() {
       continue;
     }
 
-    uint16_t idx = versyms[i] & ~VERSYM_HIDDEN;
+    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.
-      if (idx != VER_NDX_LOCAL && idx != VER_NDX_GLOBAL) {
+      if (ver != VER_NDX_LOCAL && ver != VER_NDX_GLOBAL) {
         if (idx >= verneeds.size()) {
           error("corrupt input file: version need index " + Twine(idx) +
                 " for symbol " + name + " is out of bounds\n>>> defined in " +
@@ -1486,34 +1486,33 @@ template <class ELFT> void SharedFile::parse() {
       continue;
     }
 
-    // In GNU ld < 2.31 (before 3be08ea4728b56d35e136af4e6fd3086ade17764), the
-    // MIPS port puts _gp_disp symbol into DSO files and incorrectly assigns
-    // VER_NDX_LOCAL. Workaround this bug.
-    if (idx == VER_NDX_LOCAL && config->emachine == EM_MIPS &&
-        name == "_gp_disp")
+    if (ver == VER_NDX_LOCAL ||
+        (ver != VER_NDX_GLOBAL && idx >= verdefs.size())) {
+      // In GNU ld < 2.31 (before 3be08ea4728b56d35e136af4e6fd3086ade17764), the
+      // MIPS port puts _gp_disp symbol into DSO files and incorrectly assigns
+      // VER_NDX_LOCAL. Workaround this bug.
+      if (config->emachine == EM_MIPS && name == "_gp_disp")
+        continue;
+      error("corrupt input file: version definition index " + Twine(idx) +
+            " for symbol " + name + " is out of bounds\n>>> defined in " +
+            toString(this));
       continue;
+    }
 
     uint32_t alignment = getAlignment<ELFT>(sections, sym);
-    if (!(versyms[i] & VERSYM_HIDDEN)) {
+    if (ver == idx) {
       auto *s = symtab.addSymbol(
           SharedSymbol{*this, name, sym.getBinding(), sym.st_other,
                        sym.getType(), sym.st_value, sym.st_size, alignment});
       if (s->file == this)
-        s->verdefIndex = idx;
+        s->verdefIndex = ver;
     }
 
     // Also add the symbol with the versioned name to handle undefined symbols
     // with explicit versions.
-    if (idx == VER_NDX_GLOBAL)
+    if (ver == VER_NDX_GLOBAL)
       continue;
 
-    if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) {
-      error("corrupt input file: version definition index " + Twine(idx) +
-            " for symbol " + name + " is out of bounds\n>>> defined in " +
-            toString(this));
-      continue;
-    }
-
     StringRef verName =
         stringTable.data() +
         reinterpret_cast<const Elf_Verdef *>(verdefs[idx])->getAux()->vda_name;


        


More information about the llvm-commits mailing list