summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-21 19:21:39 (GMT)
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-21 19:21:39 (GMT)
commit472deb37084dc269c2a9ad42579bfa762c032984 (patch)
tree49dc295525bd0be66460438fd203a5ffdcc9802b /src
parent9b794ce69129340e1b7160b9aca2910d09e34693 (diff)
downloadpatchelf-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).
Diffstat (limited to 'src')
-rw-r--r--src/patchelf.cc33
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 {