diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2012-08-21 19:21:39 (GMT) |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2012-08-21 19:21:39 (GMT) |
commit | 472deb37084dc269c2a9ad42579bfa762c032984 (patch) | |
tree | 49dc295525bd0be66460438fd203a5ffdcc9802b | |
parent | 9b794ce69129340e1b7160b9aca2910d09e34693 (diff) | |
download | patchelf-472deb37084dc269c2a9ad42579bfa762c032984.zip patchelf-472deb37084dc269c2a9ad42579bfa762c032984.tar.gz patchelf-472deb37084dc269c2a9ad42579bfa762c032984.tar.bz2 |
Rewrite the st_shndx field in symbol tables
The st_shndx field in symbol tables specifies the index of the section
that contains the symbol. Since we reorder sections, we need to
update this field as well. Otherwise programs like gdb won't be able
to resolve addresses to symbol names (and will print "?? ()" instead).
-rw-r--r-- | src/patchelf.cc | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc index cf79310..e1520a8 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -40,8 +40,8 @@ off_t fileSize, maxSize; unsigned char * contents = 0; -#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn -#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn +#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym +#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym template<ElfFileParams> @@ -68,6 +68,8 @@ class ElfFile respectively. */ unsigned int sectionAlignment; + vector<SectionName> sectionsByOldIndex; + public: ElfFile() @@ -293,6 +295,10 @@ void ElfFile<ElfFileParamNames>::parse() assert(shstrtab[shstrtabSize - 1] == 0); sectionNames = string(shstrtab, shstrtabSize); + + sectionsByOldIndex.resize(hdr->e_shnum); + for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) + sectionsByOldIndex[i] = getSectionName(shdrs[i]); } @@ -816,6 +822,25 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress) else if (d_tag == DT_VERSYM) dyn->d_un.d_ptr = findSection(".gnu.version").sh_addr; } + + + /* Rewrite the .dynsym section. It contains the indices of the + sections in which symbols appear, so these need to be + remapped. */ + for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) { + if (rdi(shdrs[i].sh_type) != SHT_SYMTAB && rdi(shdrs[i].sh_type) != SHT_DYNSYM) continue; + debug("rewriting symbol table section %d\n", i); + for (size_t entry = 0; (entry + 1) * sizeof(Elf_Sym) <= rdi(shdrs[i].sh_size); entry++) { + Elf_Sym * sym = (Elf_Sym *) (contents + rdi(shdrs[i].sh_offset) + entry * sizeof(Elf_Sym)); + if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) { + string section = sectionsByOldIndex[rdi(sym->st_shndx)]; + assert(!section.empty()); + unsigned int newIndex = findSection3(section); // inefficient + debug("rewriting symbol %d: index = %d (%s) -> %d\n", entry, rdi(sym->st_shndx), section.c_str(), newIndex); + wri(sym->st_shndx, newIndex); + } + } + } } @@ -1079,13 +1104,13 @@ static void patchElf() if (contents[EI_CLASS] == ELFCLASS32 && contents[EI_VERSION] == EV_CURRENT) { - ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn> elfFile; + ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym> elfFile; patchElf2(elfFile, fileMode); } else if (contents[EI_CLASS] == ELFCLASS64 && contents[EI_VERSION] == EV_CURRENT) { - ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn> elfFile; + ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym> elfFile; patchElf2(elfFile, fileMode); } else { |