12fa6bcf0SYusra Syeda //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===// 22fa6bcf0SYusra Syeda // 32fa6bcf0SYusra Syeda // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42fa6bcf0SYusra Syeda // See https://llvm.org/LICENSE.txt for license information. 52fa6bcf0SYusra Syeda // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62fa6bcf0SYusra Syeda // 72fa6bcf0SYusra Syeda //===----------------------------------------------------------------------===// 82fa6bcf0SYusra Syeda // 92fa6bcf0SYusra Syeda // Implementation of the GOFFObjectFile class. 102fa6bcf0SYusra Syeda // 112fa6bcf0SYusra Syeda //===----------------------------------------------------------------------===// 122fa6bcf0SYusra Syeda 132fa6bcf0SYusra Syeda #include "llvm/Object/GOFFObjectFile.h" 142fa6bcf0SYusra Syeda #include "llvm/BinaryFormat/GOFF.h" 152fa6bcf0SYusra Syeda #include "llvm/Object/GOFF.h" 162fa6bcf0SYusra Syeda #include "llvm/Support/Debug.h" 172fa6bcf0SYusra Syeda #include "llvm/Support/Errc.h" 182fa6bcf0SYusra Syeda #include "llvm/Support/raw_ostream.h" 192fa6bcf0SYusra Syeda 202fa6bcf0SYusra Syeda #ifndef DEBUG_TYPE 212fa6bcf0SYusra Syeda #define DEBUG_TYPE "goff" 222fa6bcf0SYusra Syeda #endif 232fa6bcf0SYusra Syeda 242fa6bcf0SYusra Syeda using namespace llvm::object; 252fa6bcf0SYusra Syeda using namespace llvm; 262fa6bcf0SYusra Syeda 272fa6bcf0SYusra Syeda Expected<std::unique_ptr<ObjectFile>> 282fa6bcf0SYusra Syeda ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) { 292fa6bcf0SYusra Syeda Error Err = Error::success(); 302fa6bcf0SYusra Syeda std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err)); 312fa6bcf0SYusra Syeda if (Err) 322fa6bcf0SYusra Syeda return std::move(Err); 332fa6bcf0SYusra Syeda return std::move(Ret); 342fa6bcf0SYusra Syeda } 352fa6bcf0SYusra Syeda 362fa6bcf0SYusra Syeda GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) 372fa6bcf0SYusra Syeda : ObjectFile(Binary::ID_GOFF, Object) { 38d02c1676SLang Hames ErrorAsOutParameter ErrAsOutParam(Err); 392fa6bcf0SYusra Syeda // Object file isn't the right size, bail out early. 402fa6bcf0SYusra Syeda if ((Object.getBufferSize() % GOFF::RecordLength) != 0) { 412fa6bcf0SYusra Syeda Err = createStringError( 422fa6bcf0SYusra Syeda object_error::unexpected_eof, 432fa6bcf0SYusra Syeda "object file is not the right size. Must be a multiple " 442fa6bcf0SYusra Syeda "of 80 bytes, but is " + 452fa6bcf0SYusra Syeda std::to_string(Object.getBufferSize()) + " bytes"); 462fa6bcf0SYusra Syeda return; 472fa6bcf0SYusra Syeda } 482fa6bcf0SYusra Syeda // Object file doesn't start/end with HDR/END records. 492fa6bcf0SYusra Syeda // Bail out early. 502fa6bcf0SYusra Syeda if (Object.getBufferSize() != 0) { 512fa6bcf0SYusra Syeda if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) { 522fa6bcf0SYusra Syeda Err = createStringError(object_error::parse_failed, 532fa6bcf0SYusra Syeda "object file must start with HDR record"); 542fa6bcf0SYusra Syeda return; 552fa6bcf0SYusra Syeda } 562fa6bcf0SYusra Syeda if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 != 572fa6bcf0SYusra Syeda GOFF::RT_END) { 582fa6bcf0SYusra Syeda Err = createStringError(object_error::parse_failed, 592fa6bcf0SYusra Syeda "object file must end with END record"); 602fa6bcf0SYusra Syeda return; 612fa6bcf0SYusra Syeda } 622fa6bcf0SYusra Syeda } 632fa6bcf0SYusra Syeda 642fa6bcf0SYusra Syeda SectionEntryImpl DummySection; 652fa6bcf0SYusra Syeda SectionList.emplace_back(DummySection); // Dummy entry at index 0. 662fa6bcf0SYusra Syeda 672fa6bcf0SYusra Syeda uint8_t PrevRecordType = 0; 682fa6bcf0SYusra Syeda uint8_t PrevContinuationBits = 0; 692fa6bcf0SYusra Syeda const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd()); 702fa6bcf0SYusra Syeda for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) { 712fa6bcf0SYusra Syeda uint8_t RecordType = (I[1] & 0xF0) >> 4; 722fa6bcf0SYusra Syeda bool IsContinuation = I[1] & 0x02; 732fa6bcf0SYusra Syeda bool PrevWasContinued = PrevContinuationBits & 0x01; 742fa6bcf0SYusra Syeda size_t RecordNum = (I - base()) / GOFF::RecordLength; 752fa6bcf0SYusra Syeda 762fa6bcf0SYusra Syeda // If the previous record was continued, the current record should be a 772fa6bcf0SYusra Syeda // continuation. 782fa6bcf0SYusra Syeda if (PrevWasContinued && !IsContinuation) { 792fa6bcf0SYusra Syeda if (PrevRecordType == RecordType) { 802fa6bcf0SYusra Syeda Err = createStringError(object_error::parse_failed, 812fa6bcf0SYusra Syeda "record " + std::to_string(RecordNum) + 822fa6bcf0SYusra Syeda " is not a continuation record but the " 832fa6bcf0SYusra Syeda "preceding record is continued"); 842fa6bcf0SYusra Syeda return; 852fa6bcf0SYusra Syeda } 862fa6bcf0SYusra Syeda } 872fa6bcf0SYusra Syeda // Don't parse continuations records, only parse initial record. 882fa6bcf0SYusra Syeda if (IsContinuation) { 892fa6bcf0SYusra Syeda if (RecordType != PrevRecordType) { 902fa6bcf0SYusra Syeda Err = createStringError(object_error::parse_failed, 912fa6bcf0SYusra Syeda "record " + std::to_string(RecordNum) + 922fa6bcf0SYusra Syeda " is a continuation record that does not " 932fa6bcf0SYusra Syeda "match the type of the previous record"); 942fa6bcf0SYusra Syeda return; 952fa6bcf0SYusra Syeda } 962fa6bcf0SYusra Syeda if (!PrevWasContinued) { 972fa6bcf0SYusra Syeda Err = createStringError(object_error::parse_failed, 982fa6bcf0SYusra Syeda "record " + std::to_string(RecordNum) + 992fa6bcf0SYusra Syeda " is a continuation record that is not " 1002fa6bcf0SYusra Syeda "preceded by a continued record"); 1012fa6bcf0SYusra Syeda return; 1022fa6bcf0SYusra Syeda } 1032fa6bcf0SYusra Syeda PrevRecordType = RecordType; 1042fa6bcf0SYusra Syeda PrevContinuationBits = I[1] & 0x03; 1052fa6bcf0SYusra Syeda continue; 1062fa6bcf0SYusra Syeda } 1076634c3e9SKai Nacke LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) { 1082fa6bcf0SYusra Syeda const uint8_t *P = I + J; 1092fa6bcf0SYusra Syeda if (J % 8 == 0) 11078ceb39bSNAKAMURA Takumi dbgs() << " "; 11178ceb39bSNAKAMURA Takumi dbgs() << format("%02hhX", *P); 1126634c3e9SKai Nacke }); 1136634c3e9SKai Nacke 1142fa6bcf0SYusra Syeda switch (RecordType) { 1152fa6bcf0SYusra Syeda case GOFF::RT_ESD: { 1162fa6bcf0SYusra Syeda // Save ESD record. 1172fa6bcf0SYusra Syeda uint32_t EsdId; 1182fa6bcf0SYusra Syeda ESDRecord::getEsdId(I, EsdId); 1192fa6bcf0SYusra Syeda EsdPtrs.grow(EsdId); 1202fa6bcf0SYusra Syeda EsdPtrs[EsdId] = I; 1212fa6bcf0SYusra Syeda 1222fa6bcf0SYusra Syeda // Determine and save the "sections" in GOFF. 1232fa6bcf0SYusra Syeda // A section is saved as a tuple of the form 1242fa6bcf0SYusra Syeda // case (1): (ED,child PR) 1252fa6bcf0SYusra Syeda // - where the PR must have non-zero length. 1262fa6bcf0SYusra Syeda // case (2a) (ED,0) 1272fa6bcf0SYusra Syeda // - where the ED is of non-zero length. 1282fa6bcf0SYusra Syeda // case (2b) (ED,0) 1292fa6bcf0SYusra Syeda // - where the ED is zero length but 1302fa6bcf0SYusra Syeda // contains a label (LD). 1312fa6bcf0SYusra Syeda GOFF::ESDSymbolType SymbolType; 1322fa6bcf0SYusra Syeda ESDRecord::getSymbolType(I, SymbolType); 1332fa6bcf0SYusra Syeda SectionEntryImpl Section; 1342fa6bcf0SYusra Syeda uint32_t Length; 1352fa6bcf0SYusra Syeda ESDRecord::getLength(I, Length); 1362fa6bcf0SYusra Syeda if (SymbolType == GOFF::ESD_ST_ElementDefinition) { 1372fa6bcf0SYusra Syeda // case (2a) 1382fa6bcf0SYusra Syeda if (Length != 0) { 1392fa6bcf0SYusra Syeda Section.d.a = EsdId; 1402fa6bcf0SYusra Syeda SectionList.emplace_back(Section); 1412fa6bcf0SYusra Syeda } 1422fa6bcf0SYusra Syeda } else if (SymbolType == GOFF::ESD_ST_PartReference) { 1432fa6bcf0SYusra Syeda // case (1) 1442fa6bcf0SYusra Syeda if (Length != 0) { 1452fa6bcf0SYusra Syeda uint32_t SymEdId; 1462fa6bcf0SYusra Syeda ESDRecord::getParentEsdId(I, SymEdId); 1472fa6bcf0SYusra Syeda Section.d.a = SymEdId; 1482fa6bcf0SYusra Syeda Section.d.b = EsdId; 1492fa6bcf0SYusra Syeda SectionList.emplace_back(Section); 1502fa6bcf0SYusra Syeda } 1512fa6bcf0SYusra Syeda } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) { 1522fa6bcf0SYusra Syeda // case (2b) 1532fa6bcf0SYusra Syeda uint32_t SymEdId; 1542fa6bcf0SYusra Syeda ESDRecord::getParentEsdId(I, SymEdId); 1552fa6bcf0SYusra Syeda const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 1562fa6bcf0SYusra Syeda uint32_t EdLength; 1572fa6bcf0SYusra Syeda ESDRecord::getLength(SymEdRecord, EdLength); 1582fa6bcf0SYusra Syeda if (!EdLength) { // [ EDID, PRID ] 1592fa6bcf0SYusra Syeda // LD child of a zero length parent ED. 1602fa6bcf0SYusra Syeda // Add the section ED which was previously ignored. 1612fa6bcf0SYusra Syeda Section.d.a = SymEdId; 1622fa6bcf0SYusra Syeda SectionList.emplace_back(Section); 1632fa6bcf0SYusra Syeda } 1642fa6bcf0SYusra Syeda } 1652fa6bcf0SYusra Syeda LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); 1662fa6bcf0SYusra Syeda break; 1672fa6bcf0SYusra Syeda } 1684c718fdbSYusra Syeda case GOFF::RT_TXT: 1694c718fdbSYusra Syeda // Save TXT records. 1704c718fdbSYusra Syeda TextPtrs.emplace_back(I); 1714c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << " -- TXT\n"); 1724c718fdbSYusra Syeda break; 1732fa6bcf0SYusra Syeda case GOFF::RT_END: 1742fa6bcf0SYusra Syeda LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); 1752fa6bcf0SYusra Syeda break; 1762fa6bcf0SYusra Syeda case GOFF::RT_HDR: 1772fa6bcf0SYusra Syeda LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n"); 1782fa6bcf0SYusra Syeda break; 1792fa6bcf0SYusra Syeda default: 1802fa6bcf0SYusra Syeda llvm_unreachable("Unknown record type"); 1812fa6bcf0SYusra Syeda } 1822fa6bcf0SYusra Syeda PrevRecordType = RecordType; 1832fa6bcf0SYusra Syeda PrevContinuationBits = I[1] & 0x03; 1842fa6bcf0SYusra Syeda } 1852fa6bcf0SYusra Syeda } 1862fa6bcf0SYusra Syeda 1872fa6bcf0SYusra Syeda const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const { 1882fa6bcf0SYusra Syeda const uint8_t *EsdRecord = EsdPtrs[Symb.d.a]; 1892fa6bcf0SYusra Syeda return EsdRecord; 1902fa6bcf0SYusra Syeda } 1912fa6bcf0SYusra Syeda 1922fa6bcf0SYusra Syeda Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 193*3f1be86aSKazu Hirata if (auto It = EsdNamesCache.find(Symb.d.a); It != EsdNamesCache.end()) { 194*3f1be86aSKazu Hirata auto &StrPtr = It->second; 1952fa6bcf0SYusra Syeda return StringRef(StrPtr.second.get(), StrPtr.first); 1962fa6bcf0SYusra Syeda } 1972fa6bcf0SYusra Syeda 1982fa6bcf0SYusra Syeda SmallString<256> SymbolName; 1992fa6bcf0SYusra Syeda if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName)) 2002fa6bcf0SYusra Syeda return std::move(Err); 2012fa6bcf0SYusra Syeda 2022fa6bcf0SYusra Syeda SmallString<256> SymbolNameConverted; 20302bc772dSJie Fu ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted); 2042fa6bcf0SYusra Syeda 2052fa6bcf0SYusra Syeda size_t Size = SymbolNameConverted.size(); 2062fa6bcf0SYusra Syeda auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size)); 2072fa6bcf0SYusra Syeda char *Buf = StrPtr.second.get(); 2082fa6bcf0SYusra Syeda memcpy(Buf, SymbolNameConverted.data(), Size); 2092fa6bcf0SYusra Syeda EsdNamesCache[Symb.d.a] = std::move(StrPtr); 2102fa6bcf0SYusra Syeda return StringRef(Buf, Size); 2112fa6bcf0SYusra Syeda } 2122fa6bcf0SYusra Syeda 2132fa6bcf0SYusra Syeda Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const { 2142fa6bcf0SYusra Syeda return getSymbolName(Symbol.getRawDataRefImpl()); 2152fa6bcf0SYusra Syeda } 2162fa6bcf0SYusra Syeda 2172fa6bcf0SYusra Syeda Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 2182fa6bcf0SYusra Syeda uint32_t Offset; 2192fa6bcf0SYusra Syeda const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 2202fa6bcf0SYusra Syeda ESDRecord::getOffset(EsdRecord, Offset); 2212fa6bcf0SYusra Syeda return static_cast<uint64_t>(Offset); 2222fa6bcf0SYusra Syeda } 2232fa6bcf0SYusra Syeda 2242fa6bcf0SYusra Syeda uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 2252fa6bcf0SYusra Syeda uint32_t Offset; 2262fa6bcf0SYusra Syeda const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 2272fa6bcf0SYusra Syeda ESDRecord::getOffset(EsdRecord, Offset); 2282fa6bcf0SYusra Syeda return static_cast<uint64_t>(Offset); 2292fa6bcf0SYusra Syeda } 2302fa6bcf0SYusra Syeda 2312fa6bcf0SYusra Syeda uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 2322fa6bcf0SYusra Syeda return 0; 2332fa6bcf0SYusra Syeda } 2342fa6bcf0SYusra Syeda 2352fa6bcf0SYusra Syeda bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const { 2362fa6bcf0SYusra Syeda const uint8_t *Record = getSymbolEsdRecord(Symb); 2372fa6bcf0SYusra Syeda GOFF::ESDSymbolType SymbolType; 2382fa6bcf0SYusra Syeda ESDRecord::getSymbolType(Record, SymbolType); 2392fa6bcf0SYusra Syeda 2402fa6bcf0SYusra Syeda if (SymbolType == GOFF::ESD_ST_ExternalReference) 2412fa6bcf0SYusra Syeda return true; 2422fa6bcf0SYusra Syeda if (SymbolType == GOFF::ESD_ST_PartReference) { 2432fa6bcf0SYusra Syeda uint32_t Length; 2442fa6bcf0SYusra Syeda ESDRecord::getLength(Record, Length); 2452fa6bcf0SYusra Syeda if (Length == 0) 2462fa6bcf0SYusra Syeda return true; 2472fa6bcf0SYusra Syeda } 2482fa6bcf0SYusra Syeda return false; 2492fa6bcf0SYusra Syeda } 2502fa6bcf0SYusra Syeda 2512fa6bcf0SYusra Syeda bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const { 2522fa6bcf0SYusra Syeda const uint8_t *Record = getSymbolEsdRecord(Symb); 2532fa6bcf0SYusra Syeda bool Indirect; 2542fa6bcf0SYusra Syeda ESDRecord::getIndirectReference(Record, Indirect); 2552fa6bcf0SYusra Syeda return Indirect; 2562fa6bcf0SYusra Syeda } 2572fa6bcf0SYusra Syeda 2582fa6bcf0SYusra Syeda Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 2592fa6bcf0SYusra Syeda uint32_t Flags = 0; 2602fa6bcf0SYusra Syeda if (isSymbolUnresolved(Symb)) 2612fa6bcf0SYusra Syeda Flags |= SymbolRef::SF_Undefined; 2622fa6bcf0SYusra Syeda 2632fa6bcf0SYusra Syeda const uint8_t *Record = getSymbolEsdRecord(Symb); 2642fa6bcf0SYusra Syeda 2652fa6bcf0SYusra Syeda GOFF::ESDBindingStrength BindingStrength; 2662fa6bcf0SYusra Syeda ESDRecord::getBindingStrength(Record, BindingStrength); 2672fa6bcf0SYusra Syeda if (BindingStrength == GOFF::ESD_BST_Weak) 2682fa6bcf0SYusra Syeda Flags |= SymbolRef::SF_Weak; 2692fa6bcf0SYusra Syeda 2702fa6bcf0SYusra Syeda GOFF::ESDBindingScope BindingScope; 2712fa6bcf0SYusra Syeda ESDRecord::getBindingScope(Record, BindingScope); 2722fa6bcf0SYusra Syeda 2732fa6bcf0SYusra Syeda if (BindingScope != GOFF::ESD_BSC_Section) { 2742fa6bcf0SYusra Syeda Expected<StringRef> Name = getSymbolName(Symb); 2752fa6bcf0SYusra Syeda if (Name && *Name != " ") { // Blank name is local. 2762fa6bcf0SYusra Syeda Flags |= SymbolRef::SF_Global; 2772fa6bcf0SYusra Syeda if (BindingScope == GOFF::ESD_BSC_ImportExport) 2782fa6bcf0SYusra Syeda Flags |= SymbolRef::SF_Exported; 2792fa6bcf0SYusra Syeda else if (!(Flags & SymbolRef::SF_Undefined)) 2802fa6bcf0SYusra Syeda Flags |= SymbolRef::SF_Hidden; 2812fa6bcf0SYusra Syeda } 2822fa6bcf0SYusra Syeda } 2832fa6bcf0SYusra Syeda 2842fa6bcf0SYusra Syeda return Flags; 2852fa6bcf0SYusra Syeda } 2862fa6bcf0SYusra Syeda 2872fa6bcf0SYusra Syeda Expected<SymbolRef::Type> 2882fa6bcf0SYusra Syeda GOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 2892fa6bcf0SYusra Syeda const uint8_t *Record = getSymbolEsdRecord(Symb); 2902fa6bcf0SYusra Syeda GOFF::ESDSymbolType SymbolType; 2912fa6bcf0SYusra Syeda ESDRecord::getSymbolType(Record, SymbolType); 2922fa6bcf0SYusra Syeda GOFF::ESDExecutable Executable; 2932fa6bcf0SYusra Syeda ESDRecord::getExecutable(Record, Executable); 2942fa6bcf0SYusra Syeda 2952fa6bcf0SYusra Syeda if (SymbolType != GOFF::ESD_ST_SectionDefinition && 2962fa6bcf0SYusra Syeda SymbolType != GOFF::ESD_ST_ElementDefinition && 2972fa6bcf0SYusra Syeda SymbolType != GOFF::ESD_ST_LabelDefinition && 2982fa6bcf0SYusra Syeda SymbolType != GOFF::ESD_ST_PartReference && 2992fa6bcf0SYusra Syeda SymbolType != GOFF::ESD_ST_ExternalReference) { 3002fa6bcf0SYusra Syeda uint32_t EsdId; 3012fa6bcf0SYusra Syeda ESDRecord::getEsdId(Record, EsdId); 3022fa6bcf0SYusra Syeda return createStringError(llvm::errc::invalid_argument, 3032fa6bcf0SYusra Syeda "ESD record %" PRIu32 3042fa6bcf0SYusra Syeda " has invalid symbol type 0x%02" PRIX8, 3052fa6bcf0SYusra Syeda EsdId, SymbolType); 3062fa6bcf0SYusra Syeda } 3072fa6bcf0SYusra Syeda switch (SymbolType) { 3082fa6bcf0SYusra Syeda case GOFF::ESD_ST_SectionDefinition: 3092fa6bcf0SYusra Syeda case GOFF::ESD_ST_ElementDefinition: 3102fa6bcf0SYusra Syeda return SymbolRef::ST_Other; 3112fa6bcf0SYusra Syeda case GOFF::ESD_ST_LabelDefinition: 3122fa6bcf0SYusra Syeda case GOFF::ESD_ST_PartReference: 3132fa6bcf0SYusra Syeda case GOFF::ESD_ST_ExternalReference: 3142fa6bcf0SYusra Syeda if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA && 3152fa6bcf0SYusra Syeda Executable != GOFF::ESD_EXE_Unspecified) { 3162fa6bcf0SYusra Syeda uint32_t EsdId; 3172fa6bcf0SYusra Syeda ESDRecord::getEsdId(Record, EsdId); 3182fa6bcf0SYusra Syeda return createStringError(llvm::errc::invalid_argument, 3192fa6bcf0SYusra Syeda "ESD record %" PRIu32 3202fa6bcf0SYusra Syeda " has unknown Executable type 0x%02X", 3212fa6bcf0SYusra Syeda EsdId, Executable); 3222fa6bcf0SYusra Syeda } 3232fa6bcf0SYusra Syeda switch (Executable) { 3242fa6bcf0SYusra Syeda case GOFF::ESD_EXE_CODE: 3252fa6bcf0SYusra Syeda return SymbolRef::ST_Function; 3262fa6bcf0SYusra Syeda case GOFF::ESD_EXE_DATA: 3272fa6bcf0SYusra Syeda return SymbolRef::ST_Data; 3282fa6bcf0SYusra Syeda case GOFF::ESD_EXE_Unspecified: 3292fa6bcf0SYusra Syeda return SymbolRef::ST_Unknown; 3302fa6bcf0SYusra Syeda } 33114390ecbSSimon Pilgrim llvm_unreachable("Unhandled ESDExecutable"); 3322fa6bcf0SYusra Syeda } 33314390ecbSSimon Pilgrim llvm_unreachable("Unhandled ESDSymbolType"); 3342fa6bcf0SYusra Syeda } 3352fa6bcf0SYusra Syeda 3362fa6bcf0SYusra Syeda Expected<section_iterator> 3372fa6bcf0SYusra Syeda GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 3382fa6bcf0SYusra Syeda DataRefImpl Sec; 3392fa6bcf0SYusra Syeda 3402fa6bcf0SYusra Syeda if (isSymbolUnresolved(Symb)) 3412fa6bcf0SYusra Syeda return section_iterator(SectionRef(Sec, this)); 3422fa6bcf0SYusra Syeda 3432fa6bcf0SYusra Syeda const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a]; 3442fa6bcf0SYusra Syeda uint32_t SymEdId; 3452fa6bcf0SYusra Syeda ESDRecord::getParentEsdId(SymEsdRecord, SymEdId); 3462fa6bcf0SYusra Syeda const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 3472fa6bcf0SYusra Syeda 3482fa6bcf0SYusra Syeda for (size_t I = 0, E = SectionList.size(); I < E; ++I) { 3492fa6bcf0SYusra Syeda bool Found; 3502fa6bcf0SYusra Syeda const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I); 3512fa6bcf0SYusra Syeda if (SectionPrRecord) { 3522fa6bcf0SYusra Syeda Found = SymEsdRecord == SectionPrRecord; 3532fa6bcf0SYusra Syeda } else { 3542fa6bcf0SYusra Syeda const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I); 3552fa6bcf0SYusra Syeda Found = SymEdRecord == SectionEdRecord; 3562fa6bcf0SYusra Syeda } 3572fa6bcf0SYusra Syeda 3582fa6bcf0SYusra Syeda if (Found) { 3592fa6bcf0SYusra Syeda Sec.d.a = I; 3602fa6bcf0SYusra Syeda return section_iterator(SectionRef(Sec, this)); 3612fa6bcf0SYusra Syeda } 3622fa6bcf0SYusra Syeda } 3632fa6bcf0SYusra Syeda return createStringError(llvm::errc::invalid_argument, 3642fa6bcf0SYusra Syeda "symbol with ESD id " + std::to_string(Symb.d.a) + 3652fa6bcf0SYusra Syeda " refers to invalid section with ESD id " + 3662fa6bcf0SYusra Syeda std::to_string(SymEdId)); 3672fa6bcf0SYusra Syeda } 3682fa6bcf0SYusra Syeda 3694c718fdbSYusra Syeda uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { 3704c718fdbSYusra Syeda const uint8_t *Record = getSymbolEsdRecord(Symb); 3714c718fdbSYusra Syeda uint32_t Length; 3724c718fdbSYusra Syeda ESDRecord::getLength(Record, Length); 3734c718fdbSYusra Syeda return Length; 3744c718fdbSYusra Syeda } 3754c718fdbSYusra Syeda 3762fa6bcf0SYusra Syeda const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { 3772fa6bcf0SYusra Syeda SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 3782fa6bcf0SYusra Syeda const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; 3792fa6bcf0SYusra Syeda return EsdRecord; 3802fa6bcf0SYusra Syeda } 3812fa6bcf0SYusra Syeda 3822fa6bcf0SYusra Syeda const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const { 3832fa6bcf0SYusra Syeda SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 3842fa6bcf0SYusra Syeda const uint8_t *EsdRecord = nullptr; 3852fa6bcf0SYusra Syeda if (EsdIds.d.b) 3862fa6bcf0SYusra Syeda EsdRecord = EsdPtrs[EsdIds.d.b]; 3872fa6bcf0SYusra Syeda return EsdRecord; 3882fa6bcf0SYusra Syeda } 3892fa6bcf0SYusra Syeda 3902fa6bcf0SYusra Syeda const uint8_t * 3912fa6bcf0SYusra Syeda GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const { 3922fa6bcf0SYusra Syeda DataRefImpl Sec; 3932fa6bcf0SYusra Syeda Sec.d.a = SectionIndex; 3942fa6bcf0SYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 3952fa6bcf0SYusra Syeda return EsdRecord; 3962fa6bcf0SYusra Syeda } 3972fa6bcf0SYusra Syeda 3982fa6bcf0SYusra Syeda const uint8_t * 3992fa6bcf0SYusra Syeda GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { 4002fa6bcf0SYusra Syeda DataRefImpl Sec; 4012fa6bcf0SYusra Syeda Sec.d.a = SectionIndex; 4022fa6bcf0SYusra Syeda const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec); 4032fa6bcf0SYusra Syeda return EsdRecord; 4042fa6bcf0SYusra Syeda } 4052fa6bcf0SYusra Syeda 4064c718fdbSYusra Syeda uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const { 4074c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 4084c718fdbSYusra Syeda uint32_t Length; 4094c718fdbSYusra Syeda ESDRecord::getLength(EsdRecord, Length); 4104c718fdbSYusra Syeda if (Length == 0) { 4114c718fdbSYusra Syeda const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec); 4124c718fdbSYusra Syeda if (PrEsdRecord) 4134c718fdbSYusra Syeda EsdRecord = PrEsdRecord; 4144c718fdbSYusra Syeda } 4154c718fdbSYusra Syeda 4164c718fdbSYusra Syeda uint32_t DefEsdId; 4174c718fdbSYusra Syeda ESDRecord::getEsdId(EsdRecord, DefEsdId); 4184c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n'); 4194c718fdbSYusra Syeda return DefEsdId; 4204c718fdbSYusra Syeda } 4214c718fdbSYusra Syeda 4224c718fdbSYusra Syeda void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 4234c718fdbSYusra Syeda Sec.d.a++; 4244c718fdbSYusra Syeda if ((Sec.d.a) >= SectionList.size()) 4254c718fdbSYusra Syeda Sec.d.a = 0; 4264c718fdbSYusra Syeda } 4274c718fdbSYusra Syeda 4284c718fdbSYusra Syeda Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const { 4294c718fdbSYusra Syeda DataRefImpl EdSym; 4304c718fdbSYusra Syeda SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 4314c718fdbSYusra Syeda EdSym.d.a = EsdIds.d.a; 4324c718fdbSYusra Syeda Expected<StringRef> Name = getSymbolName(EdSym); 4334c718fdbSYusra Syeda if (Name) { 4344c718fdbSYusra Syeda StringRef Res = *Name; 4354c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n'); 4364c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n'); 4374c718fdbSYusra Syeda Name = Res; 4384c718fdbSYusra Syeda } 4394c718fdbSYusra Syeda return Name; 4404c718fdbSYusra Syeda } 4414c718fdbSYusra Syeda 4424c718fdbSYusra Syeda uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 4434c718fdbSYusra Syeda uint32_t Offset; 4444c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 4454c718fdbSYusra Syeda ESDRecord::getOffset(EsdRecord, Offset); 4464c718fdbSYusra Syeda return Offset; 4474c718fdbSYusra Syeda } 4484c718fdbSYusra Syeda 4494c718fdbSYusra Syeda uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 4504c718fdbSYusra Syeda uint32_t Length; 4514c718fdbSYusra Syeda uint32_t DefEsdId = getSectionDefEsdId(Sec); 4524c718fdbSYusra Syeda const uint8_t *EsdRecord = EsdPtrs[DefEsdId]; 4534c718fdbSYusra Syeda ESDRecord::getLength(EsdRecord, Length); 4544c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n'); 4554c718fdbSYusra Syeda return static_cast<uint64_t>(Length); 4564c718fdbSYusra Syeda } 4574c718fdbSYusra Syeda 4584c718fdbSYusra Syeda // Unravel TXT records and expand fill characters to produce 4594c718fdbSYusra Syeda // a contiguous sequence of bytes. 4604c718fdbSYusra Syeda Expected<ArrayRef<uint8_t>> 4614c718fdbSYusra Syeda GOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 462*3f1be86aSKazu Hirata if (auto It = SectionDataCache.find(Sec.d.a); It != SectionDataCache.end()) { 463*3f1be86aSKazu Hirata auto &Buf = It->second; 4644c718fdbSYusra Syeda return ArrayRef<uint8_t>(Buf); 4654c718fdbSYusra Syeda } 4664c718fdbSYusra Syeda uint64_t SectionSize = getSectionSize(Sec); 4674c718fdbSYusra Syeda uint32_t DefEsdId = getSectionDefEsdId(Sec); 4684c718fdbSYusra Syeda 4694c718fdbSYusra Syeda const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec); 4704c718fdbSYusra Syeda bool FillBytePresent; 4714c718fdbSYusra Syeda ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent); 4724c718fdbSYusra Syeda uint8_t FillByte = '\0'; 4734c718fdbSYusra Syeda if (FillBytePresent) 4744c718fdbSYusra Syeda ESDRecord::getFillByteValue(EdEsdRecord, FillByte); 4754c718fdbSYusra Syeda 4764c718fdbSYusra Syeda // Initialize section with fill byte. 4774c718fdbSYusra Syeda SmallVector<uint8_t> Data(SectionSize, FillByte); 4784c718fdbSYusra Syeda 4794c718fdbSYusra Syeda // Replace section with content from text records. 4804c718fdbSYusra Syeda for (const uint8_t *TxtRecordInt : TextPtrs) { 4814c718fdbSYusra Syeda const uint8_t *TxtRecordPtr = TxtRecordInt; 4824c718fdbSYusra Syeda uint32_t TxtEsdId; 4834c718fdbSYusra Syeda TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId); 4844c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n'); 4854c718fdbSYusra Syeda 4864c718fdbSYusra Syeda if (TxtEsdId != DefEsdId) 4874c718fdbSYusra Syeda continue; 4884c718fdbSYusra Syeda 4894c718fdbSYusra Syeda uint32_t TxtDataOffset; 4904c718fdbSYusra Syeda TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset); 4914c718fdbSYusra Syeda 4924c718fdbSYusra Syeda uint16_t TxtDataSize; 4934c718fdbSYusra Syeda TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize); 4944c718fdbSYusra Syeda 4954c718fdbSYusra Syeda LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size " 4964c718fdbSYusra Syeda << TxtDataSize << "\n"); 4974c718fdbSYusra Syeda 4984c718fdbSYusra Syeda SmallString<256> CompleteData; 4994c718fdbSYusra Syeda CompleteData.reserve(TxtDataSize); 5004c718fdbSYusra Syeda if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData)) 5014c718fdbSYusra Syeda return std::move(Err); 5024c718fdbSYusra Syeda assert(CompleteData.size() == TxtDataSize && "Wrong length of data"); 5034c718fdbSYusra Syeda std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize, 5044c718fdbSYusra Syeda Data.begin() + TxtDataOffset); 5054c718fdbSYusra Syeda } 5064c718fdbSYusra Syeda SectionDataCache[Sec.d.a] = Data; 5074c718fdbSYusra Syeda return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]); 5084c718fdbSYusra Syeda } 5094c718fdbSYusra Syeda 5104c718fdbSYusra Syeda uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 5114c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 5124c718fdbSYusra Syeda GOFF::ESDAlignment Pow2Alignment; 5134c718fdbSYusra Syeda ESDRecord::getAlignment(EsdRecord, Pow2Alignment); 514db080605SSimon Pilgrim return 1ULL << static_cast<uint64_t>(Pow2Alignment); 5154c718fdbSYusra Syeda } 5164c718fdbSYusra Syeda 5174c718fdbSYusra Syeda bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { 5184c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 5194c718fdbSYusra Syeda GOFF::ESDExecutable Executable; 5204c718fdbSYusra Syeda ESDRecord::getExecutable(EsdRecord, Executable); 5214c718fdbSYusra Syeda return Executable == GOFF::ESD_EXE_CODE; 5224c718fdbSYusra Syeda } 5234c718fdbSYusra Syeda 5244c718fdbSYusra Syeda bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const { 5254c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 5264c718fdbSYusra Syeda GOFF::ESDExecutable Executable; 5274c718fdbSYusra Syeda ESDRecord::getExecutable(EsdRecord, Executable); 5284c718fdbSYusra Syeda return Executable == GOFF::ESD_EXE_DATA; 5294c718fdbSYusra Syeda } 5304c718fdbSYusra Syeda 5314c718fdbSYusra Syeda bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const { 5324c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 5334c718fdbSYusra Syeda GOFF::ESDLoadingBehavior LoadingBehavior; 5344c718fdbSYusra Syeda ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); 5354c718fdbSYusra Syeda return LoadingBehavior == GOFF::ESD_LB_NoLoad; 5364c718fdbSYusra Syeda } 5374c718fdbSYusra Syeda 5384c718fdbSYusra Syeda bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { 5394c718fdbSYusra Syeda if (!isSectionData(Sec)) 5404c718fdbSYusra Syeda return false; 5414c718fdbSYusra Syeda 5424c718fdbSYusra Syeda const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 5434c718fdbSYusra Syeda GOFF::ESDLoadingBehavior LoadingBehavior; 5444c718fdbSYusra Syeda ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); 5454c718fdbSYusra Syeda return LoadingBehavior == GOFF::ESD_LB_Initial; 5464c718fdbSYusra Syeda } 5474c718fdbSYusra Syeda 5484c718fdbSYusra Syeda bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { 5494c718fdbSYusra Syeda // GOFF uses fill characters and fill characters are applied 5504c718fdbSYusra Syeda // on getSectionContents() - so we say false to zero init. 5514c718fdbSYusra Syeda return false; 5524c718fdbSYusra Syeda } 5534c718fdbSYusra Syeda 5542fa6bcf0SYusra Syeda section_iterator GOFFObjectFile::section_begin() const { 5552fa6bcf0SYusra Syeda DataRefImpl Sec; 5562fa6bcf0SYusra Syeda moveSectionNext(Sec); 5572fa6bcf0SYusra Syeda return section_iterator(SectionRef(Sec, this)); 5582fa6bcf0SYusra Syeda } 5592fa6bcf0SYusra Syeda 5602fa6bcf0SYusra Syeda section_iterator GOFFObjectFile::section_end() const { 5612fa6bcf0SYusra Syeda DataRefImpl Sec; 5622fa6bcf0SYusra Syeda return section_iterator(SectionRef(Sec, this)); 5632fa6bcf0SYusra Syeda } 5642fa6bcf0SYusra Syeda 5652fa6bcf0SYusra Syeda void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 5662fa6bcf0SYusra Syeda for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) { 5672fa6bcf0SYusra Syeda if (EsdPtrs[I]) { 5682fa6bcf0SYusra Syeda const uint8_t *EsdRecord = EsdPtrs[I]; 5692fa6bcf0SYusra Syeda GOFF::ESDSymbolType SymbolType; 5702fa6bcf0SYusra Syeda ESDRecord::getSymbolType(EsdRecord, SymbolType); 5712fa6bcf0SYusra Syeda // Skip EDs - i.e. section symbols. 5722fa6bcf0SYusra Syeda bool IgnoreSpecialGOFFSymbols = true; 5732fa6bcf0SYusra Syeda bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) || 5742fa6bcf0SYusra Syeda (SymbolType == GOFF::ESD_ST_SectionDefinition)) && 5752fa6bcf0SYusra Syeda IgnoreSpecialGOFFSymbols; 5762fa6bcf0SYusra Syeda if (!SkipSymbol) { 5772fa6bcf0SYusra Syeda Symb.d.a = I; 5782fa6bcf0SYusra Syeda return; 5792fa6bcf0SYusra Syeda } 5802fa6bcf0SYusra Syeda } 5812fa6bcf0SYusra Syeda } 5822fa6bcf0SYusra Syeda Symb.d.a = 0; 5832fa6bcf0SYusra Syeda } 5842fa6bcf0SYusra Syeda 5852fa6bcf0SYusra Syeda basic_symbol_iterator GOFFObjectFile::symbol_begin() const { 5862fa6bcf0SYusra Syeda DataRefImpl Symb; 5872fa6bcf0SYusra Syeda moveSymbolNext(Symb); 5882fa6bcf0SYusra Syeda return basic_symbol_iterator(SymbolRef(Symb, this)); 5892fa6bcf0SYusra Syeda } 5902fa6bcf0SYusra Syeda 5912fa6bcf0SYusra Syeda basic_symbol_iterator GOFFObjectFile::symbol_end() const { 5922fa6bcf0SYusra Syeda DataRefImpl Symb; 5932fa6bcf0SYusra Syeda return basic_symbol_iterator(SymbolRef(Symb, this)); 5942fa6bcf0SYusra Syeda } 5952fa6bcf0SYusra Syeda 5962fa6bcf0SYusra Syeda Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength, 5972fa6bcf0SYusra Syeda int DataIndex, SmallString<256> &CompleteData) { 5982fa6bcf0SYusra Syeda // First record. 5992fa6bcf0SYusra Syeda const uint8_t *Slice = Record + DataIndex; 6002fa6bcf0SYusra Syeda size_t SliceLength = 6012fa6bcf0SYusra Syeda std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex)); 6022fa6bcf0SYusra Syeda CompleteData.append(Slice, Slice + SliceLength); 6032fa6bcf0SYusra Syeda DataLength -= SliceLength; 6042fa6bcf0SYusra Syeda Slice += SliceLength; 6052fa6bcf0SYusra Syeda 6062fa6bcf0SYusra Syeda // Continuation records. 6072fa6bcf0SYusra Syeda for (; DataLength > 0; 6082fa6bcf0SYusra Syeda DataLength -= SliceLength, Slice += GOFF::PayloadLength) { 6092fa6bcf0SYusra Syeda // Slice points to the start of the new record. 6102fa6bcf0SYusra Syeda // Check that this block is a Continuation. 6112fa6bcf0SYusra Syeda assert(Record::isContinuation(Slice) && "Continuation bit must be set"); 6122fa6bcf0SYusra Syeda // Check that the last Continuation is terminated correctly. 6132fa6bcf0SYusra Syeda if (DataLength <= 77 && Record::isContinued(Slice)) 6142fa6bcf0SYusra Syeda return createStringError(object_error::parse_failed, 6152fa6bcf0SYusra Syeda "continued bit should not be set"); 6162fa6bcf0SYusra Syeda 6172fa6bcf0SYusra Syeda SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength); 6182fa6bcf0SYusra Syeda Slice += GOFF::RecordPrefixLength; 6192fa6bcf0SYusra Syeda CompleteData.append(Slice, Slice + SliceLength); 6202fa6bcf0SYusra Syeda } 6212fa6bcf0SYusra Syeda return Error::success(); 6222fa6bcf0SYusra Syeda } 6232fa6bcf0SYusra Syeda 6242fa6bcf0SYusra Syeda Error HDRRecord::getData(const uint8_t *Record, 6252fa6bcf0SYusra Syeda SmallString<256> &CompleteData) { 6262fa6bcf0SYusra Syeda uint16_t Length = getPropertyModuleLength(Record); 6272fa6bcf0SYusra Syeda return getContinuousData(Record, Length, 60, CompleteData); 6282fa6bcf0SYusra Syeda } 6292fa6bcf0SYusra Syeda 6302fa6bcf0SYusra Syeda Error ESDRecord::getData(const uint8_t *Record, 6312fa6bcf0SYusra Syeda SmallString<256> &CompleteData) { 6322fa6bcf0SYusra Syeda uint16_t DataSize = getNameLength(Record); 6332fa6bcf0SYusra Syeda return getContinuousData(Record, DataSize, 72, CompleteData); 6342fa6bcf0SYusra Syeda } 6352fa6bcf0SYusra Syeda 6364c718fdbSYusra Syeda Error TXTRecord::getData(const uint8_t *Record, 6374c718fdbSYusra Syeda SmallString<256> &CompleteData) { 6384c718fdbSYusra Syeda uint16_t Length; 6394c718fdbSYusra Syeda getDataLength(Record, Length); 6404c718fdbSYusra Syeda return getContinuousData(Record, Length, 24, CompleteData); 6414c718fdbSYusra Syeda } 6424c718fdbSYusra Syeda 6432fa6bcf0SYusra Syeda Error ENDRecord::getData(const uint8_t *Record, 6442fa6bcf0SYusra Syeda SmallString<256> &CompleteData) { 6452fa6bcf0SYusra Syeda uint16_t Length = getNameLength(Record); 6462fa6bcf0SYusra Syeda return getContinuousData(Record, Length, 26, CompleteData); 6472fa6bcf0SYusra Syeda } 648