Update symbols for secondary entry points

Summary:
Update the output ELF symbol table for symbols representing
secondary entry points for functions. Previously, those were left
unchanged in the symtab.

Reviewed By: maksfb

Differential Revision: D15010517

fbshipit-source-id: 330f12580c1
This commit is contained in:
Rafael Auler 2019-04-18 16:32:22 -07:00 committed by Facebook Github Bot
parent 449c43120f
commit 32fd328ade
3 changed files with 38 additions and 10 deletions

View File

@ -1242,7 +1242,8 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF) {
BinaryFunction *
BinaryContext::getBinaryFunctionContainingAddress(uint64_t Address,
bool CheckPastEnd,
bool UseMaxSize) {
bool UseMaxSize,
bool Shallow) {
auto FI = BinaryFunctions.upper_bound(Address);
if (FI == BinaryFunctions.begin())
return nullptr;
@ -1255,6 +1256,9 @@ BinaryContext::getBinaryFunctionContainingAddress(uint64_t Address,
return nullptr;
auto *BF = &FI->second;
if (Shallow)
return BF;
while (BF->getParentFunction())
BF = BF->getParentFunction();

View File

@ -56,6 +56,7 @@ using namespace object;
namespace bolt {
class BinaryFunction;
class BinaryBasicBlock;
class DataReader;
/// Helper function to truncate a \p Value to given size in \p Bytes.
@ -183,7 +184,8 @@ public:
/// body and the next object in address ranges that we check.
BinaryFunction *getBinaryFunctionContainingAddress(uint64_t Address,
bool CheckPastEnd = false,
bool UseMaxSize = false);
bool UseMaxSize = false,
bool Shallow = false);
/// Return BinaryFunction which has a fragment that starts at a given
/// \p Address. If the BinaryFunction is a child fragment, then return its

View File

@ -3307,8 +3307,9 @@ void RewriteInstance::updateOutputValues(const MCAsmLayout &Layout) {
Layout.getSymbolOffset(*Function.getFunctionEndLabel()));
}
// Update basic block output ranges only for the debug info.
if (!opts::UpdateDebugSections)
// Update basic block output ranges only for the debug info or if we have
// secondary entry points in the symbol table to update
if (!opts::UpdateDebugSections && !Function.isMultiEntry())
return;
// Output ranges should match the input if the body hasn't changed.
@ -4042,11 +4043,17 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
for (const Elf_Sym &Symbol : cantFail(Obj->symbols(Section))) {
auto NewSymbol = Symbol;
const auto *Function = BC->getBinaryFunctionAtAddress(Symbol.st_value,
/*Shallow=*/true);
const auto *Function =
BC->getBinaryFunctionContainingAddress(NewSymbol.st_value,
/*CheckPastEnd=*/false,
/*UseMaxSize=*/true,
/*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();
@ -4102,9 +4109,24 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
uint32_t OldSectionIndex = NewSymbol.st_shndx;
auto *BD = !Function ? BC->getBinaryDataAtAddress(NewSymbol.st_value)
: nullptr;
if (BD && BD->isMoved() && !BD->isJumpTable()) {
assert((!BD->getSize() ||
!NewSymbol.st_size ||
auto Output =
Function && !Function->getPLTSymbol()
? Function->translateInputToOutputAddress(NewSymbol.st_value)
: 0;
// Handle secondary entry points for this function
// (when Function->getAddress() != Symbol.st_value)
if (Output && NewSymbol.getType() != ELF::STT_SECTION) {
NewSymbol.st_value = Output;
// Force secondary entry points to have zero size
NewSymbol.st_size = 0;
NewSymbol.st_shndx = Output >= Function->cold().getAddress() &&
Output < Function->cold().getImageSize()
? Function->getColdCodeSection()->getIndex()
: Function->getCodeSection()->getIndex();
OldSectionIndex = ELF::SHN_LORESERVE;
} else if (BD && BD->isMoved() && !BD->isJumpTable()) {
assert((!BD->getSize() || !NewSymbol.st_size ||
NewSymbol.st_size == BD->getSize()) &&
"sizes must match");
@ -4133,7 +4155,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
if (NewSymbol.getType() == ELF::STT_NOTYPE &&
NewSymbol.getBinding() == ELF::STB_LOCAL &&
NewSymbol.st_size == 0) {
auto ExpectedSec = File->getELFFile()->getSection(OldSectionIndex);
auto ExpectedSec = File->getELFFile()->getSection(Symbol.st_shndx);
if (ExpectedSec) {
auto Section = *ExpectedSec;
if (Section->sh_type == ELF::SHT_PROGBITS &&