llvm-ar.cpp revision 71857ccdb83b6374f7a791c2dae45ce9934a85af
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 "Archive.h" 16#include "llvm/IR/LLVMContext.h" 17#include "llvm/IR/Module.h" 18#include "llvm/Support/CommandLine.h" 19#include "llvm/Support/FileSystem.h" 20#include "llvm/Support/Format.h" 21#include "llvm/Support/ManagedStatic.h" 22#include "llvm/Support/PrettyStackTrace.h" 23#include "llvm/Support/Signals.h" 24#include "llvm/Support/raw_ostream.h" 25#include <algorithm> 26#include <cstdlib> 27#include <fcntl.h> 28#include <memory> 29 30#if !defined(_MSC_VER) && !defined(__MINGW32__) 31#include <unistd.h> 32#else 33#include <io.h> 34#endif 35 36using namespace llvm; 37 38// Option for compatibility with AIX, not used but must allow it to be present. 39static cl::opt<bool> 40X32Option ("X32_64", cl::Hidden, 41 cl::desc("Ignored option for compatibility with AIX")); 42 43// llvm-ar operation code and modifier flags. This must come first. 44static cl::opt<std::string> 45Options(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 46 47// llvm-ar remaining positional arguments. 48static cl::list<std::string> 49RestOfArgs(cl::Positional, cl::OneOrMore, 50 cl::desc("[relpos] [count] <archive-file> [members]...")); 51 52// MoreHelp - Provide additional help output explaining the operations and 53// modifiers of llvm-ar. This object instructs the CommandLine library 54// to print the text of the constructor when the --help option is given. 55static cl::extrahelp MoreHelp( 56 "\nOPERATIONS:\n" 57 " d[NsS] - delete file(s) from the archive\n" 58 " m[abiSs] - move file(s) in the archive\n" 59 " p[kN] - print file(s) found in the archive\n" 60 " q[ufsS] - quick append file(s) to the archive\n" 61 " r[abfiuRsS] - replace or insert file(s) into the archive\n" 62 " t - display contents of archive\n" 63 " x[No] - extract file(s) from the archive\n" 64 "\nMODIFIERS (operation specific):\n" 65 " [a] - put file(s) after [relpos]\n" 66 " [b] - put file(s) before [relpos] (same as [i])\n" 67 " [i] - put file(s) before [relpos] (same as [b])\n" 68 " [N] - use instance [count] of name\n" 69 " [o] - preserve original dates\n" 70 " [s] - create an archive index (cf. ranlib)\n" 71 " [S] - do not build a symbol table\n" 72 " [u] - update only files newer than archive contents\n" 73 "\nMODIFIERS (generic):\n" 74 " [c] - do not warn if the library had to be created\n" 75 " [v] - be verbose about actions taken\n" 76); 77 78// This enumeration delineates the kinds of operations on an archive 79// that are permitted. 80enum ArchiveOperation { 81 Print, ///< Print the contents of the archive 82 Delete, ///< Delete the specified members 83 Move, ///< Move members to end or as given by {a,b,i} modifiers 84 QuickAppend, ///< Quickly append to end of archive 85 ReplaceOrInsert, ///< Replace or Insert members 86 DisplayTable, ///< Display the table of contents 87 Extract ///< Extract files back to file system 88}; 89 90// Modifiers to follow operation to vary behavior 91bool AddAfter = false; ///< 'a' modifier 92bool AddBefore = false; ///< 'b' modifier 93bool Create = false; ///< 'c' modifier 94bool InsertBefore = false; ///< 'i' modifier 95bool OriginalDates = false; ///< 'o' modifier 96bool SymTable = true; ///< 's' & 'S' modifiers 97bool OnlyUpdate = false; ///< 'u' modifier 98bool Verbose = false; ///< 'v' modifier 99 100// Relative Positional Argument (for insert/move). This variable holds 101// the name of the archive member to which the 'a', 'b' or 'i' modifier 102// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 103// one variable. 104std::string RelPos; 105 106// This variable holds the name of the archive file as given on the 107// command line. 108std::string ArchiveName; 109 110// This variable holds the list of member files to proecess, as given 111// on the command line. 112std::vector<std::string> Members; 113 114// This variable holds the (possibly expanded) list of path objects that 115// correspond to files we will 116std::set<std::string> Paths; 117 118// The Archive object to which all the editing operations will be sent. 119Archive* TheArchive = 0; 120 121// The name this program was invoked as. 122static const char *program_name; 123 124// show_help - Show the error message, the help message and exit. 125LLVM_ATTRIBUTE_NORETURN static void 126show_help(const std::string &msg) { 127 errs() << program_name << ": " << msg << "\n\n"; 128 cl::PrintHelpMessage(); 129 if (TheArchive) 130 delete TheArchive; 131 std::exit(1); 132} 133 134// fail - Show the error message and exit. 135LLVM_ATTRIBUTE_NORETURN static void 136fail(const std::string &msg) { 137 errs() << program_name << ": " << msg << "\n\n"; 138 if (TheArchive) 139 delete TheArchive; 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 145void 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// getArchive - Get the archive file name from the command line 153void getArchive() { 154 if(RestOfArgs.size() == 0) 155 show_help("An archive name must be specified"); 156 ArchiveName = RestOfArgs[0]; 157 RestOfArgs.erase(RestOfArgs.begin()); 158} 159 160// getMembers - Copy over remaining items in RestOfArgs to our Members vector 161// This is just for clarity. 162void getMembers() { 163 if(RestOfArgs.size() > 0) 164 Members = std::vector<std::string>(RestOfArgs); 165} 166 167// parseCommandLine - Parse the command line options as presented and return the 168// operation specified. Process all modifiers and check to make sure that 169// constraints on modifier/operation pairs have not been violated. 170ArchiveOperation parseCommandLine() { 171 172 // Keep track of number of operations. We can only specify one 173 // per execution. 174 unsigned NumOperations = 0; 175 176 // Keep track of the number of positional modifiers (a,b,i). Only 177 // one can be specified. 178 unsigned NumPositional = 0; 179 180 // Keep track of which operation was requested 181 ArchiveOperation Operation; 182 183 for(unsigned i=0; i<Options.size(); ++i) { 184 switch(Options[i]) { 185 case 'd': ++NumOperations; Operation = Delete; break; 186 case 'm': ++NumOperations; Operation = Move ; break; 187 case 'p': ++NumOperations; Operation = Print; break; 188 case 'q': ++NumOperations; Operation = QuickAppend; break; 189 case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 190 case 't': ++NumOperations; Operation = DisplayTable; break; 191 case 'x': ++NumOperations; Operation = Extract; break; 192 case 'c': Create = true; break; 193 case 'l': /* accepted but unused */ break; 194 case 'o': OriginalDates = true; break; 195 case 's': break; // Ignore for now. 196 case 'S': break; // Ignore for now. 197 case 'u': OnlyUpdate = true; break; 198 case 'v': Verbose = true; break; 199 case 'a': 200 getRelPos(); 201 AddAfter = true; 202 NumPositional++; 203 break; 204 case 'b': 205 getRelPos(); 206 AddBefore = true; 207 NumPositional++; 208 break; 209 case 'i': 210 getRelPos(); 211 InsertBefore = true; 212 NumPositional++; 213 break; 214 default: 215 cl::PrintHelpMessage(); 216 } 217 } 218 219 // At this point, the next thing on the command line must be 220 // the archive name. 221 getArchive(); 222 223 // Everything on the command line at this point is a member. 224 getMembers(); 225 226 // Perform various checks on the operation/modifier specification 227 // to make sure we are dealing with a legal request. 228 if (NumOperations == 0) 229 show_help("You must specify at least one of the operations"); 230 if (NumOperations > 1) 231 show_help("Only one operation may be specified"); 232 if (NumPositional > 1) 233 show_help("You may only specify one of a, b, and i modifiers"); 234 if (AddAfter || AddBefore || InsertBefore) { 235 if (Operation != Move && Operation != ReplaceOrInsert) 236 show_help("The 'a', 'b' and 'i' modifiers can only be specified with " 237 "the 'm' or 'r' operations"); 238 } 239 if (OriginalDates && Operation != Extract) 240 show_help("The 'o' modifier is only applicable to the 'x' operation"); 241 if (OnlyUpdate && Operation != ReplaceOrInsert) 242 show_help("The 'u' modifier is only applicable to the 'r' operation"); 243 244 // Return the parsed operation to the caller 245 return Operation; 246} 247 248// buildPaths - Convert the strings in the Members vector to sys::Path objects 249// and make sure they are valid and exist exist. This check is only needed for 250// the operations that add/replace files to the archive ('q' and 'r') 251bool buildPaths(bool checkExistence, std::string* ErrMsg) { 252 for (unsigned i = 0; i < Members.size(); i++) { 253 std::string aPath = Members[i]; 254 if (checkExistence) { 255 bool IsDirectory; 256 error_code EC = sys::fs::is_directory(aPath, IsDirectory); 257 if (EC) 258 fail(aPath + ": " + EC.message()); 259 if (IsDirectory) 260 fail(aPath + " Is a directory"); 261 262 Paths.insert(aPath); 263 } else { 264 Paths.insert(aPath); 265 } 266 } 267 return false; 268} 269 270// doPrint - Implements the 'p' operation. This function traverses the archive 271// looking for members that match the path list. It is careful to uncompress 272// things that should be and to skip bitcode files unless the 'k' modifier was 273// given. 274bool doPrint(std::string* ErrMsg) { 275 if (buildPaths(false, ErrMsg)) 276 return true; 277 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 278 I != E; ++I ) { 279 if (Paths.empty() || 280 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 281 const char *data = reinterpret_cast<const char *>(I->getData()); 282 283 // Skip things that don't make sense to print 284 if (I->isSVR4SymbolTable() || I->isBSD4SymbolTable()) 285 continue; 286 287 if (Verbose) 288 outs() << "Printing " << I->getPath().str() << "\n"; 289 290 unsigned len = I->getSize(); 291 outs().write(data, len); 292 } 293 } 294 return false; 295} 296 297// putMode - utility function for printing out the file mode when the 't' 298// operation is in verbose mode. 299void 300printMode(unsigned mode) { 301 if (mode & 004) 302 outs() << "r"; 303 else 304 outs() << "-"; 305 if (mode & 002) 306 outs() << "w"; 307 else 308 outs() << "-"; 309 if (mode & 001) 310 outs() << "x"; 311 else 312 outs() << "-"; 313} 314 315// doDisplayTable - Implement the 't' operation. This function prints out just 316// the file names of each of the members. However, if verbose mode is requested 317// ('v' modifier) then the file type, permission mode, user, group, size, and 318// modification time are also printed. 319bool 320doDisplayTable(std::string* ErrMsg) { 321 if (buildPaths(false, ErrMsg)) 322 return true; 323 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 324 I != E; ++I ) { 325 if (Paths.empty() || 326 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 327 if (Verbose) { 328 unsigned mode = I->getMode(); 329 printMode((mode >> 6) & 007); 330 printMode((mode >> 3) & 007); 331 printMode(mode & 007); 332 outs() << ' ' << I->getUser(); 333 outs() << "/" << I->getGroup(); 334 outs() << ' ' << format("%6u", I->getSize()); 335 sys::TimeValue ModTime = I->getModTime(); 336 outs() << " " << ModTime.str(); 337 outs() << " " << I->getPath().str() << "\n"; 338 } else { 339 outs() << I->getPath().str() << "\n"; 340 } 341 } 342 } 343 return false; 344} 345 346// doExtract - Implement the 'x' operation. This function extracts files back to 347// the file system. 348bool 349doExtract(std::string* ErrMsg) { 350 if (buildPaths(false, ErrMsg)) 351 return true; 352 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 353 I != E; ++I ) { 354 if (Paths.empty() || 355 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 356 357 // Open up a file stream for writing 358 int OpenFlags = O_TRUNC | O_WRONLY | O_CREAT; 359#ifdef O_BINARY 360 OpenFlags |= O_BINARY; 361#endif 362 363 // Retain the original mode. 364 sys::fs::perms Mode = sys::fs::perms(I->getMode()); 365 366 int FD = open(I->getPath().str().c_str(), OpenFlags, Mode); 367 if (FD < 0) 368 return true; 369 370 { 371 raw_fd_ostream file(FD, false); 372 373 // Get the data and its length 374 const char* data = reinterpret_cast<const char*>(I->getData()); 375 unsigned len = I->getSize(); 376 377 // Write the data. 378 file.write(data, len); 379 } 380 381 // If we're supposed to retain the original modification times, etc. do so 382 // now. 383 if (OriginalDates) { 384 error_code EC = 385 sys::fs::setLastModificationAndAccessTime(FD, I->getModTime()); 386 if (EC) 387 fail(EC.message()); 388 } 389 if (close(FD)) 390 return true; 391 } 392 } 393 return false; 394} 395 396// doDelete - Implement the delete operation. This function deletes zero or more 397// members from the archive. Note that if the count is specified, there should 398// be no more than one path in the Paths list or else this algorithm breaks. 399// That check is enforced in parseCommandLine (above). 400bool 401doDelete(std::string* ErrMsg) { 402 if (buildPaths(false, ErrMsg)) 403 return true; 404 if (Paths.empty()) 405 return false; 406 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 407 I != E; ) { 408 if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 409 Archive::iterator J = I; 410 ++I; 411 TheArchive->erase(J); 412 } else { 413 ++I; 414 } 415 } 416 417 // We're done editting, reconstruct the archive. 418 if (TheArchive->writeToDisk(ErrMsg)) 419 return true; 420 return false; 421} 422 423// doMore - Implement the move operation. This function re-arranges just the 424// order of the archive members so that when the archive is written the move 425// of the members is accomplished. Note the use of the RelPos variable to 426// determine where the items should be moved to. 427bool 428doMove(std::string* ErrMsg) { 429 if (buildPaths(false, ErrMsg)) 430 return true; 431 432 // By default and convention the place to move members to is the end of the 433 // archive. 434 Archive::iterator moveto_spot = TheArchive->end(); 435 436 // However, if the relative positioning modifiers were used, we need to scan 437 // the archive to find the member in question. If we don't find it, its no 438 // crime, we just move to the end. 439 if (AddBefore || InsertBefore || AddAfter) { 440 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 441 I != E; ++I ) { 442 if (RelPos == I->getPath().str()) { 443 if (AddAfter) { 444 moveto_spot = I; 445 moveto_spot++; 446 } else { 447 moveto_spot = I; 448 } 449 break; 450 } 451 } 452 } 453 454 // Keep a list of the paths remaining to be moved 455 std::set<std::string> remaining(Paths); 456 457 // Scan the archive again, this time looking for the members to move to the 458 // moveto_spot. 459 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 460 I != E && !remaining.empty(); ++I ) { 461 std::set<std::string>::iterator found = 462 std::find(remaining.begin(),remaining.end(), I->getPath()); 463 if (found != remaining.end()) { 464 if (I != moveto_spot) 465 TheArchive->splice(moveto_spot,*TheArchive,I); 466 remaining.erase(found); 467 } 468 } 469 470 // We're done editting, reconstruct the archive. 471 if (TheArchive->writeToDisk(ErrMsg)) 472 return true; 473 return false; 474} 475 476// doQuickAppend - Implements the 'q' operation. This function just 477// indiscriminantly adds the members to the archive and rebuilds it. 478bool 479doQuickAppend(std::string* ErrMsg) { 480 // Get the list of paths to append. 481 if (buildPaths(true, ErrMsg)) 482 return true; 483 if (Paths.empty()) 484 return false; 485 486 // Append them quickly. 487 for (std::set<std::string>::iterator PI = Paths.begin(), PE = Paths.end(); 488 PI != PE; ++PI) { 489 if (TheArchive->addFileBefore(*PI, TheArchive->end(), ErrMsg)) 490 return true; 491 } 492 493 // We're done editting, reconstruct the archive. 494 if (TheArchive->writeToDisk(ErrMsg)) 495 return true; 496 return false; 497} 498 499// doReplaceOrInsert - Implements the 'r' operation. This function will replace 500// any existing files or insert new ones into the archive. 501bool 502doReplaceOrInsert(std::string* ErrMsg) { 503 504 // Build the list of files to be added/replaced. 505 if (buildPaths(true, ErrMsg)) 506 return true; 507 if (Paths.empty()) 508 return false; 509 510 // Keep track of the paths that remain to be inserted. 511 std::set<std::string> remaining(Paths); 512 513 // Default the insertion spot to the end of the archive 514 Archive::iterator insert_spot = TheArchive->end(); 515 516 // Iterate over the archive contents 517 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 518 I != E && !remaining.empty(); ++I ) { 519 520 // Determine if this archive member matches one of the paths we're trying 521 // to replace. 522 523 std::set<std::string>::iterator found = remaining.end(); 524 for (std::set<std::string>::iterator RI = remaining.begin(), 525 RE = remaining.end(); RI != RE; ++RI ) { 526 std::string compare(sys::path::filename(*RI)); 527 if (compare == I->getPath().str()) { 528 found = RI; 529 break; 530 } 531 } 532 533 if (found != remaining.end()) { 534 sys::fs::file_status Status; 535 error_code EC = sys::fs::status(*found, Status); 536 if (EC) 537 return true; 538 if (!sys::fs::is_directory(Status)) { 539 if (OnlyUpdate) { 540 // Replace the item only if it is newer. 541 if (Status.getLastModificationTime() > I->getModTime()) 542 if (I->replaceWith(*found, ErrMsg)) 543 return true; 544 } else { 545 // Replace the item regardless of time stamp 546 if (I->replaceWith(*found, ErrMsg)) 547 return true; 548 } 549 } else { 550 // We purposefully ignore directories. 551 } 552 553 // Remove it from our "to do" list 554 remaining.erase(found); 555 } 556 557 // Determine if this is the place where we should insert 558 if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) 559 insert_spot = I; 560 else if (AddAfter && RelPos == I->getPath().str()) { 561 insert_spot = I; 562 insert_spot++; 563 } 564 } 565 566 // If we didn't replace all the members, some will remain and need to be 567 // inserted at the previously computed insert-spot. 568 if (!remaining.empty()) { 569 for (std::set<std::string>::iterator PI = remaining.begin(), 570 PE = remaining.end(); PI != PE; ++PI) { 571 if (TheArchive->addFileBefore(*PI, insert_spot, ErrMsg)) 572 return true; 573 } 574 } 575 576 // We're done editting, reconstruct the archive. 577 if (TheArchive->writeToDisk(ErrMsg)) 578 return true; 579 return false; 580} 581 582bool shouldCreateArchive(ArchiveOperation Op) { 583 switch (Op) { 584 case Print: 585 case Delete: 586 case Move: 587 case DisplayTable: 588 case Extract: 589 return false; 590 591 case QuickAppend: 592 case ReplaceOrInsert: 593 return true; 594 } 595 596 llvm_unreachable("Missing entry in covered switch."); 597} 598 599// main - main program for llvm-ar .. see comments in the code 600int main(int argc, char **argv) { 601 program_name = argv[0]; 602 // Print a stack trace if we signal out. 603 sys::PrintStackTraceOnErrorSignal(); 604 PrettyStackTraceProgram X(argc, argv); 605 LLVMContext &Context = getGlobalContext(); 606 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 607 608 // Have the command line options parsed and handle things 609 // like --help and --version. 610 cl::ParseCommandLineOptions(argc, argv, 611 "LLVM Archiver (llvm-ar)\n\n" 612 " This program archives bitcode files into single libraries\n" 613 ); 614 615 int exitCode = 0; 616 617 // Do our own parsing of the command line because the CommandLine utility 618 // can't handle the grouped positional parameters without a dash. 619 ArchiveOperation Operation = parseCommandLine(); 620 621 // Create or open the archive object. 622 if (shouldCreateArchive(Operation) && !llvm::sys::fs::exists(ArchiveName)) { 623 // Produce a warning if we should and we're creating the archive 624 if (!Create) 625 errs() << argv[0] << ": creating " << ArchiveName << "\n"; 626 TheArchive = Archive::CreateEmpty(ArchiveName, Context); 627 TheArchive->writeToDisk(); 628 } 629 630 if (!TheArchive) { 631 std::string Error; 632 TheArchive = Archive::OpenAndLoad(ArchiveName, Context, &Error); 633 if (TheArchive == 0) { 634 errs() << argv[0] << ": error loading '" << ArchiveName << "': " 635 << Error << "!\n"; 636 return 1; 637 } 638 } 639 640 // Make sure we're not fooling ourselves. 641 assert(TheArchive && "Unable to instantiate the archive"); 642 643 // Perform the operation 644 std::string ErrMsg; 645 bool haveError = false; 646 switch (Operation) { 647 case Print: haveError = doPrint(&ErrMsg); break; 648 case Delete: haveError = doDelete(&ErrMsg); break; 649 case Move: haveError = doMove(&ErrMsg); break; 650 case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 651 case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 652 case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 653 case Extract: haveError = doExtract(&ErrMsg); break; 654 } 655 if (haveError) { 656 errs() << argv[0] << ": " << ErrMsg << "\n"; 657 return 1; 658 } 659 660 delete TheArchive; 661 TheArchive = 0; 662 663 // Return result code back to operating system. 664 return exitCode; 665} 666