aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2013-08-07 15:07:10 -0700
committerStephen Hines <srhines@google.com>2013-08-07 15:07:10 -0700
commitfab2daa4a1127ecb217abe2b07c1769122b6fee1 (patch)
tree268ebfd1963fd98ba412e76819afdf95a7d4267b /tools
parent8197ac1c1a0a91baa70c4dea8cb488f254ef974c (diff)
parent10251753b6897adcd22cc981c0cc42f348c109de (diff)
downloadexternal_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.zip
external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.gz
external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.bz2
Merge commit '10251753b6897adcd22cc981c0cc42f348c109de' into merge-20130807
Conflicts: lib/Archive/ArchiveReader.cpp lib/Support/Unix/PathV2.inc Change-Id: I29d8c1e321a4a380b6013f00bac6a8e4b593cc4e
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt10
-rw-r--r--tools/LLVMBuild.txt2
-rw-r--r--tools/Makefile2
-rw-r--r--tools/bugpoint/BugDriver.cpp4
-rw-r--r--tools/bugpoint/BugDriver.h4
-rw-r--r--tools/bugpoint/CrashDebugger.cpp12
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp62
-rw-r--r--tools/bugpoint/ExtractFunction.cpp30
-rw-r--r--tools/bugpoint/FindBugs.cpp3
-rw-r--r--tools/bugpoint/Miscompilation.cpp99
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp99
-rw-r--r--tools/bugpoint/ToolRunner.cpp199
-rw-r--r--tools/bugpoint/ToolRunner.h61
-rw-r--r--tools/gold/gold-plugin.cpp20
-rw-r--r--tools/llc/llc.cpp9
-rw-r--r--tools/lli/CMakeLists.txt2
-rw-r--r--tools/lli/LLVMBuild.txt2
-rw-r--r--tools/lli/Makefile2
-rw-r--r--tools/lli/lli.cpp16
-rw-r--r--tools/llvm-ar/CMakeLists.txt2
-rw-r--r--tools/llvm-ar/LLVMBuild.txt1
-rw-r--r--tools/llvm-ar/Makefile2
-rw-r--r--tools/llvm-ar/llvm-ar.cpp1106
-rw-r--r--tools/llvm-as/llvm-as.cpp5
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp2
-rw-r--r--tools/llvm-config/llvm-config.cpp7
-rw-r--r--tools/llvm-dis/llvm-dis.cpp5
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp1
-rw-r--r--tools/llvm-extract/llvm-extract.cpp3
-rw-r--r--tools/llvm-link/llvm-link.cpp16
-rw-r--r--tools/llvm-mc/Disassembler.cpp72
-rw-r--r--tools/llvm-mc/llvm-mc.cpp6
-rw-r--r--tools/llvm-nm/CMakeLists.txt2
-rw-r--r--tools/llvm-nm/LLVMBuild.txt2
-rw-r--r--tools/llvm-nm/Makefile2
-rw-r--r--tools/llvm-nm/llvm-nm.cpp54
-rw-r--r--tools/llvm-objdump/COFFDump.cpp2
-rw-r--r--tools/llvm-objdump/MachODump.cpp2
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp2
-rw-r--r--tools/llvm-ranlib/CMakeLists.txt5
-rw-r--r--tools/llvm-ranlib/LLVMBuild.txt22
-rw-r--r--tools/llvm-ranlib/Makefile17
-rw-r--r--tools/llvm-ranlib/llvm-ranlib.cpp98
-rw-r--r--tools/llvm-readobj/CMakeLists.txt1
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp118
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp4
-rw-r--r--tools/llvm-readobj/LLVMBuild.txt2
-rw-r--r--tools/llvm-readobj/Makefile2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp14
-rw-r--r--tools/llvm-shlib/Makefile8
-rw-r--r--tools/llvm-stress/llvm-stress.cpp2
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp136
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.h33
-rw-r--r--tools/llvm-symbolizer/llvm-symbolizer.cpp6
-rw-r--r--tools/lto/LTOCodeGenerator.cpp122
-rw-r--r--tools/lto/LTOCodeGenerator.h55
-rw-r--r--tools/lto/LTOModule.cpp32
-rw-r--r--tools/lto/LTOModule.h1
-rw-r--r--tools/lto/Makefile2
-rw-r--r--tools/lto/lto.cpp15
-rw-r--r--tools/obj2yaml/CMakeLists.txt2
-rw-r--r--tools/obj2yaml/coff2yaml.cpp2
-rw-r--r--tools/opt/opt.cpp19
-rw-r--r--tools/yaml2obj/yaml2elf.cpp362
64 files changed, 1829 insertions, 1183 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 6b7c884..e663781 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -14,7 +14,6 @@ add_subdirectory(llvm-dis)
add_subdirectory(llvm-mc)
add_subdirectory(llc)
-add_subdirectory(llvm-ranlib)
add_subdirectory(llvm-ar)
add_subdirectory(llvm-nm)
add_subdirectory(llvm-size)
@@ -59,8 +58,11 @@ if( LLVM_ENABLE_PIC )
endif()
add_llvm_external_project(clang)
-add_llvm_external_project(lld)
-add_llvm_external_project(lldb)
-add_llvm_external_project(polly)
+
+if( NOT LLVM_INCLUDE_TOOLS STREQUAL "bootstrap-only" )
+ add_llvm_external_project(lld)
+ add_llvm_external_project(lldb)
+ add_llvm_external_project(polly)
+endif()
set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt
index 25aa177..9ec89f3 100644
--- a/tools/LLVMBuild.txt
+++ b/tools/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
+subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
[component_0]
type = Group
diff --git a/tools/Makefile b/tools/Makefile
index eaf9ed3..b7375c9 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -28,7 +28,7 @@ OPTIONAL_DIRS := lldb
# in parallel builds. Please retain this ordering.
DIRS := llvm-config
PARALLEL_DIRS := opt llvm-as llvm-dis \
- llc llvm-ranlib llvm-ar llvm-nm \
+ llc llvm-ar llvm-nm \
llvm-prof llvm-link \
lli llvm-extract llvm-mc \
bugpoint llvm-bcanalyzer \
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index 937d86a..a5436ba 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -194,8 +194,8 @@ bool BugDriver::run(std::string &ErrMsg) {
// Make sure the reference output file gets deleted on exit from this
// function, if appropriate.
- sys::Path ROF(ReferenceOutputFile);
- FileRemover RemoverInstance(ROF.str(), CreatedOutput && !SaveTemps);
+ std::string ROF(ReferenceOutputFile);
+ FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps);
// Diff the output of the raw program against the reference output. If it
// matches, then we assume there is a miscompilation bug and try to
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index 2b621ec..27b37f4 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -191,7 +191,7 @@ public:
/// this function.
///
bool createReferenceFile(Module *M, const std::string &Filename
- = "bugpoint.reference.out");
+ = "bugpoint.reference.out-%%%%%%%");
/// diffProgram - This method executes the specified module and diffs the
/// output against the file specified by ReferenceOutputFile. If the output
@@ -275,6 +275,8 @@ public:
/// bitcode file. If an error occurs, true is returned.
///
bool writeProgramToFile(const std::string &Filename, const Module *M) const;
+ bool writeProgramToFile(const std::string &Filename, int FD,
+ const Module *M) const;
private:
/// runPasses - Just like the method above, but this just returns true or
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index ed211a6..c8b4f6f 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -62,25 +62,23 @@ ReducePassList::TestResult
ReducePassList::doTest(std::vector<std::string> &Prefix,
std::vector<std::string> &Suffix,
std::string &Error) {
- sys::Path PrefixOutput;
+ std::string PrefixOutput;
Module *OrigProgram = 0;
if (!Prefix.empty()) {
outs() << "Checking to see if these passes crash: "
<< getPassesString(Prefix) << ": ";
- std::string PfxOutput;
- if (BD.runPasses(BD.getProgram(), Prefix, PfxOutput))
+ if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
return KeepPrefix;
- PrefixOutput.set(PfxOutput);
OrigProgram = BD.Program;
- BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext());
+ BD.Program = ParseInputFile(PrefixOutput, BD.getContext());
if (BD.Program == 0) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
- << PrefixOutput.str() << "'!\n";
+ << PrefixOutput << "'!\n";
exit(1);
}
- PrefixOutput.eraseFromDisk();
+ sys::fs::remove(PrefixOutput);
}
outs() << "Checking to see if these passes crash: "
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index da36045..3d3dac3 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -265,16 +265,18 @@ bool BugDriver::initializeExecutionEnvironment() {
///
void BugDriver::compileProgram(Module *M, std::string *Error) const {
// Emit the program to a bitcode file...
- sys::Path BitcodeFile (OutputPrefix + "-test-program.bc");
- std::string ErrMsg;
- if (BitcodeFile.makeUnique(true, &ErrMsg)) {
- errs() << ToolName << ": Error making unique filename: " << ErrMsg
+ SmallString<128> BitcodeFile;
+ int BitcodeFD;
+ error_code EC = sys::fs::createUniqueFile(
+ OutputPrefix + "-test-program-%%%%%%%.bc", BitcodeFD, BitcodeFile);
+ if (EC) {
+ errs() << ToolName << ": Error making unique filename: " << EC.message()
<< "\n";
exit(1);
}
- if (writeProgramToFile(BitcodeFile.str(), M)) {
- errs() << ToolName << ": Error emitting bitcode to file '"
- << BitcodeFile.str() << "'!\n";
+ if (writeProgramToFile(BitcodeFile.str(), BitcodeFD, M)) {
+ errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile
+ << "'!\n";
exit(1);
}
@@ -302,15 +304,18 @@ std::string BugDriver::executeProgram(const Module *Program,
std::string ErrMsg;
if (BitcodeFile.empty()) {
// Emit the program to a bitcode file...
- sys::Path uniqueFilename(OutputPrefix + "-test-program.bc");
- if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+ SmallString<128> UniqueFilename;
+ int UniqueFD;
+ error_code EC = sys::fs::createUniqueFile(
+ OutputPrefix + "-test-program-%%%%%%%.bc", UniqueFD, UniqueFilename);
+ if (EC) {
errs() << ToolName << ": Error making unique filename: "
- << ErrMsg << "!\n";
+ << EC.message() << "!\n";
exit(1);
}
- BitcodeFile = uniqueFilename.str();
+ BitcodeFile = UniqueFilename.str();
- if (writeProgramToFile(BitcodeFile, Program)) {
+ if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) {
errs() << ToolName << ": Error emitting bitcode to file '"
<< BitcodeFile << "'!\n";
exit(1);
@@ -319,20 +324,21 @@ std::string BugDriver::executeProgram(const Module *Program,
}
// Remove the temporary bitcode file when we are done.
- sys::Path BitcodePath(BitcodeFile);
- FileRemover BitcodeFileRemover(BitcodePath.str(),
+ std::string BitcodePath(BitcodeFile);
+ FileRemover BitcodeFileRemover(BitcodePath,
CreatedBitcode && !SaveTemps);
- if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output";
+ if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output-%%%%%%%";
// Check to see if this is a valid output filename...
- sys::Path uniqueFile(OutputFile);
- if (uniqueFile.makeUnique(true, &ErrMsg)) {
+ SmallString<128> UniqueFile;
+ error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile);
+ if (EC) {
errs() << ToolName << ": Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- OutputFile = uniqueFile.str();
+ OutputFile = UniqueFile.str();
// Figure out which shared objects to run, if any.
std::vector<std::string> SharedObjs(AdditionalSOs);
@@ -380,7 +386,7 @@ std::string BugDriver::executeProgramSafely(const Module *Program,
std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
std::string &Error) {
assert(Interpreter && "Interpreter should have been created already!");
- sys::Path OutputFile;
+ std::string OutputFile;
// Using the known-good backend.
GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile,
@@ -389,7 +395,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
return "";
std::string SharedObjectFile;
- bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile,
+ bool Failure = gcc->MakeSharedObject(OutputFile, FT, SharedObjectFile,
AdditionalLinkerArgs, Error);
if (!Error.empty())
return "";
@@ -397,7 +403,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
exit(1);
// Remove the intermediate C file
- OutputFile.eraseFromDisk();
+ sys::fs::remove(OutputFile);
return "./" + SharedObjectFile;
}
@@ -439,15 +445,15 @@ bool BugDriver::diffProgram(const Module *Program,
bool RemoveBitcode,
std::string *ErrMsg) const {
// Execute the program, generating an output file...
- sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0,
- ErrMsg));
+ std::string Output(
+ executeProgram(Program, "", BitcodeFile, SharedObject, 0, ErrMsg));
if (!ErrMsg->empty())
return false;
std::string Error;
bool FilesDifferent = false;
- if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
- sys::Path(Output.str()),
+ if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile,
+ Output,
AbsTolerance, RelTolerance, &Error)) {
if (Diff == 2) {
errs() << "While diffing output: " << Error << '\n';
@@ -457,12 +463,12 @@ bool BugDriver::diffProgram(const Module *Program,
}
else {
// Remove the generated output if there are no differences.
- Output.eraseFromDisk();
+ sys::fs::remove(Output);
}
// Remove the bitcode file if we are supposed to.
if (RemoveBitcode)
- sys::Path(BitcodeFile).eraseFromDisk();
+ sys::fs::remove(BitcodeFile);
return FilesDifferent;
}
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index bb27767..2098928 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -363,25 +363,19 @@ llvm::SplitFunctionsOutOfModule(Module *M,
Module *BugDriver::ExtractMappedBlocksFromModule(const
std::vector<BasicBlock*> &BBs,
Module *M) {
- sys::Path uniqueFilename(OutputPrefix + "-extractblocks");
- std::string ErrMsg;
- if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
+ SmallString<128> Filename;
+ int FD;
+ error_code EC = sys::fs::createUniqueFile(
+ OutputPrefix + "-extractblocks%%%%%%%", FD, Filename);
+ if (EC) {
outs() << "*** Basic Block extraction failed!\n";
- errs() << "Error creating temporary file: " << ErrMsg << "\n";
+ errs() << "Error creating temporary file: " << EC.message() << "\n";
EmitProgressBitcode(M, "basicblockextractfail", true);
return 0;
}
- sys::RemoveFileOnSignal(uniqueFilename);
+ sys::RemoveFileOnSignal(Filename);
- std::string ErrorInfo;
- tool_output_file BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo);
- if (!ErrorInfo.empty()) {
- outs() << "*** Basic Block extraction failed!\n";
- errs() << "Error writing list of blocks to not extract: " << ErrorInfo
- << "\n";
- EmitProgressBitcode(M, "basicblockextractfail", true);
- return 0;
- }
+ tool_output_file BlocksToNotExtractFile(Filename.c_str(), FD);
for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
I != E; ++I) {
BasicBlock *BB = *I;
@@ -393,22 +387,22 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
}
BlocksToNotExtractFile.os().close();
if (BlocksToNotExtractFile.os().has_error()) {
- errs() << "Error writing list of blocks to not extract: " << ErrorInfo
- << "\n";
+ errs() << "Error writing list of blocks to not extract\n";
EmitProgressBitcode(M, "basicblockextractfail", true);
BlocksToNotExtractFile.os().clear_error();
return 0;
}
BlocksToNotExtractFile.keep();
- std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str();
+ std::string uniqueFN = "--extract-blocks-file=";
+ uniqueFN += Filename.str();
const char *ExtraArg = uniqueFN.c_str();
std::vector<std::string> PI;
PI.push_back("extract-blocks");
Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg);
- uniqueFilename.eraseFromDisk(); // Free disk space
+ sys::fs::remove(Filename.c_str());
if (Ret == 0) {
outs() << "*** Basic Block extraction failed, please report a bug!\n";
diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp
index a291f9f..e2941f6 100644
--- a/tools/bugpoint/FindBugs.cpp
+++ b/tools/bugpoint/FindBugs.cpp
@@ -17,6 +17,7 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/Pass.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <ctime>
@@ -103,7 +104,7 @@ bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses,
}
outs() << "\n*** diff'd output matches!\n";
- sys::Path(Filename).eraseFromDisk();
+ sys::fs::remove(Filename);
outs() << "\n\n";
num++;
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index 11ac0de..771ec34 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -120,7 +120,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
return InternalError;
if (Diff) {
outs() << " nope.\n";
- sys::Path(BitcodeResult).eraseFromDisk();
+ sys::fs::remove(BitcodeResult);
return KeepPrefix;
}
outs() << " yup.\n"; // No miscompilation!
@@ -135,7 +135,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
<< BitcodeResult << "'!\n";
exit(1);
}
- sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk
+ sys::fs::remove(BitcodeResult);
// Don't check if there are no passes in the suffix.
if (Suffix.empty())
@@ -337,8 +337,13 @@ static bool ExtractLoops(BugDriver &BD,
false, Error, Failure);
if (!New)
return false;
+
// Delete the original and set the new program.
- delete BD.swapProgramIn(New);
+ Module *Old = BD.swapProgramIn(New);
+ for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
+ MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
+ delete Old;
+
if (Failure) {
BD.switchToInterpreter(AI);
@@ -366,21 +371,51 @@ static bool ExtractLoops(BugDriver &BD,
outs() << " Testing after loop extraction:\n";
// Clone modules, the tester function will free them.
- Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted);
- Module *TNOBackup = CloneModule(ToNotOptimize);
+ Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted, VMap);
+ Module *TNOBackup = CloneModule(ToNotOptimize, VMap);
+
+ for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
+ MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
+
Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error);
if (!Error.empty())
return false;
+
+ ToOptimizeLoopExtracted = TOLEBackup;
+ ToNotOptimize = TNOBackup;
+
if (!Failure) {
outs() << "*** Loop extraction masked the problem. Undoing.\n";
// If the program is not still broken, then loop extraction did something
// that masked the error. Stop loop extraction now.
- delete TOLEBackup;
- delete TNOBackup;
+
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
+ for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) {
+ Function *F = MiscompiledFunctions[i];
+ MisCompFunctions.push_back(std::make_pair(F->getName(),
+ F->getFunctionType()));
+ }
+
+ std::string ErrorMsg;
+ if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted,
+ Linker::DestroySource, &ErrorMsg)){
+ errs() << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
+ exit(1);
+ }
+
+ MiscompiledFunctions.clear();
+ for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
+ Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
+
+ assert(NewF && "Function not found??");
+ MiscompiledFunctions.push_back(NewF);
+ }
+
+ delete ToOptimizeLoopExtracted;
+ BD.setNewProgram(ToNotOptimize);
return MadeChange;
}
- ToOptimizeLoopExtracted = TOLEBackup;
- ToNotOptimize = TNOBackup;
outs() << "*** Loop extraction successful!\n";
@@ -926,14 +961,16 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
std::string &Error) {
CleanupAndPrepareModules(BD, Test, Safe);
- sys::Path TestModuleBC("bugpoint.test.bc");
- std::string ErrMsg;
- if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> TestModuleBC;
+ int TestModuleFD;
+ error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc",
+ TestModuleFD, TestModuleBC);
+ if (EC) {
errs() << BD.getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(TestModuleBC.str(), Test)) {
+ if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) {
errs() << "Error writing bitcode to `" << TestModuleBC.str()
<< "'\nExiting.";
exit(1);
@@ -943,14 +980,17 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps);
// Make the shared library
- sys::Path SafeModuleBC("bugpoint.safe.bc");
- if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> SafeModuleBC;
+ int SafeModuleFD;
+ EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
+ SafeModuleBC);
+ if (EC) {
errs() << BD.getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) {
+ if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) {
errs() << "Error writing bitcode to `" << SafeModuleBC.str()
<< "'\nExiting.";
exit(1);
@@ -1015,15 +1055,17 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
// Condition the modules
CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen);
- sys::Path TestModuleBC("bugpoint.test.bc");
- std::string ErrMsg;
- if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> TestModuleBC;
+ int TestModuleFD;
+ error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc",
+ TestModuleFD, TestModuleBC);
+ if (EC) {
errs() << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) {
+ if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) {
errs() << "Error writing bitcode to `" << TestModuleBC.str()
<< "'\nExiting.";
exit(1);
@@ -1031,14 +1073,17 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
delete ToCodeGen;
// Make the shared library
- sys::Path SafeModuleBC("bugpoint.safe.bc");
- if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> SafeModuleBC;
+ int SafeModuleFD;
+ EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
+ SafeModuleBC);
+ if (EC) {
errs() << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) {
+ if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) {
errs() << "Error writing bitcode to `" << SafeModuleBC.str()
<< "'\nExiting.";
exit(1);
diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp
index 87dc9f3..20c609c 100644
--- a/tools/bugpoint/OptimizerDriver.cpp
+++ b/tools/bugpoint/OptimizerDriver.cpp
@@ -33,6 +33,7 @@
#include "llvm/Support/PluginLoader.h"
#include <fstream>
+
using namespace llvm;
namespace llvm {
@@ -43,25 +44,36 @@ namespace {
// ChildOutput - This option captures the name of the child output file that
// is set up by the parent bugpoint process
cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden);
+ cl::opt<std::string> OptCmd("opt-command", cl::init(""),
+ cl::desc("Path to opt. (default: search path "
+ "for 'opt'.)"));
}
/// writeProgramToFile - This writes the current "Program" to the named bitcode
/// file. If an error occurs, true is returned.
///
+static bool writeProgramToFileAux(tool_output_file &Out, const Module *M) {
+ WriteBitcodeToFile(M, Out.os());
+ Out.os().close();
+ if (!Out.os().has_error()) {
+ Out.keep();
+ return false;
+ }
+ return true;
+}
+
+bool BugDriver::writeProgramToFile(const std::string &Filename, int FD,
+ const Module *M) const {
+ tool_output_file Out(Filename.c_str(), FD);
+ return writeProgramToFileAux(Out, M);
+}
+
bool BugDriver::writeProgramToFile(const std::string &Filename,
const Module *M) const {
std::string ErrInfo;
- tool_output_file Out(Filename.c_str(), ErrInfo,
- raw_fd_ostream::F_Binary);
- if (ErrInfo.empty()) {
- WriteBitcodeToFile(M, Out.os());
- Out.os().close();
- if (!Out.os().has_error()) {
- Out.keep();
- return false;
- }
- }
- Out.os().clear_error();
+ tool_output_file Out(Filename.c_str(), ErrInfo, sys::fs::F_Binary);
+ if (ErrInfo.empty())
+ return writeProgramToFileAux(Out, M);
return true;
}
@@ -114,41 +126,38 @@ bool BugDriver::runPasses(Module *Program,
const char * const *ExtraArgs) const {
// setup the output file name
outs().flush();
- sys::Path uniqueFilename(OutputPrefix + "-output.bc");
- std::string ErrMsg;
- if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+ SmallString<128> UniqueFilename;
+ error_code EC = sys::fs::createUniqueFile(
+ OutputPrefix + "-output-%%%%%%%.bc", UniqueFilename);
+ if (EC) {
errs() << getToolName() << ": Error making unique filename: "
- << ErrMsg << "\n";
- return(1);
+ << EC.message() << "\n";
+ return 1;
}
- OutputFilename = uniqueFilename.str();
+ OutputFilename = UniqueFilename.str();
// set up the input file name
- sys::Path inputFilename(OutputPrefix + "-input.bc");
- if (inputFilename.makeUnique(true, &ErrMsg)) {
+ SmallString<128> InputFilename;
+ int InputFD;
+ EC = sys::fs::createUniqueFile(OutputPrefix + "-input-%%%%%%%.bc", InputFD,
+ InputFilename);
+ if (EC) {
errs() << getToolName() << ": Error making unique filename: "
- << ErrMsg << "\n";
- return(1);
+ << EC.message() << "\n";
+ return 1;
}
- std::string ErrInfo;
- tool_output_file InFile(inputFilename.c_str(), ErrInfo,
- raw_fd_ostream::F_Binary);
-
+ tool_output_file InFile(InputFilename.c_str(), InputFD);
- if (!ErrInfo.empty()) {
- errs() << "Error opening bitcode file: " << inputFilename.str() << "\n";
- return 1;
- }
WriteBitcodeToFile(Program, InFile.os());
InFile.os().close();
if (InFile.os().has_error()) {
- errs() << "Error writing bitcode file: " << inputFilename.str() << "\n";
+ errs() << "Error writing bitcode file: " << InputFilename << "\n";
InFile.os().clear_error();
return 1;
}
- sys::Path tool = sys::Program::FindProgramByName("opt");
+ std::string tool = OptCmd.empty()? sys::FindProgramByName("opt") : OptCmd;
if (tool.empty()) {
errs() << "Cannot find `opt' in PATH!\n";
return 1;
@@ -159,14 +168,13 @@ bool BugDriver::runPasses(Module *Program,
// setup the child process' arguments
SmallVector<const char*, 8> Args;
- std::string Opt = tool.str();
if (UseValgrind) {
Args.push_back("valgrind");
Args.push_back("--error-exitcode=1");
Args.push_back("-q");
Args.push_back(tool.c_str());
} else
- Args.push_back(Opt.c_str());
+ Args.push_back(tool.c_str());
Args.push_back("-o");
Args.push_back(OutputFilename.c_str());
@@ -183,7 +191,7 @@ bool BugDriver::runPasses(Module *Program,
for (std::vector<std::string>::const_iterator I = pass_args.begin(),
E = pass_args.end(); I != E; ++I )
Args.push_back(I->c_str());
- Args.push_back(inputFilename.c_str());
+ Args.push_back(InputFilename.c_str());
for (unsigned i = 0; i < NumExtraArgs; ++i)
Args.push_back(*ExtraArgs);
Args.push_back(0);
@@ -194,27 +202,28 @@ bool BugDriver::runPasses(Module *Program,
errs() << "\n";
);
- sys::Path prog;
+ std::string Prog;
if (UseValgrind)
- prog = sys::Program::FindProgramByName("valgrind");
+ Prog = sys::FindProgramByName("valgrind");
else
- prog = tool;
+ Prog = tool;
// Redirect stdout and stderr to nowhere if SilencePasses is given
- sys::Path Nowhere;
- const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere};
+ StringRef Nowhere;
+ const StringRef *Redirects[3] = {0, &Nowhere, &Nowhere};
- int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0,
- (SilencePasses ? Redirects : 0),
- Timeout, MemoryLimit, &ErrMsg);
+ std::string ErrMsg;
+ int result = sys::ExecuteAndWait(Prog, Args.data(), 0,
+ (SilencePasses ? Redirects : 0), Timeout,
+ MemoryLimit, &ErrMsg);
// If we are supposed to delete the bitcode file or if the passes crashed,
// remove it now. This may fail if the file was never created, but that's ok.
if (DeleteOutput || result != 0)
- sys::Path(OutputFilename).eraseFromDisk();
+ sys::fs::remove(OutputFilename);
// Remove the temporary input file as well
- inputFilename.eraseFromDisk();
+ sys::fs::remove(InputFilename.c_str());
if (!Quiet) {
if (result == 0)
@@ -262,6 +271,6 @@ Module *BugDriver::runPassesOn(Module *M,
<< BitcodeResult << "'!\n";
exit(1);
}
- sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk
+ sys::fs::remove(BitcodeResult);
return Ret;
}
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
index 735061d..107d0db 100644
--- a/tools/bugpoint/ToolRunner.cpp
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -16,6 +16,7 @@
#include "llvm/Config/config.h" // for HAVE_LINK_R
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -53,18 +54,15 @@ namespace {
/// RunProgramWithTimeout - This function provides an alternate interface
/// to the sys::Program::ExecuteAndWait interface.
/// @see sys::Program::ExecuteAndWait
-static int RunProgramWithTimeout(const sys::Path &ProgramPath,
+static int RunProgramWithTimeout(StringRef ProgramPath,
const char **Args,
- const sys::Path &StdInFile,
- const sys::Path &StdOutFile,
- const sys::Path &StdErrFile,
+ StringRef StdInFile,
+ StringRef StdOutFile,
+ StringRef StdErrFile,
unsigned NumSeconds = 0,
unsigned MemoryLimit = 0,
std::string *ErrMsg = 0) {
- const sys::Path* redirects[3];
- redirects[0] = &StdInFile;
- redirects[1] = &StdOutFile;
- redirects[2] = &StdErrFile;
+ const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
#if 0 // For debug purposes
{
@@ -75,9 +73,8 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath,
}
#endif
- return
- sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
- NumSeconds, MemoryLimit, ErrMsg);
+ return sys::ExecuteAndWait(ProgramPath, Args, 0, Redirects,
+ NumSeconds, MemoryLimit, ErrMsg);
}
/// RunProgramRemotelyWithTimeout - This function runs the given program
@@ -86,17 +83,14 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath,
/// fails. Remote client is required to return 255 if it failed or program exit
/// code otherwise.
/// @see sys::Program::ExecuteAndWait
-static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
+static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
const char **Args,
- const sys::Path &StdInFile,
- const sys::Path &StdOutFile,
- const sys::Path &StdErrFile,
+ StringRef StdInFile,
+ StringRef StdOutFile,
+ StringRef StdErrFile,
unsigned NumSeconds = 0,
unsigned MemoryLimit = 0) {
- const sys::Path* redirects[3];
- redirects[0] = &StdInFile;
- redirects[1] = &StdOutFile;
- redirects[2] = &StdErrFile;
+ const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
#if 0 // For debug purposes
{
@@ -108,8 +102,8 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
#endif
// Run the program remotely with the remote client
- int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args,
- 0, redirects, NumSeconds, MemoryLimit);
+ int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, 0,
+ Redirects, NumSeconds, MemoryLimit);
// Has the remote client fail?
if (255 == ReturnCode) {
@@ -120,7 +114,8 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
OS << "\n";
// The error message is in the output file, let's print it out from there.
- std::ifstream ErrorFile(StdOutFile.c_str());
+ std::string StdOutFileName = StdOutFile.str();
+ std::ifstream ErrorFile(StdOutFileName.c_str());
if (ErrorFile) {
std::copy(std::istreambuf_iterator<char>(ErrorFile),
std::istreambuf_iterator<char>(),
@@ -134,7 +129,7 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
return ReturnCode;
}
-static std::string ProcessFailure(sys::Path ProgPath, const char** Args,
+static std::string ProcessFailure(StringRef ProgPath, const char** Args,
unsigned Timeout = 0,
unsigned MemoryLimit = 0) {
std::ostringstream OS;
@@ -144,14 +139,16 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args,
OS << "\n";
// Rerun the compiler, capturing any error messages to print them.
- sys::Path ErrorFilename("bugpoint.program_error_messages");
- std::string ErrMsg;
- if (ErrorFilename.makeUnique(true, &ErrMsg)) {
- errs() << "Error making unique filename: " << ErrMsg << "\n";
+ SmallString<128> ErrorFilename;
+ int ErrorFD;
+ error_code EC = sys::fs::createTemporaryFile(
+ "bugpoint.program_error_messages", "", ErrorFD, ErrorFilename);
+ if (EC) {
+ errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
- ErrorFilename, Timeout, MemoryLimit);
+ RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(),
+ ErrorFilename.str(), Timeout, MemoryLimit);
// FIXME: check return code ?
// Print out the error messages generated by GCC if possible...
@@ -163,7 +160,7 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args,
ErrorFile.close();
}
- ErrorFilename.eraseFromDisk();
+ sys::fs::remove(ErrorFilename.c_str());
return OS.str();
}
@@ -229,19 +226,50 @@ int LLI::ExecuteProgram(const std::string &Bitcode,
errs() << " " << LLIArgs[i];
errs() << "\n";
);
- return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
- sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ return RunProgramWithTimeout(LLIPath, &LLIArgs[0],
+ InputFile, OutputFile, OutputFile,
Timeout, MemoryLimit, Error);
}
void AbstractInterpreter::anchor() { }
+#if defined(LLVM_ON_UNIX)
+const char EXESuffix[] = "";
+#elif defined (LLVM_ON_WIN32)
+const char EXESuffix[] = "exe";
+#endif
+
+/// Prepend the path to the program being executed
+/// to \p ExeName, given the value of argv[0] and the address of main()
+/// itself. This allows us to find another LLVM tool if it is built in the same
+/// directory. An empty string is returned on error; note that this function
+/// just mainpulates the path and doesn't check for executability.
+/// @brief Find a named executable.
+static std::string PrependMainExecutablePath(const std::string &ExeName,
+ const char *Argv0,
+ void *MainAddr) {
+ // Check the directory that the calling program is in. We can do
+ // this if ProgramPath contains at least one / character, indicating that it
+ // is a relative path to the executable itself.
+ std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
+ StringRef Result = sys::path::parent_path(Main);
+
+ if (!Result.empty()) {
+ SmallString<128> Storage = Result;
+ sys::path::append(Storage, ExeName);
+ sys::path::replace_extension(Storage, EXESuffix);
+ return Storage.str();
+ }
+
+ return Result.str();
+}
+
// LLI create method - Try to find the LLI executable
AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0,
std::string &Message,
const std::vector<std::string> *ToolArgs) {
std::string LLIPath =
- PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str();
+ PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createLLI);
if (!LLIPath.empty()) {
Message = "Found lli: " + LLIPath + "\n";
return new LLI(LLIPath, ToolArgs);
@@ -305,10 +333,10 @@ void CustomCompiler::compileProgram(const std::string &Bitcode,
for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
ProgramArgs.push_back(CompilerArgs[i].c_str());
- if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0],
- sys::Path(), sys::Path(), sys::Path(),
+ if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0],
+ "", "", "",
Timeout, MemoryLimit, Error))
- *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0],
+ *Error = ProcessFailure(CompilerCommand, &ProgramArgs[0],
Timeout, MemoryLimit);
}
@@ -363,9 +391,9 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
ProgramArgs.push_back(Args[i].c_str());
return RunProgramWithTimeout(
- sys::Path(ExecutionCommand),
- &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
- sys::Path(OutputFile), Timeout, MemoryLimit, Error);
+ ExecutionCommand,
+ &ProgramArgs[0], InputFile, OutputFile,
+ OutputFile, Timeout, MemoryLimit, Error);
}
// Tokenize the CommandLine to the command and the args to allow
@@ -398,7 +426,7 @@ static void lexCommand(std::string &Message, const std::string &CommandLine,
pos = CommandLine.find_first_of(delimiters, lastPos);
}
- CmdPath = sys::Program::FindProgramByName(Command).str();
+ CmdPath = sys::FindProgramByName(Command);
if (CmdPath.empty()) {
Message =
std::string("Cannot find '") + Command +
@@ -444,16 +472,18 @@ AbstractInterpreter *AbstractInterpreter::createCustomExecutor(
// LLC Implementation of AbstractIntepreter interface
//
GCC::FileType LLC::OutputCode(const std::string &Bitcode,
- sys::Path &OutputAsmFile, std::string &Error,
+ std::string &OutputAsmFile, std::string &Error,
unsigned Timeout, unsigned MemoryLimit) {
const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s");
- sys::Path uniqueFile(Bitcode + Suffix);
- std::string ErrMsg;
- if (uniqueFile.makeUnique(true, &ErrMsg)) {
- errs() << "Error making unique filename: " << ErrMsg << "\n";
+
+ SmallString<128> UniqueFile;
+ error_code EC =
+ sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile);
+ if (EC) {
+ errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- OutputAsmFile = uniqueFile;
+ OutputAsmFile = UniqueFile.str();
std::vector<const char *> LLCArgs;
LLCArgs.push_back(LLCPath.c_str());
@@ -477,19 +507,19 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode,
errs() << " " << LLCArgs[i];
errs() << "\n";
);
- if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
- sys::Path(), sys::Path(), sys::Path(),
+ if (RunProgramWithTimeout(LLCPath, &LLCArgs[0],
+ "", "", "",
Timeout, MemoryLimit))
- Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0],
+ Error = ProcessFailure(LLCPath, &LLCArgs[0],
Timeout, MemoryLimit);
return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile;
}
void LLC::compileProgram(const std::string &Bitcode, std::string *Error,
unsigned Timeout, unsigned MemoryLimit) {
- sys::Path OutputAsmFile;
+ std::string OutputAsmFile;
OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit);
- OutputAsmFile.eraseFromDisk();
+ sys::fs::remove(OutputAsmFile);
}
int LLC::ExecuteProgram(const std::string &Bitcode,
@@ -502,16 +532,16 @@ int LLC::ExecuteProgram(const std::string &Bitcode,
unsigned Timeout,
unsigned MemoryLimit) {
- sys::Path OutputAsmFile;
+ std::string OutputAsmFile;
GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout,
MemoryLimit);
- FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps);
+ FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
std::vector<std::string> GCCArgs(ArgsForGCC);
GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
// Assuming LLC worked, compile the result with GCC and run it.
- return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind,
+ return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind,
InputFile, OutputFile, Error, GCCArgs,
Timeout, MemoryLimit);
}
@@ -525,7 +555,7 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0,
const std::vector<std::string> *GCCArgs,
bool UseIntegratedAssembler) {
std::string LLCPath =
- PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str();
+ PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC);
if (LLCPath.empty()) {
Message = "Cannot find `llc' in executable directory!\n";
return 0;
@@ -603,8 +633,8 @@ int JIT::ExecuteProgram(const std::string &Bitcode,
errs() << "\n";
);
DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
- return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
- sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ return RunProgramWithTimeout(LLIPath, &JITArgs[0],
+ InputFile, OutputFile, OutputFile,
Timeout, MemoryLimit, Error);
}
@@ -613,7 +643,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode,
AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0,
std::string &Message, const std::vector<std::string> *Args) {
std::string LLIPath =
- PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str();
+ PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createJIT);
if (!LLIPath.empty()) {
Message = "Found lli: " + LLIPath + "\n";
return new JIT(LLIPath, Args);
@@ -682,10 +712,12 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
GCCArgs.push_back("-x");
GCCArgs.push_back("none");
GCCArgs.push_back("-o");
- sys::Path OutputBinary (ProgramFile+".gcc.exe");
- std::string ErrMsg;
- if (OutputBinary.makeUnique(true, &ErrMsg)) {
- errs() << "Error making unique filename: " << ErrMsg << "\n";
+
+ SmallString<128> OutputBinary;
+ error_code EC =
+ sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary);
+ if (EC) {
+ errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
@@ -712,8 +744,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
errs() << " " << GCCArgs[i];
errs() << "\n";
);
- if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
- sys::Path())) {
+ if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
*Error = ProcessFailure(GCCPath, &GCCArgs[0]);
return -1;
}
@@ -724,7 +755,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
// ProgramArgs is used.
std::string Exec;
- if (RemoteClientPath.isEmpty())
+ if (RemoteClientPath.empty())
ProgramArgs.push_back(OutputBinary.c_str());
else {
ProgramArgs.push_back(RemoteClientPath.c_str());
@@ -766,11 +797,11 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps);
- if (RemoteClientPath.isEmpty()) {
+ if (RemoteClientPath.empty()) {
DEBUG(errs() << "<run locally>");
- int ExitCode = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
- sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
- Timeout, MemoryLimit, Error);
+ int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0],
+ InputFile, OutputFile, OutputFile,
+ Timeout, MemoryLimit, Error);
// Treat a signal (usually SIGSEGV) or timeout as part of the program output
// so that crash-causing miscompilation is handled seamlessly.
if (ExitCode < -1) {
@@ -782,9 +813,9 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
return ExitCode;
} else {
outs() << "<run remotely>"; outs().flush();
- return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath),
- &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
- sys::Path(OutputFile), Timeout, MemoryLimit);
+ return RunProgramRemotelyWithTimeout(RemoteClientPath,
+ &ProgramArgs[0], InputFile, OutputFile,
+ OutputFile, Timeout, MemoryLimit);
}
}
@@ -792,13 +823,14 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
std::string &OutputFile,
const std::vector<std::string> &ArgsForGCC,
std::string &Error) {
- sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
- std::string ErrMsg;
- if (uniqueFilename.makeUnique(true, &ErrMsg)) {
- errs() << "Error making unique filename: " << ErrMsg << "\n";
+ SmallString<128> UniqueFilename;
+ error_code EC = sys::fs::createUniqueFile(
+ InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename);
+ if (EC) {
+ errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- OutputFile = uniqueFilename.str();
+ OutputFile = UniqueFilename.str();
std::vector<const char*> GCCArgs;
@@ -862,8 +894,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
errs() << " " << GCCArgs[i];
errs() << "\n";
);
- if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
- sys::Path())) {
+ if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
Error = ProcessFailure(GCCPath, &GCCArgs[0]);
return 1;
}
@@ -875,16 +906,16 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
GCC *GCC::create(std::string &Message,
const std::string &GCCBinary,
const std::vector<std::string> *Args) {
- sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary);
- if (GCCPath.isEmpty()) {
+ std::string GCCPath = sys::FindProgramByName(GCCBinary);
+ if (GCCPath.empty()) {
Message = "Cannot find `"+ GCCBinary +"' in PATH!\n";
return 0;
}
- sys::Path RemoteClientPath;
+ std::string RemoteClientPath;
if (!RemoteClient.empty())
- RemoteClientPath = sys::Program::FindProgramByName(RemoteClient);
+ RemoteClientPath = sys::FindProgramByName(RemoteClient);
- Message = "Found gcc: " + GCCPath.str() + "\n";
+ Message = "Found gcc: " + GCCPath + "\n";
return new GCC(GCCPath, RemoteClientPath, Args);
}
diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h
index 28c09f5..bc2be46 100644
--- a/tools/bugpoint/ToolRunner.h
+++ b/tools/bugpoint/ToolRunner.h
@@ -21,7 +21,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PathV1.h"
#include "llvm/Support/SystemUtils.h"
#include <exception>
#include <vector>
@@ -31,17 +30,16 @@ namespace llvm {
extern cl::opt<bool> SaveTemps;
extern Triple TargetTriple;
-class CBE;
class LLC;
//===---------------------------------------------------------------------===//
// GCC abstraction
//
class GCC {
- sys::Path GCCPath; // The path to the gcc executable.
- sys::Path RemoteClientPath; // The path to the rsh / ssh executable.
+ std::string GCCPath; // The path to the gcc executable.
+ std::string RemoteClientPath; // The path to the rsh / ssh executable.
std::vector<std::string> gccArgs; // GCC-specific arguments.
- GCC(const sys::Path &gccPath, const sys::Path &RemotePath,
+ GCC(StringRef gccPath, StringRef RemotePath,
const std::vector<std::string> *GCCArgs)
: GCCPath(gccPath), RemoteClientPath(RemotePath) {
if (GCCArgs) gccArgs = *GCCArgs;
@@ -89,10 +87,6 @@ public:
class AbstractInterpreter {
virtual void anchor();
public:
- static CBE *createCBE(const char *Argv0, std::string &Message,
- const std::string &GCCBinary,
- const std::vector<std::string> *Args = 0,
- const std::vector<std::string> *GCCArgs = 0);
static LLC *createLLC(const char *Argv0, std::string &Message,
const std::string &GCCBinary,
const std::vector<std::string> *Args = 0,
@@ -127,7 +121,7 @@ public:
/// fails, it sets Error, otherwise, this function returns the type of code
/// emitted.
virtual GCC::FileType OutputCode(const std::string &Bitcode,
- sys::Path &OutFile, std::string &Error,
+ std::string &OutFile, std::string &Error,
unsigned Timeout = 0,
unsigned MemoryLimit = 0) {
Error = "OutputCode not supported by this AbstractInterpreter!";
@@ -153,51 +147,6 @@ public:
};
//===---------------------------------------------------------------------===//
-// CBE Implementation of AbstractIntepreter interface
-//
-class CBE : public AbstractInterpreter {
- sys::Path LLCPath; // The path to the `llc' executable.
- std::vector<std::string> ToolArgs; // Extra args to pass to LLC.
- GCC *gcc;
-public:
- CBE(const sys::Path &llcPath, GCC *Gcc,
- const std::vector<std::string> *Args)
- : LLCPath(llcPath), gcc(Gcc) {
- ToolArgs.clear ();
- if (Args) ToolArgs = *Args;
- }
- ~CBE() { delete gcc; }
-
- /// compileProgram - Compile the specified program from bitcode to executable
- /// code. This does not produce any output, it is only used when debugging
- /// the code generator. Returns false if the code generator fails.
- virtual void compileProgram(const std::string &Bitcode, std::string *Error,
- unsigned Timeout = 0, unsigned MemoryLimit = 0);
-
- virtual int ExecuteProgram(const std::string &Bitcode,
- const std::vector<std::string> &Args,
- const std::string &InputFile,
- const std::string &OutputFile,
- std::string *Error,
- const std::vector<std::string> &GCCArgs =
- std::vector<std::string>(),
- const std::vector<std::string> &SharedLibs =
- std::vector<std::string>(),
- unsigned Timeout = 0,
- unsigned MemoryLimit = 0);
-
- /// OutputCode - Compile the specified program from bitcode to code
- /// understood by the GCC driver (either C or asm). If the code generator
- /// fails, it sets Error, otherwise, this function returns the type of code
- /// emitted.
- virtual GCC::FileType OutputCode(const std::string &Bitcode,
- sys::Path &OutFile, std::string &Error,
- unsigned Timeout = 0,
- unsigned MemoryLimit = 0);
-};
-
-
-//===---------------------------------------------------------------------===//
// LLC Implementation of AbstractIntepreter interface
//
class LLC : public AbstractInterpreter {
@@ -239,7 +188,7 @@ public:
/// fails, it sets Error, otherwise, this function returns the type of code
/// emitted.
virtual GCC::FileType OutputCode(const std::string &Bitcode,
- sys::Path &OutFile, std::string &Error,
+ std::string &OutFile, std::string &Error,
unsigned Timeout = 0,
unsigned MemoryLimit = 0);
};
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index 40f5fd6..7771709 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -17,6 +17,7 @@
#include "llvm-c/lto.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Errno.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
@@ -64,7 +65,7 @@ namespace {
lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
std::string output_name = "";
std::list<claimed_file> Modules;
- std::vector<sys::Path> Cleanup;
+ std::vector<std::string> Cleanup;
lto_code_gen_t code_gen = NULL;
}
@@ -251,9 +252,8 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
if (file->offset) {
offset = file->offset;
}
- if (error_code ec =
- MemoryBuffer::getOpenFile(file->fd, file->name, buffer, file->filesize,
- -1, offset, false)) {
+ if (error_code ec = MemoryBuffer::getOpenFileSlice(
+ file->fd, file->name, buffer, file->filesize, offset)) {
(*message)(LDPL_ERROR, ec.message().c_str());
return LDPS_ERR;
}
@@ -447,18 +447,18 @@ static ld_plugin_status all_symbols_read_hook(void) {
}
if (options::obj_path.empty())
- Cleanup.push_back(sys::Path(objPath));
+ Cleanup.push_back(objPath);
return LDPS_OK;
}
static ld_plugin_status cleanup_hook(void) {
- std::string ErrMsg;
-
- for (int i = 0, e = Cleanup.size(); i != e; ++i)
- if (Cleanup[i].eraseFromDisk(false, &ErrMsg))
+ for (int i = 0, e = Cleanup.size(); i != e; ++i) {
+ error_code EC = sys::fs::remove(Cleanup[i]);
+ if (EC)
(*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
- ErrMsg.c_str());
+ EC.message().c_str());
+ }
return LDPS_OK;
}
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 8a462c6..6aac8ff 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+
#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Assembly/PrintModulePass.h"
@@ -144,8 +145,9 @@ static tool_output_file *GetOutputStream(const char *TargetName,
// Open the file.
std::string error;
- unsigned OpenFlags = 0;
- if (Binary) OpenFlags |= raw_fd_ostream::F_Binary;
+ sys::fs::OpenFlags OpenFlags = sys::fs::F_None;
+ if (Binary)
+ OpenFlags |= sys::fs::F_Binary;
tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error,
OpenFlags);
if (!error.empty()) {
@@ -260,7 +262,6 @@ static int compileModule(char **argv, LLVMContext &Context) {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.NoFramePointerElim = DisableFPElim;
- Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
@@ -274,12 +275,10 @@ static int compileModule(char **argv, LLVMContext &Context) {
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.DisableTailCalls = DisableTailCalls;
Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.RealignStack = EnableRealignStack;
Options.TrapFuncName = TrapFuncName;
Options.PositionIndependentExecutable = EnablePIE;
Options.EnableSegmentedStacks = SegmentedStacks;
Options.UseInitArray = UseInitArray;
- Options.SSPBufferSize = SSPBufferSize;
OwningPtr<TargetMachine>
target(TheTarget->createTargetMachine(TheTriple.getTriple(),
diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt
index aaa6598..98f411d 100644
--- a/tools/lli/CMakeLists.txt
+++ b/tools/lli/CMakeLists.txt
@@ -1,5 +1,5 @@
-set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native)
+set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native instrumentation)
if( LLVM_USE_OPROFILE )
set(LLVM_LINK_COMPONENTS
diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt
index 5823792..c96a9e8 100644
--- a/tools/lli/LLVMBuild.txt
+++ b/tools/lli/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = lli
parent = Tools
-required_libraries = AsmParser BitReader IRReader Interpreter JIT MCJIT NativeCodeGen SelectionDAG Native
+required_libraries = AsmParser BitReader IRReader Instrumentation Interpreter JIT MCJIT NativeCodeGen SelectionDAG Native
diff --git a/tools/lli/Makefile b/tools/lli/Makefile
index a653058..7a40427 100644
--- a/tools/lli/Makefile
+++ b/tools/lli/Makefile
@@ -12,7 +12,7 @@ TOOLNAME := lli
include $(LEVEL)/Makefile.config
-LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native
+LINK_COMPONENTS := mcjit jit instrumentation interpreter nativecodegen bitreader asmparser irreader selectiondag native
# If Intel JIT Events support is confiured, link against the LLVM Intel JIT
# Events interface library
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 031f945..8d74b23 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
#ifdef __CYGWIN__
@@ -71,6 +72,10 @@ namespace {
"use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"),
cl::init(false));
+ cl::opt<bool> DebugIR(
+ "debug-ir", cl::desc("Generate debug information to allow debugging IR."),
+ cl::init(false));
+
// The MCJIT supports building for a target address space separate from
// the JIT compilation process. Use a forked process and a copying
// memory manager with IPC to execute using this functionality.
@@ -321,6 +326,17 @@ int main(int argc, char **argv, char * const *envp) {
}
}
+ if (DebugIR) {
+ if (!UseMCJIT) {
+ errs() << "warning: -debug-ir used without -use-mcjit. Only partial debug"
+ << " information will be emitted by the non-MC JIT engine. To see full"
+ << " source debug information, enable the flag '-use-mcjit'.\n";
+
+ }
+ ModulePass *DebugIRPass = createDebugIRPass();
+ DebugIRPass->runOnModule(*Mod);
+ }
+
EngineBuilder builder(Mod);
builder.setMArch(MArch);
builder.setMCPU(MCPU);
diff --git a/tools/llvm-ar/CMakeLists.txt b/tools/llvm-ar/CMakeLists.txt
index 70eb760..503999c 100644
--- a/tools/llvm-ar/CMakeLists.txt
+++ b/tools/llvm-ar/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS archive)
+set(LLVM_LINK_COMPONENTS support object bitreader)
add_llvm_tool(llvm-ar
llvm-ar.cpp
diff --git a/tools/llvm-ar/LLVMBuild.txt b/tools/llvm-ar/LLVMBuild.txt
index 1f61a32..236b465 100644
--- a/tools/llvm-ar/LLVMBuild.txt
+++ b/tools/llvm-ar/LLVMBuild.txt
@@ -19,4 +19,3 @@
type = Tool
name = llvm-ar
parent = Tools
-required_libraries = Archive
diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile
index fafb14b..15fb090 100644
--- a/tools/llvm-ar/Makefile
+++ b/tools/llvm-ar/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-ar
-LINK_COMPONENTS := archive
+LINK_COMPONENTS := bitreader support object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 86eb8e2..6026fa7 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -13,21 +13,56 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Bitcode/Archive.h"
#include "llvm/IR/Module.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdlib>
-#include <fstream>
#include <memory>
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
using namespace llvm;
+// The name this program was invoked as.
+static StringRef ToolName;
+
+static const char *TemporaryOutput;
+static int TmpArchiveFD = -1;
+
+// fail - Show the error message and exit.
+LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) {
+ outs() << ToolName << ": " << Error << ".\n";
+ if (TmpArchiveFD != -1)
+ close(TmpArchiveFD);
+ if (TemporaryOutput)
+ sys::fs::remove(TemporaryOutput);
+ exit(1);
+}
+
+static void failIfError(error_code EC, Twine Context = "") {
+ if (!EC)
+ return;
+
+ std::string ContextStr = Context.str();
+ if (ContextStr == "")
+ fail(EC.message());
+ fail(Context + ": " + EC.message());
+}
+
// Option for compatibility with AIX, not used but must allow it to be present.
static cl::opt<bool>
X32Option ("X32_64", cl::Hidden,
@@ -57,123 +92,72 @@ static cl::extrahelp MoreHelp(
"\nMODIFIERS (operation specific):\n"
" [a] - put file(s) after [relpos]\n"
" [b] - put file(s) before [relpos] (same as [i])\n"
- " [f] - truncate inserted file names\n"
" [i] - put file(s) before [relpos] (same as [b])\n"
- " [k] - always print bitcode files (default is to skip them)\n"
" [N] - use instance [count] of name\n"
" [o] - preserve original dates\n"
- " [P] - use full path names when matching\n"
- " [R] - recurse through directories when inserting\n"
" [s] - create an archive index (cf. ranlib)\n"
" [S] - do not build a symbol table\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"
- " [V] - be *really* verbose about actions taken\n"
);
// This enumeration delineates the kinds of operations on an archive
// that are permitted.
enum ArchiveOperation {
- NoOperation, ///< An operation hasn't been specified
Print, ///< Print the contents of the archive
Delete, ///< Delete the specified members
Move, ///< Move members to end or as given by {a,b,i} modifiers
QuickAppend, ///< Quickly append to end of archive
ReplaceOrInsert, ///< Replace or Insert members
DisplayTable, ///< Display the table of contents
- Extract ///< Extract files back to file system
+ Extract, ///< Extract files back to file system
+ CreateSymTab ///< Create a symbol table in an existing archive
};
// Modifiers to follow operation to vary behavior
-bool AddAfter = false; ///< 'a' modifier
-bool AddBefore = false; ///< 'b' modifier
-bool Create = false; ///< 'c' modifier
-bool TruncateNames = false; ///< 'f' modifier
-bool InsertBefore = false; ///< 'i' modifier
-bool DontSkipBitcode = false; ///< 'k' modifier
-bool UseCount = false; ///< 'N' modifier
-bool OriginalDates = false; ///< 'o' modifier
-bool FullPath = false; ///< 'P' modifier
-bool RecurseDirectories = false; ///< 'R' modifier
-bool SymTable = true; ///< 's' & 'S' modifiers
-bool OnlyUpdate = false; ///< 'u' modifier
-bool Verbose = false; ///< 'v' modifier
-bool ReallyVerbose = false; ///< 'V' modifier
+static bool AddAfter = false; ///< 'a' modifier
+static bool AddBefore = false; ///< 'b' modifier
+static bool Create = false; ///< 'c' modifier
+static bool OriginalDates = false; ///< 'o' modifier
+static bool OnlyUpdate = false; ///< 'u' modifier
+static bool Verbose = false; ///< 'v' modifier
+static bool Symtab = true; ///< 's' modifier
// Relative Positional Argument (for insert/move). This variable holds
// the name of the archive member to which the 'a', 'b' or 'i' modifier
// refers. Only one of 'a', 'b' or 'i' can be specified so we only need
// one variable.
-std::string RelPos;
-
-// Select which of multiple entries in the archive with the same name should be
-// used (specified with -N) for the delete and extract operations.
-int Count = 1;
+static std::string RelPos;
// This variable holds the name of the archive file as given on the
// command line.
-std::string ArchiveName;
+static std::string ArchiveName;
// This variable holds the list of member files to proecess, as given
// on the command line.
-std::vector<std::string> Members;
-
-// This variable holds the (possibly expanded) list of path objects that
-// correspond to files we will
-std::set<sys::Path> Paths;
-
-// The Archive object to which all the editing operations will be sent.
-Archive* TheArchive = 0;
-
-// The name this program was invoked as.
-static const char *program_name;
+static std::vector<std::string> Members;
// show_help - Show the error message, the help message and exit.
LLVM_ATTRIBUTE_NORETURN static void
show_help(const std::string &msg) {
- errs() << program_name << ": " << msg << "\n\n";
+ errs() << ToolName << ": " << msg << "\n\n";
cl::PrintHelpMessage();
- if (TheArchive)
- delete TheArchive;
- std::exit(1);
-}
-
-// fail - Show the error message and exit.
-LLVM_ATTRIBUTE_NORETURN static void
-fail(const std::string &msg) {
- errs() << program_name << ": " << msg << "\n\n";
- if (TheArchive)
- delete TheArchive;
std::exit(1);
}
// getRelPos - Extract the member filename from the command line for
// the [relpos] argument associated with a, b, and i modifiers
-void getRelPos() {
+static void getRelPos() {
if(RestOfArgs.size() == 0)
show_help("Expected [relpos] for a, b, or i modifier");
RelPos = RestOfArgs[0];
RestOfArgs.erase(RestOfArgs.begin());
}
-// getCount - Extract the [count] argument associated with the N modifier
-// from the command line and check its value.
-void getCount() {
- if(RestOfArgs.size() == 0)
- show_help("Expected [count] value with N modifier");
-
- Count = atoi(RestOfArgs[0].c_str());
- RestOfArgs.erase(RestOfArgs.begin());
-
- // Non-positive counts are not allowed
- if (Count < 1)
- show_help("Invalid [count] value (not a positive integer)");
-}
-
// getArchive - Get the archive file name from the command line
-void getArchive() {
+static void getArchive() {
if(RestOfArgs.size() == 0)
show_help("An archive name must be specified");
ArchiveName = RestOfArgs[0];
@@ -182,7 +166,7 @@ void getArchive() {
// getMembers - Copy over remaining items in RestOfArgs to our Members vector
// This is just for clarity.
-void getMembers() {
+static void getMembers() {
if(RestOfArgs.size() > 0)
Members = std::vector<std::string>(RestOfArgs);
}
@@ -190,7 +174,7 @@ void getMembers() {
// parseCommandLine - Parse the command line options as presented and return the
// operation specified. Process all modifiers and check to make sure that
// constraints on modifier/operation pairs have not been violated.
-ArchiveOperation parseCommandLine() {
+static ArchiveOperation parseCommandLine() {
// Keep track of number of operations. We can only specify one
// per execution.
@@ -201,7 +185,9 @@ ArchiveOperation parseCommandLine() {
unsigned NumPositional = 0;
// Keep track of which operation was requested
- ArchiveOperation Operation = NoOperation;
+ ArchiveOperation Operation;
+
+ bool MaybeJustCreateSymTab = false;
for(unsigned i=0; i<Options.size(); ++i) {
switch(Options[i]) {
@@ -213,17 +199,17 @@ ArchiveOperation parseCommandLine() {
case 't': ++NumOperations; Operation = DisplayTable; break;
case 'x': ++NumOperations; Operation = Extract; break;
case 'c': Create = true; break;
- case 'f': TruncateNames = true; break;
- case 'k': DontSkipBitcode = true; break;
case 'l': /* accepted but unused */ break;
case 'o': OriginalDates = true; break;
- case 'P': FullPath = true; break;
- case 'R': RecurseDirectories = true; break;
- case 's': SymTable = true; break;
- case 'S': SymTable = false; break;
+ case 's':
+ Symtab = true;
+ MaybeJustCreateSymTab = true;
+ break;
+ case 'S':
+ Symtab = false;
+ break;
case 'u': OnlyUpdate = true; break;
case 'v': Verbose = true; break;
- case 'V': Verbose = ReallyVerbose = true; break;
case 'a':
getRelPos();
AddAfter = true;
@@ -236,13 +222,9 @@ ArchiveOperation parseCommandLine() {
break;
case 'i':
getRelPos();
- InsertBefore = true;
+ AddBefore = true;
NumPositional++;
break;
- case 'N':
- getCount();
- UseCount = true;
- break;
default:
cl::PrintHelpMessage();
}
@@ -255,6 +237,13 @@ ArchiveOperation parseCommandLine() {
// Everything on the command line at this point is a member.
getMembers();
+ if (NumOperations == 0 && MaybeJustCreateSymTab) {
+ NumOperations = 1;
+ Operation = CreateSymTab;
+ if (!Members.empty())
+ show_help("The s operation takes only an archive as argument");
+ }
+
// Perform various checks on the operation/modifier specification
// to make sure we are dealing with a legal request.
if (NumOperations == 0)
@@ -263,140 +252,33 @@ ArchiveOperation parseCommandLine() {
show_help("Only one operation may be specified");
if (NumPositional > 1)
show_help("You may only specify one of a, b, and i modifiers");
- if (AddAfter || AddBefore || InsertBefore) {
+ if (AddAfter || AddBefore) {
if (Operation != Move && Operation != ReplaceOrInsert)
show_help("The 'a', 'b' and 'i' modifiers can only be specified with "
"the 'm' or 'r' operations");
}
- if (RecurseDirectories && Operation != ReplaceOrInsert)
- show_help("The 'R' modifiers is only applicabe to the 'r' operation");
if (OriginalDates && Operation != Extract)
show_help("The 'o' modifier is only applicable to the 'x' operation");
- if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert)
- show_help("The 'f' modifier is only applicable to the 'q' and 'r' "
- "operations");
if (OnlyUpdate && Operation != ReplaceOrInsert)
show_help("The 'u' modifier is only applicable to the 'r' operation");
- if (Count > 1 && Members.size() > 1)
- show_help("Only one member name may be specified with the 'N' modifier");
// Return the parsed operation to the caller
return Operation;
}
-// recurseDirectories - Implements the "R" modifier. This function scans through
-// the Paths vector (built by buildPaths, below) and replaces any directories it
-// finds with all the files in that directory (recursively). It uses the
-// sys::Path::getDirectoryContent method to perform the actual directory scans.
-bool
-recurseDirectories(const sys::Path& path,
- std::set<sys::Path>& result, std::string* ErrMsg) {
- result.clear();
- if (RecurseDirectories) {
- std::set<sys::Path> content;
- if (path.getDirectoryContents(content, ErrMsg))
- return true;
-
- for (std::set<sys::Path>::iterator I = content.begin(), E = content.end();
- I != E; ++I) {
- // Make sure it exists and is a directory
- sys::PathWithStatus PwS(*I);
- const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg);
- if (!Status)
- return true;
- if (Status->isDir) {
- std::set<sys::Path> moreResults;
- if (recurseDirectories(*I, moreResults, ErrMsg))
- return true;
- result.insert(moreResults.begin(), moreResults.end());
- } else {
- result.insert(*I);
- }
- }
- }
- return false;
-}
+// Implements the 'p' operation. This function traverses the archive
+// looking for members that match the path list.
+static void doPrint(StringRef Name, object::Archive::child_iterator I) {
+ if (Verbose)
+ outs() << "Printing " << Name << "\n";
-// buildPaths - Convert the strings in the Members vector to sys::Path objects
-// and make sure they are valid and exist exist. This check is only needed for
-// the operations that add/replace files to the archive ('q' and 'r')
-bool buildPaths(bool checkExistence, std::string* ErrMsg) {
- for (unsigned i = 0; i < Members.size(); i++) {
- sys::Path aPath;
- if (!aPath.set(Members[i]))
- fail(std::string("File member name invalid: ") + Members[i]);
- if (checkExistence) {
- bool Exists;
- if (sys::fs::exists(aPath.str(), Exists) || !Exists)
- fail(std::string("File does not exist: ") + Members[i]);
- std::string Err;
- sys::PathWithStatus PwS(aPath);
- const sys::FileStatus *si = PwS.getFileStatus(false, &Err);
- if (!si)
- fail(Err);
- if (si->isDir) {
- std::set<sys::Path> dirpaths;
- if (recurseDirectories(aPath, dirpaths, ErrMsg))
- return true;
- Paths.insert(dirpaths.begin(),dirpaths.end());
- } else {
- Paths.insert(aPath);
- }
- } else {
- Paths.insert(aPath);
- }
- }
- return false;
-}
-
-// printSymbolTable - print out the archive's symbol table.
-void printSymbolTable() {
- outs() << "\nArchive Symbol Table:\n";
- const Archive::SymTabType& symtab = TheArchive->getSymbolTable();
- for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end();
- I != E; ++I ) {
- unsigned offset = TheArchive->getFirstFileOffset() + I->second;
- outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n";
- }
-}
-
-// doPrint - Implements the 'p' operation. This function traverses the archive
-// looking for members that match the path list. It is careful to uncompress
-// things that should be and to skip bitcode files unless the 'k' modifier was
-// given.
-bool doPrint(std::string* ErrMsg) {
- if (buildPaths(false, ErrMsg))
- return true;
- unsigned countDown = Count;
- for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
- I != E; ++I ) {
- if (Paths.empty() ||
- (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
- if (countDown == 1) {
- const char* data = reinterpret_cast<const char*>(I->getData());
-
- // Skip things that don't make sense to print
- if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() ||
- I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode()))
- continue;
-
- if (Verbose)
- outs() << "Printing " << I->getPath().str() << "\n";
-
- unsigned len = I->getSize();
- outs().write(data, len);
- } else {
- countDown--;
- }
- }
- }
- return false;
+ StringRef Data = I->getBuffer();
+ outs().write(Data.data(), Data.size());
}
// putMode - utility function for printing out the file mode when the 't'
// operation is in verbose mode.
-void
-printMode(unsigned mode) {
+static void printMode(unsigned mode) {
if (mode & 004)
outs() << "r";
else
@@ -411,303 +293,576 @@ printMode(unsigned mode) {
outs() << "-";
}
-// doDisplayTable - Implement the 't' operation. This function prints out just
+// Implement the 't' operation. This function prints out just
// the file names of each of the members. However, if verbose mode is requested
// ('v' modifier) then the file type, permission mode, user, group, size, and
// modification time are also printed.
-bool
-doDisplayTable(std::string* ErrMsg) {
- if (buildPaths(false, ErrMsg))
- return true;
- for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
- I != E; ++I ) {
- if (Paths.empty() ||
- (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
- if (Verbose) {
- // FIXME: Output should be this format:
- // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile
- if (I->isBitcode())
- outs() << "b";
- else
- outs() << " ";
- unsigned mode = I->getMode();
- printMode((mode >> 6) & 007);
- printMode((mode >> 3) & 007);
- printMode(mode & 007);
- outs() << " " << format("%4u", I->getUser());
- outs() << "/" << format("%4u", I->getGroup());
- outs() << " " << format("%8u", I->getSize());
- outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str());
- outs() << " " << I->getPath().str() << "\n";
- } else {
- outs() << I->getPath().str() << "\n";
- }
- }
+static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) {
+ if (Verbose) {
+ sys::fs::perms Mode = I->getAccessMode();
+ printMode((Mode >> 6) & 007);
+ printMode((Mode >> 3) & 007);
+ printMode(Mode & 007);
+ outs() << ' ' << I->getUID();
+ outs() << '/' << I->getGID();
+ outs() << ' ' << format("%6llu", I->getSize());
+ outs() << ' ' << I->getLastModified().str();
+ outs() << ' ';
}
- if (ReallyVerbose)
- printSymbolTable();
- return false;
+ outs() << Name << "\n";
}
-// doExtract - Implement the 'x' operation. This function extracts files back to
-// the file system.
-bool
-doExtract(std::string* ErrMsg) {
- if (buildPaths(false, ErrMsg))
- return true;
- for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
- I != E; ++I ) {
- if (Paths.empty() ||
- (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
-
- // Make sure the intervening directories are created
- if (I->hasPath()) {
- sys::Path dirs(I->getPath());
- dirs.eraseComponent();
- if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg))
- return true;
- }
+// Implement the 'x' operation. This function extracts files back to the file
+// system.
+static void doExtract(StringRef Name, object::Archive::child_iterator I) {
+ // Retain the original mode.
+ sys::fs::perms Mode = I->getAccessMode();
+ SmallString<128> Storage = Name;
- // Open up a file stream for writing
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream file(I->getPath().c_str(), io_mode);
+ int FD;
+ failIfError(
+ sys::fs::openFileForWrite(Storage.c_str(), FD, sys::fs::F_Binary, Mode),
+ Storage.c_str());
- // Get the data and its length
- const char* data = reinterpret_cast<const char*>(I->getData());
- unsigned len = I->getSize();
+ {
+ raw_fd_ostream file(FD, false);
- // Write the data.
- file.write(data,len);
- file.close();
+ // Get the data and its length
+ StringRef Data = I->getBuffer();
- // If we're supposed to retain the original modification times, etc. do so
- // now.
- if (OriginalDates)
- I->getPath().setStatusInfoOnDisk(I->getFileStatus());
- }
+ // Write the data.
+ file.write(Data.data(), Data.size());
}
- return false;
+
+ // If we're supposed to retain the original modification times, etc. do so
+ // now.
+ if (OriginalDates)
+ failIfError(
+ sys::fs::setLastModificationAndAccessTime(FD, I->getLastModified()));
+
+ if (close(FD))
+ fail("Could not close the file");
}
-// doDelete - Implement the delete operation. This function deletes zero or more
-// members from the archive. Note that if the count is specified, there should
-// be no more than one path in the Paths list or else this algorithm breaks.
-// That check is enforced in parseCommandLine (above).
-bool
-doDelete(std::string* ErrMsg) {
- if (buildPaths(false, ErrMsg))
- return true;
- if (Paths.empty())
+static bool shouldCreateArchive(ArchiveOperation Op) {
+ switch (Op) {
+ case Print:
+ case Delete:
+ case Move:
+ case DisplayTable:
+ case Extract:
+ case CreateSymTab:
return false;
- unsigned countDown = Count;
- for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
- I != E; ) {
- if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) {
- if (countDown == 1) {
- Archive::iterator J = I;
- ++I;
- TheArchive->erase(J);
- } else
- countDown--;
- } else {
- ++I;
+
+ case QuickAppend:
+ case ReplaceOrInsert:
+ return true;
+ }
+
+ llvm_unreachable("Missing entry in covered switch.");
+}
+
+static void performReadOperation(ArchiveOperation Operation,
+ object::Archive *OldArchive) {
+ for (object::Archive::child_iterator I = OldArchive->begin_children(),
+ E = OldArchive->end_children();
+ I != E; ++I) {
+ StringRef Name;
+ failIfError(I->getName(Name));
+
+ if (!Members.empty() &&
+ std::find(Members.begin(), Members.end(), Name) == Members.end())
+ continue;
+
+ switch (Operation) {
+ default:
+ llvm_unreachable("Not a read operation");
+ case Print:
+ doPrint(Name, I);
+ break;
+ case DisplayTable:
+ doDisplayTable(Name, I);
+ break;
+ case Extract:
+ doExtract(Name, I);
+ break;
}
}
+}
- // We're done editting, reconstruct the archive.
- if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg))
- return true;
- if (ReallyVerbose)
- printSymbolTable();
- return false;
+namespace {
+class NewArchiveIterator {
+ bool IsNewMember;
+ StringRef Name;
+ object::Archive::child_iterator OldI;
+ std::string NewFilename;
+
+public:
+ NewArchiveIterator(object::Archive::child_iterator I, StringRef Name);
+ NewArchiveIterator(std::string *I, StringRef Name);
+ NewArchiveIterator();
+ bool isNewMember() const;
+ object::Archive::child_iterator getOld() const;
+ const char *getNew() const;
+ StringRef getName() const;
+};
}
-// doMore - Implement the move operation. This function re-arranges just the
-// order of the archive members so that when the archive is written the move
-// of the members is accomplished. Note the use of the RelPos variable to
-// determine where the items should be moved to.
-bool
-doMove(std::string* ErrMsg) {
- if (buildPaths(false, ErrMsg))
- return true;
+NewArchiveIterator::NewArchiveIterator() {}
+
+NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
+ StringRef Name)
+ : IsNewMember(false), Name(Name), OldI(I) {}
+
+NewArchiveIterator::NewArchiveIterator(std::string *NewFilename, StringRef Name)
+ : IsNewMember(true), Name(Name), NewFilename(*NewFilename) {}
+
+StringRef NewArchiveIterator::getName() const { return Name; }
+
+bool NewArchiveIterator::isNewMember() const { return IsNewMember; }
+
+object::Archive::child_iterator NewArchiveIterator::getOld() const {
+ assert(!IsNewMember);
+ return OldI;
+}
+
+const char *NewArchiveIterator::getNew() const {
+ assert(IsNewMember);
+ return NewFilename.c_str();
+}
- // By default and convention the place to move members to is the end of the
- // archive.
- Archive::iterator moveto_spot = TheArchive->end();
-
- // However, if the relative positioning modifiers were used, we need to scan
- // the archive to find the member in question. If we don't find it, its no
- // crime, we just move to the end.
- if (AddBefore || InsertBefore || AddAfter) {
- for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end();
- I != E; ++I ) {
- if (RelPos == I->getPath().str()) {
- if (AddAfter) {
- moveto_spot = I;
- moveto_spot++;
- } else {
- moveto_spot = I;
- }
+template <typename T>
+void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name,
+ int Pos = -1) {
+ NewArchiveIterator NI(I, Name);
+ if (Pos == -1)
+ Members.push_back(NI);
+ else
+ Members[Pos] = NI;
+}
+
+namespace {
+class HasName {
+ StringRef Name;
+
+public:
+ HasName(StringRef Name) : Name(Name) {}
+ bool operator()(StringRef Path) { return Name == sys::path::filename(Path); }
+};
+}
+
+enum InsertAction {
+ IA_AddOldMember,
+ IA_AddNewMeber,
+ IA_Delete,
+ IA_MoveOldMember,
+ IA_MoveNewMember
+};
+
+static InsertAction
+computeInsertAction(ArchiveOperation Operation,
+ object::Archive::child_iterator I, StringRef Name,
+ std::vector<std::string>::iterator &Pos) {
+ if (Operation == QuickAppend || Members.empty())
+ return IA_AddOldMember;
+
+ std::vector<std::string>::iterator MI =
+ std::find_if(Members.begin(), Members.end(), HasName(Name));
+
+ if (MI == Members.end())
+ return IA_AddOldMember;
+
+ Pos = MI;
+
+ if (Operation == Delete)
+ return IA_Delete;
+
+ if (Operation == Move)
+ return IA_MoveOldMember;
+
+ if (Operation == ReplaceOrInsert) {
+ StringRef PosName = sys::path::filename(RelPos);
+ if (!OnlyUpdate) {
+ if (PosName.empty())
+ return IA_AddNewMeber;
+ return IA_MoveNewMember;
+ }
+
+ // We could try to optimize this to a fstat, but it is not a common
+ // operation.
+ sys::fs::file_status Status;
+ failIfError(sys::fs::status(*MI, Status));
+ if (Status.getLastModificationTime() < I->getLastModified()) {
+ if (PosName.empty())
+ return IA_AddOldMember;
+ return IA_MoveOldMember;
+ }
+
+ if (PosName.empty())
+ return IA_AddNewMeber;
+ return IA_MoveNewMember;
+ }
+ llvm_unreachable("No such operation");
+}
+
+// We have to walk this twice and computing it is not trivial, so creating an
+// explicit std::vector is actually fairly efficient.
+static std::vector<NewArchiveIterator>
+computeNewArchiveMembers(ArchiveOperation Operation,
+ object::Archive *OldArchive) {
+ std::vector<NewArchiveIterator> Ret;
+ std::vector<NewArchiveIterator> Moved;
+ int InsertPos = -1;
+ StringRef PosName = sys::path::filename(RelPos);
+ if (OldArchive) {
+ for (object::Archive::child_iterator I = OldArchive->begin_children(),
+ E = OldArchive->end_children();
+ I != E; ++I) {
+ int Pos = Ret.size();
+ StringRef Name;
+ failIfError(I->getName(Name));
+ if (Name == PosName) {
+ assert(AddAfter || AddBefore);
+ if (AddBefore)
+ InsertPos = Pos;
+ else
+ InsertPos = Pos + 1;
+ }
+
+ std::vector<std::string>::iterator MemberI = Members.end();
+ InsertAction Action = computeInsertAction(Operation, I, Name, MemberI);
+ switch (Action) {
+ case IA_AddOldMember:
+ addMember(Ret, I, Name);
+ break;
+ case IA_AddNewMeber:
+ addMember(Ret, &*MemberI, Name);
+ break;
+ case IA_Delete:
+ break;
+ case IA_MoveOldMember:
+ addMember(Moved, I, Name);
+ break;
+ case IA_MoveNewMember:
+ addMember(Moved, &*MemberI, Name);
break;
}
+ if (MemberI != Members.end())
+ Members.erase(MemberI);
}
}
- // Keep a list of the paths remaining to be moved
- std::set<sys::Path> remaining(Paths);
-
- // Scan the archive again, this time looking for the members to move to the
- // moveto_spot.
- for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end();
- I != E && !remaining.empty(); ++I ) {
- std::set<sys::Path>::iterator found =
- std::find(remaining.begin(),remaining.end(),I->getPath());
- if (found != remaining.end()) {
- if (I != moveto_spot)
- TheArchive->splice(moveto_spot,*TheArchive,I);
- remaining.erase(found);
- }
+ if (Operation == Delete)
+ return Ret;
+
+ if (!RelPos.empty() && InsertPos == -1)
+ fail("Insertion point not found");
+
+ if (RelPos.empty())
+ InsertPos = Ret.size();
+
+ assert(unsigned(InsertPos) <= Ret.size());
+ Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end());
+
+ Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator());
+ int Pos = InsertPos;
+ for (std::vector<std::string>::iterator I = Members.begin(),
+ E = Members.end();
+ I != E; ++I, ++Pos) {
+ StringRef Name = sys::path::filename(*I);
+ addMember(Ret, &*I, Name, Pos);
}
- // We're done editting, reconstruct the archive.
- if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg))
- return true;
- if (ReallyVerbose)
- printSymbolTable();
- return false;
+ return Ret;
}
-// doQuickAppend - Implements the 'q' operation. This function just
-// indiscriminantly adds the members to the archive and rebuilds it.
-bool
-doQuickAppend(std::string* ErrMsg) {
- // Get the list of paths to append.
- if (buildPaths(true, ErrMsg))
- return true;
- if (Paths.empty())
- return false;
+template <typename T>
+static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
+ uint64_t OldPos = OS.tell();
+ OS << Data;
+ unsigned SizeSoFar = OS.tell() - OldPos;
+ assert(Size >= SizeSoFar && "Data doesn't fit in Size");
+ unsigned Remaining = Size - SizeSoFar;
+ for (unsigned I = 0; I < Remaining; ++I)
+ OS << ' ';
+}
- // Append them quickly.
- for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end();
- PI != PE; ++PI) {
- if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg))
- return true;
+static void print32BE(raw_fd_ostream &Out, unsigned Val) {
+ for (int I = 3; I >= 0; --I) {
+ char V = (Val >> (8 * I)) & 0xff;
+ Out << V;
}
+}
- // We're done editting, reconstruct the archive.
- if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg))
- return true;
- if (ReallyVerbose)
- printSymbolTable();
- return false;
+static void printRestOfMemberHeader(raw_fd_ostream &Out,
+ const sys::TimeValue &ModTime, unsigned UID,
+ unsigned GID, unsigned Perms,
+ unsigned Size) {
+ printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
+ printWithSpacePadding(Out, UID, 6);
+ printWithSpacePadding(Out, GID, 6);
+ printWithSpacePadding(Out, format("%o", Perms), 8);
+ printWithSpacePadding(Out, Size, 10);
+ Out << "`\n";
}
-// doReplaceOrInsert - Implements the 'r' operation. This function will replace
-// any existing files or insert new ones into the archive.
-bool
-doReplaceOrInsert(std::string* ErrMsg) {
+static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
+ const sys::TimeValue &ModTime, unsigned UID,
+ unsigned GID, unsigned Perms, unsigned Size) {
+ printWithSpacePadding(Out, Twine(Name) + "/", 16);
+ printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
+}
- // Build the list of files to be added/replaced.
- if (buildPaths(true, ErrMsg))
- return true;
- if (Paths.empty())
- return false;
+static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset,
+ const sys::TimeValue &ModTime, unsigned UID,
+ unsigned GID, unsigned Perms, unsigned Size) {
+ Out << '/';
+ printWithSpacePadding(Out, NameOffset, 15);
+ printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
+}
- // Keep track of the paths that remain to be inserted.
- std::set<sys::Path> remaining(Paths);
-
- // Default the insertion spot to the end of the archive
- Archive::iterator insert_spot = TheArchive->end();
-
- // Iterate over the archive contents
- for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
- I != E && !remaining.empty(); ++I ) {
-
- // Determine if this archive member matches one of the paths we're trying
- // to replace.
-
- std::set<sys::Path>::iterator found = remaining.end();
- for (std::set<sys::Path>::iterator RI = remaining.begin(),
- RE = remaining.end(); RI != RE; ++RI ) {
- std::string compare(RI->str());
- if (TruncateNames && compare.length() > 15) {
- const char* nm = compare.c_str();
- unsigned len = compare.length();
- size_t slashpos = compare.rfind('/');
- if (slashpos != std::string::npos) {
- nm += slashpos + 1;
- len -= slashpos +1;
- }
- if (len > 15)
- len = 15;
- compare.assign(nm,len);
- }
- if (compare == I->getPath().str()) {
- found = RI;
- break;
- }
+static void writeStringTable(raw_fd_ostream &Out,
+ ArrayRef<NewArchiveIterator> Members,
+ std::vector<unsigned> &StringMapIndexes) {
+ unsigned StartOffset = 0;
+ for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
+ E = Members.end();
+ I != E; ++I) {
+ StringRef Name = I->getName();
+ if (Name.size() < 16)
+ continue;
+ if (StartOffset == 0) {
+ printWithSpacePadding(Out, "//", 58);
+ Out << "`\n";
+ StartOffset = Out.tell();
}
+ StringMapIndexes.push_back(Out.tell() - StartOffset);
+ Out << Name << "/\n";
+ }
+ if (StartOffset == 0)
+ return;
+ if (Out.tell() % 2)
+ Out << '\n';
+ int Pos = Out.tell();
+ Out.seek(StartOffset - 12);
+ printWithSpacePadding(Out, Pos - StartOffset, 10);
+ Out.seek(Pos);
+}
- if (found != remaining.end()) {
- std::string Err;
- sys::PathWithStatus PwS(*found);
- const sys::FileStatus *si = PwS.getFileStatus(false, &Err);
- if (!si)
- return true;
- if (!si->isDir) {
- if (OnlyUpdate) {
- // Replace the item only if it is newer.
- if (si->modTime > I->getModTime())
- if (I->replaceWith(*found, ErrMsg))
- return true;
- } else {
- // Replace the item regardless of time stamp
- if (I->replaceWith(*found, ErrMsg))
- return true;
- }
+static void writeSymbolTable(
+ raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
+ std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) {
+ unsigned StartOffset = 0;
+ unsigned MemberNum = 0;
+ std::vector<StringRef> SymNames;
+ std::vector<object::ObjectFile *> DeleteIt;
+ for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
+ E = Members.end();
+ I != E; ++I, ++MemberNum) {
+ object::ObjectFile *Obj;
+ if (I->isNewMember()) {
+ const char *Filename = I->getNew();
+ Obj = object::ObjectFile::createObjectFile(Filename);
+ } else {
+ object::Archive::child_iterator OldMember = I->getOld();
+ OwningPtr<object::Binary> Binary;
+ error_code EC = OldMember->getAsBinary(Binary);
+ if (EC) { // FIXME: check only for "not an object file" errors.
+ Obj = NULL;
} else {
- // We purposefully ignore directories.
+ Obj = dyn_cast<object::ObjectFile>(Binary.get());
+ if (Obj)
+ Binary.take();
}
-
- // Remove it from our "to do" list
- remaining.erase(found);
+ }
+ if (!Obj)
+ continue;
+ DeleteIt.push_back(Obj);
+ if (!StartOffset) {
+ printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
+ StartOffset = Out.tell();
+ print32BE(Out, 0);
}
- // Determine if this is the place where we should insert
- if ((AddBefore || InsertBefore) && RelPos == I->getPath().str())
- insert_spot = I;
- else if (AddAfter && RelPos == I->getPath().str()) {
- insert_spot = I;
- insert_spot++;
+ error_code Err;
+ for (object::symbol_iterator I = Obj->begin_symbols(),
+ E = Obj->end_symbols();
+ I != E; I.increment(Err), failIfError(Err)) {
+ uint32_t Symflags;
+ failIfError(I->getFlags(Symflags));
+ if (Symflags & object::SymbolRef::SF_FormatSpecific)
+ continue;
+ if (!(Symflags & object::SymbolRef::SF_Global))
+ continue;
+ if (Symflags & object::SymbolRef::SF_Undefined)
+ continue;
+ StringRef Name;
+ failIfError(I->getName(Name));
+ SymNames.push_back(Name);
+ MemberOffsetRefs.push_back(std::make_pair(Out.tell(), MemberNum));
+ print32BE(Out, 0);
}
}
+ for (std::vector<StringRef>::iterator I = SymNames.begin(),
+ E = SymNames.end();
+ I != E; ++I) {
+ Out << *I;
+ Out << '\0';
+ }
+
+ for (std::vector<object::ObjectFile *>::iterator I = DeleteIt.begin(),
+ E = DeleteIt.end();
+ I != E; ++I) {
+ object::ObjectFile *O = *I;
+ delete O;
+ }
+
+ if (StartOffset == 0)
+ return;
+
+ if (Out.tell() % 2)
+ Out << '\0';
+
+ unsigned Pos = Out.tell();
+ Out.seek(StartOffset - 12);
+ printWithSpacePadding(Out, Pos - StartOffset, 10);
+ Out.seek(StartOffset);
+ print32BE(Out, SymNames.size());
+ Out.seek(Pos);
+}
+
+static void performWriteOperation(ArchiveOperation Operation,
+ object::Archive *OldArchive) {
+ SmallString<128> TmpArchive;
+ failIfError(sys::fs::createUniqueFile(ArchiveName + ".temp-archive-%%%%%%%.a",
+ TmpArchiveFD, TmpArchive));
+
+ TemporaryOutput = TmpArchive.c_str();
+ tool_output_file Output(TemporaryOutput, TmpArchiveFD);
+ raw_fd_ostream &Out = Output.os();
+ Out << "!<arch>\n";
+
+ std::vector<NewArchiveIterator> NewMembers =
+ computeNewArchiveMembers(Operation, OldArchive);
+
+ std::vector<std::pair<unsigned, unsigned> > MemberOffsetRefs;
+
+ if (Symtab) {
+ writeSymbolTable(Out, NewMembers, MemberOffsetRefs);
+ }
+
+ std::vector<unsigned> StringMapIndexes;
+ writeStringTable(Out, NewMembers, StringMapIndexes);
+
+ std::vector<std::pair<unsigned, unsigned> >::iterator MemberRefsI =
+ MemberOffsetRefs.begin();
- // If we didn't replace all the members, some will remain and need to be
- // inserted at the previously computed insert-spot.
- if (!remaining.empty()) {
- for (std::set<sys::Path>::iterator PI = remaining.begin(),
- PE = remaining.end(); PI != PE; ++PI) {
- if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg))
- return true;
+ unsigned MemberNum = 0;
+ unsigned LongNameMemberNum = 0;
+ for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(),
+ E = NewMembers.end();
+ I != E; ++I, ++MemberNum) {
+
+ unsigned Pos = Out.tell();
+ while (MemberRefsI != MemberOffsetRefs.end() &&
+ MemberRefsI->second == MemberNum) {
+ Out.seek(MemberRefsI->first);
+ print32BE(Out, Pos);
+ ++MemberRefsI;
+ }
+ Out.seek(Pos);
+
+ if (I->isNewMember()) {
+ const char *FileName = I->getNew();
+
+ int FD;
+ failIfError(sys::fs::openFileForRead(FileName, FD), FileName);
+
+ sys::fs::file_status Status;
+ failIfError(sys::fs::status(FD, Status), FileName);
+
+ OwningPtr<MemoryBuffer> File;
+ failIfError(MemoryBuffer::getOpenFile(FD, FileName, File,
+ Status.getSize(), false),
+ FileName);
+
+ StringRef Name = sys::path::filename(FileName);
+ if (Name.size() < 16)
+ printMemberHeader(Out, Name, Status.getLastModificationTime(),
+ Status.getUser(), Status.getGroup(),
+ Status.permissions(), Status.getSize());
+ else
+ printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
+ Status.getLastModificationTime(), Status.getUser(),
+ Status.getGroup(), Status.permissions(),
+ Status.getSize());
+ Out << File->getBuffer();
+ } else {
+ object::Archive::child_iterator OldMember = I->getOld();
+ StringRef Name = I->getName();
+
+ if (Name.size() < 16)
+ printMemberHeader(Out, Name, OldMember->getLastModified(),
+ OldMember->getUID(), OldMember->getGID(),
+ OldMember->getAccessMode(), OldMember->getSize());
+ else
+ printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
+ OldMember->getLastModified(), OldMember->getUID(),
+ OldMember->getGID(), OldMember->getAccessMode(),
+ OldMember->getSize());
+ Out << OldMember->getBuffer();
}
+
+ if (Out.tell() % 2)
+ Out << '\n';
}
+ Output.keep();
+ Out.close();
+ sys::fs::rename(TemporaryOutput, ArchiveName);
+ TemporaryOutput = NULL;
+}
- // We're done editting, reconstruct the archive.
- if (TheArchive->writeToDisk(SymTable,TruncateNames,ErrMsg))
- return true;
- if (ReallyVerbose)
- printSymbolTable();
- return false;
+static void createSymbolTable(object::Archive *OldArchive) {
+ // When an archive is created or modified, if the s option is given, the
+ // resulting archive will have a current symbol table. If the S option
+ // is given, it will have no symbol table.
+ // In summary, we only need to update the symbol table if we have none.
+ // This is actually very common because of broken build systems that think
+ // they have to run ranlib.
+ if (OldArchive->hasSymbolTable())
+ return;
+
+ performWriteOperation(CreateSymTab, OldArchive);
+}
+
+static void performOperation(ArchiveOperation Operation,
+ object::Archive *OldArchive) {
+ switch (Operation) {
+ case Print:
+ case DisplayTable:
+ case Extract:
+ performReadOperation(Operation, OldArchive);
+ return;
+
+ case Delete:
+ case Move:
+ case QuickAppend:
+ case ReplaceOrInsert:
+ performWriteOperation(Operation, OldArchive);
+ return;
+ case CreateSymTab:
+ createSymbolTable(OldArchive);
+ return;
+ }
+ llvm_unreachable("Unknown operation.");
}
// main - main program for llvm-ar .. see comments in the code
int main(int argc, char **argv) {
- program_name = argv[0];
+ ToolName = argv[0];
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Have the command line options parsed and handle things
@@ -717,63 +872,42 @@ int main(int argc, char **argv) {
" This program archives bitcode files into single libraries\n"
);
- int exitCode = 0;
-
// Do our own parsing of the command line because the CommandLine utility
// can't handle the grouped positional parameters without a dash.
ArchiveOperation Operation = parseCommandLine();
- // Check the path name of the archive
- sys::Path ArchivePath;
- if (!ArchivePath.set(ArchiveName)) {
- errs() << argv[0] << ": Archive name invalid: " << ArchiveName << "\n";
+ // Create or open the archive object.
+ OwningPtr<MemoryBuffer> Buf;
+ error_code EC = MemoryBuffer::getFile(ArchiveName, Buf, -1, false);
+ if (EC && EC != llvm::errc::no_such_file_or_directory) {
+ errs() << argv[0] << ": error opening '" << ArchiveName
+ << "': " << EC.message() << "!\n";
return 1;
}
- // Create or open the archive object.
- bool Exists;
- if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) {
- // Produce a warning if we should and we're creating the archive
- if (!Create)
- errs() << argv[0] << ": creating " << ArchivePath.str() << "\n";
- TheArchive = Archive::CreateEmpty(ArchivePath, Context);
- TheArchive->writeToDisk();
- } else {
- std::string Error;
- TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error);
- if (TheArchive == 0) {
- errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': "
- << Error << "!\n";
+ if (!EC) {
+ object::Archive Archive(Buf.take(), EC);
+
+ if (EC) {
+ errs() << argv[0] << ": error loading '" << ArchiveName
+ << "': " << EC.message() << "!\n";
return 1;
}
+ performOperation(Operation, &Archive);
+ return 0;
}
- // Make sure we're not fooling ourselves.
- assert(TheArchive && "Unable to instantiate the archive");
+ assert(EC == llvm::errc::no_such_file_or_directory);
- // Perform the operation
- std::string ErrMsg;
- bool haveError = false;
- switch (Operation) {
- case Print: haveError = doPrint(&ErrMsg); break;
- case Delete: haveError = doDelete(&ErrMsg); break;
- case Move: haveError = doMove(&ErrMsg); break;
- case QuickAppend: haveError = doQuickAppend(&ErrMsg); break;
- case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break;
- case DisplayTable: haveError = doDisplayTable(&ErrMsg); break;
- case Extract: haveError = doExtract(&ErrMsg); break;
- case NoOperation:
- errs() << argv[0] << ": No operation was selected.\n";
- break;
- }
- if (haveError) {
- errs() << argv[0] << ": " << ErrMsg << "\n";
- return 1;
+ if (!shouldCreateArchive(Operation)) {
+ failIfError(EC, Twine("error loading '") + ArchiveName + "'");
+ } else {
+ if (!Create) {
+ // Produce a warning if we should and we're creating the archive
+ errs() << argv[0] << ": creating " << ArchiveName << "\n";
+ }
}
- delete TheArchive;
- TheArchive = 0;
-
- // Return result code back to operating system.
- return exitCode;
+ performOperation(Operation, NULL);
+ return 0;
}
diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp
index d6f1919..b2e44ef 100644
--- a/tools/llvm-as/llvm-as.cpp
+++ b/tools/llvm-as/llvm-as.cpp
@@ -69,9 +69,8 @@ static void WriteOutputFile(const Module *M) {
}
std::string ErrorInfo;
- OwningPtr<tool_output_file> Out
- (new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ OwningPtr<tool_output_file> Out(new tool_output_file(
+ OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
exit(1);
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 99479a4..186eea9 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -481,7 +481,7 @@ static int AnalyzeBitcode() {
OwningPtr<MemoryBuffer> MemBuf;
if (error_code ec =
- MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), MemBuf))
+ MemoryBuffer::getFileOrSTDIN(InputFilename, MemBuf))
return Error("Error reading '" + InputFilename + "': " + ec.message());
if (MemBuf->getBufferSize() & 3)
diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
index 5151d1a..3924e2e 100644
--- a/tools/llvm-config/llvm-config.cpp
+++ b/tools/llvm-config/llvm-config.cpp
@@ -25,7 +25,6 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PathV1.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
@@ -162,11 +161,11 @@ Typical components:\n\
}
/// \brief Compute the path to the main executable.
-llvm::sys::Path GetExecutablePath(const char *Argv0) {
+std::string GetExecutablePath(const char *Argv0) {
// This just needs to be some symbol in the binary; C++ doesn't
// allow taking the address of ::main however.
void *P = (void*) (intptr_t) GetExecutablePath;
- return llvm::sys::Path::GetMainExecutable(Argv0, P);
+ return llvm::sys::fs::getMainExecutable(Argv0, P);
}
int main(int argc, char **argv) {
@@ -180,7 +179,7 @@ int main(int argc, char **argv) {
// tree.
bool IsInDevelopmentTree;
enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout;
- llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str());
+ llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]));
std::string CurrentExecPrefix;
std::string ActiveObjRoot;
diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp
index 067955e..87eb347 100644
--- a/tools/llvm-dis/llvm-dis.cpp
+++ b/tools/llvm-dis/llvm-dis.cpp
@@ -168,9 +168,8 @@ int main(int argc, char **argv) {
}
std::string ErrorInfo;
- OwningPtr<tool_output_file>
- Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ OwningPtr<tool_output_file> Out(new tool_output_file(
+ OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 8094856..eef6f79 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -63,6 +63,7 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_Info, "info", ".debug_info"),
clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
clEnumValN(DIDT_Line, "line", ".debug_line"),
+ clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index 2f45b4e..9ba68b4 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -265,8 +265,7 @@ int main(int argc, char **argv) {
Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
std::string ErrorInfo;
- tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index 01a61c6..652c414 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -55,18 +55,11 @@ DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
//
static inline Module *LoadFile(const char *argv0, const std::string &FN,
LLVMContext& Context) {
- sys::Path Filename;
- if (!Filename.set(FN)) {
- errs() << "Invalid file name: '" << FN << "'\n";
- return NULL;
- }
-
SMDiagnostic Err;
- if (Verbose) errs() << "Loading '" << Filename.c_str() << "'\n";
+ if (Verbose) errs() << "Loading '" << FN << "'\n";
Module* Result = 0;
-
- const std::string &FNStr = Filename.str();
- Result = ParseIRFile(FNStr, Err, Context);
+
+ Result = ParseIRFile(FN, Err, Context);
if (Result) return Result; // Load successful!
Err.print(argv0, errs());
@@ -113,8 +106,7 @@ int main(int argc, char **argv) {
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
std::string ErrorInfo;
- tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index 06c7721..81a0045 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -51,7 +51,7 @@ public:
static bool PrintInsts(const MCDisassembler &DisAsm,
const ByteArrayTy &Bytes,
SourceMgr &SM, raw_ostream &Out,
- MCStreamer &Streamer) {
+ MCStreamer &Streamer, bool InAtomicBlock) {
// Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes);
@@ -70,8 +70,13 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
SourceMgr::DK_Warning,
"invalid instruction encoding");
+ // Don't try to resynchronise the stream in a block
+ if (InAtomicBlock)
+ return true;
+
if (Size == 0)
Size = 1; // skip illegible bytes
+
break;
case MCDisassembler::SoftFail:
@@ -89,14 +94,11 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
return false;
}
-static bool ByteArrayFromString(ByteArrayTy &ByteArray,
- StringRef &Str,
- SourceMgr &SM) {
- while (!Str.empty()) {
- // Strip horizontal whitespace.
- if (size_t Pos = Str.find_first_not_of(" \t\r")) {
+static bool SkipToToken(StringRef &Str) {
+ while (!Str.empty() && Str.find_first_not_of(" \t\r\n#,") != 0) {
+ // Strip horizontal whitespace and commas.
+ if (size_t Pos = Str.find_first_not_of(" \t\r,")) {
Str = Str.substr(Pos);
- continue;
}
// If this is the end of a line or start of a comment, remove the rest of
@@ -113,9 +115,22 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray,
}
continue;
}
+ }
+
+ return !Str.empty();
+}
+
+
+static bool ByteArrayFromString(ByteArrayTy &ByteArray,
+ StringRef &Str,
+ SourceMgr &SM) {
+ while (SkipToToken(Str)) {
+ // Handled by higher level
+ if (Str[0] == '[' || Str[0] == ']')
+ return false;
// Get the current token.
- size_t Next = Str.find_first_of(" \t\n\r#");
+ size_t Next = Str.find_first_of(" \t\n\r,#[]");
StringRef Value = Str.substr(0, Next);
// Convert to a byte and add to the byte vector.
@@ -157,11 +172,44 @@ int Disassembler::disassemble(const Target &T,
// Convert the input to a vector for disassembly.
ByteArrayTy ByteArray;
StringRef Str = Buffer.getBuffer();
+ bool InAtomicBlock = false;
+
+ while (SkipToToken(Str)) {
+ ByteArray.clear();
+
+ if (Str[0] == '[') {
+ if (InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "nested atomic blocks make no sense");
+ ErrorOccurred = true;
+ }
+ InAtomicBlock = true;
+ Str = Str.drop_front();
+ continue;
+ } else if (Str[0] == ']') {
+ if (!InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "attempt to close atomic block without opening");
+ ErrorOccurred = true;
+ }
+ InAtomicBlock = false;
+ Str = Str.drop_front();
+ continue;
+ }
- ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
+ // It's a real token, get the bytes and emit them
+ ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
- if (!ByteArray.empty())
- ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
+ if (!ByteArray.empty())
+ ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer,
+ InAtomicBlock);
+ }
+
+ if (InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "unclosed atomic block");
+ ErrorOccurred = true;
+ }
return ErrorOccurred;
}
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index 289a445..f10a614 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -210,8 +210,8 @@ static tool_output_file *GetOutputStream() {
OutputFilename = "-";
std::string Err;
- tool_output_file *Out = new tool_output_file(OutputFilename.c_str(), Err,
- raw_fd_ostream::F_Binary);
+ tool_output_file *Out =
+ new tool_output_file(OutputFilename.c_str(), Err, sys::fs::F_Binary);
if (!Err.empty()) {
errs() << Err << '\n';
delete Out;
@@ -388,7 +388,7 @@ int main(int argc, char **argv) {
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
- MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
+ MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx);
if (SaveTempLabels)
diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt
index b6cd80b..b1672ff 100644
--- a/tools/llvm-nm/CMakeLists.txt
+++ b/tools/llvm-nm/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS archive bitreader object)
+set(LLVM_LINK_COMPONENTS bitreader object)
add_llvm_tool(llvm-nm
llvm-nm.cpp
diff --git a/tools/llvm-nm/LLVMBuild.txt b/tools/llvm-nm/LLVMBuild.txt
index 38ecbfd..3e64577 100644
--- a/tools/llvm-nm/LLVMBuild.txt
+++ b/tools/llvm-nm/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = llvm-nm
parent = Tools
-required_libraries = Archive BitReader Object
+required_libraries = BitReader Object
diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile
index d9cee98..b95e920 100644
--- a/tools/llvm-nm/Makefile
+++ b/tools/llvm-nm/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-nm
-LINK_COMPONENTS := archive bitreader object
+LINK_COMPONENTS := bitreader object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index a24aae6..01dd1c3 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -17,10 +17,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Bitcode/Archive.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -121,6 +121,8 @@ namespace {
bool MultipleFiles = false;
+ bool HadError = false;
+
std::string ToolName;
}
@@ -132,6 +134,7 @@ static void error(Twine message, Twine path = Twine()) {
static bool error(error_code ec, Twine path = Twine()) {
if (ec) {
error(ec.message(), path);
+ HadError = true;
return true;
}
return false;
@@ -362,21 +365,24 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
if (ArchiveMap) {
- outs() << "Archive map" << "\n";
- for (object::Archive::symbol_iterator i = a->begin_symbols(),
- e = a->end_symbols(); i != e; ++i) {
- object::Archive::child_iterator c;
- StringRef symname;
- StringRef filename;
- if (error(i->getMember(c)))
+ object::Archive::symbol_iterator I = a->begin_symbols();
+ object::Archive::symbol_iterator E = a->end_symbols();
+ if (I !=E) {
+ outs() << "Archive map" << "\n";
+ for (; I != E; ++I) {
+ object::Archive::child_iterator c;
+ StringRef symname;
+ StringRef filename;
+ if (error(I->getMember(c)))
return;
- if (error(i->getName(symname)))
+ if (error(I->getName(symname)))
return;
- if (error(c->getName(filename)))
+ if (error(c->getName(filename)))
return;
- outs() << symname << " in " << filename << "\n";
+ outs() << symname << " in " << filename << "\n";
+ }
+ outs() << "\n";
}
- outs() << "\n";
}
for (object::Archive::child_iterator i = a->begin_children(),
@@ -403,6 +409,23 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
}
}
}
+ } else if (magic == sys::fs::file_magic::macho_universal_binary) {
+ OwningPtr<Binary> Bin;
+ if (error(object::createBinary(Buffer.take(), Bin), Filename))
+ return;
+
+ object::MachOUniversalBinary *UB =
+ cast<object::MachOUniversalBinary>(Bin.get());
+ for (object::MachOUniversalBinary::object_iterator
+ I = UB->begin_objects(),
+ E = UB->end_objects();
+ I != E; ++I) {
+ OwningPtr<ObjectFile> Obj;
+ if (!I->getAsObjectFile(Obj)) {
+ outs() << Obj->getFileName() << ":\n";
+ DumpSymbolNamesFromObject(Obj.get());
+ }
+ }
} else if (magic.is_object()) {
OwningPtr<Binary> obj;
if (error(object::createBinary(Buffer.take(), obj), Filename))
@@ -412,6 +435,7 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
} else {
errs() << ToolName << ": " << Filename << ": "
<< "unrecognizable file type\n";
+ HadError = true;
return;
}
}
@@ -425,7 +449,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
// llvm-nm only reads binary files.
- if (error(sys::Program::ChangeStdinToBinary()))
+ if (error(sys::ChangeStdinToBinary()))
return 1;
ToolName = argv[0];
@@ -446,5 +470,9 @@ int main(int argc, char **argv) {
std::for_each(InputFilenames.begin(), InputFilenames.end(),
DumpSymbolNamesFromFile);
+
+ if (HadError)
+ return 1;
+
return 0;
}
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
index 7b55007..bca6fc9 100644
--- a/tools/llvm-objdump/COFFDump.cpp
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -229,7 +229,7 @@ static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
const coff_file_header *Header;
- if (error(Obj->getHeader(Header))) return;
+ if (error(Obj->getCOFFHeader(Header))) return;
if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
errs() << "Unsupported image machine type "
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index 27e1623..e0ec9cc 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -295,7 +295,7 @@ static void DisassembleInputMachO2(StringRef Filename,
// get the sections and supply it to the section name parsing machinery.
if (!DSYMFile.empty()) {
OwningPtr<MemoryBuffer> Buf;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) {
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile, Buf)) {
errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
return;
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 8049dac..122ac83 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -310,7 +310,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Symbolize) {
MOFI.reset(new MCObjectFileInfo);
- Ctx.reset(new MCContext(*AsmInfo.get(), *MRI.get(), MOFI.get()));
+ Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get()));
OwningPtr<MCRelocationInfo> RelInfo(
TheTarget->createMCRelocationInfo(TripleName, *Ctx.get()));
if (RelInfo) {
diff --git a/tools/llvm-ranlib/CMakeLists.txt b/tools/llvm-ranlib/CMakeLists.txt
deleted file mode 100644
index 2d7defe..0000000
--- a/tools/llvm-ranlib/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-set(LLVM_LINK_COMPONENTS archive)
-
-add_llvm_tool(llvm-ranlib
- llvm-ranlib.cpp
- )
diff --git a/tools/llvm-ranlib/LLVMBuild.txt b/tools/llvm-ranlib/LLVMBuild.txt
deleted file mode 100644
index 23015c5..0000000
--- a/tools/llvm-ranlib/LLVMBuild.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-;===- ./tools/llvm-ranlib/LLVMBuild.txt ------------------------*- Conf -*--===;
-;
-; The LLVM Compiler Infrastructure
-;
-; This file is distributed under the University of Illinois Open Source
-; License. See LICENSE.TXT for details.
-;
-;===------------------------------------------------------------------------===;
-;
-; This is an LLVMBuild description file for the components in this subdirectory.
-;
-; For more information on the LLVMBuild system, please see:
-;
-; http://llvm.org/docs/LLVMBuild.html
-;
-;===------------------------------------------------------------------------===;
-
-[component_0]
-type = Tool
-name = llvm-ranlib
-parent = Tools
-required_libraries = Archive
diff --git a/tools/llvm-ranlib/Makefile b/tools/llvm-ranlib/Makefile
deleted file mode 100644
index cca9501..0000000
--- a/tools/llvm-ranlib/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- tools/llvm-ranlib/Makefile --------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL := ../..
-TOOLNAME := llvm-ranlib
-LINK_COMPONENTS := archive
-
-# This tool has no plugins, optimize startup time.
-TOOL_NO_EXPORTS := 1
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp
deleted file mode 100644
index e3e3bad..0000000
--- a/tools/llvm-ranlib/llvm-ranlib.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- llvm-ranlib.cpp - LLVM archive index generator --------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Adds or updates an index (symbol table) for an LLVM archive file.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/Bitcode/Archive.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-using namespace llvm;
-
-// llvm-ar operation code and modifier flags
-static cl::opt<std::string>
-ArchiveName(cl::Positional, cl::Optional, cl::desc("<archive-file>"));
-
-static cl::opt<bool>
-Verbose("verbose",cl::Optional,cl::init(false),
- cl::desc("Print the symbol table"));
-
-// printSymbolTable - print out the archive's symbol table.
-void printSymbolTable(Archive* TheArchive) {
- outs() << "\nArchive Symbol Table:\n";
- const Archive::SymTabType& symtab = TheArchive->getSymbolTable();
- for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end();
- I != E; ++I ) {
- unsigned offset = TheArchive->getFirstFileOffset() + I->second;
- outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n";
- }
-}
-
-int main(int argc, char **argv) {
- // Print a stack trace if we signal out.
- llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::PrettyStackTraceProgram X(argc, argv);
-
- LLVMContext &Context = getGlobalContext();
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
-
- // Have the command line options parsed and handle things
- // like --help and --version.
- cl::ParseCommandLineOptions(argc, argv,
- "LLVM Archive Index Generator (llvm-ranlib)\n\n"
- " This program adds or updates an index of bitcode symbols\n"
- " to an LLVM archive file."
- );
-
- int exitCode = 0;
-
- // Check the path name of the archive
- sys::Path ArchivePath;
- if (!ArchivePath.set(ArchiveName)) {
- errs() << argv[0] << ": " << "Archive name invalid: " << ArchiveName <<
- "\n";
- return 1;
- }
-
- // Make sure it exists, we don't create empty archives
- bool Exists;
- if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) {
- errs() << argv[0] << ": " << "Archive file does not exist" <<
- ArchivePath.str() << "\n";
- return 1;
- }
-
- std::string err_msg;
- OwningPtr<Archive>
- AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg));
- Archive* TheArchive = AutoArchive.get();
- if (!TheArchive) {
- errs() << argv[0] << ": " << err_msg << "\n";
- return 1;
- }
-
- if (TheArchive->writeToDisk(true, false, &err_msg )) {
- errs() << argv[0] << ": " << err_msg << "\n";
- return 1;
- }
-
- if (Verbose)
- printSymbolTable(TheArchive);
-
- return exitCode;
-}
diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt
index 3d20def..90997a8 100644
--- a/tools/llvm-readobj/CMakeLists.txt
+++ b/tools/llvm-readobj/CMakeLists.txt
@@ -1,6 +1,5 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
- archive
bitreader
object)
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 3cbb9b3..2f309e3 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -60,6 +60,8 @@ private:
void printRelocation(section_iterator SecI, relocation_iterator RelI);
+ void printDataDirectory(uint32_t Index, const std::string &FieldName);
+
void printX64UnwindInfo();
void printRuntimeFunction(
@@ -262,6 +264,31 @@ static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )
};
+static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),
+};
+
+static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
+};
+
static const EnumEntry<COFF::SectionCharacteristics>
ImageSectionCharacteristics[] = {
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),
@@ -454,15 +481,15 @@ static std::string formatSymbol(const std::vector<RelocationRef> &Rels,
StringRef Sym;
if (resolveSymbolName(Rels, Offset, Sym)) {
- Str << format(" (0x%X)", Offset);
+ Str << format(" (0x%" PRIX64 ")", Offset);
return Str.str();
}
Str << Sym;
if (Disp > 0) {
- Str << format(" +0x%X (0x%X)", Disp, Offset);
+ Str << format(" +0x%X (0x%" PRIX64 ")", Disp, Offset);
} else {
- Str << format(" (0x%X)", Offset);
+ Str << format(" (0x%" PRIX64 ")", Offset);
}
return Str.str();
@@ -535,27 +562,90 @@ void COFFDumper::cacheRelocations() {
}
}
+void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
+ const data_directory *Data;
+ if (Obj->getDataDirectory(Index, Data))
+ return;
+ W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
+ W.printHex(FieldName + "Size", Data->Size);
+}
+
void COFFDumper::printFileHeaders() {
- const coff_file_header *Header = 0;
- if (error(Obj->getHeader(Header)))
+ // Print COFF header
+ const coff_file_header *COFFHeader = 0;
+ if (error(Obj->getCOFFHeader(COFFHeader)))
return;
- time_t TDS = Header->TimeDateStamp;
+ time_t TDS = COFFHeader->TimeDateStamp;
char FormattedTime[20] = { };
strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
{
DictScope D(W, "ImageFileHeader");
- W.printEnum ("Machine", Header->Machine,
+ W.printEnum ("Machine", COFFHeader->Machine,
makeArrayRef(ImageFileMachineType));
- W.printNumber("SectionCount", Header->NumberOfSections);
- W.printHex ("TimeDateStamp", FormattedTime, Header->TimeDateStamp);
- W.printHex ("PointerToSymbolTable", Header->PointerToSymbolTable);
- W.printNumber("SymbolCount", Header->NumberOfSymbols);
- W.printNumber("OptionalHeaderSize", Header->SizeOfOptionalHeader);
- W.printFlags ("Characteristics", Header->Characteristics,
+ W.printNumber("SectionCount", COFFHeader->NumberOfSections);
+ W.printHex ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp);
+ W.printHex ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable);
+ W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols);
+ W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader);
+ W.printFlags ("Characteristics", COFFHeader->Characteristics,
makeArrayRef(ImageFileCharacteristics));
}
+
+ // Print PE header. This header does not exist if this is an object file and
+ // not an executable.
+ const pe32_header *PEHeader = 0;
+ if (error(Obj->getPE32Header(PEHeader)))
+ return;
+
+ if (PEHeader) {
+ DictScope D(W, "ImageOptionalHeader");
+ W.printNumber("MajorLinkerVersion", PEHeader->MajorLinkerVersion);
+ W.printNumber("MinorLinkerVersion", PEHeader->MinorLinkerVersion);
+ W.printNumber("SizeOfCode", PEHeader->SizeOfCode);
+ W.printNumber("SizeOfInitializedData", PEHeader->SizeOfInitializedData);
+ W.printNumber("SizeOfUninitializedData", PEHeader->SizeOfUninitializedData);
+ W.printHex ("AddressOfEntryPoint", PEHeader->AddressOfEntryPoint);
+ W.printHex ("BaseOfCode", PEHeader->BaseOfCode);
+ W.printHex ("BaseOfData", PEHeader->BaseOfData);
+ W.printHex ("ImageBase", PEHeader->ImageBase);
+ W.printNumber("SectionAlignment", PEHeader->SectionAlignment);
+ W.printNumber("FileAlignment", PEHeader->FileAlignment);
+ W.printNumber("MajorOperatingSystemVersion",
+ PEHeader->MajorOperatingSystemVersion);
+ W.printNumber("MinorOperatingSystemVersion",
+ PEHeader->MinorOperatingSystemVersion);
+ W.printNumber("MajorImageVersion", PEHeader->MajorImageVersion);
+ W.printNumber("MinorImageVersion", PEHeader->MinorImageVersion);
+ W.printNumber("MajorSubsystemVersion", PEHeader->MajorSubsystemVersion);
+ W.printNumber("MinorSubsystemVersion", PEHeader->MinorSubsystemVersion);
+ W.printNumber("SizeOfImage", PEHeader->SizeOfImage);
+ W.printNumber("SizeOfHeaders", PEHeader->SizeOfHeaders);
+ W.printEnum ("Subsystem", PEHeader->Subsystem,
+ makeArrayRef(PEWindowsSubsystem));
+ W.printFlags ("Subsystem", PEHeader->DLLCharacteristics,
+ makeArrayRef(PEDLLCharacteristics));
+ W.printNumber("SizeOfStackReserve", PEHeader->SizeOfStackReserve);
+ W.printNumber("SizeOfStackCommit", PEHeader->SizeOfStackCommit);
+ W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
+ W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
+ W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
+
+ if (PEHeader->NumberOfRvaAndSize > 0) {
+ DictScope D(W, "DataDirectory");
+ static const char * const directory[] = {
+ "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
+ "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
+ "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
+ "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
+ };
+
+ for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
+ printDataDirectory(i, directory[i]);
+ }
+ }
+ }
}
void COFFDumper::printSections() {
@@ -834,7 +924,7 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
void COFFDumper::printUnwindInfo() {
const coff_file_header *Header;
- if (error(Obj->getHeader(Header)))
+ if (error(Obj->getCOFFHeader(Header)))
return;
ListScope D(W, "UnwindInformation");
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 67bbafa..3628c3b 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -290,7 +290,6 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EM_STM8 ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_TILE64 ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEPRO ),
- LLVM_READOBJ_ENUM_ENT(ELF, EM_MICROBLAZE ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_CUDA ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEGX ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_CLOUDSHIELD ),
@@ -301,8 +300,7 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EM_RL78 ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5 ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR ),
- LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ),
- LLVM_READOBJ_ENUM_ENT(ELF, EM_MBLAZE )
+ LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX )
};
static const EnumEntry<unsigned> ElfSymbolBindings[] = {
diff --git a/tools/llvm-readobj/LLVMBuild.txt b/tools/llvm-readobj/LLVMBuild.txt
index 813c12b..e75f195 100644
--- a/tools/llvm-readobj/LLVMBuild.txt
+++ b/tools/llvm-readobj/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = llvm-readobj
parent = Tools
-required_libraries = all-targets Archive BitReader Object
+required_libraries = all-targets BitReader Object
diff --git a/tools/llvm-readobj/Makefile b/tools/llvm-readobj/Makefile
index 1bb7295..958bd0c 100644
--- a/tools/llvm-readobj/Makefile
+++ b/tools/llvm-readobj/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-readobj
-LINK_COMPONENTS := archive bitreader object all-targets
+LINK_COMPONENTS := bitreader object all-targets
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index b68f2a0..7f042d2 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -124,8 +124,8 @@ static int printLineInfoForInput() {
InputFileList.push_back("-");
for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
// Instantiate a dynamic linker.
- TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
- RuntimeDyld Dyld(MemMgr);
+ TrivialMemoryManager MemMgr;
+ RuntimeDyld Dyld(&MemMgr);
// Load the input memory buffer.
OwningPtr<MemoryBuffer> InputBuffer;
@@ -180,8 +180,8 @@ static int printLineInfoForInput() {
static int executeInput() {
// Instantiate a dynamic linker.
- TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
- RuntimeDyld Dyld(MemMgr);
+ TrivialMemoryManager MemMgr;
+ RuntimeDyld Dyld(&MemMgr);
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
@@ -204,7 +204,7 @@ static int executeInput() {
// Resolve all the relocations we can.
Dyld.resolveRelocations();
// Clear instruction cache before code will be executed.
- MemMgr->invalidateInstructionCache();
+ MemMgr.invalidateInstructionCache();
// FIXME: Error out if there are unresolved relocations.
@@ -214,8 +214,8 @@ static int executeInput() {
return Error("no definition for '" + EntryPoint + "'");
// Invalidate the instruction cache for each loaded function.
- for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) {
- sys::MemoryBlock &Data = MemMgr->FunctionMemory[i];
+ for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) {
+ sys::MemoryBlock &Data = MemMgr.FunctionMemory[i];
// Make sure the memory is executable.
std::string ErrorStr;
sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile
index 8697bbf..1d9053b 100644
--- a/tools/llvm-shlib/Makefile
+++ b/tools/llvm-shlib/Makefile
@@ -58,22 +58,22 @@ ifeq ($(HOST_OS),Darwin)
ifneq ($(DARWIN_VERS),8)
LLVMLibsOptions := $(LLVMLibsOptions) \
-Wl,-install_name \
- -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
endif
endif
-ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD OpenBSD GNU Bitrig))
+ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD GNU/kFreeBSD OpenBSD GNU Bitrig))
# Include everything from the .a's into the shared library.
LLVMLibsOptions := -Wl,--whole-archive $(LLVMLibsOptions) \
-Wl,--no-whole-archive
endif
-ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD GNU))
+ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD GNU/kFreeBSD GNU))
# Add soname to the library.
LLVMLibsOptions += -Wl,--soname,lib$(LIBRARYNAME)$(SHLIBEXT)
endif
-ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux GNU))
+ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux GNU GNU/kFreeBSD))
# Don't allow unresolved symbols.
LLVMLibsOptions += -Wl,--no-undefined
endif
diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp
index fbda1b7..15f7abf 100644
--- a/tools/llvm-stress/llvm-stress.cpp
+++ b/tools/llvm-stress/llvm-stress.cpp
@@ -702,7 +702,7 @@ int main(int argc, char **argv) {
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ sys::fs::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 7fccedf..0346fb2 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -74,6 +74,9 @@ ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
StringRef SymbolName;
if (error(si->getName(SymbolName)))
continue;
+ // Mach-O symbol table names have leading underscore, skip it.
+ if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
+ SymbolName = SymbolName.drop_front();
// FIXME: If a function has alias, there are two entries in symbol table
// with same address size. Make sure we choose the correct one.
SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
@@ -187,8 +190,8 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
uint64_t Size = 0;
if (Opts.UseSymbolTable) {
if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
- if (Info->symbolizeData(ModuleOffset, Name, Start, Size))
- DemangleName(Name);
+ if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
+ Name = DemangleName(Name);
}
}
std::stringstream ss;
@@ -198,23 +201,12 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
void LLVMSymbolizer::flush() {
DeleteContainerSeconds(Modules);
+ DeleteContainerPointers(ParsedBinariesAndObjects);
+ BinaryForPath.clear();
+ ObjectFileForArch.clear();
}
-// Returns true if the object endianness is known.
-static bool getObjectEndianness(const ObjectFile *Obj, bool &IsLittleEndian) {
- // FIXME: Implement this when libLLVMObject allows to do it easily.
- IsLittleEndian = true;
- return true;
-}
-
-static ObjectFile *getObjectFile(const std::string &Path) {
- OwningPtr<MemoryBuffer> Buff;
- if (error(MemoryBuffer::getFile(Path, Buff)))
- return 0;
- return ObjectFile::createObjectFile(Buff.take());
-}
-
-static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
+static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
StringRef Basename = sys::path::filename(Path);
const std::string &DSymDirectory = Path + ".dSYM";
SmallString<16> ResourceName = StringRef(DSymDirectory);
@@ -223,39 +215,89 @@ static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
return ResourceName.str();
}
+LLVMSymbolizer::BinaryPair
+LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
+ BinaryMapTy::iterator I = BinaryForPath.find(Path);
+ if (I != BinaryForPath.end())
+ return I->second;
+ Binary *Bin = 0;
+ Binary *DbgBin = 0;
+ OwningPtr<Binary> ParsedBinary;
+ OwningPtr<Binary> ParsedDbgBinary;
+ if (!error(createBinary(Path, ParsedBinary))) {
+ // Check if it's a universal binary.
+ Bin = ParsedBinary.take();
+ ParsedBinariesAndObjects.push_back(Bin);
+ if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
+ // On Darwin we may find DWARF in separate object file in
+ // resource directory.
+ const std::string &ResourcePath =
+ getDarwinDWARFResourceForPath(Path);
+ bool ResourceFileExists = false;
+ if (!sys::fs::exists(ResourcePath, ResourceFileExists) &&
+ ResourceFileExists &&
+ !error(createBinary(ResourcePath, ParsedDbgBinary))) {
+ DbgBin = ParsedDbgBinary.take();
+ ParsedBinariesAndObjects.push_back(DbgBin);
+ }
+ }
+ }
+ if (DbgBin == 0)
+ DbgBin = Bin;
+ BinaryPair Res = std::make_pair(Bin, DbgBin);
+ BinaryForPath[Path] = Res;
+ return Res;
+}
+
+ObjectFile *
+LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
+ if (Bin == 0)
+ return 0;
+ ObjectFile *Res = 0;
+ if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
+ ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
+ std::make_pair(UB, ArchName));
+ if (I != ObjectFileForArch.end())
+ return I->second;
+ OwningPtr<ObjectFile> ParsedObj;
+ if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
+ Res = ParsedObj.take();
+ ParsedBinariesAndObjects.push_back(Res);
+ }
+ ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
+ } else if (Bin->isObject()) {
+ Res = cast<ObjectFile>(Bin);
+ }
+ return Res;
+}
+
ModuleInfo *
LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
ModuleMapTy::iterator I = Modules.find(ModuleName);
if (I != Modules.end())
return I->second;
+ std::string BinaryName = ModuleName;
+ std::string ArchName = Opts.DefaultArch;
+ size_t ColonPos = ModuleName.find_last_of(':');
+ // Verify that substring after colon form a valid arch name.
+ if (ColonPos != std::string::npos) {
+ std::string ArchStr = ModuleName.substr(ColonPos + 1);
+ if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
+ BinaryName = ModuleName.substr(0, ColonPos);
+ ArchName = ArchStr;
+ }
+ }
+ BinaryPair Binaries = getOrCreateBinary(BinaryName);
+ ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
+ ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);
- ObjectFile *Obj = getObjectFile(ModuleName);
if (Obj == 0) {
- // Module name doesn't point to a valid object file.
+ // Failed to find valid object file.
Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
return 0;
}
-
- DIContext *Context = 0;
- bool IsLittleEndian;
- if (getObjectEndianness(Obj, IsLittleEndian)) {
- // On Darwin we may find DWARF in separate object file in
- // resource directory.
- ObjectFile *DbgObj = Obj;
- if (isa<MachOObjectFile>(Obj)) {
- const std::string &ResourceName =
- getDarwinDWARFResourceForModule(ModuleName);
- bool ResourceFileExists = false;
- if (!sys::fs::exists(ResourceName, ResourceFileExists) &&
- ResourceFileExists) {
- if (ObjectFile *ResourceObj = getObjectFile(ResourceName))
- DbgObj = ResourceObj;
- }
- }
- Context = DIContext::getDWARFContext(DbgObj);
- assert(Context);
- }
-
+ DIContext *Context = DIContext::getDWARFContext(DbgObj);
+ assert(Context);
ModuleInfo *Info = new ModuleInfo(Obj, Context);
Modules.insert(make_pair(ModuleName, Info));
return Info;
@@ -270,7 +312,8 @@ std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
std::string FunctionName = LineInfo.getFunctionName();
if (FunctionName == kDILineInfoBadString)
FunctionName = kBadString;
- DemangleName(FunctionName);
+ else if (Opts.Demangle)
+ FunctionName = DemangleName(FunctionName);
Result << FunctionName << "\n";
}
std::string Filename = LineInfo.getFileName();
@@ -287,16 +330,17 @@ extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
size_t *length, int *status);
#endif
-void LLVMSymbolizer::DemangleName(std::string &Name) const {
+std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
#if !defined(_MSC_VER)
- if (!Opts.Demangle)
- return;
int status = 0;
char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
if (status != 0)
- return;
- Name = DemangledName;
+ return Name;
+ std::string Result = DemangledName;
free(DemangledName);
+ return Result;
+#else
+ return Name;
#endif
}
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h
index 188331b..03c765c 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -14,7 +14,9 @@
#define LLVM_SYMBOLIZE_H
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
@@ -35,14 +37,20 @@ public:
bool PrintFunctions : 1;
bool PrintInlining : 1;
bool Demangle : 1;
+ std::string DefaultArch;
Options(bool UseSymbolTable = true, bool PrintFunctions = true,
- bool PrintInlining = true, bool Demangle = true)
+ bool PrintInlining = true, bool Demangle = true,
+ std::string DefaultArch = "")
: UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions),
- PrintInlining(PrintInlining), Demangle(Demangle) {
+ PrintInlining(PrintInlining), Demangle(Demangle),
+ DefaultArch(DefaultArch) {
}
};
LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
+ ~LLVMSymbolizer() {
+ flush();
+ }
// Returns the result of symbolization for module name/offset as
// a string (possibly containing newlines).
@@ -51,13 +59,30 @@ public:
std::string
symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
void flush();
+ static std::string DemangleName(const std::string &Name);
private:
+ typedef std::pair<Binary*, Binary*> BinaryPair;
+
ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
+ /// \brief Returns pair of pointers to binary and debug binary.
+ BinaryPair getOrCreateBinary(const std::string &Path);
+ /// \brief Returns a parsed object file for a given architecture in a
+ /// universal binary (or the binary itself if it is an object file).
+ ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);
+
std::string printDILineInfo(DILineInfo LineInfo) const;
- void DemangleName(std::string &Name) const;
+ // Owns all the parsed binaries and object files.
+ SmallVector<Binary*, 4> ParsedBinariesAndObjects;
+ // Owns module info objects.
typedef std::map<std::string, ModuleInfo *> ModuleMapTy;
ModuleMapTy Modules;
+ typedef std::map<std::string, BinaryPair> BinaryMapTy;
+ BinaryMapTy BinaryForPath;
+ typedef std::map<std::pair<MachOUniversalBinary *, std::string>, ObjectFile *>
+ ObjectFileForArchMapTy;
+ ObjectFileForArchMapTy ObjectFileForArch;
+
Options Opts;
static const char kBadString[];
};
@@ -77,7 +102,7 @@ private:
bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const;
- OwningPtr<ObjectFile> Module;
+ ObjectFile *Module;
OwningPtr<DIContext> DebugInfoContext;
struct SymbolDesc {
diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 0cafffa..c32e949 100644
--- a/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -47,6 +47,10 @@ ClPrintInlining("inlining", cl::init(true),
static cl::opt<bool>
ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
+static cl::opt<std::string> ClDefaultArch("default-arch", cl::init(""),
+ cl::desc("Default architecture "
+ "(for multi-arch objects)"));
+
static bool parseCommand(bool &IsData, std::string &ModuleName,
uint64_t &ModuleOffset) {
const char *kDataCmd = "DATA ";
@@ -102,7 +106,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n");
LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
- ClPrintInlining, ClDemangle);
+ ClPrintInlining, ClDemangle, ClDefaultArch);
LLVMSymbolizer Symbolizer(Opts);
bool IsData = false;
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 465ccb4..758227d 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -24,12 +24,14 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
#include "llvm/Linker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -76,6 +78,7 @@ LTOCodeGenerator::LTOCodeGenerator()
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
+ initializeLTOPasses();
}
LTOCodeGenerator::~LTOCodeGenerator() {
@@ -88,6 +91,36 @@ LTOCodeGenerator::~LTOCodeGenerator() {
free(*I);
}
+// Initialize LTO passes. Please keep this funciton in sync with
+// PassManagerBuilder::populateLTOPassManager(), and make sure all LTO
+// passes are initialized.
+//
+void LTOCodeGenerator::initializeLTOPasses() {
+ PassRegistry &R = *PassRegistry::getPassRegistry();
+
+ initializeInternalizePassPass(R);
+ initializeIPSCCPPass(R);
+ initializeGlobalOptPass(R);
+ initializeConstantMergePass(R);
+ initializeDAHPass(R);
+ initializeInstCombinerPass(R);
+ initializeSimpleInlinerPass(R);
+ initializePruneEHPass(R);
+ initializeGlobalDCEPass(R);
+ initializeArgPromotionPass(R);
+ initializeJumpThreadingPass(R);
+ initializeSROAPass(R);
+ initializeSROA_DTPass(R);
+ initializeSROA_SSAUpPass(R);
+ initializeFunctionAttrsPass(R);
+ initializeGlobalsModRefPass(R);
+ initializeLICMPass(R);
+ initializeGVNPass(R);
+ initializeMemCpyOptPass(R);
+ initializeDCEPass(R);
+ initializeCFGSimplifyPassPass(R);
+}
+
bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
bool ret = _linker.linkInModule(mod->getLLVVMModule(), &errMsg);
@@ -95,51 +128,50 @@ bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
for (int i = 0, e = undefs.size(); i != e; ++i)
_asmUndefinedRefs[undefs[i]] = 1;
- return ret;
+ return !ret;
}
-bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug,
- std::string& errMsg) {
+void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) {
switch (debug) {
case LTO_DEBUG_MODEL_NONE:
_emitDwarfDebugInfo = false;
- return false;
+ return;
case LTO_DEBUG_MODEL_DWARF:
_emitDwarfDebugInfo = true;
- return false;
+ return;
}
llvm_unreachable("Unknown debug format!");
}
-bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
- std::string& errMsg) {
+void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) {
switch (model) {
case LTO_CODEGEN_PIC_MODEL_STATIC:
case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
_codeModel = model;
- return false;
+ return;
}
llvm_unreachable("Unknown PIC model!");
}
bool LTOCodeGenerator::writeMergedModules(const char *path,
std::string &errMsg) {
- if (determineTarget(errMsg))
- return true;
+ if (!determineTarget(errMsg))
+ return false;
- // mark which symbols can not be internalized
- applyScopeRestrictions();
+ // Run the verifier on the merged modules.
+ PassManager passes;
+ passes.add(createVerifierPass());
+ passes.run(*_linker.getModule());
// create output file
std::string ErrInfo;
- tool_output_file Out(path, ErrInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(path, ErrInfo, sys::fs::F_Binary);
if (!ErrInfo.empty()) {
errMsg = "could not open bitcode file for writing: ";
errMsg += path;
- return true;
+ return false;
}
// write bitcode to it
@@ -150,52 +182,48 @@ bool LTOCodeGenerator::writeMergedModules(const char *path,
errMsg = "could not write bitcode file: ";
errMsg += path;
Out.os().clear_error();
- return true;
+ return false;
}
Out.keep();
- return false;
+ return true;
}
bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
// make unique temp .o file to put generated object file
- sys::PathWithStatus uniqueObjPath("lto-llvm.o");
- if (uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg)) {
- uniqueObjPath.eraseFromDisk();
- return true;
+ SmallString<128> Filename;
+ int FD;
+ error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename);
+ if (EC) {
+ errMsg = EC.message();
+ return false;
}
- sys::RemoveFileOnSignal(uniqueObjPath);
// generate object file
- bool genResult = false;
- tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
- if (!errMsg.empty()) {
- uniqueObjPath.eraseFromDisk();
- return true;
- }
+ tool_output_file objFile(Filename.c_str(), FD);
- genResult = this->generateObjectFile(objFile.os(), errMsg);
+ bool genResult = generateObjectFile(objFile.os(), errMsg);
objFile.os().close();
if (objFile.os().has_error()) {
objFile.os().clear_error();
- uniqueObjPath.eraseFromDisk();
- return true;
+ sys::fs::remove(Twine(Filename));
+ return false;
}
objFile.keep();
- if (genResult) {
- uniqueObjPath.eraseFromDisk();
- return true;
+ if (!genResult) {
+ sys::fs::remove(Twine(Filename));
+ return false;
}
- _nativeObjectPath = uniqueObjPath.str();
+ _nativeObjectPath = Filename.c_str();
*name = _nativeObjectPath.c_str();
- return false;
+ return true;
}
const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
const char *name;
- if (compile_to_file(&name, errMsg))
+ if (!compile_to_file(&name, errMsg))
return NULL;
// remove old buffer if compile() called twice
@@ -205,13 +233,13 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
OwningPtr<MemoryBuffer> BuffPtr;
if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
errMsg = ec.message();
- sys::Path(_nativeObjectPath).eraseFromDisk();
+ sys::fs::remove(_nativeObjectPath);
return NULL;
}
_nativeObjectFile = BuffPtr.take();
// remove temp files
- sys::Path(_nativeObjectPath).eraseFromDisk();
+ sys::fs::remove(_nativeObjectPath);
// return buffer, unless error
if (_nativeObjectFile == NULL)
@@ -222,7 +250,7 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
if (_target != NULL)
- return false;
+ return true;
// if options were requested, set them
if (!_codegenOptions.empty())
@@ -237,7 +265,7 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
// create target machine from info for merged modules
const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
if (march == NULL)
- return true;
+ return false;
// The relocation model is actually a static member of TargetMachine and
// needs to be set before the TargetMachine is instantiated.
@@ -270,7 +298,7 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
_target = march->createTargetMachine(TripleStr, _mCpu, FeatureStr, Options,
RelocModel, CodeModel::Default,
CodeGenOpt::Aggressive);
- return false;
+ return true;
}
void LTOCodeGenerator::
@@ -309,7 +337,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
passes.add(createVerifierPass());
// mark which symbols can not be internalized
- MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
+ MCContext Context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL);
Mangler mangler(Context, _target);
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
@@ -361,8 +389,8 @@ void LTOCodeGenerator::applyScopeRestrictions() {
/// Optimize merged modules using various IPO passes
bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
std::string &errMsg) {
- if (this->determineTarget(errMsg))
- return true;
+ if (!this->determineTarget(errMsg))
+ return false;
Module* mergedModule = _linker.getModule();
@@ -405,7 +433,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
if (_target->addPassesToEmitFile(codeGenPasses, Out,
TargetMachine::CGFT_ObjectFile)) {
errMsg = "target file type not supported";
- return true;
+ return false;
}
// Run our queue of passes all at once now, efficiently.
@@ -414,7 +442,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
// Run the code generator, and write assembly file
codeGenPasses.run(*mergedModule);
- return false; // success
+ return true;
}
/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging
diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h
index a4ade9f..8f37cf0 100644
--- a/tools/lto/LTOCodeGenerator.h
+++ b/tools/lto/LTOCodeGenerator.h
@@ -9,6 +9,27 @@
//
// This file declares the LTOCodeGenerator class.
//
+// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO.
+//
+// The Pre-IPO phase compiles source code into bitcode file. The resulting
+// bitcode files, along with object files and libraries, will be fed to the
+// linker to through the IPO and Post-IPO phases. By using obj-file extension,
+// the resulting bitcode file disguises itself as an object file, and therefore
+// obviates the need of writing a special set of the make-rules only for LTO
+// compilation.
+//
+// The IPO phase perform inter-procedural analyses and optimizations, and
+// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations
+// (SOPT), and intra-procedural target-dependent code generator (CG).
+//
+// As of this writing, we don't separate IPO and the Post-IPO SOPT. They
+// are intermingled together, and are driven by a single pass manager (see
+// PassManagerBuilder::populateLTOPassManager()).
+//
+// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages.
+// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator"
+// with the machine specific code generator.
+//
//===----------------------------------------------------------------------===//
#ifndef LTO_CODE_GENERATOR_H
@@ -40,9 +61,11 @@ struct LTOCodeGenerator {
LTOCodeGenerator();
~LTOCodeGenerator();
+ // Merge given module, return true on success.
bool addModule(struct LTOModule*, std::string &errMsg);
- bool setDebugInfo(lto_debug_model, std::string &errMsg);
- bool setCodePICModel(lto_codegen_model, std::string &errMsg);
+
+ void setDebugInfo(lto_debug_model);
+ void setCodePICModel(lto_codegen_model);
void setCpu(const char* mCpu) { _mCpu = mCpu; }
@@ -50,12 +73,38 @@ struct LTOCodeGenerator {
_mustPreserveSymbols[sym] = 1;
}
+ // To pass options to the driver and optimization passes. These options are
+ // not necessarily for debugging purpose (The function name is misleading).
+ // This function should be called before LTOCodeGenerator::compilexxx(),
+ // and LTOCodeGenerator::writeMergedModules().
+ //
+ void setCodeGenDebugOptions(const char *opts);
+
+ // Write the merged module to the file specified by the given path.
+ // Return true on success.
bool writeMergedModules(const char *path, std::string &errMsg);
+
+ // Compile the merged module into a *single* object file; the path to object
+ // file is returned to the caller via argument "name". Return true on
+ // success.
+ //
+ // NOTE that it is up to the linker to remove the intermediate object file.
+ // Do not try to remove the object file in LTOCodeGenerator's destructor
+ // as we don't who (LTOCodeGenerator or the obj file) will last longer.
+ //
bool compile_to_file(const char **name, std::string &errMsg);
+
+ // As with compile_to_file(), this function compiles the merged module into
+ // single object file. Instead of returning the object-file-path to the caller
+ // (linker), it brings the object to a buffer, and return the buffer to the
+ // caller. This function should delete intermediate object file once its content
+ // is brought to memory. Return NULL is the compilation was not successful.
+ //
const void *compile(size_t *length, std::string &errMsg);
- void setCodeGenDebugOptions(const char *opts);
private:
+ void initializeLTOPasses();
+
bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg);
void applyScopeRestrictions();
void applyRestriction(llvm::GlobalValue &GV,
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 263e8b3..e89733f 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -50,11 +50,6 @@ DisableFPElim("disable-fp-elim",
cl::init(false));
static cl::opt<bool>
-DisableFPElimNonLeaf("disable-non-leaf-fp-elim",
- cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"),
- cl::init(false));
-
-static cl::opt<bool>
EnableUnsafeFPMath("enable-unsafe-fp-math",
cl::desc("Enable optimizations that may decrease FP precision"),
cl::init(false));
@@ -126,11 +121,6 @@ OverrideStackAlignment("stack-alignment",
cl::desc("Override default stack alignment"),
cl::init(0));
-static cl::opt<bool>
-EnableRealignStack("realign-stack",
- cl::desc("Realign stack if needed"),
- cl::init(true));
-
static cl::opt<std::string>
TrapFuncName("trap-func", cl::Hidden,
cl::desc("Emit a call to trap function rather than a trap instruction"),
@@ -151,14 +141,9 @@ UseInitArray("use-init-array",
cl::desc("Use .init_array instead of .ctors."),
cl::init(false));
-static cl::opt<unsigned>
-SSPBufferSize("stack-protector-buffer-size", cl::init(8),
- cl::desc("Lower bound for a buffer to be considered for "
- "stack protection"));
-
LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t)
: _module(m), _target(t),
- _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL),
+ _context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL),
_mangler(_context, t) {}
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
@@ -214,17 +199,16 @@ LTOModule *LTOModule::makeLTOModule(const char *path, std::string &errMsg) {
LTOModule *LTOModule::makeLTOModule(int fd, const char *path,
size_t size, std::string &errMsg) {
- return makeLTOModule(fd, path, size, size, 0, errMsg);
+ return makeLTOModule(fd, path, size, 0, errMsg);
}
LTOModule *LTOModule::makeLTOModule(int fd, const char *path,
- size_t file_size,
size_t map_size,
off_t offset,
std::string &errMsg) {
OwningPtr<MemoryBuffer> buffer;
- if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, file_size,
- map_size, offset, false)) {
+ if (error_code ec =
+ MemoryBuffer::getOpenFileSlice(fd, path, buffer, map_size, offset)) {
errMsg = ec.message();
return NULL;
}
@@ -242,7 +226,6 @@ LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length,
void LTOModule::getTargetOptions(TargetOptions &Options) {
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.NoFramePointerElim = DisableFPElim;
- Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
@@ -256,12 +239,10 @@ void LTOModule::getTargetOptions(TargetOptions &Options) {
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.DisableTailCalls = DisableTailCalls;
Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.RealignStack = EnableRealignStack;
Options.TrapFuncName = TrapFuncName;
Options.PositionIndependentExecutable = EnablePIE;
Options.EnableSegmentedStacks = SegmentedStacks;
Options.UseInitArray = UseInitArray;
- Options.SSPBufferSize = SSPBufferSize;
}
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
@@ -792,9 +773,8 @@ namespace {
unsigned ByteAlignment) {}
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {}
- virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {}
- virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
- unsigned AddrSpace) {}
+ virtual void EmitBytes(StringRef Data) {}
+ virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {}
virtual void EmitULEB128Value(const MCExpr *Value) {}
virtual void EmitSLEB128Value(const MCExpr *Value) {}
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h
index 83f3a7d..902e9c5 100644
--- a/tools/lto/LTOModule.h
+++ b/tools/lto/LTOModule.h
@@ -82,7 +82,6 @@ public:
static LTOModule *makeLTOModule(int fd, const char *path,
size_t size, std::string &errMsg);
static LTOModule *makeLTOModule(int fd, const char *path,
- size_t file_size,
size_t map_size,
off_t offset,
std::string& errMsg);
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index 30719f4..56c67df 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -46,7 +46,7 @@ ifeq ($(HOST_OS),Darwin)
ifneq ($(DARWIN_VERS),8)
LLVMLibsOptions := $(LLVMLibsOptions) \
-Wl,-install_name \
- -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
endif
# If we're doing an Apple-style build, add the LTO object path.
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
index 11ad532..db7147c 100644
--- a/tools/lto/lto.cpp
+++ b/tools/lto/lto.cpp
@@ -78,8 +78,7 @@ lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
size_t file_size,
size_t map_size,
off_t offset) {
- return LTOModule::makeLTOModule(fd, path, file_size, map_size,
- offset, sLastErrorString);
+ return LTOModule::makeLTOModule(fd, path, map_size, offset, sLastErrorString);
}
/// lto_module_create_from_memory - Loads an object file from memory. Returns
@@ -141,20 +140,22 @@ void lto_codegen_dispose(lto_code_gen_t cg) {
/// which code will be generated. Returns true on error (check
/// lto_get_error_message() for details).
bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
- return cg->addModule(mod, sLastErrorString);
+ return !cg->addModule(mod, sLastErrorString);
}
/// lto_codegen_set_debug_model - Sets what if any format of debug info should
/// be generated. Returns true on error (check lto_get_error_message() for
/// details).
bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
- return cg->setDebugInfo(debug, sLastErrorString);
+ cg->setDebugInfo(debug);
+ return false;
}
/// lto_codegen_set_pic_model - Sets what code model to generated. Returns true
/// on error (check lto_get_error_message() for details).
bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
- return cg->setCodePICModel(model, sLastErrorString);
+ cg->setCodePICModel(model);
+ return false;
}
/// lto_codegen_set_cpu - Sets the cpu to generate code for.
@@ -186,7 +187,7 @@ void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
/// that contains the merged contents of all modules added so far. Returns true
/// on error (check lto_get_error_message() for details).
bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
- return cg->writeMergedModules(path, sLastErrorString);
+ return !cg->writeMergedModules(path, sLastErrorString);
}
/// lto_codegen_compile - Generates code for all added modules into one native
@@ -203,7 +204,7 @@ const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
/// native object file. The name of the file is written to name. Returns true on
/// error.
bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
- return cg->compile_to_file(name, sLastErrorString);
+ return !cg->compile_to_file(name, sLastErrorString);
}
/// lto_codegen_debug_options - Used to pass extra options to the code
diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt
index d64bf1b..6b39193 100644
--- a/tools/obj2yaml/CMakeLists.txt
+++ b/tools/obj2yaml/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS archive object)
+set(LLVM_LINK_COMPONENTS object)
add_llvm_utility(obj2yaml
obj2yaml.cpp coff2yaml.cpp
diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp
index 0ec35bf..1e28c4e 100644
--- a/tools/obj2yaml/coff2yaml.cpp
+++ b/tools/obj2yaml/coff2yaml.cpp
@@ -38,7 +38,7 @@ static void check(error_code ec) {
COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
const object::coff_file_header *Header;
- check(Obj.getHeader(Header));
+ check(Obj.getCOFFHeader(Header));
dumpHeader(Header);
dumpSections(Header->NumberOfSections);
dumpSymbols(Header->NumberOfSymbols);
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 57b03b4..37637ca 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -389,8 +389,11 @@ struct BreakpointPrinter : public ModulePass {
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
std::string Name;
DISubprogram SP(NMD->getOperand(i));
- if (SP.Verify())
- getContextName(SP.getContext(), Name);
+ assert((!SP || SP.isSubprogram()) &&
+ "A MDNode in llvm.dbg.sp should be null or a DISubprogram.");
+ if (!SP)
+ continue;
+ getContextName(SP.getContext(), Name);
Name = Name + SP.getDisplayName().str();
if (!Name.empty() && Processed.insert(Name)) {
Out << Name << "\n";
@@ -445,7 +448,6 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
}
Builder.DisableUnitAtATime = !UnitAtATime;
Builder.DisableUnrollLoops = OptLevel == 0;
- Builder.DisableSimplifyLibCalls = DisableSimplifyLibCalls;
Builder.populateFunctionPassManager(FPM);
Builder.populateModulePassManager(MPM);
@@ -465,7 +467,6 @@ static void AddStandardCompilePasses(PassManagerBase &PM) {
if (!DisableInline)
Builder.Inliner = createFunctionInliningPass();
Builder.OptLevel = 3;
- Builder.DisableSimplifyLibCalls = DisableSimplifyLibCalls;
Builder.populateModulePassManager(PM);
}
@@ -490,7 +491,6 @@ static TargetOptions GetTargetOptions() {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.NoFramePointerElim = DisableFPElim;
- Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
@@ -504,12 +504,10 @@ static TargetOptions GetTargetOptions() {
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.DisableTailCalls = DisableTailCalls;
Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.RealignStack = EnableRealignStack;
Options.TrapFuncName = TrapFuncName;
Options.PositionIndependentExecutable = EnablePIE;
Options.EnableSegmentedStacks = SegmentedStacks;
Options.UseInitArray = UseInitArray;
- Options.SSPBufferSize = SSPBufferSize;
return Options;
}
@@ -615,7 +613,7 @@ int main(int argc, char **argv) {
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ sys::fs::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
@@ -668,6 +666,9 @@ int main(int argc, char **argv) {
FPasses.reset(new FunctionPassManager(M.get()));
if (TD)
FPasses->add(new DataLayout(*TD));
+ if (TM.get())
+ TM->addAnalysisPasses(*FPasses);
+
}
if (PrintBreakpoints) {
@@ -678,7 +679,7 @@ int main(int argc, char **argv) {
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ sys::fs::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index 45ccb62..61252a4 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -22,13 +22,232 @@
using namespace llvm;
+// There is similar code in yaml2coff, but with some slight COFF-specific
+// variations like different initial state. Might be able to deduplicate
+// some day, but also want to make sure that the Mach-O use case is served.
+//
+// This class has a deliberately small interface, since a lot of
+// implementation variation is possible.
+//
+// TODO: Use an ordered container with a suffix-based comparison in order
+// to deduplicate suffixes. std::map<> with a custom comparator is likely
+// to be the simplest implementation, but a suffix trie could be more
+// suitable for the job.
+namespace {
+class StringTableBuilder {
+ /// \brief Indices of strings currently present in `Buf`.
+ StringMap<unsigned> StringIndices;
+ /// \brief The contents of the string table as we build it.
+ std::string Buf;
+public:
+ StringTableBuilder() {
+ Buf.push_back('\0');
+ }
+ /// \returns Index of string in string table.
+ unsigned addString(StringRef S) {
+ StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S);
+ unsigned &I = Entry.getValue();
+ if (I != 0)
+ return I;
+ I = Buf.size();
+ Buf.append(S.begin(), S.end());
+ Buf.push_back('\0');
+ return I;
+ }
+ size_t size() const {
+ return Buf.size();
+ }
+ void writeToStream(raw_ostream &OS) {
+ OS.write(Buf.data(), Buf.size());
+ }
+};
+} // end anonymous namespace
+
+// This class is used to build up a contiguous binary blob while keeping
+// track of an offset in the output (which notionally begins at
+// `InitialOffset`).
+namespace {
+class ContiguousBlobAccumulator {
+ const uint64_t InitialOffset;
+ SmallVector<char, 128> Buf;
+ raw_svector_ostream OS;
+
+ /// \returns The new offset.
+ uint64_t padToAlignment(unsigned Align) {
+ uint64_t CurrentOffset = InitialOffset + OS.tell();
+ uint64_t AlignedOffset = RoundUpToAlignment(CurrentOffset, Align);
+ for (; CurrentOffset != AlignedOffset; ++CurrentOffset)
+ OS.write('\0');
+ return AlignedOffset; // == CurrentOffset;
+ }
+
+public:
+ ContiguousBlobAccumulator(uint64_t InitialOffset_)
+ : InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
+ template <class Integer>
+ raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align = 16) {
+ Offset = padToAlignment(Align);
+ return OS;
+ }
+ void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
+};
+} // end anonymous namespace
+
+// Used to keep track of section names, so that in the YAML file sections
+// can be referenced by name instead of by index.
+namespace {
+class SectionNameToIdxMap {
+ StringMap<int> Map;
+public:
+ /// \returns true if name is already present in the map.
+ bool addName(StringRef SecName, unsigned i) {
+ StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1);
+ if (Entry.getValue() != -1)
+ return true;
+ Entry.setValue((int)i);
+ return false;
+ }
+ /// \returns true if name is not present in the map
+ bool lookupSection(StringRef SecName, unsigned &Idx) const {
+ StringMap<int>::const_iterator I = Map.find(SecName);
+ if (I == Map.end())
+ return true;
+ Idx = I->getValue();
+ return false;
+ }
+};
+} // end anonymous namespace
+
+template <class T>
+static size_t vectorDataSize(const std::vector<T> &Vec) {
+ return Vec.size() * sizeof(T);
+}
+
+template <class T>
+static void writeVectorData(raw_ostream &OS, const std::vector<T> &Vec) {
+ OS.write((const char *)Vec.data(), vectorDataSize(Vec));
+}
+
+template <class T>
+static void zero(T &Obj) {
+ memset(&Obj, 0, sizeof(Obj));
+}
+
+/// \brief Create a string table in `SHeader`, which we assume is already
+/// zero'd.
+template <class Elf_Shdr>
+static void createStringTableSectionHeader(Elf_Shdr &SHeader,
+ StringTableBuilder &STB,
+ ContiguousBlobAccumulator &CBA) {
+ SHeader.sh_type = ELF::SHT_STRTAB;
+ STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
+ SHeader.sh_size = STB.size();
+ SHeader.sh_addralign = 1;
+}
+
+namespace {
+/// \brief "Single point of truth" for the ELF file construction.
+/// TODO: This class still has a ways to go before it is truly a "single
+/// point of truth".
template <class ELFT>
-static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
- const ELFYAML::FileHeader &Hdr = Doc.Header;
+class ELFState {
+ /// \brief The future ".strtab" section.
+ StringTableBuilder DotStrtab;
+ /// \brief The section number of the ".strtab" section.
+ unsigned DotStrtabSecNo;
+ /// \brief The accumulated contents of all sections so far.
+ ContiguousBlobAccumulator &SectionContentAccum;
+ typedef typename object::ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
+ /// \brief The ELF file header.
+ Elf_Ehdr &Header;
+
+ SectionNameToIdxMap &SN2I;
+
+public:
+
+ ELFState(Elf_Ehdr &Header_, ContiguousBlobAccumulator &Accum,
+ unsigned DotStrtabSecNo_, SectionNameToIdxMap &SN2I_)
+ : DotStrtab(), DotStrtabSecNo(DotStrtabSecNo_),
+ SectionContentAccum(Accum), Header(Header_), SN2I(SN2I_) {}
+
+ unsigned getDotStrTabSecNo() const { return DotStrtabSecNo; }
+ StringTableBuilder &getStringTable() { return DotStrtab; }
+ ContiguousBlobAccumulator &getSectionContentAccum() {
+ return SectionContentAccum;
+ }
+ SectionNameToIdxMap &getSN2I() { return SN2I; }
+};
+} // end anonymous namespace
+
+// FIXME: At this point it is fairly clear that we need to refactor these
+// static functions into methods of a class sharing some typedefs. These
+// ELF type names are insane.
+template <class ELFT>
+static void
+addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, ELFState<ELFT> &State,
+ std::vector<typename object::ELFObjectFile<ELFT>::Elf_Sym> &Syms,
+ unsigned SymbolBinding) {
+ typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
+ for (unsigned i = 0, e = Symbols.size(); i != e; ++i) {
+ const ELFYAML::Symbol &Sym = Symbols[i];
+ Elf_Sym Symbol;
+ zero(Symbol);
+ if (!Sym.Name.empty())
+ Symbol.st_name = State.getStringTable().addString(Sym.Name);
+ Symbol.setBindingAndType(SymbolBinding, Sym.Type);
+ if (!Sym.Section.empty()) {
+ unsigned Index;
+ if (State.getSN2I().lookupSection(Sym.Section, Index)) {
+ errs() << "error: Unknown section referenced: '" << Sym.Section
+ << "' by YAML symbol " << Sym.Name << ".\n";
+ exit(1);
+ }
+ Symbol.st_shndx = Index;
+ } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
+ Symbol.st_value = Sym.Value;
+ Symbol.st_size = Sym.Size;
+ Syms.push_back(Symbol);
+ }
+}
+
+template <class ELFT>
+static void handleSymtabSectionHeader(
+ const ELFYAML::LocalGlobalWeakSymbols &Symbols, ELFState<ELFT> &State,
+ typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) {
+
+ typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
+ SHeader.sh_type = ELF::SHT_SYMTAB;
+ SHeader.sh_link = State.getDotStrTabSecNo();
+ // One greater than symbol table index of the last local symbol.
+ SHeader.sh_info = Symbols.Local.size() + 1;
+ SHeader.sh_entsize = sizeof(Elf_Sym);
+
+ std::vector<Elf_Sym> Syms;
+ {
+ // Ensure STN_UNDEF is present
+ Elf_Sym Sym;
+ zero(Sym);
+ Syms.push_back(Sym);
+ }
+ addSymbols(Symbols.Local, State, Syms, ELF::STB_LOCAL);
+ addSymbols(Symbols.Global, State, Syms, ELF::STB_GLOBAL);
+ addSymbols(Symbols.Weak, State, Syms, ELF::STB_WEAK);
+
+ ContiguousBlobAccumulator &CBA = State.getSectionContentAccum();
+ writeVectorData(CBA.getOSAndAlignedOffset(SHeader.sh_offset), Syms);
+ SHeader.sh_size = vectorDataSize(Syms);
+}
+
+template <class ELFT>
+static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
using namespace llvm::ELF;
- using namespace llvm::object;
- typename ELFObjectFile<ELFT>::Elf_Ehdr Header;
- memset(&Header, 0, sizeof(Header));
+ typedef typename object::ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
+ typedef typename object::ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
+
+ const ELFYAML::FileHeader &Hdr = Doc.Header;
+
+ Elf_Ehdr Header;
+ zero(Header);
Header.e_ident[EI_MAG0] = 0x7f;
Header.e_ident[EI_MAG1] = 'E';
Header.e_ident[EI_MAG2] = 'L';
@@ -36,22 +255,120 @@ static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
-
Header.e_ident[EI_VERSION] = EV_CURRENT;
-
- // TODO: Implement ELF_ELFOSABI enum.
- Header.e_ident[EI_OSABI] = ELFOSABI_NONE;
- // TODO: Implement ELF_ABIVERSION enum.
+ Header.e_ident[EI_OSABI] = Hdr.OSABI;
Header.e_ident[EI_ABIVERSION] = 0;
Header.e_type = Hdr.Type;
Header.e_machine = Hdr.Machine;
Header.e_version = EV_CURRENT;
Header.e_entry = Hdr.Entry;
- Header.e_ehsize = sizeof(Header);
+ Header.e_ehsize = sizeof(Elf_Ehdr);
+
+ // TODO: Flesh out section header support.
+ // TODO: Program headers.
- // TODO: Section headers and program headers.
+ Header.e_shentsize = sizeof(Elf_Shdr);
+ // Immediately following the ELF header.
+ Header.e_shoff = sizeof(Header);
+ const std::vector<ELFYAML::Section> &Sections = Doc.Sections;
+ // "+ 4" for
+ // - SHT_NULL entry (placed first, i.e. 0'th entry)
+ // - symbol table (.symtab) (placed third to last)
+ // - string table (.strtab) (placed second to last)
+ // - section header string table. (placed last)
+ Header.e_shnum = Sections.size() + 4;
+ // Place section header string table last.
+ Header.e_shstrndx = Header.e_shnum - 1;
+ const unsigned DotStrtabSecNo = Header.e_shnum - 2;
+
+ // XXX: This offset is tightly coupled with the order that we write
+ // things to `OS`.
+ const size_t SectionContentBeginOffset =
+ Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
+ ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
+ SectionNameToIdxMap SN2I;
+ for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+ StringRef Name = Sections[i].Name;
+ if (Name.empty())
+ continue;
+ // "+ 1" to take into account the SHT_NULL entry.
+ if (SN2I.addName(Name, i + 1)) {
+ errs() << "error: Repeated section name: '" << Name
+ << "' at YAML section number " << i << ".\n";
+ return 1;
+ }
+ }
+
+ ELFState<ELFT> State(Header, CBA, DotStrtabSecNo, SN2I);
+
+ StringTableBuilder SHStrTab;
+ std::vector<Elf_Shdr> SHeaders;
+ {
+ // Ensure SHN_UNDEF entry is present. An all-zero section header is a
+ // valid SHN_UNDEF entry since SHT_NULL == 0.
+ Elf_Shdr SHdr;
+ zero(SHdr);
+ SHeaders.push_back(SHdr);
+ }
+ for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+ const ELFYAML::Section &Sec = Sections[i];
+ Elf_Shdr SHeader;
+ zero(SHeader);
+ SHeader.sh_name = SHStrTab.addString(Sec.Name);
+ SHeader.sh_type = Sec.Type;
+ SHeader.sh_flags = Sec.Flags;
+ SHeader.sh_addr = Sec.Address;
+
+ Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
+ SHeader.sh_size = Sec.Content.binary_size();
+
+ if (!Sec.Link.empty()) {
+ unsigned Index;
+ if (SN2I.lookupSection(Sec.Link, Index)) {
+ errs() << "error: Unknown section referenced: '" << Sec.Link
+ << "' at YAML section number " << i << ".\n";
+ return 1;
+ }
+ SHeader.sh_link = Index;
+ }
+ SHeader.sh_info = 0;
+ SHeader.sh_addralign = Sec.AddressAlign;
+ SHeader.sh_entsize = 0;
+ SHeaders.push_back(SHeader);
+ }
+
+ // .symtab section.
+ Elf_Shdr SymtabSHeader;
+ zero(SymtabSHeader);
+ SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab"));
+ handleSymtabSectionHeader<ELFT>(Doc.Symbols, State, SymtabSHeader);
+ SHeaders.push_back(SymtabSHeader);
+
+ // .strtab string table header.
+ Elf_Shdr DotStrTabSHeader;
+ zero(DotStrTabSHeader);
+ DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
+ createStringTableSectionHeader(DotStrTabSHeader, State.getStringTable(), CBA);
+ SHeaders.push_back(DotStrTabSHeader);
+
+ // Section header string table header.
+ Elf_Shdr SHStrTabSHeader;
+ zero(SHStrTabSHeader);
+ createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA);
+ SHeaders.push_back(SHStrTabSHeader);
OS.write((const char *)&Header, sizeof(Header));
+ writeVectorData(OS, SHeaders);
+ CBA.writeBlobToStream(OS);
+ return 0;
+}
+
+static bool is64Bit(const ELFYAML::Object &Doc) {
+ return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
+}
+
+static bool isLittleEndian(const ELFYAML::Object &Doc) {
+ return Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
}
int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
@@ -62,17 +379,20 @@ int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
errs() << "yaml2obj: Failed to parse YAML file!\n";
return 1;
}
- if (Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) {
- if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
- writeELF<object::ELFType<support::little, 8, true> >(outs(), Doc);
+ using object::ELFType;
+ typedef ELFType<support::little, 8, true> LE64;
+ typedef ELFType<support::big, 8, true> BE64;
+ typedef ELFType<support::little, 4, false> LE32;
+ typedef ELFType<support::big, 4, false> BE32;
+ if (is64Bit(Doc)) {
+ if (isLittleEndian(Doc))
+ return writeELF<LE64>(outs(), Doc);
else
- writeELF<object::ELFType<support::big, 8, true> >(outs(), Doc);
+ return writeELF<BE64>(outs(), Doc);
} else {
- if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
- writeELF<object::ELFType<support::little, 4, false> >(outs(), Doc);
+ if (isLittleEndian(Doc))
+ return writeELF<LE32>(outs(), Doc);
else
- writeELF<object::ELFType<support::big, 4, false> >(outs(), Doc);
+ return writeELF<BE32>(outs(), Doc);
}
-
- return 0;
}