23#define DEBUG_TYPE "goff"
36 return PhysicalRecord[1] & 0x02;
41 return PhysicalRecord[1] & 0x01;
60 const uint8_t *Ptr =
Record + DataIndex;
61 size_t SliceLength = std::min(
63 CompleteData.
append(Ptr, Ptr + SliceLength);
64 DataLength -= SliceLength;
67 unsigned BlocksConsumed = 1;
69 while (DataLength > 0) {
76 "continued bit should not be set");
81 CompleteData.
append(Ptr, Ptr + SliceLength);
82 DataLength -= SliceLength;
87 return BlocksConsumed;
91Error GOFFObjectFile::createFlattenedData() {
92 const uint8_t *It =
base();
96 const uint8_t *ValidateIt = It;
97 unsigned ValidateIndex = 0;
98 bool PrevContinued =
false;
99 bool PrevWasContinuation =
false;
102 while (ValidateIt < End) {
109 if (!PrevContinued) {
111 "record " + std::to_string(ValidateIndex) +
112 " is a continuation record that is not "
113 "preceded by a continued record");
116 if (CurrentType != PrevRecordType) {
119 "record " + std::to_string(ValidateIndex) +
120 " is a continuation record that does not match "
121 "the type of the previous record");
124 PrevContinued = IsContd;
127 if (PrevContinued && !PrevWasContinuation) {
129 "record " + std::to_string(ValidateIndex) +
130 " is not a continuation record but the "
131 "preceding record is continued");
133 PrevRecordType = CurrentType;
134 PrevContinued = IsContd;
137 PrevWasContinuation = IsCont;
155 uint16_t DataLength = 0;
157 DataExtractor DE(Slice,
false);
163 DataLength = DE.getU16(&
Offset);
169 DataLength = DE.getU16(&
Offset);
175 DataLength = DE.getU16(&
Offset);
181 DataLength = DE.getU16(&
Offset);
187 DataLength = DE.getU16(&
Offset);
193 DataLength = DE.getU16(&
Offset);
198 SmallVector<uint8_t> CompleteData;
199 Expected<unsigned> BlocksConsumed =
200 getContinuousData(CompleteData, DataIndex, DataLength, It);
201 if (!BlocksConsumed) {
205 BlocksConsumed.
takeError(), [](
const llvm::ErrorInfoBase &EIB) {
206 llvm::errs() <<
"ERROR: " << EIB.message() <<
"\n";
212 FlattenedData.push_back({
RecordType, std::move(CompleteData)});
220Expected<std::unique_ptr<ObjectFile>>
223 std::unique_ptr<GOFFObjectFile> Ret(
new GOFFObjectFile(Object, Err));
225 return std::move(Err);
226 return std::move(Ret);
236 "object file is not the right size. Must be a multiple "
237 "of 80 bytes, but is " +
238 std::to_string(Object.getBufferSize()) +
" bytes");
243 if (Object.getBufferSize() != 0) {
246 "object file must start with HDR record");
252 "object file must end with END record");
257 if (
Error E = createFlattenedData()) {
262 SectionEntryImpl DummySection;
263 SectionList.emplace_back(DummySection);
268 RelEntries.emplace_back(DummyRelEntry);
291 SectionEntryImpl Section;
298 SectionList.emplace_back(Section);
305 Section.d.a = SymEdId;
307 SectionList.emplace_back(Section);
313 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
319 Section.d.a = SymEdId;
320 SectionList.emplace_back(Section);
328 TextPtrs.emplace_back(
I);
332 setRelocationData(
I);
349 const uint8_t *EsdRecord = EsdPtrs[Symb.
d.
a];
354 if (
auto It = EsdNamesCache.find(Symb.
d.
a); It != EsdNamesCache.end()) {
355 auto &StrPtr = It->second;
356 return StringRef(StrPtr.second.get(), StrPtr.first);
360 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
365 if (NameLength > 0) {
368 const uint8_t *NameStart = EsdRecord + 72;
369 SymbolName.append(NameStart, NameStart + NameLength);
372 SmallString<256> SymbolNameConverted;
375 size_t Size = SymbolNameConverted.
size();
376 auto StrPtr = std::make_pair(
Size, std::make_unique<
char[]>(
Size));
377 char *Buf = StrPtr.second.get();
378 memcpy(Buf, SymbolNameConverted.
data(),
Size);
379 EsdNamesCache[Symb.
d.
a] = std::move(StrPtr);
380 return StringRef(Buf,
Size);
389 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
391 return static_cast<uint64_t
>(
Offset);
394uint64_t GOFFObjectFile::getSymbolValueImpl(
DataRefImpl Symb)
const {
396 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
398 return static_cast<uint64_t
>(
Offset);
405bool GOFFObjectFile::isSymbolUnresolved(
DataRefImpl Symb)
const {
406 const uint8_t *
Record = getSymbolEsdRecord(Symb);
421bool GOFFObjectFile::isSymbolIndirect(
DataRefImpl Symb)
const {
422 const uint8_t *
Record = getSymbolEsdRecord(Symb);
428Expected<uint32_t> GOFFObjectFile::getSymbolFlags(
DataRefImpl Symb)
const {
430 if (isSymbolUnresolved(Symb))
433 const uint8_t *
Record = getSymbolEsdRecord(Symb);
451 if (Name && *Name !=
" ") {
463Expected<SymbolRef::Type>
464GOFFObjectFile::getSymbolType(
DataRefImpl Symb)
const {
465 const uint8_t *
Record = getSymbolEsdRecord(Symb);
479 "ESD record %" PRIu32
480 " has invalid symbol type 0x%02" PRIX8,
495 "ESD record %" PRIu32
496 " has unknown Executable type 0x%02X",
499 switch (Executable) {
512Expected<section_iterator>
513GOFFObjectFile::getSymbolSection(
DataRefImpl Symb)
const {
516 if (isSymbolUnresolved(Symb))
519 const uint8_t *SymEsdRecord = EsdPtrs[Symb.
d.
a];
522 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
524 for (
size_t I = 0,
E = SectionList.size();
I <
E; ++
I) {
526 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(
I);
527 if (SectionPrRecord) {
528 Found = SymEsdRecord == SectionPrRecord;
530 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(
I);
531 Found = SymEdRecord == SectionEdRecord;
540 "symbol with ESD id " + std::to_string(Symb.
d.
a) +
541 " refers to invalid section with ESD id " +
542 std::to_string(SymEdId));
546 const uint8_t *SymRecord = getSymbolEsdRecord(Symb);
561 const uint8_t *EdRecord = EsdPtrs[ParentEsdId];
583uint64_t GOFFObjectFile::getSymbolSize(
DataRefImpl Symb)
const {
591 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
592 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
597 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
598 const uint8_t *EsdRecord =
nullptr;
600 EsdRecord = EsdPtrs[EsdIds.d.b];
605GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex)
const {
607 Sec.
d.
a = SectionIndex;
608 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
613GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex)
const {
615 Sec.
d.
a = SectionIndex;
616 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
620uint32_t GOFFObjectFile::getSectionDefEsdId(
DataRefImpl &Sec)
const {
621 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
625 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
627 EsdRecord = PrEsdRecord;
636void GOFFObjectFile::moveSectionNext(
DataRefImpl &Sec)
const {
638 if ((Sec.
d.
a) >= SectionList.size())
642Expected<StringRef> GOFFObjectFile::getSectionName(
DataRefImpl Sec)
const {
644 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
645 EdSym.
d.
a = EsdIds.d.a;
648 StringRef Res = *
Name;
658 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
665 uint32_t DefEsdId = getSectionDefEsdId(Sec);
666 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
674Expected<ArrayRef<uint8_t>>
675GOFFObjectFile::getSectionContents(
DataRefImpl Sec)
const {
676 if (
auto It = SectionDataCache.find(Sec.
d.
a); It != SectionDataCache.end()) {
677 auto &Buf = It->second;
678 return ArrayRef<uint8_t>(Buf);
681 uint32_t DefEsdId = getSectionDefEsdId(Sec);
683 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
684 bool FillBytePresent;
686 uint8_t FillByte =
'\0';
691 SmallVector<uint8_t>
Data(SectionSize, FillByte);
694 for (
const uint8_t *TxtRecordPtr : TextPtrs) {
699 if (TxtEsdId != DefEsdId)
702 uint32_t TxtDataOffset;
705 uint16_t TxtDataSize;
708 LLVM_DEBUG(
dbgs() <<
"Record offset " << TxtDataOffset <<
", data size "
709 << TxtDataSize <<
"\n");
713 const uint8_t *TxtData = TxtRecordPtr + 24;
714 assert(TxtDataSize <=
Data.size() - TxtDataOffset &&
715 "Text data exceeds section size");
716 std::copy(TxtData, TxtData + TxtDataSize,
Data.begin() + TxtDataOffset);
718 auto &Cache = SectionDataCache[Sec.
d.
a];
719 Cache = std::move(
Data);
720 return ArrayRef<uint8_t>(Cache);
724 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
727 return 1ULL <<
static_cast<uint64_t>(Pow2Alignment);
730bool GOFFObjectFile::isSectionText(
DataRefImpl Sec)
const {
731 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
737bool GOFFObjectFile::isSectionData(
DataRefImpl Sec)
const {
738 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
745 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
752 if (!isSectionData(Sec))
755 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
769 moveSectionNext(Sec);
779 for (
uint32_t I = Symb.
d.
a + 1, E = EsdPtrs.size();
I < E; ++
I) {
780 if (
const uint8_t *EsdRecord = EsdPtrs[
I]) {
784 bool IgnoreSpecialGOFFSymbols =
true;
787 IgnoreSpecialGOFFSymbols;
815void GOFFObjectFile::setRelocationData(
const uint8_t *RldRecord) {
822 const uint8_t *RldI = RldRecord + DataIndex;
823 const uint8_t *RldE = RldI + DataLength;
827 for (
const uint8_t *Rld = RldI; Rld < RldE;) {
851 RelEntry.
PEsdId = CurPEsdId;
852 RelEntry.
REsdId = CurREsdId;
855 RelEntries.emplace_back(RelEntry);
858 assert(Rld <= RldE &&
"RLD length?");
862void GOFFObjectFile::moveRelocationNext(
DataRefImpl &Rel)
const {
863 for (
size_t I = Rel.
d.
b + 1,
E = RelEntries.size();
I <
E; ++
I) {
864 const GOFFRelEntry &RelEntry = RelEntries[
I];
875 assert(Rel.
d.
b > 0 && Rel.
d.
b < RelEntries.size() &&
876 "Rel Index out of boundary");
877 const GOFFRelEntry &RelEntry = RelEntries[Rel.
d.
b];
882 assert(Rel.
d.
b > 0 && Rel.
d.
b < RelEntries.size() &&
883 "Rel Index out of boundary");
884 const GOFFRelEntry &RelEntry = RelEntries[Rel.
d.
b];
891 assert(Rel.
d.
b > 0 && Rel.
d.
b < RelEntries.size() &&
892 "Rel Index out of boundary");
893 const GOFFRelEntry &RelEntry = RelEntries[Rel.
d.
b];
897void GOFFObjectFile::getRelocationTypeName(
898 DataRefImpl Rel, SmallVectorImpl<char> &Result)
const {
899 uint64_t RelType = getRelocationType(Rel);
900 std::string HexStr =
formatv(
"R_{0:x-8}", RelType).str();
901 Result.append(HexStr.begin(), HexStr.end());
906 Rel.
d.
a = getSectionDefEsdId(Sec);
908 moveRelocationNext(Rel);
914 Rel.
d.
a = getSectionDefEsdId(Sec);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
constexpr uint8_t SAME_R_ID
static bool isContinued(const uint8_t *PhysicalRecord)
constexpr uint8_t SAME_P_ID
constexpr uint8_t EXT_ATTR_PRESENT
constexpr uint8_t SAME_OFFSET
constexpr uint8_t BYTE_OFFSET_8
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().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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 getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode)
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 void getLinkageType(const uint8_t *Record, GOFF::ESDLinkageType &Type)
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)
static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id)
uint32_t getZOSSymbolArchiveAttributes(DataRefImpl Symb) const
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
friend class RelocationRef
const uint8_t * base() const
static Expected< std::unique_ptr< ObjectFile > > createGOFFObjectFile(MemoryBufferRef Object)
ObjectFile(unsigned int Type, MemoryBufferRef Source)
static void getDataLength(const uint8_t *Record, uint16_t &Length)
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
uint64_t getRldType(const uint8_t *Rld)
content_iterator< RelocationRef > relocation_iterator
uint64_t read64be(const void *P)
uint32_t read32be(const void *P)
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.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d