1*06c3fb27SDimitry Andric //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric // 9*06c3fb27SDimitry Andric // Implementation of the GOFFObjectFile class. 10*06c3fb27SDimitry Andric // 11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #include "llvm/Object/GOFFObjectFile.h" 14*06c3fb27SDimitry Andric #include "llvm/BinaryFormat/GOFF.h" 15*06c3fb27SDimitry Andric #include "llvm/Object/GOFF.h" 16*06c3fb27SDimitry Andric #include "llvm/Support/Debug.h" 17*06c3fb27SDimitry Andric #include "llvm/Support/Errc.h" 18*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 19*06c3fb27SDimitry Andric 20*06c3fb27SDimitry Andric #ifndef DEBUG_TYPE 21*06c3fb27SDimitry Andric #define DEBUG_TYPE "goff" 22*06c3fb27SDimitry Andric #endif 23*06c3fb27SDimitry Andric 24*06c3fb27SDimitry Andric using namespace llvm::object; 25*06c3fb27SDimitry Andric using namespace llvm; 26*06c3fb27SDimitry Andric 27*06c3fb27SDimitry Andric Expected<std::unique_ptr<ObjectFile>> 28*06c3fb27SDimitry Andric ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) { 29*06c3fb27SDimitry Andric Error Err = Error::success(); 30*06c3fb27SDimitry Andric std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err)); 31*06c3fb27SDimitry Andric if (Err) 32*06c3fb27SDimitry Andric return std::move(Err); 33*06c3fb27SDimitry Andric return std::move(Ret); 34*06c3fb27SDimitry Andric } 35*06c3fb27SDimitry Andric 36*06c3fb27SDimitry Andric GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) 37*06c3fb27SDimitry Andric : ObjectFile(Binary::ID_GOFF, Object) { 38*06c3fb27SDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err); 39*06c3fb27SDimitry Andric // Object file isn't the right size, bail out early. 40*06c3fb27SDimitry Andric if ((Object.getBufferSize() % GOFF::RecordLength) != 0) { 41*06c3fb27SDimitry Andric Err = createStringError( 42*06c3fb27SDimitry Andric object_error::unexpected_eof, 43*06c3fb27SDimitry Andric "object file is not the right size. Must be a multiple " 44*06c3fb27SDimitry Andric "of 80 bytes, but is " + 45*06c3fb27SDimitry Andric std::to_string(Object.getBufferSize()) + " bytes"); 46*06c3fb27SDimitry Andric return; 47*06c3fb27SDimitry Andric } 48*06c3fb27SDimitry Andric // Object file doesn't start/end with HDR/END records. 49*06c3fb27SDimitry Andric // Bail out early. 50*06c3fb27SDimitry Andric if (Object.getBufferSize() != 0) { 51*06c3fb27SDimitry Andric if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) { 52*06c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed, 53*06c3fb27SDimitry Andric "object file must start with HDR record"); 54*06c3fb27SDimitry Andric return; 55*06c3fb27SDimitry Andric } 56*06c3fb27SDimitry Andric if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 != 57*06c3fb27SDimitry Andric GOFF::RT_END) { 58*06c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed, 59*06c3fb27SDimitry Andric "object file must end with END record"); 60*06c3fb27SDimitry Andric return; 61*06c3fb27SDimitry Andric } 62*06c3fb27SDimitry Andric } 63*06c3fb27SDimitry Andric 64*06c3fb27SDimitry Andric SectionEntryImpl DummySection; 65*06c3fb27SDimitry Andric SectionList.emplace_back(DummySection); // Dummy entry at index 0. 66*06c3fb27SDimitry Andric 67*06c3fb27SDimitry Andric uint8_t PrevRecordType = 0; 68*06c3fb27SDimitry Andric uint8_t PrevContinuationBits = 0; 69*06c3fb27SDimitry Andric const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd()); 70*06c3fb27SDimitry Andric for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) { 71*06c3fb27SDimitry Andric uint8_t RecordType = (I[1] & 0xF0) >> 4; 72*06c3fb27SDimitry Andric bool IsContinuation = I[1] & 0x02; 73*06c3fb27SDimitry Andric bool PrevWasContinued = PrevContinuationBits & 0x01; 74*06c3fb27SDimitry Andric size_t RecordNum = (I - base()) / GOFF::RecordLength; 75*06c3fb27SDimitry Andric 76*06c3fb27SDimitry Andric // If the previous record was continued, the current record should be a 77*06c3fb27SDimitry Andric // continuation. 78*06c3fb27SDimitry Andric if (PrevWasContinued && !IsContinuation) { 79*06c3fb27SDimitry Andric if (PrevRecordType == RecordType) { 80*06c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed, 81*06c3fb27SDimitry Andric "record " + std::to_string(RecordNum) + 82*06c3fb27SDimitry Andric " is not a continuation record but the " 83*06c3fb27SDimitry Andric "preceding record is continued"); 84*06c3fb27SDimitry Andric return; 85*06c3fb27SDimitry Andric } 86*06c3fb27SDimitry Andric } 87*06c3fb27SDimitry Andric // Don't parse continuations records, only parse initial record. 88*06c3fb27SDimitry Andric if (IsContinuation) { 89*06c3fb27SDimitry Andric if (RecordType != PrevRecordType) { 90*06c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed, 91*06c3fb27SDimitry Andric "record " + std::to_string(RecordNum) + 92*06c3fb27SDimitry Andric " is a continuation record that does not " 93*06c3fb27SDimitry Andric "match the type of the previous record"); 94*06c3fb27SDimitry Andric return; 95*06c3fb27SDimitry Andric } 96*06c3fb27SDimitry Andric if (!PrevWasContinued) { 97*06c3fb27SDimitry Andric Err = createStringError(object_error::parse_failed, 98*06c3fb27SDimitry Andric "record " + std::to_string(RecordNum) + 99*06c3fb27SDimitry Andric " is a continuation record that is not " 100*06c3fb27SDimitry Andric "preceded by a continued record"); 101*06c3fb27SDimitry Andric return; 102*06c3fb27SDimitry Andric } 103*06c3fb27SDimitry Andric PrevRecordType = RecordType; 104*06c3fb27SDimitry Andric PrevContinuationBits = I[1] & 0x03; 105*06c3fb27SDimitry Andric continue; 106*06c3fb27SDimitry Andric } 107*06c3fb27SDimitry Andric 108*06c3fb27SDimitry Andric #ifndef NDEBUG 109*06c3fb27SDimitry Andric for (size_t J = 0; J < GOFF::RecordLength; ++J) { 110*06c3fb27SDimitry Andric const uint8_t *P = I + J; 111*06c3fb27SDimitry Andric if (J % 8 == 0) 112*06c3fb27SDimitry Andric dbgs() << " "; 113*06c3fb27SDimitry Andric 114*06c3fb27SDimitry Andric dbgs() << format("%02hhX", *P); 115*06c3fb27SDimitry Andric } 116*06c3fb27SDimitry Andric #endif 117*06c3fb27SDimitry Andric switch (RecordType) { 118*06c3fb27SDimitry Andric case GOFF::RT_ESD: { 119*06c3fb27SDimitry Andric // Save ESD record. 120*06c3fb27SDimitry Andric uint32_t EsdId; 121*06c3fb27SDimitry Andric ESDRecord::getEsdId(I, EsdId); 122*06c3fb27SDimitry Andric EsdPtrs.grow(EsdId); 123*06c3fb27SDimitry Andric EsdPtrs[EsdId] = I; 124*06c3fb27SDimitry Andric 125*06c3fb27SDimitry Andric // Determine and save the "sections" in GOFF. 126*06c3fb27SDimitry Andric // A section is saved as a tuple of the form 127*06c3fb27SDimitry Andric // case (1): (ED,child PR) 128*06c3fb27SDimitry Andric // - where the PR must have non-zero length. 129*06c3fb27SDimitry Andric // case (2a) (ED,0) 130*06c3fb27SDimitry Andric // - where the ED is of non-zero length. 131*06c3fb27SDimitry Andric // case (2b) (ED,0) 132*06c3fb27SDimitry Andric // - where the ED is zero length but 133*06c3fb27SDimitry Andric // contains a label (LD). 134*06c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType; 135*06c3fb27SDimitry Andric ESDRecord::getSymbolType(I, SymbolType); 136*06c3fb27SDimitry Andric SectionEntryImpl Section; 137*06c3fb27SDimitry Andric uint32_t Length; 138*06c3fb27SDimitry Andric ESDRecord::getLength(I, Length); 139*06c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_ElementDefinition) { 140*06c3fb27SDimitry Andric // case (2a) 141*06c3fb27SDimitry Andric if (Length != 0) { 142*06c3fb27SDimitry Andric Section.d.a = EsdId; 143*06c3fb27SDimitry Andric SectionList.emplace_back(Section); 144*06c3fb27SDimitry Andric } 145*06c3fb27SDimitry Andric } else if (SymbolType == GOFF::ESD_ST_PartReference) { 146*06c3fb27SDimitry Andric // case (1) 147*06c3fb27SDimitry Andric if (Length != 0) { 148*06c3fb27SDimitry Andric uint32_t SymEdId; 149*06c3fb27SDimitry Andric ESDRecord::getParentEsdId(I, SymEdId); 150*06c3fb27SDimitry Andric Section.d.a = SymEdId; 151*06c3fb27SDimitry Andric Section.d.b = EsdId; 152*06c3fb27SDimitry Andric SectionList.emplace_back(Section); 153*06c3fb27SDimitry Andric } 154*06c3fb27SDimitry Andric } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) { 155*06c3fb27SDimitry Andric // case (2b) 156*06c3fb27SDimitry Andric uint32_t SymEdId; 157*06c3fb27SDimitry Andric ESDRecord::getParentEsdId(I, SymEdId); 158*06c3fb27SDimitry Andric const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 159*06c3fb27SDimitry Andric uint32_t EdLength; 160*06c3fb27SDimitry Andric ESDRecord::getLength(SymEdRecord, EdLength); 161*06c3fb27SDimitry Andric if (!EdLength) { // [ EDID, PRID ] 162*06c3fb27SDimitry Andric // LD child of a zero length parent ED. 163*06c3fb27SDimitry Andric // Add the section ED which was previously ignored. 164*06c3fb27SDimitry Andric Section.d.a = SymEdId; 165*06c3fb27SDimitry Andric SectionList.emplace_back(Section); 166*06c3fb27SDimitry Andric } 167*06c3fb27SDimitry Andric } 168*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); 169*06c3fb27SDimitry Andric break; 170*06c3fb27SDimitry Andric } 171*06c3fb27SDimitry Andric case GOFF::RT_END: 172*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); 173*06c3fb27SDimitry Andric break; 174*06c3fb27SDimitry Andric case GOFF::RT_HDR: 175*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n"); 176*06c3fb27SDimitry Andric break; 177*06c3fb27SDimitry Andric default: 178*06c3fb27SDimitry Andric llvm_unreachable("Unknown record type"); 179*06c3fb27SDimitry Andric } 180*06c3fb27SDimitry Andric PrevRecordType = RecordType; 181*06c3fb27SDimitry Andric PrevContinuationBits = I[1] & 0x03; 182*06c3fb27SDimitry Andric } 183*06c3fb27SDimitry Andric } 184*06c3fb27SDimitry Andric 185*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const { 186*06c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[Symb.d.a]; 187*06c3fb27SDimitry Andric return EsdRecord; 188*06c3fb27SDimitry Andric } 189*06c3fb27SDimitry Andric 190*06c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 191*06c3fb27SDimitry Andric if (EsdNamesCache.count(Symb.d.a)) { 192*06c3fb27SDimitry Andric auto &StrPtr = EsdNamesCache[Symb.d.a]; 193*06c3fb27SDimitry Andric return StringRef(StrPtr.second.get(), StrPtr.first); 194*06c3fb27SDimitry Andric } 195*06c3fb27SDimitry Andric 196*06c3fb27SDimitry Andric SmallString<256> SymbolName; 197*06c3fb27SDimitry Andric if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName)) 198*06c3fb27SDimitry Andric return std::move(Err); 199*06c3fb27SDimitry Andric 200*06c3fb27SDimitry Andric SmallString<256> SymbolNameConverted; 201*06c3fb27SDimitry Andric ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted); 202*06c3fb27SDimitry Andric 203*06c3fb27SDimitry Andric size_t Size = SymbolNameConverted.size(); 204*06c3fb27SDimitry Andric auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size)); 205*06c3fb27SDimitry Andric char *Buf = StrPtr.second.get(); 206*06c3fb27SDimitry Andric memcpy(Buf, SymbolNameConverted.data(), Size); 207*06c3fb27SDimitry Andric EsdNamesCache[Symb.d.a] = std::move(StrPtr); 208*06c3fb27SDimitry Andric return StringRef(Buf, Size); 209*06c3fb27SDimitry Andric } 210*06c3fb27SDimitry Andric 211*06c3fb27SDimitry Andric Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const { 212*06c3fb27SDimitry Andric return getSymbolName(Symbol.getRawDataRefImpl()); 213*06c3fb27SDimitry Andric } 214*06c3fb27SDimitry Andric 215*06c3fb27SDimitry Andric Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 216*06c3fb27SDimitry Andric uint32_t Offset; 217*06c3fb27SDimitry Andric const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 218*06c3fb27SDimitry Andric ESDRecord::getOffset(EsdRecord, Offset); 219*06c3fb27SDimitry Andric return static_cast<uint64_t>(Offset); 220*06c3fb27SDimitry Andric } 221*06c3fb27SDimitry Andric 222*06c3fb27SDimitry Andric uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 223*06c3fb27SDimitry Andric uint32_t Offset; 224*06c3fb27SDimitry Andric const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 225*06c3fb27SDimitry Andric ESDRecord::getOffset(EsdRecord, Offset); 226*06c3fb27SDimitry Andric return static_cast<uint64_t>(Offset); 227*06c3fb27SDimitry Andric } 228*06c3fb27SDimitry Andric 229*06c3fb27SDimitry Andric uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 230*06c3fb27SDimitry Andric return 0; 231*06c3fb27SDimitry Andric } 232*06c3fb27SDimitry Andric 233*06c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const { 234*06c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb); 235*06c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType; 236*06c3fb27SDimitry Andric ESDRecord::getSymbolType(Record, SymbolType); 237*06c3fb27SDimitry Andric 238*06c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_ExternalReference) 239*06c3fb27SDimitry Andric return true; 240*06c3fb27SDimitry Andric if (SymbolType == GOFF::ESD_ST_PartReference) { 241*06c3fb27SDimitry Andric uint32_t Length; 242*06c3fb27SDimitry Andric ESDRecord::getLength(Record, Length); 243*06c3fb27SDimitry Andric if (Length == 0) 244*06c3fb27SDimitry Andric return true; 245*06c3fb27SDimitry Andric } 246*06c3fb27SDimitry Andric return false; 247*06c3fb27SDimitry Andric } 248*06c3fb27SDimitry Andric 249*06c3fb27SDimitry Andric bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const { 250*06c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb); 251*06c3fb27SDimitry Andric bool Indirect; 252*06c3fb27SDimitry Andric ESDRecord::getIndirectReference(Record, Indirect); 253*06c3fb27SDimitry Andric return Indirect; 254*06c3fb27SDimitry Andric } 255*06c3fb27SDimitry Andric 256*06c3fb27SDimitry Andric Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 257*06c3fb27SDimitry Andric uint32_t Flags = 0; 258*06c3fb27SDimitry Andric if (isSymbolUnresolved(Symb)) 259*06c3fb27SDimitry Andric Flags |= SymbolRef::SF_Undefined; 260*06c3fb27SDimitry Andric 261*06c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb); 262*06c3fb27SDimitry Andric 263*06c3fb27SDimitry Andric GOFF::ESDBindingStrength BindingStrength; 264*06c3fb27SDimitry Andric ESDRecord::getBindingStrength(Record, BindingStrength); 265*06c3fb27SDimitry Andric if (BindingStrength == GOFF::ESD_BST_Weak) 266*06c3fb27SDimitry Andric Flags |= SymbolRef::SF_Weak; 267*06c3fb27SDimitry Andric 268*06c3fb27SDimitry Andric GOFF::ESDBindingScope BindingScope; 269*06c3fb27SDimitry Andric ESDRecord::getBindingScope(Record, BindingScope); 270*06c3fb27SDimitry Andric 271*06c3fb27SDimitry Andric if (BindingScope != GOFF::ESD_BSC_Section) { 272*06c3fb27SDimitry Andric Expected<StringRef> Name = getSymbolName(Symb); 273*06c3fb27SDimitry Andric if (Name && *Name != " ") { // Blank name is local. 274*06c3fb27SDimitry Andric Flags |= SymbolRef::SF_Global; 275*06c3fb27SDimitry Andric if (BindingScope == GOFF::ESD_BSC_ImportExport) 276*06c3fb27SDimitry Andric Flags |= SymbolRef::SF_Exported; 277*06c3fb27SDimitry Andric else if (!(Flags & SymbolRef::SF_Undefined)) 278*06c3fb27SDimitry Andric Flags |= SymbolRef::SF_Hidden; 279*06c3fb27SDimitry Andric } 280*06c3fb27SDimitry Andric } 281*06c3fb27SDimitry Andric 282*06c3fb27SDimitry Andric return Flags; 283*06c3fb27SDimitry Andric } 284*06c3fb27SDimitry Andric 285*06c3fb27SDimitry Andric Expected<SymbolRef::Type> 286*06c3fb27SDimitry Andric GOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 287*06c3fb27SDimitry Andric const uint8_t *Record = getSymbolEsdRecord(Symb); 288*06c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType; 289*06c3fb27SDimitry Andric ESDRecord::getSymbolType(Record, SymbolType); 290*06c3fb27SDimitry Andric GOFF::ESDExecutable Executable; 291*06c3fb27SDimitry Andric ESDRecord::getExecutable(Record, Executable); 292*06c3fb27SDimitry Andric 293*06c3fb27SDimitry Andric if (SymbolType != GOFF::ESD_ST_SectionDefinition && 294*06c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_ElementDefinition && 295*06c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_LabelDefinition && 296*06c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_PartReference && 297*06c3fb27SDimitry Andric SymbolType != GOFF::ESD_ST_ExternalReference) { 298*06c3fb27SDimitry Andric uint32_t EsdId; 299*06c3fb27SDimitry Andric ESDRecord::getEsdId(Record, EsdId); 300*06c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument, 301*06c3fb27SDimitry Andric "ESD record %" PRIu32 302*06c3fb27SDimitry Andric " has invalid symbol type 0x%02" PRIX8, 303*06c3fb27SDimitry Andric EsdId, SymbolType); 304*06c3fb27SDimitry Andric } 305*06c3fb27SDimitry Andric switch (SymbolType) { 306*06c3fb27SDimitry Andric case GOFF::ESD_ST_SectionDefinition: 307*06c3fb27SDimitry Andric case GOFF::ESD_ST_ElementDefinition: 308*06c3fb27SDimitry Andric return SymbolRef::ST_Other; 309*06c3fb27SDimitry Andric case GOFF::ESD_ST_LabelDefinition: 310*06c3fb27SDimitry Andric case GOFF::ESD_ST_PartReference: 311*06c3fb27SDimitry Andric case GOFF::ESD_ST_ExternalReference: 312*06c3fb27SDimitry Andric if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA && 313*06c3fb27SDimitry Andric Executable != GOFF::ESD_EXE_Unspecified) { 314*06c3fb27SDimitry Andric uint32_t EsdId; 315*06c3fb27SDimitry Andric ESDRecord::getEsdId(Record, EsdId); 316*06c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument, 317*06c3fb27SDimitry Andric "ESD record %" PRIu32 318*06c3fb27SDimitry Andric " has unknown Executable type 0x%02X", 319*06c3fb27SDimitry Andric EsdId, Executable); 320*06c3fb27SDimitry Andric } 321*06c3fb27SDimitry Andric switch (Executable) { 322*06c3fb27SDimitry Andric case GOFF::ESD_EXE_CODE: 323*06c3fb27SDimitry Andric return SymbolRef::ST_Function; 324*06c3fb27SDimitry Andric case GOFF::ESD_EXE_DATA: 325*06c3fb27SDimitry Andric return SymbolRef::ST_Data; 326*06c3fb27SDimitry Andric case GOFF::ESD_EXE_Unspecified: 327*06c3fb27SDimitry Andric return SymbolRef::ST_Unknown; 328*06c3fb27SDimitry Andric } 329*06c3fb27SDimitry Andric llvm_unreachable("Unhandled ESDExecutable"); 330*06c3fb27SDimitry Andric } 331*06c3fb27SDimitry Andric llvm_unreachable("Unhandled ESDSymbolType"); 332*06c3fb27SDimitry Andric } 333*06c3fb27SDimitry Andric 334*06c3fb27SDimitry Andric Expected<section_iterator> 335*06c3fb27SDimitry Andric GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 336*06c3fb27SDimitry Andric DataRefImpl Sec; 337*06c3fb27SDimitry Andric 338*06c3fb27SDimitry Andric if (isSymbolUnresolved(Symb)) 339*06c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this)); 340*06c3fb27SDimitry Andric 341*06c3fb27SDimitry Andric const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a]; 342*06c3fb27SDimitry Andric uint32_t SymEdId; 343*06c3fb27SDimitry Andric ESDRecord::getParentEsdId(SymEsdRecord, SymEdId); 344*06c3fb27SDimitry Andric const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 345*06c3fb27SDimitry Andric 346*06c3fb27SDimitry Andric for (size_t I = 0, E = SectionList.size(); I < E; ++I) { 347*06c3fb27SDimitry Andric bool Found; 348*06c3fb27SDimitry Andric const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I); 349*06c3fb27SDimitry Andric if (SectionPrRecord) { 350*06c3fb27SDimitry Andric Found = SymEsdRecord == SectionPrRecord; 351*06c3fb27SDimitry Andric } else { 352*06c3fb27SDimitry Andric const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I); 353*06c3fb27SDimitry Andric Found = SymEdRecord == SectionEdRecord; 354*06c3fb27SDimitry Andric } 355*06c3fb27SDimitry Andric 356*06c3fb27SDimitry Andric if (Found) { 357*06c3fb27SDimitry Andric Sec.d.a = I; 358*06c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this)); 359*06c3fb27SDimitry Andric } 360*06c3fb27SDimitry Andric } 361*06c3fb27SDimitry Andric return createStringError(llvm::errc::invalid_argument, 362*06c3fb27SDimitry Andric "symbol with ESD id " + std::to_string(Symb.d.a) + 363*06c3fb27SDimitry Andric " refers to invalid section with ESD id " + 364*06c3fb27SDimitry Andric std::to_string(SymEdId)); 365*06c3fb27SDimitry Andric } 366*06c3fb27SDimitry Andric 367*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { 368*06c3fb27SDimitry Andric SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 369*06c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; 370*06c3fb27SDimitry Andric return EsdRecord; 371*06c3fb27SDimitry Andric } 372*06c3fb27SDimitry Andric 373*06c3fb27SDimitry Andric const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const { 374*06c3fb27SDimitry Andric SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 375*06c3fb27SDimitry Andric const uint8_t *EsdRecord = nullptr; 376*06c3fb27SDimitry Andric if (EsdIds.d.b) 377*06c3fb27SDimitry Andric EsdRecord = EsdPtrs[EsdIds.d.b]; 378*06c3fb27SDimitry Andric return EsdRecord; 379*06c3fb27SDimitry Andric } 380*06c3fb27SDimitry Andric 381*06c3fb27SDimitry Andric const uint8_t * 382*06c3fb27SDimitry Andric GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const { 383*06c3fb27SDimitry Andric DataRefImpl Sec; 384*06c3fb27SDimitry Andric Sec.d.a = SectionIndex; 385*06c3fb27SDimitry Andric const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 386*06c3fb27SDimitry Andric return EsdRecord; 387*06c3fb27SDimitry Andric } 388*06c3fb27SDimitry Andric 389*06c3fb27SDimitry Andric const uint8_t * 390*06c3fb27SDimitry Andric GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { 391*06c3fb27SDimitry Andric DataRefImpl Sec; 392*06c3fb27SDimitry Andric Sec.d.a = SectionIndex; 393*06c3fb27SDimitry Andric const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec); 394*06c3fb27SDimitry Andric return EsdRecord; 395*06c3fb27SDimitry Andric } 396*06c3fb27SDimitry Andric 397*06c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_begin() const { 398*06c3fb27SDimitry Andric DataRefImpl Sec; 399*06c3fb27SDimitry Andric moveSectionNext(Sec); 400*06c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this)); 401*06c3fb27SDimitry Andric } 402*06c3fb27SDimitry Andric 403*06c3fb27SDimitry Andric section_iterator GOFFObjectFile::section_end() const { 404*06c3fb27SDimitry Andric DataRefImpl Sec; 405*06c3fb27SDimitry Andric return section_iterator(SectionRef(Sec, this)); 406*06c3fb27SDimitry Andric } 407*06c3fb27SDimitry Andric 408*06c3fb27SDimitry Andric void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 409*06c3fb27SDimitry Andric for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) { 410*06c3fb27SDimitry Andric if (EsdPtrs[I]) { 411*06c3fb27SDimitry Andric const uint8_t *EsdRecord = EsdPtrs[I]; 412*06c3fb27SDimitry Andric GOFF::ESDSymbolType SymbolType; 413*06c3fb27SDimitry Andric ESDRecord::getSymbolType(EsdRecord, SymbolType); 414*06c3fb27SDimitry Andric // Skip EDs - i.e. section symbols. 415*06c3fb27SDimitry Andric bool IgnoreSpecialGOFFSymbols = true; 416*06c3fb27SDimitry Andric bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) || 417*06c3fb27SDimitry Andric (SymbolType == GOFF::ESD_ST_SectionDefinition)) && 418*06c3fb27SDimitry Andric IgnoreSpecialGOFFSymbols; 419*06c3fb27SDimitry Andric if (!SkipSymbol) { 420*06c3fb27SDimitry Andric Symb.d.a = I; 421*06c3fb27SDimitry Andric return; 422*06c3fb27SDimitry Andric } 423*06c3fb27SDimitry Andric } 424*06c3fb27SDimitry Andric } 425*06c3fb27SDimitry Andric Symb.d.a = 0; 426*06c3fb27SDimitry Andric } 427*06c3fb27SDimitry Andric 428*06c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_begin() const { 429*06c3fb27SDimitry Andric DataRefImpl Symb; 430*06c3fb27SDimitry Andric moveSymbolNext(Symb); 431*06c3fb27SDimitry Andric return basic_symbol_iterator(SymbolRef(Symb, this)); 432*06c3fb27SDimitry Andric } 433*06c3fb27SDimitry Andric 434*06c3fb27SDimitry Andric basic_symbol_iterator GOFFObjectFile::symbol_end() const { 435*06c3fb27SDimitry Andric DataRefImpl Symb; 436*06c3fb27SDimitry Andric return basic_symbol_iterator(SymbolRef(Symb, this)); 437*06c3fb27SDimitry Andric } 438*06c3fb27SDimitry Andric 439*06c3fb27SDimitry Andric Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength, 440*06c3fb27SDimitry Andric int DataIndex, SmallString<256> &CompleteData) { 441*06c3fb27SDimitry Andric // First record. 442*06c3fb27SDimitry Andric const uint8_t *Slice = Record + DataIndex; 443*06c3fb27SDimitry Andric size_t SliceLength = 444*06c3fb27SDimitry Andric std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex)); 445*06c3fb27SDimitry Andric CompleteData.append(Slice, Slice + SliceLength); 446*06c3fb27SDimitry Andric DataLength -= SliceLength; 447*06c3fb27SDimitry Andric Slice += SliceLength; 448*06c3fb27SDimitry Andric 449*06c3fb27SDimitry Andric // Continuation records. 450*06c3fb27SDimitry Andric for (; DataLength > 0; 451*06c3fb27SDimitry Andric DataLength -= SliceLength, Slice += GOFF::PayloadLength) { 452*06c3fb27SDimitry Andric // Slice points to the start of the new record. 453*06c3fb27SDimitry Andric // Check that this block is a Continuation. 454*06c3fb27SDimitry Andric assert(Record::isContinuation(Slice) && "Continuation bit must be set"); 455*06c3fb27SDimitry Andric // Check that the last Continuation is terminated correctly. 456*06c3fb27SDimitry Andric if (DataLength <= 77 && Record::isContinued(Slice)) 457*06c3fb27SDimitry Andric return createStringError(object_error::parse_failed, 458*06c3fb27SDimitry Andric "continued bit should not be set"); 459*06c3fb27SDimitry Andric 460*06c3fb27SDimitry Andric SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength); 461*06c3fb27SDimitry Andric Slice += GOFF::RecordPrefixLength; 462*06c3fb27SDimitry Andric CompleteData.append(Slice, Slice + SliceLength); 463*06c3fb27SDimitry Andric } 464*06c3fb27SDimitry Andric return Error::success(); 465*06c3fb27SDimitry Andric } 466*06c3fb27SDimitry Andric 467*06c3fb27SDimitry Andric Error HDRRecord::getData(const uint8_t *Record, 468*06c3fb27SDimitry Andric SmallString<256> &CompleteData) { 469*06c3fb27SDimitry Andric uint16_t Length = getPropertyModuleLength(Record); 470*06c3fb27SDimitry Andric return getContinuousData(Record, Length, 60, CompleteData); 471*06c3fb27SDimitry Andric } 472*06c3fb27SDimitry Andric 473*06c3fb27SDimitry Andric Error ESDRecord::getData(const uint8_t *Record, 474*06c3fb27SDimitry Andric SmallString<256> &CompleteData) { 475*06c3fb27SDimitry Andric uint16_t DataSize = getNameLength(Record); 476*06c3fb27SDimitry Andric return getContinuousData(Record, DataSize, 72, CompleteData); 477*06c3fb27SDimitry Andric } 478*06c3fb27SDimitry Andric 479*06c3fb27SDimitry Andric Error ENDRecord::getData(const uint8_t *Record, 480*06c3fb27SDimitry Andric SmallString<256> &CompleteData) { 481*06c3fb27SDimitry Andric uint16_t Length = getNameLength(Record); 482*06c3fb27SDimitry Andric return getContinuousData(Record, Length, 26, CompleteData); 483*06c3fb27SDimitry Andric } 484