}
}
+MarkerSymType BinaryContext::getMarkerType(const SymbolRef &Symbol) const {
+ // For aarch64, the ABI defines mapping symbols so we identify data in the
+ // code section (see IHI0056B). $x identifies a symbol starting code or the
+ // end of a data chunk inside code, $d indentifies start of data.
+ if (!isAArch64() || ELFSymbolRef(Symbol).getSize())
+ return MarkerSymType::NONE;
+
+ Expected<StringRef> NameOrError = Symbol.getName();
+ Expected<object::SymbolRef::Type> TypeOrError = Symbol.getType();
+
+ if (!TypeOrError || !NameOrError)
+ return MarkerSymType::NONE;
+
+ if (*TypeOrError != SymbolRef::ST_Unknown)
+ return MarkerSymType::NONE;
+
+ if (*NameOrError == "$x" || NameOrError->startswith("$x."))
+ return MarkerSymType::CODE;
+
+ if (*NameOrError == "$d" || NameOrError->startswith("$d."))
+ return MarkerSymType::DATA;
+
+ return MarkerSymType::NONE;
+}
+
+bool BinaryContext::isMarker(const SymbolRef &Symbol) const {
+ return getMarkerType(Symbol) != MarkerSymType::NONE;
+}
+
void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
uint64_t Offset,
const BinaryFunction *Function,
}
}
-bool BinaryFunction::isDataMarker(const SymbolRef &Symbol,
- uint64_t SymbolSize) const {
- // For aarch64, the ABI defines mapping symbols so we identify data in the
- // code section (see IHI0056B). $d identifies a symbol starting data contents.
- if (BC.isAArch64() && Symbol.getType() &&
- cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 &&
- Symbol.getName() &&
- (cantFail(Symbol.getName()) == "$d" ||
- cantFail(Symbol.getName()).startswith("$d.")))
- return true;
- return false;
-}
-
-bool BinaryFunction::isCodeMarker(const SymbolRef &Symbol,
- uint64_t SymbolSize) const {
- // For aarch64, the ABI defines mapping symbols so we identify data in the
- // code section (see IHI0056B). $x identifies a symbol starting code or the
- // end of a data chunk inside code.
- if (BC.isAArch64() && Symbol.getType() &&
- cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 &&
- Symbol.getName() &&
- (cantFail(Symbol.getName()) == "$x" ||
- cantFail(Symbol.getName()).startswith("$x.")))
- return true;
- return false;
-}
-
bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol,
uint64_t SymbolSize) const {
// If this symbol is in a different section from the one where the
// Some symbols are tolerated inside function bodies, others are not.
// The real function boundaries may not be known at this point.
- if (isDataMarker(Symbol, SymbolSize) || isCodeMarker(Symbol, SymbolSize))
+ if (BC.isMarker(Symbol))
return true;
// It's okay to have a zero-sized symbol in the middle of non-zero-sized
std::vector<SymbolRef> SortedFileSymbols;
std::copy_if(InputFile->symbol_begin(), InputFile->symbol_end(),
std::back_inserter(SortedFileSymbols), isSymbolInMemory);
+ auto CompareSymbols = [this](const SymbolRef &A, const SymbolRef &B) {
+ // Marker symbols have the highest precedence, while
+ // SECTIONs have the lowest.
+ auto AddressA = cantFail(A.getAddress());
+ auto AddressB = cantFail(B.getAddress());
+ if (AddressA != AddressB)
+ return AddressA < AddressB;
+
+ bool AMarker = BC->isMarker(A);
+ bool BMarker = BC->isMarker(B);
+ if (AMarker || BMarker) {
+ return AMarker && !BMarker;
+ }
- std::stable_sort(
- SortedFileSymbols.begin(), SortedFileSymbols.end(),
- [](const SymbolRef &A, const SymbolRef &B) {
- // FUNC symbols have the highest precedence, while SECTIONs
- // have the lowest.
- uint64_t AddressA = cantFail(A.getAddress());
- uint64_t AddressB = cantFail(B.getAddress());
- if (AddressA != AddressB)
- return AddressA < AddressB;
-
- SymbolRef::Type AType = cantFail(A.getType());
- SymbolRef::Type BType = cantFail(B.getType());
- if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function)
- return true;
- if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug)
- return true;
+ auto AType = cantFail(A.getType());
+ auto BType = cantFail(B.getType());
+ if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function)
+ return true;
+ if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug)
+ return true;
- return false;
- });
+ return false;
+ };
+
+ std::stable_sort(SortedFileSymbols.begin(), SortedFileSymbols.end(),
+ CompareSymbols);
+
+ auto LastSymbol = SortedFileSymbols.end() - 1;
// For aarch64, the ABI defines mapping symbols so we identify data in the
// code section (see IHI0056B). $d identifies data contents.
- auto LastSymbol = SortedFileSymbols.end() - 1;
+ // Compilers usually merge multiple data objects in a single $d-$x interval,
+ // but we need every data object to be marked with $d. Because of that we
+ // create a vector of MarkerSyms with all locations of data objects.
+
+ struct MarkerSym {
+ uint64_t Address;
+ MarkerSymType Type;
+ };
+
+ std::vector<MarkerSym> SortedMarkerSymbols;
+ auto addExtraDataMarkerPerSymbol =
+ [this](const std::vector<SymbolRef> &SortedFileSymbols,
+ std::vector<MarkerSym> &SortedMarkerSymbols) {
+ bool IsData = false;
+ uint64_t LastAddr = 0;
+ for (auto Sym = SortedFileSymbols.begin();
+ Sym < SortedFileSymbols.end(); ++Sym) {
+ uint64_t Address = cantFail(Sym->getAddress());
+ if (LastAddr == Address) // don't repeat markers
+ continue;
+
+ MarkerSymType MarkerType = BC->getMarkerType(*Sym);
+ if (MarkerType != MarkerSymType::NONE) {
+ SortedMarkerSymbols.push_back(MarkerSym{Address, MarkerType});
+ LastAddr = Address;
+ IsData = MarkerType == MarkerSymType::DATA;
+ continue;
+ }
+
+ if (IsData) {
+ SortedMarkerSymbols.push_back(
+ MarkerSym{cantFail(Sym->getAddress()), MarkerSymType::DATA});
+ LastAddr = Address;
+ }
+ }
+ };
+
if (BC->isAArch64()) {
+ addExtraDataMarkerPerSymbol(SortedFileSymbols, SortedMarkerSymbols);
LastSymbol = std::stable_partition(
SortedFileSymbols.begin(), SortedFileSymbols.end(),
- [](const SymbolRef &Symbol) {
- StringRef Name = cantFail(Symbol.getName());
- return !(cantFail(Symbol.getType()) == SymbolRef::ST_Unknown &&
- (Name == "$d" || Name.startswith("$d.") || Name == "$x" ||
- Name.startswith("$x.")));
- });
+ [this](const SymbolRef &Symbol) { return !BC->isMarker(Symbol); });
--LastSymbol;
}
BinaryFunction *PreviousFunction = nullptr;
unsigned AnonymousId = 0;
- const auto MarkersBegin = std::next(LastSymbol);
- for (auto ISym = SortedFileSymbols.begin(); ISym != MarkersBegin; ++ISym) {
+ const auto SortedSymbolsEnd = std::next(LastSymbol);
+ for (auto ISym = SortedFileSymbols.begin(); ISym != SortedSymbolsEnd;
+ ++ISym) {
const SymbolRef &Symbol = *ISym;
// Keep undefined symbols for pretty printing?
if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined)
adjustFunctionBoundaries();
// Annotate functions with code/data markers in AArch64
- for (auto ISym = MarkersBegin; ISym != SortedFileSymbols.end(); ++ISym) {
- const SymbolRef &Symbol = *ISym;
- uint64_t Address =
- cantFail(Symbol.getAddress(), "cannot get symbol address");
- uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
- BinaryFunction *BF =
- BC->getBinaryFunctionContainingAddress(Address, true, true);
+ for (auto ISym = SortedMarkerSymbols.begin();
+ ISym != SortedMarkerSymbols.end(); ++ISym) {
+
+ auto *BF =
+ BC->getBinaryFunctionContainingAddress(ISym->Address, true, true);
+
if (!BF) {
// Stray marker
continue;
}
- const uint64_t EntryOffset = Address - BF->getAddress();
- if (BF->isCodeMarker(Symbol, SymbolSize)) {
+ const auto EntryOffset = ISym->Address - BF->getAddress();
+ if (ISym->Type == MarkerSymType::CODE) {
BF->markCodeAtOffset(EntryOffset);
continue;
}
- if (BF->isDataMarker(Symbol, SymbolSize)) {
+ if (ISym->Type == MarkerSymType::DATA) {
BF->markDataAtOffset(EntryOffset);
- BC->AddressToConstantIslandMap[Address] = BF;
+ BC->AddressToConstantIslandMap[ISym->Address] = BF;
continue;
}
llvm_unreachable("Unknown marker");