xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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>>
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 
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 
18706c3fb27SDimitry 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 
19206c3fb27SDimitry 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 
21306c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const {
21406c3fb27SDimitry Andric   return getSymbolName(Symbol.getRawDataRefImpl());
21506c3fb27SDimitry Andric }
21606c3fb27SDimitry Andric 
21706c3fb27SDimitry 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 
22406c3fb27SDimitry 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 
23106c3fb27SDimitry Andric uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
23206c3fb27SDimitry Andric   return 0;
23306c3fb27SDimitry Andric }
23406c3fb27SDimitry Andric 
23506c3fb27SDimitry 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 
25106c3fb27SDimitry 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 
25806c3fb27SDimitry 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>
28806c3fb27SDimitry 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>
33706c3fb27SDimitry 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 
369*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 
37606c3fb27SDimitry 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 
38206c3fb27SDimitry 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 *
39106c3fb27SDimitry 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 *
39906c3fb27SDimitry 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 
406*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 
422*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 
428*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 
442*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 
449*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>>
461*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 
510*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 
517*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 
524*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 
531*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 
538*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 
548*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 
55406c3fb27SDimitry 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 
56006c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_end() const {
56106c3fb27SDimitry Andric   DataRefImpl Sec;
56206c3fb27SDimitry Andric   return section_iterator(SectionRef(Sec, this));
56306c3fb27SDimitry Andric }
56406c3fb27SDimitry Andric 
56506c3fb27SDimitry 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 
58506c3fb27SDimitry 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 
59106c3fb27SDimitry 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 
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 
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 
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 
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 
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