[lld] c720b16 - [ELF] Use SmallVector for SharedFile and simplify parseVerdefs

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 14 21:11:51 PST 2021


Author: Fangrui Song
Date: 2021-12-14T21:11:45-08:00
New Revision: c720b16aa56b2a3904864d5eda19f1edd301eff4

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

LOG: [ELF] Use SmallVector for SharedFile and simplify parseVerdefs

SHT_GNU_verdef is typically small, so it's unnecessary to reserve the vector.

While here, fix a hypothetical issue when SHT_GNU_verdef has non-increasing
version indexes, which don't happen with GNU ld, gold, ld.lld's output.

My x86-64 lld executable is 256 bytes smaller.

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 63f83a486d3c..8b1d1827e24e 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1318,26 +1318,21 @@ unsigned SharedFile::vernauxNum;
 // vector whose nth element contains a pointer to the Elf_Verdef for version
 // identifier n. Version identifiers that are not definitions map to nullptr.
 template <typename ELFT>
-static std::vector<const void *> parseVerdefs(const uint8_t *base,
-                                              const typename ELFT::Shdr *sec) {
+static SmallVector<const void *, 0>
+parseVerdefs(const uint8_t *base, const typename ELFT::Shdr *sec) {
   if (!sec)
     return {};
 
-  // We cannot determine the largest verdef identifier without inspecting
-  // every Elf_Verdef, but both bfd and gold assign verdef identifiers
-  // sequentially starting from 1, so we predict that the largest identifier
-  // will be verdefCount.
-  unsigned verdefCount = sec->sh_info;
-  std::vector<const void *> verdefs(verdefCount + 1);
-
   // Build the Verdefs array by following the chain of Elf_Verdef objects
   // from the start of the .gnu.version_d section.
+  SmallVector<const void *, 0> verdefs;
   const uint8_t *verdef = base + sec->sh_offset;
-  for (unsigned i = 0; i != verdefCount; ++i) {
+  for (unsigned i = 0, e = sec->sh_info; i != e; ++i) {
     auto *curVerdef = reinterpret_cast<const typename ELFT::Verdef *>(verdef);
     verdef += curVerdef->vd_next;
     unsigned verdefIndex = curVerdef->vd_ndx;
-    verdefs.resize(verdefIndex + 1);
+    if (verdefIndex >= verdefs.size())
+      verdefs.resize(verdefIndex + 1);
     verdefs[verdefIndex] = curVerdef;
   }
   return verdefs;

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index ec6f1a7ad7a2..d359a49616e2 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -368,16 +368,16 @@ class SharedFile : public ELFFileBase {
         isNeeded(!config->asNeeded) {}
 
   // This is actually a vector of Elf_Verdef pointers.
-  std::vector<const void *> verdefs;
+  SmallVector<const void *, 0> verdefs;
 
   // If the output file needs Elf_Verneed data structures for this file, this is
   // a vector of Elf_Vernaux version identifiers that map onto the entries in
   // Verdefs, otherwise it is empty.
-  std::vector<unsigned> vernauxs;
+  SmallVector<uint32_t, 0> vernauxs;
 
   static unsigned vernauxNum;
 
-  std::vector<StringRef> dtNeeded;
+  SmallVector<StringRef, 0> dtNeeded;
   StringRef soName;
 
   static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
@@ -389,7 +389,7 @@ class SharedFile : public ELFFileBase {
 
   // Non-weak undefined symbols which are not yet resolved when the SO is
   // parsed. Only filled for `--no-allow-shlib-undefined`.
-  std::vector<Symbol *> requiredSymbols;
+  SmallVector<Symbol *, 0> requiredSymbols;
 
 private:
   template <typename ELFT>


        


More information about the llvm-commits mailing list