LLVM: lib/Object/GOFFObjectFile.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
19
20#ifndef DEBUG_TYPE
21#define DEBUG_TYPE "goff"
22#endif
23
25using namespace llvm;
26
30 std::unique_ptr Ret(new GOFFObjectFile(Object, Err));
31 if (Err)
32 return std::move(Err);
33 return std::move(Ret);
34}
35
39
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");
46 return;
47 }
48
49
50 if (Object.getBufferSize() != 0) {
53 "object file must start with HDR record");
54 return;
55 }
59 "object file must end with END record");
60 return;
61 }
62 }
63
64 SectionEntryImpl DummySection;
65 SectionList.emplace_back(DummySection);
66
67 uint8_t PrevRecordType = 0;
68 uint8_t PrevContinuationBits = 0;
69 const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
72 bool IsContinuation = I[1] & 0x02;
73 bool PrevWasContinued = PrevContinuationBits & 0x01;
75
76
77
78 if (PrevWasContinued && !IsContinuation) {
81 "record " + std::to_string(RecordNum) +
82 " is not a continuation record but the "
83 "preceding record is continued");
84 return;
85 }
86 }
87
88 if (IsContinuation) {
91 "record " + std::to_string(RecordNum) +
92 " is a continuation record that does not "
93 "match the type of the previous record");
94 return;
95 }
96 if (!PrevWasContinued) {
98 "record " + std::to_string(RecordNum) +
99 " is a continuation record that is not "
100 "preceded by a continued record");
101 return;
102 }
104 PrevContinuationBits = I[1] & 0x03;
105 continue;
106 }
109 if (J % 8 == 0)
110 dbgs() << " ";
112 });
113
116
119 EsdPtrs.grow(EsdId);
120 EsdPtrs[EsdId] = I;
121
122
123
124
125
126
127
128
129
130
133 SectionEntryImpl Section;
137
139 Section.d.a = EsdId;
140 SectionList.emplace_back(Section);
141 }
143
147 Section.d.a = SymEdId;
148 Section.d.b = EsdId;
149 SectionList.emplace_back(Section);
150 }
152
155 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
158 if (!EdLength) {
159
160
161 Section.d.a = SymEdId;
162 SectionList.emplace_back(Section);
163 }
164 }
166 break;
167 }
169
170 TextPtrs.emplace_back(I);
172 break;
174 LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
175 break;
177 LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n");
178 break;
179 default:
181 }
183 PrevContinuationBits = I[1] & 0x03;
184 }
185}
186
187const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
188 const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
189 return EsdRecord;
190}
191
193 if (auto It = EsdNamesCache.find(Symb.d.a); It != EsdNamesCache.end()) {
194 auto &StrPtr = It->second;
195 return StringRef(StrPtr.second.get(), StrPtr.first);
196 }
197
199 if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
200 return std::move(Err);
201
204
205 size_t Size = SymbolNameConverted.size();
206 auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));
207 char *Buf = StrPtr.second.get();
208 memcpy(Buf, SymbolNameConverted.data(), Size);
209 EsdNamesCache[Symb.d.a] = std::move(StrPtr);
211}
212
216
219 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
222}
223
226 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
229}
230
231uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
232 return 0;
233}
234
235bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
236 const uint8_t *Record = getSymbolEsdRecord(Symb);
239
241 return true;
246 return true;
247 }
248 return false;
249}
250
251bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
252 const uint8_t *Record = getSymbolEsdRecord(Symb);
256}
257
258Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
259 uint32_t Flags = 0;
260 if (isSymbolUnresolved(Symb))
262
263 const uint8_t *Record = getSymbolEsdRecord(Symb);
264
269
272
275 if (Name && *Name != " ") {
281 }
282 }
283
285}
286
287ExpectedSymbolRef::Type
288GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
289 const uint8_t *Record = getSymbolEsdRecord(Symb);
294
300 uint32_t EsdId;
303 "ESD record %" PRIu32
304 " has invalid symbol type 0x%02" PRIX8,
306 }
316 uint32_t EsdId;
319 "ESD record %" PRIu32
320 " has unknown Executable type 0x%02X",
321 EsdId, Executable);
322 }
323 switch (Executable) {
330 }
332 }
334}
335
336Expected<section_iterator>
337GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
338 DataRefImpl Sec;
339
340 if (isSymbolUnresolved(Symb))
342
343 const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
344 uint32_t SymEdId;
346 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
347
348 for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
349 bool Found;
350 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
351 if (SectionPrRecord) {
352 Found = SymEsdRecord == SectionPrRecord;
353 } else {
354 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
355 Found = SymEdRecord == SectionEdRecord;
356 }
357
358 if (Found) {
361 }
362 }
364 "symbol with ESD id " + std::to_string(Symb.d.a) +
365 " refers to invalid section with ESD id " +
366 std::to_string(SymEdId));
367}
368
369uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
370 const uint8_t *Record = getSymbolEsdRecord(Symb);
374}
375
376const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
377 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
378 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
379 return EsdRecord;
380}
381
382const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
383 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
384 const uint8_t *EsdRecord = nullptr;
385 if (EsdIds.d.b)
386 EsdRecord = EsdPtrs[EsdIds.d.b];
387 return EsdRecord;
388}
389
390const uint8_t *
391GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
392 DataRefImpl Sec;
394 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
395 return EsdRecord;
396}
397
398const uint8_t *
399GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
400 DataRefImpl Sec;
402 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
403 return EsdRecord;
404}
405
406uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
407 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
411 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
412 if (PrEsdRecord)
413 EsdRecord = PrEsdRecord;
414 }
415
416 uint32_t DefEsdId;
418 LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
419 return DefEsdId;
420}
421
422void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
424 if ((Sec.d.a) >= SectionList.size())
426}
427
428Expected GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
429 DataRefImpl EdSym;
430 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
433 if (Name) {
434 StringRef Res = *Name;
435 LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
436 LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
438 }
440}
441
442uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
444 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
447}
448
449uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
451 uint32_t DefEsdId = getSectionDefEsdId(Sec);
452 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
455 return static_cast<uint64_t>(Length);
456}
457
458
459
460Expected<ArrayRef<uint8_t>>
461GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
462 if (auto It = SectionDataCache.find(Sec.d.a); It != SectionDataCache.end()) {
463 auto &Buf = It->second;
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;
472 uint8_t FillByte = '\0';
473 if (FillBytePresent)
475
476
477 SmallVector<uint8_t> Data(SectionSize, FillByte);
478
479
480 for (const uint8_t *TxtRecordInt : TextPtrs) {
481 const uint8_t *TxtRecordPtr = TxtRecordInt;
482 uint32_t TxtEsdId;
484 LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
485
486 if (TxtEsdId != DefEsdId)
487 continue;
488
489 uint32_t TxtDataOffset;
491
492 uint16_t TxtDataSize;
494
495 LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
496 << TxtDataSize << "\n");
497
498 SmallString<256> CompleteData;
499 CompleteData.reserve(TxtDataSize);
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 auto &Cache = SectionDataCache[Sec.d.a];
507 Cache = Data;
508 return ArrayRef<uint8_t>(Cache);
509}
510
511uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
512 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
515 return 1ULL << static_cast<uint64_t>(Pow2Alignment);
516}
517
518bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
519 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
523}
524
525bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
526 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
530}
531
533 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
537}
538
540 if (!isSectionData(Sec))
541 return false;
542
543 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
547}
548
550
551
552 return false;
553}
554
557 moveSectionNext(Sec);
559}
560
565
567 for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
568 if (const uint8_t *EsdRecord = EsdPtrs[I]) {
571
572 bool IgnoreSpecialGOFFSymbols = true;
575 IgnoreSpecialGOFFSymbols;
576 if (!SkipSymbol) {
578 return;
579 }
580 }
581 }
583}
584
590
595
598
600 size_t SliceLength =
603 DataLength -= SliceLength;
604 Slice += SliceLength;
605
606
607 for (; DataLength > 0;
609
610
612
615 "continued bit should not be set");
616
620 }
622}
623
629
635
642
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().
StringRef - Represent a constant reference to a string, i.e.
static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
Definition GOFFObjectFile.cpp:643
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 Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
Definition GOFFObjectFile.cpp:630
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
Definition GOFFObjectFile.cpp:555
basic_symbol_iterator symbol_end() const override
Definition GOFFObjectFile.cpp:591
GOFFObjectFile(MemoryBufferRef Object, Error &Err)
Definition GOFFObjectFile.cpp:36
bool isSectionReadOnlyData(DataRefImpl Sec) const
Definition GOFFObjectFile.cpp:539
bool isSectionNoLoad(DataRefImpl Sec) const
Definition GOFFObjectFile.cpp:532
section_iterator section_end() const override
Definition GOFFObjectFile.cpp:561
Expected< StringRef > getSymbolName(SymbolRef Symbol) const
Definition GOFFObjectFile.cpp:213
void moveSymbolNext(DataRefImpl &Symb) const override
Definition GOFFObjectFile.cpp:566
basic_symbol_iterator symbol_begin() const override
Definition GOFFObjectFile.cpp:585
bool isSectionZeroInit(DataRefImpl Sec) const
Definition GOFFObjectFile.cpp:549
static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
Definition GOFFObjectFile.cpp:624
static uint16_t getPropertyModuleLength(const uint8_t *Record)
const uint8_t * base() const
static Expected< std::unique_ptr< ObjectFile > > createGOFFObjectFile(MemoryBufferRef Object)
Definition GOFFObjectFile.cpp:28
ObjectFile(unsigned int Type, MemoryBufferRef Source)
Represents a GOFF physical record.
static bool isContinued(const uint8_t *Record)
static Error getContinuousData(const uint8_t *Record, uint16_t DataLength, int DataIndex, SmallString< 256 > &CompleteData)
Definition GOFFObjectFile.cpp:596
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 Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)
Definition GOFFObjectFile.cpp:636
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.
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
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