summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/llvm-ar/llvm-ar.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/llvm-ar/llvm-ar.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/llvm-ar/llvm-ar.cpp')
-rw-r--r--gnu/llvm/tools/llvm-ar/llvm-ar.cpp296
1 files changed, 185 insertions, 111 deletions
diff --git a/gnu/llvm/tools/llvm-ar/llvm-ar.cpp b/gnu/llvm/tools/llvm-ar/llvm-ar.cpp
index ae7d1a7f1b7..64be08ff946 100644
--- a/gnu/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/gnu/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -15,8 +15,6 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
-#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/MachO.h"
@@ -26,15 +24,17 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
+#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
@@ -47,10 +47,74 @@ using namespace llvm;
// The name this program was invoked as.
static StringRef ToolName;
+// The basename of this program.
+static StringRef Stem;
+
+const char RanlibHelp[] = R"(
+OVERVIEW: LLVM Ranlib (llvm-ranlib)
+
+ This program generates an index to speed access to archives
+
+USAGE: llvm-ranlib <archive-file>
+
+OPTIONS:
+ -help - Display available options
+ -version - Display the version of this program
+)";
+
+const char ArHelp[] = R"(
+OVERVIEW: LLVM Archiver
+
+USAGE: llvm-ar [options] [-]<operation>[modifiers] [relpos] <archive> [files]
+ llvm-ar -M [<mri-script]
+
+OPTIONS:
+ --format - Archive format to create
+ =default - default
+ =gnu - gnu
+ =darwin - darwin
+ =bsd - bsd
+ --plugin=<string> - Ignored for compatibility
+ --help - Display available options
+ --version - Display the version of this program
+
+OPERATIONS:
+ d - delete [files] from the archive
+ m - move [files] in the archive
+ p - print [files] found in the archive
+ q - quick append [files] to the archive
+ r - replace or insert [files] into the archive
+ s - act as ranlib
+ t - display contents of archive
+ x - extract [files] from the archive
+
+MODIFIERS:
+ [a] - put [files] after [relpos]
+ [b] - put [files] before [relpos] (same as [i])
+ [c] - do not warn if archive had to be created
+ [D] - use zero for timestamps and uids/gids (default)
+ [i] - put [files] before [relpos] (same as [b])
+ [l] - ignored for compatibility
+ [o] - preserve original dates
+ [s] - create an archive index (cf. ranlib)
+ [S] - do not build a symbol table
+ [T] - create a thin archive
+ [u] - update only [files] newer than archive contents
+ [U] - use actual timestamps and uids/gids
+ [v] - be verbose about actions taken
+)";
+
+void printHelpMessage() {
+ if (Stem.contains_lower("ranlib"))
+ outs() << RanlibHelp;
+ else if (Stem.contains_lower("ar"))
+ outs() << ArHelp;
+}
+
// Show the error message and exit.
LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) {
errs() << ToolName << ": " << Error << ".\n";
- cl::PrintHelpMessage();
+ printHelpMessage();
exit(1);
}
@@ -76,55 +140,18 @@ static void failIfError(Error E, Twine Context = "") {
});
}
-// llvm-ar/llvm-ranlib remaining positional arguments.
-static cl::list<std::string>
- RestOfArgs(cl::Positional, cl::ZeroOrMore,
- cl::desc("[relpos] [count] <archive-file> [members]..."));
+static SmallVector<const char *, 256> PositionalArgs;
-static cl::opt<bool> MRI("M", cl::desc(""));
-static cl::opt<std::string> Plugin("plugin", cl::desc("plugin (ignored for compatibility"));
+static bool MRI;
namespace {
-enum Format { Default, GNU, BSD, DARWIN };
+enum Format { Default, GNU, BSD, DARWIN, Unknown };
}
-static cl::opt<Format>
- FormatOpt("format", cl::desc("Archive format to create"),
- cl::values(clEnumValN(Default, "default", "default"),
- clEnumValN(GNU, "gnu", "gnu"),
- clEnumValN(DARWIN, "darwin", "darwin"),
- clEnumValN(BSD, "bsd", "bsd")));
+static Format FormatType = Default;
static std::string Options;
-// Provide additional help output explaining the operations and modifiers of
-// llvm-ar. This object instructs the CommandLine library to print the text of
-// the constructor when the --help option is given.
-static cl::extrahelp MoreHelp(
- "\nOPERATIONS:\n"
- " d[NsS] - delete file(s) from the archive\n"
- " m[abiSs] - move file(s) in the archive\n"
- " p[kN] - print file(s) found in the archive\n"
- " q[ufsS] - quick append file(s) to the archive\n"
- " r[abfiuRsS] - replace or insert file(s) into the archive\n"
- " t - display contents of archive\n"
- " x[No] - extract file(s) from the archive\n"
- "\nMODIFIERS (operation specific):\n"
- " [a] - put file(s) after [relpos]\n"
- " [b] - put file(s) before [relpos] (same as [i])\n"
- " [i] - put file(s) before [relpos] (same as [b])\n"
- " [o] - preserve original dates\n"
- " [s] - create an archive index (cf. ranlib)\n"
- " [S] - do not build a symbol table\n"
- " [T] - create a thin archive\n"
- " [u] - update only files newer than archive contents\n"
- "\nMODIFIERS (generic):\n"
- " [c] - do not warn if the library had to be created\n"
- " [v] - be verbose about actions taken\n"
-);
-
-static const char OptionChars[] = "dmpqrtxabiosSTucv";
-
// This enumeration delineates the kinds of operations on an archive
// that are permitted.
enum ArchiveOperation {
@@ -166,30 +193,23 @@ static std::vector<StringRef> Members;
// Extract the member filename from the command line for the [relpos] argument
// associated with a, b, and i modifiers
static void getRelPos() {
- if(RestOfArgs.size() == 0)
+ if (PositionalArgs.size() == 0)
fail("Expected [relpos] for a, b, or i modifier");
- RelPos = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
-}
-
-static void getOptions() {
- if(RestOfArgs.size() == 0)
- fail("Expected options");
- Options = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
+ RelPos = PositionalArgs[0];
+ PositionalArgs.erase(PositionalArgs.begin());
}
// Get the archive file name from the command line
static void getArchive() {
- if(RestOfArgs.size() == 0)
+ if (PositionalArgs.size() == 0)
fail("An archive name must be specified");
- ArchiveName = RestOfArgs[0];
- RestOfArgs.erase(RestOfArgs.begin());
+ ArchiveName = PositionalArgs[0];
+ PositionalArgs.erase(PositionalArgs.begin());
}
-// Copy over remaining items in RestOfArgs to our Members vector
+// Copy over remaining items in PositionalArgs to our Members vector
static void getMembers() {
- for (auto &Arg : RestOfArgs)
+ for (auto &Arg : PositionalArgs)
Members.push_back(Arg);
}
@@ -200,13 +220,11 @@ static void runMRIScript();
// modifier/operation pairs have not been violated.
static ArchiveOperation parseCommandLine() {
if (MRI) {
- if (!RestOfArgs.empty())
+ if (!PositionalArgs.empty() || !Options.empty())
fail("Cannot mix -M and other options");
runMRIScript();
}
- getOptions();
-
// Keep track of number of operations. We can only specify one
// per execution.
unsigned NumOperations = 0;
@@ -370,6 +388,7 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
int FD;
failIfError(sys::fs::openFileForWrite(sys::path::filename(Name), FD,
+ sys::fs::CD_CreateAlways,
sys::fs::F_None, Mode),
Name);
@@ -651,7 +670,7 @@ performWriteOperation(ArchiveOperation Operation,
NewMembers = computeNewArchiveMembers(Operation, OldArchive);
object::Archive::Kind Kind;
- switch (FormatOpt) {
+ switch (FormatType) {
case Default:
if (Thin)
Kind = object::Archive::K_GNU;
@@ -677,6 +696,8 @@ performWriteOperation(ArchiveOperation Operation,
fail("Only the gnu format has a thin mode");
Kind = object::Archive::K_DARWIN;
break;
+ case Unknown:
+ llvm_unreachable("");
}
Error E =
@@ -758,7 +779,7 @@ static int performOperation(ArchiveOperation Operation,
}
static void runMRIScript() {
- enum class MRICommand { AddLib, AddMod, Create, Save, End, Invalid };
+ enum class MRICommand { AddLib, AddMod, Create, Delete, Save, End, Invalid };
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getSTDIN();
failIfError(Buf.getError());
@@ -779,6 +800,7 @@ static void runMRIScript() {
.Case("addlib", MRICommand::AddLib)
.Case("addmod", MRICommand::AddMod)
.Case("create", MRICommand::Create)
+ .Case("delete", MRICommand::Delete)
.Case("save", MRICommand::Save)
.Case("end", MRICommand::End)
.Default(MRICommand::Invalid);
@@ -813,6 +835,12 @@ static void runMRIScript() {
fail("File already saved");
ArchiveName = Rest;
break;
+ case MRICommand::Delete: {
+ StringRef Name = sys::path::filename(Rest);
+ llvm::erase_if(NewMembers,
+ [=](NewArchiveMember &M) { return M.MemberName == Name; });
+ break;
+ }
case MRICommand::Save:
Saved = true;
break;
@@ -829,67 +857,113 @@ static void runMRIScript() {
exit(0);
}
-static int ar_main() {
- // Do our own parsing of the command line because the CommandLine utility
- // can't handle the grouped positional parameters without a dash.
+static bool handleGenericOption(StringRef arg) {
+ if (arg == "-help" || arg == "--help") {
+ printHelpMessage();
+ return true;
+ }
+ if (arg == "-version" || arg == "--version") {
+ cl::PrintVersionMessage();
+ return true;
+ }
+ return false;
+}
+
+static int ar_main(int argc, char **argv) {
+ SmallVector<const char *, 0> Argv(argv, argv + argc);
+ BumpPtrAllocator Alloc;
+ StringSaver Saver(Alloc);
+ cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
+ for(size_t i = 1; i < Argv.size(); ++i) {
+ StringRef Arg = Argv[i];
+ const char *match;
+ auto MatchFlagWithArg = [&](const char *expected) {
+ size_t len = strlen(expected);
+ if (Arg == expected) {
+ if (++i >= Argv.size())
+ fail(std::string(expected) + " requires an argument");
+ match = Argv[i];
+ return true;
+ }
+ if (Arg.startswith(expected) && Arg.size() > len &&
+ Arg[len] == '=') {
+ match = Arg.data() + len + 1;
+ return true;
+ }
+ return false;
+ };
+ if (handleGenericOption(Argv[i]))
+ return 0;
+ if (Arg == "--") {
+ for(; i < Argv.size(); ++i)
+ PositionalArgs.push_back(Argv[i]);
+ break;
+ }
+ if (Arg[0] == '-') {
+ if (Arg.startswith("--"))
+ Arg = Argv[i] + 2;
+ else
+ Arg = Argv[i] + 1;
+ if (Arg == "M") {
+ MRI = true;
+ } else if (MatchFlagWithArg("format")) {
+ FormatType = StringSwitch<Format>(match)
+ .Case("default", Default)
+ .Case("gnu", GNU)
+ .Case("darwin", DARWIN)
+ .Case("bsd", BSD)
+ .Default(Unknown);
+ if (FormatType == Unknown)
+ fail(std::string("Invalid format ") + match);
+ } else if (MatchFlagWithArg("plugin")) {
+ // Ignored.
+ } else {
+ Options += Argv[i] + 1;
+ }
+ } else if (Options.empty()) {
+ Options += Argv[i];
+ } else {
+ PositionalArgs.push_back(Argv[i]);
+ }
+ }
ArchiveOperation Operation = parseCommandLine();
return performOperation(Operation, nullptr);
}
-static int ranlib_main() {
- if (RestOfArgs.size() != 1)
- fail(ToolName + " takes just one archive as an argument");
- ArchiveName = RestOfArgs[0];
+static int ranlib_main(int argc, char **argv) {
+ bool ArchiveSpecified = false;
+ for(int i = 1; i < argc; ++i) {
+ if (handleGenericOption(argv[i])) {
+ return 0;
+ } else {
+ if (ArchiveSpecified)
+ fail("Exactly one archive should be specified");
+ ArchiveSpecified = true;
+ ArchiveName = argv[i];
+ }
+ }
return performOperation(CreateSymTab, nullptr);
}
int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
ToolName = argv[0];
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
- StringRef Stem = sys::path::stem(ToolName);
- if (Stem.find("dlltool") != StringRef::npos)
+ Stem = sys::path::stem(ToolName);
+ if (Stem.contains_lower("dlltool"))
return dlltoolDriverMain(makeArrayRef(argv, argc));
- if (Stem.find("ranlib") == StringRef::npos &&
- Stem.find("lib") != StringRef::npos)
- return libDriverMain(makeArrayRef(argv, argc));
+ if (Stem.contains_lower("ranlib"))
+ return ranlib_main(argc, argv);
- for (int i = 1; i < argc; i++) {
- // If an argument starts with a dash and only contains chars
- // that belong to the options chars set, remove the dash.
- // We can't handle it after the command line options parsing
- // is done, since it will error out on an unrecognized string
- // starting with a dash.
- // Make sure this doesn't match the actual llvm-ar specific options
- // that start with a dash.
- StringRef S = argv[i];
- if (S.startswith("-") &&
- S.find_first_not_of(OptionChars, 1) == StringRef::npos) {
- argv[i]++;
- break;
- }
- if (S == "--")
- break;
- }
+ if (Stem.contains_lower("lib"))
+ return libDriverMain(makeArrayRef(argv, argc));
- // Have the command line options parsed and handle things
- // like --help and --version.
- cl::ParseCommandLineOptions(argc, argv,
- "LLVM Archiver (llvm-ar)\n\n"
- " This program archives bitcode files into single libraries\n"
- );
-
- if (Stem.find("ranlib") != StringRef::npos)
- return ranlib_main();
- if (Stem.find("ar") != StringRef::npos)
- return ar_main();
+ if (Stem.contains_lower("ar"))
+ return ar_main(argc, argv);
fail("Not ranlib, ar, lib or dlltool!");
}