1 //===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Implementation of the GOFFObjectFile class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Object/GOFFObjectFile.h" 14 #include "llvm/BinaryFormat/GOFF.h" 15 #include "llvm/Object/GOFF.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/Errc.h" 18 #include "llvm/Support/raw_ostream.h" 19 20 #ifndef DEBUG_TYPE 21 #define DEBUG_TYPE "goff" 22 #endif 23 24 using namespace llvm::object; 25 using namespace llvm; 26 27 Expected<std::unique_ptr<ObjectFile>> 28 ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) { 29 Error Err = Error::success(); 30 std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err)); 31 if (Err) 32 return std::move(Err); 33 return std::move(Ret); 34 } 35 36 GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) 37 : ObjectFile(Binary::ID_GOFF, Object) { 38 ErrorAsOutParameter ErrAsOutParam(&Err); 39 // Object file isn't the right size, bail out early. 40 if ((Object.getBufferSize() % GOFF::RecordLength) != 0) { 41 Err = createStringError( 42 object_error::unexpected_eof, 43 "object file is not the right size. Must be a multiple " 44 "of 80 bytes, but is " + 45 std::to_string(Object.getBufferSize()) + " bytes"); 46 return; 47 } 48 // Object file doesn't start/end with HDR/END records. 49 // Bail out early. 50 if (Object.getBufferSize() != 0) { 51 if ((base()[1] & 0xF0) >> 4 != GOFF::RT_HDR) { 52 Err = createStringError(object_error::parse_failed, 53 "object file must start with HDR record"); 54 return; 55 } 56 if ((base()[Object.getBufferSize() - GOFF::RecordLength + 1] & 0xF0) >> 4 != 57 GOFF::RT_END) { 58 Err = createStringError(object_error::parse_failed, 59 "object file must end with END record"); 60 return; 61 } 62 } 63 64 SectionEntryImpl DummySection; 65 SectionList.emplace_back(DummySection); // Dummy entry at index 0. 66 67 uint8_t PrevRecordType = 0; 68 uint8_t PrevContinuationBits = 0; 69 const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd()); 70 for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) { 71 uint8_t RecordType = (I[1] & 0xF0) >> 4; 72 bool IsContinuation = I[1] & 0x02; 73 bool PrevWasContinued = PrevContinuationBits & 0x01; 74 size_t RecordNum = (I - base()) / GOFF::RecordLength; 75 76 // If the previous record was continued, the current record should be a 77 // continuation. 78 if (PrevWasContinued && !IsContinuation) { 79 if (PrevRecordType == RecordType) { 80 Err = createStringError(object_error::parse_failed, 81 "record " + std::to_string(RecordNum) + 82 " is not a continuation record but the " 83 "preceding record is continued"); 84 return; 85 } 86 } 87 // Don't parse continuations records, only parse initial record. 88 if (IsContinuation) { 89 if (RecordType != PrevRecordType) { 90 Err = createStringError(object_error::parse_failed, 91 "record " + std::to_string(RecordNum) + 92 " is a continuation record that does not " 93 "match the type of the previous record"); 94 return; 95 } 96 if (!PrevWasContinued) { 97 Err = createStringError(object_error::parse_failed, 98 "record " + std::to_string(RecordNum) + 99 " is a continuation record that is not " 100 "preceded by a continued record"); 101 return; 102 } 103 PrevRecordType = RecordType; 104 PrevContinuationBits = I[1] & 0x03; 105 continue; 106 } 107 LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) { 108 const uint8_t *P = I + J; 109 if (J % 8 == 0) 110 dbgs() << " "; 111 dbgs() << format("%02hhX", *P); 112 }); 113 114 switch (RecordType) { 115 case GOFF::RT_ESD: { 116 // Save ESD record. 117 uint32_t EsdId; 118 ESDRecord::getEsdId(I, EsdId); 119 EsdPtrs.grow(EsdId); 120 EsdPtrs[EsdId] = I; 121 122 // Determine and save the "sections" in GOFF. 123 // A section is saved as a tuple of the form 124 // case (1): (ED,child PR) 125 // - where the PR must have non-zero length. 126 // case (2a) (ED,0) 127 // - where the ED is of non-zero length. 128 // case (2b) (ED,0) 129 // - where the ED is zero length but 130 // contains a label (LD). 131 GOFF::ESDSymbolType SymbolType; 132 ESDRecord::getSymbolType(I, SymbolType); 133 SectionEntryImpl Section; 134 uint32_t Length; 135 ESDRecord::getLength(I, Length); 136 if (SymbolType == GOFF::ESD_ST_ElementDefinition) { 137 // case (2a) 138 if (Length != 0) { 139 Section.d.a = EsdId; 140 SectionList.emplace_back(Section); 141 } 142 } else if (SymbolType == GOFF::ESD_ST_PartReference) { 143 // case (1) 144 if (Length != 0) { 145 uint32_t SymEdId; 146 ESDRecord::getParentEsdId(I, SymEdId); 147 Section.d.a = SymEdId; 148 Section.d.b = EsdId; 149 SectionList.emplace_back(Section); 150 } 151 } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) { 152 // case (2b) 153 uint32_t SymEdId; 154 ESDRecord::getParentEsdId(I, SymEdId); 155 const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 156 uint32_t EdLength; 157 ESDRecord::getLength(SymEdRecord, EdLength); 158 if (!EdLength) { // [ EDID, PRID ] 159 // LD child of a zero length parent ED. 160 // Add the section ED which was previously ignored. 161 Section.d.a = SymEdId; 162 SectionList.emplace_back(Section); 163 } 164 } 165 LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); 166 break; 167 } 168 case GOFF::RT_TXT: 169 // Save TXT records. 170 TextPtrs.emplace_back(I); 171 LLVM_DEBUG(dbgs() << " -- TXT\n"); 172 break; 173 case GOFF::RT_END: 174 LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); 175 break; 176 case GOFF::RT_HDR: 177 LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n"); 178 break; 179 default: 180 llvm_unreachable("Unknown record type"); 181 } 182 PrevRecordType = RecordType; 183 PrevContinuationBits = I[1] & 0x03; 184 } 185 } 186 187 const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const { 188 const uint8_t *EsdRecord = EsdPtrs[Symb.d.a]; 189 return EsdRecord; 190 } 191 192 Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 193 if (EsdNamesCache.count(Symb.d.a)) { 194 auto &StrPtr = EsdNamesCache[Symb.d.a]; 195 return StringRef(StrPtr.second.get(), StrPtr.first); 196 } 197 198 SmallString<256> SymbolName; 199 if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName)) 200 return std::move(Err); 201 202 SmallString<256> SymbolNameConverted; 203 ConverterEBCDIC::convertToUTF8(SymbolName, SymbolNameConverted); 204 205 size_t Size = SymbolNameConverted.size(); 206 auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size)); 207 char *Buf = StrPtr.second.get(); 208 memcpy(Buf, SymbolNameConverted.data(), Size); 209 EsdNamesCache[Symb.d.a] = std::move(StrPtr); 210 return StringRef(Buf, Size); 211 } 212 213 Expected<StringRef> GOFFObjectFile::getSymbolName(SymbolRef Symbol) const { 214 return getSymbolName(Symbol.getRawDataRefImpl()); 215 } 216 217 Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 218 uint32_t Offset; 219 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 220 ESDRecord::getOffset(EsdRecord, Offset); 221 return static_cast<uint64_t>(Offset); 222 } 223 224 uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 225 uint32_t Offset; 226 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb); 227 ESDRecord::getOffset(EsdRecord, Offset); 228 return static_cast<uint64_t>(Offset); 229 } 230 231 uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 232 return 0; 233 } 234 235 bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const { 236 const uint8_t *Record = getSymbolEsdRecord(Symb); 237 GOFF::ESDSymbolType SymbolType; 238 ESDRecord::getSymbolType(Record, SymbolType); 239 240 if (SymbolType == GOFF::ESD_ST_ExternalReference) 241 return true; 242 if (SymbolType == GOFF::ESD_ST_PartReference) { 243 uint32_t Length; 244 ESDRecord::getLength(Record, Length); 245 if (Length == 0) 246 return true; 247 } 248 return false; 249 } 250 251 bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const { 252 const uint8_t *Record = getSymbolEsdRecord(Symb); 253 bool Indirect; 254 ESDRecord::getIndirectReference(Record, Indirect); 255 return Indirect; 256 } 257 258 Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 259 uint32_t Flags = 0; 260 if (isSymbolUnresolved(Symb)) 261 Flags |= SymbolRef::SF_Undefined; 262 263 const uint8_t *Record = getSymbolEsdRecord(Symb); 264 265 GOFF::ESDBindingStrength BindingStrength; 266 ESDRecord::getBindingStrength(Record, BindingStrength); 267 if (BindingStrength == GOFF::ESD_BST_Weak) 268 Flags |= SymbolRef::SF_Weak; 269 270 GOFF::ESDBindingScope BindingScope; 271 ESDRecord::getBindingScope(Record, BindingScope); 272 273 if (BindingScope != GOFF::ESD_BSC_Section) { 274 Expected<StringRef> Name = getSymbolName(Symb); 275 if (Name && *Name != " ") { // Blank name is local. 276 Flags |= SymbolRef::SF_Global; 277 if (BindingScope == GOFF::ESD_BSC_ImportExport) 278 Flags |= SymbolRef::SF_Exported; 279 else if (!(Flags & SymbolRef::SF_Undefined)) 280 Flags |= SymbolRef::SF_Hidden; 281 } 282 } 283 284 return Flags; 285 } 286 287 Expected<SymbolRef::Type> 288 GOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 289 const uint8_t *Record = getSymbolEsdRecord(Symb); 290 GOFF::ESDSymbolType SymbolType; 291 ESDRecord::getSymbolType(Record, SymbolType); 292 GOFF::ESDExecutable Executable; 293 ESDRecord::getExecutable(Record, Executable); 294 295 if (SymbolType != GOFF::ESD_ST_SectionDefinition && 296 SymbolType != GOFF::ESD_ST_ElementDefinition && 297 SymbolType != GOFF::ESD_ST_LabelDefinition && 298 SymbolType != GOFF::ESD_ST_PartReference && 299 SymbolType != GOFF::ESD_ST_ExternalReference) { 300 uint32_t EsdId; 301 ESDRecord::getEsdId(Record, EsdId); 302 return createStringError(llvm::errc::invalid_argument, 303 "ESD record %" PRIu32 304 " has invalid symbol type 0x%02" PRIX8, 305 EsdId, SymbolType); 306 } 307 switch (SymbolType) { 308 case GOFF::ESD_ST_SectionDefinition: 309 case GOFF::ESD_ST_ElementDefinition: 310 return SymbolRef::ST_Other; 311 case GOFF::ESD_ST_LabelDefinition: 312 case GOFF::ESD_ST_PartReference: 313 case GOFF::ESD_ST_ExternalReference: 314 if (Executable != GOFF::ESD_EXE_CODE && Executable != GOFF::ESD_EXE_DATA && 315 Executable != GOFF::ESD_EXE_Unspecified) { 316 uint32_t EsdId; 317 ESDRecord::getEsdId(Record, EsdId); 318 return createStringError(llvm::errc::invalid_argument, 319 "ESD record %" PRIu32 320 " has unknown Executable type 0x%02X", 321 EsdId, Executable); 322 } 323 switch (Executable) { 324 case GOFF::ESD_EXE_CODE: 325 return SymbolRef::ST_Function; 326 case GOFF::ESD_EXE_DATA: 327 return SymbolRef::ST_Data; 328 case GOFF::ESD_EXE_Unspecified: 329 return SymbolRef::ST_Unknown; 330 } 331 llvm_unreachable("Unhandled ESDExecutable"); 332 } 333 llvm_unreachable("Unhandled ESDSymbolType"); 334 } 335 336 Expected<section_iterator> 337 GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 338 DataRefImpl Sec; 339 340 if (isSymbolUnresolved(Symb)) 341 return section_iterator(SectionRef(Sec, this)); 342 343 const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a]; 344 uint32_t SymEdId; 345 ESDRecord::getParentEsdId(SymEsdRecord, SymEdId); 346 const uint8_t *SymEdRecord = EsdPtrs[SymEdId]; 347 348 for (size_t I = 0, E = SectionList.size(); I < E; ++I) { 349 bool Found; 350 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I); 351 if (SectionPrRecord) { 352 Found = SymEsdRecord == SectionPrRecord; 353 } else { 354 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I); 355 Found = SymEdRecord == SectionEdRecord; 356 } 357 358 if (Found) { 359 Sec.d.a = I; 360 return section_iterator(SectionRef(Sec, this)); 361 } 362 } 363 return createStringError(llvm::errc::invalid_argument, 364 "symbol with ESD id " + std::to_string(Symb.d.a) + 365 " refers to invalid section with ESD id " + 366 std::to_string(SymEdId)); 367 } 368 369 uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { 370 const uint8_t *Record = getSymbolEsdRecord(Symb); 371 uint32_t Length; 372 ESDRecord::getLength(Record, Length); 373 return Length; 374 } 375 376 const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { 377 SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 378 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; 379 return EsdRecord; 380 } 381 382 const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const { 383 SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 384 const uint8_t *EsdRecord = nullptr; 385 if (EsdIds.d.b) 386 EsdRecord = EsdPtrs[EsdIds.d.b]; 387 return EsdRecord; 388 } 389 390 const uint8_t * 391 GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const { 392 DataRefImpl Sec; 393 Sec.d.a = SectionIndex; 394 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 395 return EsdRecord; 396 } 397 398 const uint8_t * 399 GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { 400 DataRefImpl Sec; 401 Sec.d.a = SectionIndex; 402 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec); 403 return EsdRecord; 404 } 405 406 uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const { 407 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 408 uint32_t Length; 409 ESDRecord::getLength(EsdRecord, Length); 410 if (Length == 0) { 411 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec); 412 if (PrEsdRecord) 413 EsdRecord = PrEsdRecord; 414 } 415 416 uint32_t DefEsdId; 417 ESDRecord::getEsdId(EsdRecord, DefEsdId); 418 LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n'); 419 return DefEsdId; 420 } 421 422 void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 423 Sec.d.a++; 424 if ((Sec.d.a) >= SectionList.size()) 425 Sec.d.a = 0; 426 } 427 428 Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const { 429 DataRefImpl EdSym; 430 SectionEntryImpl EsdIds = SectionList[Sec.d.a]; 431 EdSym.d.a = EsdIds.d.a; 432 Expected<StringRef> Name = getSymbolName(EdSym); 433 if (Name) { 434 StringRef Res = *Name; 435 LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n'); 436 LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n'); 437 Name = Res; 438 } 439 return Name; 440 } 441 442 uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 443 uint32_t Offset; 444 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 445 ESDRecord::getOffset(EsdRecord, Offset); 446 return Offset; 447 } 448 449 uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 450 uint32_t Length; 451 uint32_t DefEsdId = getSectionDefEsdId(Sec); 452 const uint8_t *EsdRecord = EsdPtrs[DefEsdId]; 453 ESDRecord::getLength(EsdRecord, Length); 454 LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n'); 455 return static_cast<uint64_t>(Length); 456 } 457 458 // Unravel TXT records and expand fill characters to produce 459 // a contiguous sequence of bytes. 460 Expected<ArrayRef<uint8_t>> 461 GOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 462 if (SectionDataCache.count(Sec.d.a)) { 463 auto &Buf = SectionDataCache[Sec.d.a]; 464 return ArrayRef<uint8_t>(Buf); 465 } 466 uint64_t SectionSize = getSectionSize(Sec); 467 uint32_t DefEsdId = getSectionDefEsdId(Sec); 468 469 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec); 470 bool FillBytePresent; 471 ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent); 472 uint8_t FillByte = '\0'; 473 if (FillBytePresent) 474 ESDRecord::getFillByteValue(EdEsdRecord, FillByte); 475 476 // Initialize section with fill byte. 477 SmallVector<uint8_t> Data(SectionSize, FillByte); 478 479 // Replace section with content from text records. 480 for (const uint8_t *TxtRecordInt : TextPtrs) { 481 const uint8_t *TxtRecordPtr = TxtRecordInt; 482 uint32_t TxtEsdId; 483 TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId); 484 LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n'); 485 486 if (TxtEsdId != DefEsdId) 487 continue; 488 489 uint32_t TxtDataOffset; 490 TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset); 491 492 uint16_t TxtDataSize; 493 TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize); 494 495 LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size " 496 << TxtDataSize << "\n"); 497 498 SmallString<256> CompleteData; 499 CompleteData.reserve(TxtDataSize); 500 if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData)) 501 return std::move(Err); 502 assert(CompleteData.size() == TxtDataSize && "Wrong length of data"); 503 std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize, 504 Data.begin() + TxtDataOffset); 505 } 506 SectionDataCache[Sec.d.a] = Data; 507 return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]); 508 } 509 510 uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 511 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 512 GOFF::ESDAlignment Pow2Alignment; 513 ESDRecord::getAlignment(EsdRecord, Pow2Alignment); 514 return 1ULL << static_cast<uint64_t>(Pow2Alignment); 515 } 516 517 bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { 518 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 519 GOFF::ESDExecutable Executable; 520 ESDRecord::getExecutable(EsdRecord, Executable); 521 return Executable == GOFF::ESD_EXE_CODE; 522 } 523 524 bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const { 525 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 526 GOFF::ESDExecutable Executable; 527 ESDRecord::getExecutable(EsdRecord, Executable); 528 return Executable == GOFF::ESD_EXE_DATA; 529 } 530 531 bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const { 532 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 533 GOFF::ESDLoadingBehavior LoadingBehavior; 534 ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); 535 return LoadingBehavior == GOFF::ESD_LB_NoLoad; 536 } 537 538 bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { 539 if (!isSectionData(Sec)) 540 return false; 541 542 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); 543 GOFF::ESDLoadingBehavior LoadingBehavior; 544 ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); 545 return LoadingBehavior == GOFF::ESD_LB_Initial; 546 } 547 548 bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { 549 // GOFF uses fill characters and fill characters are applied 550 // on getSectionContents() - so we say false to zero init. 551 return false; 552 } 553 554 section_iterator GOFFObjectFile::section_begin() const { 555 DataRefImpl Sec; 556 moveSectionNext(Sec); 557 return section_iterator(SectionRef(Sec, this)); 558 } 559 560 section_iterator GOFFObjectFile::section_end() const { 561 DataRefImpl Sec; 562 return section_iterator(SectionRef(Sec, this)); 563 } 564 565 void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 566 for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) { 567 if (EsdPtrs[I]) { 568 const uint8_t *EsdRecord = EsdPtrs[I]; 569 GOFF::ESDSymbolType SymbolType; 570 ESDRecord::getSymbolType(EsdRecord, SymbolType); 571 // Skip EDs - i.e. section symbols. 572 bool IgnoreSpecialGOFFSymbols = true; 573 bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) || 574 (SymbolType == GOFF::ESD_ST_SectionDefinition)) && 575 IgnoreSpecialGOFFSymbols; 576 if (!SkipSymbol) { 577 Symb.d.a = I; 578 return; 579 } 580 } 581 } 582 Symb.d.a = 0; 583 } 584 585 basic_symbol_iterator GOFFObjectFile::symbol_begin() const { 586 DataRefImpl Symb; 587 moveSymbolNext(Symb); 588 return basic_symbol_iterator(SymbolRef(Symb, this)); 589 } 590 591 basic_symbol_iterator GOFFObjectFile::symbol_end() const { 592 DataRefImpl Symb; 593 return basic_symbol_iterator(SymbolRef(Symb, this)); 594 } 595 596 Error Record::getContinuousData(const uint8_t *Record, uint16_t DataLength, 597 int DataIndex, SmallString<256> &CompleteData) { 598 // First record. 599 const uint8_t *Slice = Record + DataIndex; 600 size_t SliceLength = 601 std::min(DataLength, (uint16_t)(GOFF::RecordLength - DataIndex)); 602 CompleteData.append(Slice, Slice + SliceLength); 603 DataLength -= SliceLength; 604 Slice += SliceLength; 605 606 // Continuation records. 607 for (; DataLength > 0; 608 DataLength -= SliceLength, Slice += GOFF::PayloadLength) { 609 // Slice points to the start of the new record. 610 // Check that this block is a Continuation. 611 assert(Record::isContinuation(Slice) && "Continuation bit must be set"); 612 // Check that the last Continuation is terminated correctly. 613 if (DataLength <= 77 && Record::isContinued(Slice)) 614 return createStringError(object_error::parse_failed, 615 "continued bit should not be set"); 616 617 SliceLength = std::min(DataLength, (uint16_t)GOFF::PayloadLength); 618 Slice += GOFF::RecordPrefixLength; 619 CompleteData.append(Slice, Slice + SliceLength); 620 } 621 return Error::success(); 622 } 623 624 Error HDRRecord::getData(const uint8_t *Record, 625 SmallString<256> &CompleteData) { 626 uint16_t Length = getPropertyModuleLength(Record); 627 return getContinuousData(Record, Length, 60, CompleteData); 628 } 629 630 Error ESDRecord::getData(const uint8_t *Record, 631 SmallString<256> &CompleteData) { 632 uint16_t DataSize = getNameLength(Record); 633 return getContinuousData(Record, DataSize, 72, CompleteData); 634 } 635 636 Error TXTRecord::getData(const uint8_t *Record, 637 SmallString<256> &CompleteData) { 638 uint16_t Length; 639 getDataLength(Record, Length); 640 return getContinuousData(Record, Length, 24, CompleteData); 641 } 642 643 Error ENDRecord::getData(const uint8_t *Record, 644 SmallString<256> &CompleteData) { 645 uint16_t Length = getNameLength(Record); 646 return getContinuousData(Record, Length, 26, CompleteData); 647 } 648