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/LLVMContext.h" 16 #include "llvm/Module.h" 17 #include "llvm/Bitcode/Archive.h" 18 #include "llvm/Support/CommandLine.h" 19 #include "llvm/Support/FileSystem.h" 20 #include "llvm/Support/ManagedStatic.h" 21 #include "llvm/Support/PrettyStackTrace.h" 22 #include "llvm/Support/Format.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include "llvm/Support/Signals.h" 25 #include <algorithm> 26 #include <memory> 27 #include <fstream> 28 using namespace llvm; 29 30 // Option for compatibility with AIX, not used but must allow it to be present. 31 static cl::opt<bool> 32 X32Option ("X32_64", cl::Hidden, 33 cl::desc("Ignored option for compatibility with AIX")); 34 35 // llvm-ar operation code and modifier flags. This must come first. 36 static cl::opt<std::string> 37 Options(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 38 39 // llvm-ar remaining positional arguments. 40 static cl::list<std::string> 41 RestOfArgs(cl::Positional, cl::OneOrMore, 42 cl::desc("[relpos] [count] <archive-file> [members]...")); 43 44 // MoreHelp - Provide additional help output explaining the operations and 45 // modifiers of llvm-ar. This object instructs the CommandLine library 46 // to print the text of the constructor when the --help option is given. 47 static cl::extrahelp MoreHelp( 48 "\nOPERATIONS:\n" 49 " d[NsS] - delete file(s) from the archive\n" 50 " m[abiSs] - move file(s) in the archive\n" 51 " p[kN] - print file(s) found in the archive\n" 52 " q[ufsS] - quick append file(s) to the archive\n" 53 " r[abfiuzRsS] - replace or insert file(s) into the archive\n" 54 " t - display contents of archive\n" 55 " x[No] - extract file(s) from the archive\n" 56 "\nMODIFIERS (operation specific):\n" 57 " [a] - put file(s) after [relpos]\n" 58 " [b] - put file(s) before [relpos] (same as [i])\n" 59 " [f] - truncate inserted file names\n" 60 " [i] - put file(s) before [relpos] (same as [b])\n" 61 " [k] - always print bitcode files (default is to skip them)\n" 62 " [N] - use instance [count] of name\n" 63 " [o] - preserve original dates\n" 64 " [P] - use full path names when matching\n" 65 " [R] - recurse through directories when inserting\n" 66 " [s] - create an archive index (cf. ranlib)\n" 67 " [S] - do not build a symbol table\n" 68 " [u] - update only files newer than archive contents\n" 69 " [z] - compress files before inserting/extracting\n" 70 "\nMODIFIERS (generic):\n" 71 " [c] - do not warn if the library had to be created\n" 72 " [v] - be verbose about actions taken\n" 73 " [V] - be *really* verbose about actions taken\n" 74 ); 75 76 // This enumeration delineates the kinds of operations on an archive 77 // that are permitted. 78 enum ArchiveOperation { 79 NoOperation, ///< An operation hasn't been specified 80 Print, ///< Print the contents of the archive 81 Delete, ///< Delete the specified members 82 Move, ///< Move members to end or as given by {a,b,i} modifiers 83 QuickAppend, ///< Quickly append to end of archive 84 ReplaceOrInsert, ///< Replace or Insert members 85 DisplayTable, ///< Display the table of contents 86 Extract ///< Extract files back to file system 87 }; 88 89 // Modifiers to follow operation to vary behavior 90 bool AddAfter = false; ///< 'a' modifier 91 bool AddBefore = false; ///< 'b' modifier 92 bool Create = false; ///< 'c' modifier 93 bool TruncateNames = false; ///< 'f' modifier 94 bool InsertBefore = false; ///< 'i' modifier 95 bool DontSkipBitcode = false; ///< 'k' modifier 96 bool UseCount = false; ///< 'N' modifier 97 bool OriginalDates = false; ///< 'o' modifier 98 bool FullPath = false; ///< 'P' modifier 99 bool RecurseDirectories = false; ///< 'R' modifier 100 bool SymTable = true; ///< 's' & 'S' modifiers 101 bool OnlyUpdate = false; ///< 'u' modifier 102 bool Verbose = false; ///< 'v' modifier 103 bool ReallyVerbose = false; ///< 'V' modifier 104 bool Compression = false; ///< 'z' modifier 105 106 // Relative Positional Argument (for insert/move). This variable holds 107 // the name of the archive member to which the 'a', 'b' or 'i' modifier 108 // refers. Only one of 'a', 'b' or 'i' can be specified so we only need 109 // one variable. 110 std::string RelPos; 111 112 // Select which of multiple entries in the archive with the same name should be 113 // used (specified with -N) for the delete and extract operations. 114 int Count = 1; 115 116 // This variable holds the name of the archive file as given on the 117 // command line. 118 std::string ArchiveName; 119 120 // This variable holds the list of member files to proecess, as given 121 // on the command line. 122 std::vector<std::string> Members; 123 124 // This variable holds the (possibly expanded) list of path objects that 125 // correspond to files we will 126 std::set<sys::Path> Paths; 127 128 // The Archive object to which all the editing operations will be sent. 129 Archive* TheArchive = 0; 130 131 // getRelPos - Extract the member filename from the command line for 132 // the [relpos] argument associated with a, b, and i modifiers 133 void getRelPos() { 134 if(RestOfArgs.size() > 0) { 135 RelPos = RestOfArgs[0]; 136 RestOfArgs.erase(RestOfArgs.begin()); 137 } 138 else 139 throw "Expected [relpos] for a, b, or i modifier"; 140 } 141 142 // getCount - Extract the [count] argument associated with the N modifier 143 // from the command line and check its value. 144 void getCount() { 145 if(RestOfArgs.size() > 0) { 146 Count = atoi(RestOfArgs[0].c_str()); 147 RestOfArgs.erase(RestOfArgs.begin()); 148 } 149 else 150 throw "Expected [count] value with N modifier"; 151 152 // Non-positive counts are not allowed 153 if (Count < 1) 154 throw "Invalid [count] value (not a positive integer)"; 155 } 156 157 // getArchive - Get the archive file name from the command line 158 void getArchive() { 159 if(RestOfArgs.size() > 0) { 160 ArchiveName = RestOfArgs[0]; 161 RestOfArgs.erase(RestOfArgs.begin()); 162 } 163 else 164 throw "An archive name must be specified."; 165 } 166 167 // getMembers - Copy over remaining items in RestOfArgs to our Members vector 168 // This is just for clarity. 169 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 ArchiveOperation parseCommandLine() { 178 179 // Keep track of number of operations. We can only specify one 180 // per execution. 181 unsigned NumOperations = 0; 182 183 // Keep track of the number of positional modifiers (a,b,i). Only 184 // one can be specified. 185 unsigned NumPositional = 0; 186 187 // Keep track of which operation was requested 188 ArchiveOperation Operation = NoOperation; 189 190 for(unsigned i=0; i<Options.size(); ++i) { 191 switch(Options[i]) { 192 case 'd': ++NumOperations; Operation = Delete; break; 193 case 'm': ++NumOperations; Operation = Move ; break; 194 case 'p': ++NumOperations; Operation = Print; break; 195 case 'q': ++NumOperations; Operation = QuickAppend; break; 196 case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 197 case 't': ++NumOperations; Operation = DisplayTable; break; 198 case 'x': ++NumOperations; Operation = Extract; break; 199 case 'c': Create = true; break; 200 case 'f': TruncateNames = true; break; 201 case 'k': DontSkipBitcode = true; break; 202 case 'l': /* accepted but unused */ break; 203 case 'o': OriginalDates = true; break; 204 case 'P': FullPath = true; break; 205 case 'R': RecurseDirectories = true; break; 206 case 's': SymTable = true; break; 207 case 'S': SymTable = false; break; 208 case 'u': OnlyUpdate = true; break; 209 case 'v': Verbose = true; break; 210 case 'V': Verbose = ReallyVerbose = true; break; 211 case 'z': Compression = true; break; 212 case 'a': 213 getRelPos(); 214 AddAfter = true; 215 NumPositional++; 216 break; 217 case 'b': 218 getRelPos(); 219 AddBefore = true; 220 NumPositional++; 221 break; 222 case 'i': 223 getRelPos(); 224 InsertBefore = true; 225 NumPositional++; 226 break; 227 case 'N': 228 getCount(); 229 UseCount = true; 230 break; 231 default: 232 cl::PrintHelpMessage(); 233 } 234 } 235 236 // At this point, the next thing on the command line must be 237 // the archive name. 238 getArchive(); 239 240 // Everything on the command line at this point is a member. 241 getMembers(); 242 243 // Perform various checks on the operation/modifier specification 244 // to make sure we are dealing with a legal request. 245 if (NumOperations == 0) 246 throw "You must specify at least one of the operations"; 247 if (NumOperations > 1) 248 throw "Only one operation may be specified"; 249 if (NumPositional > 1) 250 throw "You may only specify one of a, b, and i modifiers"; 251 if (AddAfter || AddBefore || InsertBefore) 252 if (Operation != Move && Operation != ReplaceOrInsert) 253 throw "The 'a', 'b' and 'i' modifiers can only be specified with " 254 "the 'm' or 'r' operations"; 255 if (RecurseDirectories && Operation != ReplaceOrInsert) 256 throw "The 'R' modifiers is only applicabe to the 'r' operation"; 257 if (OriginalDates && Operation != Extract) 258 throw "The 'o' modifier is only applicable to the 'x' operation"; 259 if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 260 throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 261 if (OnlyUpdate && Operation != ReplaceOrInsert) 262 throw "The 'u' modifier is only applicable to the 'r' operation"; 263 if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) 264 throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; 265 if (Count > 1 && Members.size() > 1) 266 throw "Only one member name may be specified with the 'N' modifier"; 267 268 // Return the parsed operation to the caller 269 return Operation; 270 } 271 272 // recurseDirectories - Implements the "R" modifier. This function scans through 273 // the Paths vector (built by buildPaths, below) and replaces any directories it 274 // finds with all the files in that directory (recursively). It uses the 275 // sys::Path::getDirectoryContent method to perform the actual directory scans. 276 bool 277 recurseDirectories(const sys::Path& path, 278 std::set<sys::Path>& result, std::string* ErrMsg) { 279 result.clear(); 280 if (RecurseDirectories) { 281 std::set<sys::Path> content; 282 if (path.getDirectoryContents(content, ErrMsg)) 283 return true; 284 285 for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 286 I != E; ++I) { 287 // Make sure it exists and is a directory 288 sys::PathWithStatus PwS(*I); 289 const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); 290 if (!Status) 291 return true; 292 if (Status->isDir) { 293 std::set<sys::Path> moreResults; 294 if (recurseDirectories(*I, moreResults, ErrMsg)) 295 return true; 296 result.insert(moreResults.begin(), moreResults.end()); 297 } else { 298 result.insert(*I); 299 } 300 } 301 } 302 return false; 303 } 304 305 // buildPaths - Convert the strings in the Members vector to sys::Path objects 306 // and make sure they are valid and exist exist. This check is only needed for 307 // the operations that add/replace files to the archive ('q' and 'r') 308 bool buildPaths(bool checkExistence, std::string* ErrMsg) { 309 for (unsigned i = 0; i < Members.size(); i++) { 310 sys::Path aPath; 311 if (!aPath.set(Members[i])) 312 throw std::string("File member name invalid: ") + Members[i]; 313 if (checkExistence) { 314 bool Exists; 315 if (sys::fs::exists(aPath.str(), Exists) || !Exists) 316 throw std::string("File does not exist: ") + Members[i]; 317 std::string Err; 318 sys::PathWithStatus PwS(aPath); 319 const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 320 if (!si) 321 throw Err; 322 if (si->isDir) { 323 std::set<sys::Path> dirpaths; 324 if (recurseDirectories(aPath, dirpaths, ErrMsg)) 325 return true; 326 Paths.insert(dirpaths.begin(),dirpaths.end()); 327 } else { 328 Paths.insert(aPath); 329 } 330 } else { 331 Paths.insert(aPath); 332 } 333 } 334 return false; 335 } 336 337 // printSymbolTable - print out the archive's symbol table. 338 void printSymbolTable() { 339 outs() << "\nArchive Symbol Table:\n"; 340 const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 341 for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 342 I != E; ++I ) { 343 unsigned offset = TheArchive->getFirstFileOffset() + I->second; 344 outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; 345 } 346 } 347 348 // doPrint - Implements the 'p' operation. This function traverses the archive 349 // looking for members that match the path list. It is careful to uncompress 350 // things that should be and to skip bitcode files unless the 'k' modifier was 351 // given. 352 bool doPrint(std::string* ErrMsg) { 353 if (buildPaths(false, ErrMsg)) 354 return true; 355 unsigned countDown = Count; 356 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 357 I != E; ++I ) { 358 if (Paths.empty() || 359 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 360 if (countDown == 1) { 361 const char* data = reinterpret_cast<const char*>(I->getData()); 362 363 // Skip things that don't make sense to print 364 if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 365 I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) 366 continue; 367 368 if (Verbose) 369 outs() << "Printing " << I->getPath().str() << "\n"; 370 371 unsigned len = I->getSize(); 372 outs().write(data, len); 373 } else { 374 countDown--; 375 } 376 } 377 } 378 return false; 379 } 380 381 // putMode - utility function for printing out the file mode when the 't' 382 // operation is in verbose mode. 383 void 384 printMode(unsigned mode) { 385 if (mode & 004) 386 outs() << "r"; 387 else 388 outs() << "-"; 389 if (mode & 002) 390 outs() << "w"; 391 else 392 outs() << "-"; 393 if (mode & 001) 394 outs() << "x"; 395 else 396 outs() << "-"; 397 } 398 399 // doDisplayTable - Implement the 't' operation. This function prints out just 400 // the file names of each of the members. However, if verbose mode is requested 401 // ('v' modifier) then the file type, permission mode, user, group, size, and 402 // modification time are also printed. 403 bool 404 doDisplayTable(std::string* ErrMsg) { 405 if (buildPaths(false, ErrMsg)) 406 return true; 407 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 408 I != E; ++I ) { 409 if (Paths.empty() || 410 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 411 if (Verbose) { 412 // FIXME: Output should be this format: 413 // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 414 if (I->isBitcode()) 415 outs() << "b"; 416 else if (I->isCompressed()) 417 outs() << "Z"; 418 else 419 outs() << " "; 420 unsigned mode = I->getMode(); 421 printMode((mode >> 6) & 007); 422 printMode((mode >> 3) & 007); 423 printMode(mode & 007); 424 outs() << " " << format("%4u", I->getUser()); 425 outs() << "/" << format("%4u", I->getGroup()); 426 outs() << " " << format("%8u", I->getSize()); 427 outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); 428 outs() << " " << I->getPath().str() << "\n"; 429 } else { 430 outs() << I->getPath().str() << "\n"; 431 } 432 } 433 } 434 if (ReallyVerbose) 435 printSymbolTable(); 436 return false; 437 } 438 439 // doExtract - Implement the 'x' operation. This function extracts files back to 440 // the file system, making sure to uncompress any that were compressed 441 bool 442 doExtract(std::string* ErrMsg) { 443 if (buildPaths(false, ErrMsg)) 444 return true; 445 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 446 I != E; ++I ) { 447 if (Paths.empty() || 448 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 449 450 // Make sure the intervening directories are created 451 if (I->hasPath()) { 452 sys::Path dirs(I->getPath()); 453 dirs.eraseComponent(); 454 if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 455 return true; 456 } 457 458 // Open up a file stream for writing 459 std::ios::openmode io_mode = std::ios::out | std::ios::trunc | 460 std::ios::binary; 461 std::ofstream file(I->getPath().c_str(), io_mode); 462 463 // Get the data and its length 464 const char* data = reinterpret_cast<const char*>(I->getData()); 465 unsigned len = I->getSize(); 466 467 // Write the data. 468 file.write(data,len); 469 file.close(); 470 471 // If we're supposed to retain the original modification times, etc. do so 472 // now. 473 if (OriginalDates) 474 I->getPath().setStatusInfoOnDisk(I->getFileStatus()); 475 } 476 } 477 return false; 478 } 479 480 // doDelete - Implement the delete operation. This function deletes zero or more 481 // members from the archive. Note that if the count is specified, there should 482 // be no more than one path in the Paths list or else this algorithm breaks. 483 // That check is enforced in parseCommandLine (above). 484 bool 485 doDelete(std::string* ErrMsg) { 486 if (buildPaths(false, ErrMsg)) 487 return true; 488 if (Paths.empty()) 489 return false; 490 unsigned countDown = Count; 491 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 492 I != E; ) { 493 if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 494 if (countDown == 1) { 495 Archive::iterator J = I; 496 ++I; 497 TheArchive->erase(J); 498 } else 499 countDown--; 500 } else { 501 ++I; 502 } 503 } 504 505 // We're done editting, reconstruct the archive. 506 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 507 return true; 508 if (ReallyVerbose) 509 printSymbolTable(); 510 return false; 511 } 512 513 // doMore - Implement the move operation. This function re-arranges just the 514 // order of the archive members so that when the archive is written the move 515 // of the members is accomplished. Note the use of the RelPos variable to 516 // determine where the items should be moved to. 517 bool 518 doMove(std::string* ErrMsg) { 519 if (buildPaths(false, ErrMsg)) 520 return true; 521 522 // By default and convention the place to move members to is the end of the 523 // archive. 524 Archive::iterator moveto_spot = TheArchive->end(); 525 526 // However, if the relative positioning modifiers were used, we need to scan 527 // the archive to find the member in question. If we don't find it, its no 528 // crime, we just move to the end. 529 if (AddBefore || InsertBefore || AddAfter) { 530 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 531 I != E; ++I ) { 532 if (RelPos == I->getPath().str()) { 533 if (AddAfter) { 534 moveto_spot = I; 535 moveto_spot++; 536 } else { 537 moveto_spot = I; 538 } 539 break; 540 } 541 } 542 } 543 544 // Keep a list of the paths remaining to be moved 545 std::set<sys::Path> remaining(Paths); 546 547 // Scan the archive again, this time looking for the members to move to the 548 // moveto_spot. 549 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 550 I != E && !remaining.empty(); ++I ) { 551 std::set<sys::Path>::iterator found = 552 std::find(remaining.begin(),remaining.end(),I->getPath()); 553 if (found != remaining.end()) { 554 if (I != moveto_spot) 555 TheArchive->splice(moveto_spot,*TheArchive,I); 556 remaining.erase(found); 557 } 558 } 559 560 // We're done editting, reconstruct the archive. 561 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 562 return true; 563 if (ReallyVerbose) 564 printSymbolTable(); 565 return false; 566 } 567 568 // doQuickAppend - Implements the 'q' operation. This function just 569 // indiscriminantly adds the members to the archive and rebuilds it. 570 bool 571 doQuickAppend(std::string* ErrMsg) { 572 // Get the list of paths to append. 573 if (buildPaths(true, ErrMsg)) 574 return true; 575 if (Paths.empty()) 576 return false; 577 578 // Append them quickly. 579 for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 580 PI != PE; ++PI) { 581 if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) 582 return true; 583 } 584 585 // We're done editting, reconstruct the archive. 586 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 587 return true; 588 if (ReallyVerbose) 589 printSymbolTable(); 590 return false; 591 } 592 593 // doReplaceOrInsert - Implements the 'r' operation. This function will replace 594 // any existing files or insert new ones into the archive. 595 bool 596 doReplaceOrInsert(std::string* ErrMsg) { 597 598 // Build the list of files to be added/replaced. 599 if (buildPaths(true, ErrMsg)) 600 return true; 601 if (Paths.empty()) 602 return false; 603 604 // Keep track of the paths that remain to be inserted. 605 std::set<sys::Path> remaining(Paths); 606 607 // Default the insertion spot to the end of the archive 608 Archive::iterator insert_spot = TheArchive->end(); 609 610 // Iterate over the archive contents 611 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 612 I != E && !remaining.empty(); ++I ) { 613 614 // Determine if this archive member matches one of the paths we're trying 615 // to replace. 616 617 std::set<sys::Path>::iterator found = remaining.end(); 618 for (std::set<sys::Path>::iterator RI = remaining.begin(), 619 RE = remaining.end(); RI != RE; ++RI ) { 620 std::string compare(RI->str()); 621 if (TruncateNames && compare.length() > 15) { 622 const char* nm = compare.c_str(); 623 unsigned len = compare.length(); 624 size_t slashpos = compare.rfind('/'); 625 if (slashpos != std::string::npos) { 626 nm += slashpos + 1; 627 len -= slashpos +1; 628 } 629 if (len > 15) 630 len = 15; 631 compare.assign(nm,len); 632 } 633 if (compare == I->getPath().str()) { 634 found = RI; 635 break; 636 } 637 } 638 639 if (found != remaining.end()) { 640 std::string Err; 641 sys::PathWithStatus PwS(*found); 642 const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 643 if (!si) 644 return true; 645 if (!si->isDir) { 646 if (OnlyUpdate) { 647 // Replace the item only if it is newer. 648 if (si->modTime > I->getModTime()) 649 if (I->replaceWith(*found, ErrMsg)) 650 return true; 651 } else { 652 // Replace the item regardless of time stamp 653 if (I->replaceWith(*found, ErrMsg)) 654 return true; 655 } 656 } else { 657 // We purposefully ignore directories. 658 } 659 660 // Remove it from our "to do" list 661 remaining.erase(found); 662 } 663 664 // Determine if this is the place where we should insert 665 if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) 666 insert_spot = I; 667 else if (AddAfter && RelPos == I->getPath().str()) { 668 insert_spot = I; 669 insert_spot++; 670 } 671 } 672 673 // If we didn't replace all the members, some will remain and need to be 674 // inserted at the previously computed insert-spot. 675 if (!remaining.empty()) { 676 for (std::set<sys::Path>::iterator PI = remaining.begin(), 677 PE = remaining.end(); PI != PE; ++PI) { 678 if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) 679 return true; 680 } 681 } 682 683 // We're done editting, reconstruct the archive. 684 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 685 return true; 686 if (ReallyVerbose) 687 printSymbolTable(); 688 return false; 689 } 690 691 // main - main program for llvm-ar .. see comments in the code 692 int main(int argc, char **argv) { 693 // Print a stack trace if we signal out. 694 sys::PrintStackTraceOnErrorSignal(); 695 PrettyStackTraceProgram X(argc, argv); 696 LLVMContext &Context = getGlobalContext(); 697 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 698 699 // Have the command line options parsed and handle things 700 // like --help and --version. 701 cl::ParseCommandLineOptions(argc, argv, 702 "LLVM Archiver (llvm-ar)\n\n" 703 " This program archives bitcode files into single libraries\n" 704 ); 705 706 int exitCode = 0; 707 708 // Make sure we don't exit with "unhandled exception". 709 try { 710 // Do our own parsing of the command line because the CommandLine utility 711 // can't handle the grouped positional parameters without a dash. 712 ArchiveOperation Operation = parseCommandLine(); 713 714 // Check the path name of the archive 715 sys::Path ArchivePath; 716 if (!ArchivePath.set(ArchiveName)) 717 throw std::string("Archive name invalid: ") + ArchiveName; 718 719 // Create or open the archive object. 720 bool Exists; 721 if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { 722 // Produce a warning if we should and we're creating the archive 723 if (!Create) 724 errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; 725 TheArchive = Archive::CreateEmpty(ArchivePath, Context); 726 TheArchive->writeToDisk(); 727 } else { 728 std::string Error; 729 TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); 730 if (TheArchive == 0) { 731 errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " 732 << Error << "!\n"; 733 return 1; 734 } 735 } 736 737 // Make sure we're not fooling ourselves. 738 assert(TheArchive && "Unable to instantiate the archive"); 739 740 // Make sure we clean up the archive even on failure. 741 std::auto_ptr<Archive> AutoArchive(TheArchive); 742 743 // Perform the operation 744 std::string ErrMsg; 745 bool haveError = false; 746 switch (Operation) { 747 case Print: haveError = doPrint(&ErrMsg); break; 748 case Delete: haveError = doDelete(&ErrMsg); break; 749 case Move: haveError = doMove(&ErrMsg); break; 750 case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 751 case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 752 case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 753 case Extract: haveError = doExtract(&ErrMsg); break; 754 case NoOperation: 755 errs() << argv[0] << ": No operation was selected.\n"; 756 break; 757 } 758 if (haveError) { 759 errs() << argv[0] << ": " << ErrMsg << "\n"; 760 return 1; 761 } 762 } catch (const char*msg) { 763 // These errors are usage errors, thrown only by the various checks in the 764 // code above. 765 errs() << argv[0] << ": " << msg << "\n\n"; 766 cl::PrintHelpMessage(); 767 exitCode = 1; 768 } catch (const std::string& msg) { 769 // These errors are thrown by LLVM libraries (e.g. lib System) and represent 770 // a more serious error so we bump the exitCode and don't print the usage. 771 errs() << argv[0] << ": " << msg << "\n"; 772 exitCode = 2; 773 } catch (...) { 774 // This really shouldn't happen, but just in case .... 775 errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; 776 exitCode = 3; 777 } 778 779 // Return result code back to operating system. 780 return exitCode; 781 } 782