Skip to content

Commit 50cc734

Browse files
author
Yusra Syeda
committed
add txt record to goff reader
1 parent 899855d commit 50cc734

File tree

4 files changed

+326
-14
lines changed

4 files changed

+326
-14
lines changed

llvm/include/llvm/Object/GOFF.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ class Record {
7373
}
7474
};
7575

76+
class TXTRecord : public Record {
77+
public:
78+
/// \brief Maximum length of data; any more must go in continuation.
79+
static const uint8_t TXTMaxDataLength = 56;
80+
81+
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
82+
83+
static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) {
84+
get<uint32_t>(Record, 4, EsdId);
85+
}
86+
87+
static void getOffset(const uint8_t *Record, uint32_t &Offset) {
88+
get<uint32_t>(Record, 12, Offset);
89+
}
90+
91+
static void getDataLength(const uint8_t *Record, uint16_t &Length) {
92+
get<uint16_t>(Record, 22, Length);
93+
}
94+
};
95+
7696
class HDRRecord : public Record {
7797
public:
7898
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);

llvm/include/llvm/Object/GOFFObjectFile.h

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ namespace llvm {
2929
namespace object {
3030

3131
class GOFFObjectFile : public ObjectFile {
32+
friend class GOFFSymbolRef;
33+
3234
IndexedMap<const uint8_t *> EsdPtrs; // Indexed by EsdId.
35+
SmallVector<const uint8_t *, 256> TextPtrs;
3336

3437
mutable DenseMap<uint32_t, std::pair<size_t, std::unique_ptr<char[]>>>
3538
EsdNamesCache;
@@ -38,7 +41,7 @@ class GOFFObjectFile : public ObjectFile {
3841
// (EDID, 0) code, r/o data section
3942
// (EDID,PRID) r/w data section
4043
SmallVector<SectionEntryImpl, 256> SectionList;
41-
mutable DenseMap<uint32_t, std::string> SectionDataCache;
44+
mutable DenseMap<uint32_t, SmallVector<uint8_t>> SectionDataCache;
4245

4346
public:
4447
Expected<StringRef> getSymbolName(SymbolRef Symbol) const;
@@ -66,6 +69,10 @@ class GOFFObjectFile : public ObjectFile {
6669
return true;
6770
}
6871

72+
bool isSectionNoLoad(DataRefImpl Sec) const;
73+
bool isSectionReadOnlyData(DataRefImpl Sec) const;
74+
bool isSectionZeroInit(DataRefImpl Sec) const;
75+
6976
private:
7077
// SymbolRef.
7178
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
@@ -75,27 +82,24 @@ class GOFFObjectFile : public ObjectFile {
7582
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
7683
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
7784
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
85+
uint64_t getSymbolSize(DataRefImpl Symb) const;
7886

7987
const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const;
8088
bool isSymbolUnresolved(DataRefImpl Symb) const;
8189
bool isSymbolIndirect(DataRefImpl Symb) const;
8290

8391
// SectionRef.
84-
void moveSectionNext(DataRefImpl &Sec) const override {}
85-
virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const override {
86-
return StringRef();
87-
}
88-
uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; }
89-
uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; }
92+
void moveSectionNext(DataRefImpl &Sec) const override;
93+
virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
94+
uint64_t getSectionAddress(DataRefImpl Sec) const override;
95+
uint64_t getSectionSize(DataRefImpl Sec) const override;
9096
virtual Expected<ArrayRef<uint8_t>>
91-
getSectionContents(DataRefImpl Sec) const override {
92-
return ArrayRef<uint8_t>();
93-
}
94-
uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; }
95-
uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; }
97+
getSectionContents(DataRefImpl Sec) const override;
98+
uint64_t getSectionIndex(DataRefImpl Sec) const override { return Sec.d.a; }
99+
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
96100
bool isSectionCompressed(DataRefImpl Sec) const override { return false; }
97-
bool isSectionText(DataRefImpl Sec) const override { return false; }
98-
bool isSectionData(DataRefImpl Sec) const override { return false; }
101+
bool isSectionText(DataRefImpl Sec) const override;
102+
bool isSectionData(DataRefImpl Sec) const override;
99103
bool isSectionBSS(DataRefImpl Sec) const override { return false; }
100104
bool isSectionVirtual(DataRefImpl Sec) const override { return false; }
101105
relocation_iterator section_rel_begin(DataRefImpl Sec) const override {
@@ -109,6 +113,7 @@ class GOFFObjectFile : public ObjectFile {
109113
const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const;
110114
const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const;
111115
const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const;
116+
uint32_t getSectionDefEsdId(DataRefImpl &Sec) const;
112117

113118
// RelocationRef.
114119
void moveRelocationNext(DataRefImpl &Rel) const override {}
@@ -122,6 +127,29 @@ class GOFFObjectFile : public ObjectFile {
122127
SmallVectorImpl<char> &Result) const override {}
123128
};
124129

130+
class GOFFSymbolRef : public SymbolRef {
131+
public:
132+
GOFFSymbolRef(const SymbolRef &B) : SymbolRef(B) {
133+
assert(isa<GOFFObjectFile>(SymbolRef::getObject()));
134+
}
135+
136+
const GOFFObjectFile *getObject() const {
137+
return cast<GOFFObjectFile>(BasicSymbolRef::getObject());
138+
}
139+
140+
Expected<uint32_t> getSymbolGOFFFlags() const {
141+
return getObject()->getSymbolFlags(getRawDataRefImpl());
142+
}
143+
144+
Expected<SymbolRef::Type> getSymbolGOFFType() const {
145+
return getObject()->getSymbolType(getRawDataRefImpl());
146+
}
147+
148+
uint64_t getSize() const {
149+
return getObject()->getSymbolSize(getRawDataRefImpl());
150+
}
151+
};
152+
125153
} // namespace object
126154

127155
} // namespace llvm

llvm/lib/Object/GOFFObjectFile.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
165165
LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n");
166166
break;
167167
}
168+
case GOFF::RT_TXT:
169+
// Save TXT records.
170+
TextPtrs.emplace_back(I);
171+
LLVM_DEBUG(dbgs() << " -- TXT\n");
172+
break;
168173
case GOFF::RT_END:
169174
LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
170175
break;
@@ -361,6 +366,13 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
361366
std::to_string(SymEdId));
362367
}
363368

369+
uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
370+
const uint8_t *Record = getSymbolEsdRecord(Symb);
371+
uint32_t Length;
372+
ESDRecord::getLength(Record, Length);
373+
return Length;
374+
}
375+
364376
const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
365377
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
366378
const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
@@ -391,6 +403,154 @@ GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
391403
return EsdRecord;
392404
}
393405

406+
uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
407+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
408+
uint32_t Length;
409+
ESDRecord::getLength(EsdRecord, Length);
410+
if (Length == 0) {
411+
const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
412+
if (PrEsdRecord)
413+
EsdRecord = PrEsdRecord;
414+
}
415+
416+
uint32_t DefEsdId;
417+
ESDRecord::getEsdId(EsdRecord, DefEsdId);
418+
LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
419+
return DefEsdId;
420+
}
421+
422+
void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
423+
Sec.d.a++;
424+
if ((Sec.d.a) >= SectionList.size())
425+
Sec.d.a = 0;
426+
}
427+
428+
Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
429+
DataRefImpl EdSym;
430+
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
431+
EdSym.d.a = EsdIds.d.a;
432+
Expected<StringRef> Name = getSymbolName(EdSym);
433+
if (Name) {
434+
StringRef Res = *Name;
435+
LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
436+
LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
437+
Name = Res;
438+
}
439+
return Name;
440+
}
441+
442+
uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
443+
uint32_t Offset;
444+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
445+
ESDRecord::getOffset(EsdRecord, Offset);
446+
return Offset;
447+
}
448+
449+
uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
450+
uint32_t Length;
451+
uint32_t DefEsdId = getSectionDefEsdId(Sec);
452+
const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
453+
ESDRecord::getLength(EsdRecord, Length);
454+
LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
455+
return static_cast<uint64_t>(Length);
456+
}
457+
458+
// Unravel TXT records and expand fill characters to produce
459+
// a contiguous sequence of bytes.
460+
Expected<ArrayRef<uint8_t>>
461+
GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
462+
if (SectionDataCache.count(Sec.d.a)) {
463+
auto &Buf = SectionDataCache[Sec.d.a];
464+
return ArrayRef<uint8_t>(Buf);
465+
}
466+
uint64_t SectionSize = getSectionSize(Sec);
467+
uint32_t DefEsdId = getSectionDefEsdId(Sec);
468+
469+
const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
470+
bool FillBytePresent;
471+
ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
472+
uint8_t FillByte = '\0';
473+
if (FillBytePresent)
474+
ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
475+
476+
// Initialize section with fill byte.
477+
SmallVector<uint8_t> Data(SectionSize, FillByte);
478+
479+
// Replace section with content from text records.
480+
for (const uint8_t *TxtRecordInt : TextPtrs) {
481+
const uint8_t *TxtRecordPtr = TxtRecordInt;
482+
uint32_t TxtEsdId;
483+
TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
484+
LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
485+
486+
if (TxtEsdId != DefEsdId)
487+
continue;
488+
489+
uint32_t TxtDataOffset;
490+
TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
491+
492+
uint16_t TxtDataSize;
493+
TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
494+
495+
LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
496+
<< TxtDataSize << "\n");
497+
498+
SmallString<256> CompleteData;
499+
CompleteData.reserve(TxtDataSize);
500+
if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData))
501+
return std::move(Err);
502+
assert(CompleteData.size() == TxtDataSize && "Wrong length of data");
503+
std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,
504+
Data.begin() + TxtDataOffset);
505+
}
506+
SectionDataCache[Sec.d.a] = Data;
507+
return ArrayRef<uint8_t>(Data);
508+
}
509+
510+
uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
511+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
512+
GOFF::ESDAlignment Pow2Alignment;
513+
ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
514+
return 1 << static_cast<uint64_t>(Pow2Alignment);
515+
}
516+
517+
bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
518+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
519+
GOFF::ESDExecutable Executable;
520+
ESDRecord::getExecutable(EsdRecord, Executable);
521+
return Executable == GOFF::ESD_EXE_CODE;
522+
}
523+
524+
bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
525+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
526+
GOFF::ESDExecutable Executable;
527+
ESDRecord::getExecutable(EsdRecord, Executable);
528+
return Executable == GOFF::ESD_EXE_DATA;
529+
}
530+
531+
bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const {
532+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
533+
GOFF::ESDLoadingBehavior LoadingBehavior;
534+
ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
535+
return LoadingBehavior == GOFF::ESD_LB_NoLoad;
536+
}
537+
538+
bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
539+
if (!isSectionData(Sec))
540+
return false;
541+
542+
const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
543+
GOFF::ESDLoadingBehavior LoadingBehavior;
544+
ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
545+
return LoadingBehavior == GOFF::ESD_LB_Initial;
546+
}
547+
548+
bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
549+
// GOFF uses fill characters and fill characters are applied
550+
// on getSectionContents() - so we say false to zero init.
551+
return false;
552+
}
553+
394554
section_iterator GOFFObjectFile::section_begin() const {
395555
DataRefImpl Sec;
396556
moveSectionNext(Sec);
@@ -473,6 +633,13 @@ Error ESDRecord::getData(const uint8_t *Record,
473633
return getContinuousData(Record, DataSize, 72, CompleteData);
474634
}
475635

636+
Error TXTRecord::getData(const uint8_t *Record,
637+
SmallString<256> &CompleteData) {
638+
uint16_t Length;
639+
getDataLength(Record, Length);
640+
return getContinuousData(Record, Length, 24, CompleteData);
641+
}
642+
476643
Error ENDRecord::getData(const uint8_t *Record,
477644
SmallString<256> &CompleteData) {
478645
uint16_t Length = getNameLength(Record);

0 commit comments

Comments
 (0)