[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