106c3fb27SDimitry Andric //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric // Implementation of the GOFFObjectFile class.
1006c3fb27SDimitry Andric //
1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1206c3fb27SDimitry Andric
1306c3fb27SDimitry Andric #include "llvm/Object/GOFFObjectFile.h"
1406c3fb27SDimitry Andric #include "llvm/BinaryFormat/GOFF.h"
1506c3fb27SDimitry Andric #include "llvm/Object/GOFF.h"
1606c3fb27SDimitry Andric #include "llvm/Support/Debug.h"
1706c3fb27SDimitry Andric #include "llvm/Support/Errc.h"
1806c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
1906c3fb27SDimitry Andric
2006c3fb27SDimitry Andric #ifndef DEBUG_TYPE
2106c3fb27SDimitry Andric #define DEBUG_TYPE "goff"
2206c3fb27SDimitry Andric #endif
2306c3fb27SDimitry Andric
2406c3fb27SDimitry Andric using namespace llvm::object;
2506c3fb27SDimitry Andric using namespace llvm;
2606c3fb27SDimitry Andric
2706c3fb27SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createGOFFObjectFile(MemoryBufferRef Object)2806c3fb27SDimitry Andric ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
2906c3fb27SDimitry Andric Error Err = Error::success();
3006c3fb27SDimitry Andric std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
3106c3fb27SDimitry Andric if (Err)
3206c3fb27SDimitry Andric return std::move(Err);
3306c3fb27SDimitry Andric return std::move(Ret);
3406c3fb27SDimitry Andric }
3506c3fb27SDimitry Andric
GOFFObjectFile(MemoryBufferRef Object,Error & Err)3606c3fb27SDimitry Andric GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
3706c3fb27SDimitry Andric : ObjectFile(Binary::ID_GOFF, Object) {
3806c3fb27SDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err);
3906c3fb27SDimitry Andric // Object file isn't the right size, bail out early.
4006c3fb27SDimitry Andric if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
4106c3fb27SDimitry Andric Err = createStringError(
4206c3fb27SDimitry Andric object_error::unexpected_eof,
4306c3fb27SDimitry Andric "object file is not the right size. Must be a multiple "
4406c3fb27SDimitry Andric "of 80 bytes, but is " +
4506c3fb27SDimitry Andric std::to_string(Object.getBufferSize()) + " bytes");
4606c3fb27SDimitry Andric return;
4706c3fb27SDimitry Andric }
4806c3fb27SDimitry Andric // Object file doesn't start/end with HDR/END records.
4906c3fb27SDimitry Andric // Bail out early.
5006c3fb27SDimitry Andric if (Object.getBufferSize() != 0) {
5106c3fb27SDimitry Andric if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) {
5206c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed,
5306c3fb27SDimitry Andric "object file must start with HDR record");
5406c3fb27SDimitry Andric return;
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 !=
5706c3fb27SDimitry Andric GOFF::RT_END) {
5806c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed,
5906c3fb27SDimitry Andric "object file must end with END record");
6006c3fb27SDimitry Andric return;
6106c3fb27SDimitry Andric }
6206c3fb27SDimitry Andric }
6306c3fb27SDimitry Andric
6406c3fb27SDimitry Andric SectionEntryImpl DummySection;
6506c3fb27SDimitry Andric SectionList.emplace_back(DummySection); // Dummy entry at index 0.
6606c3fb27SDimitry Andric
6706c3fb27SDimitry Andric uint8_t PrevRecordType = 0;
6806c3fb27SDimitry Andric uint8_t PrevContinuationBits = 0;
6906c3fb27SDimitry Andric const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
7006c3fb27SDimitry Andric for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
7106c3fb27SDimitry Andric uint8_t RecordType = (I[1] & 0xF0) >> 4;
7206c3fb27SDimitry Andric bool IsContinuation = I[1] & 0x02;
7306c3fb27SDimitry Andric bool PrevWasContinued = PrevContinuationBits & 0x01;
7406c3fb27SDimitry Andric size_t RecordNum = (I - base()) / GOFF::RecordLength;
7506c3fb27SDimitry Andric
7606c3fb27SDimitry Andric // If the previous record was continued, the current record should be a
7706c3fb27SDimitry Andric // continuation.
7806c3fb27SDimitry Andric if (PrevWasContinued && !IsContinuation) {
7906c3fb27SDimitry Andric if (PrevRecordType == RecordType) {
8006c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed,
8106c3fb27SDimitry Andric "record " + std::to_string(RecordNum) +
8206c3fb27SDimitry Andric " is not a continuation record but the "
8306c3fb27SDimitry Andric "preceding record is continued");
8406c3fb27SDimitry Andric return;
8506c3fb27SDimitry Andric }
8606c3fb27SDimitry Andric }
8706c3fb27SDimitry Andric // Don't parse continuations records, only parse initial record.
8806c3fb27SDimitry Andric if (IsContinuation) {
8906c3fb27SDimitry Andric if (RecordType != PrevRecordType) {
9006c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed,
9106c3fb27SDimitry Andric "record " + std::to_string(RecordNum) +
9206c3fb27SDimitry Andric " is a continuation record that does not "
9306c3fb27SDimitry Andric "match the type of the previous record");
9406c3fb27SDimitry Andric return;
9506c3fb27SDimitry Andric }
9606c3fb27SDimitry Andric if (!PrevWasContinued) {
9706c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed,
9806c3fb27SDimitry Andric "record " + std::to_string(RecordNum) +
9906c3fb27SDimitry Andric " is a continuation record that is not "
10006c3fb27SDimitry Andric "preceded by a continued record");
10106c3fb27SDimitry Andric return;
10206c3fb27SDimitry Andric }
10306c3fb27SDimitry Andric PrevRecordType = RecordType;
10406c3fb27SDimitry Andric PrevContinuationBits = I[1] & 0x03;
10506c3fb27SDimitry Andric continue;
10606c3fb27SDimitry Andric }
107*0fca6ea1SDimitry Andric LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) {
10806c3fb27SDimitry Andric const uint8_t *P = I + J;
10906c3fb27SDimitry Andric if (J % 8 == 0)
11006c3fb27SDimitry Andric dbgs() << " ";
11106c3fb27SDimitry Andric dbgs() << format("%02hhX", *P);
112*0fca6ea1SDimitry Andric });
113*0fca6ea1SDimitry Andric
11406c3fb27SDimitry Andric switch (RecordType) {
11506c3fb27SDimitry Andric case GOFF::RT_ESD: {
11606c3fb27SDimitry Andric // Save ESD record.
11706c3fb27SDimitry Andric uint32_t EsdId;
11806c3fb27SDimitry Andric ESDRecord::getEsdId(I, EsdId);
11906c3fb27SDimitry Andric EsdPtrs.grow(EsdId);
12006c3fb27SDimitry Andric EsdPtrs[EsdId] = I;
12106c3fb27SDimitry Andric
12206c3fb27SDimitry Andric // Determine and save the "sections" in GOFF.
12306c3fb27SDimitry Andric // A section is saved as a tuple of the form
12406c3fb27SDimitry Andric // case (1): (ED,child PR)
12506c3fb27SDimitry Andric // - where the PR must have non-zero length.
12606c3fb27SDimitry Andric // case (2a) (ED,0)
12706c3fb27SDimitry Andric // - where the ED is of non-zero length.
12806c3fb27SDimitry Andric // case (2b) (ED,0)
12906c3fb27SDimitry Andric // - where the ED is zero length but
13006c3fb27SDimitry Andric // contains a label (LD).
13106c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType;
13206c3fb27SDimitry Andric ESDRecord::getSymbolType(I, SymbolType);
13306c3fb27SDimitry Andric SectionEntryImpl Section;
13406c3fb27SDimitry Andric uint32_t Length;
13506c3fb27SDimitry Andric ESDRecord::getLength(I, Length);
13606c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
13706c3fb27SDimitry Andric // case (2a)
13806c3fb27SDimitry Andric if (Length != 0) {
13906c3fb27SDimitry Andric Section.d.a = EsdId;
14006c3fb27SDimitry Andric SectionList.emplace_back(Section);
14106c3fb27SDimitry Andric }
14206c3fb27SDimitry Andric } else if (SymbolType == GOFF::ESD_ST_PartReference) {
14306c3fb27SDimitry Andric // case (1)
14406c3fb27SDimitry Andric if (Length != 0) {
14506c3fb27SDimitry Andric uint32_t SymEdId;
14606c3fb27SDimitry Andric ESDRecord::getParentEsdId(I, SymEdId);
14706c3fb27SDimitry Andric Section.d.a = SymEdId;
14806c3fb27SDimitry Andric Section.d.b = EsdId;
14906c3fb27SDimitry Andric SectionList.emplace_back(Section);
15006c3fb27SDimitry Andric }
15106c3fb27SDimitry Andric } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
15206c3fb27SDimitry Andric // case (2b)
15306c3fb27SDimitry Andric uint32_t SymEdId;
15406c3fb27SDimitry Andric ESDRecord::getParentEsdId(I, SymEdId);
15506c3fb27SDimitry Andric const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
15606c3fb27SDimitry Andric uint32_t EdLength;
15706c3fb27SDimitry Andric ESDRecord::getLength(SymEdRecord, EdLength);
15806c3fb27SDimitry Andric if (!EdLength) { // [ EDID, PRID ]
15906c3fb27SDimitry Andric // LD child of a zero length parent ED.
16006c3fb27SDimitry Andric // Add the section ED which was previously ignored.
16106c3fb27SDimitry Andric Section.d.a = SymEdId;
16206c3fb27SDimitry Andric SectionList.emplace_back(Section);
16306c3fb27SDimitry Andric }
16406c3fb27SDimitry Andric }
16506c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n");
16606c3fb27SDimitry Andric break;
16706c3fb27SDimitry Andric }
168*0fca6ea1SDimitry Andric case GOFF::RT_TXT:
169*0fca6ea1SDimitry Andric // Save TXT records.
170*0fca6ea1SDimitry Andric TextPtrs.emplace_back(I);
171*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " -- TXT\n");
172*0fca6ea1SDimitry Andric break;
17306c3fb27SDimitry Andric case GOFF::RT_END:
17406c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
17506c3fb27SDimitry Andric break;
17606c3fb27SDimitry Andric case GOFF::RT_HDR:
17706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n");
17806c3fb27SDimitry Andric break;
17906c3fb27SDimitry Andric default:
18006c3fb27SDimitry Andric llvm_unreachable("Unknown record type");
18106c3fb27SDimitry Andric }
18206c3fb27SDimitry Andric PrevRecordType = RecordType;
18306c3fb27SDimitry Andric PrevContinuationBits = I[1] & 0x03;
18406c3fb27SDimitry Andric }
18506c3fb27SDimitry Andric }
18606c3fb27SDimitry Andric
getSymbolEsdRecord(DataRefImpl Symb) const18706c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
18806c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];
18906c3fb27SDimitry Andric return EsdRecord;
19006c3fb27SDimitry Andric }
19106c3fb27SDimitry Andric
getSymbolName(DataRefImpl Symb) const19206c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
19306c3fb27SDimitry Andric if (EsdNamesCache.count(Symb.d.a)) {
19406c3fb27SDimitry Andric auto &StrPtr = EsdNamesCache[Symb.d.a];
19506c3fb27SDimitry Andric return StringRef(StrPtr.second.get(), StrPtr.first);
19606c3fb27SDimitry Andric }
19706c3fb27SDimitry Andric
19806c3fb27SDimitry Andric SmallString<256> SymbolName;
19906c3fb27SDimitry Andric if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))
20006c3fb27SDimitry Andric return std::move(Err);
20106c3fb27SDimitry Andric
20206c3fb27SDimitry Andric SmallString<256> SymbolNameConverted;
20306c3fb27SDimitry Andric ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted);
20406c3fb27SDimitry Andric
20506c3fb27SDimitry Andric size_t Size = SymbolNameConverted.size();
20606c3fb27SDimitry Andric auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));
20706c3fb27SDimitry Andric char *Buf = StrPtr.second.get();
20806c3fb27SDimitry Andric memcpy(Buf, SymbolNameConverted.data(), Size);
20906c3fb27SDimitry Andric EsdNamesCache[Symb.d.a] = std::move(StrPtr);
21006c3fb27SDimitry Andric return StringRef(Buf, Size);
21106c3fb27SDimitry Andric }
21206c3fb27SDimitry Andric
getSymbolName(SymbolRef Symbol) const21306c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
21406c3fb27SDimitry Andric return getSymbolName(Symbol.getRawDataRefImpl());
21506c3fb27SDimitry Andric }
21606c3fb27SDimitry Andric
getSymbolAddress(DataRefImpl Symb) const21706c3fb27SDimitry Andric Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
21806c3fb27SDimitry Andric uint32_t Offset;
21906c3fb27SDimitry Andric const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
22006c3fb27SDimitry Andric ESDRecord::getOffset(EsdRecord, Offset);
22106c3fb27SDimitry Andric return static_cast<uint64_t>(Offset);
22206c3fb27SDimitry Andric }
22306c3fb27SDimitry Andric
getSymbolValueImpl(DataRefImpl Symb) const22406c3fb27SDimitry Andric uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
22506c3fb27SDimitry Andric uint32_t Offset;
22606c3fb27SDimitry Andric const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
22706c3fb27SDimitry Andric ESDRecord::getOffset(EsdRecord, Offset);
22806c3fb27SDimitry Andric return static_cast<uint64_t>(Offset);
22906c3fb27SDimitry Andric }
23006c3fb27SDimitry Andric
getCommonSymbolSizeImpl(DataRefImpl Symb) const23106c3fb27SDimitry Andric uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
23206c3fb27SDimitry Andric return 0;
23306c3fb27SDimitry Andric }
23406c3fb27SDimitry Andric
isSymbolUnresolved(DataRefImpl Symb) const23506c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
23606c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb);
23706c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType;
23806c3fb27SDimitry Andric ESDRecord::getSymbolType(Record, SymbolType);
23906c3fb27SDimitry Andric
24006c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_ExternalReference)
24106c3fb27SDimitry Andric return true;
24206c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_PartReference) {
24306c3fb27SDimitry Andric uint32_t Length;
24406c3fb27SDimitry Andric ESDRecord::getLength(Record, Length);
24506c3fb27SDimitry Andric if (Length == 0)
24606c3fb27SDimitry Andric return true;
24706c3fb27SDimitry Andric }
24806c3fb27SDimitry Andric return false;
24906c3fb27SDimitry Andric }
25006c3fb27SDimitry Andric
isSymbolIndirect(DataRefImpl Symb) const25106c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
25206c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb);
25306c3fb27SDimitry Andric bool Indirect;
25406c3fb27SDimitry Andric ESDRecord::getIndirectReference(Record, Indirect);
25506c3fb27SDimitry Andric return Indirect;
25606c3fb27SDimitry Andric }
25706c3fb27SDimitry Andric
getSymbolFlags(DataRefImpl Symb) const25806c3fb27SDimitry Andric Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
25906c3fb27SDimitry Andric uint32_t Flags = 0;
26006c3fb27SDimitry Andric if (isSymbolUnresolved(Symb))
26106c3fb27SDimitry Andric Flags |= SymbolRef::SF_Undefined;
26206c3fb27SDimitry Andric
26306c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb);
26406c3fb27SDimitry Andric
26506c3fb27SDimitry Andric GOFF::ESDBindingStrength BindingStrength;
26606c3fb27SDimitry Andric ESDRecord::getBindingStrength(Record, BindingStrength);
26706c3fb27SDimitry Andric if (BindingStrength == GOFF::ESD_BST_Weak)
26806c3fb27SDimitry Andric Flags |= SymbolRef::SF_Weak;
26906c3fb27SDimitry Andric
27006c3fb27SDimitry Andric GOFF::ESDBindingScope BindingScope;
27106c3fb27SDimitry Andric ESDRecord::getBindingScope(Record, BindingScope);
27206c3fb27SDimitry Andric
27306c3fb27SDimitry Andric if (BindingScope != GOFF::ESD_BSC_Section) {
27406c3fb27SDimitry Andric Expected<StringRef> Name = getSymbolName(Symb);
27506c3fb27SDimitry Andric if (Name && *Name != " ") { // Blank name is local.
27606c3fb27SDimitry Andric Flags |= SymbolRef::SF_Global;
27706c3fb27SDimitry Andric if (BindingScope == GOFF::ESD_BSC_ImportExport)
27806c3fb27SDimitry Andric Flags |= SymbolRef::SF_Exported;
27906c3fb27SDimitry Andric else if (!(Flags & SymbolRef::SF_Undefined))
28006c3fb27SDimitry Andric Flags |= SymbolRef::SF_Hidden;
28106c3fb27SDimitry Andric }
28206c3fb27SDimitry Andric }
28306c3fb27SDimitry Andric
28406c3fb27SDimitry Andric return Flags;
28506c3fb27SDimitry Andric }
28606c3fb27SDimitry Andric
28706c3fb27SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const28806c3fb27SDimitry Andric GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
28906c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb);
29006c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType;
29106c3fb27SDimitry Andric ESDRecord::getSymbolType(Record, SymbolType);
29206c3fb27SDimitry Andric GOFF::ESDExecutable Executable;
29306c3fb27SDimitry Andric ESDRecord::getExecutable(Record, Executable);
29406c3fb27SDimitry Andric
29506c3fb27SDimitry Andric if (SymbolType != GOFF::ESD_ST_SectionDefinition &&
29606c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_ElementDefinition &&
29706c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_LabelDefinition &&
29806c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_PartReference &&
29906c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_ExternalReference) {
30006c3fb27SDimitry Andric uint32_t EsdId;
30106c3fb27SDimitry Andric ESDRecord::getEsdId(Record, EsdId);
30206c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument,
30306c3fb27SDimitry Andric "ESD record %" PRIu32
30406c3fb27SDimitry Andric " has invalid symbol type 0x%02" PRIX8,
30506c3fb27SDimitry Andric EsdId, SymbolType);
30606c3fb27SDimitry Andric }
30706c3fb27SDimitry Andric switch (SymbolType) {
30806c3fb27SDimitry Andric case GOFF::ESD_ST_SectionDefinition:
30906c3fb27SDimitry Andric case GOFF::ESD_ST_ElementDefinition:
31006c3fb27SDimitry Andric return SymbolRef::ST_Other;
31106c3fb27SDimitry Andric case GOFF::ESD_ST_LabelDefinition:
31206c3fb27SDimitry Andric case GOFF::ESD_ST_PartReference:
31306c3fb27SDimitry Andric case GOFF::ESD_ST_ExternalReference:
31406c3fb27SDimitry Andric if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA &&
31506c3fb27SDimitry Andric Executable != GOFF::ESD_EXE_Unspecified) {
31606c3fb27SDimitry Andric uint32_t EsdId;
31706c3fb27SDimitry Andric ESDRecord::getEsdId(Record, EsdId);
31806c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument,
31906c3fb27SDimitry Andric "ESD record %" PRIu32
32006c3fb27SDimitry Andric " has unknown Executable type 0x%02X",
32106c3fb27SDimitry Andric EsdId, Executable);
32206c3fb27SDimitry Andric }
32306c3fb27SDimitry Andric switch (Executable) {
32406c3fb27SDimitry Andric case GOFF::ESD_EXE_CODE:
32506c3fb27SDimitry Andric return SymbolRef::ST_Function;
32606c3fb27SDimitry Andric case GOFF::ESD_EXE_DATA:
32706c3fb27SDimitry Andric return SymbolRef::ST_Data;
32806c3fb27SDimitry Andric case GOFF::ESD_EXE_Unspecified:
32906c3fb27SDimitry Andric return SymbolRef::ST_Unknown;
33006c3fb27SDimitry Andric }
33106c3fb27SDimitry Andric llvm_unreachable("Unhandled ESDExecutable");
33206c3fb27SDimitry Andric }
33306c3fb27SDimitry Andric llvm_unreachable("Unhandled ESDSymbolType");
33406c3fb27SDimitry Andric }
33506c3fb27SDimitry Andric
33606c3fb27SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const33706c3fb27SDimitry Andric GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
33806c3fb27SDimitry Andric DataRefImpl Sec;
33906c3fb27SDimitry Andric
34006c3fb27SDimitry Andric if (isSymbolUnresolved(Symb))
34106c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this));
34206c3fb27SDimitry Andric
34306c3fb27SDimitry Andric const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];
34406c3fb27SDimitry Andric uint32_t SymEdId;
34506c3fb27SDimitry Andric ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
34606c3fb27SDimitry Andric const uint8_t *SymEdRecord = EsdPtrs[SymEdId];
34706c3fb27SDimitry Andric
34806c3fb27SDimitry Andric for (size_t I = 0, E = SectionList.size(); I < E; ++I) {
34906c3fb27SDimitry Andric bool Found;
35006c3fb27SDimitry Andric const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
35106c3fb27SDimitry Andric if (SectionPrRecord) {
35206c3fb27SDimitry Andric Found = SymEsdRecord == SectionPrRecord;
35306c3fb27SDimitry Andric } else {
35406c3fb27SDimitry Andric const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
35506c3fb27SDimitry Andric Found = SymEdRecord == SectionEdRecord;
35606c3fb27SDimitry Andric }
35706c3fb27SDimitry Andric
35806c3fb27SDimitry Andric if (Found) {
35906c3fb27SDimitry Andric Sec.d.a = I;
36006c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this));
36106c3fb27SDimitry Andric }
36206c3fb27SDimitry Andric }
36306c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument,
36406c3fb27SDimitry Andric "symbol with ESD id " + std::to_string(Symb.d.a) +
36506c3fb27SDimitry Andric " refers to invalid section with ESD id " +
36606c3fb27SDimitry Andric std::to_string(SymEdId));
36706c3fb27SDimitry Andric }
36806c3fb27SDimitry Andric
getSymbolSize(DataRefImpl Symb) const369*0fca6ea1SDimitry Andric uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
370*0fca6ea1SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb);
371*0fca6ea1SDimitry Andric uint32_t Length;
372*0fca6ea1SDimitry Andric ESDRecord::getLength(Record, Length);
373*0fca6ea1SDimitry Andric return Length;
374*0fca6ea1SDimitry Andric }
375*0fca6ea1SDimitry Andric
getSectionEdEsdRecord(DataRefImpl & Sec) const37606c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
37706c3fb27SDimitry Andric SectionEntryImpl EsdIds = SectionList[Sec.d.a];
37806c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
37906c3fb27SDimitry Andric return EsdRecord;
38006c3fb27SDimitry Andric }
38106c3fb27SDimitry Andric
getSectionPrEsdRecord(DataRefImpl & Sec) const38206c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
38306c3fb27SDimitry Andric SectionEntryImpl EsdIds = SectionList[Sec.d.a];
38406c3fb27SDimitry Andric const uint8_t *EsdRecord = nullptr;
38506c3fb27SDimitry Andric if (EsdIds.d.b)
38606c3fb27SDimitry Andric EsdRecord = EsdPtrs[EsdIds.d.b];
38706c3fb27SDimitry Andric return EsdRecord;
38806c3fb27SDimitry Andric }
38906c3fb27SDimitry Andric
39006c3fb27SDimitry Andric const uint8_t *
getSectionEdEsdRecord(uint32_t SectionIndex) const39106c3fb27SDimitry Andric GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
39206c3fb27SDimitry Andric DataRefImpl Sec;
39306c3fb27SDimitry Andric Sec.d.a = SectionIndex;
39406c3fb27SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
39506c3fb27SDimitry Andric return EsdRecord;
39606c3fb27SDimitry Andric }
39706c3fb27SDimitry Andric
39806c3fb27SDimitry Andric const uint8_t *
getSectionPrEsdRecord(uint32_t SectionIndex) const39906c3fb27SDimitry Andric GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
40006c3fb27SDimitry Andric DataRefImpl Sec;
40106c3fb27SDimitry Andric Sec.d.a = SectionIndex;
40206c3fb27SDimitry Andric const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
40306c3fb27SDimitry Andric return EsdRecord;
40406c3fb27SDimitry Andric }
40506c3fb27SDimitry Andric
getSectionDefEsdId(DataRefImpl & Sec) const406*0fca6ea1SDimitry Andric uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
407*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
408*0fca6ea1SDimitry Andric uint32_t Length;
409*0fca6ea1SDimitry Andric ESDRecord::getLength(EsdRecord, Length);
410*0fca6ea1SDimitry Andric if (Length == 0) {
411*0fca6ea1SDimitry Andric const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
412*0fca6ea1SDimitry Andric if (PrEsdRecord)
413*0fca6ea1SDimitry Andric EsdRecord = PrEsdRecord;
414*0fca6ea1SDimitry Andric }
415*0fca6ea1SDimitry Andric
416*0fca6ea1SDimitry Andric uint32_t DefEsdId;
417*0fca6ea1SDimitry Andric ESDRecord::getEsdId(EsdRecord, DefEsdId);
418*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
419*0fca6ea1SDimitry Andric return DefEsdId;
420*0fca6ea1SDimitry Andric }
421*0fca6ea1SDimitry Andric
moveSectionNext(DataRefImpl & Sec) const422*0fca6ea1SDimitry Andric void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
423*0fca6ea1SDimitry Andric Sec.d.a++;
424*0fca6ea1SDimitry Andric if ((Sec.d.a) >= SectionList.size())
425*0fca6ea1SDimitry Andric Sec.d.a = 0;
426*0fca6ea1SDimitry Andric }
427*0fca6ea1SDimitry Andric
getSectionName(DataRefImpl Sec) const428*0fca6ea1SDimitry Andric Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
429*0fca6ea1SDimitry Andric DataRefImpl EdSym;
430*0fca6ea1SDimitry Andric SectionEntryImpl EsdIds = SectionList[Sec.d.a];
431*0fca6ea1SDimitry Andric EdSym.d.a = EsdIds.d.a;
432*0fca6ea1SDimitry Andric Expected<StringRef> Name = getSymbolName(EdSym);
433*0fca6ea1SDimitry Andric if (Name) {
434*0fca6ea1SDimitry Andric StringRef Res = *Name;
435*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
436*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
437*0fca6ea1SDimitry Andric Name = Res;
438*0fca6ea1SDimitry Andric }
439*0fca6ea1SDimitry Andric return Name;
440*0fca6ea1SDimitry Andric }
441*0fca6ea1SDimitry Andric
getSectionAddress(DataRefImpl Sec) const442*0fca6ea1SDimitry Andric uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
443*0fca6ea1SDimitry Andric uint32_t Offset;
444*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
445*0fca6ea1SDimitry Andric ESDRecord::getOffset(EsdRecord, Offset);
446*0fca6ea1SDimitry Andric return Offset;
447*0fca6ea1SDimitry Andric }
448*0fca6ea1SDimitry Andric
getSectionSize(DataRefImpl Sec) const449*0fca6ea1SDimitry Andric uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
450*0fca6ea1SDimitry Andric uint32_t Length;
451*0fca6ea1SDimitry Andric uint32_t DefEsdId = getSectionDefEsdId(Sec);
452*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
453*0fca6ea1SDimitry Andric ESDRecord::getLength(EsdRecord, Length);
454*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
455*0fca6ea1SDimitry Andric return static_cast<uint64_t>(Length);
456*0fca6ea1SDimitry Andric }
457*0fca6ea1SDimitry Andric
458*0fca6ea1SDimitry Andric // Unravel TXT records and expand fill characters to produce
459*0fca6ea1SDimitry Andric // a contiguous sequence of bytes.
460*0fca6ea1SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const461*0fca6ea1SDimitry Andric GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
462*0fca6ea1SDimitry Andric if (SectionDataCache.count(Sec.d.a)) {
463*0fca6ea1SDimitry Andric auto &Buf = SectionDataCache[Sec.d.a];
464*0fca6ea1SDimitry Andric return ArrayRef<uint8_t>(Buf);
465*0fca6ea1SDimitry Andric }
466*0fca6ea1SDimitry Andric uint64_t SectionSize = getSectionSize(Sec);
467*0fca6ea1SDimitry Andric uint32_t DefEsdId = getSectionDefEsdId(Sec);
468*0fca6ea1SDimitry Andric
469*0fca6ea1SDimitry Andric const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
470*0fca6ea1SDimitry Andric bool FillBytePresent;
471*0fca6ea1SDimitry Andric ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
472*0fca6ea1SDimitry Andric uint8_t FillByte = '\0';
473*0fca6ea1SDimitry Andric if (FillBytePresent)
474*0fca6ea1SDimitry Andric ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
475*0fca6ea1SDimitry Andric
476*0fca6ea1SDimitry Andric // Initialize section with fill byte.
477*0fca6ea1SDimitry Andric SmallVector<uint8_t> Data(SectionSize, FillByte);
478*0fca6ea1SDimitry Andric
479*0fca6ea1SDimitry Andric // Replace section with content from text records.
480*0fca6ea1SDimitry Andric for (const uint8_t *TxtRecordInt : TextPtrs) {
481*0fca6ea1SDimitry Andric const uint8_t *TxtRecordPtr = TxtRecordInt;
482*0fca6ea1SDimitry Andric uint32_t TxtEsdId;
483*0fca6ea1SDimitry Andric TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
484*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
485*0fca6ea1SDimitry Andric
486*0fca6ea1SDimitry Andric if (TxtEsdId != DefEsdId)
487*0fca6ea1SDimitry Andric continue;
488*0fca6ea1SDimitry Andric
489*0fca6ea1SDimitry Andric uint32_t TxtDataOffset;
490*0fca6ea1SDimitry Andric TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
491*0fca6ea1SDimitry Andric
492*0fca6ea1SDimitry Andric uint16_t TxtDataSize;
493*0fca6ea1SDimitry Andric TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
494*0fca6ea1SDimitry Andric
495*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
496*0fca6ea1SDimitry Andric << TxtDataSize << "\n");
497*0fca6ea1SDimitry Andric
498*0fca6ea1SDimitry Andric SmallString<256> CompleteData;
499*0fca6ea1SDimitry Andric CompleteData.reserve(TxtDataSize);
500*0fca6ea1SDimitry Andric if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData))
501*0fca6ea1SDimitry Andric return std::move(Err);
502*0fca6ea1SDimitry Andric assert(CompleteData.size() == TxtDataSize && "Wrong length of data");
503*0fca6ea1SDimitry Andric std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,
504*0fca6ea1SDimitry Andric Data.begin() + TxtDataOffset);
505*0fca6ea1SDimitry Andric }
506*0fca6ea1SDimitry Andric SectionDataCache[Sec.d.a] = Data;
507*0fca6ea1SDimitry Andric return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]);
508*0fca6ea1SDimitry Andric }
509*0fca6ea1SDimitry Andric
getSectionAlignment(DataRefImpl Sec) const510*0fca6ea1SDimitry Andric uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
511*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
512*0fca6ea1SDimitry Andric GOFF::ESDAlignment Pow2Alignment;
513*0fca6ea1SDimitry Andric ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
514*0fca6ea1SDimitry Andric return 1ULL << static_cast<uint64_t>(Pow2Alignment);
515*0fca6ea1SDimitry Andric }
516*0fca6ea1SDimitry Andric
isSectionText(DataRefImpl Sec) const517*0fca6ea1SDimitry Andric bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
518*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
519*0fca6ea1SDimitry Andric GOFF::ESDExecutable Executable;
520*0fca6ea1SDimitry Andric ESDRecord::getExecutable(EsdRecord, Executable);
521*0fca6ea1SDimitry Andric return Executable == GOFF::ESD_EXE_CODE;
522*0fca6ea1SDimitry Andric }
523*0fca6ea1SDimitry Andric
isSectionData(DataRefImpl Sec) const524*0fca6ea1SDimitry Andric bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
525*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
526*0fca6ea1SDimitry Andric GOFF::ESDExecutable Executable;
527*0fca6ea1SDimitry Andric ESDRecord::getExecutable(EsdRecord, Executable);
528*0fca6ea1SDimitry Andric return Executable == GOFF::ESD_EXE_DATA;
529*0fca6ea1SDimitry Andric }
530*0fca6ea1SDimitry Andric
isSectionNoLoad(DataRefImpl Sec) const531*0fca6ea1SDimitry Andric bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const {
532*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
533*0fca6ea1SDimitry Andric GOFF::ESDLoadingBehavior LoadingBehavior;
534*0fca6ea1SDimitry Andric ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
535*0fca6ea1SDimitry Andric return LoadingBehavior == GOFF::ESD_LB_NoLoad;
536*0fca6ea1SDimitry Andric }
537*0fca6ea1SDimitry Andric
isSectionReadOnlyData(DataRefImpl Sec) const538*0fca6ea1SDimitry Andric bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
539*0fca6ea1SDimitry Andric if (!isSectionData(Sec))
540*0fca6ea1SDimitry Andric return false;
541*0fca6ea1SDimitry Andric
542*0fca6ea1SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
543*0fca6ea1SDimitry Andric GOFF::ESDLoadingBehavior LoadingBehavior;
544*0fca6ea1SDimitry Andric ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
545*0fca6ea1SDimitry Andric return LoadingBehavior == GOFF::ESD_LB_Initial;
546*0fca6ea1SDimitry Andric }
547*0fca6ea1SDimitry Andric
isSectionZeroInit(DataRefImpl Sec) const548*0fca6ea1SDimitry Andric bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
549*0fca6ea1SDimitry Andric // GOFF uses fill characters and fill characters are applied
550*0fca6ea1SDimitry Andric // on getSectionContents() - so we say false to zero init.
551*0fca6ea1SDimitry Andric return false;
552*0fca6ea1SDimitry Andric }
553*0fca6ea1SDimitry Andric
section_begin() const55406c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_begin() const {
55506c3fb27SDimitry Andric DataRefImpl Sec;
55606c3fb27SDimitry Andric moveSectionNext(Sec);
55706c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this));
55806c3fb27SDimitry Andric }
55906c3fb27SDimitry Andric
section_end() const56006c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_end() const {
56106c3fb27SDimitry Andric DataRefImpl Sec;
56206c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this));
56306c3fb27SDimitry Andric }
56406c3fb27SDimitry Andric
moveSymbolNext(DataRefImpl & Symb) const56506c3fb27SDimitry Andric void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
56606c3fb27SDimitry Andric for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {
56706c3fb27SDimitry Andric if (EsdPtrs[I]) {
56806c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[I];
56906c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType;
57006c3fb27SDimitry Andric ESDRecord::getSymbolType(EsdRecord, SymbolType);
57106c3fb27SDimitry Andric // Skip EDs - i.e. section symbols.
57206c3fb27SDimitry Andric bool IgnoreSpecialGOFFSymbols = true;
57306c3fb27SDimitry Andric bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
57406c3fb27SDimitry Andric (SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
57506c3fb27SDimitry Andric IgnoreSpecialGOFFSymbols;
57606c3fb27SDimitry Andric if (!SkipSymbol) {
57706c3fb27SDimitry Andric Symb.d.a = I;
57806c3fb27SDimitry Andric return;
57906c3fb27SDimitry Andric }
58006c3fb27SDimitry Andric }
58106c3fb27SDimitry Andric }
58206c3fb27SDimitry Andric Symb.d.a = 0;
58306c3fb27SDimitry Andric }
58406c3fb27SDimitry Andric
symbol_begin() const58506c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
58606c3fb27SDimitry Andric DataRefImpl Symb;
58706c3fb27SDimitry Andric moveSymbolNext(Symb);
58806c3fb27SDimitry Andric return basic_symbol_iterator(SymbolRef(Symb, this));
58906c3fb27SDimitry Andric }
59006c3fb27SDimitry Andric
symbol_end() const59106c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_end() const {
59206c3fb27SDimitry Andric DataRefImpl Symb;
59306c3fb27SDimitry Andric return basic_symbol_iterator(SymbolRef(Symb, this));
59406c3fb27SDimitry Andric }
59506c3fb27SDimitry Andric
getContinuousData(const uint8_t * Record,uint16_t DataLength,int DataIndex,SmallString<256> & CompleteData)59606c3fb27SDimitry Andric Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength,
59706c3fb27SDimitry Andric int DataIndex, SmallString<256> &CompleteData) {
59806c3fb27SDimitry Andric // First record.
59906c3fb27SDimitry Andric const uint8_t *Slice = Record + DataIndex;
60006c3fb27SDimitry Andric size_t SliceLength =
60106c3fb27SDimitry Andric std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex));
60206c3fb27SDimitry Andric CompleteData.append(Slice, Slice + SliceLength);
60306c3fb27SDimitry Andric DataLength -= SliceLength;
60406c3fb27SDimitry Andric Slice += SliceLength;
60506c3fb27SDimitry Andric
60606c3fb27SDimitry Andric // Continuation records.
60706c3fb27SDimitry Andric for (; DataLength > 0;
60806c3fb27SDimitry Andric DataLength -= SliceLength, Slice += GOFF::PayloadLength) {
60906c3fb27SDimitry Andric // Slice points to the start of the new record.
61006c3fb27SDimitry Andric // Check that this block is a Continuation.
61106c3fb27SDimitry Andric assert(Record::isContinuation(Slice) && "Continuation bit must be set");
61206c3fb27SDimitry Andric // Check that the last Continuation is terminated correctly.
61306c3fb27SDimitry Andric if (DataLength <= 77 && Record::isContinued(Slice))
61406c3fb27SDimitry Andric return createStringError(object_error::parse_failed,
61506c3fb27SDimitry Andric "continued bit should not be set");
61606c3fb27SDimitry Andric
61706c3fb27SDimitry Andric SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength);
61806c3fb27SDimitry Andric Slice += GOFF::RecordPrefixLength;
61906c3fb27SDimitry Andric CompleteData.append(Slice, Slice + SliceLength);
62006c3fb27SDimitry Andric }
62106c3fb27SDimitry Andric return Error::success();
62206c3fb27SDimitry Andric }
62306c3fb27SDimitry Andric
getData(const uint8_t * Record,SmallString<256> & CompleteData)62406c3fb27SDimitry Andric Error HDRRecord::getData(const uint8_t *Record,
62506c3fb27SDimitry Andric SmallString<256> &CompleteData) {
62606c3fb27SDimitry Andric uint16_t Length = getPropertyModuleLength(Record);
62706c3fb27SDimitry Andric return getContinuousData(Record, Length, 60, CompleteData);
62806c3fb27SDimitry Andric }
62906c3fb27SDimitry Andric
getData(const uint8_t * Record,SmallString<256> & CompleteData)63006c3fb27SDimitry Andric Error ESDRecord::getData(const uint8_t *Record,
63106c3fb27SDimitry Andric SmallString<256> &CompleteData) {
63206c3fb27SDimitry Andric uint16_t DataSize = getNameLength(Record);
63306c3fb27SDimitry Andric return getContinuousData(Record, DataSize, 72, CompleteData);
63406c3fb27SDimitry Andric }
63506c3fb27SDimitry Andric
getData(const uint8_t * Record,SmallString<256> & CompleteData)636*0fca6ea1SDimitry Andric Error TXTRecord::getData(const uint8_t *Record,
637*0fca6ea1SDimitry Andric SmallString<256> &CompleteData) {
638*0fca6ea1SDimitry Andric uint16_t Length;
639*0fca6ea1SDimitry Andric getDataLength(Record, Length);
640*0fca6ea1SDimitry Andric return getContinuousData(Record, Length, 24, CompleteData);
641*0fca6ea1SDimitry Andric }
642*0fca6ea1SDimitry Andric
getData(const uint8_t * Record,SmallString<256> & CompleteData)64306c3fb27SDimitry Andric Error ENDRecord::getData(const uint8_t *Record,
64406c3fb27SDimitry Andric SmallString<256> &CompleteData) {
64506c3fb27SDimitry Andric uint16_t Length = getNameLength(Record);
64606c3fb27SDimitry Andric return getContinuousData(Record, Length, 26, CompleteData);
64706c3fb27SDimitry Andric }
648