22#define DEBUG_TYPE "goff"
35 return PhysicalRecord[1] & 0x02;
40 return PhysicalRecord[1] & 0x01;
59 const uint8_t *Ptr =
Record + DataIndex;
60 size_t SliceLength = std::min(
62 CompleteData.
append(Ptr, Ptr + SliceLength);
63 DataLength -= SliceLength;
66 unsigned BlocksConsumed = 1;
68 while (DataLength > 0) {
75 "continued bit should not be set");
80 CompleteData.
append(Ptr, Ptr + SliceLength);
81 DataLength -= SliceLength;
86 return BlocksConsumed;
90Error GOFFObjectFile::createFlattenedData() {
91 const uint8_t *It =
base();
95 const uint8_t *ValidateIt = It;
96 unsigned ValidateIndex = 0;
97 bool PrevContinued =
false;
98 bool PrevWasContinuation =
false;
101 while (ValidateIt < End) {
108 if (!PrevContinued) {
110 "record " + std::to_string(ValidateIndex) +
111 " is a continuation record that is not "
112 "preceded by a continued record");
115 if (CurrentType != PrevRecordType) {
118 "record " + std::to_string(ValidateIndex) +
119 " is a continuation record that does not match "
120 "the type of the previous record");
123 PrevContinued = IsContd;
126 if (PrevContinued && !PrevWasContinuation) {
128 "record " + std::to_string(ValidateIndex) +
129 " is not a continuation record but the "
130 "preceding record is continued");
132 PrevRecordType = CurrentType;
133 PrevContinued = IsContd;
136 PrevWasContinuation = IsCont;
154 uint16_t DataLength = 0;
156 DataExtractor DE(Slice,
false);
162 DataLength = DE.getU16(&
Offset);
168 DataLength = DE.getU16(&
Offset);
174 DataLength = DE.getU16(&
Offset);
180 DataLength = DE.getU16(&
Offset);
186 DataLength = DE.getU16(&
Offset);
192 DataLength = DE.getU16(&
Offset);
197 SmallVector<uint8_t> CompleteData;
198 Expected<unsigned> BlocksConsumed =
199 getContinuousData(CompleteData, DataIndex, DataLength, It);
200 if (!BlocksConsumed) {
204 BlocksConsumed.
takeError(), [](
const llvm::ErrorInfoBase &EIB) {
205 llvm::errs() <<
"ERROR: " << EIB.message() <<
"\n";
211 FlattenedData.push_back({
RecordType, std::move(CompleteData)});
219Expected<std::unique_ptr<ObjectFile>>
222 std::unique_ptr<GOFFObjectFile> Ret(
new GOFFObjectFile(Object, Err));
224 return std::move(Err);
225 return std::move(Ret);
235 "object file is not the right size. Must be a multiple "
236 "of 80 bytes, but is " +
237 std::to_string(Object.getBufferSize()) +
" bytes");
242 if (Object.getBufferSize() != 0) {
245 "object file must start with HDR record");
251 "object file must end with END record");
256 if (
Error E = createFlattenedData()) {
261 SectionEntryImpl DummySection;
262 SectionList.emplace_back(DummySection);
285 SectionEntryImpl Section;
292 SectionList.emplace_back(Section);
299 Section.d.a = SymEdId;
301 SectionList.emplace_back(Section);
307 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
313 Section.d.a = SymEdId;
314 SectionList.emplace_back(Section);
322 TextPtrs.emplace_back(
I);
342 const uint8_t *EsdRecord = EsdPtrs[Symb.
d.
a];
347 if (
auto It = EsdNamesCache.find(Symb.
d.
a); It != EsdNamesCache.end()) {
348 auto &StrPtr = It->second;
349 return StringRef(StrPtr.second.get(), StrPtr.first);
353 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
358 if (NameLength > 0) {
361 const uint8_t *NameStart = EsdRecord + 72;
362 SymbolName.append(NameStart, NameStart + NameLength);
365 SmallString<256> SymbolNameConverted;
368 size_t Size = SymbolNameConverted.
size();
369 auto StrPtr = std::make_pair(
Size, std::make_unique<
char[]>(
Size));
370 char *Buf = StrPtr.second.get();
371 memcpy(Buf, SymbolNameConverted.
data(),
Size);
372 EsdNamesCache[Symb.
d.
a] = std::move(StrPtr);
373 return StringRef(Buf,
Size);
382 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
389 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
398bool GOFFObjectFile::isSymbolUnresolved(
DataRefImpl Symb)
const {
399 const uint8_t *
Record = getSymbolEsdRecord(Symb);
414bool GOFFObjectFile::isSymbolIndirect(
DataRefImpl Symb)
const {
415 const uint8_t *
Record = getSymbolEsdRecord(Symb);
421Expected<uint32_t> GOFFObjectFile::getSymbolFlags(
DataRefImpl Symb)
const {
423 if (isSymbolUnresolved(Symb))
426 const uint8_t *
Record = getSymbolEsdRecord(Symb);
444 if (Name && *Name !=
" ") {
456Expected<SymbolRef::Type>
457GOFFObjectFile::getSymbolType(
DataRefImpl Symb)
const {
458 const uint8_t *
Record = getSymbolEsdRecord(Symb);
472 "ESD record %" PRIu32
473 " has invalid symbol type 0x%02" PRIX8,
488 "ESD record %" PRIu32
489 " has unknown Executable type 0x%02X",
492 switch (Executable) {
505Expected<section_iterator>
506GOFFObjectFile::getSymbolSection(
DataRefImpl Symb)
const {
509 if (isSymbolUnresolved(Symb))
512 const uint8_t *SymEsdRecord = EsdPtrs[Symb.
d.
a];
515 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
517 for (
size_t I = 0,
E = SectionList.size();
I <
E; ++
I) {
519 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(
I);
520 if (SectionPrRecord) {
521 Found = SymEsdRecord == SectionPrRecord;
523 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(
I);
524 Found = SymEdRecord == SectionEdRecord;
533 "symbol with ESD id " + std::to_string(Symb.
d.
a) +
534 " refers to invalid section with ESD id " +
535 std::to_string(SymEdId));
538uint64_t GOFFObjectFile::getSymbolSize(
DataRefImpl Symb)
const {
539 const uint8_t *
Record = getSymbolEsdRecord(Symb);
545const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(
DataRefImpl &Sec)
const {
546 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
547 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
551const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(
DataRefImpl &Sec)
const {
552 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
553 const uint8_t *EsdRecord =
nullptr;
555 EsdRecord = EsdPtrs[EsdIds.d.b];
560GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex)
const {
562 Sec.
d.
a = SectionIndex;
563 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
568GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex)
const {
570 Sec.
d.
a = SectionIndex;
571 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
575uint32_t GOFFObjectFile::getSectionDefEsdId(
DataRefImpl &Sec)
const {
576 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
580 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
582 EsdRecord = PrEsdRecord;
591void GOFFObjectFile::moveSectionNext(
DataRefImpl &Sec)
const {
593 if ((Sec.
d.
a) >= SectionList.size())
597Expected<StringRef> GOFFObjectFile::getSectionName(
DataRefImpl Sec)
const {
599 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
600 EdSym.
d.
a = EsdIds.d.a;
603 StringRef Res = *
Name;
611uint64_t GOFFObjectFile::getSectionAddress(
DataRefImpl Sec)
const {
613 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
618uint64_t GOFFObjectFile::getSectionSize(
DataRefImpl Sec)
const {
620 uint32_t DefEsdId = getSectionDefEsdId(Sec);
621 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
624 return static_cast<uint64_t
>(
Length);
629Expected<ArrayRef<uint8_t>>
630GOFFObjectFile::getSectionContents(
DataRefImpl Sec)
const {
631 if (
auto It = SectionDataCache.find(Sec.
d.
a); It != SectionDataCache.end()) {
632 auto &Buf = It->second;
633 return ArrayRef<uint8_t>(Buf);
636 uint32_t DefEsdId = getSectionDefEsdId(Sec);
638 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
639 bool FillBytePresent;
641 uint8_t FillByte =
'\0';
646 SmallVector<uint8_t>
Data(SectionSize, FillByte);
649 for (
const uint8_t *TxtRecordPtr : TextPtrs) {
654 if (TxtEsdId != DefEsdId)
657 uint32_t TxtDataOffset;
660 uint16_t TxtDataSize;
663 LLVM_DEBUG(
dbgs() <<
"Record offset " << TxtDataOffset <<
", data size "
664 << TxtDataSize <<
"\n");
668 const uint8_t *TxtData = TxtRecordPtr + 24;
669 assert(TxtDataSize <=
Data.size() - TxtDataOffset &&
670 "Text data exceeds section size");
671 std::copy(TxtData, TxtData + TxtDataSize,
Data.begin() + TxtDataOffset);
673 auto &Cache = SectionDataCache[Sec.
d.
a];
674 Cache = std::move(
Data);
675 return ArrayRef<uint8_t>(Cache);
678uint64_t GOFFObjectFile::getSectionAlignment(
DataRefImpl Sec)
const {
679 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
682 return 1ULL <<
static_cast<uint64_t
>(Pow2Alignment);
685bool GOFFObjectFile::isSectionText(
DataRefImpl Sec)
const {
686 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
692bool GOFFObjectFile::isSectionData(
DataRefImpl Sec)
const {
693 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
700 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
707 if (!isSectionData(Sec))
710 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
724 moveSectionNext(Sec);
734 for (
uint32_t I = Symb.
d.
a + 1, E = EsdPtrs.size();
I < E; ++
I) {
735 if (
const uint8_t *EsdRecord = EsdPtrs[
I]) {
739 bool IgnoreSpecialGOFFSymbols =
true;
742 IgnoreSpecialGOFFSymbols;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool isContinued(const uint8_t *PhysicalRecord)
static bool isContinuation(const uint8_t *PhysicalRecord)
static GOFF::RecordType getRecordType(const uint8_t *PhysicalRecord)
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
pointer data()
Return a pointer to the vector's buffer, even if empty().
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
StringRef getData() const
static void getIndirectReference(const uint8_t *Record, bool &Indirect)
static void getBindingStrength(const uint8_t *Record, GOFF::ESDBindingStrength &Strength)
static void getOffset(const uint8_t *Record, uint32_t &Offset)
static void getEsdId(const uint8_t *Record, uint32_t &EsdId)
static void getLoadingBehavior(const uint8_t *Record, GOFF::ESDLoadingBehavior &Behavior)
static void getFillBytePresent(const uint8_t *Record, bool &Present)
static void getLength(const uint8_t *Record, uint32_t &Length)
static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId)
static void getFillByteValue(const uint8_t *Record, uint8_t &Fill)
static void getSymbolType(const uint8_t *Record, GOFF::ESDSymbolType &SymbolType)
static void getAlignment(const uint8_t *Record, GOFF::ESDAlignment &Alignment)
static uint16_t getNameLength(const uint8_t *Record)
static void getExecutable(const uint8_t *Record, GOFF::ESDExecutable &Executable)
static void getBindingScope(const uint8_t *Record, GOFF::ESDBindingScope &Scope)
section_iterator section_begin() const override
basic_symbol_iterator symbol_end() const override
GOFFObjectFile(MemoryBufferRef Object, Error &Err)
bool isSectionReadOnlyData(DataRefImpl Sec) const
bool isSectionNoLoad(DataRefImpl Sec) const
section_iterator section_end() const override
Expected< StringRef > getSymbolName(SymbolRef Symbol) const
void moveSymbolNext(DataRefImpl &Symb) const override
basic_symbol_iterator symbol_begin() const override
bool isSectionZeroInit(DataRefImpl Sec) const
const uint8_t * base() const
static Expected< std::unique_ptr< ObjectFile > > createGOFFObjectFile(MemoryBufferRef Object)
ObjectFile(unsigned int Type, MemoryBufferRef Source)
Represents a GOFF physical record.
static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId)
static void getDataLength(const uint8_t *Record, uint16_t &Length)
static void getOffset(const uint8_t *Record, uint32_t &Offset)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI void convertToUTF8(StringRef Source, SmallVectorImpl< char > &Result)
constexpr uint8_t RecordPrefixLength
constexpr uint8_t PayloadLength
constexpr uint8_t RecordLength
Length of the parts of a physical GOFF record.
@ ESD_ST_ElementDefinition
@ ESD_ST_SectionDefinition
@ ESD_ST_ExternalReference
content_iterator< SectionRef > section_iterator
content_iterator< BasicSymbolRef > basic_symbol_iterator
This is an optimization pass for GlobalISel generic memory operations.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d