[BOLT] Fix symboltable update bug

Summary:
Commit "Update symbols for secondary entry points" introduced
a bug by using getBinaryFunctionContainingAddress() instead of
getBinaryFunctionAtAddress() regarding ICF'd functions. Only the latter
would fetch the correct BinaryFunction object for addresses of functions
that were ICF'd. As a result of this bug, the dynamic symbol table was
not updated for function symbols that were folded by ICF.

(cherry picked from FBD15112941)
This commit is contained in:
Rafael Auler 2019-04-26 19:52:36 -07:00 committed by Maksim Panchenko
parent caa0fafa18
commit 21ee0e98c7
1 changed files with 32 additions and 23 deletions

View File

@ -4057,16 +4057,12 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
for (const Elf_Sym &Symbol : cantFail(Obj->symbols(Section))) {
auto NewSymbol = Symbol;
const auto *Function =
BC->getBinaryFunctionContainingAddress(NewSymbol.st_value,
/*CheckPastEnd=*/false,
/*UseMaxSize=*/true,
/*Shallow=*/true);
const auto *Function = BC->getBinaryFunctionAtAddress(Symbol.st_value,
/*Shallow=*/true);
// Some section symbols may be mistakenly associated with the first
// function emitted in the section. Dismiss if it is a section symbol.
if (Function &&
Function->getAddress() == NewSymbol.st_value &&
!Function->getPLTSymbol() &&
NewSymbol.getType() != ELF::STT_SECTION) {
NewSymbol.st_value = Function->getOutputAddress();
@ -4120,6 +4116,28 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
}
} else {
uint32_t OldSectionIndex = NewSymbol.st_shndx;
// Check if the original section where this symbol links to is
// code that we may have reordered.
auto ExpectedSec = File->getELFFile()->getSection(Symbol.st_shndx);
bool IsCodeSym{false};
if (ExpectedSec) {
auto Section = *ExpectedSec;
IsCodeSym = (Section->sh_type == ELF::SHT_PROGBITS &&
Section->sh_flags & ELF::SHF_ALLOC &&
Section->sh_flags & ELF::SHF_EXECINSTR &&
!(Section->sh_flags & ELF::SHF_WRITE));
} else {
consumeError(ExpectedSec.takeError());
}
// Try to fetch a containing function to check if this symbol is
// a secondary entry point of it
if (!Function && IsCodeSym && NewSymbol.getType() == ELF::STT_FUNC) {
Function =
BC->getBinaryFunctionContainingAddress(NewSymbol.st_value,
/*CheckPastEnd=*/false,
/*UseMaxSize=*/true,
/*Shallow=*/true);
}
auto *BD = !Function ? BC->getBinaryDataAtAddress(NewSymbol.st_value)
: nullptr;
auto Output =
@ -4167,23 +4185,14 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
// .text (t15274167). Remove then from the symtab.
if (NewSymbol.getType() == ELF::STT_NOTYPE &&
NewSymbol.getBinding() == ELF::STB_LOCAL &&
NewSymbol.st_size == 0) {
auto ExpectedSec = File->getELFFile()->getSection(Symbol.st_shndx);
if (ExpectedSec) {
auto Section = *ExpectedSec;
if (Section->sh_type == ELF::SHT_PROGBITS &&
Section->sh_flags & ELF::SHF_ALLOC &&
Section->sh_flags & ELF::SHF_EXECINSTR) {
// This will cause the symbol to not be emitted if we are
// creating a new symtab from scratch instead of patching one.
if (!PatchExisting)
continue;
// If patching an existing symtab, patch this value to zero.
NewSymbol.st_value = 0;
}
} else {
consumeError(ExpectedSec.takeError());
}
NewSymbol.st_size == 0 &&
IsCodeSym) {
// This will cause the symbol to not be emitted if we are
// creating a new symtab from scratch instead of patching one.
if (!PatchExisting)
continue;
// If patching an existing symtab, patch this value to zero.
NewSymbol.st_value = 0;
}
}