[Git][ghc/ghc][master] Optimise ELF linker (#23464)

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Thu Jun 29 01:09:19 UTC 2023



Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC


Commits:
b3e1436f by aadaa_fgtaa at 2023-06-28T21:08:53-04:00
Optimise ELF linker (#23464)

- cache last elements of `relTable`, `relaTable` and `symbolTables` in `ocInit_ELF`
- cache shndx table in ObjectCode
- run `checkProddableBlock` only with debug rts

- - - - -


3 changed files:

- rts/Linker.c
- rts/LinkerInternals.h
- rts/linker/Elf.c


Changes:

=====================================
rts/Linker.c
=====================================
@@ -1379,6 +1379,10 @@ mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
    oc->rx_m32 = m32_allocator_new(true);
 #endif
 
+#if defined(OBJFORMAT_ELF) && defined(SHN_XINDEX)
+   oc->shndx_table = SHNDX_TABLE_UNINIT;
+#endif
+
    oc->nc_ranges = NULL;
    oc->dlopen_handle = NULL;
 


=====================================
rts/LinkerInternals.h
=====================================
@@ -360,6 +360,15 @@ struct _ObjectCode {
     m32_allocator *rw_m32, *rx_m32;
 #endif
 
+#if defined(OBJFORMAT_ELF) && defined(SHN_XINDEX)
+    /* Cached address of ELF's shndx table, or SHNDX_TABLE_UNINIT if not
+     * initialized yet. It would be better to put it info ELF-specific
+     * ObjectCodeFormatInfo, but unfortunately shndx table is needed in
+     * ocVerifyImage_ELF which runs before ObjectCodeFormatInfo is
+     * initialized by ocInit_ELF. */
+    Elf_Word *shndx_table;
+#endif
+
     /*
      * The following are only valid if .type == DYNAMIC_OBJECT
      */
@@ -371,6 +380,15 @@ struct _ObjectCode {
     NativeCodeRange *nc_ranges;
 };
 
+#if defined(OBJFORMAT_ELF) && defined(SHN_XINDEX)
+/* We cannot simply use NULL to signal uninitialised shndx_table because NULL
+ * is valid return value of get_shndx_table. Thus SHNDX_TABLE_UNINIT is defined
+ * as the address of global variable shndx_table_uninit_label, defined in
+ * rts/linker/Elf.c, which is definitely unequal to any heap-allocated address */
+extern Elf_Word shndx_table_uninit_label;
+#define SHNDX_TABLE_UNINIT (&shndx_table_uninit_label)
+#endif
+
 #define OC_INFORMATIVE_FILENAME(OC)             \
     ( (OC)->archiveMemberName ?                 \
       (OC)->archiveMemberName :                 \


=====================================
rts/linker/Elf.c
=====================================
@@ -132,6 +132,11 @@
 
 */
 
+#if defined(SHN_XINDEX)
+/* global variable which address is used to signal an uninitialised shndx_table */
+Elf_Word shndx_table_uninit_label = 0;
+#endif
+
 static Elf_Word elf_shnum(Elf_Ehdr* ehdr)
 {
    Elf_Shdr* shdr = (Elf_Shdr*) ((char*)ehdr + ehdr->e_shoff);
@@ -154,16 +159,22 @@ static Elf_Word elf_shstrndx(Elf_Ehdr* ehdr)
 
 #if defined(SHN_XINDEX)
 static Elf_Word*
-get_shndx_table(Elf_Ehdr* ehdr)
+get_shndx_table(ObjectCode* oc)
 {
+   if (RTS_LIKELY(oc->shndx_table != SHNDX_TABLE_UNINIT)) {
+      return oc->shndx_table;
+   }
+
    Elf_Word  i;
-   char*     ehdrC    = (char*)ehdr;
+   char*     ehdrC    = oc->image;
+   Elf_Ehdr* ehdr     = (Elf_Ehdr*)ehdrC;
    Elf_Shdr* shdr     = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
    const Elf_Word shnum = elf_shnum(ehdr);
 
    for (i = 0; i < shnum; i++) {
      if (shdr[i].sh_type == SHT_SYMTAB_SHNDX) {
-       return (Elf32_Word*)(ehdrC + shdr[i].sh_offset);
+       oc->shndx_table = (Elf32_Word*)(ehdrC + shdr[i].sh_offset);
+       return oc->shndx_table;
      }
    }
    return NULL;
@@ -193,6 +204,10 @@ ocInit_ELF(ObjectCode * oc)
 
     oc->n_sections = elf_shnum(oc->info->elfHeader);
 
+    ElfRelocationTable *relTableLast = NULL;
+    ElfRelocationATable *relaTableLast = NULL;
+    ElfSymbolTable *symbolTablesLast = NULL;
+
     /* get the symbol table(s) */
     for(int i=0; i < oc->n_sections; i++) {
         if(SHT_REL  == oc->info->sectionHeader[i].sh_type) {
@@ -210,12 +225,12 @@ ocInit_ELF(ObjectCode * oc)
 
             relTab->sectionHeader      = &oc->info->sectionHeader[i];
 
-            if(oc->info->relTable == NULL) {
+            if(relTableLast == NULL) {
                 oc->info->relTable = relTab;
+                relTableLast = relTab;
             } else {
-                ElfRelocationTable * tail = oc->info->relTable;
-                while(tail->next != NULL) tail = tail->next;
-                tail->next = relTab;
+                relTableLast->next = relTab;
+                relTableLast = relTab;
             }
 
         } else if(SHT_RELA == oc->info->sectionHeader[i].sh_type) {
@@ -233,12 +248,12 @@ ocInit_ELF(ObjectCode * oc)
 
             relTab->sectionHeader      = &oc->info->sectionHeader[i];
 
-            if(oc->info->relaTable == NULL) {
+            if(relaTableLast == NULL) {
                 oc->info->relaTable = relTab;
+                relaTableLast = relTab;
             } else {
-                ElfRelocationATable * tail = oc->info->relaTable;
-                while(tail->next != NULL) tail = tail->next;
-                tail->next = relTab;
+                relaTableLast->next = relTab;
+                relaTableLast = relTab;
             }
 
         } else if(SHT_SYMTAB == oc->info->sectionHeader[i].sh_type) {
@@ -279,12 +294,12 @@ ocInit_ELF(ObjectCode * oc)
             }
 
             /* append the ElfSymbolTable */
-            if(oc->info->symbolTables == NULL) {
+            if(symbolTablesLast == NULL) {
                 oc->info->symbolTables = symTab;
+                symbolTablesLast = symTab;
             } else {
-                ElfSymbolTable * tail = oc->info->symbolTables;
-                while(tail->next != NULL) tail = tail->next;
-                tail->next = symTab;
+                symbolTablesLast->next = symTab;
+                symbolTablesLast = symTab;
             }
         }
     }
@@ -329,6 +344,9 @@ ocDeinit_ELF(ObjectCode * oc)
 
         stgFree(oc->info);
         oc->info = NULL;
+#if defined(SHN_XINDEX)
+        oc->shndx_table = SHNDX_TABLE_UNINIT;
+#endif
     }
 }
 
@@ -532,7 +550,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       IF_DEBUG(linker_verbose,debugBelch("   no normal string tables (potentially, but not necessarily a problem)\n"));
    }
 #if defined(SHN_XINDEX)
-   Elf_Word* shndxTable = get_shndx_table(ehdr);
+   Elf_Word* shndxTable = get_shndx_table(oc);
 #endif
    nsymtabs = 0;
    IF_DEBUG(linker_verbose,debugBelch( "Symbol tables\n" ));
@@ -683,7 +701,7 @@ ocGetNames_ELF ( ObjectCode* oc )
    Elf_Shdr* shdr     = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
    Section * sections;
 #if defined(SHN_XINDEX)
-   Elf_Word* shndxTable = get_shndx_table(ehdr);
+   Elf_Word* shndxTable = get_shndx_table(oc);
 #endif
    const Elf_Word shnum = elf_shnum(ehdr);
 
@@ -1251,7 +1269,11 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
        IF_DEBUG(linker_verbose,
                 debugBelch("Reloc: P = %p   S = %p   A = %p   type=%d\n",
                            (void*)P, (void*)S, (void*)A, reloc_type ));
+#if defined(DEBUG)
        checkProddableBlock ( oc, pP, sizeof(Elf_Word) );
+#else
+       (void) pP; /* suppress unused varialbe warning in non-debug build */
+#endif
 
 #if defined(i386_HOST_ARCH)
        value = S + A;
@@ -1555,7 +1577,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
    int strtab_shndx = shdr[symtab_shndx].sh_link;
    int target_shndx = shdr[shnum].sh_info;
 #if defined(SHN_XINDEX)
-   Elf_Word* shndx_table = get_shndx_table((Elf_Ehdr*)ehdrC);
+   Elf_Word* shndx_table = get_shndx_table(oc);
 #endif
 #if defined(DEBUG) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
    /* This #if def only serves to avoid unused-var warnings. */
@@ -1657,7 +1679,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
          IF_DEBUG(linker_verbose,debugBelch("`%s' resolves to %p\n", symbol, (void*)S));
       }
 
-#if defined(DEBUG) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
+#if defined(DEBUG)
       IF_DEBUG(linker_verbose,debugBelch("Reloc: P = %p   S = %p   A = %p\n",
                                          (void*)P, (void*)S, (void*)A ));
       checkProddableBlock(oc, (void*)P, sizeof(Elf_Word));
@@ -1920,7 +1942,7 @@ ocResolve_ELF ( ObjectCode* oc )
    const Elf_Word shnum = elf_shnum(ehdr);
 
 #if defined(SHN_XINDEX)
-    Elf_Word* shndxTable = get_shndx_table(ehdr);
+    Elf_Word* shndxTable = get_shndx_table(oc);
 #endif
 
     /* resolve section symbols



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b3e1436f968c0c36a27ea0339ee2554970b329fe

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b3e1436f968c0c36a27ea0339ee2554970b329fe
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230628/84dfcc2c/attachment-0001.html>


More information about the ghc-commits mailing list