xref: /freebsd/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
13 #include "llvm/Object/GOFFObjectFile.h"
14 #include "llvm/BinaryFormat/GOFF.h"
15 #include "llvm/Object/GOFF.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/Errc.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 #ifndef DEBUG_TYPE
21 #define DEBUG_TYPE "goff"
22 #endif
23 
24 using namespace llvm::object;
25 using namespace llvm;
26 
27 Expected<std::unique_ptr<ObjectFile>>
createGOFFObjectFile(MemoryBufferRef Object)28 ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
29   Error Err = Error::success();
30   std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
31   if (Err)
32     return std::move(Err);
33   return std::move(Ret);
34 }
35 
GOFFObjectFile(MemoryBufferRef Object,Error & Err)36 GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
37     : ObjectFile(Binary::ID_GOFF, Object) {
38   ErrorAsOutParameter ErrAsOutParam(&Err);
39   // Object file isn't the right size, bail out early.
40   if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
41     Err = createStringError(
42         object_error::unexpected_eof,
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   // Object file doesn't start/end with HDR/END records.
49   // Bail out early.
50   if (Object.getBufferSize() != 0) {
51     if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
52       Err = createStringError(object_error::parse_failed,
53                               "object file must start with HDR record");
54       return;
55     }
56     if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
57         GOFF::RT_END) {
58       Err = createStringError(object_error::parse_failed,
59                               "object file must end with END record");
60       return;
61     }
62   }
63 
64   SectionEntryImpl DummySection;
65   SectionList.emplace_back(DummySection); // Dummy entry at index 0.
66 
67   uint8_t PrevRecordType = 0;
68   uint8_t PrevContinuationBits = 0;
69   const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
70   for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
71     uint8_t RecordType = (I[1] & 0xF0) >> 4;
72     bool IsContinuation = I[1] & 0x02;
73     bool PrevWasContinued = PrevContinuationBits & 0x01;
74     size_t RecordNum = (I - base()) / GOFF::RecordLength;
75 
76     // If the previous record was continued, the current record should be a
77     // continuation.
78     if (PrevWasContinued && !IsContinuation) {
79       if (PrevRecordType == RecordType) {
80         Err = createStringError(object_error::parse_failed,
81                                 "record " + std::to_string(RecordNum) +
82                                     " is not a continuation record but the "
83                                     "preceding record is continued");
84         return;
85       }
86     }
87     // Don't parse continuations records, only parse initial record.
88     if (IsContinuation) {
89       if (RecordType != PrevRecordType) {
90         Err = createStringError(object_error::parse_failed,
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) {
97         Err = createStringError(object_error::parse_failed,
98                                 "record " + std::to_string(RecordNum) +
99                                     " is a continuation record that is not "
100                                     "preceded by a continued record");
101         return;
102       }
103       PrevRecordType = RecordType;
104       PrevContinuationBits = I[1] & 0x03;
105       continue;
106     }
107     LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) {
108       const uint8_t *P = I + J;
109       if (J % 8 == 0)
110         dbgs() << "  ";
111       dbgs() << format("%02hhX", *P);
112     });
113 
114     switch (RecordType) {
115     case GOFF::RT_ESD: {
116       // Save ESD record.
117       uint32_t EsdId;
118       ESDRecord::getEsdId(I, EsdId);
119       EsdPtrs.grow(EsdId);
120       EsdPtrs[EsdId] = I;
121 
122       // Determine and save the "sections" in GOFF.
123       // A section is saved as a tuple of the form
124       // case (1): (ED,child PR)
125       //    - where the PR must have non-zero length.
126       // case (2a) (ED,0)
127       //   - where the ED is of non-zero length.
128       // case (2b) (ED,0)
129       //   - where the ED is zero length but
130       //     contains a label (LD).
131       GOFF::ESDSymbolType SymbolType;
132       ESDRecord::getSymbolType(I, SymbolType);
133       SectionEntryImpl Section;
134       uint32_t Length;
135       ESDRecord::getLength(I, Length);
136       if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
137         // case (2a)
138         if (Length != 0) {
139           Section.d.a = EsdId;
140           SectionList.emplace_back(Section);
141         }
142       } else if (SymbolType == GOFF::ESD_ST_PartReference) {
143         // case (1)
144         if (Length != 0) {
145           uint32_t SymEdId;
146           ESDRecord::getParentEsdId(I, SymEdId);
147           Section.d.a = SymEdId;
148           Section.d.b = EsdId;
149           SectionList.emplace_back(Section);
150         }
151       } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
152         // case (2b)
153         uint32_t SymEdId;
154         ESDRecord::getParentEsdId(I, SymEdId);
155         const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
156         uint32_t EdLength;
157         ESDRecord::getLength(SymEdRecord, EdLength);
158         if (!EdLength) { // [ EDID, PRID ]
159           // LD child of a zero length parent ED.
160           // Add the section ED which was previously ignored.
161           Section.d.a = SymEdId;
162           SectionList.emplace_back(Section);
163         }
164       }
165       LLVM_DEBUG(dbgs() << "  --  ESD " << EsdId << "\n");
166       break;
167     }
168     case GOFF::RT_TXT:
169       // Save TXT records.
170       TextPtrs.emplace_back(I);
171       LLVM_DEBUG(dbgs() << "  --  TXT\n");
172       break;
173     case GOFF::RT_END:
174       LLVM_DEBUG(dbgs() << "  --  END (GOFF record type) unhandled\n");
175       break;
176     case GOFF::RT_HDR:
177       LLVM_DEBUG(dbgs() << "  --  HDR (GOFF record type) unhandled\n");
178       break;
179     default:
180       llvm_unreachable("Unknown record type");
181     }
182     PrevRecordType = RecordType;
183     PrevContinuationBits = I[1] & 0x03;
184   }
185 }
186 
getSymbolEsdRecord(DataRefImpl Symb) const187 const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
188   const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
189   return EsdRecord;
190 }
191 
getSymbolName(DataRefImpl Symb) const192 Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
193   if (EsdNamesCache.count(Symb.d.a)) {
194     auto &StrPtr = EsdNamesCache[Symb.d.a];
195     return StringRef(StrPtr.second.get(), StrPtr.first);
196   }
197 
198   SmallString<256> SymbolName;
199   if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
200     return std::move(Err);
201 
202   SmallString<256> SymbolNameConverted;
203   ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
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);
210   return StringRef(Buf, Size);
211 }
212 
getSymbolName(SymbolRef Symbol) const213 Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
214   return getSymbolName(Symbol.getRawDataRefImpl());
215 }
216 
getSymbolAddress(DataRefImpl Symb) const217 Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
218   uint32_t Offset;
219   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
220   ESDRecord::getOffset(EsdRecord, Offset);
221   return static_cast<uint64_t>(Offset);
222 }
223 
getSymbolValueImpl(DataRefImpl Symb) const224 uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
225   uint32_t Offset;
226   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
227   ESDRecord::getOffset(EsdRecord, Offset);
228   return static_cast<uint64_t>(Offset);
229 }
230 
getCommonSymbolSizeImpl(DataRefImpl Symb) const231 uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
232   return 0;
233 }
234 
isSymbolUnresolved(DataRefImpl Symb) const235 bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
236   const uint8_t *Record = getSymbolEsdRecord(Symb);
237   GOFF::ESDSymbolType SymbolType;
238   ESDRecord::getSymbolType(Record, SymbolType);
239 
240   if (SymbolType == GOFF::ESD_ST_ExternalReference)
241     return true;
242   if (SymbolType == GOFF::ESD_ST_PartReference) {
243     uint32_t Length;
244     ESDRecord::getLength(Record, Length);
245     if (Length == 0)
246       return true;
247   }
248   return false;
249 }
250 
isSymbolIndirect(DataRefImpl Symb) const251 bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
252   const uint8_t *Record = getSymbolEsdRecord(Symb);
253   bool Indirect;
254   ESDRecord::getIndirectReference(Record, Indirect);
255   return Indirect;
256 }
257 
getSymbolFlags(DataRefImpl Symb) const258 Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
259   uint32_t Flags = 0;
260   if (isSymbolUnresolved(Symb))
261     Flags |= SymbolRef::SF_Undefined;
262 
263   const uint8_t *Record = getSymbolEsdRecord(Symb);
264 
265   GOFF::ESDBindingStrength BindingStrength;
266   ESDRecord::getBindingStrength(Record, BindingStrength);
267   if (BindingStrength == GOFF::ESD_BST_Weak)
268     Flags |= SymbolRef::SF_Weak;
269 
270   GOFF::ESDBindingScope BindingScope;
271   ESDRecord::getBindingScope(Record, BindingScope);
272 
273   if (BindingScope != GOFF::ESD_BSC_Section) {
274     Expected<StringRef> Name = getSymbolName(Symb);
275     if (Name && *Name != " ") { // Blank name is local.
276       Flags |= SymbolRef::SF_Global;
277       if (BindingScope == GOFF::ESD_BSC_ImportExport)
278         Flags |= SymbolRef::SF_Exported;
279       else if (!(Flags & SymbolRef::SF_Undefined))
280         Flags |= SymbolRef::SF_Hidden;
281     }
282   }
283 
284   return Flags;
285 }
286 
287 Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const288 GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
289   const uint8_t *Record = getSymbolEsdRecord(Symb);
290   GOFF::ESDSymbolType SymbolType;
291   ESDRecord::getSymbolType(Record, SymbolType);
292   GOFF::ESDExecutable Executable;
293   ESDRecord::getExecutable(Record, Executable);
294 
295   if (SymbolType != GOFF::ESD_ST_SectionDefinition &&
296       SymbolType != GOFF::ESD_ST_ElementDefinition &&
297       SymbolType != GOFF::ESD_ST_LabelDefinition &&
298       SymbolType != GOFF::ESD_ST_PartReference &&
299       SymbolType != GOFF::ESD_ST_ExternalReference) {
300     uint32_t EsdId;
301     ESDRecord::getEsdId(Record, EsdId);
302     return createStringError(llvm::errc::invalid_argument,
303                              "ESD record %" PRIu32
304                              " has invalid symbol type 0x%02" PRIX8,
305                              EsdId, SymbolType);
306   }
307   switch (SymbolType) {
308   case GOFF::ESD_ST_SectionDefinition:
309   case GOFF::ESD_ST_ElementDefinition:
310     return SymbolRef::ST_Other;
311   case GOFF::ESD_ST_LabelDefinition:
312   case GOFF::ESD_ST_PartReference:
313   case GOFF::ESD_ST_ExternalReference:
314     if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
315         Executable != GOFF::ESD_EXE_Unspecified) {
316       uint32_t EsdId;
317       ESDRecord::getEsdId(Record, EsdId);
318       return createStringError(llvm::errc::invalid_argument,
319                                "ESD record %" PRIu32
320                                " has unknown Executable type 0x%02X",
321                                EsdId, Executable);
322     }
323     switch (Executable) {
324     case GOFF::ESD_EXE_CODE:
325       return SymbolRef::ST_Function;
326     case GOFF::ESD_EXE_DATA:
327       return SymbolRef::ST_Data;
328     case GOFF::ESD_EXE_Unspecified:
329       return SymbolRef::ST_Unknown;
330     }
331     llvm_unreachable("Unhandled ESDExecutable");
332   }
333   llvm_unreachable("Unhandled ESDSymbolType");
334 }
335 
336 Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const337 GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
338   DataRefImpl Sec;
339 
340   if (isSymbolUnresolved(Symb))
341     return section_iterator(SectionRef(Sec, this));
342 
343   const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
344   uint32_t SymEdId;
345   ESDRecord::getParentEsdId(SymEsdRecord, 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) {
359       Sec.d.a = I;
360       return section_iterator(SectionRef(Sec, this));
361     }
362   }
363   return createStringError(llvm::errc::invalid_argument,
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 
getSymbolSize(DataRefImpl Symb) const369 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 
getSectionEdEsdRecord(DataRefImpl & Sec) const376 const 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 
getSectionPrEsdRecord(DataRefImpl & Sec) const382 const 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 
390 const uint8_t *
getSectionEdEsdRecord(uint32_t SectionIndex) const391 GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
392   DataRefImpl Sec;
393   Sec.d.a = SectionIndex;
394   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
395   return EsdRecord;
396 }
397 
398 const uint8_t *
getSectionPrEsdRecord(uint32_t SectionIndex) const399 GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
400   DataRefImpl Sec;
401   Sec.d.a = SectionIndex;
402   const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
403   return EsdRecord;
404 }
405 
getSectionDefEsdId(DataRefImpl & Sec) const406 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 
moveSectionNext(DataRefImpl & Sec) const422 void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
423   Sec.d.a++;
424   if ((Sec.d.a) >= SectionList.size())
425     Sec.d.a = 0;
426 }
427 
getSectionName(DataRefImpl Sec) const428 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 
getSectionAddress(DataRefImpl Sec) const442 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 
getSectionSize(DataRefImpl Sec) const449 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>>
getSectionContents(DataRefImpl Sec) const461 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>(SectionDataCache[Sec.d.a]);
508 }
509 
getSectionAlignment(DataRefImpl Sec) const510 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 1ULL << static_cast<uint64_t>(Pow2Alignment);
515 }
516 
isSectionText(DataRefImpl Sec) const517 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 
isSectionData(DataRefImpl Sec) const524 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 
isSectionNoLoad(DataRefImpl Sec) const531 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 
isSectionReadOnlyData(DataRefImpl Sec) const538 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 
isSectionZeroInit(DataRefImpl Sec) const548 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 
section_begin() const554 section_iterator GOFFObjectFile::section_begin() const {
555   DataRefImpl Sec;
556   moveSectionNext(Sec);
557   return section_iterator(SectionRef(Sec, this));
558 }
559 
section_end() const560 section_iterator GOFFObjectFile::section_end() const {
561   DataRefImpl Sec;
562   return section_iterator(SectionRef(Sec, this));
563 }
564 
moveSymbolNext(DataRefImpl & Symb) const565 void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
566   for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
567     if (EsdPtrs[I]) {
568       const uint8_t *EsdRecord = EsdPtrs[I];
569       GOFF::ESDSymbolType SymbolType;
570       ESDRecord::getSymbolType(EsdRecord, SymbolType);
571       // Skip EDs - i.e. section symbols.
572       bool IgnoreSpecialGOFFSymbols = true;
573       bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
574                          (SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
575                         IgnoreSpecialGOFFSymbols;
576       if (!SkipSymbol) {
577         Symb.d.a = I;
578         return;
579       }
580     }
581   }
582   Symb.d.a = 0;
583 }
584 
symbol_begin() const585 basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
586   DataRefImpl Symb;
587   moveSymbolNext(Symb);
588   return basic_symbol_iterator(SymbolRef(Symb, this));
589 }
590 
symbol_end() const591 basic_symbol_iterator GOFFObjectFile::symbol_end() const {
592   DataRefImpl Symb;
593   return basic_symbol_iterator(SymbolRef(Symb, this));
594 }
595 
getContinuousData(const uint8_t * Record,uint16_t DataLength,int DataIndex,SmallString<256> & CompleteData)596 Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength,
597                                 int DataIndex, SmallString<256> &CompleteData) {
598   // First record.
599   const uint8_t *Slice = Record + DataIndex;
600   size_t SliceLength =
601       std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex));
602   CompleteData.append(Slice, Slice + SliceLength);
603   DataLength -= SliceLength;
604   Slice += SliceLength;
605 
606   // Continuation records.
607   for (; DataLength > 0;
608        DataLength -= SliceLength, Slice += GOFF::PayloadLength) {
609     // Slice points to the start of the new record.
610     // Check that this block is a Continuation.
611     assert(Record::isContinuation(Slice) && "Continuation bit must be set");
612     // Check that the last Continuation is terminated correctly.
613     if (DataLength <= 77 && Record::isContinued(Slice))
614       return createStringError(object_error::parse_failed,
615                                "continued bit should not be set");
616 
617     SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength);
618     Slice += GOFF::RecordPrefixLength;
619     CompleteData.append(Slice, Slice + SliceLength);
620   }
621   return Error::success();
622 }
623 
getData(const uint8_t * Record,SmallString<256> & CompleteData)624 Error HDRRecord::getData(const uint8_t *Record,
625                          SmallString<256> &CompleteData) {
626   uint16_t Length = getPropertyModuleLength(Record);
627   return getContinuousData(Record, Length, 60, CompleteData);
628 }
629 
getData(const uint8_t * Record,SmallString<256> & CompleteData)630 Error ESDRecord::getData(const uint8_t *Record,
631                          SmallString<256> &CompleteData) {
632   uint16_t DataSize = getNameLength(Record);
633   return getContinuousData(Record, DataSize, 72, CompleteData);
634 }
635 
getData(const uint8_t * Record,SmallString<256> & CompleteData)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 
getData(const uint8_t * Record,SmallString<256> & CompleteData)643 Error ENDRecord::getData(const uint8_t *Record,
644                          SmallString<256> &CompleteData) {
645   uint16_t Length = getNameLength(Record);
646   return getContinuousData(Record, Length, 26, CompleteData);
647 }
648