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