1 //===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 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 // Builds up (relatively) standard unix archive files (.a) containing LLVM 11 // bitcode or other files. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Object/Archive.h" 18 #include "llvm/Object/ObjectFile.h" 19 #include "llvm/Support/CommandLine.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/ManagedStatic.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "llvm/Support/PrettyStackTrace.h" 25 #include "llvm/Support/Signals.h" 26 #include "llvm/Support/ToolOutputFile.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <algorithm> 29 #include <cstdlib> 30 #include <memory> 31 32 #if !defined(_MSC_VER) && !defined(__MINGW32__) 33 #include <unistd.h> 34 #else 35 #include <io.h> 36 #endif 37 38 using namespace llvm; 39 40 // The name this program was invoked as. 41 static StringRef ToolName; 42 43 static const char *TemporaryOutput; 44 static int TmpArchiveFD = -1; 45 46 // fail - Show the error message and exit. 47 LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) { 48 outs() << ToolName << ": " << Error << ".\n"; 49 if (TmpArchiveFD != -1) 50 close(TmpArchiveFD); 51 if (TemporaryOutput) 52 sys::fs::remove(TemporaryOutput); 53 exit(1); 54 } 55 56 static void failIfError(error_code EC, Twine Context = "") { 57 if (!EC) 58 return; 59 60 std::string ContextStr = Context.str(); 61 if (ContextStr == "") 62 fail(EC.message()); 63 fail(Context + ": " + EC.message()); 64 } 65 66 // llvm-ar/llvm-ranlib remaining positional arguments. 67 static cl::list<std::string> 68 RestOfArgs(cl::Positional, cl::OneOrMore, 69 cl::desc("[relpos] [count] <archive-file> [members]...")); 70 71 std::string Options; 72 73 // MoreHelp - Provide additional help output explaining the operations and 74 // modifiers of llvm-ar. This object instructs the CommandLine library 75 // to print the text of the constructor when the --help option is given. 76 static cl::extrahelp MoreHelp( 77 "\nOPERATIONS:\n" 78 " d[NsS] - delete file(s) from the archive\n" 79 " m[abiSs] - move file(s) in the archive\n" 80 " p[kN] - print file(s) found in the archive\n" 81 " q[ufsS] - quick append file(s) to the archive\n" 82 " r[abfiuRsS] - replace or insert file(s) into the archive\n" 83 " t - display contents of archive\n" 84 " x[No] - extract file(s) from the archive\n" 85 "\nMODIFIERS (operation specific):\n" 86 " [a] - put file(s) after [relpos]\n" 87 " [b] - put file(s) before [relpos] (same as [i])\n" 88 " [i] - put file(s) before [relpos] (same as [b])\n" 89 " [N] - use instance [count] of name\n" 90 " [o] - preserve original dates\n" 91 " [s] - create an archive index (cf. ranlib)\n" 92 " [S] - do not build a symbol table\n" 93 " [u] - update only files newer than archive contents\n" 94 "\nMODIFIERS (generic):\n" 95 " [c] - do not warn if the library had to be created\n" 96 " [v] - be verbose about actions taken\n" 97 ); 98 99 // This enumeration delineates the kinds of operations on an archive 100 // that are permitted. 101 enum ArchiveOperation { 102 Print, ///< Print the contents of the archive 103 Delete, ///< Delete the specified members 104 Move, ///< Move members to end or as given by {a,b,i} modifiers 105 QuickAppend, ///< Quickly append to end of archive 106 ReplaceOrInsert, ///< Replace or Insert members 107 DisplayTable, ///< Display the table of contents 108 Extract, ///< Extract files back to file system 109 CreateSymTab ///< Create a symbol table in an existing archive 110 }; 111 112 // Modifiers to follow operation to vary behavior 113 static bool AddAfter = false; ///< 'a' modifier 114 static bool AddBefore = false; ///< 'b' modifier 115 static bool Create = false; ///< 'c' modifier 116 static bool OriginalDates = false; ///< 'o' modifier 117 static bool OnlyUpdate = false; ///< 'u' modifier 118 static bool Verbose = false; ///< 'v' modifier 119 static bool Symtab = true; ///< 's' modifier 120 121 // Relative Positional Argument (for insert/move). This variable holds 122 // the name of the archive member to which the 'a', 'b' or 'i' modifier 123 // refers. Only one of 'a', 'b' or 'i' can be specified so we only need 124 // one variable. 125 static std::string RelPos; 126 127 // This variable holds the name of the archive file as given on the 128 // command line. 129 static std::string ArchiveName; 130 131 // This variable holds the list of member files to proecess, as given 132 // on the command line. 133 static std::vector<std::string> Members; 134 135 // show_help - Show the error message, the help message and exit. 136 LLVM_ATTRIBUTE_NORETURN static void 137 show_help(const std::string &msg) { 138 errs() << ToolName << ": " << msg << "\n\n"; 139 cl::PrintHelpMessage(); 140 std::exit(1); 141 } 142 143 // getRelPos - Extract the member filename from the command line for 144 // the [relpos] argument associated with a, b, and i modifiers 145 static void getRelPos() { 146 if(RestOfArgs.size() == 0) 147 show_help("Expected [relpos] for a, b, or i modifier"); 148 RelPos = RestOfArgs[0]; 149 RestOfArgs.erase(RestOfArgs.begin()); 150 } 151 152 static void getOptions() { 153 if(RestOfArgs.size() == 0) 154 show_help("Expected options"); 155 Options = RestOfArgs[0]; 156 RestOfArgs.erase(RestOfArgs.begin()); 157 } 158 159 // getArchive - Get the archive file name from the command line 160 static void getArchive() { 161 if(RestOfArgs.size() == 0) 162 show_help("An archive name must be specified"); 163 ArchiveName = RestOfArgs[0]; 164 RestOfArgs.erase(RestOfArgs.begin()); 165 } 166 167 // getMembers - Copy over remaining items in RestOfArgs to our Members vector 168 // This is just for clarity. 169 static void getMembers() { 170 if(RestOfArgs.size() > 0) 171 Members = std::vector<std::string>(RestOfArgs); 172 } 173 174 // parseCommandLine - Parse the command line options as presented and return the 175 // operation specified. Process all modifiers and check to make sure that 176 // constraints on modifier/operation pairs have not been violated. 177 static ArchiveOperation parseCommandLine() { 178 getOptions(); 179 180 // Keep track of number of operations. We can only specify one 181 // per execution. 182 unsigned NumOperations = 0; 183 184 // Keep track of the number of positional modifiers (a,b,i). Only 185 // one can be specified. 186 unsigned NumPositional = 0; 187 188 // Keep track of which operation was requested 189 ArchiveOperation Operation; 190 191 bool MaybeJustCreateSymTab = false; 192 193 for(unsigned i=0; i<Options.size(); ++i) { 194 switch(Options[i]) { 195 case 'd': ++NumOperations; Operation = Delete; break; 196 case 'm': ++NumOperations; Operation = Move ; break; 197 case 'p': ++NumOperations; Operation = Print; break; 198 case 'q': ++NumOperations; Operation = QuickAppend; break; 199 case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 200 case 't': ++NumOperations; Operation = DisplayTable; break; 201 case 'x': ++NumOperations; Operation = Extract; break; 202 case 'c': Create = true; break; 203 case 'l': /* accepted but unused */ break; 204 case 'o': OriginalDates = true; break; 205 case 's': 206 Symtab = true; 207 MaybeJustCreateSymTab = true; 208 break; 209 case 'S': 210 Symtab = false; 211 break; 212 case 'u': OnlyUpdate = true; break; 213 case 'v': Verbose = true; break; 214 case 'a': 215 getRelPos(); 216 AddAfter = true; 217 NumPositional++; 218 break; 219 case 'b': 220 getRelPos(); 221 AddBefore = true; 222 NumPositional++; 223 break; 224 case 'i': 225 getRelPos(); 226 AddBefore = true; 227 NumPositional++; 228 break; 229 default: 230 cl::PrintHelpMessage(); 231 } 232 } 233 234 // At this point, the next thing on the command line must be 235 // the archive name. 236 getArchive(); 237 238 // Everything on the command line at this point is a member. 239 getMembers(); 240 241 if (NumOperations == 0 && MaybeJustCreateSymTab) { 242 NumOperations = 1; 243 Operation = CreateSymTab; 244 if (!Members.empty()) 245 show_help("The s operation takes only an archive as argument"); 246 } 247 248 // Perform various checks on the operation/modifier specification 249 // to make sure we are dealing with a legal request. 250 if (NumOperations == 0) 251 show_help("You must specify at least one of the operations"); 252 if (NumOperations > 1) 253 show_help("Only one operation may be specified"); 254 if (NumPositional > 1) 255 show_help("You may only specify one of a, b, and i modifiers"); 256 if (AddAfter || AddBefore) { 257 if (Operation != Move && Operation != ReplaceOrInsert) 258 show_help("The 'a', 'b' and 'i' modifiers can only be specified with " 259 "the 'm' or 'r' operations"); 260 } 261 if (OriginalDates && Operation != Extract) 262 show_help("The 'o' modifier is only applicable to the 'x' operation"); 263 if (OnlyUpdate && Operation != ReplaceOrInsert) 264 show_help("The 'u' modifier is only applicable to the 'r' operation"); 265 266 // Return the parsed operation to the caller 267 return Operation; 268 } 269 270 // Implements the 'p' operation. This function traverses the archive 271 // looking for members that match the path list. 272 static void doPrint(StringRef Name, object::Archive::child_iterator I) { 273 if (Verbose) 274 outs() << "Printing " << Name << "\n"; 275 276 StringRef Data = I->getBuffer(); 277 outs().write(Data.data(), Data.size()); 278 } 279 280 // putMode - utility function for printing out the file mode when the 't' 281 // operation is in verbose mode. 282 static void printMode(unsigned mode) { 283 if (mode & 004) 284 outs() << "r"; 285 else 286 outs() << "-"; 287 if (mode & 002) 288 outs() << "w"; 289 else 290 outs() << "-"; 291 if (mode & 001) 292 outs() << "x"; 293 else 294 outs() << "-"; 295 } 296 297 // Implement the 't' operation. This function prints out just 298 // the file names of each of the members. However, if verbose mode is requested 299 // ('v' modifier) then the file type, permission mode, user, group, size, and 300 // modification time are also printed. 301 static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) { 302 if (Verbose) { 303 sys::fs::perms Mode = I->getAccessMode(); 304 printMode((Mode >> 6) & 007); 305 printMode((Mode >> 3) & 007); 306 printMode(Mode & 007); 307 outs() << ' ' << I->getUID(); 308 outs() << '/' << I->getGID(); 309 outs() << ' ' << format("%6llu", I->getSize()); 310 outs() << ' ' << I->getLastModified().str(); 311 outs() << ' '; 312 } 313 outs() << Name << "\n"; 314 } 315 316 // Implement the 'x' operation. This function extracts files back to the file 317 // system. 318 static void doExtract(StringRef Name, object::Archive::child_iterator I) { 319 // Retain the original mode. 320 sys::fs::perms Mode = I->getAccessMode(); 321 SmallString<128> Storage = Name; 322 323 int FD; 324 failIfError( 325 sys::fs::openFileForWrite(Storage.c_str(), FD, sys::fs::F_Binary, Mode), 326 Storage.c_str()); 327 328 { 329 raw_fd_ostream file(FD, false); 330 331 // Get the data and its length 332 StringRef Data = I->getBuffer(); 333 334 // Write the data. 335 file.write(Data.data(), Data.size()); 336 } 337 338 // If we're supposed to retain the original modification times, etc. do so 339 // now. 340 if (OriginalDates) 341 failIfError( 342 sys::fs::setLastModificationAndAccessTime(FD, I->getLastModified())); 343 344 if (close(FD)) 345 fail("Could not close the file"); 346 } 347 348 static bool shouldCreateArchive(ArchiveOperation Op) { 349 switch (Op) { 350 case Print: 351 case Delete: 352 case Move: 353 case DisplayTable: 354 case Extract: 355 case CreateSymTab: 356 return false; 357 358 case QuickAppend: 359 case ReplaceOrInsert: 360 return true; 361 } 362 363 llvm_unreachable("Missing entry in covered switch."); 364 } 365 366 static void performReadOperation(ArchiveOperation Operation, 367 object::Archive *OldArchive) { 368 for (object::Archive::child_iterator I = OldArchive->child_begin(), 369 E = OldArchive->child_end(); 370 I != E; ++I) { 371 StringRef Name; 372 failIfError(I->getName(Name)); 373 374 if (!Members.empty() && 375 std::find(Members.begin(), Members.end(), Name) == Members.end()) 376 continue; 377 378 switch (Operation) { 379 default: 380 llvm_unreachable("Not a read operation"); 381 case Print: 382 doPrint(Name, I); 383 break; 384 case DisplayTable: 385 doDisplayTable(Name, I); 386 break; 387 case Extract: 388 doExtract(Name, I); 389 break; 390 } 391 } 392 } 393 394 namespace { 395 class NewArchiveIterator { 396 bool IsNewMember; 397 StringRef Name; 398 399 object::Archive::child_iterator OldI; 400 401 std::string NewFilename; 402 mutable int NewFD; 403 mutable sys::fs::file_status NewStatus; 404 405 public: 406 NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); 407 NewArchiveIterator(std::string *I, StringRef Name); 408 NewArchiveIterator(); 409 bool isNewMember() const; 410 StringRef getName() const; 411 412 object::Archive::child_iterator getOld() const; 413 414 const char *getNew() const; 415 int getFD() const; 416 const sys::fs::file_status &getStatus() const; 417 }; 418 } 419 420 NewArchiveIterator::NewArchiveIterator() {} 421 422 NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I, 423 StringRef Name) 424 : IsNewMember(false), Name(Name), OldI(I) {} 425 426 NewArchiveIterator::NewArchiveIterator(std::string *NewFilename, StringRef Name) 427 : IsNewMember(true), Name(Name), NewFilename(*NewFilename), NewFD(-1) {} 428 429 StringRef NewArchiveIterator::getName() const { return Name; } 430 431 bool NewArchiveIterator::isNewMember() const { return IsNewMember; } 432 433 object::Archive::child_iterator NewArchiveIterator::getOld() const { 434 assert(!IsNewMember); 435 return OldI; 436 } 437 438 const char *NewArchiveIterator::getNew() const { 439 assert(IsNewMember); 440 return NewFilename.c_str(); 441 } 442 443 int NewArchiveIterator::getFD() const { 444 assert(IsNewMember); 445 if (NewFD != -1) 446 return NewFD; 447 failIfError(sys::fs::openFileForRead(NewFilename, NewFD), NewFilename); 448 assert(NewFD != -1); 449 450 failIfError(sys::fs::status(NewFD, NewStatus), NewFilename); 451 452 // Opening a directory doesn't make sense. Let it fail. 453 // Linux cannot open directories with open(2), although 454 // cygwin and *bsd can. 455 if (NewStatus.type() == sys::fs::file_type::directory_file) 456 failIfError(error_code(errc::is_a_directory, posix_category()), 457 NewFilename); 458 459 return NewFD; 460 } 461 462 const sys::fs::file_status &NewArchiveIterator::getStatus() const { 463 assert(IsNewMember); 464 assert(NewFD != -1 && "Must call getFD first"); 465 return NewStatus; 466 } 467 468 template <typename T> 469 void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name, 470 int Pos = -1) { 471 NewArchiveIterator NI(I, Name); 472 if (Pos == -1) 473 Members.push_back(NI); 474 else 475 Members[Pos] = NI; 476 } 477 478 namespace { 479 class HasName { 480 StringRef Name; 481 482 public: 483 HasName(StringRef Name) : Name(Name) {} 484 bool operator()(StringRef Path) { return Name == sys::path::filename(Path); } 485 }; 486 } 487 488 enum InsertAction { 489 IA_AddOldMember, 490 IA_AddNewMeber, 491 IA_Delete, 492 IA_MoveOldMember, 493 IA_MoveNewMember 494 }; 495 496 static InsertAction 497 computeInsertAction(ArchiveOperation Operation, 498 object::Archive::child_iterator I, StringRef Name, 499 std::vector<std::string>::iterator &Pos) { 500 if (Operation == QuickAppend || Members.empty()) 501 return IA_AddOldMember; 502 503 std::vector<std::string>::iterator MI = 504 std::find_if(Members.begin(), Members.end(), HasName(Name)); 505 506 if (MI == Members.end()) 507 return IA_AddOldMember; 508 509 Pos = MI; 510 511 if (Operation == Delete) 512 return IA_Delete; 513 514 if (Operation == Move) 515 return IA_MoveOldMember; 516 517 if (Operation == ReplaceOrInsert) { 518 StringRef PosName = sys::path::filename(RelPos); 519 if (!OnlyUpdate) { 520 if (PosName.empty()) 521 return IA_AddNewMeber; 522 return IA_MoveNewMember; 523 } 524 525 // We could try to optimize this to a fstat, but it is not a common 526 // operation. 527 sys::fs::file_status Status; 528 failIfError(sys::fs::status(*MI, Status)); 529 if (Status.getLastModificationTime() < I->getLastModified()) { 530 if (PosName.empty()) 531 return IA_AddOldMember; 532 return IA_MoveOldMember; 533 } 534 535 if (PosName.empty()) 536 return IA_AddNewMeber; 537 return IA_MoveNewMember; 538 } 539 llvm_unreachable("No such operation"); 540 } 541 542 // We have to walk this twice and computing it is not trivial, so creating an 543 // explicit std::vector is actually fairly efficient. 544 static std::vector<NewArchiveIterator> 545 computeNewArchiveMembers(ArchiveOperation Operation, 546 object::Archive *OldArchive) { 547 std::vector<NewArchiveIterator> Ret; 548 std::vector<NewArchiveIterator> Moved; 549 int InsertPos = -1; 550 StringRef PosName = sys::path::filename(RelPos); 551 if (OldArchive) { 552 for (object::Archive::child_iterator I = OldArchive->child_begin(), 553 E = OldArchive->child_end(); 554 I != E; ++I) { 555 int Pos = Ret.size(); 556 StringRef Name; 557 failIfError(I->getName(Name)); 558 if (Name == PosName) { 559 assert(AddAfter || AddBefore); 560 if (AddBefore) 561 InsertPos = Pos; 562 else 563 InsertPos = Pos + 1; 564 } 565 566 std::vector<std::string>::iterator MemberI = Members.end(); 567 InsertAction Action = computeInsertAction(Operation, I, Name, MemberI); 568 switch (Action) { 569 case IA_AddOldMember: 570 addMember(Ret, I, Name); 571 break; 572 case IA_AddNewMeber: 573 addMember(Ret, &*MemberI, Name); 574 break; 575 case IA_Delete: 576 break; 577 case IA_MoveOldMember: 578 addMember(Moved, I, Name); 579 break; 580 case IA_MoveNewMember: 581 addMember(Moved, &*MemberI, Name); 582 break; 583 } 584 if (MemberI != Members.end()) 585 Members.erase(MemberI); 586 } 587 } 588 589 if (Operation == Delete) 590 return Ret; 591 592 if (!RelPos.empty() && InsertPos == -1) 593 fail("Insertion point not found"); 594 595 if (RelPos.empty()) 596 InsertPos = Ret.size(); 597 598 assert(unsigned(InsertPos) <= Ret.size()); 599 Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end()); 600 601 Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator()); 602 int Pos = InsertPos; 603 for (std::vector<std::string>::iterator I = Members.begin(), 604 E = Members.end(); 605 I != E; ++I, ++Pos) { 606 StringRef Name = sys::path::filename(*I); 607 addMember(Ret, &*I, Name, Pos); 608 } 609 610 return Ret; 611 } 612 613 template <typename T> 614 static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size, 615 bool MayTruncate = false) { 616 uint64_t OldPos = OS.tell(); 617 OS << Data; 618 unsigned SizeSoFar = OS.tell() - OldPos; 619 if (Size > SizeSoFar) { 620 unsigned Remaining = Size - SizeSoFar; 621 for (unsigned I = 0; I < Remaining; ++I) 622 OS << ' '; 623 } else if (Size < SizeSoFar) { 624 assert(MayTruncate && "Data doesn't fit in Size"); 625 // Some of the data this is used for (like UID) can be larger than the 626 // space available in the archive format. Truncate in that case. 627 OS.seek(OldPos + Size); 628 } 629 } 630 631 static void print32BE(raw_fd_ostream &Out, unsigned Val) { 632 for (int I = 3; I >= 0; --I) { 633 char V = (Val >> (8 * I)) & 0xff; 634 Out << V; 635 } 636 } 637 638 static void printRestOfMemberHeader(raw_fd_ostream &Out, 639 const sys::TimeValue &ModTime, unsigned UID, 640 unsigned GID, unsigned Perms, 641 unsigned Size) { 642 printWithSpacePadding(Out, ModTime.toEpochTime(), 12); 643 printWithSpacePadding(Out, UID, 6, true); 644 printWithSpacePadding(Out, GID, 6, true); 645 printWithSpacePadding(Out, format("%o", Perms), 8); 646 printWithSpacePadding(Out, Size, 10); 647 Out << "`\n"; 648 } 649 650 static void printMemberHeader(raw_fd_ostream &Out, StringRef Name, 651 const sys::TimeValue &ModTime, unsigned UID, 652 unsigned GID, unsigned Perms, unsigned Size) { 653 printWithSpacePadding(Out, Twine(Name) + "/", 16); 654 printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); 655 } 656 657 static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset, 658 const sys::TimeValue &ModTime, unsigned UID, 659 unsigned GID, unsigned Perms, unsigned Size) { 660 Out << '/'; 661 printWithSpacePadding(Out, NameOffset, 15); 662 printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); 663 } 664 665 static void writeStringTable(raw_fd_ostream &Out, 666 ArrayRef<NewArchiveIterator> Members, 667 std::vector<unsigned> &StringMapIndexes) { 668 unsigned StartOffset = 0; 669 for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), 670 E = Members.end(); 671 I != E; ++I) { 672 StringRef Name = I->getName(); 673 if (Name.size() < 16) 674 continue; 675 if (StartOffset == 0) { 676 printWithSpacePadding(Out, "//", 58); 677 Out << "`\n"; 678 StartOffset = Out.tell(); 679 } 680 StringMapIndexes.push_back(Out.tell() - StartOffset); 681 Out << Name << "/\n"; 682 } 683 if (StartOffset == 0) 684 return; 685 if (Out.tell() % 2) 686 Out << '\n'; 687 int Pos = Out.tell(); 688 Out.seek(StartOffset - 12); 689 printWithSpacePadding(Out, Pos - StartOffset, 10); 690 Out.seek(Pos); 691 } 692 693 static void writeSymbolTable( 694 raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members, 695 ArrayRef<MemoryBuffer *> Buffers, 696 std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) { 697 unsigned StartOffset = 0; 698 unsigned MemberNum = 0; 699 std::vector<StringRef> SymNames; 700 std::vector<object::ObjectFile *> DeleteIt; 701 for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), 702 E = Members.end(); 703 I != E; ++I, ++MemberNum) { 704 MemoryBuffer *MemberBuffer = Buffers[MemberNum]; 705 ErrorOr<object::ObjectFile *> ObjOrErr = 706 object::ObjectFile::createObjectFile(MemberBuffer, false, 707 sys::fs::file_magic::unknown); 708 if (!ObjOrErr) 709 continue; // FIXME: check only for "not an object file" errors. 710 object::ObjectFile *Obj = ObjOrErr.get(); 711 712 DeleteIt.push_back(Obj); 713 if (!StartOffset) { 714 printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); 715 StartOffset = Out.tell(); 716 print32BE(Out, 0); 717 } 718 719 for (object::symbol_iterator I = Obj->symbol_begin(), 720 E = Obj->symbol_end(); 721 I != E; ++I) { 722 uint32_t Symflags = I->getFlags();; 723 if (Symflags & object::SymbolRef::SF_FormatSpecific) 724 continue; 725 if (!(Symflags & object::SymbolRef::SF_Global)) 726 continue; 727 if (Symflags & object::SymbolRef::SF_Undefined) 728 continue; 729 StringRef Name; 730 failIfError(I->getName(Name)); 731 SymNames.push_back(Name); 732 MemberOffsetRefs.push_back(std::make_pair(Out.tell(), MemberNum)); 733 print32BE(Out, 0); 734 } 735 } 736 for (std::vector<StringRef>::iterator I = SymNames.begin(), 737 E = SymNames.end(); 738 I != E; ++I) { 739 Out << *I; 740 Out << '\0'; 741 } 742 743 for (std::vector<object::ObjectFile *>::iterator I = DeleteIt.begin(), 744 E = DeleteIt.end(); 745 I != E; ++I) { 746 object::ObjectFile *O = *I; 747 delete O; 748 } 749 750 if (StartOffset == 0) 751 return; 752 753 if (Out.tell() % 2) 754 Out << '\0'; 755 756 unsigned Pos = Out.tell(); 757 Out.seek(StartOffset - 12); 758 printWithSpacePadding(Out, Pos - StartOffset, 10); 759 Out.seek(StartOffset); 760 print32BE(Out, SymNames.size()); 761 Out.seek(Pos); 762 } 763 764 static void performWriteOperation(ArchiveOperation Operation, 765 object::Archive *OldArchive) { 766 SmallString<128> TmpArchive; 767 failIfError(sys::fs::createUniqueFile(ArchiveName + ".temp-archive-%%%%%%%.a", 768 TmpArchiveFD, TmpArchive)); 769 770 TemporaryOutput = TmpArchive.c_str(); 771 tool_output_file Output(TemporaryOutput, TmpArchiveFD); 772 raw_fd_ostream &Out = Output.os(); 773 Out << "!<arch>\n"; 774 775 std::vector<NewArchiveIterator> NewMembers = 776 computeNewArchiveMembers(Operation, OldArchive); 777 778 std::vector<std::pair<unsigned, unsigned> > MemberOffsetRefs; 779 780 std::vector<MemoryBuffer *> MemberBuffers; 781 MemberBuffers.resize(NewMembers.size()); 782 783 for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) { 784 OwningPtr<MemoryBuffer> MemberBuffer; 785 NewArchiveIterator &Member = NewMembers[I]; 786 787 if (Member.isNewMember()) { 788 const char *Filename = Member.getNew(); 789 int FD = Member.getFD(); 790 const sys::fs::file_status &Status = Member.getStatus(); 791 failIfError(MemoryBuffer::getOpenFile(FD, Filename, MemberBuffer, 792 Status.getSize(), false), 793 Filename); 794 795 } else { 796 object::Archive::child_iterator OldMember = Member.getOld(); 797 failIfError(OldMember->getMemoryBuffer(MemberBuffer)); 798 } 799 MemberBuffers[I] = MemberBuffer.take(); 800 } 801 802 if (Symtab) { 803 writeSymbolTable(Out, NewMembers, MemberBuffers, MemberOffsetRefs); 804 } 805 806 std::vector<unsigned> StringMapIndexes; 807 writeStringTable(Out, NewMembers, StringMapIndexes); 808 809 std::vector<std::pair<unsigned, unsigned> >::iterator MemberRefsI = 810 MemberOffsetRefs.begin(); 811 812 unsigned MemberNum = 0; 813 unsigned LongNameMemberNum = 0; 814 for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(), 815 E = NewMembers.end(); 816 I != E; ++I, ++MemberNum) { 817 818 unsigned Pos = Out.tell(); 819 while (MemberRefsI != MemberOffsetRefs.end() && 820 MemberRefsI->second == MemberNum) { 821 Out.seek(MemberRefsI->first); 822 print32BE(Out, Pos); 823 ++MemberRefsI; 824 } 825 Out.seek(Pos); 826 827 const MemoryBuffer *File = MemberBuffers[MemberNum]; 828 if (I->isNewMember()) { 829 const char *FileName = I->getNew(); 830 const sys::fs::file_status &Status = I->getStatus(); 831 832 StringRef Name = sys::path::filename(FileName); 833 if (Name.size() < 16) 834 printMemberHeader(Out, Name, Status.getLastModificationTime(), 835 Status.getUser(), Status.getGroup(), 836 Status.permissions(), Status.getSize()); 837 else 838 printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], 839 Status.getLastModificationTime(), Status.getUser(), 840 Status.getGroup(), Status.permissions(), 841 Status.getSize()); 842 } else { 843 object::Archive::child_iterator OldMember = I->getOld(); 844 StringRef Name = I->getName(); 845 846 if (Name.size() < 16) 847 printMemberHeader(Out, Name, OldMember->getLastModified(), 848 OldMember->getUID(), OldMember->getGID(), 849 OldMember->getAccessMode(), OldMember->getSize()); 850 else 851 printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], 852 OldMember->getLastModified(), OldMember->getUID(), 853 OldMember->getGID(), OldMember->getAccessMode(), 854 OldMember->getSize()); 855 } 856 857 Out << File->getBuffer(); 858 859 if (Out.tell() % 2) 860 Out << '\n'; 861 } 862 863 for (unsigned I = 0, N = MemberBuffers.size(); I < N; ++I) { 864 delete MemberBuffers[I]; 865 } 866 867 Output.keep(); 868 Out.close(); 869 sys::fs::rename(TemporaryOutput, ArchiveName); 870 TemporaryOutput = NULL; 871 } 872 873 static void createSymbolTable(object::Archive *OldArchive) { 874 // When an archive is created or modified, if the s option is given, the 875 // resulting archive will have a current symbol table. If the S option 876 // is given, it will have no symbol table. 877 // In summary, we only need to update the symbol table if we have none. 878 // This is actually very common because of broken build systems that think 879 // they have to run ranlib. 880 if (OldArchive->hasSymbolTable()) 881 return; 882 883 performWriteOperation(CreateSymTab, OldArchive); 884 } 885 886 static void performOperation(ArchiveOperation Operation, 887 object::Archive *OldArchive) { 888 switch (Operation) { 889 case Print: 890 case DisplayTable: 891 case Extract: 892 performReadOperation(Operation, OldArchive); 893 return; 894 895 case Delete: 896 case Move: 897 case QuickAppend: 898 case ReplaceOrInsert: 899 performWriteOperation(Operation, OldArchive); 900 return; 901 case CreateSymTab: 902 createSymbolTable(OldArchive); 903 return; 904 } 905 llvm_unreachable("Unknown operation."); 906 } 907 908 static int ar_main(char **argv); 909 static int ranlib_main(); 910 911 // main - main program for llvm-ar .. see comments in the code 912 int main(int argc, char **argv) { 913 ToolName = argv[0]; 914 // Print a stack trace if we signal out. 915 sys::PrintStackTraceOnErrorSignal(); 916 PrettyStackTraceProgram X(argc, argv); 917 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 918 919 // Have the command line options parsed and handle things 920 // like --help and --version. 921 cl::ParseCommandLineOptions(argc, argv, 922 "LLVM Archiver (llvm-ar)\n\n" 923 " This program archives bitcode files into single libraries\n" 924 ); 925 926 StringRef Stem = sys::path::stem(ToolName); 927 if (Stem.find("ar") != StringRef::npos) 928 return ar_main(argv); 929 if (Stem.find("ranlib") != StringRef::npos) 930 return ranlib_main(); 931 fail("Not ranlib or ar!"); 932 } 933 934 static int performOperation(ArchiveOperation Operation); 935 936 int ranlib_main() { 937 if (RestOfArgs.size() != 1) 938 fail(ToolName + "takes just one archive as argument"); 939 ArchiveName = RestOfArgs[0]; 940 return performOperation(CreateSymTab); 941 } 942 943 int ar_main(char **argv) { 944 // Do our own parsing of the command line because the CommandLine utility 945 // can't handle the grouped positional parameters without a dash. 946 ArchiveOperation Operation = parseCommandLine(); 947 return performOperation(Operation); 948 } 949 950 static int performOperation(ArchiveOperation Operation) { 951 // Create or open the archive object. 952 OwningPtr<MemoryBuffer> Buf; 953 error_code EC = MemoryBuffer::getFile(ArchiveName, Buf, -1, false); 954 if (EC && EC != llvm::errc::no_such_file_or_directory) { 955 errs() << ToolName << ": error opening '" << ArchiveName 956 << "': " << EC.message() << "!\n"; 957 return 1; 958 } 959 960 if (!EC) { 961 object::Archive Archive(Buf.take(), EC); 962 963 if (EC) { 964 errs() << ToolName << ": error loading '" << ArchiveName 965 << "': " << EC.message() << "!\n"; 966 return 1; 967 } 968 performOperation(Operation, &Archive); 969 return 0; 970 } 971 972 assert(EC == llvm::errc::no_such_file_or_directory); 973 974 if (!shouldCreateArchive(Operation)) { 975 failIfError(EC, Twine("error loading '") + ArchiveName + "'"); 976 } else { 977 if (!Create) { 978 // Produce a warning if we should and we're creating the archive 979 errs() << ToolName << ": creating " << ArchiveName << "\n"; 980 } 981 } 982 983 performOperation(Operation, NULL); 984 return 0; 985 } 986