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