Skip to content

Commit 23085ec

Browse files
committed
[JITLink] Add a test for zero-filled content.
Also updates RuntimeDyldChecker and llvm-rtdyld to support zero-fill tests by returning a content address of zero (but no error) for zero-fill atoms, and treating loads from zero as returning zero. llvm-svn: 360547
1 parent 27415e7 commit 23085ec

File tree

7 files changed

+132
-39
lines changed

7 files changed

+132
-39
lines changed

llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h

+57-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,63 @@ class raw_ostream;
7373
///
7474
class RuntimeDyldChecker {
7575
public:
76-
struct MemoryRegionInfo {
77-
StringRef Content;
78-
JITTargetAddress TargetAddress;
76+
class MemoryRegionInfo {
77+
public:
78+
MemoryRegionInfo() = default;
79+
80+
/// Constructor for symbols/sections with content.
81+
MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress)
82+
: ContentPtr(Content.data()), Size(Content.size()),
83+
TargetAddress(TargetAddress) {}
84+
85+
/// Constructor for zero-fill symbols/sections.
86+
MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
87+
: Size(Size), TargetAddress(TargetAddress) {}
88+
89+
/// Returns true if this is a zero-fill symbol/section.
90+
bool isZeroFill() const {
91+
assert(Size && "setContent/setZeroFill must be called first");
92+
return !ContentPtr;
93+
}
94+
95+
/// Set the content for this memory region.
96+
void setContent(StringRef Content) {
97+
assert(!ContentPtr && !Size && "Content/zero-fill already set");
98+
ContentPtr = Content.data();
99+
Size = Content.size();
100+
}
101+
102+
/// Set a zero-fill length for this memory region.
103+
void setZeroFill(uint64_t Size) {
104+
assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
105+
this->Size = Size;
106+
}
107+
108+
/// Returns the content for this section if there is any.
109+
StringRef getContent() const {
110+
assert(!isZeroFill() && "Can't get content for a zero-fill section");
111+
return StringRef(ContentPtr, static_cast<size_t>(Size));
112+
}
113+
114+
/// Returns the zero-fill length for this section.
115+
uint64_t getZeroFillLength() const {
116+
assert(isZeroFill() && "Can't get zero-fill length for content section");
117+
return Size;
118+
}
119+
120+
/// Set the target address for this region.
121+
void setTargetAddress(JITTargetAddress TargetAddress) {
122+
assert(!this->TargetAddress && "TargetAddress already set");
123+
this->TargetAddress = TargetAddress;
124+
}
125+
126+
/// Return the target address for this region.
127+
JITTargetAddress getTargetAddress() const { return TargetAddress; }
128+
129+
private:
130+
const char *ContentPtr = 0;
131+
uint64_t Size = 0;
132+
JITTargetAddress TargetAddress = 0;
79133
};
80134

81135
using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;

llvm/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class MachOAtomGraphBuilder {
6262
}
6363

6464
MachOSection &setZeroFill(uint64_t Size) {
65-
assert(!ContentPtr && !Size && "Content/zeroFill already set");
65+
assert(!ContentPtr && !this->Size && "Content/zeroFill already set");
6666
this->Size = Size;
6767
return *this;
6868
}

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp

+25-11
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,11 @@ class RuntimeDyldCheckerExprEval {
526526

527527
uint64_t LoadAddr = LoadAddrExprResult.getValue();
528528

529+
// If there is no error but the content pointer is null then this is a
530+
// zero-fill symbol/section.
531+
if (LoadAddr == 0)
532+
return std::make_pair(0, RemainingExpr);
533+
529534
return std::make_pair(
530535
EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
531536
RemainingExpr);
@@ -735,8 +740,12 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
735740
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
736741
return 0;
737742
}
743+
744+
if (SymInfo->isZeroFill())
745+
return 0;
746+
738747
return static_cast<uint64_t>(
739-
reinterpret_cast<uintptr_t>(SymInfo->Content.data()));
748+
reinterpret_cast<uintptr_t>(SymInfo->getContent().data()));
740749
}
741750

742751
uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
@@ -746,7 +755,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
746755
return 0;
747756
}
748757

749-
return SymInfo->TargetAddress;
758+
return SymInfo->getTargetAddress();
750759
}
751760

752761
uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
@@ -774,7 +783,7 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
774783
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
775784
return StringRef();
776785
}
777-
return SymInfo->Content;
786+
return SymInfo->getContent();
778787
}
779788

780789
std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
@@ -796,10 +805,13 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
796805

797806
uint64_t Addr = 0;
798807

799-
if (IsInsideLoad)
800-
Addr = pointerToJITTargetAddress(SecInfo->Content.data());
801-
else
802-
Addr = SecInfo->TargetAddress;
808+
if (IsInsideLoad) {
809+
if (SecInfo->isZeroFill())
810+
Addr = 0;
811+
else
812+
Addr = pointerToJITTargetAddress(SecInfo->getContent().data());
813+
} else
814+
Addr = SecInfo->getTargetAddress();
803815

804816
return std::make_pair(Addr, "");
805817
}
@@ -823,10 +835,12 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
823835

824836
uint64_t Addr = 0;
825837

826-
if (IsInsideLoad)
827-
Addr = pointerToJITTargetAddress(StubInfo->Content.data());
828-
else
829-
Addr = StubInfo->TargetAddress;
838+
if (IsInsideLoad) {
839+
if (StubInfo->isZeroFill())
840+
return std::make_pair((uint64_t)0, "Detected zero-filled stub/GOT entry");
841+
Addr = pointerToJITTargetAddress(StubInfo->getContent().data());
842+
} else
843+
Addr = StubInfo->getTargetAddress();
830844

831845
return std::make_pair(Addr, "");
832846
}

llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s

+5
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,9 @@ subtractor_with_alt_entry_subtrahend_quad_B:
272272
.section __DATA,__nds_test_sect,regular,no_dead_strip
273273
.quad 0
274274

275+
# Check that explicit zero-fill symbols are supported
276+
# jitlink-check: *{8}zero_fill_test = 0
277+
.globl zero_fill_test
278+
.zerofill __DATA,__zero_fill_test,zero_fill_test,8,3
279+
275280
.subsections_via_symbols

llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp

+29-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// .
9+
// MachO parsing support for llvm-jitlink.
1010
//
1111
//===----------------------------------------------------------------------===//
1212

@@ -105,8 +105,6 @@ Error registerMachOStubsAndGOT(Session &S, AtomGraph &G) {
105105
bool isGOTSection = isMachOGOTSection(Sec);
106106
bool isStubsSection = isMachOStubsSection(Sec);
107107

108-
auto &SectionInfo = FileInfo.SectionInfos[Sec.getName()];
109-
110108
auto *FirstAtom = *Sec.atoms().begin();
111109
auto *LastAtom = FirstAtom;
112110
for (auto *DA : Sec.atoms()) {
@@ -115,25 +113,46 @@ Error registerMachOStubsAndGOT(Session &S, AtomGraph &G) {
115113
if (DA->getAddress() > LastAtom->getAddress())
116114
LastAtom = DA;
117115
if (isGOTSection) {
116+
if (Sec.isZeroFill())
117+
return make_error<StringError>("Content atom in zero-fill section",
118+
inconvertibleErrorCode());
119+
118120
if (auto TA = getMachOGOTTarget(G, *DA)) {
119121
FileInfo.GOTEntryInfos[TA->getName()] = {DA->getContent(),
120122
DA->getAddress()};
121123
} else
122124
return TA.takeError();
123125
} else if (isStubsSection) {
126+
if (Sec.isZeroFill())
127+
return make_error<StringError>("Content atom in zero-fill section",
128+
inconvertibleErrorCode());
129+
124130
if (auto TA = getMachOStubTarget(G, *DA))
125131
FileInfo.StubInfos[TA->getName()] = {DA->getContent(),
126132
DA->getAddress()};
127133
else
128134
return TA.takeError();
129-
} else if (DA->hasName() && DA->isGlobal())
130-
S.SymbolInfos[DA->getName()] = {DA->getContent(), DA->getAddress()};
135+
} else if (DA->hasName() && DA->isGlobal()) {
136+
if (DA->isZeroFill())
137+
S.SymbolInfos[DA->getName()] = {DA->getSize(), DA->getAddress()};
138+
else {
139+
if (Sec.isZeroFill())
140+
return make_error<StringError>("Content atom in zero-fill section",
141+
inconvertibleErrorCode());
142+
S.SymbolInfos[DA->getName()] = {DA->getContent(), DA->getAddress()};
143+
}
144+
}
131145
}
132-
const char *StartAddr = FirstAtom->getContent().data();
133-
const char *EndAddr =
134-
LastAtom->getContent().data() + LastAtom->getContent().size();
135-
SectionInfo.TargetAddress = FirstAtom->getAddress();
136-
SectionInfo.Content = StringRef(StartAddr, EndAddr - StartAddr);
146+
147+
JITTargetAddress SecAddr = FirstAtom->getAddress();
148+
uint64_t SecSize = (LastAtom->getAddress() + LastAtom->getSize()) -
149+
FirstAtom->getAddress();
150+
151+
if (Sec.isZeroFill())
152+
FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr};
153+
else
154+
FileInfo.SectionInfos[Sec.getName()] = {
155+
StringRef(FirstAtom->getContent().data(), SecSize), SecAddr};
137156
}
138157

139158
return Error::success();

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,11 @@ namespace llvm {
104104

105105
static raw_ostream &
106106
operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {
107-
return OS << "target addr = " << format("0x%016" PRIx64, MRI.TargetAddress)
108-
<< ", content: " << (const void *)MRI.Content.data() << " -- "
109-
<< (const void *)(MRI.Content.data() + MRI.Content.size()) << " ("
110-
<< MRI.Content.size() << " bytes)";
107+
return OS << "target addr = "
108+
<< format("0x%016" PRIx64, MRI.getTargetAddress())
109+
<< ", content: " << (const void *)MRI.getContent().data() << " -- "
110+
<< (const void *)(MRI.getContent().data() + MRI.getContent().size())
111+
<< " (" << MRI.getContent().size() << " bytes)";
111112
}
112113

113114
static raw_ostream &

llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ static int linkAndVerify() {
774774

775775
// First get the target address.
776776
if (auto InternalSymbol = Dyld.getSymbol(Symbol))
777-
SymInfo.TargetAddress = InternalSymbol.getAddress();
777+
SymInfo.setTargetAddress(InternalSymbol.getAddress());
778778
else {
779779
// Symbol not found in RuntimeDyld. Fall back to external lookup.
780780
#ifdef _MSC_VER
@@ -799,7 +799,7 @@ static int linkAndVerify() {
799799
auto I = Result->find(Symbol);
800800
assert(I != Result->end() &&
801801
"Expected symbol address if no error occurred");
802-
SymInfo.TargetAddress = I->second.getAddress();
802+
SymInfo.setTargetAddress(I->second.getAddress());
803803
}
804804

805805
// Now find the symbol content if possible (otherwise leave content as a
@@ -810,7 +810,7 @@ static int linkAndVerify() {
810810
char *CSymAddr = static_cast<char *>(SymAddr);
811811
StringRef SecContent = Dyld.getSectionContent(SectionID);
812812
uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
813-
SymInfo.Content = StringRef(CSymAddr, SymSize);
813+
SymInfo.setContent(StringRef(CSymAddr, SymSize));
814814
}
815815
}
816816
return SymInfo;
@@ -824,7 +824,7 @@ static int linkAndVerify() {
824824
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
825825
return false;
826826
}
827-
return SymInfo->TargetAddress != 0;
827+
return SymInfo->getTargetAddress() != 0;
828828
};
829829

830830
FileToSectionIDMap FileToSecIDMap;
@@ -836,8 +836,8 @@ static int linkAndVerify() {
836836
if (!SectionID)
837837
return SectionID.takeError();
838838
RuntimeDyldChecker::MemoryRegionInfo SecInfo;
839-
SecInfo.TargetAddress = Dyld.getSectionLoadAddress(*SectionID);
840-
SecInfo.Content = Dyld.getSectionContent(*SectionID);
839+
SecInfo.setTargetAddress(Dyld.getSectionLoadAddress(*SectionID));
840+
SecInfo.setContent(Dyld.getSectionContent(*SectionID));
841841
return SecInfo;
842842
};
843843

@@ -854,10 +854,10 @@ static int linkAndVerify() {
854854
inconvertibleErrorCode());
855855
auto &SI = StubMap[StubContainer][SymbolName];
856856
RuntimeDyldChecker::MemoryRegionInfo StubMemInfo;
857-
StubMemInfo.TargetAddress =
858-
Dyld.getSectionLoadAddress(SI.SectionID) + SI.Offset;
859-
StubMemInfo.Content =
860-
Dyld.getSectionContent(SI.SectionID).substr(SI.Offset);
857+
StubMemInfo.setTargetAddress(Dyld.getSectionLoadAddress(SI.SectionID) +
858+
SI.Offset);
859+
StubMemInfo.setContent(
860+
Dyld.getSectionContent(SI.SectionID).substr(SI.Offset));
861861
return StubMemInfo;
862862
};
863863

0 commit comments

Comments
 (0)