From 631d2e2b1b0d8fa2bb4c35986dfb34110f3a5113 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 29 Nov 2023 14:19:51 +0000 Subject: [PATCH] Add support for SHT_RELA in vkgc Currently LLVM generates relocations in an ELF SHT_REL section. To allow for changing the compiler to use SHT_RELA instead, this patch updates vkgcElfReader and vkgcPipelineDumper to support both section types. --- tool/dumper/vkgcPipelineDumper.cpp | 7 ++++-- util/vkgcElfReader.cpp | 28 +++++++++++++++++------- util/vkgcElfReader.h | 35 +++++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/tool/dumper/vkgcPipelineDumper.cpp b/tool/dumper/vkgcPipelineDumper.cpp index adfb82b15a..3691e649f7 100644 --- a/tool/dumper/vkgcPipelineDumper.cpp +++ b/tool/dumper/vkgcPipelineDumper.cpp @@ -2065,7 +2065,7 @@ OStream &operator<<(OStream &out, ElfReader &reader) { offset += noteHeaderSize + noteNameSize + alignTo(node->descSize, sizeof(unsigned)); assert(offset <= section->secHead.sh_size); } - } else if (strcmp(section->name, RelocName) == 0) { + } else if (strcmp(section->name, RelocName) == 0 || strcmp(section->name, RelocAName) == 0) { // Output .reloc section out << section->name << " (size = " << section->secHead.sh_size << " bytes)\n"; const unsigned relocCount = reader.getRelocationCount(); @@ -2075,7 +2075,10 @@ OStream &operator<<(OStream &out, ElfReader &reader) { ElfSymbol elfSym = {}; reader.getSymbol(reloc.symIdx, &elfSym); snprintf(formatBuf, sizeof(formatBuf), " %-35s", elfSym.pSymName); - out << "#" << i << " " << formatBuf << " offset = " << reloc.offset << "\n"; + out << "#" << i << " " << formatBuf << " offset = " << reloc.offset; + if (reloc.useExplicitAddend) + out << ", addend = " << reloc.addend; + out << "\n"; } } else if (strncmp(section->name, AmdGpuConfigName, sizeof(AmdGpuConfigName) - 1) == 0) { // Output .AMDGPU.config section diff --git a/util/vkgcElfReader.cpp b/util/vkgcElfReader.cpp index 1216d0d88d..12f5975e08 100644 --- a/util/vkgcElfReader.cpp +++ b/util/vkgcElfReader.cpp @@ -137,6 +137,8 @@ template Result ElfReader::ReadFromBuffer(const void *buffer, s // Get section index m_symSecIdx = GetSectionIndex(SymTabName); m_relocSecIdx = GetSectionIndex(RelocName); + if (m_relocSecIdx < 0) + m_relocSecIdx = GetSectionIndex(RelocAName); m_strtabSecIdx = GetSectionIndex(StrTabName); m_textSecIdx = GetSectionIndex(TextName); @@ -210,14 +212,24 @@ template unsigned ElfReader::getRelocationCount() const { // @param idx : Relocation index // @param [out] reloc : Info of the relocation template void ElfReader::getRelocation(unsigned idx, ElfReloc *reloc) const { - auto §ion = m_sections[m_relocSecIdx]; - - auto relocs = reinterpret_cast(section->data); - reloc->offset = relocs[idx].r_offset; - reloc->symIdx = relocs[idx].r_symbol; - reloc->type = relocs[idx].r_type; - reloc->addend = 0; - reloc->useExplicitAddend = false; + auto *section = m_sections[m_relocSecIdx]; + + if (section->secHead.sh_type == SHT_REL) { + auto relocs = reinterpret_cast(section->data); + reloc->offset = relocs[idx].r_offset; + reloc->symIdx = relocs[idx].r_symbol; + reloc->type = relocs[idx].r_type; + reloc->addend = 0; + reloc->useExplicitAddend = false; + } else { + assert(section->secHead.sh_type == SHT_RELA); + auto relocs = reinterpret_cast(section->data); + reloc->offset = relocs[idx].r_offset; + reloc->symIdx = relocs[idx].r_symbol; + reloc->type = relocs[idx].r_type; + reloc->addend = relocs[idx].r_addend; + reloc->useExplicitAddend = true; + } } // ===================================================================================================================== diff --git a/util/vkgcElfReader.h b/util/vkgcElfReader.h index 504c21f94c..6d0b7dafa4 100644 --- a/util/vkgcElfReader.h +++ b/util/vkgcElfReader.h @@ -129,6 +129,8 @@ enum ElfSectionHeaderTypes : uint32_t { SHT_HASH = 5, // Symbol hash table SHT_DYNAMIC = 6, // Information for dynamic linking SHT_NOTE = 7, // Information about the file + SHT_NOBITS = 8, // Data occupies no space in the file + SHT_REL = 9, // Relocation entries; no explicit addends }; // Enumerates ELF Section flags. @@ -150,7 +152,8 @@ static const char ShStrTabName[] = ".shstrtab"; // Name of ".shstrtab" section static const char StrTabName[] = ".strtab"; // Name of ".strtab" section static const char SymTabName[] = ".symtab"; // Name of ".symtab" section static const char NoteName[] = ".note"; // Name of ".note" section -static const char RelocName[] = ".rel.text"; // Name of ".reloc" section +static const char RelocName[] = ".rel.text"; // Name of SHT_REL section +static const char RelocAName[] = ".rela.text"; // Name of SHT_RELA section static const char CommentName[] = ".comment"; // Name of ".comment" section static const uint32_t NT_AMD_AMDGPU_ISA = 11; // Note type of AMDGPU ISA version @@ -221,7 +224,7 @@ struct Elf32 { uint16_t st_shndx; // Which section (header table index) it's defined in }; - // ELF relocation entry (without explicit append) + // ELF relocation entry (without explicit addend) struct Reloc { uint32_t r_offset; // Location (file byte offset, or program virtual address) union { @@ -233,6 +236,19 @@ struct Elf32 { }; }; + // ELF relocation entry with explicit addend + struct RelocA { + uint32_t r_offset; // Location (file byte offset, or program virtual address) + union { + uint32_t r_info; // Symbol table index and type of relocation to apply + struct { + uint32_t r_type : 8; // Type of relocation + uint32_t r_symbol : 24; // Index of the symbol in the symbol table + }; + }; + uint32_t r_addend; // Compute value for relocatable field by adding this + }; + // ELF program header struct Phdr { uint32_t p_type; // Type of segment @@ -301,7 +317,7 @@ struct Elf64 { uint64_t st_size; // Size of the symbol }; - // ELF relocation entry + // ELF relocation entry (without explicit addend) struct Reloc { uint64_t r_offset; // Location (file byte offset, or program virtual address) union { @@ -313,6 +329,19 @@ struct Elf64 { }; }; + // ELF relocation entry with explicit addend + struct RelocA { + uint64_t r_offset; // Location (file byte offset, or program virtual address) + union { + uint64_t r_info; // Symbol table index and type of relocation to apply + struct { + uint32_t r_type; // Type of relocation + uint32_t r_symbol; // Index of the symbol in the symbol table + }; + }; + uint64_t r_addend; // Compute value for relocatable field by adding this + }; + // ELF program header struct Phdr { uint32_t p_type; // Type of segment