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