[JITLink][MachO] Fix "find-symbol-by-address" logic.

Only search within the requested section, and allow one-past-then-end addresses.

This is needed to support section-end-address references to sections with no
symbols in them.
This commit is contained in:
Lang Hames 2021-11-12 20:37:07 -08:00
parent efa896e5f7
commit 2272ec1c63
5 changed files with 99 additions and 48 deletions

View File

@ -318,16 +318,19 @@ Error MachOLinkGraphBuilder::createNormalizedSymbols() {
}
void MachOLinkGraphBuilder::addSectionStartSymAndBlock(
Section &GraphSec, uint64_t Address, const char *Data, uint64_t Size,
uint32_t Alignment, bool IsLive) {
unsigned SecIndex, Section &GraphSec, uint64_t Address, const char *Data,
uint64_t Size, uint32_t Alignment, bool IsLive) {
Block &B =
Data ? G->createContentBlock(GraphSec, ArrayRef<char>(Data, Size),
Address, Alignment, 0)
: G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0);
auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive);
assert(!AddrToCanonicalSymbol.count(Sym.getAddress()) &&
auto SecI = IndexToSection.find(SecIndex);
assert(SecI != IndexToSection.end() && "SecIndex invalid");
auto &NSec = SecI->second;
assert(!NSec.CanonicalSymbols.count(Sym.getAddress()) &&
"Anonymous block start symbol clashes with existing symbol address");
AddrToCanonicalSymbol[Sym.getAddress()] = &Sym;
NSec.CanonicalSymbols[Sym.getAddress()] = &Sym;
}
Error MachOLinkGraphBuilder::graphifyRegularSymbols() {
@ -441,8 +444,8 @@ Error MachOLinkGraphBuilder::graphifyRegularSymbols() {
<< formatv("{0:x16}", NSec.Address) << " -- "
<< formatv("{0:x16}", NSec.Address + NSec.Size) << "\n";
});
addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
NSec.Size, NSec.Alignment,
addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,
NSec.Data, NSec.Size, NSec.Alignment,
SectionIsNoDeadStrip);
} else
LLVM_DEBUG({
@ -480,8 +483,8 @@ Error MachOLinkGraphBuilder::graphifyRegularSymbols() {
<< formatv("{0:x16}", NSec.Address) << " -- "
<< formatv("{0:x16}", NSec.Address + AnonBlockSize) << " ]\n";
});
addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
AnonBlockSize, NSec.Alignment,
addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,
NSec.Data, AnonBlockSize, NSec.Alignment,
SectionIsNoDeadStrip);
}
@ -580,7 +583,7 @@ Symbol &MachOLinkGraphBuilder::createStandardGraphSymbol(NormalizedSymbol &NSym,
NSym.GraphSymbol = &Sym;
if (IsCanonical)
setCanonicalSymbol(Sym);
setCanonicalSymbol(getSectionByIndex(NSym.Sect - 1), Sym);
return Sym;
}
@ -607,7 +610,6 @@ Error MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() {
Error MachOLinkGraphBuilder::graphifyCStringSection(
NormalizedSection &NSec, std::vector<NormalizedSymbol *> NSyms) {
assert(NSec.GraphSection && "C string literal section missing graph section");
assert(NSec.Data && "C string literal section has no data");
@ -661,7 +663,7 @@ Error MachOLinkGraphBuilder::graphifyCStringSection(
// If there's no symbol at the start of this block then create one.
if (NSyms.empty() || NSyms.back()->Value != B.getAddress()) {
auto &S = G->addAnonymousSymbol(B, 0, BlockSize, false, false);
setCanonicalSymbol(S);
setCanonicalSymbol(NSec, S);
LLVM_DEBUG({
dbgs() << " Adding anonymous symbol for c-string block "
<< formatv("{0:x16} -- {1:x16}", S.getAddress(),

View File

@ -77,6 +77,7 @@ protected:
uint32_t Flags = 0;
const char *Data = nullptr;
Section *GraphSection = nullptr;
std::map<JITTargetAddress, Symbol *> CanonicalSymbols;
};
using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
@ -135,19 +136,21 @@ protected:
/// Returns the symbol with the highest address not greater than the search
/// address, or null if no such symbol exists.
Symbol *getSymbolByAddress(JITTargetAddress Address) {
auto I = AddrToCanonicalSymbol.upper_bound(Address);
if (I == AddrToCanonicalSymbol.begin())
Symbol *getSymbolByAddress(NormalizedSection &NSec,
JITTargetAddress Address) {
auto I = NSec.CanonicalSymbols.upper_bound(Address);
if (I == NSec.CanonicalSymbols.begin())
return nullptr;
return std::prev(I)->second;
}
/// Returns the symbol with the highest address not greater than the search
/// address, or an error if no such symbol exists.
Expected<Symbol &> findSymbolByAddress(JITTargetAddress Address) {
auto *Sym = getSymbolByAddress(Address);
Expected<Symbol &> findSymbolByAddress(NormalizedSection &NSec,
JITTargetAddress Address) {
auto *Sym = getSymbolByAddress(NSec, Address);
if (Sym)
if (Address < Sym->getAddress() + Sym->getSize())
if (Address <= Sym->getAddress() + Sym->getSize())
return *Sym;
return make_error<JITLinkError>("No symbol covering address " +
formatv("{0:x16}", Address));
@ -178,8 +181,8 @@ private:
static unsigned getPointerSize(const object::MachOObjectFile &Obj);
static support::endianness getEndianness(const object::MachOObjectFile &Obj);
void setCanonicalSymbol(Symbol &Sym) {
auto *&CanonicalSymEntry = AddrToCanonicalSymbol[Sym.getAddress()];
void setCanonicalSymbol(NormalizedSection &NSec, Symbol &Sym) {
auto *&CanonicalSymEntry = NSec.CanonicalSymbols[Sym.getAddress()];
// There should be no symbol at this address, or, if there is,
// it should be a zero-sized symbol from an empty section (which
// we can safely override).
@ -189,9 +192,10 @@ private:
}
Section &getCommonSection();
void addSectionStartSymAndBlock(Section &GraphSec, uint64_t Address,
const char *Data, uint64_t Size,
uint32_t Alignment, bool IsLive);
void addSectionStartSymAndBlock(unsigned SecIndex, Section &GraphSec,
uint64_t Address, const char *Data,
uint64_t Size, uint32_t Alignment,
bool IsLive);
Error createNormalizedSections();
Error createNormalizedSymbols();
@ -226,7 +230,6 @@ private:
Section *CommonSection = nullptr;
DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol;
std::map<JITTargetAddress, Symbol *> AddrToCanonicalSymbol;
StringMap<SectionParserFunction> CustomSectionParserFunctions;
};

View File

@ -160,7 +160,7 @@ private:
auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
if (!ToSymbolSec)
return ToSymbolSec.takeError();
ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);
assert(ToSymbol && "No symbol for section");
FixupValue -= ToSymbol->getAddress();
}
@ -205,14 +205,18 @@ private:
continue;
}
// Skip relocations for debug symbols.
auto NSec =
findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec)
return NSec.takeError();
// Skip relocations for MachO sections without corresponding graph
// sections.
{
auto &NSec =
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec.GraphSection) {
if (!NSec->GraphSection) {
LLVM_DEBUG({
dbgs() << " Skipping relocations for MachO section "
<< NSec.SegName << "/" << NSec.SectName
<< NSec->SegName << "/" << NSec->SectName
<< " which has no associated graph section\n";
});
continue;
@ -231,18 +235,15 @@ private:
// Find the address of the value to fix up.
JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
LLVM_DEBUG({
auto &NSec =
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
dbgs() << " " << NSec.SectName << " + "
dbgs() << " " << NSec->SectName << " + "
<< formatv("{0:x8}", RI.r_address) << ":\n";
});
// Find the block that the fixup points to.
Block *BlockToFix = nullptr;
{
auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);
if (!SymbolToFixOrErr)
return SymbolToFixOrErr.takeError();
BlockToFix = &SymbolToFixOrErr->getBlock();
@ -324,7 +325,11 @@ private:
break;
case Pointer64Anon: {
JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
if (!TargetNSec)
return TargetNSec.takeError();
if (auto TargetSymbolOrErr =
findSymbolByAddress(*TargetNSec, TargetAddress))
TargetSymbol = &*TargetSymbolOrErr;
else
return TargetSymbolOrErr.takeError();

View File

@ -170,7 +170,7 @@ private:
auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
if (!ToSymbolSec)
return ToSymbolSec.takeError();
ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);
assert(ToSymbol && "No symbol for section");
FixupValue -= ToSymbol->getAddress();
}
@ -216,14 +216,18 @@ private:
continue;
}
// Skip relocations for debug symbols.
auto NSec =
findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec)
return NSec.takeError();
// Skip relocations for MachO sections without corresponding graph
// sections.
{
auto &NSec =
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec.GraphSection) {
if (!NSec->GraphSection) {
LLVM_DEBUG({
dbgs() << " Skipping relocations for MachO section "
<< NSec.SegName << "/" << NSec.SectName
<< NSec->SegName << "/" << NSec->SectName
<< " which has no associated graph section\n";
});
continue;
@ -240,16 +244,14 @@ private:
JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
LLVM_DEBUG({
auto &NSec =
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
dbgs() << " " << NSec.SectName << " + "
dbgs() << " " << NSec->SectName << " + "
<< formatv("{0:x8}", RI.r_address) << ":\n";
});
// Find the block that the fixup points to.
Block *BlockToFix = nullptr;
{
auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);
if (!SymbolToFixOrErr)
return SymbolToFixOrErr.takeError();
BlockToFix = &SymbolToFixOrErr->getBlock();
@ -342,7 +344,11 @@ private:
break;
case MachOPointer64Anon: {
JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
if (!TargetNSec)
return TargetNSec.takeError();
if (auto TargetSymbolOrErr =
findSymbolByAddress(*TargetNSec, TargetAddress))
TargetSymbol = &*TargetSymbolOrErr;
else
return TargetSymbolOrErr.takeError();
@ -363,7 +369,11 @@ private:
case MachOPCRel32Anon: {
JITTargetAddress TargetAddress =
FixupAddress + 4 + *(const little32_t *)FixupContent;
if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
if (!TargetNSec)
return TargetNSec.takeError();
if (auto TargetSymbolOrErr =
findSymbolByAddress(*TargetNSec, TargetAddress))
TargetSymbol = &*TargetSymbolOrErr;
else
return TargetSymbolOrErr.takeError();
@ -379,7 +389,11 @@ private:
1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
JITTargetAddress TargetAddress =
FixupAddress + Delta + *(const little32_t *)FixupContent;
if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
if (!TargetNSec)
return TargetNSec.takeError();
if (auto TargetSymbolOrErr =
findSymbolByAddress(*TargetNSec, TargetAddress))
TargetSymbol = &*TargetSymbolOrErr;
else
return TargetSymbolOrErr.takeError();

View File

@ -0,0 +1,27 @@
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t %s
# RUN: llvm-jitlink -noexec %t
#
# Check that JITLink handles anonymous relocations to the end of MachO sections.
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 11, 0 sdk_version 11, 1
.globl _main
.p2align 4, 0x90
_main:
movq _R(%rip), %rax
retq
.section __TEXT,__anon,regular
L__anon_start:
.byte 7
L__anon_end:
.private_extern _R
.section __DATA,__data
.globl _R
.p2align 3
_R:
.quad L__anon_end
.subsections_via_symbols