LLVM 24.0.0git
GOFFObjectFile.cpp
Go to the documentation of this file.
1//===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implementation of the GOFFObjectFile class.
10//
11//===----------------------------------------------------------------------===//
12
15#include "llvm/Object/GOFF.h"
17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Errc.h"
20
21#ifndef DEBUG_TYPE
22#define DEBUG_TYPE "goff"
23#endif
24
25using namespace llvm::object;
26using namespace llvm;
27
28// Return the type of the record.
29static GOFF::RecordType getRecordType(const uint8_t *PhysicalRecord) {
30 return GOFF::RecordType((PhysicalRecord[1] & 0xF0) >> 4);
31}
32
33// Return true if the record is a continuation record.
34static bool isContinuation(const uint8_t *PhysicalRecord) {
35 return PhysicalRecord[1] & 0x02;
36}
37
38// Return true if the record has a continuation.
39static bool isContinued(const uint8_t *PhysicalRecord) {
40 return PhysicalRecord[1] & 0x01;
41}
42
43// Helper function to get continuous data from a logical record
44// Includes PTV header + everything from first record + continuation payloads
45// Returns the number of physical records consumed (including the initial
46// record)
48GOFFObjectFile::getContinuousData(SmallVectorImpl<uint8_t> &CompleteData,
49 int DataIndex, uint16_t DataLength,
50 const uint8_t *Record) const {
51
52 CompleteData.reserve(DataLength + GOFF::RecordLength - DataIndex);
53
54 // First record - include PTV header (bytes 0-2)
55 CompleteData.append(Record, Record + GOFF::RecordPrefixLength);
56 // Append everything from the first record before the start of the data.
57 CompleteData.append(Record + GOFF::RecordPrefixLength, Record + DataIndex);
58 // Append the data.
59 const uint8_t *Ptr = Record + DataIndex;
60 size_t SliceLength = std::min(
61 DataLength, static_cast<uint16_t>(GOFF::RecordLength - DataIndex));
62 CompleteData.append(Ptr, Ptr + SliceLength);
63 DataLength -= SliceLength;
64 Ptr += SliceLength;
65
66 unsigned BlocksConsumed = 1; // Count the initial record
67 // Continuation records.
68 while (DataLength > 0) {
69 // Ptr now points to the start of the next physical record.
70 // Check that this block is a Continuation.
71 assert(isContinuation(Ptr) && "Continuation bit must be set");
72 // Check that the last Continuation is terminated correctly.
73 if (DataLength <= GOFF::PayloadLength && isContinued(Ptr))
75 "continued bit should not be set");
76
77 SliceLength =
78 std::min(DataLength, static_cast<uint16_t>(GOFF::PayloadLength));
79 Ptr += GOFF::RecordPrefixLength; // Skip the 3-byte prefix
80 CompleteData.append(Ptr, Ptr + SliceLength);
81 DataLength -= SliceLength;
82 // Advance to the start of the next record
84 BlocksConsumed++;
85 }
86 return BlocksConsumed;
87}
88
89// Walk over the object file and populate FlattenedData.
90Error GOFFObjectFile::createFlattenedData() {
91 const uint8_t *It = base();
92 const uint8_t *End = base() + getData().size();
93
94 // First pass: validate continuation records.
95 const uint8_t *ValidateIt = It;
96 unsigned ValidateIndex = 0;
97 bool PrevContinued = false;
98 bool PrevWasContinuation = false;
99 GOFF::RecordType PrevRecordType = GOFF::RT_HDR;
100
101 while (ValidateIt < End) {
102 bool IsCont = isContinuation(ValidateIt);
103 bool IsContd = isContinued(ValidateIt);
104 GOFF::RecordType CurrentType = ::getRecordType(ValidateIt);
105
106 if (IsCont) {
107 // Continuation record must be preceded by a continued record.
108 if (!PrevContinued) {
110 "record " + std::to_string(ValidateIndex) +
111 " is a continuation record that is not "
112 "preceded by a continued record");
113 }
114 // Continuation record type must match previous record type.
115 if (CurrentType != PrevRecordType) {
116 return createStringError(
118 "record " + std::to_string(ValidateIndex) +
119 " is a continuation record that does not match "
120 "the type of the previous record");
121 }
122 // Update PrevContinued for continuation records.
123 PrevContinued = IsContd;
124 } else {
125 // Check if previous non-continuation was marked as continued.
126 if (PrevContinued && !PrevWasContinuation) {
128 "record " + std::to_string(ValidateIndex) +
129 " is not a continuation record but the "
130 "preceding record is continued");
131 }
132 PrevRecordType = CurrentType;
133 PrevContinued = IsContd;
134 }
135
136 PrevWasContinuation = IsCont;
137 ValidateIt += GOFF::RecordLength;
138 ValidateIndex++;
139 }
140
141 // Second pass: process records now that we know they're valid.
142 while (It < End) {
143 // Skip continuation records - only process first physical record of each
144 // logical record.
145 if (isContinuation(It)) {
146 It += GOFF::RecordLength;
147 continue;
148 }
149
151
152 // Call get continuous data based on record type.
153 int DataIndex = 0;
154 uint16_t DataLength = 0;
155 ArrayRef<uint8_t> Slice(It, GOFF::RecordLength);
156 DataExtractor DE(Slice, false);
157
158 switch (RecordType) {
159 case GOFF::RT_ESD: {
160 DataIndex = 72;
161 uint64_t Offset = 70;
162 DataLength = DE.getU16(&Offset);
163 break;
164 }
165 case GOFF::RT_TXT: {
166 DataIndex = 24;
167 uint64_t Offset = 22;
168 DataLength = DE.getU16(&Offset);
169 break;
170 }
171 case GOFF::RT_RLD: {
172 DataIndex = 6;
173 uint64_t Offset = 4;
174 DataLength = DE.getU16(&Offset);
175 break;
176 }
177 case GOFF::RT_LEN: {
178 DataIndex = 8;
179 uint64_t Offset = 6;
180 DataLength = DE.getU16(&Offset);
181 break;
182 }
183 case GOFF::RT_END: {
184 DataIndex = 26;
185 uint64_t Offset = 24;
186 DataLength = DE.getU16(&Offset);
187 break;
188 }
189 case GOFF::RT_HDR: {
190 DataIndex = 60;
191 uint64_t Offset = 52;
192 DataLength = DE.getU16(&Offset);
193 break;
194 }
195 }
196 // Get the flattened data for this logical record (including continuations).
197 SmallVector<uint8_t> CompleteData;
198 Expected<unsigned> BlocksConsumed =
199 getContinuousData(CompleteData, DataIndex, DataLength, It);
200 if (!BlocksConsumed) {
201 // Log the error but don't fail construction - errors in continuation
202 // data will be caught when the data is actually accessed.
204 BlocksConsumed.takeError(), [](const llvm::ErrorInfoBase &EIB) {
205 llvm::errs() << "ERROR: " << EIB.message() << "\n";
206 });
207 // Skip this record and continue.
208 It += GOFF::RecordLength;
209 continue;
210 }
211 FlattenedData.push_back({RecordType, std::move(CompleteData)});
212
213 // Move to next logical record using the number of blocks consumed.
214 It += (*BlocksConsumed) * GOFF::RecordLength;
215 }
216 return Error::success();
217}
218
219Expected<std::unique_ptr<ObjectFile>>
221 Error Err = Error::success();
222 std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
223 if (Err)
224 return std::move(Err);
225 return std::move(Ret);
226}
227
229 : ObjectFile(Binary::ID_GOFF, Object) {
230 ErrorAsOutParameter ErrAsOutParam(Err);
231 // Object file isn't the right size, bail out early.
232 if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
233 Err = createStringError(
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");
238 return;
239 }
240 // Object file doesn't start/end with HDR/END records.
241 // Bail out early.
242 if (Object.getBufferSize() != 0) {
243 if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
245 "object file must start with HDR record");
246 return;
247 }
248 if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
249 GOFF::RT_END) {
251 "object file must end with END record");
252 return;
253 }
254 }
255
256 if (Error E = createFlattenedData()) {
257 Err = std::move(E);
258 return;
259 }
260
261 SectionEntryImpl DummySection;
262 SectionList.emplace_back(DummySection); // Dummy entry at index 0.
263
264 for (const auto &[RecordType, Data] : FlattenedData) {
265 const uint8_t *I = Data.data();
266 switch (RecordType) {
267 case GOFF::RT_ESD: {
268 // Save ESD record.
269 uint32_t EsdId;
270 ESDRecord::getEsdId(I, EsdId);
271 EsdPtrs.grow(EsdId);
272 EsdPtrs[EsdId] = I;
273
274 // Determine and save the "sections" in GOFF.
275 // A section is saved as a tuple of the form
276 // case (1): (ED,child PR)
277 // - where the PR must have non-zero length.
278 // case (2a) (ED,0)
279 // - where the ED is of non-zero length.
280 // case (2b) (ED,0)
281 // - where the ED is zero length but
282 // contains a label (LD).
285 SectionEntryImpl Section;
289 // case (2a)
290 if (Length != 0) {
291 Section.d.a = EsdId;
292 SectionList.emplace_back(Section);
293 }
295 // case (1)
296 if (Length != 0) {
297 uint32_t SymEdId;
299 Section.d.a = SymEdId;
300 Section.d.b = EsdId;
301 SectionList.emplace_back(Section);
302 }
304 // case (2b)
305 uint32_t SymEdId;
307 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
308 uint32_t EdLength;
309 ESDRecord::getLength(SymEdRecord, EdLength);
310 if (!EdLength) { // [ EDID, PRID ]
311 // LD child of a zero length parent ED.
312 // Add the section ED which was previously ignored.
313 Section.d.a = SymEdId;
314 SectionList.emplace_back(Section);
315 }
316 }
317 LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n");
318 break;
319 }
320 case GOFF::RT_TXT:
321 // Save TXT records.
322 TextPtrs.emplace_back(I);
323 LLVM_DEBUG(dbgs() << " -- TXT\n");
324 break;
325 case GOFF::RT_RLD:
326 LLVM_DEBUG(dbgs() << " -- RLD (GOFF record type) unhandled\n");
327 break;
328 case GOFF::RT_LEN:
329 LLVM_DEBUG(dbgs() << " -- LEN (GOFF record type) unhandled\n");
330 break;
331 case GOFF::RT_END:
332 LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
333 break;
334 case GOFF::RT_HDR:
335 LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n");
336 break;
337 }
338 }
339}
340
341const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
342 const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
343 return EsdRecord;
344}
345
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);
350 }
351
352 // Get the ESD record pointer from EsdPtrs (points to FlattenedData)
353 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
354 // Extract name from the flattened ESD record
355 // Name length is at byte 70-71, name data starts at byte 72
356 uint16_t NameLength = ESDRecord::getNameLength(EsdRecord);
357 SmallString<256> SymbolName;
358 if (NameLength > 0) {
359 // Name starts at byte 72 in the record (already flattened, no
360 // continuations)
361 const uint8_t *NameStart = EsdRecord + 72;
362 SymbolName.append(NameStart, NameStart + NameLength);
363 }
364
365 SmallString<256> SymbolNameConverted;
366 ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
367
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);
374}
375
377 return getSymbolName(Symbol.getRawDataRefImpl());
378}
379
380Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
382 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
383 ESDRecord::getOffset(EsdRecord, Offset);
384 return static_cast<uint64_t>(Offset);
385}
386
387uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
389 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
390 ESDRecord::getOffset(EsdRecord, Offset);
391 return static_cast<uint64_t>(Offset);
392}
393
394uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
395 return 0;
396}
397
398bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
399 const uint8_t *Record = getSymbolEsdRecord(Symb);
402
404 return true;
406 uint32_t Length;
408 if (Length == 0)
409 return true;
410 }
411 return false;
412}
413
414bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
415 const uint8_t *Record = getSymbolEsdRecord(Symb);
416 bool Indirect;
417 ESDRecord::getIndirectReference(Record, Indirect);
418 return Indirect;
419}
420
421Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
422 uint32_t Flags = 0;
423 if (isSymbolUnresolved(Symb))
425
426 const uint8_t *Record = getSymbolEsdRecord(Symb);
427
428 GOFF::ESDBindingStrength BindingStrength;
429 ESDRecord::getBindingStrength(Record, BindingStrength);
430 if (BindingStrength == GOFF::ESD_BST_Weak)
432
433 GOFF::ESDBindingScope BindingScope;
434 ESDRecord::getBindingScope(Record, BindingScope);
435
438
441 BindingScope != GOFF::ESD_BSC_Section &&
442 BindingScope != GOFF::ESD_BSC_Module) {
443 Expected<StringRef> Name = getSymbolName(Symb);
444 if (Name && *Name != " ") { // Blank name is local.
446 if (BindingScope == GOFF::ESD_BSC_ImportExport)
448 else if (!(Flags & SymbolRef::SF_Undefined))
450 }
451 }
452
453 return Flags;
454}
455
456Expected<SymbolRef::Type>
457GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
458 const uint8_t *Record = getSymbolEsdRecord(Symb);
461 GOFF::ESDExecutable Executable;
462 ESDRecord::getExecutable(Record, Executable);
463
469 uint32_t EsdId;
470 ESDRecord::getEsdId(Record, EsdId);
472 "ESD record %" PRIu32
473 " has invalid symbol type 0x%02" PRIX8,
474 EsdId, SymbolType);
475 }
476 switch (SymbolType) {
479 return SymbolRef::ST_Other;
483 if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
484 Executable != GOFF::ESD_EXE_Unspecified) {
485 uint32_t EsdId;
486 ESDRecord::getEsdId(Record, EsdId);
488 "ESD record %" PRIu32
489 " has unknown Executable type 0x%02X",
490 EsdId, Executable);
491 }
492 switch (Executable) {
496 return SymbolRef::ST_Data;
499 }
500 llvm_unreachable("Unhandled ESDExecutable");
501 }
502 llvm_unreachable("Unhandled ESDSymbolType");
503}
504
505Expected<section_iterator>
506GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
507 DataRefImpl Sec;
508
509 if (isSymbolUnresolved(Symb))
510 return section_iterator(SectionRef(Sec, this));
511
512 const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
513 uint32_t SymEdId;
514 ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
515 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
516
517 for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
518 bool Found;
519 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
520 if (SectionPrRecord) {
521 Found = SymEsdRecord == SectionPrRecord;
522 } else {
523 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
524 Found = SymEdRecord == SectionEdRecord;
525 }
526
527 if (Found) {
528 Sec.d.a = I;
529 return section_iterator(SectionRef(Sec, this));
530 }
531 }
533 "symbol with ESD id " + std::to_string(Symb.d.a) +
534 " refers to invalid section with ESD id " +
535 std::to_string(SymEdId));
536}
537
539 const uint8_t *SymRecord = getSymbolEsdRecord(Symb);
540 uint32_t Attrs = 0;
541
542 // Bit 2 (0x4): 64-bit AMODE. If the child AMODE is unspecified,
543 // query the parent ED.
544 // TODO: The parent-walk path (child ESD_AMODE_None with a parent that has
545 // ESD_AMODE_64) cannot currently be tested as GOFFObjectWriter always emits
546 // ESD_AMODE_64 directly on LD/ER records and does not set AMODE on ED
547 // records. Full coverage requires yaml2obj GOFF ESD record support.
548 GOFF::ESDAmode Amode;
549 ESDRecord::getAmode(SymRecord, Amode);
550 if (Amode == GOFF::ESD_AMODE_None) {
551 uint32_t ParentEsdId;
552 ESDRecord::getParentEsdId(SymRecord, ParentEsdId);
553 if (ParentEsdId) {
554 const uint8_t *EdRecord = EsdPtrs[ParentEsdId];
555 ESDRecord::getAmode(EdRecord, Amode);
556 }
557 }
558 if (Amode == GOFF::ESD_AMODE_64)
559 Attrs |= 0x4;
560
561 // Bit 1 (0x2): XPLink — LinkageType is ESD_LT_XPLink.
562 GOFF::ESDLinkageType LinkageType;
563 ESDRecord::getLinkageType(SymRecord, LinkageType);
564 if (LinkageType == GOFF::ESD_LT_XPLink)
565 Attrs |= 0x2;
566
567 // Bit 0 (0x1): Writable Static Area.
568 GOFF::ESDNameSpaceId NameSpace;
569 ESDRecord::getNameSpaceId(SymRecord, NameSpace);
570 if (NameSpace == GOFF::ESD_NS_Parts)
571 Attrs |= 0x1;
572
573 return Attrs;
574}
575
576uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
577 const uint8_t *Record = getSymbolEsdRecord(Symb);
580 return Length;
581}
582
583const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
584 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
585 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
586 return EsdRecord;
587}
588
589const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
590 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
591 const uint8_t *EsdRecord = nullptr;
592 if (EsdIds.d.b)
593 EsdRecord = EsdPtrs[EsdIds.d.b];
594 return EsdRecord;
595}
596
597const uint8_t *
598GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
599 DataRefImpl Sec;
600 Sec.d.a = SectionIndex;
601 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
602 return EsdRecord;
603}
604
605const uint8_t *
606GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
607 DataRefImpl Sec;
608 Sec.d.a = SectionIndex;
609 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
610 return EsdRecord;
611}
612
613uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
614 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
615 uint32_t Length;
616 ESDRecord::getLength(EsdRecord, Length);
617 if (Length == 0) {
618 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
619 if (PrEsdRecord)
620 EsdRecord = PrEsdRecord;
621 }
622
623 uint32_t DefEsdId;
624 ESDRecord::getEsdId(EsdRecord, DefEsdId);
625 LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
626 return DefEsdId;
627}
628
629void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
630 Sec.d.a++;
631 if ((Sec.d.a) >= SectionList.size())
632 Sec.d.a = 0;
633}
634
635Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
636 DataRefImpl EdSym;
637 SectionEntryImpl EsdIds = SectionList[Sec.d.a];
638 EdSym.d.a = EsdIds.d.a;
639 Expected<StringRef> Name = getSymbolName(EdSym);
640 if (Name) {
641 StringRef Res = *Name;
642 LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
643 LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
644 Name = Res;
645 }
646 return Name;
647}
648
649uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
650 uint32_t Offset;
651 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
652 ESDRecord::getOffset(EsdRecord, Offset);
653 return Offset;
654}
655
656uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
657 uint32_t Length;
658 uint32_t DefEsdId = getSectionDefEsdId(Sec);
659 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
660 ESDRecord::getLength(EsdRecord, Length);
661 LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
662 return static_cast<uint64_t>(Length);
663}
664
665// Unravel TXT records and expand fill characters to produce
666// a contiguous sequence of bytes.
667Expected<ArrayRef<uint8_t>>
668GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
669 if (auto It = SectionDataCache.find(Sec.d.a); It != SectionDataCache.end()) {
670 auto &Buf = It->second;
671 return ArrayRef<uint8_t>(Buf);
672 }
673 uint64_t SectionSize = getSectionSize(Sec);
674 uint32_t DefEsdId = getSectionDefEsdId(Sec);
675
676 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
677 bool FillBytePresent;
678 ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
679 uint8_t FillByte = '\0';
680 if (FillBytePresent)
681 ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
682
683 // Initialize section with fill byte.
684 SmallVector<uint8_t> Data(SectionSize, FillByte);
685
686 // Replace section with content from text records.
687 for (const uint8_t *TxtRecordPtr : TextPtrs) {
688 uint32_t TxtEsdId;
689 TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
690 LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
691
692 if (TxtEsdId != DefEsdId)
693 continue;
694
695 uint32_t TxtDataOffset;
696 TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
697
698 uint16_t TxtDataSize;
699 TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
700
701 LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
702 << TxtDataSize << "\n");
703
704 // Text data starts at byte 24 in the flattened record (already processed
705 // continuations)
706 const uint8_t *TxtData = TxtRecordPtr + 24;
707 assert(TxtDataSize <= Data.size() - TxtDataOffset &&
708 "Text data exceeds section size");
709 std::copy(TxtData, TxtData + TxtDataSize, Data.begin() + TxtDataOffset);
710 }
711 auto &Cache = SectionDataCache[Sec.d.a];
712 Cache = std::move(Data);
713 return ArrayRef<uint8_t>(Cache);
714}
715
716uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
717 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
718 GOFF::ESDAlignment Pow2Alignment;
719 ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
720 return 1ULL << static_cast<uint64_t>(Pow2Alignment);
721}
722
723bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
724 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
725 GOFF::ESDExecutable Executable;
726 ESDRecord::getExecutable(EsdRecord, Executable);
727 return Executable == GOFF::ESD_EXE_CODE;
728}
729
730bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
731 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
732 GOFF::ESDExecutable Executable;
733 ESDRecord::getExecutable(EsdRecord, Executable);
734 return Executable == GOFF::ESD_EXE_DATA;
735}
736
738 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
739 GOFF::ESDLoadingBehavior LoadingBehavior;
740 ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
741 return LoadingBehavior == GOFF::ESD_LB_NoLoad;
742}
743
745 if (!isSectionData(Sec))
746 return false;
747
748 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
749 GOFF::ESDLoadingBehavior LoadingBehavior;
750 ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
751 return LoadingBehavior == GOFF::ESD_LB_Initial;
752}
753
755 // GOFF uses fill characters and fill characters are applied
756 // on getSectionContents() - so we say false to zero init.
757 return false;
758}
759
761 DataRefImpl Sec;
762 moveSectionNext(Sec);
763 return section_iterator(SectionRef(Sec, this));
764}
765
770
772 for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
773 if (const uint8_t *EsdRecord = EsdPtrs[I]) {
776 // Skip EDs - i.e. section symbols.
777 bool IgnoreSpecialGOFFSymbols = true;
778 bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
780 IgnoreSpecialGOFFSymbols;
781 if (!SkipSymbol) {
782 Symb.d.a = I;
783 return;
784 }
785 }
786 }
787 Symb.d.a = 0;
788}
789
795
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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)
#define I(x, y, z)
Definition MD5.cpp:57
FunctionLoweringInfo::StatepointRelocationRecord RecordType
#define LLVM_DEBUG(...)
Definition Debug.h:119
Helper for Errors used as out-parameters.
Definition Error.h:1160
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
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.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
MemoryBufferRef Data
Definition Binary.h:38
StringRef getData() const
Definition Binary.cpp:39
static void getIndirectReference(const uint8_t *Record, bool &Indirect)
Definition GOFF.h:259
static void getBindingStrength(const uint8_t *Record, GOFF::ESDBindingStrength &Strength)
Definition GOFF.h:245
static void getOffset(const uint8_t *Record, uint32_t &Offset)
Definition GOFF.h:143
static void getEsdId(const uint8_t *Record, uint32_t &EsdId)
Definition GOFF.h:135
static void getLoadingBehavior(const uint8_t *Record, GOFF::ESDLoadingBehavior &Behavior)
Definition GOFF.h:252
static void getFillBytePresent(const uint8_t *Record, bool &Present)
Definition GOFF.h:157
static void getLength(const uint8_t *Record, uint32_t &Length)
Definition GOFF.h:147
static void getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode)
Definition GOFF.h:193
static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId)
Definition GOFF.h:139
static void getFillByteValue(const uint8_t *Record, uint8_t &Fill)
Definition GOFF.h:181
static void getSymbolType(const uint8_t *Record, GOFF::ESDSymbolType &SymbolType)
Definition GOFF.h:128
static void getAlignment(const uint8_t *Record, GOFF::ESDAlignment &Alignment)
Definition GOFF.h:279
static void getLinkageType(const uint8_t *Record, GOFF::ESDLinkageType &Type)
Definition GOFF.h:272
static uint16_t getNameLength(const uint8_t *Record)
Definition GOFF.h:286
static void getExecutable(const uint8_t *Record, GOFF::ESDExecutable &Executable)
Definition GOFF.h:231
static void getBindingScope(const uint8_t *Record, GOFF::ESDBindingScope &Scope)
Definition GOFF.h:265
static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id)
Definition GOFF.h:151
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
const uint8_t * base() const
Definition ObjectFile.h:237
static Expected< std::unique_ptr< ObjectFile > > createGOFFObjectFile(MemoryBufferRef Object)
ObjectFile(unsigned int Type, MemoryBufferRef Source)
Represents a GOFF physical record.
Definition GOFF.h:31
static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId)
Definition GOFF.h:85
static void getDataLength(const uint8_t *Record, uint16_t &Length)
Definition GOFF.h:93
static void getOffset(const uint8_t *Record, uint32_t &Offset)
Definition GOFF.h:89
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SectionSize
Definition COFF.h:61
LLVM_ABI void convertToUTF8(StringRef Source, SmallVectorImpl< char > &Result)
ESDLoadingBehavior
Definition GOFF.h:127
@ ESD_LB_NoLoad
Definition GOFF.h:130
@ ESD_LB_Initial
Definition GOFF.h:128
RecordType
Definition GOFF.h:44
@ RT_RLD
Definition GOFF.h:47
@ RT_TXT
Definition GOFF.h:46
@ RT_ESD
Definition GOFF.h:45
@ RT_LEN
Definition GOFF.h:48
@ RT_HDR
Definition GOFF.h:50
@ RT_END
Definition GOFF.h:49
constexpr uint8_t RecordPrefixLength
Definition GOFF.h:29
constexpr uint8_t PayloadLength
Definition GOFF.h:30
ESDExecutable
Definition GOFF.h:109
@ ESD_EXE_Unspecified
Definition GOFF.h:110
@ ESD_EXE_CODE
Definition GOFF.h:112
@ ESD_EXE_DATA
Definition GOFF.h:111
ESDAlignment
Definition GOFF.h:144
@ ESD_AMODE_None
Definition GOFF.h:76
@ ESD_AMODE_64
Definition GOFF.h:80
ESDBindingScope
Definition GOFF.h:134
@ ESD_BSC_Module
Definition GOFF.h:137
@ ESD_BSC_ImportExport
Definition GOFF.h:139
@ ESD_BSC_Section
Definition GOFF.h:136
ESDLinkageType
Definition GOFF.h:142
@ ESD_LT_XPLink
Definition GOFF.h:142
constexpr uint8_t RecordLength
Length of the parts of a physical GOFF record.
Definition GOFF.h:28
ESDNameSpaceId
Definition GOFF.h:61
@ ESD_NS_Parts
Definition GOFF.h:65
ESDSymbolType
Definition GOFF.h:53
@ ESD_ST_PartReference
Definition GOFF.h:57
@ ESD_ST_ElementDefinition
Definition GOFF.h:55
@ ESD_ST_LabelDefinition
Definition GOFF.h:56
@ ESD_ST_SectionDefinition
Definition GOFF.h:54
@ ESD_ST_ExternalReference
Definition GOFF.h:58
ESDBindingStrength
Definition GOFF.h:122
@ ESD_BST_Weak
Definition GOFF.h:124
content_iterator< SectionRef > section_iterator
Definition ObjectFile.h:49
content_iterator< BasicSymbolRef > basic_symbol_iterator
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Length
Definition DWP.cpp:577
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ invalid_argument
Definition Errc.h:56
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d