2023-10-24 12:22:43 -07:00
|
|
|
//===- bolt/Core/AddressMap.cpp - Input-output Address Map ----------------===//
|
|
|
|
|
//
|
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2023-08-21 10:10:48 +02:00
|
|
|
#include "bolt/Core/AddressMap.h"
|
|
|
|
|
#include "bolt/Core/BinaryContext.h"
|
|
|
|
|
#include "bolt/Core/BinaryFunction.h"
|
2023-10-24 12:22:43 -07:00
|
|
|
#include "bolt/Core/BinarySection.h"
|
2023-08-21 10:10:48 +02:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
|
#include "llvm/Support/DataExtractor.h"
|
|
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
namespace bolt {
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
const char *const AddressMap::AddressSectionName = ".bolt.addr2addr_map";
|
|
|
|
|
const char *const AddressMap::LabelSectionName = ".bolt.label2addr_map";
|
2023-08-21 10:10:48 +02:00
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
static void emitAddress(MCStreamer &Streamer, uint64_t InputAddress,
|
|
|
|
|
const MCSymbol *OutputLabel) {
|
2023-08-21 10:10:48 +02:00
|
|
|
Streamer.emitIntValue(InputAddress, 8);
|
|
|
|
|
Streamer.emitSymbolValue(OutputLabel, 8);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
static void emitLabel(MCStreamer &Streamer, const MCSymbol *OutputLabel) {
|
|
|
|
|
Streamer.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel), 8);
|
|
|
|
|
Streamer.emitSymbolValue(OutputLabel, 8);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-21 10:10:48 +02:00
|
|
|
void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
|
2023-10-24 12:22:43 -07:00
|
|
|
// Mark map sections as link-only to avoid allocation in the output file.
|
|
|
|
|
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly*/ true,
|
|
|
|
|
/*IsText*/ false,
|
|
|
|
|
/*IsAllocatable*/ true);
|
|
|
|
|
BC.registerOrUpdateSection(AddressSectionName, ELF::SHT_PROGBITS, Flags)
|
|
|
|
|
.setLinkOnly();
|
|
|
|
|
BC.registerOrUpdateSection(LabelSectionName, ELF::SHT_PROGBITS, Flags)
|
|
|
|
|
.setLinkOnly();
|
2023-08-21 10:10:48 +02:00
|
|
|
|
|
|
|
|
for (const auto &[BFAddress, BF] : BC.getBinaryFunctions()) {
|
|
|
|
|
if (!BF.requiresAddressMap())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (const auto &BB : BF) {
|
|
|
|
|
if (!BB.getLabel()->isDefined())
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
Streamer.switchSection(BC.getDataSection(LabelSectionName));
|
|
|
|
|
emitLabel(Streamer, BB.getLabel());
|
2023-08-21 10:10:48 +02:00
|
|
|
|
|
|
|
|
if (!BB.hasLocSyms())
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
Streamer.switchSection(BC.getDataSection(AddressSectionName));
|
2023-08-21 10:10:48 +02:00
|
|
|
for (auto [Offset, Symbol] : BB.getLocSyms())
|
2023-10-24 12:22:43 -07:00
|
|
|
emitAddress(Streamer, BFAddress + Offset, Symbol);
|
2023-08-21 10:10:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {
|
|
|
|
|
auto AddressMapSection = BC.getUniqueSectionByName(AddressSectionName);
|
|
|
|
|
auto LabelMapSection = BC.getUniqueSectionByName(LabelSectionName);
|
2023-08-21 10:10:48 +02:00
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
if (!AddressMapSection && !LabelMapSection)
|
|
|
|
|
return std::nullopt;
|
2023-08-21 10:10:48 +02:00
|
|
|
|
|
|
|
|
AddressMap Parsed;
|
|
|
|
|
|
2023-10-24 12:22:43 -07:00
|
|
|
const size_t EntrySize = 2 * BC.AsmInfo->getCodePointerSize();
|
|
|
|
|
auto parseSection =
|
|
|
|
|
[&](BinarySection &Section,
|
|
|
|
|
function_ref<void(uint64_t, uint64_t)> InsertCallback) {
|
|
|
|
|
StringRef Buffer = Section.getOutputContents();
|
|
|
|
|
assert(Buffer.size() % EntrySize == 0 && "Unexpected address map size");
|
|
|
|
|
|
|
|
|
|
DataExtractor DE(Buffer, BC.AsmInfo->isLittleEndian(),
|
|
|
|
|
BC.AsmInfo->getCodePointerSize());
|
|
|
|
|
DataExtractor::Cursor Cursor(0);
|
|
|
|
|
|
|
|
|
|
while (Cursor && !DE.eof(Cursor)) {
|
|
|
|
|
const uint64_t Input = DE.getAddress(Cursor);
|
|
|
|
|
const uint64_t Output = DE.getAddress(Cursor);
|
|
|
|
|
InsertCallback(Input, Output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(Cursor && "Error reading address map section");
|
|
|
|
|
BC.deregisterSection(Section);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (AddressMapSection) {
|
|
|
|
|
Parsed.Address2AddressMap.reserve(AddressMapSection->getOutputSize() /
|
|
|
|
|
EntrySize);
|
|
|
|
|
parseSection(*AddressMapSection, [&](uint64_t Input, uint64_t Output) {
|
|
|
|
|
if (!Parsed.Address2AddressMap.count(Input))
|
|
|
|
|
Parsed.Address2AddressMap.insert({Input, Output});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LabelMapSection) {
|
|
|
|
|
Parsed.Label2AddrMap.reserve(LabelMapSection->getOutputSize() / EntrySize);
|
|
|
|
|
parseSection(*LabelMapSection, [&](uint64_t Input, uint64_t Output) {
|
|
|
|
|
assert(!Parsed.Label2AddrMap.count(
|
|
|
|
|
reinterpret_cast<const MCSymbol *>(Input)) &&
|
|
|
|
|
"Duplicate label entry detected.");
|
|
|
|
|
Parsed.Label2AddrMap.insert(
|
|
|
|
|
{reinterpret_cast<const MCSymbol *>(Input), Output});
|
|
|
|
|
});
|
2023-08-21 10:10:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Parsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace bolt
|
|
|
|
|
} // namespace llvm
|