///
class RuntimeDyldChecker {
public:
- struct MemoryRegionInfo {
- StringRef Content;
- JITTargetAddress TargetAddress;
+ class MemoryRegionInfo {
+ public:
+ MemoryRegionInfo() = default;
+
+ /// Constructor for symbols/sections with content.
+ MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress)
+ : ContentPtr(Content.data()), Size(Content.size()),
+ TargetAddress(TargetAddress) {}
+
+ /// Constructor for zero-fill symbols/sections.
+ MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
+ : Size(Size), TargetAddress(TargetAddress) {}
+
+ /// Returns true if this is a zero-fill symbol/section.
+ bool isZeroFill() const {
+ assert(Size && "setContent/setZeroFill must be called first");
+ return !ContentPtr;
+ }
+
+ /// Set the content for this memory region.
+ void setContent(StringRef Content) {
+ assert(!ContentPtr && !Size && "Content/zero-fill already set");
+ ContentPtr = Content.data();
+ Size = Content.size();
+ }
+
+ /// Set a zero-fill length for this memory region.
+ void setZeroFill(uint64_t Size) {
+ assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
+ this->Size = Size;
+ }
+
+ /// Returns the content for this section if there is any.
+ StringRef getContent() const {
+ assert(!isZeroFill() && "Can't get content for a zero-fill section");
+ return StringRef(ContentPtr, static_cast<size_t>(Size));
+ }
+
+ /// Returns the zero-fill length for this section.
+ uint64_t getZeroFillLength() const {
+ assert(isZeroFill() && "Can't get zero-fill length for content section");
+ return Size;
+ }
+
+ /// Set the target address for this region.
+ void setTargetAddress(JITTargetAddress TargetAddress) {
+ assert(!this->TargetAddress && "TargetAddress already set");
+ this->TargetAddress = TargetAddress;
+ }
+
+ /// Return the target address for this region.
+ JITTargetAddress getTargetAddress() const { return TargetAddress; }
+
+ private:
+ const char *ContentPtr = 0;
+ uint64_t Size = 0;
+ JITTargetAddress TargetAddress = 0;
};
using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
}
MachOSection &setZeroFill(uint64_t Size) {
- assert(!ContentPtr && !Size && "Content/zeroFill already set");
+ assert(!ContentPtr && !this->Size && "Content/zeroFill already set");
this->Size = Size;
return *this;
}
uint64_t LoadAddr = LoadAddrExprResult.getValue();
+ // If there is no error but the content pointer is null then this is a
+ // zero-fill symbol/section.
+ if (LoadAddr == 0)
+ return std::make_pair(0, RemainingExpr);
+
return std::make_pair(
EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)),
RemainingExpr);
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
return 0;
}
+
+ if (SymInfo->isZeroFill())
+ return 0;
+
return static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(SymInfo->Content.data()));
+ reinterpret_cast<uintptr_t>(SymInfo->getContent().data()));
}
uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
return 0;
}
- return SymInfo->TargetAddress;
+ return SymInfo->getTargetAddress();
}
uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
return StringRef();
}
- return SymInfo->Content;
+ return SymInfo->getContent();
}
std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
uint64_t Addr = 0;
- if (IsInsideLoad)
- Addr = pointerToJITTargetAddress(SecInfo->Content.data());
- else
- Addr = SecInfo->TargetAddress;
+ if (IsInsideLoad) {
+ if (SecInfo->isZeroFill())
+ Addr = 0;
+ else
+ Addr = pointerToJITTargetAddress(SecInfo->getContent().data());
+ } else
+ Addr = SecInfo->getTargetAddress();
return std::make_pair(Addr, "");
}
uint64_t Addr = 0;
- if (IsInsideLoad)
- Addr = pointerToJITTargetAddress(StubInfo->Content.data());
- else
- Addr = StubInfo->TargetAddress;
+ if (IsInsideLoad) {
+ if (StubInfo->isZeroFill())
+ return std::make_pair((uint64_t)0, "Detected zero-filled stub/GOT entry");
+ Addr = pointerToJITTargetAddress(StubInfo->getContent().data());
+ } else
+ Addr = StubInfo->getTargetAddress();
return std::make_pair(Addr, "");
}
.section __DATA,__nds_test_sect,regular,no_dead_strip
.quad 0
+# Check that explicit zero-fill symbols are supported
+# jitlink-check: *{8}zero_fill_test = 0
+ .globl zero_fill_test
+.zerofill __DATA,__zero_fill_test,zero_fill_test,8,3
+
.subsections_via_symbols
//
//===----------------------------------------------------------------------===//
//
-// .
+// MachO parsing support for llvm-jitlink.
//
//===----------------------------------------------------------------------===//
bool isGOTSection = isMachOGOTSection(Sec);
bool isStubsSection = isMachOStubsSection(Sec);
- auto &SectionInfo = FileInfo.SectionInfos[Sec.getName()];
-
auto *FirstAtom = *Sec.atoms().begin();
auto *LastAtom = FirstAtom;
for (auto *DA : Sec.atoms()) {
if (DA->getAddress() > LastAtom->getAddress())
LastAtom = DA;
if (isGOTSection) {
+ if (Sec.isZeroFill())
+ return make_error<StringError>("Content atom in zero-fill section",
+ inconvertibleErrorCode());
+
if (auto TA = getMachOGOTTarget(G, *DA)) {
FileInfo.GOTEntryInfos[TA->getName()] = {DA->getContent(),
DA->getAddress()};
} else
return TA.takeError();
} else if (isStubsSection) {
+ if (Sec.isZeroFill())
+ return make_error<StringError>("Content atom in zero-fill section",
+ inconvertibleErrorCode());
+
if (auto TA = getMachOStubTarget(G, *DA))
FileInfo.StubInfos[TA->getName()] = {DA->getContent(),
DA->getAddress()};
else
return TA.takeError();
- } else if (DA->hasName() && DA->isGlobal())
- S.SymbolInfos[DA->getName()] = {DA->getContent(), DA->getAddress()};
+ } else if (DA->hasName() && DA->isGlobal()) {
+ if (DA->isZeroFill())
+ S.SymbolInfos[DA->getName()] = {DA->getSize(), DA->getAddress()};
+ else {
+ if (Sec.isZeroFill())
+ return make_error<StringError>("Content atom in zero-fill section",
+ inconvertibleErrorCode());
+ S.SymbolInfos[DA->getName()] = {DA->getContent(), DA->getAddress()};
+ }
+ }
}
- const char *StartAddr = FirstAtom->getContent().data();
- const char *EndAddr =
- LastAtom->getContent().data() + LastAtom->getContent().size();
- SectionInfo.TargetAddress = FirstAtom->getAddress();
- SectionInfo.Content = StringRef(StartAddr, EndAddr - StartAddr);
+
+ JITTargetAddress SecAddr = FirstAtom->getAddress();
+ uint64_t SecSize = (LastAtom->getAddress() + LastAtom->getSize()) -
+ FirstAtom->getAddress();
+
+ if (Sec.isZeroFill())
+ FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr};
+ else
+ FileInfo.SectionInfos[Sec.getName()] = {
+ StringRef(FirstAtom->getContent().data(), SecSize), SecAddr};
}
return Error::success();
static raw_ostream &
operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {
- return OS << "target addr = " << format("0x%016" PRIx64, MRI.TargetAddress)
- << ", content: " << (const void *)MRI.Content.data() << " -- "
- << (const void *)(MRI.Content.data() + MRI.Content.size()) << " ("
- << MRI.Content.size() << " bytes)";
+ return OS << "target addr = "
+ << format("0x%016" PRIx64, MRI.getTargetAddress())
+ << ", content: " << (const void *)MRI.getContent().data() << " -- "
+ << (const void *)(MRI.getContent().data() + MRI.getContent().size())
+ << " (" << MRI.getContent().size() << " bytes)";
}
static raw_ostream &
// First get the target address.
if (auto InternalSymbol = Dyld.getSymbol(Symbol))
- SymInfo.TargetAddress = InternalSymbol.getAddress();
+ SymInfo.setTargetAddress(InternalSymbol.getAddress());
else {
// Symbol not found in RuntimeDyld. Fall back to external lookup.
#ifdef _MSC_VER
auto I = Result->find(Symbol);
assert(I != Result->end() &&
"Expected symbol address if no error occurred");
- SymInfo.TargetAddress = I->second.getAddress();
+ SymInfo.setTargetAddress(I->second.getAddress());
}
// Now find the symbol content if possible (otherwise leave content as a
char *CSymAddr = static_cast<char *>(SymAddr);
StringRef SecContent = Dyld.getSectionContent(SectionID);
uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
- SymInfo.Content = StringRef(CSymAddr, SymSize);
+ SymInfo.setContent(StringRef(CSymAddr, SymSize));
}
}
return SymInfo;
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
return false;
}
- return SymInfo->TargetAddress != 0;
+ return SymInfo->getTargetAddress() != 0;
};
FileToSectionIDMap FileToSecIDMap;
if (!SectionID)
return SectionID.takeError();
RuntimeDyldChecker::MemoryRegionInfo SecInfo;
- SecInfo.TargetAddress = Dyld.getSectionLoadAddress(*SectionID);
- SecInfo.Content = Dyld.getSectionContent(*SectionID);
+ SecInfo.setTargetAddress(Dyld.getSectionLoadAddress(*SectionID));
+ SecInfo.setContent(Dyld.getSectionContent(*SectionID));
return SecInfo;
};
inconvertibleErrorCode());
auto &SI = StubMap[StubContainer][SymbolName];
RuntimeDyldChecker::MemoryRegionInfo StubMemInfo;
- StubMemInfo.TargetAddress =
- Dyld.getSectionLoadAddress(SI.SectionID) + SI.Offset;
- StubMemInfo.Content =
- Dyld.getSectionContent(SI.SectionID).substr(SI.Offset);
+ StubMemInfo.setTargetAddress(Dyld.getSectionLoadAddress(SI.SectionID) +
+ SI.Offset);
+ StubMemInfo.setContent(
+ Dyld.getSectionContent(SI.SectionID).substr(SI.Offset));
return StubMemInfo;
};