21#define DEBUG_TYPE "goff"
30 std::unique_ptr<GOFFObjectFile> Ret(
new GOFFObjectFile(Object, Err));
32 return std::move(Err);
33 return std::move(Ret);
43 "object file is not the right size. Must be a multiple "
44 "of 80 bytes, but is " +
45 std::to_string(Object.getBufferSize()) +
" bytes");
50 if (Object.getBufferSize() != 0) {
53 "object file must start with HDR record");
59 "object file must end with END record");
64 SectionEntryImpl DummySection;
65 SectionList.emplace_back(DummySection);
68 uint8_t PrevContinuationBits = 0;
72 bool IsContinuation =
I[1] & 0x02;
73 bool PrevWasContinued = PrevContinuationBits & 0x01;
78 if (PrevWasContinued && !IsContinuation) {
81 "record " + std::to_string(RecordNum) +
82 " is not a continuation record but the "
83 "preceding record is continued");
91 "record " + std::to_string(RecordNum) +
92 " is a continuation record that does not "
93 "match the type of the previous record");
96 if (!PrevWasContinued) {
98 "record " + std::to_string(RecordNum) +
99 " is a continuation record that is not "
100 "preceded by a continued record");
104 PrevContinuationBits =
I[1] & 0x03;
133 SectionEntryImpl Section;
140 SectionList.emplace_back(Section);
147 Section.d.a = SymEdId;
149 SectionList.emplace_back(Section);
155 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
161 Section.d.a = SymEdId;
162 SectionList.emplace_back(Section);
170 TextPtrs.emplace_back(
I);
187 "record %zu has unknown record type 0x%02" PRIX8,
192 PrevContinuationBits =
I[1] & 0x03;
197 const uint8_t *EsdRecord = EsdPtrs[Symb.
d.
a];
202 if (
auto It = EsdNamesCache.find(Symb.
d.
a); It != EsdNamesCache.end()) {
203 auto &StrPtr = It->second;
204 return StringRef(StrPtr.second.get(), StrPtr.first);
209 return std::move(Err);
214 size_t Size = SymbolNameConverted.
size();
215 auto StrPtr = std::make_pair(
Size, std::make_unique<
char[]>(
Size));
216 char *Buf = StrPtr.second.get();
217 memcpy(Buf, SymbolNameConverted.
data(),
Size);
218 EsdNamesCache[Symb.
d.
a] = std::move(StrPtr);
228 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
235 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
244bool GOFFObjectFile::isSymbolUnresolved(
DataRefImpl Symb)
const {
245 const uint8_t *
Record = getSymbolEsdRecord(Symb);
260bool GOFFObjectFile::isSymbolIndirect(
DataRefImpl Symb)
const {
261 const uint8_t *
Record = getSymbolEsdRecord(Symb);
267Expected<uint32_t> GOFFObjectFile::getSymbolFlags(
DataRefImpl Symb)
const {
269 if (isSymbolUnresolved(Symb))
272 const uint8_t *
Record = getSymbolEsdRecord(Symb);
284 if (Name && *Name !=
" ") {
296Expected<SymbolRef::Type>
297GOFFObjectFile::getSymbolType(
DataRefImpl Symb)
const {
298 const uint8_t *
Record = getSymbolEsdRecord(Symb);
312 "ESD record %" PRIu32
313 " has invalid symbol type 0x%02" PRIX8,
328 "ESD record %" PRIu32
329 " has unknown Executable type 0x%02X",
332 switch (Executable) {
345Expected<section_iterator>
346GOFFObjectFile::getSymbolSection(
DataRefImpl Symb)
const {
349 if (isSymbolUnresolved(Symb))
352 const uint8_t *SymEsdRecord = EsdPtrs[Symb.
d.
a];
355 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
357 for (
size_t I = 0,
E = SectionList.size();
I <
E; ++
I) {
359 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(
I);
360 if (SectionPrRecord) {
361 Found = SymEsdRecord == SectionPrRecord;
363 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(
I);
364 Found = SymEdRecord == SectionEdRecord;
373 "symbol with ESD id " + std::to_string(Symb.
d.
a) +
374 " refers to invalid section with ESD id " +
375 std::to_string(SymEdId));
378uint64_t GOFFObjectFile::getSymbolSize(
DataRefImpl Symb)
const {
379 const uint8_t *
Record = getSymbolEsdRecord(Symb);
385const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(
DataRefImpl &Sec)
const {
386 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
387 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
391const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(
DataRefImpl &Sec)
const {
392 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
393 const uint8_t *EsdRecord =
nullptr;
395 EsdRecord = EsdPtrs[EsdIds.d.b];
400GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex)
const {
402 Sec.
d.
a = SectionIndex;
403 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
408GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex)
const {
410 Sec.
d.
a = SectionIndex;
411 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
415uint32_t GOFFObjectFile::getSectionDefEsdId(
DataRefImpl &Sec)
const {
416 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
420 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
422 EsdRecord = PrEsdRecord;
431void GOFFObjectFile::moveSectionNext(
DataRefImpl &Sec)
const {
433 if ((Sec.
d.
a) >= SectionList.size())
437Expected<StringRef> GOFFObjectFile::getSectionName(
DataRefImpl Sec)
const {
439 SectionEntryImpl EsdIds = SectionList[Sec.
d.
a];
440 EdSym.
d.
a = EsdIds.d.a;
443 StringRef Res = *
Name;
451uint64_t GOFFObjectFile::getSectionAddress(
DataRefImpl Sec)
const {
453 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
458uint64_t GOFFObjectFile::getSectionSize(
DataRefImpl Sec)
const {
460 uint32_t DefEsdId = getSectionDefEsdId(Sec);
461 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
464 return static_cast<uint64_t
>(
Length);
469Expected<ArrayRef<uint8_t>>
470GOFFObjectFile::getSectionContents(
DataRefImpl Sec)
const {
471 if (
auto It = SectionDataCache.find(Sec.
d.
a); It != SectionDataCache.end()) {
472 auto &Buf = It->second;
473 return ArrayRef<uint8_t>(Buf);
476 uint32_t DefEsdId = getSectionDefEsdId(Sec);
478 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
479 bool FillBytePresent;
481 uint8_t FillByte =
'\0';
486 SmallVector<uint8_t>
Data(SectionSize, FillByte);
489 for (
const uint8_t *TxtRecordInt : TextPtrs) {
490 const uint8_t *TxtRecordPtr = TxtRecordInt;
495 if (TxtEsdId != DefEsdId)
498 uint32_t TxtDataOffset;
501 uint16_t TxtDataSize;
504 LLVM_DEBUG(
dbgs() <<
"Record offset " << TxtDataOffset <<
", data size "
505 << TxtDataSize <<
"\n");
507 SmallString<256> CompleteData;
508 CompleteData.
reserve(TxtDataSize);
510 return std::move(Err);
511 assert(CompleteData.
size() == TxtDataSize &&
"Wrong length of data");
512 std::copy(CompleteData.
data(), CompleteData.
data() + TxtDataSize,
513 Data.begin() + TxtDataOffset);
515 auto &Cache = SectionDataCache[Sec.
d.
a];
516 Cache = std::move(
Data);
517 return ArrayRef<uint8_t>(Cache);
520uint64_t GOFFObjectFile::getSectionAlignment(
DataRefImpl Sec)
const {
521 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
524 return 1ULL <<
static_cast<uint64_t
>(Pow2Alignment);
527bool GOFFObjectFile::isSectionText(
DataRefImpl Sec)
const {
528 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
534bool GOFFObjectFile::isSectionData(
DataRefImpl Sec)
const {
535 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
542 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
549 if (!isSectionData(Sec))
552 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
566 moveSectionNext(Sec);
576 for (
uint32_t I = Symb.
d.
a + 1, E = EsdPtrs.size();
I < E; ++
I) {
577 if (
const uint8_t *EsdRecord = EsdPtrs[
I]) {
581 bool IgnoreSpecialGOFFSymbols =
true;
584 IgnoreSpecialGOFFSymbols;
612 DataLength -= SliceLength;
613 Slice += SliceLength;
616 for (; DataLength > 0;
624 "continued bit should not be set");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
void reserve(size_type N)
pointer data()
Return a pointer to the vector's buffer, even if empty().
Represent a constant reference to a string, i.e.
static LLVM_ABI Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
static uint16_t getNameLength(const uint8_t *Record)
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 LLVM_ABI Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
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
static LLVM_ABI Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
static uint16_t getPropertyModuleLength(const uint8_t *Record)
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 bool isContinued(const uint8_t *Record)
static LLVM_ABI Error getContinuousData(const uint8_t *Record, uint16_t DataLength, int DataIndex, SmallString< 256 > &CompleteData)
static bool isContinuation(const uint8_t *Record)
static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId)
static void getDataLength(const uint8_t *Record, uint16_t &Length)
static LLVM_ABI Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
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.
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.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d