1 //===- Archive.cpp - ar File Format implementation --------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the ArchiveObjectFile class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Object/Archive.h" 15 #include "llvm/ADT/SmallString.h" 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/Support/Endian.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include "llvm/Support/Path.h" 20 21 using namespace llvm; 22 using namespace object; 23 using namespace llvm::support::endian; 24 25 static const char *const Magic = "!<arch>\n"; 26 static const char *const ThinMagic = "!<thin>\n"; 27 28 void Archive::anchor() { } 29 30 static Error 31 malformedError(Twine Msg) { 32 std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")"; 33 return make_error<GenericBinaryError>(std::move(StringMsg), 34 object_error::parse_failed); 35 } 36 37 ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent, 38 const char *RawHeaderPtr, 39 uint64_t Size, Error *Err) 40 : Parent(Parent), 41 ArMemHdr(reinterpret_cast<const ArMemHdrType *>(RawHeaderPtr)) { 42 if (RawHeaderPtr == nullptr) 43 return; 44 ErrorAsOutParameter ErrAsOutParam(Err); 45 46 // TODO: For errors messages with the ArchiveMemberHeader class use the 47 // archive member name instead of the the offset to the archive member header. 48 // When there is also error getting the member name then use the offset to 49 // the member in the message. 50 51 if (Size < sizeof(ArMemHdrType)) { 52 if (Err) { 53 uint64_t Offset = RawHeaderPtr - Parent->getData().data(); 54 *Err = malformedError("remaining size of archive too small for next " 55 "archive member header at offset " + 56 Twine(Offset)); 57 } 58 return; 59 } 60 if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') { 61 if (Err) { 62 std::string Buf; 63 raw_string_ostream OS(Buf); 64 OS.write_escaped(llvm::StringRef(ArMemHdr->Terminator, 65 sizeof(ArMemHdr->Terminator))); 66 OS.flush(); 67 uint64_t Offset = RawHeaderPtr - Parent->getData().data(); 68 *Err = malformedError("terminator characters in archive member \"" + Buf + 69 "\" not the correct \"`\\n\" values for the " 70 "archive member header at offset " + Twine(Offset)); 71 } 72 return; 73 } 74 } 75 76 StringRef ArchiveMemberHeader::getName() const { 77 char EndCond; 78 if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#') 79 EndCond = ' '; 80 else 81 EndCond = '/'; 82 llvm::StringRef::size_type end = 83 llvm::StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond); 84 if (end == llvm::StringRef::npos) 85 end = sizeof(ArMemHdr->Name); 86 assert(end <= sizeof(ArMemHdr->Name) && end > 0); 87 // Don't include the EndCond if there is one. 88 return llvm::StringRef(ArMemHdr->Name, end); 89 } 90 91 Expected<uint32_t> ArchiveMemberHeader::getSize() const { 92 uint32_t Ret; 93 if (llvm::StringRef(ArMemHdr->Size, 94 sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) { 95 std::string Buf; 96 raw_string_ostream OS(Buf); 97 OS.write_escaped(llvm::StringRef(ArMemHdr->Size, 98 sizeof(ArMemHdr->Size)).rtrim(" ")); 99 OS.flush(); 100 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) - 101 Parent->getData().data(); 102 return malformedError("characters in size field in archive header are not " 103 "all decimal numbers: '" + Buf + "' for archive " 104 "member header at offset " + Twine(Offset)); 105 } 106 return Ret; 107 } 108 109 sys::fs::perms ArchiveMemberHeader::getAccessMode() const { 110 unsigned Ret; 111 if (StringRef(ArMemHdr->AccessMode, 112 sizeof(ArMemHdr->AccessMode)).rtrim(' ').getAsInteger(8, Ret)) 113 llvm_unreachable("Access mode is not an octal number."); 114 return static_cast<sys::fs::perms>(Ret); 115 } 116 117 sys::TimeValue ArchiveMemberHeader::getLastModified() const { 118 unsigned Seconds; 119 if (StringRef(ArMemHdr->LastModified, 120 sizeof(ArMemHdr->LastModified)).rtrim(' ') 121 .getAsInteger(10, Seconds)) 122 llvm_unreachable("Last modified time not a decimal number."); 123 124 sys::TimeValue Ret; 125 Ret.fromEpochTime(Seconds); 126 return Ret; 127 } 128 129 unsigned ArchiveMemberHeader::getUID() const { 130 unsigned Ret; 131 StringRef User = StringRef(ArMemHdr->UID, sizeof(ArMemHdr->UID)).rtrim(' '); 132 if (User.empty()) 133 return 0; 134 if (User.getAsInteger(10, Ret)) 135 llvm_unreachable("UID time not a decimal number."); 136 return Ret; 137 } 138 139 unsigned ArchiveMemberHeader::getGID() const { 140 unsigned Ret; 141 StringRef Group = StringRef(ArMemHdr->GID, sizeof(ArMemHdr->GID)).rtrim(' '); 142 if (Group.empty()) 143 return 0; 144 if (Group.getAsInteger(10, Ret)) 145 llvm_unreachable("GID time not a decimal number."); 146 return Ret; 147 } 148 149 Archive::Child::Child(const Archive *Parent, StringRef Data, 150 uint16_t StartOfFile) 151 : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr), 152 Data(Data), StartOfFile(StartOfFile) { 153 } 154 155 Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) 156 : Parent(Parent), Header(Parent, Start, Parent->getData().size() - 157 (Start - Parent->getData().data()), Err) { 158 if (!Start) 159 return; 160 ErrorAsOutParameter ErrAsOutParam(Err); 161 162 // If there was an error in the construction of the Header and we were passed 163 // Err that is not nullptr then just return with the error now set. 164 if (Err && *Err) 165 return; 166 167 uint64_t Size = Header.getSizeOf(); 168 Data = StringRef(Start, Size); 169 if (!isThinMember()) { 170 Expected<uint64_t> MemberSize = getRawSize(); 171 if (!MemberSize) { 172 if (Err) 173 *Err = MemberSize.takeError(); 174 return; 175 } 176 Size += MemberSize.get(); 177 Data = StringRef(Start, Size); 178 } 179 180 // Setup StartOfFile and PaddingBytes. 181 StartOfFile = Header.getSizeOf(); 182 // Don't include attached name. 183 StringRef Name = getRawName(); 184 if (Name.startswith("#1/")) { 185 uint64_t NameSize; 186 if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize)) 187 llvm_unreachable("Long name length is not an integer"); 188 StartOfFile += NameSize; 189 } 190 } 191 192 Expected<uint64_t> Archive::Child::getSize() const { 193 if (Parent->IsThin) { 194 Expected<uint32_t> Size = Header.getSize(); 195 if (!Size) 196 return Size.takeError(); 197 return Size.get(); 198 } 199 return Data.size() - StartOfFile; 200 } 201 202 Expected<uint64_t> Archive::Child::getRawSize() const { 203 return Header.getSize(); 204 } 205 206 bool Archive::Child::isThinMember() const { 207 StringRef Name = Header.getName(); 208 return Parent->IsThin && Name != "/" && Name != "//"; 209 } 210 211 ErrorOr<std::string> Archive::Child::getFullName() const { 212 assert(isThinMember()); 213 ErrorOr<StringRef> NameOrErr = getName(); 214 if (std::error_code EC = NameOrErr.getError()) 215 return EC; 216 StringRef Name = *NameOrErr; 217 if (sys::path::is_absolute(Name)) 218 return Name; 219 220 SmallString<128> FullName = sys::path::parent_path( 221 Parent->getMemoryBufferRef().getBufferIdentifier()); 222 sys::path::append(FullName, Name); 223 return StringRef(FullName); 224 } 225 226 ErrorOr<StringRef> Archive::Child::getBuffer() const { 227 if (!isThinMember()) { 228 Expected<uint32_t> Size = getSize(); 229 if (!Size) 230 return errorToErrorCode(Size.takeError()); 231 return StringRef(Data.data() + StartOfFile, Size.get()); 232 } 233 ErrorOr<std::string> FullNameOrEr = getFullName(); 234 if (std::error_code EC = FullNameOrEr.getError()) 235 return EC; 236 const std::string &FullName = *FullNameOrEr; 237 ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName); 238 if (std::error_code EC = Buf.getError()) 239 return EC; 240 Parent->ThinBuffers.push_back(std::move(*Buf)); 241 return Parent->ThinBuffers.back()->getBuffer(); 242 } 243 244 Expected<Archive::Child> Archive::Child::getNext() const { 245 size_t SpaceToSkip = Data.size(); 246 // If it's odd, add 1 to make it even. 247 if (SpaceToSkip & 1) 248 ++SpaceToSkip; 249 250 const char *NextLoc = Data.data() + SpaceToSkip; 251 252 // Check to see if this is at the end of the archive. 253 if (NextLoc == Parent->Data.getBufferEnd()) 254 return Child(Parent, nullptr, nullptr); 255 256 // Check to see if this is past the end of the archive. 257 if (NextLoc > Parent->Data.getBufferEnd()) { 258 Twine Msg("offset to next archive member past the end of the archive after " 259 "member "); 260 ErrorOr<StringRef> NameOrErr = getName(); 261 if (NameOrErr.getError()) { 262 uint64_t Offset = Data.data() - Parent->getData().data(); 263 return malformedError(Msg + "at offset " + Twine(Offset)); 264 } else 265 return malformedError(Msg + Twine(NameOrErr.get())); 266 } 267 268 Error Err; 269 Child Ret(Parent, NextLoc, &Err); 270 if (Err) 271 return std::move(Err); 272 return Ret; 273 } 274 275 uint64_t Archive::Child::getChildOffset() const { 276 const char *a = Parent->Data.getBuffer().data(); 277 const char *c = Data.data(); 278 uint64_t offset = c - a; 279 return offset; 280 } 281 282 ErrorOr<StringRef> Archive::Child::getName() const { 283 StringRef name = getRawName(); 284 // Check if it's a special name. 285 if (name[0] == '/') { 286 if (name.size() == 1) // Linker member. 287 return name; 288 if (name.size() == 2 && name[1] == '/') // String table. 289 return name; 290 // It's a long name. 291 // Get the offset. 292 std::size_t offset; 293 if (name.substr(1).rtrim(' ').getAsInteger(10, offset)) 294 llvm_unreachable("Long name offset is not an integer"); 295 296 // Verify it. 297 if (offset >= Parent->StringTable.size()) 298 return object_error::parse_failed; 299 const char *addr = Parent->StringTable.begin() + offset; 300 301 // GNU long file names end with a "/\n". 302 if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) { 303 StringRef::size_type End = StringRef(addr).find('\n'); 304 return StringRef(addr, End - 1); 305 } 306 return StringRef(addr); 307 } else if (name.startswith("#1/")) { 308 uint64_t name_size; 309 if (name.substr(3).rtrim(' ').getAsInteger(10, name_size)) 310 llvm_unreachable("Long name length is not an ingeter"); 311 return Data.substr(Header.getSizeOf(), name_size).rtrim('\0'); 312 } else { 313 // It is not a long name so trim the blanks at the end of the name. 314 if (name[name.size() - 1] != '/') { 315 return name.rtrim(' '); 316 } 317 } 318 // It's a simple name. 319 if (name[name.size() - 1] == '/') 320 return name.substr(0, name.size() - 1); 321 return name; 322 } 323 324 ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const { 325 ErrorOr<StringRef> NameOrErr = getName(); 326 if (std::error_code EC = NameOrErr.getError()) 327 return EC; 328 StringRef Name = NameOrErr.get(); 329 ErrorOr<StringRef> Buf = getBuffer(); 330 if (std::error_code EC = Buf.getError()) 331 return EC; 332 return MemoryBufferRef(*Buf, Name); 333 } 334 335 Expected<std::unique_ptr<Binary>> 336 Archive::Child::getAsBinary(LLVMContext *Context) const { 337 ErrorOr<MemoryBufferRef> BuffOrErr = getMemoryBufferRef(); 338 if (std::error_code EC = BuffOrErr.getError()) 339 return errorCodeToError(EC); 340 341 auto BinaryOrErr = createBinary(BuffOrErr.get(), Context); 342 if (BinaryOrErr) 343 return std::move(*BinaryOrErr); 344 return BinaryOrErr.takeError(); 345 } 346 347 Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) { 348 Error Err; 349 std::unique_ptr<Archive> Ret(new Archive(Source, Err)); 350 if (Err) 351 return std::move(Err); 352 return std::move(Ret); 353 } 354 355 void Archive::setFirstRegular(const Child &C) { 356 FirstRegularData = C.Data; 357 FirstRegularStartOfFile = C.StartOfFile; 358 } 359 360 Archive::Archive(MemoryBufferRef Source, Error &Err) 361 : Binary(Binary::ID_Archive, Source) { 362 ErrorAsOutParameter ErrAsOutParam(&Err); 363 StringRef Buffer = Data.getBuffer(); 364 // Check for sufficient magic. 365 if (Buffer.startswith(ThinMagic)) { 366 IsThin = true; 367 } else if (Buffer.startswith(Magic)) { 368 IsThin = false; 369 } else { 370 Err = make_error<GenericBinaryError>("File too small to be an archive", 371 object_error::invalid_file_type); 372 return; 373 } 374 375 // Get the special members. 376 child_iterator I = child_begin(Err, false); 377 if (Err) 378 return; 379 child_iterator E = child_end(); 380 381 // This is at least a valid empty archive. Since an empty archive is the 382 // same in all formats, just claim it to be gnu to make sure Format is 383 // initialized. 384 Format = K_GNU; 385 386 if (I == E) { 387 Err = Error::success(); 388 return; 389 } 390 const Child *C = &*I; 391 392 auto Increment = [&]() { 393 ++I; 394 if (Err) 395 return true; 396 C = &*I; 397 return false; 398 }; 399 400 StringRef Name = C->getRawName(); 401 402 // Below is the pattern that is used to figure out the archive format 403 // GNU archive format 404 // First member : / (may exist, if it exists, points to the symbol table ) 405 // Second member : // (may exist, if it exists, points to the string table) 406 // Note : The string table is used if the filename exceeds 15 characters 407 // BSD archive format 408 // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table) 409 // There is no string table, if the filename exceeds 15 characters or has a 410 // embedded space, the filename has #1/<size>, The size represents the size 411 // of the filename that needs to be read after the archive header 412 // COFF archive format 413 // First member : / 414 // Second member : / (provides a directory of symbols) 415 // Third member : // (may exist, if it exists, contains the string table) 416 // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present 417 // even if the string table is empty. However, lib.exe does not in fact 418 // seem to create the third member if there's no member whose filename 419 // exceeds 15 characters. So the third member is optional. 420 421 if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") { 422 if (Name == "__.SYMDEF") 423 Format = K_BSD; 424 else // Name == "__.SYMDEF_64" 425 Format = K_DARWIN64; 426 // We know that the symbol table is not an external file, so we just assert 427 // there is no error. 428 SymbolTable = *C->getBuffer(); 429 if (Increment()) 430 return; 431 setFirstRegular(*C); 432 433 Err = Error::success(); 434 return; 435 } 436 437 if (Name.startswith("#1/")) { 438 Format = K_BSD; 439 // We know this is BSD, so getName will work since there is no string table. 440 ErrorOr<StringRef> NameOrErr = C->getName(); 441 if (auto ec = NameOrErr.getError()) { 442 Err = errorCodeToError(ec); 443 return; 444 } 445 Name = NameOrErr.get(); 446 if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") { 447 // We know that the symbol table is not an external file, so we just 448 // assert there is no error. 449 SymbolTable = *C->getBuffer(); 450 if (Increment()) 451 return; 452 } 453 else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") { 454 Format = K_DARWIN64; 455 // We know that the symbol table is not an external file, so we just 456 // assert there is no error. 457 SymbolTable = *C->getBuffer(); 458 if (Increment()) 459 return; 460 } 461 setFirstRegular(*C); 462 return; 463 } 464 465 // MIPS 64-bit ELF archives use a special format of a symbol table. 466 // This format is marked by `ar_name` field equals to "/SYM64/". 467 // For detailed description see page 96 in the following document: 468 // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf 469 470 bool has64SymTable = false; 471 if (Name == "/" || Name == "/SYM64/") { 472 // We know that the symbol table is not an external file, so we just assert 473 // there is no error. 474 SymbolTable = *C->getBuffer(); 475 if (Name == "/SYM64/") 476 has64SymTable = true; 477 478 if (Increment()) 479 return; 480 if (I == E) { 481 Err = Error::success(); 482 return; 483 } 484 Name = C->getRawName(); 485 } 486 487 if (Name == "//") { 488 Format = has64SymTable ? K_MIPS64 : K_GNU; 489 // The string table is never an external member, so we just assert on the 490 // ErrorOr. 491 StringTable = *C->getBuffer(); 492 if (Increment()) 493 return; 494 setFirstRegular(*C); 495 Err = Error::success(); 496 return; 497 } 498 499 if (Name[0] != '/') { 500 Format = has64SymTable ? K_MIPS64 : K_GNU; 501 setFirstRegular(*C); 502 Err = Error::success(); 503 return; 504 } 505 506 if (Name != "/") { 507 Err = errorCodeToError(object_error::parse_failed); 508 return; 509 } 510 511 Format = K_COFF; 512 // We know that the symbol table is not an external file, so we just assert 513 // there is no error. 514 SymbolTable = *C->getBuffer(); 515 516 if (Increment()) 517 return; 518 519 if (I == E) { 520 setFirstRegular(*C); 521 Err = Error::success(); 522 return; 523 } 524 525 Name = C->getRawName(); 526 527 if (Name == "//") { 528 // The string table is never an external member, so we just assert on the 529 // ErrorOr. 530 StringTable = *C->getBuffer(); 531 if (Increment()) 532 return; 533 } 534 535 setFirstRegular(*C); 536 Err = Error::success(); 537 } 538 539 Archive::child_iterator Archive::child_begin(Error &Err, 540 bool SkipInternal) const { 541 if (Data.getBufferSize() == 8) // empty archive. 542 return child_end(); 543 544 if (SkipInternal) 545 return child_iterator(Child(this, FirstRegularData, 546 FirstRegularStartOfFile), 547 &Err); 548 549 const char *Loc = Data.getBufferStart() + strlen(Magic); 550 Child C(this, Loc, &Err); 551 if (Err) 552 return child_end(); 553 return child_iterator(C, &Err); 554 } 555 556 Archive::child_iterator Archive::child_end() const { 557 return child_iterator(Child(this, nullptr, nullptr), nullptr); 558 } 559 560 StringRef Archive::Symbol::getName() const { 561 return Parent->getSymbolTable().begin() + StringIndex; 562 } 563 564 ErrorOr<Archive::Child> Archive::Symbol::getMember() const { 565 const char *Buf = Parent->getSymbolTable().begin(); 566 const char *Offsets = Buf; 567 if (Parent->kind() == K_MIPS64 || Parent->kind() == K_DARWIN64) 568 Offsets += sizeof(uint64_t); 569 else 570 Offsets += sizeof(uint32_t); 571 uint32_t Offset = 0; 572 if (Parent->kind() == K_GNU) { 573 Offset = read32be(Offsets + SymbolIndex * 4); 574 } else if (Parent->kind() == K_MIPS64) { 575 Offset = read64be(Offsets + SymbolIndex * 8); 576 } else if (Parent->kind() == K_BSD) { 577 // The SymbolIndex is an index into the ranlib structs that start at 578 // Offsets (the first uint32_t is the number of bytes of the ranlib 579 // structs). The ranlib structs are a pair of uint32_t's the first 580 // being a string table offset and the second being the offset into 581 // the archive of the member that defines the symbol. Which is what 582 // is needed here. 583 Offset = read32le(Offsets + SymbolIndex * 8 + 4); 584 } else if (Parent->kind() == K_DARWIN64) { 585 // The SymbolIndex is an index into the ranlib_64 structs that start at 586 // Offsets (the first uint64_t is the number of bytes of the ranlib_64 587 // structs). The ranlib_64 structs are a pair of uint64_t's the first 588 // being a string table offset and the second being the offset into 589 // the archive of the member that defines the symbol. Which is what 590 // is needed here. 591 Offset = read64le(Offsets + SymbolIndex * 16 + 8); 592 } else { 593 // Skip offsets. 594 uint32_t MemberCount = read32le(Buf); 595 Buf += MemberCount * 4 + 4; 596 597 uint32_t SymbolCount = read32le(Buf); 598 if (SymbolIndex >= SymbolCount) 599 return object_error::parse_failed; 600 601 // Skip SymbolCount to get to the indices table. 602 const char *Indices = Buf + 4; 603 604 // Get the index of the offset in the file member offset table for this 605 // symbol. 606 uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2); 607 // Subtract 1 since OffsetIndex is 1 based. 608 --OffsetIndex; 609 610 if (OffsetIndex >= MemberCount) 611 return object_error::parse_failed; 612 613 Offset = read32le(Offsets + OffsetIndex * 4); 614 } 615 616 const char *Loc = Parent->getData().begin() + Offset; 617 Error Err; 618 Child C(Parent, Loc, &Err); 619 if (Err) 620 return errorToErrorCode(std::move(Err)); 621 return C; 622 } 623 624 Archive::Symbol Archive::Symbol::getNext() const { 625 Symbol t(*this); 626 if (Parent->kind() == K_BSD) { 627 // t.StringIndex is an offset from the start of the __.SYMDEF or 628 // "__.SYMDEF SORTED" member into the string table for the ranlib 629 // struct indexed by t.SymbolIndex . To change t.StringIndex to the 630 // offset in the string table for t.SymbolIndex+1 we subtract the 631 // its offset from the start of the string table for t.SymbolIndex 632 // and add the offset of the string table for t.SymbolIndex+1. 633 634 // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t 635 // which is the number of bytes of ranlib structs that follow. The ranlib 636 // structs are a pair of uint32_t's the first being a string table offset 637 // and the second being the offset into the archive of the member that 638 // define the symbol. After that the next uint32_t is the byte count of 639 // the string table followed by the string table. 640 const char *Buf = Parent->getSymbolTable().begin(); 641 uint32_t RanlibCount = 0; 642 RanlibCount = read32le(Buf) / 8; 643 // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount) 644 // don't change the t.StringIndex as we don't want to reference a ranlib 645 // past RanlibCount. 646 if (t.SymbolIndex + 1 < RanlibCount) { 647 const char *Ranlibs = Buf + 4; 648 uint32_t CurRanStrx = 0; 649 uint32_t NextRanStrx = 0; 650 CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8); 651 NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8); 652 t.StringIndex -= CurRanStrx; 653 t.StringIndex += NextRanStrx; 654 } 655 } else { 656 // Go to one past next null. 657 t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1; 658 } 659 ++t.SymbolIndex; 660 return t; 661 } 662 663 Archive::symbol_iterator Archive::symbol_begin() const { 664 if (!hasSymbolTable()) 665 return symbol_iterator(Symbol(this, 0, 0)); 666 667 const char *buf = getSymbolTable().begin(); 668 if (kind() == K_GNU) { 669 uint32_t symbol_count = 0; 670 symbol_count = read32be(buf); 671 buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); 672 } else if (kind() == K_MIPS64) { 673 uint64_t symbol_count = read64be(buf); 674 buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t))); 675 } else if (kind() == K_BSD) { 676 // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t 677 // which is the number of bytes of ranlib structs that follow. The ranlib 678 // structs are a pair of uint32_t's the first being a string table offset 679 // and the second being the offset into the archive of the member that 680 // define the symbol. After that the next uint32_t is the byte count of 681 // the string table followed by the string table. 682 uint32_t ranlib_count = 0; 683 ranlib_count = read32le(buf) / 8; 684 const char *ranlibs = buf + 4; 685 uint32_t ran_strx = 0; 686 ran_strx = read32le(ranlibs); 687 buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); 688 // Skip the byte count of the string table. 689 buf += sizeof(uint32_t); 690 buf += ran_strx; 691 } else if (kind() == K_DARWIN64) { 692 // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t 693 // which is the number of bytes of ranlib_64 structs that follow. The 694 // ranlib_64 structs are a pair of uint64_t's the first being a string 695 // table offset and the second being the offset into the archive of the 696 // member that define the symbol. After that the next uint64_t is the byte 697 // count of the string table followed by the string table. 698 uint64_t ranlib_count = 0; 699 ranlib_count = read64le(buf) / 16; 700 const char *ranlibs = buf + 8; 701 uint64_t ran_strx = 0; 702 ran_strx = read64le(ranlibs); 703 buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t)))); 704 // Skip the byte count of the string table. 705 buf += sizeof(uint64_t); 706 buf += ran_strx; 707 } else { 708 uint32_t member_count = 0; 709 uint32_t symbol_count = 0; 710 member_count = read32le(buf); 711 buf += 4 + (member_count * 4); // Skip offsets. 712 symbol_count = read32le(buf); 713 buf += 4 + (symbol_count * 2); // Skip indices. 714 } 715 uint32_t string_start_offset = buf - getSymbolTable().begin(); 716 return symbol_iterator(Symbol(this, 0, string_start_offset)); 717 } 718 719 Archive::symbol_iterator Archive::symbol_end() const { 720 return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0)); 721 } 722 723 uint32_t Archive::getNumberOfSymbols() const { 724 if (!hasSymbolTable()) 725 return 0; 726 const char *buf = getSymbolTable().begin(); 727 if (kind() == K_GNU) 728 return read32be(buf); 729 if (kind() == K_MIPS64) 730 return read64be(buf); 731 if (kind() == K_BSD) 732 return read32le(buf) / 8; 733 if (kind() == K_DARWIN64) 734 return read64le(buf) / 16; 735 uint32_t member_count = 0; 736 member_count = read32le(buf); 737 buf += 4 + (member_count * 4); // Skip offsets. 738 return read32le(buf); 739 } 740 741 Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const { 742 Archive::symbol_iterator bs = symbol_begin(); 743 Archive::symbol_iterator es = symbol_end(); 744 745 for (; bs != es; ++bs) { 746 StringRef SymName = bs->getName(); 747 if (SymName == name) { 748 if (auto MemberOrErr = bs->getMember()) 749 return Child(*MemberOrErr); 750 else 751 return errorCodeToError(MemberOrErr.getError()); 752 } 753 } 754 return Optional<Child>(); 755 } 756 757 bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); } 758