1 //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===// 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 // This file defines the XCOFFObjectFile class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Object/XCOFFObjectFile.h" 14 #include <cstddef> 15 #include <cstring> 16 17 namespace llvm { 18 namespace object { 19 20 enum { 21 FUNCTION_SYM = 0x20, 22 SYM_TYPE_MASK = 0x07 23 }; 24 25 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer 26 // 'M'. Returns a pointer to the underlying object on success. 27 template <typename T> 28 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, 29 const uint64_t Size = sizeof(T)) { 30 uintptr_t Addr = uintptr_t(Ptr); 31 if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) 32 return errorCodeToError(EC); 33 return reinterpret_cast<const T *>(Addr); 34 } 35 36 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { 37 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + 38 Offset); 39 } 40 41 template <typename T> static const T *viewAs(uintptr_t in) { 42 return reinterpret_cast<const T *>(in); 43 } 44 45 static StringRef generateXCOFFFixedNameStringRef(const char *Name) { 46 auto NulCharPtr = 47 static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); 48 return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 49 : StringRef(Name, XCOFF::NameSize); 50 } 51 52 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, 53 uintptr_t TableAddress) const { 54 if (Addr < TableAddress) 55 report_fatal_error("Section header outside of section header table."); 56 57 uintptr_t Offset = Addr - TableAddress; 58 if (Offset >= getSectionHeaderSize() * getNumberOfSections()) 59 report_fatal_error("Section header outside of section header table."); 60 61 if (Offset % getSectionHeaderSize() != 0) 62 report_fatal_error( 63 "Section header pointer does not point to a valid section header."); 64 } 65 66 const XCOFFSectionHeader32 * 67 XCOFFObjectFile::toSection32(DataRefImpl Ref) const { 68 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 69 #ifndef NDEBUG 70 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 71 #endif 72 return viewAs<XCOFFSectionHeader32>(Ref.p); 73 } 74 75 const XCOFFSectionHeader64 * 76 XCOFFObjectFile::toSection64(DataRefImpl Ref) const { 77 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 78 #ifndef NDEBUG 79 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 80 #endif 81 return viewAs<XCOFFSectionHeader64>(Ref.p); 82 } 83 84 const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { 85 assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); 86 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); 87 #ifndef NDEBUG 88 checkSymbolEntryPointer(Ref.p); 89 #endif 90 auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p); 91 return SymEntPtr; 92 } 93 94 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { 95 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 96 return static_cast<const XCOFFFileHeader32 *>(FileHeader); 97 } 98 99 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { 100 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 101 return static_cast<const XCOFFFileHeader64 *>(FileHeader); 102 } 103 104 const XCOFFSectionHeader32 * 105 XCOFFObjectFile::sectionHeaderTable32() const { 106 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 107 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); 108 } 109 110 const XCOFFSectionHeader64 * 111 XCOFFObjectFile::sectionHeaderTable64() const { 112 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 113 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); 114 } 115 116 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 117 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 118 SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1; 119 #ifndef NDEBUG 120 // This function is used by basic_symbol_iterator, which allows to 121 // point to the end-of-symbol-table address. 122 if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress()) 123 checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr)); 124 #endif 125 Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr); 126 } 127 128 Expected<StringRef> 129 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { 130 // The byte offset is relative to the start of the string table. 131 // A byte offset value of 0 is a null or zero-length symbol 132 // name. A byte offset in the range 1 to 3 (inclusive) points into the length 133 // field; as a soft-error recovery mechanism, we treat such cases as having an 134 // offset of 0. 135 if (Offset < 4) 136 return StringRef(nullptr, 0); 137 138 if (StringTable.Data != nullptr && StringTable.Size > Offset) 139 return (StringTable.Data + Offset); 140 141 return make_error<GenericBinaryError>("Bad offset for string table entry", 142 object_error::parse_failed); 143 } 144 145 Expected<StringRef> 146 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { 147 if (CFileEntPtr->NameInStrTbl.Magic != 148 XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) 149 return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); 150 return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); 151 } 152 153 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 154 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 155 156 // A storage class value with the high-order bit on indicates that the name is 157 // a symbolic debugger stabstring. 158 if (SymEntPtr->StorageClass & 0x80) 159 return StringRef("Unimplemented Debug Name"); 160 161 if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) 162 return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName); 163 164 return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset); 165 } 166 167 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 168 uint64_t Result = 0; 169 llvm_unreachable("Not yet implemented!"); 170 return Result; 171 } 172 173 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 174 assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); 175 return toSymbolEntry(Symb)->Value; 176 } 177 178 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 179 uint64_t Result = 0; 180 llvm_unreachable("Not yet implemented!"); 181 return Result; 182 } 183 184 Expected<SymbolRef::Type> 185 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 186 llvm_unreachable("Not yet implemented!"); 187 return SymbolRef::ST_Other; 188 } 189 190 Expected<section_iterator> 191 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 192 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 193 int16_t SectNum = SymEntPtr->SectionNumber; 194 195 if (isReservedSectionNumber(SectNum)) 196 return section_end(); 197 198 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); 199 if (!ExpSec) 200 return ExpSec.takeError(); 201 202 return section_iterator(SectionRef(ExpSec.get(), this)); 203 } 204 205 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 206 const char *Ptr = reinterpret_cast<const char *>(Sec.p); 207 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 208 } 209 210 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 211 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec)); 212 } 213 214 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 215 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 216 // with MSVC. 217 if (is64Bit()) 218 return toSection64(Sec)->VirtualAddress; 219 220 return toSection32(Sec)->VirtualAddress; 221 } 222 223 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 224 // Section numbers in XCOFF are numbered beginning at 1. A section number of 225 // zero is used to indicate that a symbol is being imported or is undefined. 226 if (is64Bit()) 227 return toSection64(Sec) - sectionHeaderTable64() + 1; 228 else 229 return toSection32(Sec) - sectionHeaderTable32() + 1; 230 } 231 232 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 233 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 234 // with MSVC. 235 if (is64Bit()) 236 return toSection64(Sec)->SectionSize; 237 238 return toSection32(Sec)->SectionSize; 239 } 240 241 Expected<ArrayRef<uint8_t>> 242 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 243 llvm_unreachable("Not yet implemented!"); 244 } 245 246 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 247 uint64_t Result = 0; 248 llvm_unreachable("Not yet implemented!"); 249 return Result; 250 } 251 252 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 253 bool Result = false; 254 llvm_unreachable("Not yet implemented!"); 255 return Result; 256 } 257 258 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 259 return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 260 } 261 262 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 263 uint32_t Flags = getSectionFlags(Sec); 264 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 265 } 266 267 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 268 uint32_t Flags = getSectionFlags(Sec); 269 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 270 } 271 272 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 273 bool Result = false; 274 llvm_unreachable("Not yet implemented!"); 275 return Result; 276 } 277 278 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 279 llvm_unreachable("Not yet implemented!"); 280 return relocation_iterator(RelocationRef()); 281 } 282 283 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 284 llvm_unreachable("Not yet implemented!"); 285 return relocation_iterator(RelocationRef()); 286 } 287 288 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 289 llvm_unreachable("Not yet implemented!"); 290 return; 291 } 292 293 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 294 llvm_unreachable("Not yet implemented!"); 295 uint64_t Result = 0; 296 return Result; 297 } 298 299 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 300 llvm_unreachable("Not yet implemented!"); 301 return symbol_iterator(SymbolRef()); 302 } 303 304 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 305 llvm_unreachable("Not yet implemented!"); 306 uint64_t Result = 0; 307 return Result; 308 } 309 310 void XCOFFObjectFile::getRelocationTypeName( 311 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 312 llvm_unreachable("Not yet implemented!"); 313 return; 314 } 315 316 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 317 uint32_t Result = 0; 318 llvm_unreachable("Not yet implemented!"); 319 return Result; 320 } 321 322 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 323 assert(!is64Bit() && "64-bit support not implemented yet."); 324 DataRefImpl SymDRI; 325 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 326 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 327 } 328 329 basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 330 assert(!is64Bit() && "64-bit support not implemented yet."); 331 DataRefImpl SymDRI; 332 SymDRI.p = reinterpret_cast<uintptr_t>( 333 SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); 334 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 335 } 336 337 section_iterator XCOFFObjectFile::section_begin() const { 338 DataRefImpl DRI; 339 DRI.p = getSectionHeaderTableAddress(); 340 return section_iterator(SectionRef(DRI, this)); 341 } 342 343 section_iterator XCOFFObjectFile::section_end() const { 344 DataRefImpl DRI; 345 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 346 getNumberOfSections() * getSectionHeaderSize()); 347 return section_iterator(SectionRef(DRI, this)); 348 } 349 350 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 351 352 StringRef XCOFFObjectFile::getFileFormatName() const { 353 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 354 } 355 356 Triple::ArchType XCOFFObjectFile::getArch() const { 357 return is64Bit() ? Triple::ppc64 : Triple::ppc; 358 } 359 360 SubtargetFeatures XCOFFObjectFile::getFeatures() const { 361 llvm_unreachable("Not yet implemented!"); 362 return SubtargetFeatures(); 363 } 364 365 bool XCOFFObjectFile::isRelocatableObject() const { 366 bool Result = false; 367 llvm_unreachable("Not yet implemented!"); 368 return Result; 369 } 370 371 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 372 // TODO FIXME Should get from auxiliary_header->o_entry when support for the 373 // auxiliary_header is added. 374 return 0; 375 } 376 377 size_t XCOFFObjectFile::getFileHeaderSize() const { 378 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 379 } 380 381 size_t XCOFFObjectFile::getSectionHeaderSize() const { 382 return is64Bit() ? sizeof(XCOFFSectionHeader64) : 383 sizeof(XCOFFSectionHeader32); 384 } 385 386 bool XCOFFObjectFile::is64Bit() const { 387 return Binary::ID_XCOFF64 == getType(); 388 } 389 390 uint16_t XCOFFObjectFile::getMagic() const { 391 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 392 } 393 394 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 395 if (Num <= 0 || Num > getNumberOfSections()) 396 return errorCodeToError(object_error::invalid_section_index); 397 398 DataRefImpl DRI; 399 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 400 getSectionHeaderSize() * (Num - 1)); 401 return DRI; 402 } 403 404 Expected<StringRef> 405 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { 406 assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); 407 int16_t SectionNum = SymEntPtr->SectionNumber; 408 409 switch (SectionNum) { 410 case XCOFF::N_DEBUG: 411 return "N_DEBUG"; 412 case XCOFF::N_ABS: 413 return "N_ABS"; 414 case XCOFF::N_UNDEF: 415 return "N_UNDEF"; 416 default: 417 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 418 if (SecRef) 419 return generateXCOFFFixedNameStringRef( 420 getSectionNameInternal(SecRef.get())); 421 return SecRef.takeError(); 422 } 423 } 424 425 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 426 return (SectionNumber <= 0 && SectionNumber >= -2); 427 } 428 429 uint16_t XCOFFObjectFile::getNumberOfSections() const { 430 return is64Bit() ? fileHeader64()->NumberOfSections 431 : fileHeader32()->NumberOfSections; 432 } 433 434 int32_t XCOFFObjectFile::getTimeStamp() const { 435 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 436 } 437 438 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 439 return is64Bit() ? fileHeader64()->AuxHeaderSize 440 : fileHeader32()->AuxHeaderSize; 441 } 442 443 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 444 return fileHeader32()->SymbolTableOffset; 445 } 446 447 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 448 // As far as symbol table size is concerned, if this field is negative it is 449 // to be treated as a 0. However since this field is also used for printing we 450 // don't want to truncate any negative values. 451 return fileHeader32()->NumberOfSymTableEntries; 452 } 453 454 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 455 return (fileHeader32()->NumberOfSymTableEntries >= 0 456 ? fileHeader32()->NumberOfSymTableEntries 457 : 0); 458 } 459 460 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 461 return fileHeader64()->SymbolTableOffset; 462 } 463 464 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 465 return fileHeader64()->NumberOfSymTableEntries; 466 } 467 468 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 469 uint32_t NumberOfSymTableEntries = 470 is64Bit() ? getNumberOfSymbolTableEntries64() 471 : getLogicalNumberOfSymbolTableEntries32(); 472 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 473 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 474 } 475 476 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 477 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 478 report_fatal_error("Symbol table entry is outside of symbol table."); 479 480 if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 481 report_fatal_error("Symbol table entry is outside of symbol table."); 482 483 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 484 reinterpret_cast<const char *>(SymbolTblPtr); 485 486 if (Offset % XCOFF::SymbolTableEntrySize != 0) 487 report_fatal_error( 488 "Symbol table entry position is not valid inside of symbol table."); 489 } 490 491 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 492 return (reinterpret_cast<const char *>(SymbolEntPtr) - 493 reinterpret_cast<const char *>(SymbolTblPtr)) / 494 XCOFF::SymbolTableEntrySize; 495 } 496 497 uint16_t XCOFFObjectFile::getFlags() const { 498 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 499 } 500 501 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 502 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 503 } 504 505 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 506 return reinterpret_cast<uintptr_t>(SectionHeaderTable); 507 } 508 509 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 510 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 511 } 512 513 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 514 : ObjectFile(Type, Object) { 515 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 516 } 517 518 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 519 assert(is64Bit() && "64-bit interface called for non 64-bit file."); 520 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 521 return ArrayRef<XCOFFSectionHeader64>(TablePtr, 522 TablePtr + getNumberOfSections()); 523 } 524 525 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 526 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 527 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 528 return ArrayRef<XCOFFSectionHeader32>(TablePtr, 529 TablePtr + getNumberOfSections()); 530 } 531 532 Expected<XCOFFStringTable> 533 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 534 // If there is a string table, then the buffer must contain at least 4 bytes 535 // for the string table's size. Not having a string table is not an error. 536 if (auto EC = Binary::checkOffset( 537 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) 538 return XCOFFStringTable{0, nullptr}; 539 540 // Read the size out of the buffer. 541 uint32_t Size = support::endian::read32be(Obj->base() + Offset); 542 543 // If the size is less then 4, then the string table is just a size and no 544 // string data. 545 if (Size <= 4) 546 return XCOFFStringTable{4, nullptr}; 547 548 auto StringTableOrErr = 549 getObject<char>(Obj->Data, Obj->base() + Offset, Size); 550 if (Error E = StringTableOrErr.takeError()) 551 return std::move(E); 552 553 const char *StringTablePtr = StringTableOrErr.get(); 554 if (StringTablePtr[Size - 1] != '\0') 555 return errorCodeToError(object_error::string_table_non_null_end); 556 557 return XCOFFStringTable{Size, StringTablePtr}; 558 } 559 560 Expected<std::unique_ptr<XCOFFObjectFile>> 561 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 562 // Can't use std::make_unique because of the private constructor. 563 std::unique_ptr<XCOFFObjectFile> Obj; 564 Obj.reset(new XCOFFObjectFile(Type, MBR)); 565 566 uint64_t CurOffset = 0; 567 const auto *Base = Obj->base(); 568 MemoryBufferRef Data = Obj->Data; 569 570 // Parse file header. 571 auto FileHeaderOrErr = 572 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 573 if (Error E = FileHeaderOrErr.takeError()) 574 return std::move(E); 575 Obj->FileHeader = FileHeaderOrErr.get(); 576 577 CurOffset += Obj->getFileHeaderSize(); 578 // TODO FIXME we don't have support for an optional header yet, so just skip 579 // past it. 580 CurOffset += Obj->getOptionalHeaderSize(); 581 582 // Parse the section header table if it is present. 583 if (Obj->getNumberOfSections()) { 584 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 585 Obj->getNumberOfSections() * 586 Obj->getSectionHeaderSize()); 587 if (Error E = SecHeadersOrErr.takeError()) 588 return std::move(E); 589 Obj->SectionHeaderTable = SecHeadersOrErr.get(); 590 } 591 592 // 64-bit object supports only file header and section headers for now. 593 if (Obj->is64Bit()) 594 return std::move(Obj); 595 596 // If there is no symbol table we are done parsing the memory buffer. 597 if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0) 598 return std::move(Obj); 599 600 // Parse symbol table. 601 CurOffset = Obj->fileHeader32()->SymbolTableOffset; 602 uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) * 603 Obj->getLogicalNumberOfSymbolTableEntries32(); 604 auto SymTableOrErr = 605 getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize); 606 if (Error E = SymTableOrErr.takeError()) 607 return std::move(E); 608 Obj->SymbolTblPtr = SymTableOrErr.get(); 609 CurOffset += SymbolTableSize; 610 611 // Parse String table. 612 Expected<XCOFFStringTable> StringTableOrErr = 613 parseStringTable(Obj.get(), CurOffset); 614 if (Error E = StringTableOrErr.takeError()) 615 return std::move(E); 616 Obj->StringTable = StringTableOrErr.get(); 617 618 return std::move(Obj); 619 } 620 621 Expected<std::unique_ptr<ObjectFile>> 622 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 623 unsigned FileType) { 624 return XCOFFObjectFile::create(FileType, MemBufRef); 625 } 626 627 StringRef XCOFFSectionHeader32::getName() const { 628 return generateXCOFFFixedNameStringRef(Name); 629 } 630 631 StringRef XCOFFSectionHeader64::getName() const { 632 return generateXCOFFFixedNameStringRef(Name); 633 } 634 635 XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const { 636 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass; 637 } 638 639 uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const { 640 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries; 641 } 642 643 const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const { 644 assert(!OwningObjectPtr->is64Bit() && 645 "32-bit interface called on 64-bit object file."); 646 assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found."); 647 648 // In XCOFF32, the csect auxilliary entry is always the last auxiliary 649 // entry for the symbol. 650 uintptr_t AuxAddr = getWithOffset( 651 SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries()); 652 653 #ifndef NDEBUG 654 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 655 #endif 656 657 return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr); 658 } 659 660 uint16_t XCOFFSymbolRef::getType() const { 661 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType; 662 } 663 664 int16_t XCOFFSymbolRef::getSectionNumber() const { 665 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber; 666 } 667 668 bool XCOFFSymbolRef::hasCsectAuxEnt() const { 669 XCOFF::StorageClass SC = getStorageClass(); 670 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 671 SC == XCOFF::C_HIDEXT); 672 } 673 674 bool XCOFFSymbolRef::isFunction() const { 675 if (OwningObjectPtr->is64Bit()) 676 report_fatal_error("64-bit support is unimplemented yet."); 677 678 if (getType() & FUNCTION_SYM) 679 return true; 680 681 if (!hasCsectAuxEnt()) 682 return false; 683 684 const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32(); 685 686 // A function definition should be a label definition. 687 if ((CsectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD) 688 return false; 689 690 if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR) 691 return false; 692 693 int16_t SectNum = getSectionNumber(); 694 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 695 if (!SI) 696 return false; 697 698 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 699 } 700 701 } // namespace object 702 } // namespace llvm 703