[BOLT] Update SDTs based on translation tables

Summary:
We've used to emit special annotations to update SDT markers. However,
we can just use "Offset" annotations for the same purpose. Unlike BAT,
we have to generate "reverse" address translation tables.
This approach eliminates reliance on instructions after code emission.

(cherry picked from FBD18318660)
This commit is contained in:
Maksim Panchenko 2019-11-03 21:57:15 -08:00
parent 98e63610b1
commit f2b257bec8
9 changed files with 207 additions and 197 deletions

View File

@ -15,6 +15,7 @@
#include "ParallelUtilities.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include <limits>
@ -589,5 +590,27 @@ BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
return NewBlock;
}
void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) {
if (!LocSyms)
return;
const auto BBAddress = getOutputAddressRange().first;
const auto BBOffset = Layout.getSymbolOffset(*getLabel());
for (const auto &LocSymKV : *LocSyms) {
const uint32_t InputFunctionOffset = LocSymKV.first;
const uint32_t OutputOffset = static_cast<uint32_t>(
Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
getOffsetTranslationTable().emplace_back(
std::make_pair(OutputOffset, InputFunctionOffset));
// Update reverse (relative to BAT) address lookup table for function.
if (getFunction()->hasSDTMarker()) {
getFunction()->getInputOffsetToAddressMap().emplace(
std::make_pair(InputFunctionOffset, OutputOffset + BBAddress));
}
}
LocSyms.reset(nullptr);
}
} // namespace bolt
} // namespace llvm

View File

@ -86,16 +86,20 @@ private:
/// Original offset range of the basic block in the function.
std::pair<uint32_t, uint32_t> InputRange{INVALID_OFFSET, INVALID_OFFSET};
/// Map input offset of an instruction to an output symbol. Enables writing
/// bolt address translation tables, used for mapping control transfer in the
/// output binary back to the original binary.
/// Map input offset (from function start) of an instruction to an output
/// symbol. Enables writing BOLT address translation tables used for mapping
/// control transfer in the output binary back to the original binary.
using LocSymsTy = std::vector<std::pair<uint32_t, const MCSymbol *>>;
std::unique_ptr<LocSymsTy> LocSyms;
/// Map input offsets in the basic block to output offsets.
/// After output/codegen, map output offsets of instructions in this basic
/// block to instruction offsets in the original function. Note that the
/// output basic block could be different from the input basic block.
/// We only map instruction of interest, such as calls, and sdt markers.
///
/// NOTE: map only instruction of interest, such as calls.
using OffsetTranslationTableTy = std::vector<std::pair<uint16_t, uint16_t>>;
/// We store the offset array in a basic block to facilitate BAT tables
/// generation. Otherwise, the mapping could be done at function level.
using OffsetTranslationTableTy = std::vector<std::pair<uint32_t, uint32_t>>;
std::unique_ptr<OffsetTranslationTableTy> OffsetTranslationTable;
/// Alignment requirements for the block.
@ -828,6 +832,9 @@ public:
return OutputAddressRange;
}
/// Update addresses of special instructions inside this basic block.
void updateOutputValues(const MCAsmLayout &Layout);
/// Return mapping of input offsets to symbols in the output.
LocSymsTy &getLocSyms() {
return LocSyms ? *LocSyms : *(LocSyms = std::make_unique<LocSymsTy>());

View File

@ -20,6 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@ -1730,22 +1731,13 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
const auto InstrInputAddr = I->first + Address;
bool IsSDTMarker =
MIB->isNoop(Instr) && BC.SDTMarkers.count(InstrInputAddr);
if (IsSDTMarker) {
HasSDTMarker = true;
DEBUG(dbgs() << "SDTMarker detected in the input at : "
<< utohexstr(InstrInputAddr) << "\n");
MIB->addAnnotation<uint64_t>(Instr, "SDTMarker", InstrInputAddr,
AllocatorId);
// This mutex is used to lock concurrent writes to GlobalSymbols and
// BinaryDataMap that happens in registerNameAtAddress
{
static std::shared_timed_mutex GlobalSymbolCreationMtx;
std::unique_lock<std::shared_timed_mutex> Lock(GlobalSymbolCreationMtx);
BC.SDTMarkers[InstrInputAddr].Label =
getOrCreateLocalLabel(InstrInputAddr);
if (!MIB->hasAnnotation(Instr, "Offset")) {
MIB->addAnnotation(Instr, "Offset", static_cast<uint32_t>(Offset),
AllocatorId);
}
}
@ -1947,11 +1939,10 @@ void BinaryFunction::postProcessCFG() {
clearList(IgnoredBranches);
clearList(EntryOffsets);
// Remove "Offset" annotations, unless we need to write a BOLT address
// translation table later. This has no cost, since annotations are allocated
// by a bumpptr allocator and won't be released anyway until late in the
// pipeline.
if (!opts::EnableBAT && !opts::Instrument)
// Remove "Offset" annotations, unless we need an address-translation table
// later. This has no cost, since annotations are allocated by a bumpptr
// allocator and won't be released anyway until late in the pipeline.
if (!requiresAddressTranslation() && !opts::Instrument)
for (auto *BB : layout())
for (auto &Inst : *BB)
BC.MIB->removeAnnotation(Inst, "Offset");
@ -2655,6 +2646,10 @@ bool BinaryFunction::finalizeCFIState() {
return true;
}
bool BinaryFunction::requiresAddressTranslation() const {
return opts::EnableBAT || hasSDTMarker();
}
uint64_t BinaryFunction::getInstructionCount() const {
uint64_t Count = 0;
for (auto &Block : BasicBlocksLayout) {
@ -2673,7 +2668,7 @@ uint64_t BinaryFunction::getEditDistance() const {
}
void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
bool EmitCodeOnly, bool LabelsForOffsets) {
bool EmitCodeOnly) {
if (!EmitCodeOnly && EmitColdPart && hasConstantIsland())
duplicateConstantIslands();
@ -2741,7 +2736,7 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
// Prepare to tag this location with a label if we need to keep track of
// the location of calls/returns for BOLT address translation maps
if (!EmitCodeOnly && LabelsForOffsets &&
if (!EmitCodeOnly && requiresAddressTranslation() &&
BC.MIB->hasAnnotation(Instr, "Offset")) {
const auto Offset = BC.MIB->getAnnotationAs<uint32_t>(Instr, "Offset");
MCSymbol *LocSym = BC.Ctx->createTempSymbol(/*CanBeUnnamed=*/true);
@ -2749,17 +2744,6 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
BB->getLocSyms().emplace_back(std::make_pair(Offset, LocSym));
}
// Emit SDT labels
if (!EmitCodeOnly && BC.MIB->hasAnnotation(Instr, "SDTMarker")) {
auto OriginalAddress =
BC.MIB->tryGetAnnotationAs<uint64_t>(Instr, "SDTMarker").get();
auto *SDTLabel = BC.SDTMarkers[OriginalAddress].Label;
// A given symbol should only be emitted as a label once
if (SDTLabel->isUndefined())
Streamer.EmitLabel(SDTLabel);
}
Streamer.EmitInstruction(Instr, *BC.STI);
LastIsPrefix = BC.MIB->isPrefix(Instr);
}
@ -4058,6 +4042,98 @@ void BinaryFunction::calculateLoopInfo() {
}
}
void BinaryFunction::updateOutputValues(const MCAsmLayout &Layout) {
if (!isEmitted()) {
assert(!isInjected() && "injected function should be emitted");
setOutputAddress(getAddress());
setOutputSize(getSize());
return;
}
const auto BaseAddress = getCodeSection()->getOutputAddress();
auto ColdSection = getColdCodeSection();
const auto ColdBaseAddress =
isSplit() ? ColdSection->getOutputAddress() : 0;
if (BC.HasRelocations || isInjected()) {
const auto StartOffset = Layout.getSymbolOffset(*getSymbol());
const auto EndOffset = Layout.getSymbolOffset(*getFunctionEndLabel());
setOutputAddress(BaseAddress + StartOffset);
setOutputSize(EndOffset - StartOffset);
if (hasConstantIsland()) {
const auto DataOffset =
Layout.getSymbolOffset(*getFunctionConstantIslandLabel());
setOutputDataAddress(BaseAddress + DataOffset);
}
if (isSplit()) {
const auto *ColdStartSymbol = getColdSymbol();
assert(ColdStartSymbol && ColdStartSymbol->isDefined() &&
"split function should have defined cold symbol");
const auto *ColdEndSymbol = getFunctionColdEndLabel();
assert(ColdEndSymbol && ColdEndSymbol->isDefined() &&
"split function should have defined cold end symbol");
const auto ColdStartOffset = Layout.getSymbolOffset(*ColdStartSymbol);
const auto ColdEndOffset = Layout.getSymbolOffset(*ColdEndSymbol);
cold().setAddress(ColdBaseAddress + ColdStartOffset);
cold().setImageSize(ColdEndOffset - ColdStartOffset);
if (hasConstantIsland()) {
const auto DataOffset = Layout.getSymbolOffset(
*getFunctionColdConstantIslandLabel());
setOutputColdDataAddress(ColdBaseAddress + DataOffset);
}
}
} else {
setOutputAddress(getAddress());
setOutputSize(
Layout.getSymbolOffset(*getFunctionEndLabel()));
}
// Update basic block output ranges for the debug info, if we have
// secondary entry points in the symbol table to update or if writing BAT.
if (!opts::UpdateDebugSections && !isMultiEntry() &&
!requiresAddressTranslation())
return;
// Output ranges should match the input if the body hasn't changed.
if (!isSimple() && !BC.HasRelocations)
return;
// AArch64 may have functions that only contains a constant island (no code).
if (layout_begin() == layout_end())
return;
BinaryBasicBlock *PrevBB = nullptr;
for (auto BBI = layout_begin(), BBE = layout_end(); BBI != BBE; ++BBI) {
auto *BB = *BBI;
assert(BB->getLabel()->isDefined() && "symbol should be defined");
const auto BBBaseAddress = BB->isCold() ? ColdBaseAddress : BaseAddress;
if (!BC.HasRelocations) {
if (BB->isCold()) {
assert(BBBaseAddress == cold().getAddress());
} else {
assert(BBBaseAddress == getOutputAddress());
}
}
const auto BBOffset = Layout.getSymbolOffset(*BB->getLabel());
const auto BBAddress = BBBaseAddress + BBOffset;
BB->setOutputStartAddress(BBAddress);
if (PrevBB) {
auto PrevBBEndAddress = BBAddress;
if (BB->isCold() != PrevBB->isCold()) {
PrevBBEndAddress =
getOutputAddress() + getOutputSize();
}
PrevBB->setOutputEndAddress(PrevBBEndAddress);
}
PrevBB = BB;
BB->updateOutputValues(Layout);
}
PrevBB->setOutputEndAddress(PrevBB->isCold() ?
cold().getAddress() + cold().getImageSize() :
getOutputAddress() + getOutputSize());
}
DebugAddressRangesVector BinaryFunction::getOutputAddressRanges() const {
DebugAddressRangesVector OutputRanges;
@ -4093,6 +4169,13 @@ uint64_t BinaryFunction::translateInputToOutputAddress(uint64_t Address) const {
if (Address < getAddress())
return 0;
// Check if the address is associated with an instruction that is tracked
// by address translation.
auto KV = InputOffsetToAddressMap.find(Address - getAddress());
if (KV != InputOffsetToAddressMap.end()) {
return KV->second;
}
// FIXME: #18950828 - we rely on relative offsets inside basic blocks to stay
// intact. Instead we can use pseudo instructions and/or annotations.
const auto Offset = Address - getAddress();

View File

@ -249,6 +249,9 @@ private:
/// the control to any basic block of its parent or its sibling.
bool IsFragment{false};
/// Indicate that the function body has SDT marker
bool HasSDTMarker{false};
/// The address for the code for this function in codegen memory.
uint64_t ImageAddress{0};
@ -314,9 +317,6 @@ private:
/// Function order for streaming into the destination binary.
uint32_t Index{-1U};
/// Indicate that the function body has SDT marker
bool HasSDTMarker{false};
/// Get basic block index assuming it belongs to this function.
unsigned getIndex(const BinaryBasicBlock *BB) const {
assert(BB->getIndex() < BasicBlocks.size());
@ -542,6 +542,11 @@ private:
/// Count the number of functions created.
static uint64_t Count;
/// Map offsets of special instructions to addresses in the output.
using InputOffsetToAddressMapTy = std::unordered_map<uint64_t, uint64_t>;
InputOffsetToAddressMapTy InputOffsetToAddressMap;
private:
/// Register alternative function name.
void addAlternativeName(std::string NewName) {
Names.emplace_back(NewName);
@ -1117,6 +1122,16 @@ public:
PLTSymbol = Symbol;
}
/// Update output values of the function based on the final \p Layout.
void updateOutputValues(const MCAsmLayout &Layout);
/// Return mapping of input to output addresses. Most users should call
/// translateInputToOutputAddress() for address translation.
InputOffsetToAddressMapTy &getInputOffsetToAddressMap() {
assert(isEmitted() && "cannot use address mapping before code emission");
return InputOffsetToAddressMap;
}
/// Register relocation type \p RelType at a given \p Address in the function
/// against \p Symbol.
/// Assert if the \p Address is not inside this function.
@ -2083,6 +2098,10 @@ public:
/// is corrupted. If it is unable to fix it, it returns false.
bool finalizeCFIState();
/// Return true if this function needs an address-transaltion table after
/// its code emission.
bool requiresAddressTranslation() const;
/// Adjust branch instructions to match the CFG.
///
/// As it comes to internal branches, the CFG represents "the ultimate source
@ -2124,7 +2143,7 @@ public:
/// Emit function code. The caller is responsible for emitting function
/// symbol(s) and setting the section to emit the code to.
void emitBody(MCStreamer &Streamer, bool EmitColdPart,
bool EmitCodeOnly = false, bool LabelsForOffsets = false);
bool EmitCodeOnly = false);
/// Emit function as a blob with relocations and labels for relocations.
void emitBodyRaw(MCStreamer *Streamer);

View File

@ -461,9 +461,6 @@ struct SDTMarkerInfo {
/// The offset of PC within the note section
unsigned PCOffset;
/// A label that marks the location of the SDT nop instruction
MCSymbol *Label;
};
} // namespace bolt

View File

@ -43,8 +43,8 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map,
Map[BBOutputOffset] = BBInputOffset;
for (const auto &IOPair : BB.getOffsetTranslationTable()) {
const auto InputOffset = IOPair.first + BBInputOffset;
const auto OutputOffset = IOPair.second + BBOutputOffset;
const auto OutputOffset = IOPair.first + BBOutputOffset;
const auto InputOffset = IOPair.second;
// Is this the first instruction in the BB? No need to duplicate the entry.
if (OutputOffset == BBOutputOffset)

View File

@ -495,7 +495,6 @@ bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const {
}
void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
std::vector<std::pair<MCInst *, uint64_t>> PreservedSDTAnnotations;
std::vector<std::pair<MCInst *, uint32_t>> PreservedOffsetAnnotations;
for (auto &It : BC.getBinaryFunctions()) {
@ -528,18 +527,13 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
}
}
// Now record preserved annotations separately and then strip annotations
// Now record preserved annotations separately and then strip annotations.
for (auto II = BB->begin(); II != BB->end(); ++II) {
if (BC.MIB->hasAnnotation(*II, "SDTMarker")) {
PreservedSDTAnnotations.push_back(std::make_pair(
&(*II), BC.MIB->getAnnotationAs<uint64_t>(*II, "SDTMarker")));
}
if (opts::EnableBAT && BC.MIB->hasAnnotation(*II, "Offset")) {
if (BF.requiresAddressTranslation() &&
BC.MIB->hasAnnotation(*II, "Offset")) {
PreservedOffsetAnnotations.push_back(std::make_pair(
&(*II), BC.MIB->getAnnotationAs<uint32_t>(*II, "Offset")));
}
BC.MIB->stripAnnotations(*II);
}
}
@ -549,8 +543,6 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
BC.MIB->freeAnnotations();
// Reinsert preserved annotations we need during code emission.
for (const auto &Item : PreservedSDTAnnotations)
BC.MIB->addAnnotation<uint64_t>(*Item.first, "SDTMarker", Item.second);
for (const auto &Item : PreservedOffsetAnnotations)
BC.MIB->addAnnotation<uint32_t>(*Item.first, "Offset", Item.second);
}

View File

@ -1074,7 +1074,7 @@ void RewriteInstance::run() {
emitAndLink();
updateDebugInfo();
updateMetadata();
if (opts::WriteBoltInfoSection)
addBoltInfoSection();
@ -2756,7 +2756,6 @@ void RewriteInstance::disassembleFunctions() {
// Create annotation indices to allow lock-free execution
BC->MIB->getOrCreateAnnotationIndex("Offset");
BC->MIB->getOrCreateAnnotationIndex("JTIndexReg");
BC->MIB->getOrCreateAnnotationIndex("SDTMarker");
ParallelUtilities::WorkFuncWithAllocTy WorkFun =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {
@ -2903,8 +2902,7 @@ void RewriteInstance::emitFunction(MCStreamer &Streamer,
}
// Emit code.
Function.emitBody(Streamer, EmitColdPart, false,
/*LabelsForOffsets=*/opts::EnableBAT);
Function.emitBody(Streamer, EmitColdPart, /*EmitCodeOnly=*/false);
// Emit padding if requested.
if (auto Padding = opts::padFunction(Function)) {
@ -3168,7 +3166,9 @@ void RewriteInstance::linkRuntime() {
<< Twine::utohexstr(InstrumentationRuntimeStartAddress) << "\n";
}
void RewriteInstance::updateDebugInfo() {
void RewriteInstance::updateMetadata() {
updateSDTMarkers();
if (!opts::UpdateDebugSections)
return;
@ -3177,6 +3177,24 @@ void RewriteInstance::updateDebugInfo() {
DebugInfoRewriter->updateDebugInfo();
}
void RewriteInstance::updateSDTMarkers() {
NamedRegionTimer T("updateSDTMarkers", "update SDT markers", TimerGroupName,
TimerGroupDesc, opts::TimeRewrite);
SectionPatchers[".note.stapsdt"] = llvm::make_unique<SimpleBinaryPatcher>();
auto *SDTNotePatcher = static_cast<SimpleBinaryPatcher *>(
SectionPatchers[".note.stapsdt"].get());
for (auto &SDTInfoKV : BC->SDTMarkers) {
const auto OriginalAddress = SDTInfoKV.first;
auto &SDTInfo = SDTInfoKV.second;
const auto *F = BC->getBinaryFunctionContainingAddress(OriginalAddress);
if (!F)
continue;
const auto NewAddress = F->translateInputToOutputAddress(OriginalAddress);
SDTNotePatcher->addLE64Patch(SDTInfo.PCOffset, NewAddress);
}
}
void RewriteInstance::emitFunctions(MCStreamer *Streamer) {
auto emit = [&](const std::vector<BinaryFunction *> &Functions) {
for (auto *Function : Functions) {
@ -3530,145 +3548,13 @@ void RewriteInstance::mapExtraSections(orc::VModuleKey Key) {
}
void RewriteInstance::updateOutputValues(const MCAsmLayout &Layout) {
SectionPatchers[".note.stapsdt"] = llvm::make_unique<SimpleBinaryPatcher>();
auto *SDTNotePatcher = static_cast<SimpleBinaryPatcher *>(
SectionPatchers[".note.stapsdt"].get());
auto updateOutputValue = [&](BinaryFunction &Function) {
if (!Function.isEmitted()) {
assert(!Function.isInjected() && "injected function should be emitted");
Function.setOutputAddress(Function.getAddress());
Function.setOutputSize(Function.getSize());
return;
}
const auto BaseAddress = Function.getCodeSection()->getOutputAddress();
auto ColdSection = Function.getColdCodeSection();
const auto ColdBaseAddress =
Function.isSplit() ? ColdSection->getOutputAddress() : 0;
if (BC->HasRelocations || Function.isInjected()) {
const auto StartOffset = Layout.getSymbolOffset(*Function.getSymbol());
const auto EndOffset =
Layout.getSymbolOffset(*Function.getFunctionEndLabel());
Function.setOutputAddress(BaseAddress + StartOffset);
Function.setOutputSize(EndOffset - StartOffset);
if (Function.hasConstantIsland()) {
const auto DataOffset =
Layout.getSymbolOffset(*Function.getFunctionConstantIslandLabel());
Function.setOutputDataAddress(BaseAddress + DataOffset);
}
if (Function.isSplit()) {
const auto *ColdStartSymbol = Function.getColdSymbol();
assert(ColdStartSymbol && ColdStartSymbol->isDefined() &&
"split function should have defined cold symbol");
const auto *ColdEndSymbol = Function.getFunctionColdEndLabel();
assert(ColdEndSymbol && ColdEndSymbol->isDefined() &&
"split function should have defined cold end symbol");
const auto ColdStartOffset = Layout.getSymbolOffset(*ColdStartSymbol);
const auto ColdEndOffset = Layout.getSymbolOffset(*ColdEndSymbol);
Function.cold().setAddress(ColdBaseAddress + ColdStartOffset);
Function.cold().setImageSize(ColdEndOffset - ColdStartOffset);
if (Function.hasConstantIsland()) {
const auto DataOffset = Layout.getSymbolOffset(
*Function.getFunctionColdConstantIslandLabel());
Function.setOutputColdDataAddress(ColdBaseAddress + DataOffset);
}
}
} else {
Function.setOutputAddress(Function.getAddress());
Function.setOutputSize(
Layout.getSymbolOffset(*Function.getFunctionEndLabel()));
}
// Create patches that update .note.stapsdt section to reflect the new
// locations of the SDT markers
if (Function.hasSDTMarker()) {
for (auto BBI = Function.layout_begin(), BBE = Function.layout_end();
BBI != BBE; ++BBI) {
auto *BB = *BBI;
const auto BBBaseAddress = BB->isCold() ? ColdBaseAddress : BaseAddress;
for (auto &Instr : *BB) {
if (BC->MIB->hasAnnotation(Instr, "SDTMarker")) {
const auto OriginalSDTAddress =
BC->MIB->getAnnotationAs<uint64_t>(Instr, "SDTMarker");
const auto NewSDTAddress =
Layout.getSymbolOffset(
*BC->SDTMarkers[OriginalSDTAddress].Label) +
BBBaseAddress;
DEBUG(dbgs() << "SDTMarker at :" << utohexstr(OriginalSDTAddress)
<< "moved to :" << utohexstr(NewSDTAddress) << "\n");
SDTNotePatcher->addLE64Patch(
BC->SDTMarkers[OriginalSDTAddress].PCOffset, NewSDTAddress);
BC->MIB->removeAnnotation(Instr, "SDTMarker");
}
}
}
}
// Update basic block output ranges for the debug info, if we have
// secondary entry points in the symbol table to update or if writing BAT.
if (!opts::UpdateDebugSections && !Function.isMultiEntry() &&
!opts::EnableBAT)
return;
// Output ranges should match the input if the body hasn't changed.
if (!Function.isSimple() && !BC->HasRelocations)
return;
// AArch64 may have functions that only contains a constant island (no code)
if (Function.layout_begin() == Function.layout_end())
return;
BinaryBasicBlock *PrevBB = nullptr;
for (auto BBI = Function.layout_begin(), BBE = Function.layout_end();
BBI != BBE; ++BBI) {
auto *BB = *BBI;
assert(BB->getLabel()->isDefined() && "symbol should be defined");
const auto BBBaseAddress = BB->isCold() ? ColdBaseAddress : BaseAddress;
if (!BC->HasRelocations) {
if (BB->isCold()) {
assert(BBBaseAddress == Function.cold().getAddress());
} else {
assert(BBBaseAddress == Function.getOutputAddress());
}
}
const auto BBOffset = Layout.getSymbolOffset(*BB->getLabel());
const auto BBAddress = BBBaseAddress + BBOffset;
BB->setOutputStartAddress(BBAddress);
if (PrevBB) {
auto PrevBBEndAddress = BBAddress;
if (BB->isCold() != PrevBB->isCold()) {
PrevBBEndAddress =
Function.getOutputAddress() + Function.getOutputSize();
}
PrevBB->setOutputEndAddress(PrevBBEndAddress);
}
PrevBB = BB;
for (const auto &LocSymKV : BB->getLocSyms()) {
const uint16_t InputOffset =
static_cast<uint16_t>(LocSymKV.first - BB->getInputOffset());
const uint16_t OutputOffset = static_cast<uint16_t>(
Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
BB->getOffsetTranslationTable().emplace_back(
std::make_pair(InputOffset, OutputOffset));
}
}
PrevBB->setOutputEndAddress(PrevBB->isCold() ?
Function.cold().getAddress() + Function.cold().getImageSize() :
Function.getOutputAddress() + Function.getOutputSize());
};
for (auto &BFI : BC->getBinaryFunctions()) {
auto &Function = BFI.second;
updateOutputValue(Function);
Function.updateOutputValues(Layout);
}
for (auto *InjectedFunction : BC->getInjectedBinaryFunctions()) {
updateOutputValue(*InjectedFunction);
InjectedFunction->updateOutputValues(Layout);
}
}

View File

@ -126,8 +126,11 @@ public:
/// Emit data sections that have code references in them.
void emitDataSections(MCStreamer *Streamer);
/// Update debug information in the file for re-written code.
void updateDebugInfo();
/// Update debug and other auxiliary information in the file.
void updateMetadata();
/// Update SDTMarkers' locations for the output binary.
void updateSDTMarkers();
/// Return the list of code sections in the output order.
std::vector<BinarySection *> getCodeSections();