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