xref: /src/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
17fa27ce4SDimitry Andric //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
27fa27ce4SDimitry Andric //
37fa27ce4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fa27ce4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57fa27ce4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fa27ce4SDimitry Andric //
77fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
87fa27ce4SDimitry Andric //
97fa27ce4SDimitry Andric // Implementation of the GOFFObjectFile class.
107fa27ce4SDimitry Andric //
117fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
127fa27ce4SDimitry Andric 
137fa27ce4SDimitry Andric #include "llvm/Object/GOFFObjectFile.h"
147fa27ce4SDimitry Andric #include "llvm/BinaryFormat/GOFF.h"
157fa27ce4SDimitry Andric #include "llvm/Object/GOFF.h"
167fa27ce4SDimitry Andric #include "llvm/Support/Debug.h"
177fa27ce4SDimitry Andric #include "llvm/Support/Errc.h"
187fa27ce4SDimitry Andric #include "llvm/Support/raw_ostream.h"
197fa27ce4SDimitry Andric 
207fa27ce4SDimitry Andric #ifndef DEBUG_TYPE
217fa27ce4SDimitry Andric #define DEBUG_TYPE "goff"
227fa27ce4SDimitry Andric #endif
237fa27ce4SDimitry Andric 
247fa27ce4SDimitry Andric using namespace llvm::object;
257fa27ce4SDimitry Andric using namespace llvm;
267fa27ce4SDimitry Andric 
277fa27ce4SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createGOFFObjectFile(MemoryBufferRef Object)287fa27ce4SDimitry Andric ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
297fa27ce4SDimitry Andric   Error Err = Error::success();
307fa27ce4SDimitry Andric   std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
317fa27ce4SDimitry Andric   if (Err)
327fa27ce4SDimitry Andric     return std::move(Err);
337fa27ce4SDimitry Andric   return std::move(Ret);
347fa27ce4SDimitry Andric }
357fa27ce4SDimitry Andric 
GOFFObjectFile(MemoryBufferRef Object,Error & Err)367fa27ce4SDimitry Andric GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
377fa27ce4SDimitry Andric     : ObjectFile(Binary::ID_GOFF, Object) {
387fa27ce4SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
397fa27ce4SDimitry Andric   // Object file isn't the right size, bail out early.
407fa27ce4SDimitry Andric   if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
417fa27ce4SDimitry Andric     Err = createStringError(
427fa27ce4SDimitry Andric         object_error::unexpected_eof,
437fa27ce4SDimitry Andric         "object file is not the right size. Must be a multiple "
447fa27ce4SDimitry Andric         "of 80 bytes, but is " +
457fa27ce4SDimitry Andric             std::to_string(Object.getBufferSize()) + " bytes");
467fa27ce4SDimitry Andric     return;
477fa27ce4SDimitry Andric   }
487fa27ce4SDimitry Andric   // Object file doesn't start/end with HDR/END records.
497fa27ce4SDimitry Andric   // Bail out early.
507fa27ce4SDimitry Andric   if (Object.getBufferSize() != 0) {
517fa27ce4SDimitry Andric     if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
527fa27ce4SDimitry Andric       Err = createStringError(object_error::parse_failed,
537fa27ce4SDimitry Andric                               "object file must start with HDR record");
547fa27ce4SDimitry Andric       return;
557fa27ce4SDimitry Andric     }
567fa27ce4SDimitry Andric     if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
577fa27ce4SDimitry Andric         GOFF::RT_END) {
587fa27ce4SDimitry Andric       Err = createStringError(object_error::parse_failed,
597fa27ce4SDimitry Andric                               "object file must end with END record");
607fa27ce4SDimitry Andric       return;
617fa27ce4SDimitry Andric     }
627fa27ce4SDimitry Andric   }
637fa27ce4SDimitry Andric 
647fa27ce4SDimitry Andric   SectionEntryImpl DummySection;
657fa27ce4SDimitry Andric   SectionList.emplace_back(DummySection); // Dummy entry at index 0.
667fa27ce4SDimitry Andric 
677fa27ce4SDimitry Andric   uint8_t PrevRecordType = 0;
687fa27ce4SDimitry Andric   uint8_t PrevContinuationBits = 0;
697fa27ce4SDimitry Andric   const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
707fa27ce4SDimitry Andric   for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
717fa27ce4SDimitry Andric     uint8_t RecordType = (I[1] & 0xF0) >> 4;
727fa27ce4SDimitry Andric     bool IsContinuation = I[1] & 0x02;
737fa27ce4SDimitry Andric     bool PrevWasContinued = PrevContinuationBits & 0x01;
747fa27ce4SDimitry Andric     size_t RecordNum = (I - base()) / GOFF::RecordLength;
757fa27ce4SDimitry Andric 
767fa27ce4SDimitry Andric     // If the previous record was continued, the current record should be a
777fa27ce4SDimitry Andric     // continuation.
787fa27ce4SDimitry Andric     if (PrevWasContinued && !IsContinuation) {
797fa27ce4SDimitry Andric       if (PrevRecordType == RecordType) {
807fa27ce4SDimitry Andric         Err = createStringError(object_error::parse_failed,
817fa27ce4SDimitry Andric                                 "record " + std::to_string(RecordNum) +
827fa27ce4SDimitry Andric                                     " is not a continuation record but the "
837fa27ce4SDimitry Andric                                     "preceding record is continued");
847fa27ce4SDimitry Andric         return;
857fa27ce4SDimitry Andric       }
867fa27ce4SDimitry Andric     }
877fa27ce4SDimitry Andric     // Don't parse continuations records, only parse initial record.
887fa27ce4SDimitry Andric     if (IsContinuation) {
897fa27ce4SDimitry Andric       if (RecordType != PrevRecordType) {
907fa27ce4SDimitry Andric         Err = createStringError(object_error::parse_failed,
917fa27ce4SDimitry Andric                                 "record " + std::to_string(RecordNum) +
927fa27ce4SDimitry Andric                                     " is a continuation record that does not "
937fa27ce4SDimitry Andric                                     "match the type of the previous record");
947fa27ce4SDimitry Andric         return;
957fa27ce4SDimitry Andric       }
967fa27ce4SDimitry Andric       if (!PrevWasContinued) {
977fa27ce4SDimitry Andric         Err = createStringError(object_error::parse_failed,
987fa27ce4SDimitry Andric                                 "record " + std::to_string(RecordNum) +
997fa27ce4SDimitry Andric                                     " is a continuation record that is not "
1007fa27ce4SDimitry Andric                                     "preceded by a continued record");
1017fa27ce4SDimitry Andric         return;
1027fa27ce4SDimitry Andric       }
1037fa27ce4SDimitry Andric       PrevRecordType = RecordType;
1047fa27ce4SDimitry Andric       PrevContinuationBits = I[1] & 0x03;
1057fa27ce4SDimitry Andric       continue;
1067fa27ce4SDimitry Andric     }
107ac9a064cSDimitry Andric     LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) {
1087fa27ce4SDimitry Andric       const uint8_t *P = I + J;
1097fa27ce4SDimitry Andric       if (J % 8 == 0)
1107fa27ce4SDimitry Andric         dbgs() << "  ";
1117fa27ce4SDimitry Andric       dbgs() << format("%02hhX", *P);
112ac9a064cSDimitry Andric     });
113ac9a064cSDimitry Andric 
1147fa27ce4SDimitry Andric     switch (RecordType) {
1157fa27ce4SDimitry Andric     case GOFF::RT_ESD: {
1167fa27ce4SDimitry Andric       // Save ESD record.
1177fa27ce4SDimitry Andric       uint32_t EsdId;
1187fa27ce4SDimitry Andric       ESDRecord::getEsdId(I, EsdId);
1197fa27ce4SDimitry Andric       EsdPtrs.grow(EsdId);
1207fa27ce4SDimitry Andric       EsdPtrs[EsdId] = I;
1217fa27ce4SDimitry Andric 
1227fa27ce4SDimitry Andric       // Determine and save the "sections" in GOFF.
1237fa27ce4SDimitry Andric       // A section is saved as a tuple of the form
1247fa27ce4SDimitry Andric       // case (1): (ED,child PR)
1257fa27ce4SDimitry Andric       //    - where the PR must have non-zero length.
1267fa27ce4SDimitry Andric       // case (2a) (ED,0)
1277fa27ce4SDimitry Andric       //   - where the ED is of non-zero length.
1287fa27ce4SDimitry Andric       // case (2b) (ED,0)
1297fa27ce4SDimitry Andric       //   - where the ED is zero length but
1307fa27ce4SDimitry Andric       //     contains a label (LD).
1317fa27ce4SDimitry Andric       GOFF::ESDSymbolType SymbolType;
1327fa27ce4SDimitry Andric       ESDRecord::getSymbolType(I, SymbolType);
1337fa27ce4SDimitry Andric       SectionEntryImpl Section;
1347fa27ce4SDimitry Andric       uint32_t Length;
1357fa27ce4SDimitry Andric       ESDRecord::getLength(I, Length);
1367fa27ce4SDimitry Andric       if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
1377fa27ce4SDimitry Andric         // case (2a)
1387fa27ce4SDimitry Andric         if (Length != 0) {
1397fa27ce4SDimitry Andric           Section.d.a = EsdId;
1407fa27ce4SDimitry Andric           SectionList.emplace_back(Section);
1417fa27ce4SDimitry Andric         }
1427fa27ce4SDimitry Andric       } else if (SymbolType == GOFF::ESD_ST_PartReference) {
1437fa27ce4SDimitry Andric         // case (1)
1447fa27ce4SDimitry Andric         if (Length != 0) {
1457fa27ce4SDimitry Andric           uint32_t SymEdId;
1467fa27ce4SDimitry Andric           ESDRecord::getParentEsdId(I, SymEdId);
1477fa27ce4SDimitry Andric           Section.d.a = SymEdId;
1487fa27ce4SDimitry Andric           Section.d.b = EsdId;
1497fa27ce4SDimitry Andric           SectionList.emplace_back(Section);
1507fa27ce4SDimitry Andric         }
1517fa27ce4SDimitry Andric       } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
1527fa27ce4SDimitry Andric         // case (2b)
1537fa27ce4SDimitry Andric         uint32_t SymEdId;
1547fa27ce4SDimitry Andric         ESDRecord::getParentEsdId(I, SymEdId);
1557fa27ce4SDimitry Andric         const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
1567fa27ce4SDimitry Andric         uint32_t EdLength;
1577fa27ce4SDimitry Andric         ESDRecord::getLength(SymEdRecord, EdLength);
1587fa27ce4SDimitry Andric         if (!EdLength) { // [ EDID, PRID ]
1597fa27ce4SDimitry Andric           // LD child of a zero length parent ED.
1607fa27ce4SDimitry Andric           // Add the section ED which was previously ignored.
1617fa27ce4SDimitry Andric           Section.d.a = SymEdId;
1627fa27ce4SDimitry Andric           SectionList.emplace_back(Section);
1637fa27ce4SDimitry Andric         }
1647fa27ce4SDimitry Andric       }
1657fa27ce4SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  ESD " << EsdId << "\n");
1667fa27ce4SDimitry Andric       break;
1677fa27ce4SDimitry Andric     }
168ac9a064cSDimitry Andric     case GOFF::RT_TXT:
169ac9a064cSDimitry Andric       // Save TXT records.
170ac9a064cSDimitry Andric       TextPtrs.emplace_back(I);
171ac9a064cSDimitry Andric       LLVM_DEBUG(dbgs() << "  --  TXT\n");
172ac9a064cSDimitry Andric       break;
1737fa27ce4SDimitry Andric     case GOFF::RT_END:
1747fa27ce4SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  END (GOFF record type) unhandled\n");
1757fa27ce4SDimitry Andric       break;
1767fa27ce4SDimitry Andric     case GOFF::RT_HDR:
1777fa27ce4SDimitry Andric       LLVM_DEBUG(dbgs() << "  --  HDR (GOFF record type) unhandled\n");
1787fa27ce4SDimitry Andric       break;
1797fa27ce4SDimitry Andric     default:
1807fa27ce4SDimitry Andric       llvm_unreachable("Unknown record type");
1817fa27ce4SDimitry Andric     }
1827fa27ce4SDimitry Andric     PrevRecordType = RecordType;
1837fa27ce4SDimitry Andric     PrevContinuationBits = I[1] & 0x03;
1847fa27ce4SDimitry Andric   }
1857fa27ce4SDimitry Andric }
1867fa27ce4SDimitry Andric 
getSymbolEsdRecord(DataRefImpl Symb) const1877fa27ce4SDimitry Andric const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
1887fa27ce4SDimitry Andric   const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
1897fa27ce4SDimitry Andric   return EsdRecord;
1907fa27ce4SDimitry Andric }
1917fa27ce4SDimitry Andric 
getSymbolName(DataRefImpl Symb) const1927fa27ce4SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
1937fa27ce4SDimitry Andric   if (EsdNamesCache.count(Symb.d.a)) {
1947fa27ce4SDimitry Andric     auto &StrPtr = EsdNamesCache[Symb.d.a];
1957fa27ce4SDimitry Andric     return StringRef(StrPtr.second.get(), StrPtr.first);
1967fa27ce4SDimitry Andric   }
1977fa27ce4SDimitry Andric 
1987fa27ce4SDimitry Andric   SmallString<256> SymbolName;
1997fa27ce4SDimitry Andric   if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
2007fa27ce4SDimitry Andric     return std::move(Err);
2017fa27ce4SDimitry Andric 
2027fa27ce4SDimitry Andric   SmallString<256> SymbolNameConverted;
2037fa27ce4SDimitry Andric   ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
2047fa27ce4SDimitry Andric 
2057fa27ce4SDimitry Andric   size_t Size = SymbolNameConverted.size();
2067fa27ce4SDimitry Andric   auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));
2077fa27ce4SDimitry Andric   char *Buf = StrPtr.second.get();
2087fa27ce4SDimitry Andric   memcpy(Buf, SymbolNameConverted.data(), Size);
2097fa27ce4SDimitry Andric   EsdNamesCache[Symb.d.a] = std::move(StrPtr);
2107fa27ce4SDimitry Andric   return StringRef(Buf, Size);
2117fa27ce4SDimitry Andric }
2127fa27ce4SDimitry Andric 
getSymbolName(SymbolRef Symbol) const2137fa27ce4SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
2147fa27ce4SDimitry Andric   return getSymbolName(Symbol.getRawDataRefImpl());
2157fa27ce4SDimitry Andric }
2167fa27ce4SDimitry Andric 
getSymbolAddress(DataRefImpl Symb) const2177fa27ce4SDimitry Andric Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
2187fa27ce4SDimitry Andric   uint32_t Offset;
2197fa27ce4SDimitry Andric   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
2207fa27ce4SDimitry Andric   ESDRecord::getOffset(EsdRecord, Offset);
2217fa27ce4SDimitry Andric   return static_cast<uint64_t>(Offset);
2227fa27ce4SDimitry Andric }
2237fa27ce4SDimitry Andric 
getSymbolValueImpl(DataRefImpl Symb) const2247fa27ce4SDimitry Andric uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
2257fa27ce4SDimitry Andric   uint32_t Offset;
2267fa27ce4SDimitry Andric   const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
2277fa27ce4SDimitry Andric   ESDRecord::getOffset(EsdRecord, Offset);
2287fa27ce4SDimitry Andric   return static_cast<uint64_t>(Offset);
2297fa27ce4SDimitry Andric }
2307fa27ce4SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Symb) const2317fa27ce4SDimitry Andric uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
2327fa27ce4SDimitry Andric   return 0;
2337fa27ce4SDimitry Andric }
2347fa27ce4SDimitry Andric 
isSymbolUnresolved(DataRefImpl Symb) const2357fa27ce4SDimitry Andric bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
2367fa27ce4SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
2377fa27ce4SDimitry Andric   GOFF::ESDSymbolType SymbolType;
2387fa27ce4SDimitry Andric   ESDRecord::getSymbolType(Record, SymbolType);
2397fa27ce4SDimitry Andric 
2407fa27ce4SDimitry Andric   if (SymbolType == GOFF::ESD_ST_ExternalReference)
2417fa27ce4SDimitry Andric     return true;
2427fa27ce4SDimitry Andric   if (SymbolType == GOFF::ESD_ST_PartReference) {
2437fa27ce4SDimitry Andric     uint32_t Length;
2447fa27ce4SDimitry Andric     ESDRecord::getLength(Record, Length);
2457fa27ce4SDimitry Andric     if (Length == 0)
2467fa27ce4SDimitry Andric       return true;
2477fa27ce4SDimitry Andric   }
2487fa27ce4SDimitry Andric   return false;
2497fa27ce4SDimitry Andric }
2507fa27ce4SDimitry Andric 
isSymbolIndirect(DataRefImpl Symb) const2517fa27ce4SDimitry Andric bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
2527fa27ce4SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
2537fa27ce4SDimitry Andric   bool Indirect;
2547fa27ce4SDimitry Andric   ESDRecord::getIndirectReference(Record, Indirect);
2557fa27ce4SDimitry Andric   return Indirect;
2567fa27ce4SDimitry Andric }
2577fa27ce4SDimitry Andric 
getSymbolFlags(DataRefImpl Symb) const2587fa27ce4SDimitry Andric Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
2597fa27ce4SDimitry Andric   uint32_t Flags = 0;
2607fa27ce4SDimitry Andric   if (isSymbolUnresolved(Symb))
2617fa27ce4SDimitry Andric     Flags |= SymbolRef::SF_Undefined;
2627fa27ce4SDimitry Andric 
2637fa27ce4SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
2647fa27ce4SDimitry Andric 
2657fa27ce4SDimitry Andric   GOFF::ESDBindingStrength BindingStrength;
2667fa27ce4SDimitry Andric   ESDRecord::getBindingStrength(Record, BindingStrength);
2677fa27ce4SDimitry Andric   if (BindingStrength == GOFF::ESD_BST_Weak)
2687fa27ce4SDimitry Andric     Flags |= SymbolRef::SF_Weak;
2697fa27ce4SDimitry Andric 
2707fa27ce4SDimitry Andric   GOFF::ESDBindingScope BindingScope;
2717fa27ce4SDimitry Andric   ESDRecord::getBindingScope(Record, BindingScope);
2727fa27ce4SDimitry Andric 
2737fa27ce4SDimitry Andric   if (BindingScope != GOFF::ESD_BSC_Section) {
2747fa27ce4SDimitry Andric     Expected<StringRef> Name = getSymbolName(Symb);
2757fa27ce4SDimitry Andric     if (Name && *Name != " ") { // Blank name is local.
2767fa27ce4SDimitry Andric       Flags |= SymbolRef::SF_Global;
2777fa27ce4SDimitry Andric       if (BindingScope == GOFF::ESD_BSC_ImportExport)
2787fa27ce4SDimitry Andric         Flags |= SymbolRef::SF_Exported;
2797fa27ce4SDimitry Andric       else if (!(Flags & SymbolRef::SF_Undefined))
2807fa27ce4SDimitry Andric         Flags |= SymbolRef::SF_Hidden;
2817fa27ce4SDimitry Andric     }
2827fa27ce4SDimitry Andric   }
2837fa27ce4SDimitry Andric 
2847fa27ce4SDimitry Andric   return Flags;
2857fa27ce4SDimitry Andric }
2867fa27ce4SDimitry Andric 
2877fa27ce4SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const2887fa27ce4SDimitry Andric GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
2897fa27ce4SDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
2907fa27ce4SDimitry Andric   GOFF::ESDSymbolType SymbolType;
2917fa27ce4SDimitry Andric   ESDRecord::getSymbolType(Record, SymbolType);
2927fa27ce4SDimitry Andric   GOFF::ESDExecutable Executable;
2937fa27ce4SDimitry Andric   ESDRecord::getExecutable(Record, Executable);
2947fa27ce4SDimitry Andric 
2957fa27ce4SDimitry Andric   if (SymbolType != GOFF::ESD_ST_SectionDefinition &&
2967fa27ce4SDimitry Andric       SymbolType != GOFF::ESD_ST_ElementDefinition &&
2977fa27ce4SDimitry Andric       SymbolType != GOFF::ESD_ST_LabelDefinition &&
2987fa27ce4SDimitry Andric       SymbolType != GOFF::ESD_ST_PartReference &&
2997fa27ce4SDimitry Andric       SymbolType != GOFF::ESD_ST_ExternalReference) {
3007fa27ce4SDimitry Andric     uint32_t EsdId;
3017fa27ce4SDimitry Andric     ESDRecord::getEsdId(Record, EsdId);
3027fa27ce4SDimitry Andric     return createStringError(llvm::errc::invalid_argument,
3037fa27ce4SDimitry Andric                              "ESD record %" PRIu32
3047fa27ce4SDimitry Andric                              " has invalid symbol type 0x%02" PRIX8,
3057fa27ce4SDimitry Andric                              EsdId, SymbolType);
3067fa27ce4SDimitry Andric   }
3077fa27ce4SDimitry Andric   switch (SymbolType) {
3087fa27ce4SDimitry Andric   case GOFF::ESD_ST_SectionDefinition:
3097fa27ce4SDimitry Andric   case GOFF::ESD_ST_ElementDefinition:
3107fa27ce4SDimitry Andric     return SymbolRef::ST_Other;
3117fa27ce4SDimitry Andric   case GOFF::ESD_ST_LabelDefinition:
3127fa27ce4SDimitry Andric   case GOFF::ESD_ST_PartReference:
3137fa27ce4SDimitry Andric   case GOFF::ESD_ST_ExternalReference:
3147fa27ce4SDimitry Andric     if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
3157fa27ce4SDimitry Andric         Executable != GOFF::ESD_EXE_Unspecified) {
3167fa27ce4SDimitry Andric       uint32_t EsdId;
3177fa27ce4SDimitry Andric       ESDRecord::getEsdId(Record, EsdId);
3187fa27ce4SDimitry Andric       return createStringError(llvm::errc::invalid_argument,
3197fa27ce4SDimitry Andric                                "ESD record %" PRIu32
3207fa27ce4SDimitry Andric                                " has unknown Executable type 0x%02X",
3217fa27ce4SDimitry Andric                                EsdId, Executable);
3227fa27ce4SDimitry Andric     }
3237fa27ce4SDimitry Andric     switch (Executable) {
3247fa27ce4SDimitry Andric     case GOFF::ESD_EXE_CODE:
3257fa27ce4SDimitry Andric       return SymbolRef::ST_Function;
3267fa27ce4SDimitry Andric     case GOFF::ESD_EXE_DATA:
3277fa27ce4SDimitry Andric       return SymbolRef::ST_Data;
3287fa27ce4SDimitry Andric     case GOFF::ESD_EXE_Unspecified:
3297fa27ce4SDimitry Andric       return SymbolRef::ST_Unknown;
3307fa27ce4SDimitry Andric     }
3317fa27ce4SDimitry Andric     llvm_unreachable("Unhandled ESDExecutable");
3327fa27ce4SDimitry Andric   }
3337fa27ce4SDimitry Andric   llvm_unreachable("Unhandled ESDSymbolType");
3347fa27ce4SDimitry Andric }
3357fa27ce4SDimitry Andric 
3367fa27ce4SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const3377fa27ce4SDimitry Andric GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
3387fa27ce4SDimitry Andric   DataRefImpl Sec;
3397fa27ce4SDimitry Andric 
3407fa27ce4SDimitry Andric   if (isSymbolUnresolved(Symb))
3417fa27ce4SDimitry Andric     return section_iterator(SectionRef(Sec, this));
3427fa27ce4SDimitry Andric 
3437fa27ce4SDimitry Andric   const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
3447fa27ce4SDimitry Andric   uint32_t SymEdId;
3457fa27ce4SDimitry Andric   ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
3467fa27ce4SDimitry Andric   const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
3477fa27ce4SDimitry Andric 
3487fa27ce4SDimitry Andric   for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
3497fa27ce4SDimitry Andric     bool Found;
3507fa27ce4SDimitry Andric     const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
3517fa27ce4SDimitry Andric     if (SectionPrRecord) {
3527fa27ce4SDimitry Andric       Found = SymEsdRecord == SectionPrRecord;
3537fa27ce4SDimitry Andric     } else {
3547fa27ce4SDimitry Andric       const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
3557fa27ce4SDimitry Andric       Found = SymEdRecord == SectionEdRecord;
3567fa27ce4SDimitry Andric     }
3577fa27ce4SDimitry Andric 
3587fa27ce4SDimitry Andric     if (Found) {
3597fa27ce4SDimitry Andric       Sec.d.a = I;
3607fa27ce4SDimitry Andric       return section_iterator(SectionRef(Sec, this));
3617fa27ce4SDimitry Andric     }
3627fa27ce4SDimitry Andric   }
3637fa27ce4SDimitry Andric   return createStringError(llvm::errc::invalid_argument,
3647fa27ce4SDimitry Andric                            "symbol with ESD id " + std::to_string(Symb.d.a) +
3657fa27ce4SDimitry Andric                                " refers to invalid section with ESD id " +
3667fa27ce4SDimitry Andric                                std::to_string(SymEdId));
3677fa27ce4SDimitry Andric }
3687fa27ce4SDimitry Andric 
getSymbolSize(DataRefImpl Symb) const369ac9a064cSDimitry Andric uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
370ac9a064cSDimitry Andric   const uint8_t *Record = getSymbolEsdRecord(Symb);
371ac9a064cSDimitry Andric   uint32_t Length;
372ac9a064cSDimitry Andric   ESDRecord::getLength(Record, Length);
373ac9a064cSDimitry Andric   return Length;
374ac9a064cSDimitry Andric }
375ac9a064cSDimitry Andric 
getSectionEdEsdRecord(DataRefImpl & Sec) const3767fa27ce4SDimitry Andric const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
3777fa27ce4SDimitry Andric   SectionEntryImpl EsdIds = SectionList[Sec.d.a];
3787fa27ce4SDimitry Andric   const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
3797fa27ce4SDimitry Andric   return EsdRecord;
3807fa27ce4SDimitry Andric }
3817fa27ce4SDimitry Andric 
getSectionPrEsdRecord(DataRefImpl & Sec) const3827fa27ce4SDimitry Andric const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
3837fa27ce4SDimitry Andric   SectionEntryImpl EsdIds = SectionList[Sec.d.a];
3847fa27ce4SDimitry Andric   const uint8_t *EsdRecord = nullptr;
3857fa27ce4SDimitry Andric   if (EsdIds.d.b)
3867fa27ce4SDimitry Andric     EsdRecord = EsdPtrs[EsdIds.d.b];
3877fa27ce4SDimitry Andric   return EsdRecord;
3887fa27ce4SDimitry Andric }
3897fa27ce4SDimitry Andric 
3907fa27ce4SDimitry Andric const uint8_t *
getSectionEdEsdRecord(uint32_t SectionIndex) const3917fa27ce4SDimitry Andric GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
3927fa27ce4SDimitry Andric   DataRefImpl Sec;
3937fa27ce4SDimitry Andric   Sec.d.a = SectionIndex;
3947fa27ce4SDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
3957fa27ce4SDimitry Andric   return EsdRecord;
3967fa27ce4SDimitry Andric }
3977fa27ce4SDimitry Andric 
3987fa27ce4SDimitry Andric const uint8_t *
getSectionPrEsdRecord(uint32_t SectionIndex) const3997fa27ce4SDimitry Andric GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
4007fa27ce4SDimitry Andric   DataRefImpl Sec;
4017fa27ce4SDimitry Andric   Sec.d.a = SectionIndex;
4027fa27ce4SDimitry Andric   const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
4037fa27ce4SDimitry Andric   return EsdRecord;
4047fa27ce4SDimitry Andric }
4057fa27ce4SDimitry Andric 
getSectionDefEsdId(DataRefImpl & Sec) const406ac9a064cSDimitry Andric uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
407ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
408ac9a064cSDimitry Andric   uint32_t Length;
409ac9a064cSDimitry Andric   ESDRecord::getLength(EsdRecord, Length);
410ac9a064cSDimitry Andric   if (Length == 0) {
411ac9a064cSDimitry Andric     const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
412ac9a064cSDimitry Andric     if (PrEsdRecord)
413ac9a064cSDimitry Andric       EsdRecord = PrEsdRecord;
414ac9a064cSDimitry Andric   }
415ac9a064cSDimitry Andric 
416ac9a064cSDimitry Andric   uint32_t DefEsdId;
417ac9a064cSDimitry Andric   ESDRecord::getEsdId(EsdRecord, DefEsdId);
418ac9a064cSDimitry Andric   LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
419ac9a064cSDimitry Andric   return DefEsdId;
420ac9a064cSDimitry Andric }
421ac9a064cSDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const422ac9a064cSDimitry Andric void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
423ac9a064cSDimitry Andric   Sec.d.a++;
424ac9a064cSDimitry Andric   if ((Sec.d.a) >= SectionList.size())
425ac9a064cSDimitry Andric     Sec.d.a = 0;
426ac9a064cSDimitry Andric }
427ac9a064cSDimitry Andric 
getSectionName(DataRefImpl Sec) const428ac9a064cSDimitry Andric Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
429ac9a064cSDimitry Andric   DataRefImpl EdSym;
430ac9a064cSDimitry Andric   SectionEntryImpl EsdIds = SectionList[Sec.d.a];
431ac9a064cSDimitry Andric   EdSym.d.a = EsdIds.d.a;
432ac9a064cSDimitry Andric   Expected<StringRef> Name = getSymbolName(EdSym);
433ac9a064cSDimitry Andric   if (Name) {
434ac9a064cSDimitry Andric     StringRef Res = *Name;
435ac9a064cSDimitry Andric     LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
436ac9a064cSDimitry Andric     LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
437ac9a064cSDimitry Andric     Name = Res;
438ac9a064cSDimitry Andric   }
439ac9a064cSDimitry Andric   return Name;
440ac9a064cSDimitry Andric }
441ac9a064cSDimitry Andric 
getSectionAddress(DataRefImpl Sec) const442ac9a064cSDimitry Andric uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
443ac9a064cSDimitry Andric   uint32_t Offset;
444ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
445ac9a064cSDimitry Andric   ESDRecord::getOffset(EsdRecord, Offset);
446ac9a064cSDimitry Andric   return Offset;
447ac9a064cSDimitry Andric }
448ac9a064cSDimitry Andric 
getSectionSize(DataRefImpl Sec) const449ac9a064cSDimitry Andric uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
450ac9a064cSDimitry Andric   uint32_t Length;
451ac9a064cSDimitry Andric   uint32_t DefEsdId = getSectionDefEsdId(Sec);
452ac9a064cSDimitry Andric   const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
453ac9a064cSDimitry Andric   ESDRecord::getLength(EsdRecord, Length);
454ac9a064cSDimitry Andric   LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
455ac9a064cSDimitry Andric   return static_cast<uint64_t>(Length);
456ac9a064cSDimitry Andric }
457ac9a064cSDimitry Andric 
458ac9a064cSDimitry Andric // Unravel TXT records and expand fill characters to produce
459ac9a064cSDimitry Andric // a contiguous sequence of bytes.
460ac9a064cSDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const461ac9a064cSDimitry Andric GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
462ac9a064cSDimitry Andric   if (SectionDataCache.count(Sec.d.a)) {
463ac9a064cSDimitry Andric     auto &Buf = SectionDataCache[Sec.d.a];
464ac9a064cSDimitry Andric     return ArrayRef<uint8_t>(Buf);
465ac9a064cSDimitry Andric   }
466ac9a064cSDimitry Andric   uint64_t SectionSize = getSectionSize(Sec);
467ac9a064cSDimitry Andric   uint32_t DefEsdId = getSectionDefEsdId(Sec);
468ac9a064cSDimitry Andric 
469ac9a064cSDimitry Andric   const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
470ac9a064cSDimitry Andric   bool FillBytePresent;
471ac9a064cSDimitry Andric   ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
472ac9a064cSDimitry Andric   uint8_t FillByte = '\0';
473ac9a064cSDimitry Andric   if (FillBytePresent)
474ac9a064cSDimitry Andric     ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
475ac9a064cSDimitry Andric 
476ac9a064cSDimitry Andric   // Initialize section with fill byte.
477ac9a064cSDimitry Andric   SmallVector<uint8_t> Data(SectionSize, FillByte);
478ac9a064cSDimitry Andric 
479ac9a064cSDimitry Andric   // Replace section with content from text records.
480ac9a064cSDimitry Andric   for (const uint8_t *TxtRecordInt : TextPtrs) {
481ac9a064cSDimitry Andric     const uint8_t *TxtRecordPtr = TxtRecordInt;
482ac9a064cSDimitry Andric     uint32_t TxtEsdId;
483ac9a064cSDimitry Andric     TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
484ac9a064cSDimitry Andric     LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
485ac9a064cSDimitry Andric 
486ac9a064cSDimitry Andric     if (TxtEsdId != DefEsdId)
487ac9a064cSDimitry Andric       continue;
488ac9a064cSDimitry Andric 
489ac9a064cSDimitry Andric     uint32_t TxtDataOffset;
490ac9a064cSDimitry Andric     TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
491ac9a064cSDimitry Andric 
492ac9a064cSDimitry Andric     uint16_t TxtDataSize;
493ac9a064cSDimitry Andric     TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
494ac9a064cSDimitry Andric 
495ac9a064cSDimitry Andric     LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
496ac9a064cSDimitry Andric                       << TxtDataSize << "\n");
497ac9a064cSDimitry Andric 
498ac9a064cSDimitry Andric     SmallString<256> CompleteData;
499ac9a064cSDimitry Andric     CompleteData.reserve(TxtDataSize);
500ac9a064cSDimitry Andric     if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData))
501ac9a064cSDimitry Andric       return std::move(Err);
502ac9a064cSDimitry Andric     assert(CompleteData.size() == TxtDataSize && "Wrong length of data");
503ac9a064cSDimitry Andric     std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,
504ac9a064cSDimitry Andric               Data.begin() + TxtDataOffset);
505ac9a064cSDimitry Andric   }
506ac9a064cSDimitry Andric   SectionDataCache[Sec.d.a] = Data;
507ac9a064cSDimitry Andric   return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]);
508ac9a064cSDimitry Andric }
509ac9a064cSDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const510ac9a064cSDimitry Andric uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
511ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
512ac9a064cSDimitry Andric   GOFF::ESDAlignment Pow2Alignment;
513ac9a064cSDimitry Andric   ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
514ac9a064cSDimitry Andric   return 1ULL << static_cast<uint64_t>(Pow2Alignment);
515ac9a064cSDimitry Andric }
516ac9a064cSDimitry Andric 
isSectionText(DataRefImpl Sec) const517ac9a064cSDimitry Andric bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
518ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
519ac9a064cSDimitry Andric   GOFF::ESDExecutable Executable;
520ac9a064cSDimitry Andric   ESDRecord::getExecutable(EsdRecord, Executable);
521ac9a064cSDimitry Andric   return Executable == GOFF::ESD_EXE_CODE;
522ac9a064cSDimitry Andric }
523ac9a064cSDimitry Andric 
isSectionData(DataRefImpl Sec) const524ac9a064cSDimitry Andric bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
525ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
526ac9a064cSDimitry Andric   GOFF::ESDExecutable Executable;
527ac9a064cSDimitry Andric   ESDRecord::getExecutable(EsdRecord, Executable);
528ac9a064cSDimitry Andric   return Executable == GOFF::ESD_EXE_DATA;
529ac9a064cSDimitry Andric }
530ac9a064cSDimitry Andric 
isSectionNoLoad(DataRefImpl Sec) const531ac9a064cSDimitry Andric bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const {
532ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
533ac9a064cSDimitry Andric   GOFF::ESDLoadingBehavior LoadingBehavior;
534ac9a064cSDimitry Andric   ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
535ac9a064cSDimitry Andric   return LoadingBehavior == GOFF::ESD_LB_NoLoad;
536ac9a064cSDimitry Andric }
537ac9a064cSDimitry Andric 
isSectionReadOnlyData(DataRefImpl Sec) const538ac9a064cSDimitry Andric bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
539ac9a064cSDimitry Andric   if (!isSectionData(Sec))
540ac9a064cSDimitry Andric     return false;
541ac9a064cSDimitry Andric 
542ac9a064cSDimitry Andric   const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
543ac9a064cSDimitry Andric   GOFF::ESDLoadingBehavior LoadingBehavior;
544ac9a064cSDimitry Andric   ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
545ac9a064cSDimitry Andric   return LoadingBehavior == GOFF::ESD_LB_Initial;
546ac9a064cSDimitry Andric }
547ac9a064cSDimitry Andric 
isSectionZeroInit(DataRefImpl Sec) const548ac9a064cSDimitry Andric bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
549ac9a064cSDimitry Andric   // GOFF uses fill characters and fill characters are applied
550ac9a064cSDimitry Andric   // on getSectionContents() - so we say false to zero init.
551ac9a064cSDimitry Andric   return false;
552ac9a064cSDimitry Andric }
553ac9a064cSDimitry Andric 
section_begin() const5547fa27ce4SDimitry Andric section_iterator GOFFObjectFile::section_begin() const {
5557fa27ce4SDimitry Andric   DataRefImpl Sec;
5567fa27ce4SDimitry Andric   moveSectionNext(Sec);
5577fa27ce4SDimitry Andric   return section_iterator(SectionRef(Sec, this));
5587fa27ce4SDimitry Andric }
5597fa27ce4SDimitry Andric 
section_end() const5607fa27ce4SDimitry Andric section_iterator GOFFObjectFile::section_end() const {
5617fa27ce4SDimitry Andric   DataRefImpl Sec;
5627fa27ce4SDimitry Andric   return section_iterator(SectionRef(Sec, this));
5637fa27ce4SDimitry Andric }
5647fa27ce4SDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const5657fa27ce4SDimitry Andric void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
5667fa27ce4SDimitry Andric   for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
5677fa27ce4SDimitry Andric     if (EsdPtrs[I]) {
5687fa27ce4SDimitry Andric       const uint8_t *EsdRecord = EsdPtrs[I];
5697fa27ce4SDimitry Andric       GOFF::ESDSymbolType SymbolType;
5707fa27ce4SDimitry Andric       ESDRecord::getSymbolType(EsdRecord, SymbolType);
5717fa27ce4SDimitry Andric       // Skip EDs - i.e. section symbols.
5727fa27ce4SDimitry Andric       bool IgnoreSpecialGOFFSymbols = true;
5737fa27ce4SDimitry Andric       bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
5747fa27ce4SDimitry Andric                          (SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
5757fa27ce4SDimitry Andric                         IgnoreSpecialGOFFSymbols;
5767fa27ce4SDimitry Andric       if (!SkipSymbol) {
5777fa27ce4SDimitry Andric         Symb.d.a = I;
5787fa27ce4SDimitry Andric         return;
5797fa27ce4SDimitry Andric       }
5807fa27ce4SDimitry Andric     }
5817fa27ce4SDimitry Andric   }
5827fa27ce4SDimitry Andric   Symb.d.a = 0;
5837fa27ce4SDimitry Andric }
5847fa27ce4SDimitry Andric 
symbol_begin() const5857fa27ce4SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
5867fa27ce4SDimitry Andric   DataRefImpl Symb;
5877fa27ce4SDimitry Andric   moveSymbolNext(Symb);
5887fa27ce4SDimitry Andric   return basic_symbol_iterator(SymbolRef(Symb, this));
5897fa27ce4SDimitry Andric }
5907fa27ce4SDimitry Andric 
symbol_end() const5917fa27ce4SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_end() const {
5927fa27ce4SDimitry Andric   DataRefImpl Symb;
5937fa27ce4SDimitry Andric   return basic_symbol_iterator(SymbolRef(Symb, this));
5947fa27ce4SDimitry Andric }
5957fa27ce4SDimitry Andric 
getContinuousData(const uint8_t * Record,uint16_t DataLength,int DataIndex,SmallString<256> & CompleteData)5967fa27ce4SDimitry Andric Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength,
5977fa27ce4SDimitry Andric                                 int DataIndex, SmallString<256> &CompleteData) {
5987fa27ce4SDimitry Andric   // First record.
5997fa27ce4SDimitry Andric   const uint8_t *Slice = Record + DataIndex;
6007fa27ce4SDimitry Andric   size_t SliceLength =
6017fa27ce4SDimitry Andric       std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex));
6027fa27ce4SDimitry Andric   CompleteData.append(Slice, Slice + SliceLength);
6037fa27ce4SDimitry Andric   DataLength -= SliceLength;
6047fa27ce4SDimitry Andric   Slice += SliceLength;
6057fa27ce4SDimitry Andric 
6067fa27ce4SDimitry Andric   // Continuation records.
6077fa27ce4SDimitry Andric   for (; DataLength > 0;
6087fa27ce4SDimitry Andric        DataLength -= SliceLength, Slice += GOFF::PayloadLength) {
6097fa27ce4SDimitry Andric     // Slice points to the start of the new record.
6107fa27ce4SDimitry Andric     // Check that this block is a Continuation.
6117fa27ce4SDimitry Andric     assert(Record::isContinuation(Slice) && "Continuation bit must be set");
6127fa27ce4SDimitry Andric     // Check that the last Continuation is terminated correctly.
6137fa27ce4SDimitry Andric     if (DataLength <= 77 && Record::isContinued(Slice))
6147fa27ce4SDimitry Andric       return createStringError(object_error::parse_failed,
6157fa27ce4SDimitry Andric                                "continued bit should not be set");
6167fa27ce4SDimitry Andric 
6177fa27ce4SDimitry Andric     SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength);
6187fa27ce4SDimitry Andric     Slice += GOFF::RecordPrefixLength;
6197fa27ce4SDimitry Andric     CompleteData.append(Slice, Slice + SliceLength);
6207fa27ce4SDimitry Andric   }
6217fa27ce4SDimitry Andric   return Error::success();
6227fa27ce4SDimitry Andric }
6237fa27ce4SDimitry Andric 
getData(const uint8_t * Record,SmallString<256> & CompleteData)6247fa27ce4SDimitry Andric Error HDRRecord::getData(const uint8_t *Record,
6257fa27ce4SDimitry Andric                          SmallString<256> &CompleteData) {
6267fa27ce4SDimitry Andric   uint16_t Length = getPropertyModuleLength(Record);
6277fa27ce4SDimitry Andric   return getContinuousData(Record, Length, 60, CompleteData);
6287fa27ce4SDimitry Andric }
6297fa27ce4SDimitry Andric 
getData(const uint8_t * Record,SmallString<256> & CompleteData)6307fa27ce4SDimitry Andric Error ESDRecord::getData(const uint8_t *Record,
6317fa27ce4SDimitry Andric                          SmallString<256> &CompleteData) {
6327fa27ce4SDimitry Andric   uint16_t DataSize = getNameLength(Record);
6337fa27ce4SDimitry Andric   return getContinuousData(Record, DataSize, 72, CompleteData);
6347fa27ce4SDimitry Andric }
6357fa27ce4SDimitry Andric 
getData(const uint8_t * Record,SmallString<256> & CompleteData)636ac9a064cSDimitry Andric Error TXTRecord::getData(const uint8_t *Record,
637ac9a064cSDimitry Andric                          SmallString<256> &CompleteData) {
638ac9a064cSDimitry Andric   uint16_t Length;
639ac9a064cSDimitry Andric   getDataLength(Record, Length);
640ac9a064cSDimitry Andric   return getContinuousData(Record, Length, 24, CompleteData);
641ac9a064cSDimitry Andric }
642ac9a064cSDimitry Andric 
getData(const uint8_t * Record,SmallString<256> & CompleteData)6437fa27ce4SDimitry Andric Error ENDRecord::getData(const uint8_t *Record,
6447fa27ce4SDimitry Andric                          SmallString<256> &CompleteData) {
6457fa27ce4SDimitry Andric   uint16_t Length = getNameLength(Record);
6467fa27ce4SDimitry Andric   return getContinuousData(Record, Length, 26, CompleteData);
6477fa27ce4SDimitry Andric }
648