Make Verdef and Verdaux adjacent in the version definition section.
authorRui Ueyama <ruiu@google.com>
Sat, 16 Jul 2016 02:29:45 +0000 (02:29 +0000)
committerRui Ueyama <ruiu@google.com>
Sat, 16 Jul 2016 02:29:45 +0000 (02:29 +0000)
Previously, Verdefs and Verdauxs are separated in the section.
The new layout is easier to write as we do not have to maintain
two pointers and can avoid passing a reference to a pointer.

llvm-svn: 275665

lld/ELF/OutputSections.cpp
lld/ELF/OutputSections.h

index 573c7f7..1ff94f6 100644 (file)
@@ -1498,39 +1498,35 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
   this->Header.sh_info = getVerDefNum();
 }
 
-template <class Elf_Verdef, class Elf_Verdaux>
-static void writeDefinition(Elf_Verdef *&Verdef, Elf_Verdaux *&Verdaux,
-                            uint32_t Flags, uint32_t Index, StringRef Name,
-                            size_t StrTabOffset) {
+template <class ELFT>
+void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index,
+                                              StringRef Name, size_t NameOff) {
+  auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
   Verdef->vd_version = 1;
   Verdef->vd_cnt = 1;
-  Verdef->vd_aux =
-      reinterpret_cast<char *>(Verdaux) - reinterpret_cast<char *>(Verdef);
-  Verdef->vd_next = sizeof(Elf_Verdef);
-
-  Verdef->vd_flags = Flags;
+  Verdef->vd_aux = sizeof(Elf_Verdef);
+  Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
+  Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0);
   Verdef->vd_ndx = Index;
   Verdef->vd_hash = hashSysv(Name);
-  ++Verdef;
 
-  Verdaux->vda_name = StrTabOffset;
+  auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef));
+  Verdaux->vda_name = NameOff;
   Verdaux->vda_next = 0;
-  ++Verdaux;
 }
 
 template <class ELFT>
 void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
-  Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
-  Elf_Verdaux *Verdaux =
-      reinterpret_cast<Elf_Verdaux *>(Verdef + getVerDefNum());
-
-  writeDefinition(Verdef, Verdaux, VER_FLG_BASE, 1, getFileDefName(),
-                  FileDefNameOff);
+  writeOne(Buf, 1, getFileDefName(), FileDefNameOff);
 
-  for (Version &V : Config->SymbolVersions)
-    writeDefinition(Verdef, Verdaux, 0, V.Id, V.Name, V.NameOff);
+  for (Version &V : Config->SymbolVersions) {
+    Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
+    writeOne(Buf, V.Id, V.Name, V.NameOff);
+  }
 
-  Verdef[-1].vd_next = 0;
+  // Need to terminate the last version definition.
+  Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
+  Verdef->vd_next = 0;
 }
 
 template <class ELFT>
index 1f6ea1a..1dbd7d8 100644 (file)
@@ -262,12 +262,15 @@ class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
   typedef typename ELFT::Verdef Elf_Verdef;
   typedef typename ELFT::Verdaux Elf_Verdaux;
 
-  unsigned FileDefNameOff;
-
 public:
   VersionDefinitionSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
+
+private:
+  void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff);
+
+  unsigned FileDefNameOff;
 };
 
 // The .gnu.version section specifies the required version of each symbol in the