summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt14
-rw-r--r--tools/LLVMBuild.txt2
-rw-r--r--tools/Makefile2
-rw-r--r--tools/bugpoint-passes/CMakeLists.txt8
-rw-r--r--tools/bugpoint-passes/TestPasses.cpp8
-rw-r--r--tools/bugpoint/BugDriver.cpp4
-rw-r--r--tools/bugpoint/BugDriver.h2
-rw-r--r--tools/bugpoint/CMakeLists.txt32
-rw-r--r--tools/bugpoint/CrashDebugger.cpp34
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp2
-rw-r--r--tools/bugpoint/ExtractFunction.cpp7
-rw-r--r--tools/bugpoint/LLVMBuild.txt2
-rw-r--r--tools/bugpoint/Makefile5
-rw-r--r--tools/bugpoint/Miscompilation.cpp31
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp4
-rw-r--r--tools/bugpoint/ToolRunner.cpp96
-rw-r--r--tools/bugpoint/ToolRunner.h34
-rw-r--r--tools/bugpoint/bugpoint.cpp36
-rw-r--r--tools/gold/CMakeLists.txt30
-rw-r--r--tools/gold/gold-plugin.cpp14
-rw-r--r--tools/llc/Android.mk4
-rw-r--r--tools/llc/CMakeLists.txt17
-rw-r--r--tools/llc/Makefile3
-rw-r--r--tools/llc/llc.cpp67
-rw-r--r--tools/lli/CMakeLists.txt18
-rw-r--r--tools/lli/ChildTarget/CMakeLists.txt9
-rw-r--r--tools/lli/ChildTarget/ChildTarget.cpp96
-rw-r--r--tools/lli/ChildTarget/Makefile4
-rw-r--r--tools/lli/ChildTarget/Unix/ChildTarget.inc166
-rw-r--r--tools/lli/ChildTarget/Windows/ChildTarget.inc44
-rw-r--r--tools/lli/RPCChannel.h49
-rw-r--r--tools/lli/RemoteMemoryManager.cpp12
-rw-r--r--tools/lli/RemoteMemoryManager.h42
-rw-r--r--tools/lli/RemoteTarget.cpp39
-rw-r--r--tools/lli/RemoteTarget.h38
-rw-r--r--tools/lli/RemoteTargetExternal.cpp333
-rw-r--r--tools/lli/RemoteTargetExternal.h97
-rw-r--r--tools/lli/RemoteTargetMessage.h54
-rw-r--r--tools/lli/Unix/RPCChannel.inc (renamed from tools/lli/Unix/RemoteTargetExternal.inc)58
-rw-r--r--tools/lli/Windows/RPCChannel.inc29
-rw-r--r--tools/lli/Windows/RemoteTargetExternal.inc35
-rw-r--r--tools/lli/lli.cpp208
-rw-r--r--tools/llvm-ar/CMakeLists.txt9
-rw-r--r--tools/llvm-ar/llvm-ar.cpp205
-rw-r--r--tools/llvm-as/CMakeLists.txt7
-rw-r--r--tools/llvm-as/llvm-as.cpp17
-rw-r--r--tools/llvm-bcanalyzer/CMakeLists.txt5
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp5
-rw-r--r--tools/llvm-c-test/CMakeLists.txt11
-rw-r--r--tools/llvm-config/BuildVariables.inc.in4
-rw-r--r--tools/llvm-config/CMakeLists.txt5
-rw-r--r--tools/llvm-config/Makefile10
-rw-r--r--tools/llvm-config/llvm-config.cpp85
-rw-r--r--tools/llvm-cov/llvm-cov.cpp98
-rw-r--r--tools/llvm-diff/CMakeLists.txt6
-rw-r--r--tools/llvm-diff/DiffConsumer.h10
-rw-r--r--tools/llvm-diff/DifferenceEngine.cpp4
-rw-r--r--tools/llvm-dis/CMakeLists.txt6
-rw-r--r--tools/llvm-dis/llvm-dis.cpp23
-rw-r--r--tools/llvm-dwarfdump/CMakeLists.txt1
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp15
-rw-r--r--tools/llvm-extract/CMakeLists.txt8
-rw-r--r--tools/llvm-extract/llvm-extract.cpp14
-rw-r--r--tools/llvm-jitlistener/llvm-jitlistener.cpp14
-rw-r--r--tools/llvm-link/Android.mk4
-rw-r--r--tools/llvm-link/CMakeLists.txt8
-rw-r--r--tools/llvm-link/llvm-link.cpp18
-rw-r--r--tools/llvm-lto/CMakeLists.txt8
-rw-r--r--tools/llvm-lto/llvm-lto.cpp29
-rw-r--r--tools/llvm-mc/CMakeLists.txt7
-rw-r--r--tools/llvm-mc/Disassembler.cpp16
-rw-r--r--tools/llvm-mc/llvm-mc.cpp58
-rw-r--r--tools/llvm-mcmarkup/llvm-mcmarkup.cpp5
-rw-r--r--tools/llvm-nm/CMakeLists.txt5
-rw-r--r--tools/llvm-nm/llvm-nm.cpp822
-rw-r--r--tools/llvm-objdump/CMakeLists.txt3
-rw-r--r--tools/llvm-objdump/COFFDump.cpp427
-rw-r--r--tools/llvm-objdump/MachODump.cpp80
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp385
-rw-r--r--tools/llvm-profdata/CMakeLists.txt5
-rw-r--r--tools/llvm-profdata/LLVMBuild.txt22
-rw-r--r--tools/llvm-profdata/Makefile17
-rw-r--r--tools/llvm-profdata/llvm-profdata.cpp191
-rw-r--r--tools/llvm-readobj/ARMAttributeParser.cpp639
-rw-r--r--tools/llvm-readobj/ARMAttributeParser.h124
-rw-r--r--tools/llvm-readobj/ARMEHABIPrinter.h557
-rw-r--r--tools/llvm-readobj/CMakeLists.txt6
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp497
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp119
-rw-r--r--tools/llvm-readobj/Error.cpp8
-rw-r--r--tools/llvm-readobj/Error.h4
-rw-r--r--tools/llvm-readobj/MachODumper.cpp181
-rw-r--r--tools/llvm-readobj/ObjDumper.cpp2
-rw-r--r--tools/llvm-readobj/ObjDumper.h22
-rw-r--r--tools/llvm-readobj/StreamWriter.h15
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp34
-rw-r--r--tools/llvm-readobj/llvm-readobj.h2
-rw-r--r--tools/llvm-rtdyld/CMakeLists.txt7
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp31
-rw-r--r--tools/llvm-shlib/Makefile13
-rw-r--r--tools/llvm-size/CMakeLists.txt5
-rw-r--r--tools/llvm-size/llvm-size.cpp73
-rw-r--r--tools/llvm-stress/CMakeLists.txt7
-rw-r--r--tools/llvm-stress/Makefile3
-rw-r--r--tools/llvm-stress/llvm-stress.cpp62
-rw-r--r--tools/llvm-symbolizer/CMakeLists.txt1
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp131
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.h5
-rw-r--r--tools/llvm-symbolizer/llvm-symbolizer.cpp41
-rw-r--r--tools/lto/CMakeLists.txt49
-rw-r--r--tools/lto/Makefile14
-rw-r--r--tools/lto/lto.cpp80
-rw-r--r--tools/lto/lto.exports6
-rw-r--r--tools/macho-dump/CMakeLists.txt5
-rw-r--r--tools/macho-dump/macho-dump.cpp28
-rw-r--r--tools/msbuild/CMakeLists.txt72
-rw-r--r--tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in4
-rw-r--r--tools/msbuild/install.bat42
-rw-r--r--tools/msbuild/uninstall.bat50
-rw-r--r--tools/obj2yaml/CMakeLists.txt7
-rw-r--r--tools/obj2yaml/coff2yaml.cpp134
-rw-r--r--tools/obj2yaml/obj2yaml.cpp5
-rw-r--r--tools/opt/AnalysisWrappers.cpp31
-rw-r--r--tools/opt/Android.mk4
-rw-r--r--tools/opt/BreakpointPrinter.cpp82
-rw-r--r--tools/opt/BreakpointPrinter.h25
-rw-r--r--tools/opt/CMakeLists.txt36
-rw-r--r--tools/opt/GraphPrinters.cpp11
-rw-r--r--tools/opt/LLVMBuild.txt2
-rw-r--r--tools/opt/Makefile5
-rw-r--r--tools/opt/NewPMDriver.cpp81
-rw-r--r--tools/opt/NewPMDriver.h55
-rw-r--r--tools/opt/PassPrinters.cpp260
-rw-r--r--tools/opt/PassPrinters.h47
-rw-r--r--tools/opt/Passes.cpp209
-rw-r--r--tools/opt/Passes.h57
-rw-r--r--tools/opt/PrintSCC.cpp25
-rw-r--r--tools/opt/opt.cpp415
-rw-r--r--tools/yaml2obj/CMakeLists.txt7
-rw-r--r--tools/yaml2obj/yaml2coff.cpp82
-rw-r--r--tools/yaml2obj/yaml2elf.cpp336
-rw-r--r--tools/yaml2obj/yaml2obj.cpp3
142 files changed, 6216 insertions, 3103 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 12e10fd..13b7f5a 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,9 +1,13 @@
-# NOTE: The tools are organized into groups of four consisting of one large and
-# three small executables. This is done to minimize memory load in parallel
-# builds. Please retain this ordering.
-
add_llvm_tool_subdirectory(llvm-config)
+# Build polly before the tools: the tools link against polly when
+# LINK_POLLY_INTO_TOOLS is set.
+if(WITH_POLLY)
+ add_llvm_external_project(polly)
+else(WITH_POLLY)
+ list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${LLVM_MAIN_SRC_DIR}/tools/polly")
+endif(WITH_POLLY)
+
add_llvm_tool_subdirectory(opt)
add_llvm_tool_subdirectory(llvm-as)
add_llvm_tool_subdirectory(llvm-dis)
@@ -15,6 +19,7 @@ add_llvm_tool_subdirectory(llvm-nm)
add_llvm_tool_subdirectory(llvm-size)
add_llvm_tool_subdirectory(llvm-cov)
+add_llvm_tool_subdirectory(llvm-profdata)
add_llvm_tool_subdirectory(llvm-link)
add_llvm_tool_subdirectory(lli)
@@ -69,7 +74,6 @@ add_llvm_external_project(clang)
if( NOT LLVM_INCLUDE_TOOLS STREQUAL "bootstrap-only" )
add_llvm_external_project(lld)
add_llvm_external_project(lldb)
- add_llvm_external_project(polly)
# Automatically add remaining sub-directories containing a 'CMakeLists.txt'
# file as external projects.
diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt
index 93b8d98..1b537a3 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-lto llvm-mc llvm-nm llvm-objdump 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-lto llvm-mc llvm-nm llvm-objdump llvm-profdata llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
[component_0]
type = Group
diff --git a/tools/Makefile b/tools/Makefile
index be87254..2b8c32e 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -31,7 +31,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis llc llvm-ar llvm-nm llvm-link \
lli llvm-extract llvm-mc bugpoint llvm-bcanalyzer llvm-diff \
macho-dump llvm-objdump llvm-readobj llvm-rtdyld \
llvm-dwarfdump llvm-cov llvm-size llvm-stress llvm-mcmarkup \
- llvm-symbolizer obj2yaml yaml2obj llvm-c-test
+ llvm-profdata llvm-symbolizer obj2yaml yaml2obj llvm-c-test
# If Intel JIT Events support is configured, build an extra tool to test it.
ifeq ($(USE_INTEL_JITEVENTS), 1)
diff --git a/tools/bugpoint-passes/CMakeLists.txt b/tools/bugpoint-passes/CMakeLists.txt
index 05f190a..b7ee626 100644
--- a/tools/bugpoint-passes/CMakeLists.txt
+++ b/tools/bugpoint-passes/CMakeLists.txt
@@ -2,6 +2,14 @@ if( NOT LLVM_BUILD_TOOLS )
set(EXCLUDE_FROM_ALL ON)
endif()
+# If we don't need RTTI or EH, there's no reason to export anything
+# from this plugin.
+if( NOT LLVM_REQUIRES_RTTI )
+ if( NOT LLVM_REQUIRES_EH )
+ set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bugpoint.exports)
+ endif()
+endif()
+
add_llvm_loadable_module( BugpointPasses
TestPasses.cpp
)
diff --git a/tools/bugpoint-passes/TestPasses.cpp b/tools/bugpoint-passes/TestPasses.cpp
index 118c98a..ed54e9f 100644
--- a/tools/bugpoint-passes/TestPasses.cpp
+++ b/tools/bugpoint-passes/TestPasses.cpp
@@ -14,9 +14,9 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
+#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
-#include "llvm/InstVisitor.h"
#include "llvm/Pass.h"
using namespace llvm;
@@ -29,11 +29,11 @@ namespace {
static char ID; // Pass ID, replacement for typeid
CrashOnCalls() : BasicBlockPass(ID) {}
private:
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
- bool runOnBasicBlock(BasicBlock &BB) {
+ bool runOnBasicBlock(BasicBlock &BB) override {
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
if (isa<CallInst>(*I))
abort();
@@ -56,7 +56,7 @@ namespace {
static char ID; // Pass ID, replacement for typeid
DeleteCalls() : BasicBlockPass(ID) {}
private:
- bool runOnBasicBlock(BasicBlock &BB) {
+ bool runOnBasicBlock(BasicBlock &BB) override {
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
if (CallInst *CI = dyn_cast<CallInst>(I)) {
if (!CI->use_empty())
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index a5436ba..2d1b903 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -17,7 +17,7 @@
#include "ToolRunner.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
-#include "llvm/Linker.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
@@ -122,7 +122,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
outs() << "Read input file : '" << Filenames[0] << "'\n";
for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
- OwningPtr<Module> M(ParseInputFile(Filenames[i], Context));
+ std::unique_ptr<Module> M(ParseInputFile(Filenames[i], Context));
if (M.get() == 0) return true;
outs() << "Linking in input file: '" << Filenames[i] << "'\n";
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index 27b37f4..c01bbe5 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -16,7 +16,7 @@
#ifndef BUGDRIVER_H
#define BUGDRIVER_H
-#include "llvm/ADT/ValueMap.h"
+#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <string>
#include <vector>
diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt
index 0000d97..d71e097 100644
--- a/tools/bugpoint/CMakeLists.txt
+++ b/tools/bugpoint/CMakeLists.txt
@@ -1,5 +1,24 @@
-set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo
- linker bitreader bitwriter irreader vectorize objcarcopts)
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ BitWriter
+ CodeGen
+ Core
+ IPA
+ IPO
+ IRReader
+ InstCombine
+ Instrumentation
+ Linker
+ ObjCARCOpts
+ ScalarOpts
+ Support
+ Target
+ TransformUtils
+ Vectorize
+ )
+
+# Support plugins.
+set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(bugpoint
BugDriver.cpp
@@ -13,3 +32,12 @@ add_llvm_tool(bugpoint
bugpoint.cpp
)
set_target_properties(bugpoint PROPERTIES ENABLE_EXPORTS 1)
+
+if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
+ target_link_libraries(bugpoint Polly)
+ if(POLLY_LINK_LIBS)
+ foreach(lib ${POLLY_LINK_LIBS})
+ target_link_libraries(bugpoint ${lib})
+ endforeach(lib)
+ endif(POLLY_LINK_LIBS)
+endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index b90fc61..bdaa6c9 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -15,15 +15,15 @@
#include "ListReducer.h"
#include "ToolRunner.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Analysis/Verifier.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Transforms/Scalar.h"
@@ -52,9 +52,9 @@ namespace llvm {
// running the "Kept" passes fail when run on the output of the "removed"
// passes. If we return true, we update the current module of bugpoint.
//
- virtual TestResult doTest(std::vector<std::string> &Removed,
- std::vector<std::string> &Kept,
- std::string &Error);
+ TestResult doTest(std::vector<std::string> &Removed,
+ std::vector<std::string> &Kept,
+ std::string &Error) override;
};
}
@@ -110,9 +110,9 @@ namespace {
bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix,
- std::vector<GlobalVariable*> &Kept,
- std::string &Error) {
+ TestResult doTest(std::vector<GlobalVariable*> &Prefix,
+ std::vector<GlobalVariable*> &Kept,
+ std::string &Error) override {
if (!Kept.empty() && TestGlobalVariables(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestGlobalVariables(Prefix))
@@ -180,9 +180,9 @@ namespace {
bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- virtual TestResult doTest(std::vector<Function*> &Prefix,
- std::vector<Function*> &Kept,
- std::string &Error) {
+ TestResult doTest(std::vector<Function*> &Prefix,
+ std::vector<Function*> &Kept,
+ std::string &Error) override {
if (!Kept.empty() && TestFuncs(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestFuncs(Prefix))
@@ -253,9 +253,9 @@ namespace {
bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix,
- std::vector<const BasicBlock*> &Kept,
- std::string &Error) {
+ TestResult doTest(std::vector<const BasicBlock*> &Prefix,
+ std::vector<const BasicBlock*> &Kept,
+ std::string &Error) override {
if (!Kept.empty() && TestBlocks(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestBlocks(Prefix))
@@ -362,9 +362,9 @@ namespace {
bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- virtual TestResult doTest(std::vector<const Instruction*> &Prefix,
- std::vector<const Instruction*> &Kept,
- std::string &Error) {
+ TestResult doTest(std::vector<const Instruction*> &Prefix,
+ std::vector<const Instruction*> &Kept,
+ std::string &Error) override {
if (!Kept.empty() && TestInsts(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestInsts(Prefix))
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index c05c8d7..609de03 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -404,7 +404,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
// Remove the intermediate C file
sys::fs::remove(OutputFile);
- return "./" + SharedObjectFile;
+ return SharedObjectFile;
}
/// createReferenceFile - calls compileProgram and then records the output
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index 2098928..8bcae8a 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -13,13 +13,12 @@
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/Writer.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
@@ -309,7 +308,7 @@ llvm::SplitFunctionsOutOfModule(Module *M,
for (unsigned i = 0, e = F.size(); i != e; ++i) {
Function *TNOF = cast<Function>(VMap[F[i]]);
DEBUG(errs() << "Removing function ");
- DEBUG(WriteAsOperand(errs(), TNOF, false));
+ DEBUG(TNOF->printAsOperand(errs(), false));
DEBUG(errs() << "\n");
TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
DeleteFunctionBody(TNOF); // Function is now external in this module!
@@ -330,7 +329,7 @@ llvm::SplitFunctionsOutOfModule(Module *M,
if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
errs() << "*** Error: when reducing functions, encountered "
"the global '";
- WriteAsOperand(errs(), GV, false);
+ GV->printAsOperand(errs(), false);
errs() << "' with an initializer that references blockaddresses "
"from safe function '" << SafeFn->getName()
<< "' and from test function '" << TestFn->getName() << "'.\n";
diff --git a/tools/bugpoint/LLVMBuild.txt b/tools/bugpoint/LLVMBuild.txt
index 0164355..dda8d62 100644
--- a/tools/bugpoint/LLVMBuild.txt
+++ b/tools/bugpoint/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = bugpoint
parent = Tools
-required_libraries = AsmParser BitReader BitWriter IRReader IPO Instrumentation Linker Scalar ObjCARC
+required_libraries = AsmParser BitReader BitWriter CodeGen IRReader IPO Instrumentation Linker Scalar ObjCARC
diff --git a/tools/bugpoint/Makefile b/tools/bugpoint/Makefile
index 2049321..174f8d2 100644
--- a/tools/bugpoint/Makefile
+++ b/tools/bugpoint/Makefile
@@ -10,6 +10,9 @@
LEVEL := ../..
TOOLNAME := bugpoint
LINK_COMPONENTS := asmparser instrumentation scalaropts ipo linker bitreader \
- bitwriter irreader vectorize objcarcopts
+ bitwriter irreader vectorize objcarcopts codegen
+
+# Support plugins.
+NO_DEAD_STRIP := 1
include $(LEVEL)/Makefile.common
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index 771ec34..fecae60 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -15,13 +15,13 @@
#include "BugDriver.h"
#include "ListReducer.h"
#include "ToolRunner.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/Config/config.h" // for HAVE_LINK_R
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
-#include "llvm/Linker.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
@@ -48,9 +48,9 @@ namespace {
public:
ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
- virtual TestResult doTest(std::vector<std::string> &Prefix,
- std::vector<std::string> &Suffix,
- std::string &Error);
+ TestResult doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Suffix,
+ std::string &Error) override;
};
}
@@ -128,8 +128,8 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
// Ok, so now we know that the prefix passes work, try running the suffix
// passes on the result of the prefix passes.
//
- OwningPtr<Module> PrefixOutput(ParseInputFile(BitcodeResult,
- BD.getContext()));
+ std::unique_ptr<Module> PrefixOutput(
+ ParseInputFile(BitcodeResult, BD.getContext()));
if (!PrefixOutput) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
<< BitcodeResult << "'!\n";
@@ -145,7 +145,8 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
<< "' passes compile correctly after the '"
<< getPassesString(Prefix) << "' passes: ";
- OwningPtr<Module> OriginalInput(BD.swapProgramIn(PrefixOutput.take()));
+ std::unique_ptr<Module> OriginalInput(
+ BD.swapProgramIn(PrefixOutput.release()));
if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/,
true/*quiet*/)) {
errs() << " Error running this sequence of passes"
@@ -168,7 +169,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
// Otherwise, we must not be running the bad pass anymore.
outs() << " yup.\n"; // No miscompilation!
// Restore orig program & free test.
- delete BD.swapProgramIn(OriginalInput.take());
+ delete BD.swapProgramIn(OriginalInput.release());
return NoFailure;
}
@@ -182,9 +183,9 @@ namespace {
std::string &))
: BD(bd), TestFn(F) {}
- virtual TestResult doTest(std::vector<Function*> &Prefix,
- std::vector<Function*> &Suffix,
- std::string &Error) {
+ TestResult doTest(std::vector<Function*> &Prefix,
+ std::vector<Function*> &Suffix,
+ std::string &Error) override {
if (!Suffix.empty()) {
bool Ret = TestFuncs(Suffix, Error);
if (!Error.empty())
@@ -467,9 +468,9 @@ namespace {
const std::vector<Function*> &Fns)
: BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
- virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
- std::vector<BasicBlock*> &Suffix,
- std::string &Error) {
+ TestResult doTest(std::vector<BasicBlock*> &Prefix,
+ std::vector<BasicBlock*> &Suffix,
+ std::string &Error) override {
if (!Suffix.empty()) {
bool Ret = TestFuncs(Suffix, Error);
if (!Error.empty())
diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp
index 20c609c..f91f493 100644
--- a/tools/bugpoint/OptimizerDriver.cpp
+++ b/tools/bugpoint/OptimizerDriver.cpp
@@ -16,10 +16,10 @@
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -71,7 +71,7 @@ bool BugDriver::writeProgramToFile(const std::string &Filename, int FD,
bool BugDriver::writeProgramToFile(const std::string &Filename,
const Module *M) const {
std::string ErrInfo;
- tool_output_file Out(Filename.c_str(), ErrInfo, sys::fs::F_Binary);
+ tool_output_file Out(Filename.c_str(), ErrInfo, sys::fs::F_None);
if (ErrInfo.empty())
return writeProgramToFileAux(Out, M);
return true;
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
index 254d997..f0fb4bf 100644
--- a/tools/bugpoint/ToolRunner.cpp
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -178,16 +178,16 @@ namespace {
if (Args) { ToolArgs = *Args; }
}
- 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,
- const std::vector<std::string> &SharedLibs =
- std::vector<std::string>(),
- unsigned Timeout = 0,
- unsigned MemoryLimit = 0);
+ 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,
+ const std::vector<std::string> &SharedLibs =
+ std::vector<std::string>(),
+ unsigned Timeout = 0,
+ unsigned MemoryLimit = 0) override;
};
}
@@ -294,22 +294,22 @@ namespace {
const std::string &CompilerCmd, std::vector<std::string> CompArgs) :
CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {}
- 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) {
+ void compileProgram(const std::string &Bitcode,
+ std::string *Error,
+ unsigned Timeout = 0,
+ unsigned MemoryLimit = 0) override;
+
+ 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) override {
*Error = "Execution not supported with -compile-custom";
return -1;
}
@@ -355,16 +355,16 @@ namespace {
const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) :
ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {}
- 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,
- const std::vector<std::string> &SharedLibs =
- std::vector<std::string>(),
- unsigned Timeout = 0,
- unsigned MemoryLimit = 0);
+ 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,
+ const std::vector<std::string> &SharedLibs =
+ std::vector<std::string>(),
+ unsigned Timeout = 0,
+ unsigned MemoryLimit = 0) override;
};
}
@@ -406,7 +406,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
// code borrowed from:
// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
static void lexCommand(std::string &Message, const std::string &CommandLine,
- std::string &CmdPath, std::vector<std::string> Args) {
+ std::string &CmdPath, std::vector<std::string> &Args) {
std::string Command = "";
std::string delimiters = " ";
@@ -584,17 +584,17 @@ namespace {
if (Args) { ToolArgs = *Args; }
}
- 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);
+ 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) override;
};
}
diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h
index bc2be46..38a5835 100644
--- a/tools/bugpoint/ToolRunner.h
+++ b/tools/bugpoint/ToolRunner.h
@@ -168,29 +168,29 @@ public:
/// 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);
+ void compileProgram(const std::string &Bitcode, std::string *Error,
+ unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
- 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);
+ 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) override;
/// 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,
- std::string &OutFile, std::string &Error,
- unsigned Timeout = 0,
- unsigned MemoryLimit = 0);
+ GCC::FileType OutputCode(const std::string &Bitcode,
+ std::string &OutFile, std::string &Error,
+ unsigned Timeout = 0,
+ unsigned MemoryLimit = 0) override;
};
} // End llvm namespace
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index 9bc592e..5c03b41 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -16,12 +16,12 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -34,7 +34,7 @@
using namespace llvm;
-static cl::opt<bool>
+static cl::opt<bool>
FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
"on program to find bugs"), cl::init(false));
@@ -63,24 +63,24 @@ static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
static cl::opt<bool>
-StandardCompileOpts("std-compile-opts",
+StandardCompileOpts("std-compile-opts",
cl::desc("Include the standard compile time optimizations"));
static cl::opt<bool>
-StandardLinkOpts("std-link-opts",
+StandardLinkOpts("std-link-opts",
cl::desc("Include the standard link time optimizations"));
static cl::opt<bool>
OptLevelO1("O1",
- cl::desc("Optimization level 1. Similar to llvm-gcc -O1"));
+ cl::desc("Optimization level 1. Identical to 'opt -O1'"));
static cl::opt<bool>
OptLevelO2("O2",
- cl::desc("Optimization level 2. Similar to llvm-gcc -O2"));
+ cl::desc("Optimization level 2. Identical to 'opt -O2'"));
static cl::opt<bool>
OptLevelO3("O3",
- cl::desc("Optimization level 3. Similar to llvm-gcc -O3"));
+ cl::desc("Optimization level 3. Identical to 'opt -O3'"));
static cl::opt<std::string>
OverrideTriple("mtriple", cl::desc("Override target triple for module"));
@@ -100,8 +100,8 @@ namespace {
BugDriver &D;
public:
AddToDriver(BugDriver &_D) : FunctionPassManager(0), D(_D) {}
-
- virtual void add(Pass *P) {
+
+ void add(Pass *P) override {
const void *ID = P->getPassID();
const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
D.addPass(PI->getPassArgument());
@@ -109,13 +109,19 @@ namespace {
};
}
+#ifdef LINK_POLLY_INTO_TOOLS
+namespace polly {
+void initializePollyPasses(llvm::PassRegistry &Registry);
+}
+#endif
+
int main(int argc, char **argv) {
#ifndef DEBUG_BUGPOINT
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
#endif
-
+
// Initialize passes
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
@@ -129,7 +135,11 @@ int main(int argc, char **argv) {
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
-
+
+#ifdef LINK_POLLY_INTO_TOOLS
+ polly::initializePollyPasses(Registry);
+#endif
+
cl::ParseCommandLineOptions(argc, argv,
"LLVM automatic testcase reducer. See\nhttp://"
"llvm.org/cmds/bugpoint.html"
@@ -158,7 +168,7 @@ int main(int argc, char **argv) {
BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit,
UseValgrind, Context);
if (D.addSources(InputFilenames)) return 1;
-
+
AddToDriver PM(D);
if (StandardCompileOpts) {
PassManagerBuilder Builder;
@@ -166,7 +176,7 @@ int main(int argc, char **argv) {
Builder.Inliner = createFunctionInliningPass();
Builder.populateModulePassManager(PM);
}
-
+
if (StandardLinkOpts) {
PassManagerBuilder Builder;
Builder.populateLTOPassManager(PM, /*Internalize=*/true,
diff --git a/tools/gold/CMakeLists.txt b/tools/gold/CMakeLists.txt
index 2cc132f..07a1e28 100644
--- a/tools/gold/CMakeLists.txt
+++ b/tools/gold/CMakeLists.txt
@@ -1,6 +1,8 @@
set(LLVM_BINUTILS_INCDIR "" CACHE PATH
"PATH to binutils/include containing plugin-api.h for gold plugin.")
+set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/gold.exports)
+
if( NOT LLVM_BINUTILS_INCDIR )
# Nothing to say.
elseif( NOT EXISTS "${LLVM_BINUTILS_INCDIR}/plugin-api.h" )
@@ -18,29 +20,7 @@ else()
gold-plugin.cpp
)
- # Makefile.rules contains a special cases for OpenBSD, Darwin and
- # Windows. We restrict ourselves to Linux for the time being.
- set(srcexp ${CMAKE_CURRENT_SOURCE_DIR}/gold.exports)
- add_custom_command(OUTPUT exportsfile
- COMMAND echo "{" > exportsfile
- COMMAND grep -q "\\<" ${srcexp} && echo " global:" >> exportsfile || :
- COMMAND sed -e "s/$/;/" -e "s/^/ /" < ${srcexp} >> exportsfile
- COMMAND echo " local: *;" >> exportsfile
- COMMAND echo "};" >> exportsfile
- DEPENDS ${srcexp}
- VERBATIM
- COMMENT "Creating export file for gold plugin")
- add_custom_target(gold_exports DEPENDS exportsfile)
- set_property(DIRECTORY APPEND
- PROPERTY ADDITIONAL_MAKE_CLEAN_FILES exportsfile)
-
- # Force re-linking when the exports file changes. Actually, it
- # forces recompilation of gold-plugin.cpp. The LINK_DEPENDS target
- # property only works for makefile-based generators.
- set_property(SOURCE gold-plugin.cpp APPEND PROPERTY
- OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/exportsfile)
-
- target_link_libraries(LLVMgold LTO
- -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/exportsfile)
- add_dependencies(LLVMgold gold_exports)
+ target_link_libraries(LLVMgold ${cmake_2_8_12_PRIVATE} LTO)
+
endif()
+
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index 0e3bad2..4726d82 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -13,10 +13,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H
-#include "plugin-api.h"
#include "llvm-c/lto.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -29,6 +27,7 @@
#include <cstring>
#include <fstream>
#include <list>
+#include <plugin-api.h>
#include <vector>
// Support Windows/MinGW crazyness.
@@ -38,6 +37,12 @@
# define read _read
#endif
+#ifndef LDPO_PIE
+// FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and
+// Precise and Debian Wheezy (binutils 2.23 is required)
+# define LDPO_PIE 3
+#endif
+
using namespace llvm;
namespace {
@@ -153,8 +158,7 @@ ld_plugin_status onload(ld_plugin_tv *tv) {
switch (tv->tv_u.tv_val) {
case LDPO_REL: // .o
case LDPO_DYN: // .so
- // FIXME: Replace 3 with LDPO_PIE once that is in a released binutils.
- case 3: // position independent executable
+ case LDPO_PIE: // position independent executable
output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
break;
case LDPO_EXEC: // .exe
@@ -241,7 +245,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
int *claimed) {
lto_module_t M;
const void *view;
- OwningPtr<MemoryBuffer> buffer;
+ std::unique_ptr<MemoryBuffer> buffer;
if (get_view) {
if (get_view(file->handle, &view) != LDPS_OK) {
(*message)(LDPL_ERROR, "Failed to get a view of %s", file->name);
diff --git a/tools/llc/Android.mk b/tools/llc/Android.mk
index 0d44444..2167fe3 100644
--- a/tools/llc/Android.mk
+++ b/tools/llc/Android.mk
@@ -106,6 +106,7 @@ ifeq (,$(filter $(TARGET_ARCH),$(LLVM_SUPPORTED_ARCH)))
$(warning TODO $(TARGET_ARCH): Enable llc build)
endif
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
include $(CLEAR_VARS)
LOCAL_MODULE := llc
@@ -126,9 +127,10 @@ LOCAL_STATIC_LIBRARIES += $(llvm_llc_STATIC_LIBRARIES)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
- libstlport
+ libc++
include $(LLVM_ROOT_PATH)/llvm.mk
include $(LLVM_DEVICE_BUILD_MK)
include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_EXECUTABLE)
+endif
diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt
index e5a5550..393d64c 100644
--- a/tools/llc/CMakeLists.txt
+++ b/tools/llc/CMakeLists.txt
@@ -1,5 +1,20 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser irreader)
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ AsmPrinter
+ CodeGen
+ Core
+ IRReader
+ MC
+ ScalarOpts
+ SelectionDAG
+ Support
+ Target
+ )
+
+# Support plugins.
+set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(llc
llc.cpp
)
+set_target_properties(llc PROPERTIES ENABLE_EXPORTS 1)
diff --git a/tools/llc/Makefile b/tools/llc/Makefile
index c24f378..71bce4d 100644
--- a/tools/llc/Makefile
+++ b/tools/llc/Makefile
@@ -11,5 +11,8 @@ LEVEL := ../..
TOOLNAME := llc
LINK_COMPONENTS := all-targets bitreader asmparser irreader
+# Support plugins.
+NO_DEAD_STRIP := 1
+
include $(LEVEL)/Makefile.common
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 6aac8ff..8fbdc49 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -14,13 +14,13 @@
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/SubtargetFeature.h"
@@ -58,6 +58,10 @@ TimeCompilations("time-compilations", cl::Hidden, cl::init(1u),
cl::value_desc("N"),
cl::desc("Repeat compilation N times for timing"));
+static cl::opt<bool>
+NoIntegratedAssembler("no-integrated-as", cl::Hidden,
+ cl::desc("Disable integrated assembler"));
+
// Determine optimization level.
static cl::opt<char>
OptLevel("O",
@@ -146,8 +150,8 @@ static tool_output_file *GetOutputStream(const char *TargetName,
// Open the file.
std::string error;
sys::fs::OpenFlags OpenFlags = sys::fs::F_None;
- if (Binary)
- OpenFlags |= sys::fs::F_Binary;
+ if (!Binary)
+ OpenFlags |= sys::fs::F_Text;
tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error,
OpenFlags);
if (!error.empty()) {
@@ -202,7 +206,7 @@ int main(int argc, char **argv) {
static int compileModule(char **argv, LLVMContext &Context) {
// Load the module to be compiled...
SMDiagnostic Err;
- OwningPtr<Module> M;
+ std::unique_ptr<Module> M;
Module *mod = 0;
Triple TheTriple;
@@ -259,38 +263,16 @@ static int compileModule(char **argv, LLVMContext &Context) {
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
- TargetOptions Options;
- Options.LessPreciseFPMADOption = EnableFPMAD;
- Options.NoFramePointerElim = DisableFPElim;
- Options.AllowFPOpFusion = FuseFPOps;
- Options.UnsafeFPMath = EnableUnsafeFPMath;
- Options.NoInfsFPMath = EnableNoInfsFPMath;
- Options.NoNaNsFPMath = EnableNoNaNsFPMath;
- Options.HonorSignDependentRoundingFPMathOption =
- EnableHonorSignDependentRoundingFPMath;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
- if (FloatABIForCalls != FloatABI::Default)
- Options.FloatABIType = FloatABIForCalls;
- Options.NoZerosInBSS = DontPlaceZerosInBSS;
- Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
- Options.DisableTailCalls = DisableTailCalls;
- Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.TrapFuncName = TrapFuncName;
- Options.PositionIndependentExecutable = EnablePIE;
- Options.EnableSegmentedStacks = SegmentedStacks;
- Options.UseInitArray = UseInitArray;
-
- OwningPtr<TargetMachine>
- target(TheTarget->createTargetMachine(TheTriple.getTriple(),
- MCPU, FeaturesStr, Options,
- RelocModel, CMModel, OLvl));
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+ Options.DisableIntegratedAS = NoIntegratedAssembler;
+
+ std::unique_ptr<TargetMachine> target(
+ TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
+ Options, RelocModel, CMModel, OLvl));
assert(target.get() && "Could not allocate target machine!");
assert(mod && "Should have exited after outputting help!");
TargetMachine &Target = *target.get();
- if (DisableDotLoc)
- Target.setMCUseLoc(false);
-
if (DisableCFI)
Target.setMCUseCFI(false);
@@ -300,14 +282,9 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (GenerateSoftFloatCalls)
FloatABIForCalls = FloatABI::Soft;
- // Disable .loc support for older OS X versions.
- if (TheTriple.isMacOSX() &&
- TheTriple.isMacOSXVersionLT(10, 6))
- Target.setMCUseLoc(false);
-
// Figure out where we are going to send the output.
- OwningPtr<tool_output_file> Out
- (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]));
+ std::unique_ptr<tool_output_file> Out(
+ GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]));
if (!Out) return 1;
// Build up all of the passes that we want to do to the module.
@@ -319,14 +296,10 @@ static int compileModule(char **argv, LLVMContext &Context) {
TLI->disableAllFunctions();
PM.add(TLI);
- // Add intenal analysis passes from the target machine.
- Target.addAnalysisPasses(PM);
-
// Add the target data from the target machine, if it exists, or the module.
- if (const DataLayout *TD = Target.getDataLayout())
- PM.add(new DataLayout(*TD));
- else
- PM.add(new DataLayout(mod));
+ if (const DataLayout *DL = Target.getDataLayout())
+ mod->setDataLayout(DL);
+ PM.add(new DataLayoutPass(mod));
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt
index 5f8c7c9..731b61a 100644
--- a/tools/lli/CMakeLists.txt
+++ b/tools/lli/CMakeLists.txt
@@ -1,8 +1,19 @@
-
-set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser irreader selectiondag native instrumentation)
-
add_subdirectory(ChildTarget)
+set(LLVM_LINK_COMPONENTS
+ CodeGen
+ Core
+ ExecutionEngine
+ IRReader
+ Instrumentation
+ Interpreter
+ JIT
+ MCJIT
+ SelectionDAG
+ Support
+ native
+ )
+
if( LLVM_USE_OPROFILE )
set(LLVM_LINK_COMPONENTS
${LLVM_LINK_COMPONENTS}
@@ -25,3 +36,4 @@ add_llvm_tool(lli
RemoteTarget.cpp
RemoteTargetExternal.cpp
)
+set_target_properties(lli PROPERTIES ENABLE_EXPORTS 1)
diff --git a/tools/lli/ChildTarget/CMakeLists.txt b/tools/lli/ChildTarget/CMakeLists.txt
index fd1ac24..9f88b2c 100644
--- a/tools/lli/ChildTarget/CMakeLists.txt
+++ b/tools/lli/ChildTarget/CMakeLists.txt
@@ -1,3 +1,8 @@
-add_llvm_tool(lli-child-target
+set(LLVM_LINK_COMPONENTS support)
+
+add_llvm_executable(lli-child-target
ChildTarget.cpp
- )
+ ../RemoteTarget.cpp
+)
+
+set_target_properties(lli-child-target PROPERTIES FOLDER "Misc")
diff --git a/tools/lli/ChildTarget/ChildTarget.cpp b/tools/lli/ChildTarget/ChildTarget.cpp
index 55fcae9..0d71b17 100644
--- a/tools/lli/ChildTarget/ChildTarget.cpp
+++ b/tools/lli/ChildTarget/ChildTarget.cpp
@@ -1,6 +1,8 @@
#include "llvm/Config/config.h"
-
+#include "../RPCChannel.h"
+#include "../RemoteTarget.h"
#include "../RemoteTargetMessage.h"
+#include "llvm/Support/Memory.h"
#include <assert.h>
#include <map>
#include <stdint.h>
@@ -11,36 +13,32 @@ using namespace llvm;
class LLIChildTarget {
public:
- ~LLIChildTarget(); // OS-specific destructor
void initialize();
LLIMessageType waitForIncomingMessage();
void handleMessage(LLIMessageType messageType);
+ RemoteTarget *RT;
+ RPCChannel RPC;
private:
// Incoming message handlers
void handleAllocateSpace();
void handleLoadSection(bool IsCode);
void handleExecute();
- void handleTerminate();
// Outgoing message handlers
void sendChildActive();
void sendAllocationResult(uint64_t Addr);
- void sendLoadComplete();
- void sendExecutionComplete(uint64_t Result);
+ void sendLoadStatus(uint32_t Status);
+ void sendExecutionComplete(int Result);
// OS-specific functions
void initializeConnection();
- int WriteBytes(const void *Data, size_t Size);
- int ReadBytes(void *Data, size_t Size);
- uint64_t allocate(uint32_t Alignment, uint32_t Size);
- void makeSectionExecutable(uint64_t Addr, uint32_t Size);
- void InvalidateInstructionCache(const void *Addr, size_t Len);
- void releaseMemory(uint64_t Addr, uint32_t Size);
-
- // Store a map of allocated buffers to sizes.
- typedef std::map<uint64_t, uint32_t> AllocMapType;
- AllocMapType m_AllocatedBufferMap;
+ int WriteBytes(const void *Data, size_t Size) {
+ return RPC.WriteBytes(Data, Size) ? Size : -1;
+ }
+ int ReadBytes(void *Data, size_t Size) {
+ return RPC.ReadBytes(Data, Size) ? Size : -1;
+ }
// Communication handles (OS-specific)
void *ConnectionData;
@@ -48,6 +46,7 @@ private:
int main() {
LLIChildTarget ThisChild;
+ ThisChild.RT = new RemoteTarget();
ThisChild.initialize();
LLIMessageType MsgType;
do {
@@ -55,12 +54,13 @@ int main() {
ThisChild.handleMessage(MsgType);
} while (MsgType != LLI_Terminate &&
MsgType != LLI_Error);
+ delete ThisChild.RT;
return 0;
}
// Public methods
void LLIChildTarget::initialize() {
- initializeConnection();
+ RPC.createClient();
sendChildActive();
}
@@ -86,7 +86,7 @@ void LLIChildTarget::handleMessage(LLIMessageType messageType) {
handleExecute();
break;
case LLI_Terminate:
- handleTerminate();
+ RT->stop();
break;
default:
// FIXME: Handle error!
@@ -99,6 +99,7 @@ void LLIChildTarget::handleAllocateSpace() {
// Read and verify the message data size.
uint32_t DataSize;
int rc = ReadBytes(&DataSize, 4);
+ (void)rc;
assert(rc == 4);
assert(DataSize == 8);
@@ -111,7 +112,8 @@ void LLIChildTarget::handleAllocateSpace() {
assert(rc == 4);
// Allocate the memory.
- uint64_t Addr = allocate(Alignment, AllocSize);
+ uint64_t Addr;
+ RT->allocateSpace(AllocSize, Alignment, Addr);
// Send AllocationResult message.
sendAllocationResult(Addr);
@@ -121,33 +123,36 @@ void LLIChildTarget::handleLoadSection(bool IsCode) {
// Read the message data size.
uint32_t DataSize;
int rc = ReadBytes(&DataSize, 4);
+ (void)rc;
assert(rc == 4);
// Read the target load address.
uint64_t Addr;
rc = ReadBytes(&Addr, 8);
assert(rc == 8);
-
size_t BufferSize = DataSize - 8;
- // FIXME: Verify that this is in allocated space
+ if (!RT->isAllocatedMemory(Addr, BufferSize))
+ return sendLoadStatus(LLI_Status_NotAllocated);
// Read section data into previously allocated buffer
- rc = ReadBytes((void*)Addr, DataSize - 8);
- assert(rc == (int)(BufferSize));
+ rc = ReadBytes((void*)Addr, BufferSize);
+ if (rc != (int)(BufferSize))
+ return sendLoadStatus(LLI_Status_IncompleteMsg);
// If IsCode, mark memory executable
if (IsCode)
- makeSectionExecutable(Addr, BufferSize);
+ sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize);
// Send MarkLoadComplete message.
- sendLoadComplete();
+ sendLoadStatus(LLI_Status_Success);
}
void LLIChildTarget::handleExecute() {
// Read the message data size.
uint32_t DataSize;
int rc = ReadBytes(&DataSize, 4);
+ (void)rc;
assert(rc == 4);
assert(DataSize == 8);
@@ -157,22 +162,11 @@ void LLIChildTarget::handleExecute() {
assert(rc == 8);
// Call function
- int Result;
- int (*fn)(void) = (int(*)(void))Addr;
- Result = fn();
+ int32_t Result = -1;
+ RT->executeCode(Addr, Result);
// Send ExecutionResult message.
- sendExecutionComplete((int64_t)Result);
-}
-
-void LLIChildTarget::handleTerminate() {
- // Release all allocated memory
- AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
- AllocMapType::iterator End = m_AllocatedBufferMap.end();
- for (AllocMapType::iterator It = Begin; It != End; ++It) {
- releaseMemory(It->first, It->second);
- }
- m_AllocatedBufferMap.clear();
+ sendExecutionComplete(Result);
}
// Outgoing message handlers
@@ -180,6 +174,7 @@ void LLIChildTarget::sendChildActive() {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_ChildActive;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
@@ -192,6 +187,7 @@ void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_AllocationResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
@@ -204,39 +200,45 @@ void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
assert(rc == 8);
}
-void LLIChildTarget::sendLoadComplete() {
+void LLIChildTarget::sendLoadStatus(uint32_t Status) {
// Write the message type.
- uint32_t MsgType = (uint32_t)LLI_LoadComplete;
+ uint32_t MsgType = (uint32_t)LLI_LoadResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
- uint32_t DataSize = 0;
+ uint32_t DataSize = 4;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4);
+
+ // Write the result.
+ rc = WriteBytes(&Status, 4);
+ assert(rc == 4);
}
-void LLIChildTarget::sendExecutionComplete(uint64_t Result) {
+void LLIChildTarget::sendExecutionComplete(int Result) {
// Write the message type.
uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
int rc = WriteBytes(&MsgType, 4);
+ (void)rc;
assert(rc == 4);
// Write the data size.
- uint32_t DataSize = 8;
+ uint32_t DataSize = 4;
rc = WriteBytes(&DataSize, 4);
assert(rc == 4);
// Write the result.
- rc = WriteBytes(&Result, 8);
- assert(rc == 8);
+ rc = WriteBytes(&Result, 4);
+ assert(rc == 4);
}
#ifdef LLVM_ON_UNIX
-#include "Unix/ChildTarget.inc"
+#include "../Unix/RPCChannel.inc"
#endif
#ifdef LLVM_ON_WIN32
-#include "Windows/ChildTarget.inc"
+#include "../Windows/RPCChannel.inc"
#endif
diff --git a/tools/lli/ChildTarget/Makefile b/tools/lli/ChildTarget/Makefile
index f77b144..6f4ddef 100644
--- a/tools/lli/ChildTarget/Makefile
+++ b/tools/lli/ChildTarget/Makefile
@@ -12,6 +12,8 @@ TOOLNAME := lli-child-target
include $(LEVEL)/Makefile.config
-LINK_COMPONENTS :=
+LINK_COMPONENTS := support
+
+SOURCES := ChildTarget.cpp ../RemoteTarget.cpp
include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/lli/ChildTarget/Unix/ChildTarget.inc b/tools/lli/ChildTarget/Unix/ChildTarget.inc
deleted file mode 100644
index cc95810..0000000
--- a/tools/lli/ChildTarget/Unix/ChildTarget.inc
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- ChildTarget.inc - Child process for external JIT execution for Unix -==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the Unix-specific parts of the ChildTarget class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#ifdef __APPLE__
-#include <mach/mach.h>
-#endif
-
-#if defined(__mips__)
-# if defined(__OpenBSD__)
-# include <mips64/sysarch.h>
-# else
-# include <sys/cachectl.h>
-# endif
-#endif
-
-#ifdef __APPLE__
-extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
-#else
-extern "C" void __clear_cache(void *, void*);
-#endif
-
-namespace {
-
-struct ConnectionData_t {
- int InputPipe;
- int OutputPipe;
-
- ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
-};
-
-} // namespace
-
-LLIChildTarget::~LLIChildTarget() {
- delete static_cast<ConnectionData_t *>(ConnectionData);
-}
-
-// OS-specific methods
-void LLIChildTarget::initializeConnection() {
- // Store the parent ends of the pipes
- ConnectionData = (void*)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
-}
-
-int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
- return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
-}
-
-int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
- return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
-}
-
-// The functions below duplicate functionality that is implemented in
-// Support/Memory.cpp with the goal of avoiding a dependency on any
-// llvm libraries.
-
-uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {
- if (!Alignment)
- Alignment = 16;
-
- static const size_t PageSize = getpagesize();
- const size_t NumPages = (Size+PageSize-1)/PageSize;
- Size = NumPages*PageSize;
-
- int fd = -1;
-#ifdef NEED_DEV_ZERO_FOR_MMAP
- static int zero_fd = open("/dev/zero", O_RDWR);
- if (zero_fd == -1)
- return 0;
- fd = zero_fd;
-#endif
-
- int MMFlags = MAP_PRIVATE |
-#ifdef HAVE_MMAP_ANONYMOUS
- MAP_ANONYMOUS
-#else
- MAP_ANON
-#endif
- ; // Ends statement above
-
- uint64_t Addr = (uint64_t)::mmap(0, Size, PROT_READ | PROT_WRITE, MMFlags, fd, 0);
- if (Addr == (uint64_t)MAP_FAILED)
- return 0;
-
- // Align the address.
- Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
-
- m_AllocatedBufferMap[Addr] = Size;
-
- // Return aligned address
- return Addr;
-}
-
-void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {
- // FIXME: We have to mark the memory as RWX because multiple code chunks may
- // be on the same page. The RemoteTarget interface should be changed to
- // work around that.
- int Result = ::mprotect((void*)Addr, Size, PROT_READ | PROT_WRITE | PROT_EXEC);
- if (Result != 0)
- InvalidateInstructionCache((const void *)Addr, Size);
-}
-
-/// InvalidateInstructionCache - Before the JIT can run a block of code
-/// that has been emitted it must invalidate the instruction cache on some
-/// platforms.
-void LLIChildTarget::InvalidateInstructionCache(const void *Addr,
- size_t Len) {
-
-// icache invalidation for PPC and ARM.
-#if defined(__APPLE__)
-
-# if (defined(__POWERPC__) || defined (__ppc__) || \
- defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
- sys_icache_invalidate(const_cast<void *>(Addr), Len);
-# endif
-
-#else
-
-# if (defined(__POWERPC__) || defined (__ppc__) || \
- defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
- const size_t LineSize = 32;
-
- const intptr_t Mask = ~(LineSize - 1);
- const intptr_t StartLine = ((intptr_t) Addr) & Mask;
- const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
-
- for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
- asm volatile("dcbf 0, %0" : : "r"(Line));
- asm volatile("sync");
-
- for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
- asm volatile("icbi 0, %0" : : "r"(Line));
- asm volatile("isync");
-# elif defined(__arm__) && defined(__GNUC__)
- // FIXME: Can we safely always call this for __GNUC__ everywhere?
- const char *Start = static_cast<const char *>(Addr);
- const char *End = Start + Len;
- __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
-# elif defined(__mips__)
- const char *Start = static_cast<const char *>(Addr);
- cacheflush(const_cast<char *>(Start), Len, BCACHE);
-# endif
-
-#endif // end apple
-}
-
-void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {
- ::munmap((void*)Addr, Size);
-}
diff --git a/tools/lli/ChildTarget/Windows/ChildTarget.inc b/tools/lli/ChildTarget/Windows/ChildTarget.inc
deleted file mode 100644
index 45db2b0..0000000
--- a/tools/lli/ChildTarget/Windows/ChildTarget.inc
+++ /dev/null
@@ -1,44 +0,0 @@
-//=- ChildTarget.inc - Child process for external JIT execution for Windows -=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Non-implementation of the Windows-specific parts of the ChildTarget class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-LLIChildTarget::~LLIChildTarget() {
-}
-
-// The RemoteTargetExternal implementation should prevent us from ever getting
-// here on Windows, but nothing prevents a user from running this directly.
-void LLIChildTarget::initializeConnection() {
- assert(0 && "lli-child-target is not implemented for Windows");
-}
-
-int LLIChildTarget::WriteBytes(const void *Data, size_t Size) {
- return 0;
-}
-
-int LLIChildTarget::ReadBytes(void *Data, size_t Size) {
- return 0;
-}
-
-uint64_t LLIChildTarget::allocate(uint32_t Alignment, uint32_t Size) {
- return 0;
-}
-
-void LLIChildTarget::makeSectionExecutable(uint64_t Addr, uint32_t Size) {
-}
-
-void LLIChildTarget::InvalidateInstructionCache(const void *Addr,
- size_t Len) {
-}
-
-void LLIChildTarget::releaseMemory(uint64_t Addr, uint32_t Size) {
-}
diff --git a/tools/lli/RPCChannel.h b/tools/lli/RPCChannel.h
new file mode 100644
index 0000000..2d8c708
--- /dev/null
+++ b/tools/lli/RPCChannel.h
@@ -0,0 +1,49 @@
+//===---------- RPCChannel.h - LLVM out-of-process JIT execution ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the RemoteTargetExternal class which executes JITed code in a
+// separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLI_RPCCHANNEL_H
+#define LLI_RPCCHANNEL_H
+
+#include <stdlib.h>
+#include <string>
+
+namespace llvm {
+
+class RPCChannel {
+public:
+ std::string ChildName;
+
+ RPCChannel() {}
+ ~RPCChannel();
+
+ /// Start the remote process.
+ ///
+ /// @returns True on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ bool createServer();
+
+ bool createClient();
+
+ // This will get filled in as a point to an OS-specific structure.
+ void *ConnectionData;
+
+ bool WriteBytes(const void *Data, size_t Size);
+ bool ReadBytes(void *Data, size_t Size);
+
+ void Wait();
+};
+
+} // end namespace llvm
+
+#endif // LLI_RPCCHANNEL_H
diff --git a/tools/lli/RemoteMemoryManager.cpp b/tools/lli/RemoteMemoryManager.cpp
index 04fc40e..e9f4d53 100644
--- a/tools/lli/RemoteMemoryManager.cpp
+++ b/tools/lli/RemoteMemoryManager.cpp
@@ -109,7 +109,7 @@ void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
CurOffset += Size;
}
}
- // Adjust to keep code and data aligned on seperate pages.
+ // Adjust to keep code and data aligned on separate pages.
CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
for (size_t i = 0, e = NumSections; i != e; ++i) {
Allocation &Section = UnmappedSections[i];
@@ -129,7 +129,7 @@ void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
// Allocate space in the remote target.
uint64_t RemoteAddr;
- if (Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
+ if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
report_fatal_error(Target->getErrorMsg());
// Map the section addresses so relocations will get updated in the local
@@ -155,13 +155,13 @@ bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
uint64_t RemoteAddr = I->first;
const Allocation &Section = I->second;
if (Section.IsCode) {
- Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size());
-
+ if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
+ report_fatal_error(Target->getErrorMsg());
DEBUG(dbgs() << " loading code: " << Section.MB.base()
<< " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
} else {
- Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size());
-
+ if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
+ report_fatal_error(Target->getErrorMsg());
DEBUG(dbgs() << " loading data: " << Section.MB.base()
<< " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
}
diff --git a/tools/lli/RemoteMemoryManager.h b/tools/lli/RemoteMemoryManager.h
index 5d0456f..11f600f 100644
--- a/tools/lli/RemoteMemoryManager.h
+++ b/tools/lli/RemoteMemoryManager.h
@@ -15,6 +15,7 @@
#ifndef REMOTEMEMORYMANAGER_H
#define REMOTEMEMORYMANAGER_H
+#include "RemoteTarget.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
@@ -22,8 +23,6 @@
#include "llvm/Support/Memory.h"
#include <utility>
-#include "RemoteTarget.h"
-
namespace llvm {
class RemoteMemoryManager : public JITMemoryManager {
@@ -68,45 +67,48 @@ public:
virtual ~RemoteMemoryManager();
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, StringRef SectionName);
+ unsigned SectionID,
+ StringRef SectionName) override;
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
- bool IsReadOnly);
+ bool IsReadOnly) override;
// For now, remote symbol resolution is not support in lli. The MCJIT
// interface does support this, but clients must provide their own
// mechanism for finding remote symbol addresses. MCJIT will resolve
// symbols from Modules it contains.
- uint64_t getSymbolAddress(const std::string &Name) { return 0; }
+ uint64_t getSymbolAddress(const std::string &Name) override { return 0; }
- void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj);
+ void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj) override;
- bool finalizeMemory(std::string *ErrMsg);
+ bool finalizeMemory(std::string *ErrMsg) override;
// For now, remote EH frame registration isn't supported. Remote symbol
// resolution is a prerequisite to supporting remote EH frame registration.
- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {}
- void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {}
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {}
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {}
// This is a non-interface function used by lli
void setRemoteTarget(RemoteTarget *T) { Target = T; }
// The following obsolete JITMemoryManager calls are stubbed out for
// this model.
- void setMemoryWritable();
- void setMemoryExecutable();
- void setPoisonMemory(bool poison);
- void AllocateGOT();
- uint8_t *getGOTBase() const;
- uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize);
+ void setMemoryWritable() override;
+ void setMemoryExecutable() override;
+ void setPoisonMemory(bool poison) override;
+ void AllocateGOT() override;
+ uint8_t *getGOTBase() const override;
+ uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) override;
uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
- unsigned Alignment);
+ unsigned Alignment) override;
void endFunctionBody(const Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd);
- uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
- uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
- void deallocateFunctionBody(void *Body);
+ uint8_t *FunctionEnd) override;
+ uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) override;
+ uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) override;
+ void deallocateFunctionBody(void *Body) override;
};
} // end namespace llvm
diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp
index 5c74e6e..55fc064 100644
--- a/tools/lli/RemoteTarget.cpp
+++ b/tools/lli/RemoteTarget.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "RemoteTarget.h"
-#include "RemoteTargetExternal.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Memory.h"
@@ -22,28 +21,6 @@
using namespace llvm;
-// Static methods
-RemoteTarget *RemoteTarget::createRemoteTarget() {
- return new RemoteTarget;
-}
-
-RemoteTarget *RemoteTarget::createExternalRemoteTarget(std::string &ChildName) {
-#ifdef LLVM_ON_UNIX
- return new RemoteTargetExternal(ChildName);
-#else
- return 0;
-#endif
-}
-
-bool RemoteTarget::hostSupportsExternalRemoteTarget() {
-#ifdef LLVM_ON_UNIX
- return true;
-#else
- return false;
-#endif
-}
-
-
////////////////////////////////////////////////////////////////////////////////
// Simulated remote execution
//
@@ -56,34 +33,36 @@ bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,
sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;
sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg);
if (Mem.base() == NULL)
- return true;
+ return false;
if ((uintptr_t)Mem.base() % Alignment) {
ErrorMsg = "unable to allocate sufficiently aligned memory";
- return true;
+ return false;
}
Address = reinterpret_cast<uint64_t>(Mem.base());
- return false;
+ Allocations.push_back(Mem);
+ return true;
}
bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) {
memcpy ((void*)Address, Data, Size);
- return false;
+ return true;
}
bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) {
memcpy ((void*)Address, Data, Size);
sys::MemoryBlock Mem((void*)Address, Size);
sys::Memory::setExecutable(Mem, &ErrorMsg);
- return false;
+ return true;
}
bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) {
int (*fn)(void) = (int(*)(void))Address;
RetVal = fn();
- return false;
+ return true;
}
-void RemoteTarget::create() {
+bool RemoteTarget::create() {
+ return true;
}
void RemoteTarget::stop() {
diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h
index c95fbd1..73e8ae2 100644
--- a/tools/lli/RemoteTarget.h
+++ b/tools/lli/RemoteTarget.h
@@ -25,10 +25,13 @@
namespace llvm {
class RemoteTarget {
- std::string ErrorMsg;
bool IsRunning;
- SmallVector<sys::MemoryBlock, 16> Allocations;
+ typedef SmallVector<sys::MemoryBlock, 16> AllocMapType;
+ AllocMapType Allocations;
+
+protected:
+ std::string ErrorMsg;
public:
StringRef getErrorMsg() const { return ErrorMsg; }
@@ -39,19 +42,31 @@ public:
/// @param Alignment Required minimum alignment for allocated space.
/// @param[out] Address Remote address of the allocated memory.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool allocateSpace(size_t Size,
unsigned Alignment,
uint64_t &Address);
+ bool isAllocatedMemory(uint64_t Address, uint32_t Size) {
+ uint64_t AddressEnd = Address + Size;
+ for (AllocMapType::const_iterator I = Allocations.begin(),
+ E = Allocations.end();
+ I != E; ++I) {
+ if (Address >= (uint64_t)I->base() &&
+ AddressEnd <= (uint64_t)I->base() + I->size())
+ return true;
+ }
+ return false;
+ }
+
/// Load data into the target address space.
///
/// @param Address Destination address in the target process.
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadData(uint64_t Address,
const void *Data,
@@ -63,7 +78,7 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool loadCode(uint64_t Address,
const void *Data,
@@ -76,12 +91,12 @@ public:
/// process.
/// @param[out] RetVal The integer return value of the called function.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
virtual bool executeCode(uint64_t Address,
int &RetVal);
- /// Minimum alignment for memory permissions. Used to seperate code and
+ /// Minimum alignment for memory permissions. Used to separate code and
/// data regions to make sure data doesn't get marked as code or vice
/// versa.
///
@@ -89,18 +104,13 @@ public:
virtual unsigned getPageAlignment() { return 4096; }
/// Start the remote process.
- virtual void create();
+ virtual bool create();
/// Terminate the remote process.
virtual void stop();
- RemoteTarget() : ErrorMsg(""), IsRunning(false) {}
+ RemoteTarget() : IsRunning(false), ErrorMsg("") {}
virtual ~RemoteTarget() { if (IsRunning) stop(); }
-
- // Create an instance of the system-specific remote target class.
- static RemoteTarget *createRemoteTarget();
- static RemoteTarget *createExternalRemoteTarget(std::string &ChildName);
- static bool hostSupportsExternalRemoteTarget();
private:
// Main processing function for the remote target process. Command messages
// are received on file descriptor CmdFD and responses come back on OutFD.
diff --git a/tools/lli/RemoteTargetExternal.cpp b/tools/lli/RemoteTargetExternal.cpp
index 742a948..c1bc8df 100644
--- a/tools/lli/RemoteTargetExternal.cpp
+++ b/tools/lli/RemoteTargetExternal.cpp
@@ -13,12 +13,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h"
-
#include "RemoteTarget.h"
#include "RemoteTargetExternal.h"
-
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,135 +28,298 @@ using namespace llvm;
bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
uint64_t &Address) {
- SendAllocateSpace(Alignment, Size);
- Receive(LLI_AllocationResult, Address);
- return false;
+ DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
+ ", align: " << Alignment << "\n");
+ if (!SendAllocateSpace(Alignment, Size)) {
+ ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
+ return false;
+ }
+ if (!Receive(LLI_AllocationResult, Address)) {
+ ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
+ return false;
+ }
+ if (Address == 0) {
+ ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
+ return false;
+ }
+ DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
+ format("%llx", Address) << "\n");
+ return true;
}
bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
- SendLoadSection(Address, Data, (uint32_t)Size, false);
- Receive(LLI_LoadComplete);
- return false;
+ DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
+ ", size: " << Size << "\n");
+ if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
+ ErrorMsg += ", (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ int Status = LLI_Status_Success;
+ if (!Receive(LLI_LoadResult, Status)) {
+ ErrorMsg += ", (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ if (Status == LLI_Status_IncompleteMsg) {
+ ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ if (Status == LLI_Status_NotAllocated) {
+ ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ DEBUG(dbgs() << "Message [load data] complete\n");
+ return true;
}
bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
- SendLoadSection(Address, Data, (uint32_t)Size, true);
- Receive(LLI_LoadComplete);
- return false;
+ DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
+ ", size: " << Size << "\n");
+ if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
+ ErrorMsg += ", (RemoteTargetExternal::loadCode)";
+ return false;
+ }
+ int Status = LLI_Status_Success;
+ if (!Receive(LLI_LoadResult, Status)) {
+ ErrorMsg += ", (RemoteTargetExternal::loadCode)";
+ return false;
+ }
+ if (Status == LLI_Status_IncompleteMsg) {
+ ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ if (Status == LLI_Status_NotAllocated) {
+ ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
+ return false;
+ }
+ DEBUG(dbgs() << "Message [load code] complete\n");
+ return true;
}
-bool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
- SendExecute(Address);
-
- Receive(LLI_ExecutionResult, RetVal);
- return false;
+bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
+ DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
+ if (!SendExecute(Address)) {
+ ErrorMsg += ", (RemoteTargetExternal::executeCode)";
+ return false;
+ }
+ if (!Receive(LLI_ExecutionResult, RetVal)) {
+ ErrorMsg += ", (RemoteTargetExternal::executeCode)";
+ return false;
+ }
+ DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
+ return true;
}
void RemoteTargetExternal::stop() {
SendTerminate();
- Wait();
+ RPC.Wait();
}
-void RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
- int rc;
- uint32_t MsgType = (uint32_t)LLI_AllocateSpace;
- rc = WriteBytes(&MsgType, 4);
- assert(rc == 4 && "Error writing message type.");
+bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
+ if (!SendHeader(LLI_AllocateSpace)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
+ return false;
+ }
- uint32_t DataSize = 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4 && "Error writing data size.");
+ AppendWrite((const void *)&Alignment, 4);
+ AppendWrite((const void *)&Size, 4);
- rc = WriteBytes(&Alignment, 4);
- assert(rc == 4 && "Error writing alignment data.");
-
- rc = WriteBytes(&Size, 4);
- assert(rc == 4 && "Error writing size data.");
+ if (!SendPayload()) {
+ ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
+ return false;
+ }
+ return true;
}
-void RemoteTargetExternal::SendLoadSection(uint64_t Addr,
+bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
const void *Data,
uint32_t Size,
bool IsCode) {
- int rc;
- uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
- rc = WriteBytes(&MsgType, 4);
- assert(rc == 4 && "Error writing message type.");
+ LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
+ if (!SendHeader(MsgType)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
+ return false;
+ }
+
+ AppendWrite((const void *)&Addr, 8);
+ AppendWrite(Data, Size);
+
+ if (!SendPayload()) {
+ ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
+ return false;
+ }
+ return true;
+}
- uint32_t DataSize = Size + 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4 && "Error writing data size.");
+bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
+ if (!SendHeader(LLI_Execute)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
+ return false;
+ }
- rc = WriteBytes(&Addr, 8);
- assert(rc == 8 && "Error writing data.");
+ AppendWrite((const void *)&Addr, 8);
- rc = WriteBytes(Data, Size);
- assert(rc == (int)Size && "Error writing data.");
+ if (!SendPayload()) {
+ ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
+ return false;
+ }
+ return true;
}
-void RemoteTargetExternal::SendExecute(uint64_t Addr) {
- int rc;
- uint32_t MsgType = (uint32_t)LLI_Execute;
- rc = WriteBytes(&MsgType, 4);
- assert(rc == 4 && "Error writing message type.");
-
- uint32_t DataSize = 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4 && "Error writing data size.");
+bool RemoteTargetExternal::SendTerminate() {
+ return SendHeader(LLI_Terminate);
+ // No data or data size is sent with Terminate
+}
- rc = WriteBytes(&Addr, 8);
- assert(rc == 8 && "Error writing data.");
+bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
+ if (!ReceiveHeader(Msg))
+ return false;
+ int Unused;
+ AppendRead(&Unused, 0);
+ if (!ReceivePayload())
+ return false;
+ ReceiveData.clear();
+ Sizes.clear();
+ return true;
}
-void RemoteTargetExternal::SendTerminate() {
- int rc;
- uint32_t MsgType = (uint32_t)LLI_Terminate;
- rc = WriteBytes(&MsgType, 4);
- assert(rc == 4 && "Error writing message type.");
+bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
+ if (!ReceiveHeader(Msg))
+ return false;
+ AppendRead(&Data, 4);
+ if (!ReceivePayload())
+ return false;
+ ReceiveData.clear();
+ Sizes.clear();
+ return true;
+}
- // No data or data size is sent with Terminate
+bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
+ if (!ReceiveHeader(Msg))
+ return false;
+ AppendRead(&Data, 8);
+ if (!ReceivePayload())
+ return false;
+ ReceiveData.clear();
+ Sizes.clear();
+ return true;
}
+bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
+ assert(ReceiveData.empty() && Sizes.empty() &&
+ "Payload vector not empty to receive header");
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
- int rc;
+ // Message header, with type to follow
uint32_t MsgType;
- rc = ReadBytes(&MsgType, 4);
- assert(rc == 4 && "Error reading message type.");
- assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
+ if (!ReadBytes(&MsgType, 4)) {
+ ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
+ return false;
+ }
+ if (MsgType != (uint32_t)ExpectedMsgType) {
+ ErrorMsg = "received unexpected message type";
+ ErrorMsg += ". Expecting: ";
+ ErrorMsg += ExpectedMsgType;
+ ErrorMsg += ", Got: ";
+ ErrorMsg += MsgType;
+ return false;
+ }
+ return true;
+}
+
+bool RemoteTargetExternal::ReceivePayload() {
+ assert(!ReceiveData.empty() &&
+ "Payload vector empty to receive");
+ assert(ReceiveData.size() == Sizes.size() &&
+ "Unexpected mismatch between data and size");
+ uint32_t TotalSize = 0;
+ for (int I=0, E=Sizes.size(); I < E; I++)
+ TotalSize += Sizes[I];
+
+ // Payload size header
uint32_t DataSize;
- rc = ReadBytes(&DataSize, 4);
- assert(rc == 4 && "Error reading data size.");
- assert(DataSize == 0 && "Error: unexpected data size.");
+ if (!ReadBytes(&DataSize, 4)) {
+ ErrorMsg += ", invalid data size";
+ return false;
+ }
+ if (DataSize != TotalSize) {
+ ErrorMsg = "unexpected data size";
+ ErrorMsg += ". Expecting: ";
+ ErrorMsg += TotalSize;
+ ErrorMsg += ", Got: ";
+ ErrorMsg += DataSize;
+ return false;
+ }
+ if (DataSize == 0)
+ return true;
+
+ // Payload itself
+ for (int I=0, E=Sizes.size(); I < E; I++) {
+ if (!ReadBytes(ReceiveData[I], Sizes[I])) {
+ ErrorMsg = "unexpected data while reading message";
+ return false;
+ }
+ }
+
+ return true;
}
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
- uint64_t Temp;
- Receive(ExpectedMsgType, Temp);
- Data = (int)(int64_t)Temp;
+bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
+ assert(SendData.empty() && Sizes.empty() &&
+ "Payload vector not empty to send header");
+
+ // Message header, with type to follow
+ if (!WriteBytes(&MsgType, 4)) {
+ ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
+ return false;
+ }
+ return true;
}
-void RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
- int rc;
- uint32_t MsgType;
- rc = ReadBytes(&MsgType, 4);
- assert(rc == 4 && "Error reading message type.");
- assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
+bool RemoteTargetExternal::SendPayload() {
+ assert(!SendData.empty() && !Sizes.empty() &&
+ "Payload vector empty to send");
+ assert(SendData.size() == Sizes.size() &&
+ "Unexpected mismatch between data and size");
+
+ uint32_t TotalSize = 0;
+ for (int I=0, E=Sizes.size(); I < E; I++)
+ TotalSize += Sizes[I];
+
+ // Payload size header
+ if (!WriteBytes(&TotalSize, 4)) {
+ ErrorMsg += ", invalid data size";
+ return false;
+ }
+ if (TotalSize == 0)
+ return true;
+
+ // Payload itself
+ for (int I=0, E=Sizes.size(); I < E; I++) {
+ if (!WriteBytes(SendData[I], Sizes[I])) {
+ ErrorMsg = "unexpected data while writing message";
+ return false;
+ }
+ }
+
+ SendData.clear();
+ Sizes.clear();
+ return true;
+}
- uint32_t DataSize;
- rc = ReadBytes(&DataSize, 4);
- assert(rc == 4 && "Error reading data size.");
- assert(DataSize == 8 && "Error: unexpected data size.");
+void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
+ SendData.push_back(Data);
+ Sizes.push_back(Size);
+}
- rc = ReadBytes(&Data, 8);
- assert(DataSize == 8 && "Error: unexpected data.");
+void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
+ ReceiveData.push_back(Data);
+ Sizes.push_back(Size);
}
#ifdef LLVM_ON_UNIX
-#include "Unix/RemoteTargetExternal.inc"
+#include "Unix/RPCChannel.inc"
#endif
#ifdef LLVM_ON_WIN32
-#include "Windows/RemoteTargetExternal.inc"
+#include "Windows/RPCChannel.inc"
#endif
diff --git a/tools/lli/RemoteTargetExternal.h b/tools/lli/RemoteTargetExternal.h
index a4bfad2..f87fc61 100644
--- a/tools/lli/RemoteTargetExternal.h
+++ b/tools/lli/RemoteTargetExternal.h
@@ -15,21 +15,28 @@
#ifndef LLI_REMOTETARGETEXTERNAL_H
#define LLI_REMOTETARGETEXTERNAL_H
-#include "llvm/Config/config.h"
-
+#include "RPCChannel.h"
+#include "RemoteTarget.h"
+#include "RemoteTargetMessage.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Memory.h"
#include <stdlib.h>
#include <string>
-#include "RemoteTarget.h"
-#include "RemoteTargetMessage.h"
-
namespace llvm {
class RemoteTargetExternal : public RemoteTarget {
+ RPCChannel RPC;
+
+ bool WriteBytes(const void *Data, size_t Size) {
+ return RPC.WriteBytes(Data, Size);
+ }
+
+ bool ReadBytes(void *Data, size_t Size) { return RPC.ReadBytes(Data, Size); }
+
public:
/// Allocate space in the remote target address space.
///
@@ -37,11 +44,10 @@ public:
/// @param Alignment Required minimum alignment for allocated space.
/// @param[out] Address Remote address of the allocated memory.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
- virtual bool allocateSpace(size_t Size,
- unsigned Alignment,
- uint64_t &Address);
+ bool allocateSpace(size_t Size, unsigned Alignment,
+ uint64_t &Address) override;
/// Load data into the target address space.
///
@@ -49,9 +55,9 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
- virtual bool loadData(uint64_t Address, const void *Data, size_t Size);
+ bool loadData(uint64_t Address, const void *Data, size_t Size) override;
/// Load code into the target address space and prepare it for execution.
///
@@ -59,9 +65,9 @@ public:
/// @param Data Source address in the host process.
/// @param Size Number of bytes to copy.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
- virtual bool loadCode(uint64_t Address, const void *Data, size_t Size);
+ bool loadCode(uint64_t Address, const void *Data, size_t Size) override;
/// Execute code in the target process. The called function is required
/// to be of signature int "(*)(void)".
@@ -70,47 +76,66 @@ public:
/// process.
/// @param[out] RetVal The integer return value of the called function.
///
- /// @returns False on success. On failure, ErrorMsg is updated with
+ /// @returns True on success. On failure, ErrorMsg is updated with
/// descriptive text of the encountered error.
- virtual bool executeCode(uint64_t Address, int &RetVal);
+ bool executeCode(uint64_t Address, int &RetVal) override;
- /// Minimum alignment for memory permissions. Used to seperate code and
+ /// Minimum alignment for memory permissions. Used to separate code and
/// data regions to make sure data doesn't get marked as code or vice
/// versa.
///
/// @returns Page alignment return value. Default of 4k.
- virtual unsigned getPageAlignment() { return 4096; }
+ unsigned getPageAlignment() override { return 4096; }
+
+ bool create() override {
+ RPC.ChildName = ChildName;
+ if (!RPC.createServer())
+ return true;
- /// Start the remote process.
- virtual void create();
+ // We must get Ack from the client (blocking read)
+ if (!Receive(LLI_ChildActive)) {
+ ErrorMsg += ", (RPCChannel::create) - Stopping process!";
+ stop();
+ return false;
+ }
+
+ return true;
+ }
/// Terminate the remote process.
- virtual void stop();
+ void stop() override;
RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
- virtual ~RemoteTargetExternal();
+ virtual ~RemoteTargetExternal() {}
private:
std::string ChildName;
- // This will get filled in as a point to an OS-specific structure.
- void *ConnectionData;
-
- void SendAllocateSpace(uint32_t Alignment, uint32_t Size);
- void SendLoadSection(uint64_t Addr,
+ bool SendAllocateSpace(uint32_t Alignment, uint32_t Size);
+ bool SendLoadSection(uint64_t Addr,
const void *Data,
uint32_t Size,
bool IsCode);
- void SendExecute(uint64_t Addr);
- void SendTerminate();
-
- void Receive(LLIMessageType Msg);
- void Receive(LLIMessageType Msg, int &Data);
- void Receive(LLIMessageType Msg, uint64_t &Data);
-
- int WriteBytes(const void *Data, size_t Size);
- int ReadBytes(void *Data, size_t Size);
- void Wait();
+ bool SendExecute(uint64_t Addr);
+ bool SendTerminate();
+
+ // High-level wrappers for receiving data
+ bool Receive(LLIMessageType Msg);
+ bool Receive(LLIMessageType Msg, int32_t &Data);
+ bool Receive(LLIMessageType Msg, uint64_t &Data);
+
+ // Lower level target-independent read/write to deal with errors
+ bool ReceiveHeader(LLIMessageType Msg);
+ bool ReceivePayload();
+ bool SendHeader(LLIMessageType Msg);
+ bool SendPayload();
+
+ // Functions to append/retrieve data from the payload
+ SmallVector<const void *, 2> SendData;
+ SmallVector<void *, 1> ReceiveData; // Future proof
+ SmallVector<int, 2> Sizes;
+ void AppendWrite(const void *Data, uint32_t Size);
+ void AppendRead(void *Data, uint32_t Size);
};
} // end namespace llvm
diff --git a/tools/lli/RemoteTargetMessage.h b/tools/lli/RemoteTargetMessage.h
index 12cfa9a..cb934a1 100644
--- a/tools/lli/RemoteTargetMessage.h
+++ b/tools/lli/RemoteTargetMessage.h
@@ -26,20 +26,60 @@ namespace llvm {
// only here for testing purposes and is therefore intended to be the simplest
// implementation that will work. It is assumed that the parent and child
// share characteristics like endianness.
+//
+// Quick description of the protocol:
+//
+// { Header + Payload Size + Payload }
+//
+// The protocol message consist of a header, the payload size (which can be
+// zero), and the payload itself. The payload can contain any number of items,
+// and the size has to be the sum of them all. Each end is responsible for
+// reading/writing the correct number of items with the correct sizes.
+//
+// The current four known exchanges are:
+//
+// * Allocate Space:
+// Parent: { LLI_AllocateSpace, 8, Alignment, Size }
+// Child: { LLI_AllocationResult, 8, Address }
+//
+// * Load Data:
+// Parent: { LLI_LoadDataSection, 8+Size, Address, Data }
+// Child: { LLI_LoadComplete, 4, StatusCode }
+//
+// * Load Code:
+// Parent: { LLI_LoadCodeSection, 8+Size, Address, Code }
+// Child: { LLI_LoadComplete, 4, StatusCode }
+//
+// * Execute Code:
+// Parent: { LLI_Execute, 8, Address }
+// Child: { LLI_ExecutionResult, 4, Result }
+//
+// It is the responsibility of either side to check for correct headers,
+// sizes and payloads, since any inconsistency would misalign the pipe, and
+// result in data corruption.
enum LLIMessageType {
LLI_Error = -1,
LLI_ChildActive = 0, // Data = not used
- LLI_AllocateSpace, // Data = struct { uint_32t Align, uint_32t Size }
- LLI_AllocationResult, // Data = uint64_t AllocAddress (in Child memory space)
- LLI_LoadCodeSection, // Data = uint32_t Addr, followed by section contests
- LLI_LoadDataSection, // Data = uint32_t Addr, followed by section contents
- LLI_LoadComplete, // Data = not used
- LLI_Execute, // Data = Address of function to execute
- LLI_ExecutionResult, // Data = uint64_t Result
+ LLI_AllocateSpace, // Data = struct { uint32_t Align, uint_32t Size }
+ LLI_AllocationResult, // Data = uint64_t Address (child memory space)
+
+ LLI_LoadCodeSection, // Data = uint64_t Address, void * SectionData
+ LLI_LoadDataSection, // Data = uint64_t Address, void * SectionData
+ LLI_LoadResult, // Data = uint32_t LLIMessageStatus
+
+ LLI_Execute, // Data = uint64_t Address
+ LLI_ExecutionResult, // Data = uint32_t Result
+
LLI_Terminate // Data = not used
};
+enum LLIMessageStatus {
+ LLI_Status_Success = 0, // Operation succeeded
+ LLI_Status_NotAllocated, // Address+Size not allocated in child space
+ LLI_Status_IncompleteMsg // Size received doesn't match request
+};
+
} // end namespace llvm
#endif
diff --git a/tools/lli/Unix/RemoteTargetExternal.inc b/tools/lli/Unix/RPCChannel.inc
index 9c1a4cc..4d245d6 100644
--- a/tools/lli/Unix/RemoteTargetExternal.inc
+++ b/tools/lli/Unix/RPCChannel.inc
@@ -1,4 +1,4 @@
-//=- RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Unix --=//
+//=- RPCChannel.inc - LLVM out-of-process JIT execution for Unix --=//
//
// The LLVM Compiler Infrastructure
//
@@ -7,15 +7,17 @@
//
//===----------------------------------------------------------------------===//
//
-// Implementation of the Unix-specific parts of the RemoteTargetExternal class
+// Implementation of the Unix-specific parts of the RPCChannel class
// which executes JITed code in a separate process from where it was built.
//
//===----------------------------------------------------------------------===//
-#include <unistd.h>
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/raw_ostream.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
+#include <unistd.h>
namespace {
@@ -30,7 +32,7 @@ struct ConnectionData_t {
namespace llvm {
-void RemoteTargetExternal::create() {
+bool RPCChannel::createServer() {
int PipeFD[2][2];
pid_t ChildPID;
@@ -62,8 +64,7 @@ void RemoteTargetExternal::create() {
int rc = execv(ChildName.c_str(), args);
if (rc != 0)
perror("Error executing child process: ");
- }
- else {
+ } else {
// In the parent...
// Close the child ends of the pipes
@@ -71,25 +72,50 @@ void RemoteTargetExternal::create() {
close(PipeFD[1][1]);
// Store the parent ends of the pipes
- ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
-
- Receive(LLI_ChildActive);
+ ConnectionData = (void *)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
+ return true;
}
+ return false;
}
-int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
- return write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size);
+bool RPCChannel::createClient() {
+ // Store the parent ends of the pipes
+ ConnectionData = (void *)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
+ return true;
+}
+
+void RPCChannel::Wait() { wait(NULL); }
+
+static bool CheckError(int rc, size_t Size, const char *Desc) {
+ if (rc < 0) {
+ llvm::errs() << "IO Error: " << Desc << ": " << sys::StrError() << '\n';
+ return false;
+ } else if ((size_t)rc != Size) {
+ std::string ErrorMsg;
+ char Number[10] = { 0 };
+ ErrorMsg += "Expecting ";
+ sprintf(Number, "%d", (uint32_t)Size);
+ ErrorMsg += Number;
+ ErrorMsg += " bytes, Got ";
+ sprintf(Number, "%d", rc);
+ ErrorMsg += Number;
+ llvm::errs() << "RPC Error: " << Desc << ": " << ErrorMsg << '\n';
+ return false;
+ }
+ return true;
}
-int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
- return read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size);
+bool RPCChannel::WriteBytes(const void *Data, size_t Size) {
+ int rc = write(((ConnectionData_t *)ConnectionData)->OutputPipe, Data, Size);
+ return CheckError(rc, Size, "WriteBytes");
}
-void RemoteTargetExternal::Wait() {
- wait(NULL);
+bool RPCChannel::ReadBytes(void *Data, size_t Size) {
+ int rc = read(((ConnectionData_t *)ConnectionData)->InputPipe, Data, Size);
+ return CheckError(rc, Size, "ReadBytes");
}
-RemoteTargetExternal::~RemoteTargetExternal() {
+RPCChannel::~RPCChannel() {
delete static_cast<ConnectionData_t *>(ConnectionData);
}
diff --git a/tools/lli/Windows/RPCChannel.inc b/tools/lli/Windows/RPCChannel.inc
new file mode 100644
index 0000000..82f2acb
--- /dev/null
+++ b/tools/lli/Windows/RPCChannel.inc
@@ -0,0 +1,29 @@
+//=- RPCChannel.inc - LLVM out-of-process JIT execution for Windows --=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the Windows-specific parts of the RPCChannel class
+// which executes JITed code in a separate process from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+bool RPCChannel::createServer() { return false; }
+
+bool RPCChannel::createClient() { return false; }
+
+bool RPCChannel::WriteBytes(const void *Data, size_t Size) { return false; }
+
+bool RPCChannel::ReadBytes(void *Data, size_t Size) { return false; }
+
+void RPCChannel::Wait() {}
+
+RPCChannel::~RPCChannel() {}
+
+} // namespace llvm
diff --git a/tools/lli/Windows/RemoteTargetExternal.inc b/tools/lli/Windows/RemoteTargetExternal.inc
deleted file mode 100644
index aef4627..0000000
--- a/tools/lli/Windows/RemoteTargetExternal.inc
+++ /dev/null
@@ -1,35 +0,0 @@
-//= RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Windows =//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the Windows-specific parts of the RemoteTargetExternal class
-// which is meant to execute JITed code in a separate process from where it was
-// built. To support this functionality on Windows, implement these functions.
-//
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-
-void RemoteTargetExternal::create() {
-}
-
-int RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) {
- return 0;
-}
-
-int RemoteTargetExternal::ReadBytes(void *Data, size_t Size) {
- return 0;
-}
-
-void RemoteTargetExternal::Wait() {
-}
-
-RemoteTargetExternal::~RemoteTargetExternal() {
-}
-
-} // namespace llvm
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index f317566..c0c0f9d 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -17,6 +17,7 @@
#include "llvm/IR/LLVMContext.h"
#include "RemoteMemoryManager.h"
#include "RemoteTarget.h"
+#include "RemoteTargetExternal.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@@ -26,12 +27,15 @@
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
@@ -91,12 +95,11 @@ namespace {
// execution. The child process will be executed and will communicate with
// lli via stdin/stdout pipes.
cl::opt<std::string>
- MCJITRemoteProcess("mcjit-remote-process",
- cl::desc("Specify the filename of the process to launch "
- "for remote MCJIT execution. If none is specified,"
- "\n\tremote execution will be simulated in-process."),
- cl::value_desc("filename"),
- cl::init(""));
+ ChildExecPath("mcjit-remote-process",
+ cl::desc("Specify the filename of the process to launch "
+ "for remote MCJIT execution. If none is specified,"
+ "\n\tremote execution will be simulated in-process."),
+ cl::value_desc("filename"), cl::init(""));
// Determine optimization level.
cl::opt<char>
@@ -138,6 +141,27 @@ namespace {
cl::desc("Extra modules to be loaded"),
cl::value_desc("input bitcode"));
+ cl::list<std::string>
+ ExtraObjects("extra-object",
+ cl::desc("Extra object files to be loaded"),
+ cl::value_desc("input object"));
+
+ cl::list<std::string>
+ ExtraArchives("extra-archive",
+ cl::desc("Extra archive files to be loaded"),
+ cl::value_desc("input archive"));
+
+ cl::opt<bool>
+ EnableCacheManager("enable-cache-manager",
+ cl::desc("Use cache manager to save/load mdoules"),
+ cl::init(false));
+
+ cl::opt<std::string>
+ ObjectCacheDir("object-cache-dir",
+ cl::desc("Directory to store cached object files "
+ "(must be user writable)"),
+ cl::init(""));
+
cl::opt<std::string>
FakeArgv0("fake-argv0",
cl::desc("Override the 'argv[0]' value passed into the executing"
@@ -219,12 +243,91 @@ namespace {
cl::init(false));
}
+//===----------------------------------------------------------------------===//
+// Object cache
+//
+// This object cache implementation writes cached objects to disk to the
+// directory specified by CacheDir, using a filename provided in the module
+// descriptor. The cache tries to load a saved object using that path if the
+// file exists. CacheDir defaults to "", in which case objects are cached
+// alongside their originating bitcodes.
+//
+class LLIObjectCache : public ObjectCache {
+public:
+ LLIObjectCache(const std::string& CacheDir) : CacheDir(CacheDir) {
+ // Add trailing '/' to cache dir if necessary.
+ if (!this->CacheDir.empty() &&
+ this->CacheDir[this->CacheDir.size() - 1] != '/')
+ this->CacheDir += '/';
+ }
+ virtual ~LLIObjectCache() {}
+
+ void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) override {
+ const std::string ModuleID = M->getModuleIdentifier();
+ std::string CacheName;
+ if (!getCacheFilename(ModuleID, CacheName))
+ return;
+ std::string errStr;
+ if (!CacheDir.empty()) { // Create user-defined cache dir.
+ SmallString<128> dir(CacheName);
+ sys::path::remove_filename(dir);
+ sys::fs::create_directories(Twine(dir));
+ }
+ raw_fd_ostream outfile(CacheName.c_str(), errStr, sys::fs::F_None);
+ outfile.write(Obj->getBufferStart(), Obj->getBufferSize());
+ outfile.close();
+ }
+
+ MemoryBuffer* getObject(const Module* M) override {
+ const std::string ModuleID = M->getModuleIdentifier();
+ std::string CacheName;
+ if (!getCacheFilename(ModuleID, CacheName))
+ return NULL;
+ // Load the object from the cache filename
+ std::unique_ptr<MemoryBuffer> IRObjectBuffer;
+ MemoryBuffer::getFile(CacheName.c_str(), IRObjectBuffer, -1, false);
+ // If the file isn't there, that's OK.
+ if (!IRObjectBuffer)
+ return NULL;
+ // MCJIT will want to write into this buffer, and we don't want that
+ // because the file has probably just been mmapped. Instead we make
+ // a copy. The filed-based buffer will be released when it goes
+ // out of scope.
+ return MemoryBuffer::getMemBufferCopy(IRObjectBuffer->getBuffer());
+ }
+
+private:
+ std::string CacheDir;
+
+ bool getCacheFilename(const std::string &ModID, std::string &CacheName) {
+ std::string Prefix("file:");
+ size_t PrefixLength = Prefix.length();
+ if (ModID.substr(0, PrefixLength) != Prefix)
+ return false;
+ std::string CacheSubdir = ModID.substr(PrefixLength);
+#if defined(_WIN32)
+ // Transform "X:\foo" => "/X\foo" for convenience.
+ if (isalpha(CacheSubdir[0]) && CacheSubdir[1] == ':') {
+ CacheSubdir[1] = CacheSubdir[0];
+ CacheSubdir[0] = '/';
+ }
+#endif
+ CacheName = CacheDir + CacheSubdir;
+ size_t pos = CacheName.rfind('.');
+ CacheName.replace(pos, CacheName.length() - pos, ".o");
+ return true;
+ }
+};
+
static ExecutionEngine *EE = 0;
+static LLIObjectCache *CacheManager = 0;
static void do_shutdown() {
// Cygwin-1.5 invokes DLL's dtors before atexit handler.
#ifndef DO_NOTHING_ATEXIT
delete EE;
+ if (CacheManager)
+ delete CacheManager;
llvm_shutdown();
#endif
}
@@ -300,12 +403,20 @@ int main(int argc, char **argv, char * const *envp) {
return 1;
}
+ if (EnableCacheManager) {
+ if (UseMCJIT) {
+ std::string CacheName("file:");
+ CacheName.append(InputFile);
+ Mod->setModuleIdentifier(CacheName);
+ } else
+ errs() << "warning: -enable-cache-manager can only be used with MCJIT.";
+ }
+
// If not jitting lazily, load the whole bitcode file eagerly too.
- std::string ErrorMsg;
if (NoLazyCompilation) {
- if (Mod->MaterializeAllPermanently(&ErrorMsg)) {
+ if (error_code EC = Mod->materializeAllPermanently()) {
errs() << argv[0] << ": bitcode didn't read correctly.\n";
- errs() << "Reason: " << ErrorMsg << "\n";
+ errs() << "Reason: " << EC.message() << "\n";
exit(1);
}
}
@@ -321,6 +432,7 @@ int main(int argc, char **argv, char * const *envp) {
DebugIRPass->runOnModule(*Mod);
}
+ std::string ErrorMsg;
EngineBuilder builder(Mod);
builder.setMArch(MArch);
builder.setMCPU(MCPU);
@@ -391,6 +503,11 @@ int main(int argc, char **argv, char * const *envp) {
exit(1);
}
+ if (EnableCacheManager) {
+ CacheManager = new LLIObjectCache(ObjectCacheDir);
+ EE->setObjectCache(CacheManager);
+ }
+
// Load any additional modules specified on the command line.
for (unsigned i = 0, e = ExtraModules.size(); i != e; ++i) {
Module *XMod = ParseIRFile(ExtraModules[i], Err, Context);
@@ -398,9 +515,43 @@ int main(int argc, char **argv, char * const *envp) {
Err.print(argv[0], errs());
return 1;
}
+ if (EnableCacheManager) {
+ if (UseMCJIT) {
+ std::string CacheName("file:");
+ CacheName.append(ExtraModules[i]);
+ XMod->setModuleIdentifier(CacheName);
+ }
+ // else, we already printed a warning above.
+ }
EE->addModule(XMod);
}
+ for (unsigned i = 0, e = ExtraObjects.size(); i != e; ++i) {
+ ErrorOr<object::ObjectFile *> Obj =
+ object::ObjectFile::createObjectFile(ExtraObjects[i]);
+ if (!Obj) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+ EE->addObjectFile(Obj.get());
+ }
+
+ for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) {
+ std::unique_ptr<MemoryBuffer> ArBuf;
+ error_code ec;
+ ec = MemoryBuffer::getFileOrSTDIN(ExtraArchives[i], ArBuf);
+ if (ec) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+ object::Archive *Ar = new object::Archive(ArBuf.release(), ec);
+ if (ec || !Ar) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+ EE->addArchive(Ar);
+ }
+
// If the target is Cygwin/MingW and we are generating remote code, we
// need an extra module to help out with linking.
if (RemoteMCJIT && Triple(Mod->getTargetTriple()).isOSCygMing()) {
@@ -472,7 +623,7 @@ int main(int argc, char **argv, char * const *envp) {
}
}
- // Trigger compilation separately so code regions that need to be
+ // Trigger compilation separately so code regions that need to be
// invalidated will be known.
(void)EE->getPointerToFunction(EntryFn);
// Clear instruction cache before code will be executed.
@@ -511,30 +662,35 @@ int main(int argc, char **argv, char * const *envp) {
// address space, assign the section addresses to resolve any relocations,
// and send it to the target.
- OwningPtr<RemoteTarget> Target;
- if (!MCJITRemoteProcess.empty()) { // Remote execution on a child process
- if (!RemoteTarget::hostSupportsExternalRemoteTarget()) {
- errs() << "Warning: host does not support external remote targets.\n"
- << " Defaulting to simulated remote execution\n";
- Target.reset(RemoteTarget::createRemoteTarget());
- } else {
- std::string ChildEXE = sys::FindProgramByName(MCJITRemoteProcess);
- if (ChildEXE == "") {
- errs() << "Unable to find child target: '\''" << MCJITRemoteProcess << "\'\n";
- return -1;
- }
- Target.reset(RemoteTarget::createExternalRemoteTarget(ChildEXE));
+ std::unique_ptr<RemoteTarget> Target;
+ if (!ChildExecPath.empty()) { // Remote execution on a child process
+#ifndef LLVM_ON_UNIX
+ // FIXME: Remove this pointless fallback mode which causes tests to "pass"
+ // on platforms where they should XFAIL.
+ errs() << "Warning: host does not support external remote targets.\n"
+ << " Defaulting to simulated remote execution\n";
+ Target.reset(new RemoteTarget);
+#else
+ if (!sys::fs::can_execute(ChildExecPath)) {
+ errs() << "Unable to find usable child executable: '" << ChildExecPath
+ << "'\n";
+ return -1;
}
+ Target.reset(new RemoteTargetExternal(ChildExecPath));
+#endif
} else {
// No child process name provided, use simulated remote execution.
- Target.reset(RemoteTarget::createRemoteTarget());
+ Target.reset(new RemoteTarget);
}
// Give the memory manager a pointer to our remote target interface object.
MM->setRemoteTarget(Target.get());
// Create the remote target.
- Target->create();
+ if (!Target->create()) {
+ errs() << "ERROR: " << Target->getErrorMsg() << "\n";
+ return EXIT_FAILURE;
+ }
// Since we're executing in a (at least simulated) remote address space,
// we can't use the ExecutionEngine::runFunctionAsMain(). We have to
@@ -551,7 +707,7 @@ int main(int argc, char **argv, char * const *envp) {
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
<< format("%llx", Entry) << "\n");
- if (Target->executeCode(Entry, Result))
+ if (!Target->executeCode(Entry, Result))
errs() << "ERROR: " << Target->getErrorMsg() << "\n";
// Like static constructors, the remote target MCJIT support doesn't handle
diff --git a/tools/llvm-ar/CMakeLists.txt b/tools/llvm-ar/CMakeLists.txt
index f15a1e2..9295efe 100644
--- a/tools/llvm-ar/CMakeLists.txt
+++ b/tools/llvm-ar/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS support object bitreader)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_tool(llvm-ar
llvm-ar.cpp
@@ -12,10 +15,10 @@ if(UNIX)
set(llvm_ar_binary "llvm-ar${CMAKE_EXECUTABLE_SUFFIX}")
else()
set(LLVM_LINK_OR_COPY copy)
- set(llvm_ar_binary "${LLVM_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/llvm-ar${CMAKE_EXECUTABLE_SUFFIX}")
+ set(llvm_ar_binary "${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar${CMAKE_EXECUTABLE_SUFFIX}")
endif()
-set(llvm_ranlib "${LLVM_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX}")
+set(llvm_ranlib "${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX}")
add_custom_command(TARGET llvm-ar POST_BUILD
COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${llvm_ar_binary}" "${llvm_ranlib}")
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index d70db72..047f54e 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -322,7 +322,7 @@ static void doExtract(StringRef Name, object::Archive::child_iterator I) {
int FD;
failIfError(
- sys::fs::openFileForWrite(Storage.c_str(), FD, sys::fs::F_Binary, Mode),
+ sys::fs::openFileForWrite(Storage.c_str(), FD, sys::fs::F_None, Mode),
Storage.c_str());
{
@@ -365,8 +365,8 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
static void performReadOperation(ArchiveOperation Operation,
object::Archive *OldArchive) {
- for (object::Archive::child_iterator I = OldArchive->begin_children(),
- E = OldArchive->end_children();
+ for (object::Archive::child_iterator I = OldArchive->child_begin(),
+ E = OldArchive->child_end();
I != E; ++I) {
StringRef Name;
failIfError(I->getName(Name));
@@ -395,17 +395,25 @@ namespace {
class NewArchiveIterator {
bool IsNewMember;
StringRef Name;
+
object::Archive::child_iterator OldI;
+
std::string NewFilename;
+ mutable int NewFD;
+ mutable sys::fs::file_status NewStatus;
public:
NewArchiveIterator(object::Archive::child_iterator I, StringRef Name);
NewArchiveIterator(std::string *I, StringRef Name);
NewArchiveIterator();
bool isNewMember() const;
+ StringRef getName() const;
+
object::Archive::child_iterator getOld() const;
+
const char *getNew() const;
- StringRef getName() const;
+ int getFD() const;
+ const sys::fs::file_status &getStatus() const;
};
}
@@ -416,7 +424,7 @@ NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
: IsNewMember(false), Name(Name), OldI(I) {}
NewArchiveIterator::NewArchiveIterator(std::string *NewFilename, StringRef Name)
- : IsNewMember(true), Name(Name), NewFilename(*NewFilename) {}
+ : IsNewMember(true), Name(Name), NewFilename(*NewFilename), NewFD(-1) {}
StringRef NewArchiveIterator::getName() const { return Name; }
@@ -432,6 +440,31 @@ const char *NewArchiveIterator::getNew() const {
return NewFilename.c_str();
}
+int NewArchiveIterator::getFD() const {
+ assert(IsNewMember);
+ if (NewFD != -1)
+ return NewFD;
+ failIfError(sys::fs::openFileForRead(NewFilename, NewFD), NewFilename);
+ assert(NewFD != -1);
+
+ failIfError(sys::fs::status(NewFD, NewStatus), NewFilename);
+
+ // Opening a directory doesn't make sense. Let it fail.
+ // Linux cannot open directories with open(2), although
+ // cygwin and *bsd can.
+ if (NewStatus.type() == sys::fs::file_type::directory_file)
+ failIfError(error_code(errc::is_a_directory, posix_category()),
+ NewFilename);
+
+ return NewFD;
+}
+
+const sys::fs::file_status &NewArchiveIterator::getStatus() const {
+ assert(IsNewMember);
+ assert(NewFD != -1 && "Must call getFD first");
+ return NewStatus;
+}
+
template <typename T>
void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name,
int Pos = -1) {
@@ -442,16 +475,6 @@ void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name,
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,
@@ -467,8 +490,9 @@ computeInsertAction(ArchiveOperation Operation,
if (Operation == QuickAppend || Members.empty())
return IA_AddOldMember;
- std::vector<std::string>::iterator MI =
- std::find_if(Members.begin(), Members.end(), HasName(Name));
+ std::vector<std::string>::iterator MI = std::find_if(
+ Members.begin(), Members.end(),
+ [Name](StringRef Path) { return Name == sys::path::filename(Path); });
if (MI == Members.end())
return IA_AddOldMember;
@@ -516,8 +540,8 @@ computeNewArchiveMembers(ArchiveOperation Operation,
int InsertPos = -1;
StringRef PosName = sys::path::filename(RelPos);
if (OldArchive) {
- for (object::Archive::child_iterator I = OldArchive->begin_children(),
- E = OldArchive->end_children();
+ for (object::Archive::child_iterator I = OldArchive->child_begin(),
+ E = OldArchive->child_end();
I != E; ++I) {
int Pos = Ret.size();
StringRef Name;
@@ -578,14 +602,21 @@ computeNewArchiveMembers(ArchiveOperation Operation,
}
template <typename T>
-static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
+static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
+ bool MayTruncate = false) {
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 << ' ';
+ if (Size > SizeSoFar) {
+ unsigned Remaining = Size - SizeSoFar;
+ for (unsigned I = 0; I < Remaining; ++I)
+ OS << ' ';
+ } else if (Size < SizeSoFar) {
+ assert(MayTruncate && "Data doesn't fit in Size");
+ // Some of the data this is used for (like UID) can be larger than the
+ // space available in the archive format. Truncate in that case.
+ OS.seek(OldPos + Size);
+ }
}
static void print32BE(raw_fd_ostream &Out, unsigned Val) {
@@ -600,8 +631,8 @@ static void printRestOfMemberHeader(raw_fd_ostream &Out,
unsigned GID, unsigned Perms,
unsigned Size) {
printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
- printWithSpacePadding(Out, UID, 6);
- printWithSpacePadding(Out, GID, 6);
+ printWithSpacePadding(Out, UID, 6, true);
+ printWithSpacePadding(Out, GID, 6, true);
printWithSpacePadding(Out, format("%o", Perms), 8);
printWithSpacePadding(Out, Size, 10);
Out << "`\n";
@@ -652,32 +683,26 @@ static void writeStringTable(raw_fd_ostream &Out,
static void writeSymbolTable(
raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
+ ArrayRef<MemoryBuffer *> Buffers,
std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) {
unsigned StartOffset = 0;
unsigned MemberNum = 0;
- std::vector<StringRef> SymNames;
- std::vector<object::ObjectFile *> DeleteIt;
+ std::string NameBuf;
+ raw_string_ostream NameOS(NameBuf);
+ unsigned NumSyms = 0;
+ std::vector<object::SymbolicFile *> DeleteIt;
+ LLVMContext &Context = getGlobalContext();
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 {
- Obj = dyn_cast<object::ObjectFile>(Binary.get());
- if (Obj)
- Binary.take();
- }
- }
- if (!Obj)
- continue;
+ MemoryBuffer *MemberBuffer = Buffers[MemberNum];
+ ErrorOr<object::SymbolicFile *> ObjOrErr =
+ object::SymbolicFile::createSymbolicFile(
+ MemberBuffer, false, sys::fs::file_magic::unknown, &Context);
+ if (!ObjOrErr)
+ continue; // FIXME: check only for "not an object file" errors.
+ object::SymbolicFile *Obj = ObjOrErr.get();
+
DeleteIt.push_back(Obj);
if (!StartOffset) {
printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
@@ -685,36 +710,29 @@ static void writeSymbolTable(
print32BE(Out, 0);
}
- 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));
+ for (object::basic_symbol_iterator I = Obj->symbol_begin(),
+ E = Obj->symbol_end();
+ I != E; ++I) {
+ uint32_t Symflags = I->getFlags();
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);
+ failIfError(I->printName(NameOS));
+ NameOS << '\0';
+ ++NumSyms;
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';
- }
+ Out << NameOS.str();
- for (std::vector<object::ObjectFile *>::iterator I = DeleteIt.begin(),
- E = DeleteIt.end();
+ for (std::vector<object::SymbolicFile *>::iterator I = DeleteIt.begin(),
+ E = DeleteIt.end();
I != E; ++I) {
- object::ObjectFile *O = *I;
+ object::SymbolicFile *O = *I;
delete O;
}
@@ -728,7 +746,7 @@ static void writeSymbolTable(
Out.seek(StartOffset - 12);
printWithSpacePadding(Out, Pos - StartOffset, 10);
Out.seek(StartOffset);
- print32BE(Out, SymNames.size());
+ print32BE(Out, NumSyms);
Out.seek(Pos);
}
@@ -748,8 +766,30 @@ static void performWriteOperation(ArchiveOperation Operation,
std::vector<std::pair<unsigned, unsigned> > MemberOffsetRefs;
+ std::vector<MemoryBuffer *> MemberBuffers;
+ MemberBuffers.resize(NewMembers.size());
+
+ for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
+ std::unique_ptr<MemoryBuffer> MemberBuffer;
+ NewArchiveIterator &Member = NewMembers[I];
+
+ if (Member.isNewMember()) {
+ const char *Filename = Member.getNew();
+ int FD = Member.getFD();
+ const sys::fs::file_status &Status = Member.getStatus();
+ failIfError(MemoryBuffer::getOpenFile(FD, Filename, MemberBuffer,
+ Status.getSize(), false),
+ Filename);
+
+ } else {
+ object::Archive::child_iterator OldMember = Member.getOld();
+ failIfError(OldMember->getMemoryBuffer(MemberBuffer));
+ }
+ MemberBuffers[I] = MemberBuffer.release();
+ }
+
if (Symtab) {
- writeSymbolTable(Out, NewMembers, MemberOffsetRefs);
+ writeSymbolTable(Out, NewMembers, MemberBuffers, MemberOffsetRefs);
}
std::vector<unsigned> StringMapIndexes;
@@ -773,26 +813,10 @@ static void performWriteOperation(ArchiveOperation Operation,
}
Out.seek(Pos);
+ const MemoryBuffer *File = MemberBuffers[MemberNum];
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);
-
- // Opening a directory doesn't make sense. Let it failed.
- // Linux cannot open directories with open(2), although
- // cygwin and *bsd can.
- if (Status.type() == sys::fs::file_type::directory_file)
- failIfError(error_code(errc::is_a_directory, posix_category()),
- FileName);
-
- OwningPtr<MemoryBuffer> File;
- failIfError(MemoryBuffer::getOpenFile(FD, FileName, File,
- Status.getSize(), false),
- FileName);
+ const sys::fs::file_status &Status = I->getStatus();
StringRef Name = sys::path::filename(FileName);
if (Name.size() < 16)
@@ -804,7 +828,6 @@ static void performWriteOperation(ArchiveOperation Operation,
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();
@@ -818,12 +841,18 @@ static void performWriteOperation(ArchiveOperation Operation,
OldMember->getLastModified(), OldMember->getUID(),
OldMember->getGID(), OldMember->getAccessMode(),
OldMember->getSize());
- Out << OldMember->getBuffer();
}
+ Out << File->getBuffer();
+
if (Out.tell() % 2)
Out << '\n';
}
+
+ for (unsigned I = 0, N = MemberBuffers.size(); I < N; ++I) {
+ delete MemberBuffers[I];
+ }
+
Output.keep();
Out.close();
sys::fs::rename(TemporaryOutput, ArchiveName);
@@ -909,7 +938,7 @@ int ar_main(char **argv) {
static int performOperation(ArchiveOperation Operation) {
// Create or open the archive object.
- OwningPtr<MemoryBuffer> Buf;
+ std::unique_ptr<MemoryBuffer> Buf;
error_code EC = MemoryBuffer::getFile(ArchiveName, Buf, -1, false);
if (EC && EC != llvm::errc::no_such_file_or_directory) {
errs() << ToolName << ": error opening '" << ArchiveName
@@ -918,7 +947,7 @@ static int performOperation(ArchiveOperation Operation) {
}
if (!EC) {
- object::Archive Archive(Buf.take(), EC);
+ object::Archive Archive(Buf.release(), EC);
if (EC) {
errs() << ToolName << ": error loading '" << ArchiveName
diff --git a/tools/llvm-as/CMakeLists.txt b/tools/llvm-as/CMakeLists.txt
index d5620e7..1b2789a 100644
--- a/tools/llvm-as/CMakeLists.txt
+++ b/tools/llvm-as/CMakeLists.txt
@@ -1,4 +1,9 @@
-set(LLVM_LINK_COMPONENTS asmparser bitwriter)
+set(LLVM_LINK_COMPONENTS
+ AsmParser
+ BitWriter
+ Core
+ Support
+ )
add_llvm_tool(llvm-as
llvm-as.cpp
diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp
index b2e44ef..7583b12 100644
--- a/tools/llvm-as/llvm-as.cpp
+++ b/tools/llvm-as/llvm-as.cpp
@@ -16,10 +16,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/Parser.h"
+#include "llvm/AsmParser/Parser.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -69,8 +69,8 @@ static void WriteOutputFile(const Module *M) {
}
std::string ErrorInfo;
- OwningPtr<tool_output_file> Out(new tool_output_file(
- OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary));
+ std::unique_ptr<tool_output_file> Out(
+ new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
exit(1);
@@ -93,18 +93,19 @@ int main(int argc, char **argv) {
// Parse the file now...
SMDiagnostic Err;
- OwningPtr<Module> M(ParseAssemblyFile(InputFilename, Err, Context));
+ std::unique_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context));
if (M.get() == 0) {
Err.print(argv[0], errs());
return 1;
}
if (!DisableVerify) {
- std::string Err;
- if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
+ std::string ErrorStr;
+ raw_string_ostream OS(ErrorStr);
+ if (verifyModule(*M.get(), &OS)) {
errs() << argv[0]
<< ": assembly parsed, but does not verify as correct!\n";
- errs() << Err;
+ errs() << OS.str();
return 1;
}
}
diff --git a/tools/llvm-bcanalyzer/CMakeLists.txt b/tools/llvm-bcanalyzer/CMakeLists.txt
index 0151ea9..369f469 100644
--- a/tools/llvm-bcanalyzer/CMakeLists.txt
+++ b/tools/llvm-bcanalyzer/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS bitreader)
+set(LLVM_LINK_COMPONENTS
+ BitReader
+ Support
+ )
add_llvm_tool(llvm-bcanalyzer
llvm-bcanalyzer.cpp
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index da40da2..9e17783 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -27,11 +27,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
@@ -479,7 +478,7 @@ static void PrintSize(uint64_t Bits) {
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
// Read the input file.
- OwningPtr<MemoryBuffer> MemBuf;
+ std::unique_ptr<MemoryBuffer> MemBuf;
if (error_code ec =
MemoryBuffer::getFileOrSTDIN(InputFilename, MemBuf))
diff --git a/tools/llvm-c-test/CMakeLists.txt b/tools/llvm-c-test/CMakeLists.txt
index 2926d9d..34fea3d 100644
--- a/tools/llvm-c-test/CMakeLists.txt
+++ b/tools/llvm-c-test/CMakeLists.txt
@@ -1,7 +1,14 @@
-set(LLVM_LINK_COMPONENTS all)
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ BitReader
+ Core
+ MCDisassembler
+ Object
+ Target
+ )
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wstrict-prototypes")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wstrict-prototypes")
endif ()
add_llvm_tool(llvm-c-test
diff --git a/tools/llvm-config/BuildVariables.inc.in b/tools/llvm-config/BuildVariables.inc.in
index fe87afb..2ec019b 100644
--- a/tools/llvm-config/BuildVariables.inc.in
+++ b/tools/llvm-config/BuildVariables.inc.in
@@ -11,8 +11,8 @@
// llvm-config wants to report to the user, but which can only be determined at
// build time.
//
-// The non .in variant of this file has been autogenerated by the LLVM build. Do
-// not edit!
+// The variant of this file not ending with .in has been autogenerated by the
+// LLVM build. Do not edit!
//
//===----------------------------------------------------------------------===//
diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt
index c651833..6f29a82 100644
--- a/tools/llvm-config/CMakeLists.txt
+++ b/tools/llvm-config/CMakeLists.txt
@@ -4,7 +4,7 @@ set(BUILDVARIABLES_SRCPATH ${CMAKE_CURRENT_SOURCE_DIR}/BuildVariables.inc.in)
set(BUILDVARIABLES_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.inc)
# Compute the substitution values for various items.
-get_system_libs(LLVM_SYSTEM_LIBS_LIST)
+get_property(LLVM_SYSTEM_LIBS_LIST TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS)
foreach(l ${LLVM_SYSTEM_LIBS_LIST})
set(SYSTEM_LIBS ${SYSTEM_LIBS} "-l${l}")
endforeach()
@@ -22,6 +22,9 @@ set(LLVM_SYSTEM_LIBS ${SYSTEM_LIBS})
string(REPLACE ";" " " LLVM_TARGETS_BUILT "${LLVM_TARGETS_TO_BUILD}")
configure_file(${BUILDVARIABLES_SRCPATH} ${BUILDVARIABLES_OBJPATH} @ONLY)
+# Set build-time environment(s).
+add_definitions(-DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}")
+
# Add the llvm-config tool.
add_llvm_tool(llvm-config
llvm-config.cpp
diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile
index b20b6bf..b78551e 100644
--- a/tools/llvm-config/Makefile
+++ b/tools/llvm-config/Makefile
@@ -30,6 +30,14 @@ SUB_CPPFLAGS := ${CPP.BaseFlags}
SUB_CFLAGS := ${CPP.BaseFlags} ${C.Flags}
SUB_CXXFLAGS := ${CPP.BaseFlags} ${CXX.Flags}
+# Override LIBS with TARGET's LIBS for cross compilation.
+# FIXME: Host's llvm-config is not generated. It's for target's.
+ifneq ($(TARGET_LIBS), )
+ LLVM_SYSTEM_LIBS := $(TARGET_LIBS)
+else
+ LLVM_SYSTEM_LIBS := $(LIBS)
+endif
+
# This is blank for now. We need to be careful about adding stuff here:
# LDFLAGS tend not to be portable, and we don't currently require the
# user to use libtool when linking against LLVM.
@@ -51,7 +59,7 @@ $(ObjDir)/BuildVariables.inc: $(BUILDVARIABLES_SRCPATH) Makefile $(ObjDir)/.dir
>> temp.sed
$(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \
>> temp.sed
- $(Verb) $(ECHO) 's/@LLVM_SYSTEM_LIBS@/$(subst /,\/,$(LIBS))/' \
+ $(Verb) $(ECHO) 's/@LLVM_SYSTEM_LIBS@/$(subst /,\/,$(LLVM_SYSTEM_LIBS))/' \
>> temp.sed
$(Verb) $(ECHO) 's/@LLVM_TARGETS_BUILT@/$(subst /,\/,$(TARGETS_TO_BUILD))/' \
>> temp.sed
diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
index 3924e2e..ed1c8c3 100644
--- a/tools/llvm-config/llvm-config.cpp
+++ b/tools/llvm-config/llvm-config.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Config/llvm-config.h"
@@ -147,6 +148,7 @@ Options:\n\
--cflags C compiler flags for files that include LLVM headers.\n\
--cxxflags C++ compiler flags for files that include LLVM headers.\n\
--ldflags Print Linker flags.\n\
+ --system-libs System Libraries needed to link against LLVM components.\n\
--libs Libraries needed to link against LLVM components.\n\
--libnames Bare library names for in-tree builds.\n\
--libfiles Fully qualified library filenames for makefile depends.\n\
@@ -154,6 +156,7 @@ Options:\n\
--targets-built List of all targets currently built.\n\
--host-target Target triple used to configure LLVM.\n\
--build-mode Print build mode of LLVM tree (e.g. Debug or Release).\n\
+ --assertion-mode Print assertion mode of LLVM tree (ON or OFF).\n\
Typical components:\n\
all All LLVM libraries (default).\n\
engine Either a native JIT or a bitcode interpreter.\n";
@@ -171,6 +174,7 @@ std::string GetExecutablePath(const char *Argv0) {
int main(int argc, char **argv) {
std::vector<StringRef> Components;
bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
+ bool PrintSystemLibs = false;
bool HasAnyOption = false;
// llvm-config is designed to support being run both from a development tree
@@ -183,6 +187,13 @@ int main(int argc, char **argv) {
std::string CurrentExecPrefix;
std::string ActiveObjRoot;
+ // If CMAKE_CFG_INTDIR is given, honor it as build mode.
+ char const *build_mode = LLVM_BUILDMODE;
+#if defined(CMAKE_CFG_INTDIR)
+ if (!(CMAKE_CFG_INTDIR[0] == '.' && CMAKE_CFG_INTDIR[1] == '\0'))
+ build_mode = CMAKE_CFG_INTDIR;
+#endif
+
// Create an absolute path, and pop up one directory (we expect to be inside a
// bin dir).
sys::fs::make_absolute(CurrentPath);
@@ -192,7 +203,7 @@ int main(int argc, char **argv) {
// Check to see if we are inside a development tree by comparing to possible
// locations (prefix style or CMake style).
if (sys::fs::equivalent(CurrentExecPrefix,
- Twine(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE)) {
+ Twine(LLVM_OBJ_ROOT) + "/" + build_mode)) {
IsInDevelopmentTree = true;
DevelopmentTreeLayout = MakefileStyle;
@@ -230,16 +241,18 @@ int main(int argc, char **argv) {
// layout.
switch (DevelopmentTreeLayout) {
case MakefileStyle:
- ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin";
- ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib";
+ ActivePrefix = ActiveObjRoot;
+ ActiveBinDir = ActiveObjRoot + "/" + build_mode + "/bin";
+ ActiveLibDir = ActiveObjRoot + "/" + build_mode + "/lib";
break;
case CMakeStyle:
ActiveBinDir = ActiveObjRoot + "/bin";
ActiveLibDir = ActiveObjRoot + "/lib";
break;
case CMakeBuildModeStyle:
- ActiveBinDir = ActiveObjRoot + "/bin/" + LLVM_BUILDMODE;
- ActiveLibDir = ActiveObjRoot + "/lib/" + LLVM_BUILDMODE;
+ ActivePrefix = ActiveObjRoot;
+ ActiveBinDir = ActiveObjRoot + "/bin/" + build_mode;
+ ActiveLibDir = ActiveObjRoot + "/lib/" + build_mode;
break;
}
@@ -277,8 +290,9 @@ int main(int argc, char **argv) {
} else if (Arg == "--cxxflags") {
OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n';
} else if (Arg == "--ldflags") {
- OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS
- << ' ' << LLVM_SYSTEM_LIBS << '\n';
+ OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n';
+ } else if (Arg == "--system-libs") {
+ PrintSystemLibs = true;
} else if (Arg == "--libs") {
PrintLibs = true;
} else if (Arg == "--libnames") {
@@ -298,11 +312,17 @@ int main(int argc, char **argv) {
} else if (Arg == "--targets-built") {
OS << LLVM_TARGETS_BUILT << '\n';
} else if (Arg == "--host-target") {
- OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n';
+ OS << Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE) << '\n';
} else if (Arg == "--build-mode") {
- OS << LLVM_BUILDMODE << '\n';
+ OS << build_mode << '\n';
+ } else if (Arg == "--assertion-mode") {
+#if defined(NDEBUG)
+ OS << "OFF\n";
+#else
+ OS << "ON\n";
+#endif
} else if (Arg == "--obj-root") {
- OS << LLVM_OBJ_ROOT << '\n';
+ OS << ActivePrefix << '\n';
} else if (Arg == "--src-root") {
OS << LLVM_SRC_ROOT << '\n';
} else {
@@ -316,7 +336,7 @@ int main(int argc, char **argv) {
if (!HasAnyOption)
usage();
- if (PrintLibs || PrintLibNames || PrintLibFiles) {
+ if (PrintLibs || PrintLibNames || PrintLibFiles || PrintSystemLibs) {
// If no components were specified, default to "all".
if (Components.empty())
Components.push_back("all");
@@ -326,27 +346,34 @@ int main(int argc, char **argv) {
ComputeLibsForComponents(Components, RequiredLibs,
/*IncludeNonInstalled=*/IsInDevelopmentTree);
- for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
- StringRef Lib = RequiredLibs[i];
- if (i)
- OS << ' ';
-
- if (PrintLibNames) {
- OS << Lib;
- } else if (PrintLibFiles) {
- OS << ActiveLibDir << '/' << Lib;
- } else if (PrintLibs) {
- // If this is a typical library name, include it using -l.
- if (Lib.startswith("lib") && Lib.endswith(".a")) {
- OS << "-l" << Lib.slice(3, Lib.size()-2);
- continue;
- }
+ if (PrintLibs || PrintLibNames || PrintLibFiles) {
+ for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
+ StringRef Lib = RequiredLibs[i];
+ if (i)
+ OS << ' ';
- // Otherwise, print the full path.
- OS << ActiveLibDir << '/' << Lib;
+ if (PrintLibNames) {
+ OS << Lib;
+ } else if (PrintLibFiles) {
+ OS << ActiveLibDir << '/' << Lib;
+ } else if (PrintLibs) {
+ // If this is a typical library name, include it using -l.
+ if (Lib.startswith("lib") && Lib.endswith(".a")) {
+ OS << "-l" << Lib.slice(3, Lib.size()-2);
+ continue;
+ }
+
+ // Otherwise, print the full path.
+ OS << ActiveLibDir << '/' << Lib;
+ }
}
+ OS << '\n';
}
- OS << '\n';
+
+ // Print SYSTEM_LIBS after --libs.
+ // FIXME: Each LLVM component may have its dependent system libs.
+ if (PrintSystemLibs)
+ OS << LLVM_SYSTEM_LIBS << '\n';
} else if (!Components.empty()) {
errs() << "llvm-config: error: components given, but unused\n\n";
usage();
diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp
index 5f6999e..587ee11 100644
--- a/tools/llvm-cov/llvm-cov.cpp
+++ b/tools/llvm-cov/llvm-cov.cpp
@@ -1,4 +1,4 @@
-//===- tools/llvm-cov/llvm-cov.cpp - LLVM coverage tool -------------------===//
+//===- llvm-cov.cpp - LLVM coverage tool ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,29 +11,61 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GCOV.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/system_error.h"
using namespace llvm;
-static cl::opt<bool>
-DumpGCOV("dump", cl::init(false), cl::desc("dump gcov file"));
+static cl::opt<std::string> SourceFile(cl::Positional, cl::Required,
+ cl::desc("SOURCEFILE"));
-static cl::opt<std::string>
-InputGCNO("gcno", cl::desc("<input gcno file>"), cl::init(""));
+static cl::opt<bool> AllBlocks("a", cl::init(false),
+ cl::desc("Display all basic blocks"));
+static cl::alias AllBlocksA("all-blocks", cl::aliasopt(AllBlocks));
-static cl::opt<std::string>
-InputGCDA("gcda", cl::desc("<input gcda file>"), cl::init(""));
+static cl::opt<bool> BranchProb("b", cl::init(false),
+ cl::desc("Display branch probabilities"));
+static cl::alias BranchProbA("branch-probabilities", cl::aliasopt(BranchProb));
+
+static cl::opt<bool> BranchCount("c", cl::init(false),
+ cl::desc("Display branch counts instead "
+ "of percentages (requires -b)"));
+static cl::alias BranchCountA("branch-counts", cl::aliasopt(BranchCount));
+
+static cl::opt<bool> FuncSummary("f", cl::init(false),
+ cl::desc("Show coverage for each function"));
+static cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary));
static cl::opt<std::string>
-OutputFile("o", cl::desc("<output llvm-cov file>"), cl::init("-"));
+ObjectDir("o", cl::value_desc("DIR|FILE"), cl::init(""),
+ cl::desc("Find objects in DIR or based on FILE's path"));
+static cl::alias ObjectDirA("object-directory", cl::aliasopt(ObjectDir));
+static cl::alias ObjectDirB("object-file", cl::aliasopt(ObjectDir));
+
+static cl::opt<bool> PreservePaths("p", cl::init(false),
+ cl::desc("Preserve path components"));
+static cl::alias PreservePathsA("preserve-paths", cl::aliasopt(PreservePaths));
+static cl::opt<bool> UncondBranch("u", cl::init(false),
+ cl::desc("Display unconditional branch info "
+ "(requires -b)"));
+static cl::alias UncondBranchA("unconditional-branches",
+ cl::aliasopt(UncondBranch));
+
+static cl::OptionCategory DebugCat("Internal and debugging options");
+static cl::opt<bool> DumpGCOV("dump", cl::init(false), cl::cat(DebugCat),
+ cl::desc("Dump the gcov file to stderr"));
+static cl::opt<std::string> InputGCNO("gcno", cl::cat(DebugCat), cl::init(""),
+ cl::desc("Override inferred gcno file"));
+static cl::opt<std::string> InputGCDA("gcda", cl::cat(DebugCat), cl::init(""),
+ cl::desc("Override inferred gcda file"));
//===----------------------------------------------------------------------===//
int main(int argc, char **argv) {
@@ -42,47 +74,61 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "llvm coverage tool\n");
+ cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
- std::string ErrorInfo;
- raw_fd_ostream OS(OutputFile.c_str(), ErrorInfo);
- if (!ErrorInfo.empty())
- errs() << ErrorInfo << "\n";
+ SmallString<128> CoverageFileStem(ObjectDir);
+ if (CoverageFileStem.empty()) {
+ // If no directory was specified with -o, look next to the source file.
+ CoverageFileStem = sys::path::parent_path(SourceFile);
+ sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
+ } else if (sys::fs::is_directory(ObjectDir))
+ // A directory name was given. Use it and the source file name.
+ sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
+ else
+ // A file was given. Ignore the source file and look next to this file.
+ sys::path::replace_extension(CoverageFileStem, "");
- GCOVFile GF;
if (InputGCNO.empty())
- errs() << " " << argv[0] << ": No gcov input file!\n";
+ InputGCNO = (CoverageFileStem.str() + ".gcno").str();
+ if (InputGCDA.empty())
+ InputGCDA = (CoverageFileStem.str() + ".gcda").str();
- OwningPtr<MemoryBuffer> GCNO_Buff;
+ GCOVFile GF;
+
+ std::unique_ptr<MemoryBuffer> GCNO_Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCNO, GCNO_Buff)) {
errs() << InputGCNO << ": " << ec.message() << "\n";
return 1;
}
GCOVBuffer GCNO_GB(GCNO_Buff.get());
- if (!GF.read(GCNO_GB)) {
+ if (!GF.readGCNO(GCNO_GB)) {
errs() << "Invalid .gcno File!\n";
return 1;
}
- if (!InputGCDA.empty()) {
- OwningPtr<MemoryBuffer> GCDA_Buff;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCDA, GCDA_Buff)) {
+ std::unique_ptr<MemoryBuffer> GCDA_Buff;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCDA, GCDA_Buff)) {
+ if (ec != errc::no_such_file_or_directory) {
errs() << InputGCDA << ": " << ec.message() << "\n";
return 1;
}
+ // Clear the filename to make it clear we didn't read anything.
+ InputGCDA = "-";
+ } else {
GCOVBuffer GCDA_GB(GCDA_Buff.get());
- if (!GF.read(GCDA_GB)) {
+ if (!GF.readGCDA(GCDA_GB)) {
errs() << "Invalid .gcda File!\n";
return 1;
}
}
-
if (DumpGCOV)
GF.dump();
- FileInfo FI;
+ GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
+ PreservePaths, UncondBranch);
+ FileInfo FI(Options);
GF.collectLineCounts(FI);
- FI.print(OS, InputGCNO, InputGCDA);
+ FI.print(InputGCNO, InputGCDA);
return 0;
}
diff --git a/tools/llvm-diff/CMakeLists.txt b/tools/llvm-diff/CMakeLists.txt
index 0df8b9e..4407a86 100644
--- a/tools/llvm-diff/CMakeLists.txt
+++ b/tools/llvm-diff/CMakeLists.txt
@@ -1,4 +1,8 @@
-set(LLVM_LINK_COMPONENTS support asmparser bitreader irreader)
+set(LLVM_LINK_COMPONENTS
+ Core
+ IRReader
+ Support
+ )
add_llvm_tool(llvm-diff
llvm-diff.cpp
diff --git a/tools/llvm-diff/DiffConsumer.h b/tools/llvm-diff/DiffConsumer.h
index 6c2209f..ac13a5e 100644
--- a/tools/llvm-diff/DiffConsumer.h
+++ b/tools/llvm-diff/DiffConsumer.h
@@ -79,11 +79,11 @@ namespace llvm {
: out(errs()), Differences(false), Indent(0) {}
bool hadDifferences() const;
- void enterContext(Value *L, Value *R);
- void exitContext();
- void log(StringRef text);
- void logf(const LogBuilder &Log);
- void logd(const DiffLogBuilder &Log);
+ void enterContext(Value *L, Value *R) override;
+ void exitContext() override;
+ void log(StringRef text) override;
+ void logf(const LogBuilder &Log) override;
+ void logd(const DiffLogBuilder &Log) override;
};
}
diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp
index 768b94b..7d379ef 100644
--- a/tools/llvm-diff/DifferenceEngine.cpp
+++ b/tools/llvm-diff/DifferenceEngine.cpp
@@ -18,12 +18,12 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/CallSite.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/type_traits.h"
diff --git a/tools/llvm-dis/CMakeLists.txt b/tools/llvm-dis/CMakeLists.txt
index 9f12ecb..06ac051 100644
--- a/tools/llvm-dis/CMakeLists.txt
+++ b/tools/llvm-dis/CMakeLists.txt
@@ -1,4 +1,8 @@
-set(LLVM_LINK_COMPONENTS bitreader analysis)
+set(LLVM_LINK_COMPONENTS
+ BitReader
+ Core
+ Support
+ )
add_llvm_tool(llvm-dis
llvm-dis.cpp
diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp
index 87eb347..c6f0dcf 100644
--- a/tools/llvm-dis/llvm-dis.cpp
+++ b/tools/llvm-dis/llvm-dis.cpp
@@ -17,9 +17,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Assembly/AssemblyAnnotationWriter.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
@@ -66,11 +66,11 @@ static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
class CommentWriter : public AssemblyAnnotationWriter {
public:
void emitFunctionAnnot(const Function *F,
- formatted_raw_ostream &OS) {
+ formatted_raw_ostream &OS) override {
OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses
OS << '\n';
}
- void printInfoComment(const Value &V, formatted_raw_ostream &OS) {
+ void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
bool Padded = false;
if (!V.getType()->isVoidTy()) {
OS.PadToColumn(50);
@@ -123,7 +123,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
std::string ErrorMessage;
- OwningPtr<Module> M;
+ std::unique_ptr<Module> M;
// Use the bitcode streaming interface
DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
@@ -135,8 +135,11 @@ int main(int argc, char **argv) {
DisplayFilename = InputFilename;
M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context,
&ErrorMessage));
- if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
- M.reset();
+ if(M.get() != 0) {
+ if (error_code EC = M->materializeAllPermanently()) {
+ ErrorMessage = EC.message();
+ M.reset();
+ }
}
}
@@ -168,14 +171,14 @@ int main(int argc, char **argv) {
}
std::string ErrorInfo;
- OwningPtr<tool_output_file> Out(new tool_output_file(
- OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary));
+ std::unique_ptr<tool_output_file> Out(
+ new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
- OwningPtr<AssemblyAnnotationWriter> Annotator;
+ std::unique_ptr<AssemblyAnnotationWriter> Annotator;
if (ShowAnnotations)
Annotator.reset(new CommentWriter());
diff --git a/tools/llvm-dwarfdump/CMakeLists.txt b/tools/llvm-dwarfdump/CMakeLists.txt
index 05aad3f..288b323 100644
--- a/tools/llvm-dwarfdump/CMakeLists.txt
+++ b/tools/llvm-dwarfdump/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
DebugInfo
Object
+ Support
)
add_llvm_tool(llvm-dwarfdump
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 413a50b..f4a9ae8 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/DebugInfo/DIContext.h"
@@ -63,8 +62,11 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_Info, "info", ".debug_info"),
clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
clEnumValN(DIDT_Types, "types", ".debug_types"),
+ clEnumValN(DIDT_TypesDwo, "types.dwo", ".debug_types.dwo"),
clEnumValN(DIDT_Line, "line", ".debug_line"),
+ clEnumValN(DIDT_LineDwo, "line.dwo", ".debug_line.dwo"),
clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
+ clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"),
clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),
@@ -85,20 +87,21 @@ static void PrintDILineInfo(DILineInfo dli) {
}
static void DumpInput(const StringRef &Filename) {
- OwningPtr<MemoryBuffer> Buff;
+ std::unique_ptr<MemoryBuffer> Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
errs() << Filename << ": " << ec.message() << "\n";
return;
}
- OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
- if (!Obj) {
- errs() << Filename << ": Unknown object file format\n";
+ ErrorOr<ObjectFile*> ObjOrErr(ObjectFile::createObjectFile(Buff.release()));
+ if (error_code EC = ObjOrErr.getError()) {
+ errs() << Filename << ": " << EC.message() << '\n';
return;
}
+ std::unique_ptr<ObjectFile> Obj(ObjOrErr.get());
- OwningPtr<DIContext> DICtx(DIContext::getDWARFContext(Obj.get()));
+ std::unique_ptr<DIContext> DICtx(DIContext::getDWARFContext(Obj.get()));
if (Address == -1ULL) {
outs() << Filename
diff --git a/tools/llvm-extract/CMakeLists.txt b/tools/llvm-extract/CMakeLists.txt
index 3163c4b..c984f01 100644
--- a/tools/llvm-extract/CMakeLists.txt
+++ b/tools/llvm-extract/CMakeLists.txt
@@ -1,4 +1,10 @@
-set(LLVM_LINK_COMPONENTS asmparser ipo bitreader bitwriter irreader)
+set(LLVM_LINK_COMPONENTS
+ BitWriter
+ Core
+ IPO
+ IRReader
+ Support
+ )
add_llvm_tool(llvm-extract
llvm-extract.cpp
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index dc1a410..2e5a2af 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -12,12 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
@@ -100,7 +100,7 @@ int main(int argc, char **argv) {
// Use lazy loading, since we only care about selected global values.
SMDiagnostic Err;
- OwningPtr<Module> M;
+ std::unique_ptr<Module> M;
M.reset(getLazyIRFileModule(InputFilename, Err, Context));
if (M.get() == 0) {
@@ -254,7 +254,7 @@ int main(int argc, char **argv) {
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
PassManager Passes;
- Passes.add(new DataLayout(M.get())); // Use correct DataLayout
+ Passes.add(new DataLayoutPass(M.get())); // Use correct DataLayout
std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
@@ -265,14 +265,14 @@ int main(int argc, char **argv) {
Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
std::string ErrorInfo;
- tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary);
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
if (OutputAssembly)
- Passes.add(createPrintModulePass(&Out.os()));
+ Passes.add(createPrintModulePass(Out.os()));
else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
Passes.add(createBitcodeWriterPass(Out.os()));
diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp
index dbaf075..c159aa5 100644
--- a/tools/llvm-jitlistener/llvm-jitlistener.cpp
+++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp
@@ -15,7 +15,6 @@
#include "llvm/IR/LLVMContext.h"
#include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
@@ -139,8 +138,8 @@ protected:
if (Tuple.getTriple().empty())
Tuple.setTriple(sys::getProcessTriple());
- if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) {
- Tuple.setEnvironment(Triple::ELF);
+ if (Tuple.isOSWindows() && !Tuple.isOSBinFormatELF()) {
+ Tuple.setObjectFormat(Triple::ELF);
TheModule->setTargetTriple(Tuple.getTriple());
}
@@ -163,16 +162,15 @@ protected:
LLVMContext Context; // Global ownership
Module *TheModule; // Owned by ExecutionEngine.
JITMemoryManager *JMM; // Owned by ExecutionEngine.
- OwningPtr<ExecutionEngine> TheJIT;
+ std::unique_ptr<ExecutionEngine> TheJIT;
public:
void ProcessInput(const std::string &Filename) {
InitEE(Filename);
- llvm::OwningPtr<llvm::JITEventListener> Listener(JITEventListener::createIntelJITEventListener(
- new IntelJITEventsWrapper(NotifyEvent, 0,
- IsProfilingActive, 0, 0,
- GetNewMethodID)));
+ std::unique_ptr<llvm::JITEventListener> Listener(
+ JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
+ NotifyEvent, 0, IsProfilingActive, 0, 0, GetNewMethodID)));
TheJIT->RegisterJITEventListener(Listener.get());
diff --git a/tools/llvm-link/Android.mk b/tools/llvm-link/Android.mk
index db8f2af..cbcd0af 100644
--- a/tools/llvm-link/Android.mk
+++ b/tools/llvm-link/Android.mk
@@ -34,6 +34,7 @@ include $(BUILD_HOST_EXECUTABLE)
# llvm-link command line tool (target)
#===---------------------------------------------------------------===
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
include $(CLEAR_VARS)
LOCAL_MODULE := llvm-link
@@ -42,7 +43,8 @@ LOCAL_SRC_FILES := $(llvm_link_SRC_FILES)
LOCAL_STATIC_LIBRARIES := $(llvm_link_STATIC_LIBRARIES)
LOCAL_SHARED_LIBRARIES := \
libcutils \
- libstlport
+ libc++
include $(LLVM_DEVICE_BUILD_MK)
include $(BUILD_EXECUTABLE)
+endif
diff --git a/tools/llvm-link/CMakeLists.txt b/tools/llvm-link/CMakeLists.txt
index 4df5356..d4f5be7 100644
--- a/tools/llvm-link/CMakeLists.txt
+++ b/tools/llvm-link/CMakeLists.txt
@@ -1,4 +1,10 @@
-set(LLVM_LINK_COMPONENTS linker bitreader bitwriter asmparser irreader)
+set(LLVM_LINK_COMPONENTS
+ BitWriter
+ Core
+ IRReader
+ Linker
+ Support
+ )
add_llvm_tool(llvm-link
llvm-link.cpp
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index 99cca23..1f0e224 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Linker.h"
-#include "llvm/Analysis/Verifier.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
@@ -50,6 +50,10 @@ Verbose("v", cl::desc("Print information about actions taken"));
static cl::opt<bool>
DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
+static cl::opt<bool>
+SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
+ cl::init(false));
+
// LoadFile - Read the specified bitcode file in and return it. This routine
// searches the link path for the specified file to try to find it...
//
@@ -78,17 +82,17 @@ int main(int argc, char **argv) {
unsigned BaseArg = 0;
std::string ErrorMessage;
- OwningPtr<Module> Composite(LoadFile(argv[0],
- InputFilenames[BaseArg], Context));
+ std::unique_ptr<Module> Composite(
+ LoadFile(argv[0], InputFilenames[BaseArg], Context));
if (Composite.get() == 0) {
errs() << argv[0] << ": error loading file '"
<< InputFilenames[BaseArg] << "'\n";
return 1;
}
- Linker L(Composite.get());
+ Linker L(Composite.get(), SuppressWarnings);
for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
- OwningPtr<Module> M(LoadFile(argv[0], InputFilenames[i], Context));
+ std::unique_ptr<Module> M(LoadFile(argv[0], InputFilenames[i], Context));
if (M.get() == 0) {
errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";
return 1;
@@ -106,7 +110,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, sys::fs::F_Binary);
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
diff --git a/tools/llvm-lto/CMakeLists.txt b/tools/llvm-lto/CMakeLists.txt
index 348976c..485b03d 100644
--- a/tools/llvm-lto/CMakeLists.txt
+++ b/tools/llvm-lto/CMakeLists.txt
@@ -1,4 +1,10 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} lto support)
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Core
+ LTO
+ MC
+ Support
+ )
add_llvm_tool(llvm-lto
llvm-lto.cpp
diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp
index 0fc68ae..ec3f0fa 100644
--- a/tools/llvm-lto/llvm-lto.cpp
+++ b/tools/llvm-lto/llvm-lto.cpp
@@ -20,8 +20,8 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -77,26 +77,7 @@ int main(int argc, char **argv) {
InitializeAllAsmParsers();
// set up the TargetOptions for the machine
- TargetOptions Options;
- Options.LessPreciseFPMADOption = EnableFPMAD;
- Options.NoFramePointerElim = DisableFPElim;
- Options.AllowFPOpFusion = FuseFPOps;
- Options.UnsafeFPMath = EnableUnsafeFPMath;
- Options.NoInfsFPMath = EnableNoInfsFPMath;
- Options.NoNaNsFPMath = EnableNoNaNsFPMath;
- Options.HonorSignDependentRoundingFPMathOption =
- EnableHonorSignDependentRoundingFPMath;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
- if (FloatABIForCalls != FloatABI::Default)
- Options.FloatABIType = FloatABIForCalls;
- Options.NoZerosInBSS = DontPlaceZerosInBSS;
- Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
- Options.DisableTailCalls = DisableTailCalls;
- Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.TrapFuncName = TrapFuncName;
- Options.PositionIndependentExecutable = EnablePIE;
- Options.EnableSegmentedStacks = SegmentedStacks;
- Options.UseInitArray = UseInitArray;
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
unsigned BaseArg = 0;
@@ -114,8 +95,8 @@ int main(int argc, char **argv) {
for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
std::string error;
- OwningPtr<LTOModule> Module(LTOModule::makeLTOModule(InputFilenames[i].c_str(),
- Options, error));
+ std::unique_ptr<LTOModule> Module(
+ LTOModule::makeLTOModule(InputFilenames[i].c_str(), Options, error));
if (!error.empty()) {
errs() << argv[0] << ": error loading file '" << InputFilenames[i]
<< "': " << error << "\n";
@@ -161,7 +142,7 @@ int main(int argc, char **argv) {
}
raw_fd_ostream FileStream(OutputFilename.c_str(), ErrorInfo,
- sys::fs::F_Binary);
+ sys::fs::F_None);
if (!ErrorInfo.empty()) {
errs() << argv[0] << ": error opening the file '" << OutputFilename
<< "': " << ErrorInfo << "\n";
diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt
index 805caf4..6f8e9e5 100644
--- a/tools/llvm-mc/CMakeLists.txt
+++ b/tools/llvm-mc/CMakeLists.txt
@@ -1,4 +1,9 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser MCDisassembler)
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ MC
+ MCParser
+ Support
+ )
add_llvm_tool(llvm-mc
llvm-mc.cpp
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index 81a0045..9c402f2 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "Disassembler.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -36,10 +35,10 @@ private:
public:
VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
- uint64_t getBase() const { return 0; }
- uint64_t getExtent() const { return Bytes.size(); }
+ uint64_t getBase() const override { return 0; }
+ uint64_t getExtent() const override { return Bytes.size(); }
- int readByte(uint64_t Addr, uint8_t *Byte) const {
+ int readByte(uint64_t Addr, uint8_t *Byte) const override {
if (Addr >= getExtent())
return -1;
*Byte = Bytes[Addr].first;
@@ -51,7 +50,8 @@ public:
static bool PrintInsts(const MCDisassembler &DisAsm,
const ByteArrayTy &Bytes,
SourceMgr &SM, raw_ostream &Out,
- MCStreamer &Streamer, bool InAtomicBlock) {
+ MCStreamer &Streamer, bool InAtomicBlock,
+ const MCSubtargetInfo &STI) {
// Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes);
@@ -86,7 +86,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
// Fall through
case MCDisassembler::Success:
- Streamer.EmitInstruction(Inst);
+ Streamer.EmitInstruction(Inst, STI);
break;
}
}
@@ -158,7 +158,7 @@ int Disassembler::disassemble(const Target &T,
MemoryBuffer &Buffer,
SourceMgr &SM,
raw_ostream &Out) {
- OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI));
+ std::unique_ptr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI));
if (!DisAsm) {
errs() << "error: no disassembler for target " << Triple << "\n";
return -1;
@@ -202,7 +202,7 @@ int Disassembler::disassemble(const Target &T,
if (!ByteArray.empty())
ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer,
- InAtomicBlock);
+ InAtomicBlock, STI);
}
if (InAtomicBlock) {
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index 7ec2bba..61fd2c4 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "Disassembler.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -27,6 +26,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
@@ -51,6 +51,9 @@ static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
static cl::opt<bool>
+CompressDebugSections("compress-debug-sections", cl::desc("Compress DWARF debug sections"));
+
+static cl::opt<bool>
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
static cl::opt<bool>
@@ -65,9 +68,6 @@ static cl::opt<bool>
RelaxAll("mc-relax-all", cl::desc("Relax all fixups"));
static cl::opt<bool>
-DisableCFI("disable-cfi", cl::desc("Do not use .cfi_* directives"));
-
-static cl::opt<bool>
NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack"));
enum OutputFileType {
@@ -211,7 +211,7 @@ static tool_output_file *GetOutputStream() {
std::string Err;
tool_output_file *Out =
- new tool_output_file(OutputFilename.c_str(), Err, sys::fs::F_Binary);
+ new tool_output_file(OutputFilename.c_str(), Err, sys::fs::F_None);
if (!Err.empty()) {
errs() << Err << '\n';
delete Out;
@@ -317,12 +317,12 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out)
return Error;
}
-static int AssembleInput(const char *ProgName, const Target *TheTarget,
+static int AssembleInput(const char *ProgName, const Target *TheTarget,
SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
MCAsmInfo &MAI, MCSubtargetInfo &STI, MCInstrInfo &MCII) {
- OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
- Str, MAI));
- OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(STI, *Parser, MCII));
+ std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, Str, MAI));
+ std::unique_ptr<MCTargetAsmParser> TAP(
+ TheTarget->createMCAsmParser(STI, *Parser, MCII));
if (!TAP) {
errs() << ProgName
<< ": error: this target does not support assembly parsing.\n";
@@ -363,12 +363,12 @@ int main(int argc, char **argv) {
if (!TheTarget)
return 1;
- OwningPtr<MemoryBuffer> BufferPtr;
+ std::unique_ptr<MemoryBuffer> BufferPtr;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) {
errs() << ProgName << ": " << ec.message() << '\n';
return 1;
}
- MemoryBuffer *Buffer = BufferPtr.take();
+ MemoryBuffer *Buffer = BufferPtr.release();
SourceMgr SrcMgr;
@@ -379,15 +379,23 @@ int main(int argc, char **argv) {
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
- llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
assert(MRI && "Unable to create target register info!");
- llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
assert(MAI && "Unable to create target asm info!");
+ if (CompressDebugSections) {
+ if (!zlib::isAvailable()) {
+ errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections";
+ return 1;
+ }
+ MAI->setCompressDebugSections(true);
+ }
+
// 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());
+ std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx);
@@ -413,16 +421,16 @@ int main(int argc, char **argv) {
FeaturesStr = Features.getString();
}
- OwningPtr<tool_output_file> Out(GetOutputStream());
+ std::unique_ptr<tool_output_file> Out(GetOutputStream());
if (!Out)
return 1;
formatted_raw_ostream FOS(Out->os());
- OwningPtr<MCStreamer> Str;
+ std::unique_ptr<MCStreamer> Str;
- OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
- OwningPtr<MCSubtargetInfo>
- STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
+ std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
+ std::unique_ptr<MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
MCInstPrinter *IP = NULL;
if (FileType == OFT_AssemblyFile) {
@@ -434,12 +442,10 @@ int main(int argc, char **argv) {
CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
}
- bool UseCFI = !DisableCFI;
- Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true,
- /*useLoc*/ true,
- UseCFI,
- /*useDwarfDirectory*/ true,
- IP, CE, MAB, ShowInst));
+ Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true,
+ /*UseCFI*/ true,
+ /*useDwarfDirectory*/
+ true, IP, CE, MAB, ShowInst));
} else if (FileType == OFT_Null) {
Str.reset(createNullStreamer(Ctx));
@@ -448,7 +454,7 @@ int main(int argc, char **argv) {
MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB,
- FOS, CE, RelaxAll,
+ FOS, CE, *STI, RelaxAll,
NoExecStack));
}
diff --git a/tools/llvm-mcmarkup/llvm-mcmarkup.cpp b/tools/llvm-mcmarkup/llvm-mcmarkup.cpp
index 888761f..f3a3e45 100644
--- a/tools/llvm-mcmarkup/llvm-mcmarkup.cpp
+++ b/tools/llvm-mcmarkup/llvm-mcmarkup.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
@@ -136,12 +135,12 @@ MarkupTag MarkupParser::parseTag() {
}
static void parseMCMarkup(StringRef Filename) {
- OwningPtr<MemoryBuffer> BufferPtr;
+ std::unique_ptr<MemoryBuffer> BufferPtr;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, BufferPtr)) {
errs() << ToolName << ": " << ec.message() << '\n';
return;
}
- MemoryBuffer *Buffer = BufferPtr.take();
+ MemoryBuffer *Buffer = BufferPtr.release();
SourceMgr SrcMgr;
diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt
index b1672ff..6128bf9 100644
--- a/tools/llvm-nm/CMakeLists.txt
+++ b/tools/llvm-nm/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS bitreader object)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_tool(llvm-nm
llvm-nm.cpp
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 8449c29..22e019a 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -16,15 +16,18 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/COFF.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
@@ -44,160 +47,152 @@ using namespace llvm;
using namespace object;
namespace {
- enum OutputFormatTy { bsd, sysv, posix };
- cl::opt<OutputFormatTy>
- OutputFormat("format",
- cl::desc("Specify output format"),
- cl::values(clEnumVal(bsd, "BSD format"),
- clEnumVal(sysv, "System V format"),
- clEnumVal(posix, "POSIX.2 format"),
- clEnumValEnd), cl::init(bsd));
- cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
- cl::aliasopt(OutputFormat));
-
- cl::list<std::string>
- InputFilenames(cl::Positional, cl::desc("<input bitcode files>"),
- cl::ZeroOrMore);
-
- cl::opt<bool> UndefinedOnly("undefined-only",
- cl::desc("Show only undefined symbols"));
- cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
- cl::aliasopt(UndefinedOnly));
-
- cl::opt<bool> DynamicSyms("dynamic",
- cl::desc("Display the dynamic symbols instead "
- "of normal symbols."));
- cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
- cl::aliasopt(DynamicSyms));
-
- cl::opt<bool> DefinedOnly("defined-only",
- cl::desc("Show only defined symbols"));
-
- cl::opt<bool> ExternalOnly("extern-only",
- cl::desc("Show only external symbols"));
- cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
- cl::aliasopt(ExternalOnly));
-
- cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
- cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
-
- cl::opt<bool> PrintFileName("print-file-name",
+enum OutputFormatTy { bsd, sysv, posix };
+cl::opt<OutputFormatTy> OutputFormat(
+ "format", cl::desc("Specify output format"),
+ cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"),
+ clEnumVal(posix, "POSIX.2 format"), clEnumValEnd),
+ cl::init(bsd));
+cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
+ cl::aliasopt(OutputFormat));
+
+cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
+ cl::ZeroOrMore);
+
+cl::opt<bool> UndefinedOnly("undefined-only",
+ cl::desc("Show only undefined symbols"));
+cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
+ cl::aliasopt(UndefinedOnly));
+
+cl::opt<bool> DynamicSyms("dynamic",
+ cl::desc("Display the dynamic symbols instead "
+ "of normal symbols."));
+cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
+ cl::aliasopt(DynamicSyms));
+
+cl::opt<bool> DefinedOnly("defined-only",
+ cl::desc("Show only defined symbols"));
+
+cl::opt<bool> ExternalOnly("extern-only",
+ cl::desc("Show only external symbols"));
+cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
+ cl::aliasopt(ExternalOnly));
+
+cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
+cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
+
+cl::opt<bool> PrintFileName(
+ "print-file-name",
cl::desc("Precede each symbol with the object file it came from"));
- cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
- cl::aliasopt(PrintFileName));
- cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
- cl::aliasopt(PrintFileName));
+cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
+ cl::aliasopt(PrintFileName));
+cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
+ cl::aliasopt(PrintFileName));
- cl::opt<bool> DebugSyms("debug-syms",
- cl::desc("Show all symbols, even debugger only"));
- cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
- cl::aliasopt(DebugSyms));
+cl::opt<bool> DebugSyms("debug-syms",
+ cl::desc("Show all symbols, even debugger only"));
+cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
+ cl::aliasopt(DebugSyms));
- cl::opt<bool> NumericSort("numeric-sort",
- cl::desc("Sort symbols by address"));
- cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
- cl::aliasopt(NumericSort));
- cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
- cl::aliasopt(NumericSort));
+cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"));
+cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
+ cl::aliasopt(NumericSort));
+cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
+ cl::aliasopt(NumericSort));
- cl::opt<bool> NoSort("no-sort",
- cl::desc("Show symbols in order encountered"));
- cl::alias NoSortp("p", cl::desc("Alias for --no-sort"),
- cl::aliasopt(NoSort));
+cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"));
+cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort));
- cl::opt<bool> PrintSize("print-size",
- cl::desc("Show symbol size instead of address"));
- cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
- cl::aliasopt(PrintSize));
+cl::opt<bool> PrintSize("print-size",
+ cl::desc("Show symbol size instead of address"));
+cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
+ cl::aliasopt(PrintSize));
- cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"));
+cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"));
- cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
- cl::desc("Exclude aliases from output"));
+cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
+ cl::desc("Exclude aliases from output"));
- cl::opt<bool> ArchiveMap("print-armap",
- cl::desc("Print the archive map"));
- cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"),
- cl::aliasopt(ArchiveMap));
- bool PrintAddress = true;
+cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"));
+cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"),
+ cl::aliasopt(ArchiveMap));
+bool PrintAddress = true;
- bool MultipleFiles = false;
+bool MultipleFiles = false;
- bool HadError = false;
+bool HadError = false;
- std::string ToolName;
+std::string ToolName;
}
-
-static void error(Twine message, Twine path = Twine()) {
- errs() << ToolName << ": " << path << ": " << message << ".\n";
+static void error(Twine Message, Twine Path = Twine()) {
+ HadError = true;
+ errs() << ToolName << ": " << Path << ": " << Message << ".\n";
}
-static bool error(error_code ec, Twine path = Twine()) {
- if (ec) {
- error(ec.message(), path);
- HadError = true;
+static bool error(error_code EC, Twine Path = Twine()) {
+ if (EC) {
+ error(EC.message(), Path);
return true;
}
return false;
}
namespace {
- struct NMSymbol {
- uint64_t Address;
- uint64_t Size;
- char TypeChar;
- StringRef Name;
- };
-
- static bool CompareSymbolAddress(const NMSymbol &a, const NMSymbol &b) {
- if (a.Address < b.Address)
- return true;
- else if (a.Address == b.Address && a.Name < b.Name)
- return true;
- else if (a.Address == b.Address && a.Name == b.Name && a.Size < b.Size)
- return true;
- else
- return false;
-
- }
+struct NMSymbol {
+ uint64_t Address;
+ uint64_t Size;
+ char TypeChar;
+ StringRef Name;
+};
+}
- static bool CompareSymbolSize(const NMSymbol &a, const NMSymbol &b) {
- if (a.Size < b.Size)
- return true;
- else if (a.Size == b.Size && a.Name < b.Name)
- return true;
- else if (a.Size == b.Size && a.Name == b.Name && a.Address < b.Address)
- return true;
- else
- return false;
- }
+static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
+ if (A.Address < B.Address)
+ return true;
+ else if (A.Address == B.Address && A.Name < B.Name)
+ return true;
+ else if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size)
+ return true;
+ else
+ return false;
+}
- static bool CompareSymbolName(const NMSymbol &a, const NMSymbol &b) {
- if (a.Name < b.Name)
- return true;
- else if (a.Name == b.Name && a.Size < b.Size)
- return true;
- else if (a.Name == b.Name && a.Size == b.Size && a.Address < b.Address)
- return true;
- else
- return false;
- }
+static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) {
+ if (A.Size < B.Size)
+ return true;
+ else if (A.Size == B.Size && A.Name < B.Name)
+ return true;
+ else if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address)
+ return true;
+ else
+ return false;
+}
- StringRef CurrentFilename;
- typedef std::vector<NMSymbol> SymbolListT;
- SymbolListT SymbolList;
+static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) {
+ if (A.Name < B.Name)
+ return true;
+ else if (A.Name == B.Name && A.Size < B.Size)
+ return true;
+ else if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address)
+ return true;
+ else
+ return false;
}
-static void SortAndPrintSymbolList() {
+static StringRef CurrentFilename;
+typedef std::vector<NMSymbol> SymbolListT;
+static SymbolListT SymbolList;
+
+static void sortAndPrintSymbolList() {
if (!NoSort) {
if (NumericSort)
- std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolAddress);
+ std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress);
else if (SizeSort)
- std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolSize);
+ std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolSize);
else
- std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolName);
+ std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName);
}
if (OutputFormat == posix && MultipleFiles) {
@@ -210,47 +205,46 @@ static void SortAndPrintSymbolList() {
<< " Size Line Section\n";
}
- for (SymbolListT::iterator i = SymbolList.begin(),
- e = SymbolList.end(); i != e; ++i) {
- if ((i->TypeChar != 'U') && UndefinedOnly)
+ for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end();
+ I != E; ++I) {
+ if ((I->TypeChar != 'U') && UndefinedOnly)
continue;
- if ((i->TypeChar == 'U') && DefinedOnly)
+ if ((I->TypeChar == 'U') && DefinedOnly)
continue;
- if (SizeSort && !PrintAddress && i->Size == UnknownAddressOrSize)
+ if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize)
continue;
char SymbolAddrStr[10] = "";
char SymbolSizeStr[10] = "";
- if (OutputFormat == sysv || i->Address == object::UnknownAddressOrSize)
+ if (OutputFormat == sysv || I->Address == UnknownAddressOrSize)
strcpy(SymbolAddrStr, " ");
if (OutputFormat == sysv)
strcpy(SymbolSizeStr, " ");
- if (i->Address != object::UnknownAddressOrSize)
- format("%08" PRIx64, i->Address).print(SymbolAddrStr,
- sizeof(SymbolAddrStr));
- if (i->Size != object::UnknownAddressOrSize)
- format("%08" PRIx64, i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
+ if (I->Address != UnknownAddressOrSize)
+ format("%08" PRIx64, I->Address)
+ .print(SymbolAddrStr, sizeof(SymbolAddrStr));
+ if (I->Size != UnknownAddressOrSize)
+ format("%08" PRIx64, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
if (OutputFormat == posix) {
- outs() << i->Name << " " << i->TypeChar << " "
- << SymbolAddrStr << SymbolSizeStr << "\n";
+ outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr
+ << SymbolSizeStr << "\n";
} else if (OutputFormat == bsd) {
if (PrintAddress)
outs() << SymbolAddrStr << ' ';
if (PrintSize) {
outs() << SymbolSizeStr;
- if (i->Size != object::UnknownAddressOrSize)
+ if (I->Size != UnknownAddressOrSize)
outs() << ' ';
}
- outs() << i->TypeChar << " " << i->Name << "\n";
+ outs() << I->TypeChar << " " << I->Name << "\n";
} else if (OutputFormat == sysv) {
- std::string PaddedName (i->Name);
- while (PaddedName.length () < 20)
+ std::string PaddedName(I->Name);
+ while (PaddedName.length() < 20)
PaddedName += " ";
- outs() << PaddedName << "|" << SymbolAddrStr << "| "
- << i->TypeChar
+ outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar
<< " | |" << SymbolSizeStr << "| |\n";
}
}
@@ -258,199 +252,103 @@ static void SortAndPrintSymbolList() {
SymbolList.clear();
}
-static char TypeCharForSymbol(GlobalValue &GV) {
- if (GV.isDeclaration()) return 'U';
- if (GV.hasLinkOnceLinkage()) return 'C';
- if (GV.hasCommonLinkage()) return 'C';
- if (GV.hasWeakLinkage()) return 'W';
- if (isa<Function>(GV) && GV.hasInternalLinkage()) return 't';
- if (isa<Function>(GV)) return 'T';
- if (isa<GlobalVariable>(GV) && GV.hasInternalLinkage()) return 'd';
- if (isa<GlobalVariable>(GV)) return 'D';
- if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) {
- const GlobalValue *AliasedGV = GA->getAliasedGlobal();
- if (isa<Function>(AliasedGV)) return 'T';
- if (isa<GlobalVariable>(AliasedGV)) return 'D';
- }
- return '?';
-}
-
-static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
- // Private linkage and available_externally linkage don't exist in symtab.
- if (GV.hasPrivateLinkage() ||
- GV.hasLinkerPrivateLinkage() ||
- GV.hasLinkerPrivateWeakLinkage() ||
- GV.hasAvailableExternallyLinkage())
- return;
- char TypeChar = TypeCharForSymbol(GV);
- if (GV.hasLocalLinkage () && ExternalOnly)
- return;
-
- NMSymbol s;
- s.Address = object::UnknownAddressOrSize;
- s.Size = object::UnknownAddressOrSize;
- s.TypeChar = TypeChar;
- s.Name = GV.getName();
- SymbolList.push_back(s);
-}
-
-static void DumpSymbolNamesFromModule(Module *M) {
- CurrentFilename = M->getModuleIdentifier();
- std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
- std::for_each (M->global_begin(), M->global_end(),
- DumpSymbolNameForGlobalValue);
- if (!WithoutAliases)
- std::for_each (M->alias_begin(), M->alias_end(),
- DumpSymbolNameForGlobalValue);
-
- SortAndPrintSymbolList();
-}
-
template <class ELFT>
-error_code getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, symbol_iterator I,
- char &Result) {
+static char getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj,
+ basic_symbol_iterator I) {
typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
+ // OK, this is ELF
+ symbol_iterator SymI(I);
+
DataRefImpl Symb = I->getRawDataRefImpl();
const Elf_Sym *ESym = Obj.getSymbol(Symb);
const ELFFile<ELFT> &EF = *Obj.getELFFile();
const Elf_Shdr *ESec = EF.getSection(ESym);
- char ret = '?';
-
if (ESec) {
switch (ESec->sh_type) {
case ELF::SHT_PROGBITS:
case ELF::SHT_DYNAMIC:
switch (ESec->sh_flags) {
case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) :
- ret = 't';
- break;
+ return 't';
+ case(ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE) :
case(ELF::SHF_ALLOC | ELF::SHF_WRITE) :
- ret = 'd';
- break;
+ return 'd';
case ELF::SHF_ALLOC:
case(ELF::SHF_ALLOC | ELF::SHF_MERGE) :
case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) :
- ret = 'r';
- break;
+ return 'r';
}
break;
case ELF::SHT_NOBITS:
- ret = 'b';
+ return 'b';
}
}
- switch (EF.getSymbolTableIndex(ESym)) {
- case ELF::SHN_UNDEF:
- if (ret == '?')
- ret = 'U';
- break;
- case ELF::SHN_ABS:
- ret = 'a';
- break;
- case ELF::SHN_COMMON:
- ret = 'c';
- break;
- }
-
- switch (ESym->getBinding()) {
- case ELF::STB_GLOBAL:
- ret = ::toupper(ret);
- break;
- case ELF::STB_WEAK:
- if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF)
- ret = 'w';
- else if (ESym->getType() == ELF::STT_OBJECT)
- ret = 'V';
- else
- ret = 'W';
- }
-
- if (ret == '?' && ESym->getType() == ELF::STT_SECTION) {
+ if (ESym->getType() == ELF::STT_SECTION) {
StringRef Name;
- error_code EC = I->getName(Name);
- if (EC)
- return EC;
- Result = StringSwitch<char>(Name)
- .StartsWith(".debug", 'N')
- .StartsWith(".note", 'n')
- .Default('?');
- return object_error::success;
+ if (error(SymI->getName(Name)))
+ return '?';
+ return StringSwitch<char>(Name)
+ .StartsWith(".debug", 'N')
+ .StartsWith(".note", 'n')
+ .Default('?');
}
- Result = ret;
- return object_error::success;
+ return '?';
}
-static error_code getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I,
- char &Result) {
- const coff_symbol *symb = Obj.getCOFFSymbol(I);
- StringRef name;
- if (error_code ec = I->getName(name))
- return ec;
- char ret = StringSwitch<char>(name)
+static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
+ const coff_symbol *Symb = Obj.getCOFFSymbol(*I);
+ // OK, this is COFF.
+ symbol_iterator SymI(I);
+
+ StringRef Name;
+ if (error(SymI->getName(Name)))
+ return '?';
+
+ char Ret = StringSwitch<char>(Name)
.StartsWith(".debug", 'N')
.StartsWith(".sxdata", 'N')
.Default('?');
- if (ret != '?') {
- Result = ret;
- return object_error::success;
- }
+ if (Ret != '?')
+ return Ret;
uint32_t Characteristics = 0;
- if (symb->SectionNumber > 0) {
- section_iterator SecI = Obj.end_sections();
- if (error_code ec = I->getSection(SecI))
- return ec;
- const coff_section *Section = Obj.getCOFFSection(SecI);
+ if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) {
+ section_iterator SecI = Obj.section_end();
+ if (error(SymI->getSection(SecI)))
+ return '?';
+ const coff_section *Section = Obj.getCOFFSection(*SecI);
Characteristics = Section->Characteristics;
}
- switch (symb->SectionNumber) {
- case COFF::IMAGE_SYM_UNDEFINED:
- // Check storage classes.
- if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
- Result = 'w';
- return object_error::success; // Don't do ::toupper.
- } else if (symb->Value != 0) // Check for common symbols.
- ret = 'c';
- else
- ret = 'u';
- break;
- case COFF::IMAGE_SYM_ABSOLUTE:
- ret = 'a';
- break;
+ switch (Symb->SectionNumber) {
case COFF::IMAGE_SYM_DEBUG:
- ret = 'n';
- break;
+ return 'n';
default:
// Check section type.
if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
- ret = 't';
+ return 't';
else if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
- ret = 'r';
+ return 'r';
else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
- ret = 'd';
+ return 'd';
else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- ret = 'b';
+ return 'b';
else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
- ret = 'i';
+ return 'i';
// Check for section symbol.
- else if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC &&
- symb->Value == 0)
- ret = 's';
+ else if (Symb->isSectionDefinition())
+ return 's';
}
- if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
- ret = ::toupper(static_cast<unsigned char>(ret));
-
- Result = ret;
- return object_error::success;
+ return '?';
}
static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) {
@@ -462,205 +360,226 @@ static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) {
return STE.n_type;
}
-static error_code getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I,
- char &Res) {
+static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
DataRefImpl Symb = I->getRawDataRefImpl();
uint8_t NType = getNType(Obj, Symb);
- char Char;
switch (NType & MachO::N_TYPE) {
- case MachO::N_UNDF:
- Char = 'u';
- break;
case MachO::N_ABS:
- Char = 's';
- break;
+ return 's';
case MachO::N_SECT: {
- section_iterator Sec = Obj.end_sections();
+ section_iterator Sec = Obj.section_end();
Obj.getSymbolSection(Symb, Sec);
DataRefImpl Ref = Sec->getRawDataRefImpl();
StringRef SectionName;
Obj.getSectionName(Ref, SectionName);
StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
if (SegmentName == "__TEXT" && SectionName == "__text")
- Char = 't';
+ return 't';
else
- Char = 's';
- } break;
- default:
- Char = '?';
- break;
+ return 's';
+ }
}
- if (NType & (MachO::N_EXT | MachO::N_PEXT))
- Char = toupper(static_cast<unsigned char>(Char));
- Res = Char;
- return object_error::success;
+ return '?';
}
-static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) {
- char Res = '?';
- if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj)) {
- error(getSymbolNMTypeChar(*COFF, I, Res));
- return Res;
- }
- if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj)) {
- error(getSymbolNMTypeChar(*MachO, I, Res));
- return Res;
- }
+static char getSymbolNMTypeChar(const GlobalValue &GV) {
+ if (isa<Function>(GV))
+ return 't';
+ // FIXME: should we print 'b'? At the IR level we cannot be sure if this
+ // will be in bss or not, but we could approximate.
+ if (isa<GlobalVariable>(GV))
+ return 'd';
+ const GlobalAlias *GA = cast<GlobalAlias>(&GV);
+ const GlobalValue *AliasedGV = GA->getAliasedGlobal();
+ return getSymbolNMTypeChar(*AliasedGV);
+}
- if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) {
- error(getSymbolNMTypeChar(*ELF, I, Res));
- return Res;
- }
- if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) {
- error(getSymbolNMTypeChar(*ELF, I, Res));
- return Res;
- }
- if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) {
- error(getSymbolNMTypeChar(*ELF, I, Res));
- return Res;
+static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
+ const GlobalValue &GV = Obj.getSymbolGV(I->getRawDataRefImpl());
+ return getSymbolNMTypeChar(GV);
+}
+
+template <class ELFT>
+static bool isObject(ELFObjectFile<ELFT> &Obj, symbol_iterator I) {
+ typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
+
+ DataRefImpl Symb = I->getRawDataRefImpl();
+ const Elf_Sym *ESym = Obj.getSymbol(Symb);
+
+ return ESym->getType() == ELF::STT_OBJECT;
+}
+
+static bool isObject(SymbolicFile *Obj, basic_symbol_iterator I) {
+ if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
+ return isObject(*ELF, I);
+ if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
+ return isObject(*ELF, I);
+ if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
+ return isObject(*ELF, I);
+ if (ELF64BEObjectFile *ELF = dyn_cast<ELF64BEObjectFile>(Obj))
+ return isObject(*ELF, I);
+ return false;
+}
+
+static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) {
+ uint32_t Symflags = I->getFlags();
+ if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) {
+ char Ret = isObject(Obj, I) ? 'v' : 'w';
+ if (!(Symflags & object::SymbolRef::SF_Undefined))
+ Ret = toupper(Ret);
+ return Ret;
}
- ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj);
- error(getSymbolNMTypeChar(*ELF, I, Res));
- return Res;
+
+ if (Symflags & object::SymbolRef::SF_Undefined)
+ return 'U';
+
+ if (Symflags & object::SymbolRef::SF_Common)
+ return 'C';
+
+ char Ret = '?';
+ if (Symflags & object::SymbolRef::SF_Absolute)
+ Ret = 'a';
+ else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*IR, I);
+ else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*COFF, I);
+ else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*MachO, I);
+ else if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*ELF, I);
+ else if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*ELF, I);
+ else if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
+ Ret = getSymbolNMTypeChar(*ELF, I);
+ else
+ Ret = getSymbolNMTypeChar(*cast<ELF64BEObjectFile>(Obj), I);
+
+ if (Symflags & object::SymbolRef::SF_Global)
+ Ret = toupper(Ret);
+
+ return Ret;
}
-static void DumpSymbolNamesFromObject(ObjectFile *obj) {
- error_code ec;
- symbol_iterator ibegin = obj->begin_symbols();
- symbol_iterator iend = obj->end_symbols();
+static void dumpSymbolNamesFromObject(SymbolicFile *Obj) {
+ basic_symbol_iterator IBegin = Obj->symbol_begin();
+ basic_symbol_iterator IEnd = Obj->symbol_end();
if (DynamicSyms) {
- ibegin = obj->begin_dynamic_symbols();
- iend = obj->end_dynamic_symbols();
+ if (!Obj->isELF()) {
+ error("File format has no dynamic symbol table", Obj->getFileName());
+ return;
+ }
+ std::pair<symbol_iterator, symbol_iterator> IDyn =
+ getELFDynamicSymbolIterators(Obj);
+ IBegin = IDyn.first;
+ IEnd = IDyn.second;
}
- for (symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
- if (error(ec)) break;
- uint32_t symflags;
- if (error(i->getFlags(symflags))) break;
- if (!DebugSyms && (symflags & SymbolRef::SF_FormatSpecific))
+ std::string NameBuffer;
+ raw_string_ostream OS(NameBuffer);
+ for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) {
+ uint32_t SymFlags = I->getFlags();
+ if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
continue;
- NMSymbol s;
- s.Size = object::UnknownAddressOrSize;
- s.Address = object::UnknownAddressOrSize;
- if (PrintSize || SizeSort) {
- if (error(i->getSize(s.Size))) break;
+ if (WithoutAliases) {
+ if (IRObjectFile *IR = dyn_cast<IRObjectFile>(Obj)) {
+ const GlobalValue &GV = IR->getSymbolGV(I->getRawDataRefImpl());
+ if(isa<GlobalAlias>(GV))
+ continue;
+ }
}
- if (PrintAddress)
- if (error(i->getAddress(s.Address))) break;
- s.TypeChar = getNMTypeChar(obj, i);
- if (error(i->getName(s.Name))) break;
- SymbolList.push_back(s);
+ NMSymbol S;
+ S.Size = UnknownAddressOrSize;
+ S.Address = UnknownAddressOrSize;
+ if ((PrintSize || SizeSort) && isa<ObjectFile>(Obj)) {
+ symbol_iterator SymI = I;
+ if (error(SymI->getSize(S.Size)))
+ break;
+ }
+ if (PrintAddress && isa<ObjectFile>(Obj))
+ if (error(symbol_iterator(I)->getAddress(S.Address)))
+ break;
+ S.TypeChar = getNMTypeChar(Obj, I);
+ if (error(I->printName(OS)))
+ break;
+ OS << '\0';
+ SymbolList.push_back(S);
}
- CurrentFilename = obj->getFileName();
- SortAndPrintSymbolList();
-}
-
-static void DumpSymbolNamesFromFile(std::string &Filename) {
- if (Filename != "-" && !sys::fs::exists(Filename)) {
- errs() << ToolName << ": '" << Filename << "': " << "No such file\n";
- return;
+ OS.flush();
+ const char *P = NameBuffer.c_str();
+ for (unsigned I = 0; I < SymbolList.size(); ++I) {
+ SymbolList[I].Name = P;
+ P += strlen(P) + 1;
}
- OwningPtr<MemoryBuffer> Buffer;
+ CurrentFilename = Obj->getFileName();
+ sortAndPrintSymbolList();
+}
+
+static void dumpSymbolNamesFromFile(std::string &Filename) {
+ std::unique_ptr<MemoryBuffer> Buffer;
if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename))
return;
- sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());
-
LLVMContext &Context = getGlobalContext();
- std::string ErrorMessage;
- if (magic == sys::fs::file_magic::bitcode) {
- Module *Result = 0;
- Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);
- if (Result) {
- DumpSymbolNamesFromModule(Result);
- delete Result;
- } else {
- error(ErrorMessage, Filename);
- return;
- }
- } else if (magic == sys::fs::file_magic::archive) {
- OwningPtr<Binary> arch;
- if (error(object::createBinary(Buffer.take(), arch), Filename))
- return;
-
- if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
- if (ArchiveMap) {
- 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)))
- return;
- if (error(c->getName(filename)))
- return;
- outs() << symname << " in " << filename << "\n";
- }
- outs() << "\n";
- }
- }
-
- for (object::Archive::child_iterator i = a->begin_children(),
- e = a->end_children(); i != e; ++i) {
- OwningPtr<Binary> child;
- if (i->getAsBinary(child)) {
- // Try opening it as a bitcode file.
- OwningPtr<MemoryBuffer> buff;
- if (error(i->getMemoryBuffer(buff)))
+ ErrorOr<Binary *> BinaryOrErr = createBinary(Buffer.release(), &Context);
+ if (error(BinaryOrErr.getError(), Filename))
+ return;
+ std::unique_ptr<Binary> Bin(BinaryOrErr.get());
+
+ if (Archive *A = dyn_cast<Archive>(Bin.get())) {
+ if (ArchiveMap) {
+ Archive::symbol_iterator I = A->symbol_begin();
+ Archive::symbol_iterator E = A->symbol_end();
+ if (I != E) {
+ outs() << "Archive map\n";
+ for (; I != E; ++I) {
+ Archive::child_iterator C;
+ StringRef SymName;
+ StringRef FileName;
+ if (error(I->getMember(C)))
return;
- Module *Result = 0;
- if (buff)
- Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage);
-
- if (Result) {
- DumpSymbolNamesFromModule(Result);
- delete Result;
- }
- continue;
- }
- if (object::ObjectFile *o = dyn_cast<ObjectFile>(child.get())) {
- outs() << o->getFileName() << ":\n";
- DumpSymbolNamesFromObject(o);
+ if (error(I->getName(SymName)))
+ return;
+ if (error(C->getName(FileName)))
+ return;
+ outs() << SymName << " in " << FileName << "\n";
}
+ outs() << "\n";
}
}
- } 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();
+ for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
+ I != E; ++I) {
+ std::unique_ptr<Binary> Child;
+ if (I->getAsBinary(Child, &Context))
+ continue;
+ if (SymbolicFile *O = dyn_cast<SymbolicFile>(Child.get())) {
+ outs() << O->getFileName() << ":\n";
+ dumpSymbolNamesFromObject(O);
+ }
+ }
+ return;
+ }
+ if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin.get())) {
+ for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
+ E = UB->end_objects();
I != E; ++I) {
- OwningPtr<ObjectFile> Obj;
+ std::unique_ptr<ObjectFile> Obj;
if (!I->getAsObjectFile(Obj)) {
outs() << Obj->getFileName() << ":\n";
- DumpSymbolNamesFromObject(Obj.get());
+ dumpSymbolNamesFromObject(Obj.get());
}
}
- } else if (magic.is_object()) {
- OwningPtr<Binary> obj;
- if (error(object::createBinary(Buffer.take(), obj), Filename))
- return;
- if (object::ObjectFile *o = dyn_cast<ObjectFile>(obj.get()))
- DumpSymbolNamesFromObject(o);
- } else {
- errs() << ToolName << ": " << Filename << ": "
- << "unrecognizable file type\n";
- HadError = true;
return;
}
+ if (SymbolicFile *O = dyn_cast<SymbolicFile>(Bin.get())) {
+ dumpSymbolNamesFromObject(O);
+ return;
+ }
+ error("unrecognizable file type", Filename);
+ return;
}
int main(int argc, char **argv) {
@@ -668,7 +587,7 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
// llvm-nm only reads binary files.
@@ -676,23 +595,30 @@ int main(int argc, char **argv) {
return 1;
ToolName = argv[0];
- if (BSDFormat) OutputFormat = bsd;
- if (POSIXFormat) OutputFormat = posix;
+ if (BSDFormat)
+ OutputFormat = bsd;
+ if (POSIXFormat)
+ OutputFormat = posix;
// The relative order of these is important. If you pass --size-sort it should
// only print out the size. However, if you pass -S --size-sort, it should
// print out both the size and address.
- if (SizeSort && !PrintSize) PrintAddress = false;
- if (OutputFormat == sysv || SizeSort) PrintSize = true;
+ if (SizeSort && !PrintSize)
+ PrintAddress = false;
+ if (OutputFormat == sysv || SizeSort)
+ PrintSize = true;
switch (InputFilenames.size()) {
- case 0: InputFilenames.push_back("-");
- case 1: break;
- default: MultipleFiles = true;
+ case 0:
+ InputFilenames.push_back("-");
+ case 1:
+ break;
+ default:
+ MultipleFiles = true;
}
std::for_each(InputFilenames.begin(), InputFilenames.end(),
- DumpSymbolNamesFromFile);
+ dumpSymbolNamesFromFile);
if (HadError)
return 1;
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index e983ec9..413cb9b 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -2,9 +2,8 @@ set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
DebugInfo
MC
- MCParser
- MCDisassembler
Object
+ Support
)
add_llvm_tool(llvm-objdump
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
index 5f0bcbb..49f2755 100644
--- a/tools/llvm-objdump/COFFDump.cpp
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -10,7 +10,7 @@
/// \file
/// \brief This file implements the COFF-specific dumper for llvm-objdump.
/// It outputs the Win64 EH data structures as plain text.
-/// The encoding of the unwind codes is decribed in MSDN:
+/// The encoding of the unwind codes is described in MSDN:
/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
///
//===----------------------------------------------------------------------===//
@@ -94,7 +94,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
// slots is provided.
static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
assert(UCs.size() >= getNumUsedSlots(UCs[0]));
- outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset))
+ outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset))
<< getUnwindCodeTypeName(UCs[0].getUnwindOp());
switch (UCs[0].getUnwindOp()) {
case UOP_PushNonVol:
@@ -161,10 +161,12 @@ static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
const SymbolRef &Sym,
const coff_section *&ResolvedSection,
uint64_t &ResolvedAddr) {
- if (error_code ec = Sym.getAddress(ResolvedAddr)) return ec;
- section_iterator iter(Obj->begin_sections());
- if (error_code ec = Sym.getSection(iter)) return ec;
- ResolvedSection = Obj->getCOFFSection(iter);
+ if (error_code EC = Sym.getAddress(ResolvedAddr))
+ return EC;
+ section_iterator iter(Obj->section_begin());
+ if (error_code EC = Sym.getSection(iter))
+ return EC;
+ ResolvedSection = Obj->getCOFFSection(*iter);
return object_error::success;
}
@@ -176,13 +178,14 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
E = Rels.end();
I != E; ++I) {
uint64_t Ofs;
- if (error_code ec = I->getOffset(Ofs)) return ec;
+ if (error_code EC = I->getOffset(Ofs))
+ return EC;
if (Ofs == Offset) {
Sym = *I->getSymbol();
- break;
+ return object_error::success;
}
}
- return object_error::success;
+ return object_error::parse_failed;
}
// Given a vector of relocations for a section and an offset into this section
@@ -195,11 +198,13 @@ static error_code getSectionContents(const COFFObjectFile *Obj,
ArrayRef<uint8_t> &Contents,
uint64_t &Addr) {
SymbolRef Sym;
- if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec;
+ if (error_code EC = resolveSymbol(Rels, Offset, Sym))
+ return EC;
const coff_section *Section;
- if (error_code ec = resolveSectionAndAddress(Obj, Sym, Section, Addr))
- return ec;
- if (error_code ec = Obj->getSectionContents(Section, Contents)) return ec;
+ if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
+ return EC;
+ if (error_code EC = Obj->getSectionContents(Section, Contents))
+ return EC;
return object_error::success;
}
@@ -209,8 +214,10 @@ static error_code getSectionContents(const COFFObjectFile *Obj,
static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
uint64_t Offset, StringRef &Name) {
SymbolRef Sym;
- if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec;
- if (error_code ec = Sym.getName(Name)) return ec;
+ if (error_code EC = resolveSymbol(Rels, Offset, Sym))
+ return EC;
+ if (error_code EC = Sym.getName(Name))
+ return EC;
return object_error::success;
}
@@ -218,30 +225,95 @@ static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
const std::vector<RelocationRef> &Rels,
uint64_t Offset, uint32_t Disp) {
StringRef Sym;
- if (error_code ec = resolveSymbolName(Rels, Offset, Sym)) {
- error(ec);
- return ;
+ if (!resolveSymbolName(Rels, Offset, Sym)) {
+ Out << Sym;
+ if (Disp > 0)
+ Out << format(" + 0x%04x", Disp);
+ } else {
+ Out << format("0x%04x", Disp);
}
- Out << Sym;
- if (Disp > 0)
- Out << format(" + 0x%04x", Disp);
+}
+
+static void
+printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
+ if (Count == 0)
+ return;
+
+ const pe32_header *PE32Header;
+ if (error(Obj->getPE32Header(PE32Header)))
+ return;
+ uint32_t ImageBase = PE32Header->ImageBase;
+ uintptr_t IntPtr = 0;
+ if (error(Obj->getVaPtr(TableVA, IntPtr)))
+ return;
+ const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
+ outs() << "SEH Table:";
+ for (int I = 0; I < Count; ++I)
+ outs() << format(" 0x%x", P[I] + ImageBase);
+ outs() << "\n\n";
+}
+
+static void printLoadConfiguration(const COFFObjectFile *Obj) {
+ // Skip if it's not executable.
+ const pe32_header *PE32Header;
+ if (error(Obj->getPE32Header(PE32Header)))
+ return;
+ if (!PE32Header)
+ return;
+
+ const coff_file_header *Header;
+ if (error(Obj->getCOFFHeader(Header)))
+ return;
+ // Currently only x86 is supported
+ if (Header->Machine != COFF::IMAGE_FILE_MACHINE_I386)
+ return;
+
+ const data_directory *DataDir;
+ if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir)))
+ return;
+ uintptr_t IntPtr = 0;
+ if (DataDir->RelativeVirtualAddress == 0)
+ return;
+ if (error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr)))
+ return;
+
+ auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
+ outs() << "Load configuration:"
+ << "\n Timestamp: " << LoadConf->TimeDateStamp
+ << "\n Major Version: " << LoadConf->MajorVersion
+ << "\n Minor Version: " << LoadConf->MinorVersion
+ << "\n GlobalFlags Clear: " << LoadConf->GlobalFlagsClear
+ << "\n GlobalFlags Set: " << LoadConf->GlobalFlagsSet
+ << "\n Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout
+ << "\n Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold
+ << "\n Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold
+ << "\n Lock Prefix Table: " << LoadConf->LockPrefixTable
+ << "\n Maximum Allocation Size: " << LoadConf->MaximumAllocationSize
+ << "\n Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold
+ << "\n Process Affinity Mask: " << LoadConf->ProcessAffinityMask
+ << "\n Process Heap Flags: " << LoadConf->ProcessHeapFlags
+ << "\n CSD Version: " << LoadConf->CSDVersion
+ << "\n Security Cookie: " << LoadConf->SecurityCookie
+ << "\n SEH Table: " << LoadConf->SEHandlerTable
+ << "\n SEH Count: " << LoadConf->SEHandlerCount
+ << "\n\n";
+ printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount);
+ outs() << "\n";
}
// Prints import tables. The import table is a table containing the list of
// DLL name and symbol names which will be linked by the loader.
static void printImportTables(const COFFObjectFile *Obj) {
+ import_directory_iterator I = Obj->import_directory_begin();
+ import_directory_iterator E = Obj->import_directory_end();
+ if (I == E)
+ return;
outs() << "The Import Tables:\n";
- error_code ec;
- for (import_directory_iterator i = Obj->import_directory_begin(),
- e = Obj->import_directory_end();
- i != e; i = i.increment(ec)) {
- if (ec)
- return;
-
+ for (; I != E; I = ++I) {
const import_directory_table_entry *Dir;
StringRef Name;
- if (i->getImportTableEntry(Dir)) return;
- if (i->getName(Name)) return;
+ if (I->getImportTableEntry(Dir)) return;
+ if (I->getName(Name)) return;
outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
static_cast<uint32_t>(Dir->ImportLookupTableRVA),
@@ -252,7 +324,7 @@ static void printImportTables(const COFFObjectFile *Obj) {
outs() << " DLL Name: " << Name << "\n";
outs() << " Hint/Ord Name\n";
const import_lookup_table_entry32 *entry;
- if (i->getImportLookupEntry(entry))
+ if (I->getImportLookupEntry(entry))
return;
for (; entry->data; ++entry) {
if (entry->isOrdinal()) {
@@ -269,133 +341,218 @@ static void printImportTables(const COFFObjectFile *Obj) {
}
}
-void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
- const coff_file_header *Header;
- if (error(Obj->getCOFFHeader(Header))) return;
-
- if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
- errs() << "Unsupported image machine type "
- "(currently only AMD64 is supported).\n";
+// Prints export tables. The export table is a table containing the list of
+// exported symbol from the DLL.
+static void printExportTable(const COFFObjectFile *Obj) {
+ outs() << "Export Table:\n";
+ export_directory_iterator I = Obj->export_directory_begin();
+ export_directory_iterator E = Obj->export_directory_end();
+ if (I == E)
return;
- }
-
- const coff_section *Pdata = 0;
-
- error_code ec;
- for (section_iterator SI = Obj->begin_sections(),
- SE = Obj->end_sections();
- SI != SE; SI.increment(ec)) {
- if (error(ec)) return;
+ StringRef DllName;
+ uint32_t OrdinalBase;
+ if (I->getDllName(DllName))
+ return;
+ if (I->getOrdinalBase(OrdinalBase))
+ return;
+ outs() << " DLL name: " << DllName << "\n";
+ outs() << " Ordinal base: " << OrdinalBase << "\n";
+ outs() << " Ordinal RVA Name\n";
+ for (; I != E; I = ++I) {
+ uint32_t Ordinal;
+ if (I->getOrdinal(Ordinal))
+ return;
+ uint32_t RVA;
+ if (I->getExportRVA(RVA))
+ return;
+ outs() << format(" % 4d %# 8x", Ordinal, RVA);
StringRef Name;
- if (error(SI->getName(Name))) continue;
+ if (I->getSymbolName(Name))
+ continue;
+ if (!Name.empty())
+ outs() << " " << Name;
+ outs() << "\n";
+ }
+}
- if (Name != ".pdata") continue;
+// Given the COFF object file, this function returns the relocations for .pdata
+// and the pointer to "runtime function" structs.
+static bool getPDataSection(const COFFObjectFile *Obj,
+ std::vector<RelocationRef> &Rels,
+ const RuntimeFunction *&RFStart, int &NumRFs) {
+ for (const SectionRef &Section : Obj->sections()) {
+ StringRef Name;
+ if (error(Section.getName(Name)))
+ continue;
+ if (Name != ".pdata")
+ continue;
- Pdata = Obj->getCOFFSection(SI);
- std::vector<RelocationRef> Rels;
- for (relocation_iterator RI = SI->begin_relocations(),
- RE = SI->end_relocations();
- RI != RE; RI.increment(ec)) {
- if (error(ec)) break;
- Rels.push_back(*RI);
- }
+ const coff_section *Pdata = Obj->getCOFFSection(Section);
+ for (const RelocationRef &Reloc : Section.relocations())
+ Rels.push_back(Reloc);
// Sort relocations by address.
std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(Pdata, Contents))) continue;
- if (Contents.empty()) continue;
+ if (error(Obj->getSectionContents(Pdata, Contents)))
+ continue;
+ if (Contents.empty())
+ continue;
+
+ RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data());
+ NumRFs = Contents.size() / sizeof(RuntimeFunction);
+ return true;
+ }
+ return false;
+}
- ArrayRef<RuntimeFunction> RFs(
- reinterpret_cast<const RuntimeFunction *>(Contents.data()),
- Contents.size() / sizeof(RuntimeFunction));
- for (const RuntimeFunction *I = RFs.begin(), *E = RFs.end(); I < E; ++I) {
- const uint64_t SectionOffset = std::distance(RFs.begin(), I)
- * sizeof(RuntimeFunction);
+static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
+ // The casts to int are required in order to output the value as number.
+ // Without the casts the value would be interpreted as char data (which
+ // results in garbage output).
+ outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n";
+ outs() << " Flags: " << static_cast<int>(UI->getFlags());
+ if (UI->getFlags()) {
+ if (UI->getFlags() & UNW_ExceptionHandler)
+ outs() << " UNW_ExceptionHandler";
+ if (UI->getFlags() & UNW_TerminateHandler)
+ outs() << " UNW_TerminateHandler";
+ if (UI->getFlags() & UNW_ChainInfo)
+ outs() << " UNW_ChainInfo";
+ }
+ outs() << "\n";
+ outs() << " Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n";
+ outs() << " Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n";
+ // Maybe this should move to output of UOP_SetFPReg?
+ if (UI->getFrameRegister()) {
+ outs() << " Frame register: "
+ << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
+ outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n";
+ } else {
+ outs() << " No frame pointer used\n";
+ }
+ if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
+ // FIXME: Output exception handler data
+ } else if (UI->getFlags() & UNW_ChainInfo) {
+ // FIXME: Output chained unwind info
+ }
- outs() << "Function Table:\n";
+ if (UI->NumCodes)
+ outs() << " Unwind Codes:\n";
- outs() << " Start Address: ";
- printCOFFSymbolAddress(outs(), Rels, SectionOffset +
+ printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], UI->NumCodes));
+
+ outs() << "\n";
+ outs().flush();
+}
+
+/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
+/// pointing to an executable file.
+static void printRuntimeFunction(const COFFObjectFile *Obj,
+ const RuntimeFunction &RF) {
+ if (!RF.StartAddress)
+ return;
+ outs() << "Function Table:\n"
+ << format(" Start Address: 0x%04x\n",
+ static_cast<uint32_t>(RF.StartAddress))
+ << format(" End Address: 0x%04x\n",
+ static_cast<uint32_t>(RF.EndAddress))
+ << format(" Unwind Info Address: 0x%04x\n",
+ static_cast<uint32_t>(RF.UnwindInfoOffset));
+ uintptr_t addr;
+ if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
+ return;
+ printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr));
+}
+
+/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
+/// pointing to an object file. Unlike executable, fields in RuntimeFunction
+/// struct are filled with zeros, but instead there are relocations pointing to
+/// them so that the linker will fill targets' RVAs to the fields at link
+/// time. This function interprets the relocations to find the data to be used
+/// in the resulting executable.
+static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
+ const RuntimeFunction &RF,
+ uint64_t SectionOffset,
+ const std::vector<RelocationRef> &Rels) {
+ outs() << "Function Table:\n";
+ outs() << " Start Address: ";
+ printCOFFSymbolAddress(outs(), Rels,
+ SectionOffset +
/*offsetof(RuntimeFunction, StartAddress)*/ 0,
- I->StartAddress);
- outs() << "\n";
+ RF.StartAddress);
+ outs() << "\n";
- outs() << " End Address: ";
- printCOFFSymbolAddress(outs(), Rels, SectionOffset +
+ outs() << " End Address: ";
+ printCOFFSymbolAddress(outs(), Rels,
+ SectionOffset +
/*offsetof(RuntimeFunction, EndAddress)*/ 4,
- I->EndAddress);
- outs() << "\n";
+ RF.EndAddress);
+ outs() << "\n";
- outs() << " Unwind Info Address: ";
- printCOFFSymbolAddress(outs(), Rels, SectionOffset +
+ outs() << " Unwind Info Address: ";
+ printCOFFSymbolAddress(outs(), Rels,
+ SectionOffset +
/*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
- I->UnwindInfoOffset);
- outs() << "\n";
-
- ArrayRef<uint8_t> XContents;
- uint64_t UnwindInfoOffset = 0;
- if (error(getSectionContents(Obj, Rels, SectionOffset +
- /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
- XContents, UnwindInfoOffset))) continue;
- if (XContents.empty()) continue;
-
- UnwindInfoOffset += I->UnwindInfoOffset;
- if (UnwindInfoOffset > XContents.size()) continue;
-
- const Win64EH::UnwindInfo *UI =
- reinterpret_cast<const Win64EH::UnwindInfo *>
- (XContents.data() + UnwindInfoOffset);
-
- // The casts to int are required in order to output the value as number.
- // Without the casts the value would be interpreted as char data (which
- // results in garbage output).
- outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n";
- outs() << " Flags: " << static_cast<int>(UI->getFlags());
- if (UI->getFlags()) {
- if (UI->getFlags() & UNW_ExceptionHandler)
- outs() << " UNW_ExceptionHandler";
- if (UI->getFlags() & UNW_TerminateHandler)
- outs() << " UNW_TerminateHandler";
- if (UI->getFlags() & UNW_ChainInfo)
- outs() << " UNW_ChainInfo";
- }
- outs() << "\n";
- outs() << " Size of prolog: "
- << static_cast<int>(UI->PrologSize) << "\n";
- outs() << " Number of Codes: "
- << static_cast<int>(UI->NumCodes) << "\n";
- // Maybe this should move to output of UOP_SetFPReg?
- if (UI->getFrameRegister()) {
- outs() << " Frame register: "
- << getUnwindRegisterName(UI->getFrameRegister())
- << "\n";
- outs() << " Frame offset: "
- << 16 * UI->getFrameOffset()
- << "\n";
- } else {
- outs() << " No frame pointer used\n";
- }
- if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
- // FIXME: Output exception handler data
- } else if (UI->getFlags() & UNW_ChainInfo) {
- // FIXME: Output chained unwind info
- }
+ RF.UnwindInfoOffset);
+ outs() << "\n";
- if (UI->NumCodes)
- outs() << " Unwind Codes:\n";
+ ArrayRef<uint8_t> XContents;
+ uint64_t UnwindInfoOffset = 0;
+ if (error(getSectionContents(
+ Obj, Rels, SectionOffset +
+ /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
+ XContents, UnwindInfoOffset)))
+ return;
+ if (XContents.empty())
+ return;
- printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0],
- UI->NumCodes));
+ UnwindInfoOffset += RF.UnwindInfoOffset;
+ if (UnwindInfoOffset > XContents.size())
+ return;
- outs() << "\n\n";
- outs().flush();
- }
+ auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() +
+ UnwindInfoOffset);
+ printWin64EHUnwindInfo(UI);
+}
+
+void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
+ const coff_file_header *Header;
+ if (error(Obj->getCOFFHeader(Header)))
+ return;
+
+ if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
+ errs() << "Unsupported image machine type "
+ "(currently only AMD64 is supported).\n";
+ return;
+ }
+
+ std::vector<RelocationRef> Rels;
+ const RuntimeFunction *RFStart;
+ int NumRFs;
+ if (!getPDataSection(Obj, Rels, RFStart, NumRFs))
+ return;
+ ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs);
+
+ bool IsExecutable = Rels.empty();
+ if (IsExecutable) {
+ for (const RuntimeFunction &RF : RFs)
+ printRuntimeFunction(Obj, RF);
+ return;
+ }
+
+ for (const RuntimeFunction &RF : RFs) {
+ uint64_t SectionOffset =
+ std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
+ printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
}
}
void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
- printImportTables(dyn_cast<const COFFObjectFile>(Obj));
+ const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
+ printLoadConfiguration(file);
+ printImportTables(file);
+ printExportTable(file);
}
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index 86923fd..89b038f 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
@@ -147,28 +146,23 @@ static void DumpDataInCode(const char *bytes, uint64_t Size,
}
}
-static void
-getSectionsAndSymbols(const MachO::mach_header Header,
- MachOObjectFile *MachOObj,
- std::vector<SectionRef> &Sections,
- std::vector<SymbolRef> &Symbols,
- SmallVectorImpl<uint64_t> &FoundFns,
- uint64_t &BaseSegmentAddress) {
- error_code ec;
- for (symbol_iterator SI = MachOObj->begin_symbols(),
- SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec))
- Symbols.push_back(*SI);
-
- for (section_iterator SI = MachOObj->begin_sections(),
- SE = MachOObj->end_sections(); SI != SE; SI.increment(ec)) {
- SectionRef SR = *SI;
+static void getSectionsAndSymbols(const MachO::mach_header Header,
+ MachOObjectFile *MachOObj,
+ std::vector<SectionRef> &Sections,
+ std::vector<SymbolRef> &Symbols,
+ SmallVectorImpl<uint64_t> &FoundFns,
+ uint64_t &BaseSegmentAddress) {
+ for (const SymbolRef &Symbol : MachOObj->symbols())
+ Symbols.push_back(Symbol);
+
+ for (const SectionRef &Section : MachOObj->sections()) {
StringRef SectName;
- SR.getName(SectName);
- Sections.push_back(*SI);
+ Section.getName(SectName);
+ Sections.push_back(Section);
}
MachOObjectFile::LoadCommandInfo Command =
- MachOObj->getFirstLoadCommandInfo();
+ MachOObj->getFirstLoadCommandInfo();
bool BaseSegmentAddressSet = false;
for (unsigned i = 0; ; ++i) {
if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
@@ -200,15 +194,15 @@ static void DisassembleInputMachO2(StringRef Filename,
MachOObjectFile *MachOOF);
void llvm::DisassembleInputMachO(StringRef Filename) {
- OwningPtr<MemoryBuffer> Buff;
+ std::unique_ptr<MemoryBuffer> Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n";
return;
}
- OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>(
- ObjectFile::createMachOObjectFile(Buff.take())));
+ std::unique_ptr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile *>(
+ ObjectFile::createMachOObjectFile(Buff.release()).get()));
DisassembleInputMachO2(Filename, MachOOF.get());
}
@@ -220,21 +214,22 @@ static void DisassembleInputMachO2(StringRef Filename,
// GetTarget prints out stuff.
return;
}
- OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
- OwningPtr<MCInstrAnalysis>
- InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
+ std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
+ std::unique_ptr<MCInstrAnalysis> InstrAnalysis(
+ TheTarget->createMCInstrAnalysis(InstrInfo.get()));
// Set up disassembler.
- OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
- OwningPtr<const MCAsmInfo> AsmInfo(
+ std::unique_ptr<const MCRegisterInfo> MRI(
+ TheTarget->createMCRegInfo(TripleName));
+ std::unique_ptr<const MCAsmInfo> AsmInfo(
TheTarget->createMCAsmInfo(*MRI, TripleName));
- OwningPtr<const MCSubtargetInfo>
- STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
- OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
+ std::unique_ptr<const MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ std::unique_ptr<const MCDisassembler> DisAsm(
+ TheTarget->createMCDisassembler(*STI));
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
- OwningPtr<MCInstPrinter>
- IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo,
- *MRI, *STI));
+ std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI));
if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) {
errs() << "error: couldn't initialize disassembler for target "
@@ -270,9 +265,8 @@ static void DisassembleInputMachO2(StringRef Filename,
else
BaseAddress = BaseSegmentAddress;
DiceTable Dices;
- error_code ec;
for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
- DI != DE; DI.increment(ec)){
+ DI != DE; ++DI) {
uint32_t Offset;
DI->getOffset(Offset);
Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
@@ -285,19 +279,19 @@ static void DisassembleInputMachO2(StringRef Filename,
raw_ostream &DebugOut = nulls();
#endif
- OwningPtr<DIContext> diContext;
+ std::unique_ptr<DIContext> diContext;
ObjectFile *DbgObj = MachOOF;
// Try to find debug info and set up the DIContext for it.
if (UseDbg) {
// A separate DSym file path was specified, parse it as a macho file,
// get the sections and supply it to the section name parsing machinery.
if (!DSYMFile.empty()) {
- OwningPtr<MemoryBuffer> Buf;
+ std::unique_ptr<MemoryBuffer> Buf;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile, Buf)) {
errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
return;
}
- DbgObj = ObjectFile::createMachOObjectFile(Buf.take());
+ DbgObj = ObjectFile::createMachOObjectFile(Buf.release()).get();
}
// Setup the DIContext
@@ -328,16 +322,14 @@ static void DisassembleInputMachO2(StringRef Filename,
bool symbolTableWorked = false;
// Parse relocations.
- std::vector<std::pair<uint64_t, SymbolRef> > Relocs;
- error_code ec;
- for (relocation_iterator RI = Sections[SectIdx].begin_relocations(),
- RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) {
+ std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
+ for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
uint64_t RelocOffset, SectionAddress;
- RI->getOffset(RelocOffset);
+ Reloc.getOffset(RelocOffset);
Sections[SectIdx].getAddress(SectionAddress);
RelocOffset -= SectionAddress;
- symbol_iterator RelocSym = RI->getSymbol();
+ symbol_iterator RelocSym = Reloc.getSymbol();
Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 9bc092e..729fcba 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -17,7 +17,6 @@
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
@@ -149,10 +148,11 @@ YAMLCFG("yaml-cfg",
static StringRef ToolName;
-bool llvm::error(error_code ec) {
- if (!ec) return false;
+bool llvm::error(error_code EC) {
+ if (!EC)
+ return false;
- outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
+ outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
outs().flush();
return true;
}
@@ -166,7 +166,7 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) {
// TheTriple defaults to ELF, and COFF doesn't have an environment:
// the best we can do here is indicate that it is mach-o.
if (Obj->isMachO())
- TheTriple.setEnvironment(Triple::MachO);
+ TheTriple.setObjectFormat(Triple::MachO);
}
} else
TheTriple.setTriple(Triple::normalize(TripleName));
@@ -191,7 +191,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f,
MCInstPrinter *IP) {
// Start a new dot file.
std::string Error;
- raw_fd_ostream Out(FileName, Error);
+ raw_fd_ostream Out(FileName, Error, sys::fs::F_Text);
if (!Error.empty()) {
errs() << "llvm-objdump: warning: " << Error << '\n';
return;
@@ -281,60 +281,62 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
FeaturesStr = Features.getString();
}
- OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ std::unique_ptr<const MCRegisterInfo> MRI(
+ TheTarget->createMCRegInfo(TripleName));
if (!MRI) {
errs() << "error: no register info for target " << TripleName << "\n";
return;
}
// Set up disassembler.
- OwningPtr<const MCAsmInfo> AsmInfo(
- TheTarget->createMCAsmInfo(*MRI, TripleName));
+ std::unique_ptr<const MCAsmInfo> AsmInfo(
+ TheTarget->createMCAsmInfo(*MRI, TripleName));
if (!AsmInfo) {
errs() << "error: no assembly info for target " << TripleName << "\n";
return;
}
- OwningPtr<const MCSubtargetInfo> STI(
- TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
+ std::unique_ptr<const MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
if (!STI) {
errs() << "error: no subtarget info for target " << TripleName << "\n";
return;
}
- OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
if (!MII) {
errs() << "error: no instruction info for target " << TripleName << "\n";
return;
}
- OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
+ std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
if (!DisAsm) {
errs() << "error: no disassembler for target " << TripleName << "\n";
return;
}
- OwningPtr<const MCObjectFileInfo> MOFI;
- OwningPtr<MCContext> Ctx;
+ std::unique_ptr<const MCObjectFileInfo> MOFI;
+ std::unique_ptr<MCContext> Ctx;
if (Symbolize) {
MOFI.reset(new MCObjectFileInfo);
Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get()));
- OwningPtr<MCRelocationInfo> RelInfo(
- TheTarget->createMCRelocationInfo(TripleName, *Ctx.get()));
+ std::unique_ptr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(TripleName, *Ctx.get()));
if (RelInfo) {
- OwningPtr<MCSymbolizer> Symzer(
- MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, Obj));
+ std::unique_ptr<MCSymbolizer> Symzer(
+ MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(),
+ std::move(RelInfo), Obj));
if (Symzer)
- DisAsm->setSymbolizer(Symzer);
+ DisAsm->setSymbolizer(std::move(Symzer));
}
}
- OwningPtr<const MCInstrAnalysis>
- MIA(TheTarget->createMCInstrAnalysis(MII.get()));
+ std::unique_ptr<const MCInstrAnalysis> MIA(
+ TheTarget->createMCInstrAnalysis(MII.get()));
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
- OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
if (!IP) {
errs() << "error: no instruction printer for target " << TripleName
@@ -343,9 +345,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
if (CFG || !YAMLCFG.empty()) {
- OwningPtr<MCObjectDisassembler> OD(
- new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
- OwningPtr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
+ std::unique_ptr<MCObjectDisassembler> OD(
+ new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
+ std::unique_ptr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
for (MCModule::const_atom_iterator AI = Mod->atom_begin(),
AE = Mod->atom_end();
AI != AE; ++AI) {
@@ -372,7 +374,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
if (!YAMLCFG.empty()) {
std::string Error;
- raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error);
+ raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error, sys::fs::F_Text);
if (!Error.empty()) {
errs() << ToolName << ": warning: " << Error << '\n';
return;
@@ -381,33 +383,51 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
}
+ StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " :
+ "\t\t\t%08" PRIx64 ": ";
+
+ // Create a mapping, RelocSecs = SectionRelocMap[S], where sections
+ // in RelocSecs contain the relocations for section S.
+ error_code EC;
+ std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
+ for (const SectionRef &Section : Obj->sections()) {
+ section_iterator Sec2 = Section.getRelocatedSection();
+ if (Sec2 != Obj->section_end())
+ SectionRelocMap[*Sec2].push_back(Section);
+ }
- error_code ec;
- for (section_iterator i = Obj->begin_sections(),
- e = Obj->end_sections();
- i != e; i.increment(ec)) {
- if (error(ec)) break;
- bool text;
- if (error(i->isText(text))) break;
- if (!text) continue;
+ for (const SectionRef &Section : Obj->sections()) {
+ bool Text;
+ if (error(Section.isText(Text)))
+ break;
+ if (!Text)
+ continue;
uint64_t SectionAddr;
- if (error(i->getAddress(SectionAddr))) break;
+ if (error(Section.getAddress(SectionAddr)))
+ break;
+
+ uint64_t SectSize;
+ if (error(Section.getSize(SectSize)))
+ break;
// Make a list of all the symbols in this section.
- std::vector<std::pair<uint64_t, StringRef> > Symbols;
- for (symbol_iterator si = Obj->begin_symbols(),
- se = Obj->end_symbols();
- si != se; si.increment(ec)) {
+ std::vector<std::pair<uint64_t, StringRef>> Symbols;
+ for (const SymbolRef &Symbol : Obj->symbols()) {
bool contains;
- if (!error(i->containsSymbol(*si, contains)) && contains) {
+ if (!error(Section.containsSymbol(Symbol, contains)) && contains) {
uint64_t Address;
- if (error(si->getAddress(Address))) break;
- if (Address == UnknownAddressOrSize) continue;
+ if (error(Symbol.getAddress(Address)))
+ break;
+ if (Address == UnknownAddressOrSize)
+ continue;
Address -= SectionAddr;
+ if (Address >= SectSize)
+ continue;
StringRef Name;
- if (error(si->getName(Name))) break;
+ if (error(Symbol.getName(Name)))
+ break;
Symbols.push_back(std::make_pair(Address, Name));
}
}
@@ -418,11 +438,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Make a list of all the relocations for this section.
std::vector<RelocationRef> Rels;
if (InlineRelocs) {
- for (relocation_iterator ri = i->begin_relocations(),
- re = i->end_relocations();
- ri != re; ri.increment(ec)) {
- if (error(ec)) break;
- Rels.push_back(*ri);
+ for (const SectionRef &RelocSec : SectionRelocMap[Section]) {
+ for (const RelocationRef &Reloc : RelocSec.relocations()) {
+ Rels.push_back(Reloc);
+ }
}
}
@@ -430,13 +449,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
StringRef SegmentName = "";
- if (const MachOObjectFile *MachO =
- dyn_cast<const MachOObjectFile>(Obj)) {
- DataRefImpl DR = i->getRawDataRefImpl();
+ if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {
+ DataRefImpl DR = Section.getRawDataRefImpl();
SegmentName = MachO->getSectionFinalSegmentName(DR);
}
StringRef name;
- if (error(i->getName(name))) break;
+ if (error(Section.getName(name)))
+ break;
outs() << "Disassembly of section ";
if (!SegmentName.empty())
outs() << SegmentName << ",";
@@ -452,12 +471,11 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
raw_svector_ostream CommentStream(Comments);
StringRef Bytes;
- if (error(i->getContents(Bytes))) break;
+ if (error(Section.getContents(Bytes)))
+ break;
StringRefMemoryObject memoryObject(Bytes, SectionAddr);
uint64_t Size;
uint64_t Index;
- uint64_t SectSize;
- if (error(i->getSize(SectSize))) break;
std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();
std::vector<RelocationRef>::const_iterator rel_end = Rels.end();
@@ -479,9 +497,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
outs() << '\n' << Symbols[si].second << ":\n";
#ifndef NDEBUG
- raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
+ raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
#else
- raw_ostream &DebugOut = nulls();
+ raw_ostream &DebugOut = nulls();
#endif
for (Index = Start; Index < End; Index += Size) {
@@ -522,7 +540,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (error(rel_cur->getTypeName(name))) goto skip_print_rel;
if (error(rel_cur->getValueString(val))) goto skip_print_rel;
- outs() << format("\t\t\t%8" PRIx64 ": ", SectionAddr + addr) << name
+ outs() << format(Fmt.data(), SectionAddr + addr) << name
<< "\t" << val << "\n";
skip_print_rel:
@@ -533,76 +551,82 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
}
-static void PrintRelocations(const ObjectFile *o) {
- error_code ec;
- for (section_iterator si = o->begin_sections(), se = o->end_sections();
- si != se; si.increment(ec)){
- if (error(ec)) return;
- if (si->begin_relocations() == si->end_relocations())
+static void PrintRelocations(const ObjectFile *Obj) {
+ StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
+ "%08" PRIx64;
+ for (const SectionRef &Section : Obj->sections()) {
+ if (Section.relocation_begin() == Section.relocation_end())
continue;
StringRef secname;
- if (error(si->getName(secname))) continue;
+ if (error(Section.getName(secname)))
+ continue;
outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
- for (relocation_iterator ri = si->begin_relocations(),
- re = si->end_relocations();
- ri != re; ri.increment(ec)) {
- if (error(ec)) return;
-
+ for (const RelocationRef &Reloc : Section.relocations()) {
bool hidden;
uint64_t address;
SmallString<32> relocname;
SmallString<32> valuestr;
- if (error(ri->getHidden(hidden))) continue;
- if (hidden) continue;
- if (error(ri->getTypeName(relocname))) continue;
- if (error(ri->getOffset(address))) continue;
- if (error(ri->getValueString(valuestr))) continue;
- outs() << address << " " << relocname << " " << valuestr << "\n";
+ if (error(Reloc.getHidden(hidden)))
+ continue;
+ if (hidden)
+ continue;
+ if (error(Reloc.getTypeName(relocname)))
+ continue;
+ if (error(Reloc.getOffset(address)))
+ continue;
+ if (error(Reloc.getValueString(valuestr)))
+ continue;
+ outs() << format(Fmt.data(), address) << " " << relocname << " "
+ << valuestr << "\n";
}
outs() << "\n";
}
}
-static void PrintSectionHeaders(const ObjectFile *o) {
+static void PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
- error_code ec;
unsigned i = 0;
- for (section_iterator si = o->begin_sections(), se = o->end_sections();
- si != se; si.increment(ec)) {
- if (error(ec)) return;
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(si->getName(Name))) return;
+ if (error(Section.getName(Name)))
+ return;
uint64_t Address;
- if (error(si->getAddress(Address))) return;
+ if (error(Section.getAddress(Address)))
+ return;
uint64_t Size;
- if (error(si->getSize(Size))) return;
+ if (error(Section.getSize(Size)))
+ return;
bool Text, Data, BSS;
- if (error(si->isText(Text))) return;
- if (error(si->isData(Data))) return;
- if (error(si->isBSS(BSS))) return;
+ if (error(Section.isText(Text)))
+ return;
+ if (error(Section.isData(Data)))
+ return;
+ if (error(Section.isBSS(BSS)))
+ return;
std::string Type = (std::string(Text ? "TEXT " : "") +
(Data ? "DATA " : "") + (BSS ? "BSS" : ""));
- outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n",
- i, Name.str().c_str(), Size, Address, Type.c_str());
+ outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
+ Name.str().c_str(), Size, Address, Type.c_str());
++i;
}
}
-static void PrintSectionContents(const ObjectFile *o) {
- error_code ec;
- for (section_iterator si = o->begin_sections(),
- se = o->end_sections();
- si != se; si.increment(ec)) {
- if (error(ec)) return;
+static void PrintSectionContents(const ObjectFile *Obj) {
+ error_code EC;
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
StringRef Contents;
uint64_t BaseAddr;
bool BSS;
- if (error(si->getName(Name))) continue;
- if (error(si->getContents(Contents))) continue;
- if (error(si->getAddress(BaseAddr))) continue;
- if (error(si->isBSS(BSS))) continue;
+ if (error(Section.getName(Name)))
+ continue;
+ if (error(Section.getContents(Contents)))
+ continue;
+ if (error(Section.getAddress(BaseAddr)))
+ continue;
+ if (error(Section.isBSS(BSS)))
+ continue;
outs() << "Contents of section " << Name << ":\n";
if (BSS) {
@@ -646,8 +670,7 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
for (int i = 0, e = header->NumberOfSymbols; i != e; ++i) {
if (aux_count--) {
// Figure out which type of aux this is.
- if (symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
- && symbol->Value == 0) { // Section definition.
+ if (symbol->isSectionDefinition()) { // Section definition.
const coff_aux_section_definition *asd;
if (error(coff->getAuxSymbol<coff_aux_section_definition>(i, asd)))
return;
@@ -682,78 +705,79 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
static void PrintSymbolTable(const ObjectFile *o) {
outs() << "SYMBOL TABLE:\n";
- if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o))
+ if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
PrintCOFFSymbolTable(coff);
- else {
- error_code ec;
- for (symbol_iterator si = o->begin_symbols(),
- se = o->end_symbols(); si != se; si.increment(ec)) {
- if (error(ec)) return;
- StringRef Name;
- uint64_t Address;
- SymbolRef::Type Type;
- uint64_t Size;
- uint32_t Flags;
- section_iterator Section = o->end_sections();
- if (error(si->getName(Name))) continue;
- if (error(si->getAddress(Address))) continue;
- if (error(si->getFlags(Flags))) continue;
- if (error(si->getType(Type))) continue;
- if (error(si->getSize(Size))) continue;
- if (error(si->getSection(Section))) continue;
-
- bool Global = Flags & SymbolRef::SF_Global;
- bool Weak = Flags & SymbolRef::SF_Weak;
- bool Absolute = Flags & SymbolRef::SF_Absolute;
-
- if (Address == UnknownAddressOrSize)
- Address = 0;
- if (Size == UnknownAddressOrSize)
- Size = 0;
- char GlobLoc = ' ';
- if (Type != SymbolRef::ST_Unknown)
- GlobLoc = Global ? 'g' : 'l';
- char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
- ? 'd' : ' ';
- char FileFunc = ' ';
- if (Type == SymbolRef::ST_File)
- FileFunc = 'f';
- else if (Type == SymbolRef::ST_Function)
- FileFunc = 'F';
-
- const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
- "%08" PRIx64;
-
- outs() << format(Fmt, Address) << " "
- << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
- << (Weak ? 'w' : ' ') // Weak?
- << ' ' // Constructor. Not supported yet.
- << ' ' // Warning. Not supported yet.
- << ' ' // Indirect reference to another symbol.
- << Debug // Debugging (d) or dynamic (D) symbol.
- << FileFunc // Name of function (F), file (f) or object (O).
- << ' ';
- if (Absolute)
- outs() << "*ABS*";
- else if (Section == o->end_sections())
- outs() << "*UND*";
- else {
- if (const MachOObjectFile *MachO =
- dyn_cast<const MachOObjectFile>(o)) {
- DataRefImpl DR = Section->getRawDataRefImpl();
- StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
- outs() << SegmentName << ",";
- }
- StringRef SectionName;
- if (error(Section->getName(SectionName)))
- SectionName = "";
- outs() << SectionName;
+ return;
+ }
+ for (const SymbolRef &Symbol : o->symbols()) {
+ StringRef Name;
+ uint64_t Address;
+ SymbolRef::Type Type;
+ uint64_t Size;
+ uint32_t Flags = Symbol.getFlags();
+ section_iterator Section = o->section_end();
+ if (error(Symbol.getName(Name)))
+ continue;
+ if (error(Symbol.getAddress(Address)))
+ continue;
+ if (error(Symbol.getType(Type)))
+ continue;
+ if (error(Symbol.getSize(Size)))
+ continue;
+ if (error(Symbol.getSection(Section)))
+ continue;
+
+ bool Global = Flags & SymbolRef::SF_Global;
+ bool Weak = Flags & SymbolRef::SF_Weak;
+ bool Absolute = Flags & SymbolRef::SF_Absolute;
+
+ if (Address == UnknownAddressOrSize)
+ Address = 0;
+ if (Size == UnknownAddressOrSize)
+ Size = 0;
+ char GlobLoc = ' ';
+ if (Type != SymbolRef::ST_Unknown)
+ GlobLoc = Global ? 'g' : 'l';
+ char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
+ ? 'd' : ' ';
+ char FileFunc = ' ';
+ if (Type == SymbolRef::ST_File)
+ FileFunc = 'f';
+ else if (Type == SymbolRef::ST_Function)
+ FileFunc = 'F';
+
+ const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
+ "%08" PRIx64;
+
+ outs() << format(Fmt, Address) << " "
+ << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
+ << (Weak ? 'w' : ' ') // Weak?
+ << ' ' // Constructor. Not supported yet.
+ << ' ' // Warning. Not supported yet.
+ << ' ' // Indirect reference to another symbol.
+ << Debug // Debugging (d) or dynamic (D) symbol.
+ << FileFunc // Name of function (F), file (f) or object (O).
+ << ' ';
+ if (Absolute) {
+ outs() << "*ABS*";
+ } else if (Section == o->section_end()) {
+ outs() << "*UND*";
+ } else {
+ if (const MachOObjectFile *MachO =
+ dyn_cast<const MachOObjectFile>(o)) {
+ DataRefImpl DR = Section->getRawDataRefImpl();
+ StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
+ outs() << SegmentName << ",";
}
- outs() << '\t'
- << format("%08" PRIx64 " ", Size)
- << Name
- << '\n';
+ StringRef SectionName;
+ if (error(Section->getName(SectionName)))
+ SectionName = "";
+ outs() << SectionName;
}
+ outs() << '\t'
+ << format("%08" PRIx64 " ", Size)
+ << Name
+ << '\n';
}
}
@@ -801,13 +825,13 @@ static void DumpObject(const ObjectFile *o) {
/// @brief Dump each object file in \a a;
static void DumpArchive(const Archive *a) {
- for (Archive::child_iterator i = a->begin_children(),
- e = a->end_children(); i != e; ++i) {
- OwningPtr<Binary> child;
- if (error_code ec = i->getAsBinary(child)) {
+ for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
+ ++i) {
+ std::unique_ptr<Binary> child;
+ if (error_code EC = i->getAsBinary(child)) {
// Ignore non-object files.
- if (ec != object_error::invalid_file_type)
- errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message()
+ if (EC != object_error::invalid_file_type)
+ errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message()
<< ".\n";
continue;
}
@@ -833,11 +857,12 @@ static void DumpInput(StringRef file) {
}
// Attempt to open the binary.
- OwningPtr<Binary> binary;
- if (error_code ec = createBinary(file, binary)) {
- errs() << ToolName << ": '" << file << "': " << ec.message() << ".\n";
+ ErrorOr<Binary *> BinaryOrErr = createBinary(file);
+ if (error_code EC = BinaryOrErr.getError()) {
+ errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n";
return;
}
+ std::unique_ptr<Binary> binary(BinaryOrErr.get());
if (Archive *a = dyn_cast<Archive>(binary.get()))
DumpArchive(a);
diff --git a/tools/llvm-profdata/CMakeLists.txt b/tools/llvm-profdata/CMakeLists.txt
new file mode 100644
index 0000000..3529114
--- /dev/null
+++ b/tools/llvm-profdata/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS profiledata support)
+
+add_llvm_tool(llvm-profdata
+ llvm-profdata.cpp
+ )
diff --git a/tools/llvm-profdata/LLVMBuild.txt b/tools/llvm-profdata/LLVMBuild.txt
new file mode 100644
index 0000000..bbc1ea6
--- /dev/null
+++ b/tools/llvm-profdata/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./tools/llvm-profdata/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-profdata
+parent = Tools
+required_libraries = ProfileData Support
diff --git a/tools/llvm-profdata/Makefile b/tools/llvm-profdata/Makefile
new file mode 100644
index 0000000..6f8c162
--- /dev/null
+++ b/tools/llvm-profdata/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-profdata/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-profdata
+LINK_COMPONENTS := profiledata support
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp
new file mode 100644
index 0000000..397b523
--- /dev/null
+++ b/tools/llvm-profdata/llvm-profdata.cpp
@@ -0,0 +1,191 @@
+//===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// llvm-profdata merges .profdata files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/InstrProfWriter.h"
+#include "llvm/Support/CommandLine.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/raw_ostream.h"
+
+using namespace llvm;
+
+static void exitWithError(const Twine &Message, StringRef Whence = "") {
+ errs() << "error: ";
+ if (!Whence.empty())
+ errs() << Whence << ": ";
+ errs() << Message << "\n";
+ ::exit(1);
+}
+
+int merge_main(int argc, const char *argv[]) {
+ cl::list<std::string> Inputs(cl::Positional, cl::Required, cl::OneOrMore,
+ cl::desc("<filenames...>"));
+
+ cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+ cl::init("-"),
+ cl::desc("Output file"));
+ cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+ cl::aliasopt(OutputFilename));
+
+ cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
+
+ if (OutputFilename.empty())
+ OutputFilename = "-";
+
+ std::string ErrorInfo;
+ // FIXME: F_Text would be available if line_iterator could accept CRLF.
+ raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_None);
+ if (!ErrorInfo.empty())
+ exitWithError(ErrorInfo, OutputFilename);
+
+ InstrProfWriter Writer;
+ for (const auto &Filename : Inputs) {
+ std::unique_ptr<InstrProfReader> Reader;
+ if (error_code ec = InstrProfReader::create(Filename, Reader))
+ exitWithError(ec.message(), Filename);
+
+ for (const auto &I : *Reader)
+ if (error_code EC = Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))
+ errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
+ if (Reader->hasError())
+ exitWithError(Reader->getError().message(), Filename);
+ }
+ Writer.write(Output);
+
+ return 0;
+}
+
+int show_main(int argc, const char *argv[]) {
+ cl::opt<std::string> Filename(cl::Positional, cl::Required,
+ cl::desc("<profdata-file>"));
+
+ cl::opt<bool> ShowCounts("counts", cl::init(false),
+ cl::desc("Show counter values for shown functions"));
+ cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
+ cl::desc("Details for every function"));
+ cl::opt<std::string> ShowFunction("function",
+ cl::desc("Details for matching functions"));
+
+ cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+ cl::init("-"),
+ cl::desc("Output file"));
+ cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+ cl::aliasopt(OutputFilename));
+
+ cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
+
+ std::unique_ptr<InstrProfReader> Reader;
+ if (error_code EC = InstrProfReader::create(Filename, Reader))
+ exitWithError(EC.message(), Filename);
+
+ if (OutputFilename.empty())
+ OutputFilename = "-";
+
+ std::string ErrorInfo;
+ raw_fd_ostream OS(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
+ if (!ErrorInfo.empty())
+ exitWithError(ErrorInfo, OutputFilename);
+
+ if (ShowAllFunctions && !ShowFunction.empty())
+ errs() << "warning: -function argument ignored: showing all functions\n";
+
+ uint64_t MaxFunctionCount = 0, MaxBlockCount = 0;
+ size_t ShownFunctions = 0, TotalFunctions = 0;
+ for (const auto &Func : *Reader) {
+ bool Show = ShowAllFunctions ||
+ (!ShowFunction.empty() &&
+ Func.Name.find(ShowFunction) != Func.Name.npos);
+
+ ++TotalFunctions;
+ if (Func.Counts[0] > MaxFunctionCount)
+ MaxFunctionCount = Func.Counts[0];
+
+ if (Show) {
+ if (!ShownFunctions)
+ OS << "Counters:\n";
+ ++ShownFunctions;
+
+ OS << " " << Func.Name << ":\n"
+ << " Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
+ << " Counters: " << Func.Counts.size() << "\n"
+ << " Function count: " << Func.Counts[0] << "\n";
+ }
+
+ if (Show && ShowCounts)
+ OS << " Block counts: [";
+ for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
+ if (Func.Counts[I] > MaxBlockCount)
+ MaxBlockCount = Func.Counts[I];
+ if (Show && ShowCounts)
+ OS << (I == 1 ? "" : ", ") << Func.Counts[I];
+ }
+ if (Show && ShowCounts)
+ OS << "]\n";
+ }
+ if (Reader->hasError())
+ exitWithError(Reader->getError().message(), Filename);
+
+ if (ShowAllFunctions || !ShowFunction.empty())
+ OS << "Functions shown: " << ShownFunctions << "\n";
+ OS << "Total functions: " << TotalFunctions << "\n";
+ OS << "Maximum function count: " << MaxFunctionCount << "\n";
+ OS << "Maximum internal block count: " << MaxBlockCount << "\n";
+ return 0;
+}
+
+int main(int argc, const char *argv[]) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ StringRef ProgName(sys::path::filename(argv[0]));
+ if (argc > 1) {
+ int (*func)(int, const char *[]) = 0;
+
+ if (strcmp(argv[1], "merge") == 0)
+ func = merge_main;
+ else if (strcmp(argv[1], "show") == 0)
+ func = show_main;
+
+ if (func) {
+ std::string Invocation(ProgName.str() + " " + argv[1]);
+ argv[1] = Invocation.c_str();
+ return func(argc - 1, argv + 1);
+ }
+
+ if (strcmp(argv[1], "-h") == 0 ||
+ strcmp(argv[1], "-help") == 0 ||
+ strcmp(argv[1], "--help") == 0) {
+
+ errs() << "OVERVIEW: LLVM profile data tools\n\n"
+ << "USAGE: " << ProgName << " <command> [args...]\n"
+ << "USAGE: " << ProgName << " <command> -help\n\n"
+ << "Available commands: merge, show\n";
+ return 0;
+ }
+ }
+
+ if (argc < 2)
+ errs() << ProgName << ": No command specified!\n";
+ else
+ errs() << ProgName << ": Unknown command!\n";
+
+ errs() << "USAGE: " << ProgName << " <merge|show> [args...]\n";
+ return 1;
+}
diff --git a/tools/llvm-readobj/ARMAttributeParser.cpp b/tools/llvm-readobj/ARMAttributeParser.cpp
new file mode 100644
index 0000000..5857547
--- /dev/null
+++ b/tools/llvm-readobj/ARMAttributeParser.cpp
@@ -0,0 +1,639 @@
+//===--- ARMAttributeParser.cpp - ARM Attribute Information Printer -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMAttributeParser.h"
+#include "StreamWriter.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/LEB128.h"
+
+using namespace llvm;
+using namespace llvm::ARMBuildAttrs;
+
+
+static const EnumEntry<unsigned> TagNames[] = {
+ { "Tag_File", ARMBuildAttrs::File },
+ { "Tag_Section", ARMBuildAttrs::Section },
+ { "Tag_Symbol", ARMBuildAttrs::Symbol },
+};
+
+template <typename type_, size_t size_>
+size_t countof(const type_ (&)[size_]) {
+ return size_;
+}
+
+namespace llvm {
+#define ATTRIBUTE_HANDLER(Attr_) \
+ { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ }
+
+const ARMAttributeParser::DisplayHandler
+ARMAttributeParser::DisplayRoutines[] = {
+ { ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::StringAttribute, },
+ { ARMBuildAttrs::CPU_name, &ARMAttributeParser::StringAttribute },
+ ATTRIBUTE_HANDLER(CPU_arch),
+ ATTRIBUTE_HANDLER(CPU_arch_profile),
+ ATTRIBUTE_HANDLER(ARM_ISA_use),
+ ATTRIBUTE_HANDLER(THUMB_ISA_use),
+ ATTRIBUTE_HANDLER(FP_arch),
+ ATTRIBUTE_HANDLER(WMMX_arch),
+ ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
+ ATTRIBUTE_HANDLER(PCS_config),
+ ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
+ ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
+ ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
+ ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
+ ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
+ ATTRIBUTE_HANDLER(ABI_FP_rounding),
+ ATTRIBUTE_HANDLER(ABI_FP_denormal),
+ ATTRIBUTE_HANDLER(ABI_FP_exceptions),
+ ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
+ ATTRIBUTE_HANDLER(ABI_FP_number_model),
+ ATTRIBUTE_HANDLER(ABI_align_needed),
+ ATTRIBUTE_HANDLER(ABI_align_preserved),
+ ATTRIBUTE_HANDLER(ABI_enum_size),
+ ATTRIBUTE_HANDLER(ABI_HardFP_use),
+ ATTRIBUTE_HANDLER(ABI_VFP_args),
+ ATTRIBUTE_HANDLER(ABI_WMMX_args),
+ ATTRIBUTE_HANDLER(ABI_optimization_goals),
+ ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
+ ATTRIBUTE_HANDLER(compatibility),
+ ATTRIBUTE_HANDLER(CPU_unaligned_access),
+ ATTRIBUTE_HANDLER(FP_HP_extension),
+ ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
+ ATTRIBUTE_HANDLER(MPextension_use),
+ ATTRIBUTE_HANDLER(DIV_use),
+ ATTRIBUTE_HANDLER(T2EE_use),
+ ATTRIBUTE_HANDLER(Virtualization_use),
+ ATTRIBUTE_HANDLER(nodefaults)
+};
+
+#undef ATTRIBUTE_HANDLER
+
+uint64_t ARMAttributeParser::ParseInteger(const uint8_t *Data,
+ uint32_t &Offset) {
+ unsigned Length;
+ uint64_t Value = decodeULEB128(Data + Offset, &Length);
+ Offset = Offset + Length;
+ return Value;
+}
+
+StringRef ARMAttributeParser::ParseString(const uint8_t *Data,
+ uint32_t &Offset) {
+ const char *String = reinterpret_cast<const char*>(Data + Offset);
+ size_t Length = std::strlen(String);
+ Offset = Offset + Length + 1;
+ return StringRef(String, Length);
+}
+
+void ARMAttributeParser::IntegerAttribute(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ SW.printNumber(ARMBuildAttrs::AttrTypeAsString(Tag),
+ ParseInteger(Data, Offset));
+}
+
+void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false);
+
+ DictScope AS(SW, "Attribute");
+ SW.printNumber("Tag", Tag);
+ if (!TagName.empty())
+ SW.printString("TagName", TagName);
+ SW.printString("Value", ParseString(Data, Offset));
+}
+
+void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value,
+ StringRef ValueDesc) {
+ StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false);
+
+ DictScope AS(SW, "Attribute");
+ SW.printNumber("Tag", Tag);
+ SW.printNumber("Value", Value);
+ if (!TagName.empty())
+ SW.printString("TagName", TagName);
+ if (!ValueDesc.empty())
+ SW.printString("Description", ValueDesc);
+}
+
+void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6",
+ "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M",
+ "ARM v7E-M", "ARM v8"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ uint64_t Encoded = ParseInteger(Data, Offset);
+
+ StringRef Profile;
+ switch (Encoded) {
+ default: Profile = "Unknown"; break;
+ case 'A': Profile = "Application"; break;
+ case 'R': Profile = "Real-time"; break;
+ case 'M': Profile = "Microcontroller"; break;
+ case 'S': Profile = "Classic"; break;
+ case '0': Profile = "None"; break;
+ }
+
+ PrintAttribute(Tag, Encoded, Profile);
+}
+
+void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "Permitted" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4",
+ "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
+ "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Absolute", "PC-relative", "SB-relative", "Not Permitted"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Absolute", "PC-relative", "Not Permitted" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "Direct", "GOT-Indirect" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "IEEE-754", "Runtime" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "IEEE-754" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag,
+ const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "IEEE-754" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "Finite Only", "RTABI", "IEEE-754"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+
+ std::string Description;
+ if (Value < countof(Strings))
+ Description = std::string(Strings[Value]);
+ else if (Value <= 12)
+ Description = std::string("8-byte alignment, ") + utostr(1 << Value)
+ + std::string("-byte extended alignment");
+ else
+ Description = "Invalid";
+
+ PrintAttribute(Tag, Value, Description);
+}
+
+void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Required", "8-byte data alignment", "8-byte data and code alignment",
+ "Reserved"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+
+ std::string Description;
+ if (Value < countof(Strings))
+ Description = std::string(Strings[Value]);
+ else if (Value <= 12)
+ Description = std::string("8-byte stack alignment, ") + utostr(1 << Value)
+ + std::string("-byte data alignment");
+ else
+ Description = "Invalid";
+
+ PrintAttribute(Tag, Value, Description);
+}
+
+void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "Packed", "Int32", "External Int32"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "AAPCS", "AAPCS VFP", "Custom", "Not Permitted"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_optimization_goals(AttrType Tag,
+ const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
+ "Best Debugging"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag,
+ const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy",
+ "Best Accuracy"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ uint64_t Integer = ParseInteger(Data, Offset);
+ StringRef String = ParseString(Data, Offset);
+
+ DictScope AS(SW, "Attribute");
+ SW.printNumber("Tag", Tag);
+ SW.startLine() << "Value: " << Integer << ", " << String << '\n';
+ SW.printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false));
+ switch (Integer) {
+ case 0:
+ SW.printString("Description", StringRef("No Specific Requirements"));
+ break;
+ case 1:
+ SW.printString("Description", StringRef("AEABI Conformant"));
+ break;
+ default:
+ SW.printString("Description", StringRef("AEABI Non-Conformant"));
+ break;
+ }
+}
+
+void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "v6-style" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "If Available", "Permitted" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "Permitted" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "If Available", "Not Permitted", "Permitted"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = { "Not Permitted", "Permitted" };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ static const char *Strings[] = {
+ "Not Permitted", "TrustZone", "Virtualization Extensions",
+ "TrustZone + Virtualization Extensions"
+ };
+
+ uint64_t Value = ParseInteger(Data, Offset);
+ StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ PrintAttribute(Tag, Value, ValueDesc);
+}
+
+void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset) {
+ uint64_t Value = ParseInteger(Data, Offset);
+ PrintAttribute(Tag, Value, "Unspecified Tags UNDEFINED");
+}
+
+void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset,
+ SmallVectorImpl<uint8_t> &IndexList) {
+ for (;;) {
+ unsigned Length;
+ uint64_t Value = decodeULEB128(Data + Offset, &Length);
+ Offset = Offset + Length;
+ if (Value == 0)
+ break;
+ IndexList.push_back(Value);
+ }
+}
+
+void ARMAttributeParser::ParseAttributeList(const uint8_t *Data,
+ uint32_t &Offset, uint32_t Length) {
+ while (Offset < Length) {
+ unsigned Length;
+ uint64_t Tag = decodeULEB128(Data + Offset, &Length);
+ Offset += Length;
+
+ bool Handled = false;
+ for (unsigned AHI = 0, AHE = countof(DisplayRoutines);
+ AHI != AHE && !Handled; ++AHI) {
+ if (DisplayRoutines[AHI].Attribute == Tag) {
+ (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag),
+ Data, Offset);
+ Handled = true;
+ break;
+ }
+ }
+ if (!Handled) {
+ if (Tag < 32) {
+ errs() << "unhandled AEABI Tag " << Tag
+ << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n";
+ continue;
+ }
+
+ if (Tag % 2 == 0)
+ IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
+ else
+ StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
+ }
+ }
+}
+
+void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) {
+ uint32_t Offset = sizeof(uint32_t); /* SectionLength */
+
+ SW.printNumber("SectionLength", Length);
+
+ const char *VendorName = reinterpret_cast<const char*>(Data + Offset);
+ size_t VendorNameLength = std::strlen(VendorName);
+ SW.printString("Vendor", StringRef(VendorName, VendorNameLength));
+ Offset = Offset + VendorNameLength + 1;
+
+ if (StringRef(VendorName, VendorNameLength).lower() != "aeabi")
+ return;
+
+ while (Offset < Length) {
+ /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
+ uint8_t Tag = Data[Offset];
+ SW.printEnum("Tag", Tag, makeArrayRef(TagNames));
+ Offset = Offset + sizeof(Tag);
+
+ uint32_t Size =
+ *reinterpret_cast<const support::ulittle32_t*>(Data + Offset);
+ SW.printNumber("Size", Size);
+ Offset = Offset + sizeof(Size);
+
+ if (Size > Length) {
+ errs() << "subsection length greater than section length\n";
+ return;
+ }
+
+ StringRef ScopeName, IndexName;
+ SmallVector<uint8_t, 8> Indicies;
+ switch (Tag) {
+ case ARMBuildAttrs::File:
+ ScopeName = "FileAttributes";
+ break;
+ case ARMBuildAttrs::Section:
+ ScopeName = "SectionAttributes";
+ IndexName = "Sections";
+ ParseIndexList(Data, Offset, Indicies);
+ break;
+ case ARMBuildAttrs::Symbol:
+ ScopeName = "SymbolAttributes";
+ IndexName = "Symbols";
+ ParseIndexList(Data, Offset, Indicies);
+ break;
+ default:
+ errs() << "unrecognised tag: 0x" << utohexstr(Tag) << '\n';
+ return;
+ }
+
+ DictScope ASS(SW, ScopeName);
+
+ if (!Indicies.empty())
+ SW.printList(IndexName, Indicies);
+
+ ParseAttributeList(Data, Offset, Length);
+ }
+}
+
+void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section) {
+ size_t Offset = 1;
+ unsigned SectionNumber = 0;
+
+ while (Offset < Section.size()) {
+ uint32_t SectionLength =
+ *reinterpret_cast<const support::ulittle32_t*>(Section.data() + Offset);
+
+ SW.startLine() << "Section " << ++SectionNumber << " {\n";
+ SW.indent();
+
+ ParseSubsection(Section.data() + Offset, SectionLength);
+ Offset = Offset + SectionLength;
+
+ SW.unindent();
+ SW.startLine() << "}\n";
+ }
+}
+}
+
diff --git a/tools/llvm-readobj/ARMAttributeParser.h b/tools/llvm-readobj/ARMAttributeParser.h
new file mode 100644
index 0000000..c286251
--- /dev/null
+++ b/tools/llvm-readobj/ARMAttributeParser.h
@@ -0,0 +1,124 @@
+//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_READOBJ_ARMATTRIBUTE_PARSER_H
+#define LLVM_READOBJ_ARMATTRIBUTE_PARSER_H
+
+#include "StreamWriter.h"
+#include "llvm/Support/ARMBuildAttributes.h"
+
+namespace llvm {
+class StringRef;
+
+class ARMAttributeParser {
+ StreamWriter &SW;
+
+ struct DisplayHandler {
+ ARMBuildAttrs::AttrType Attribute;
+ void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
+ const uint8_t *, uint32_t &);
+ };
+ static const DisplayHandler DisplayRoutines[];
+
+ uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
+ StringRef ParseString(const uint8_t *Data, uint32_t &Offset);
+
+ void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);
+
+ void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag,
+ const uint8_t *Data, uint32_t &Offset);
+ void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
+ uint32_t Length);
+ void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
+ SmallVectorImpl<uint8_t> &IndexList);
+ void ParseSubsection(const uint8_t *Data, uint32_t Length);
+public:
+ ARMAttributeParser(StreamWriter &SW) : SW(SW) {}
+
+ void Parse(ArrayRef<uint8_t> Section);
+};
+
+}
+
+#endif
+
diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h
new file mode 100644
index 0000000..75e2bee
--- /dev/null
+++ b/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -0,0 +1,557 @@
+//===--- ARMEHABIPrinter.h - ARM EHABI Unwind Information Printer ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_READOBJ_ARMEHABI_PRINTER_H
+#define LLVM_READOBJ_ARMEHABI_PRINTER_H
+
+#include "Error.h"
+#include "StreamWriter.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Support/ARMEHABI.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/type_traits.h"
+
+namespace {
+template <typename type_, size_t N>
+size_t countof(const type_ (&)[N]) {
+ return N;
+}
+}
+
+namespace llvm {
+namespace ARM {
+namespace EHABI {
+
+class OpcodeDecoder {
+ StreamWriter &SW;
+ raw_ostream &OS;
+
+ struct RingEntry {
+ uint8_t Mask;
+ uint8_t Value;
+ void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);
+ };
+ static const RingEntry Ring[];
+
+ void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10011101(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10011111(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10110000(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI);
+ void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI);
+
+ void PrintGPR(uint16_t GPRMask);
+ void PrintRegisters(uint32_t Mask, StringRef Prefix);
+
+public:
+ OpcodeDecoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {}
+ void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);
+};
+
+const OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = {
+ { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx },
+ { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx },
+ { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii },
+ { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 },
+ { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 },
+ { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn },
+ { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn },
+ { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn },
+ { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 },
+ { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii },
+ { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 },
+ { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc },
+ { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn },
+ { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn },
+ { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc },
+ { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii },
+ { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc },
+ { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc },
+ { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy },
+ { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn },
+ { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn },
+ { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy },
+};
+
+void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
+ ((Opcode & 0x3f) << 2) + 4);
+}
+void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
+ ((Opcode & 0x3f) << 2) + 4);
+}
+void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+
+ uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
+ SW.startLine()
+ << format("0x%02X 0x%02X ; %s",
+ Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
+ if (GPRMask)
+ PrintGPR(GPRMask);
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode);
+}
+void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode);
+}
+void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
+}
+void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; pop ", Opcode);
+ PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; pop ", Opcode);
+ PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; finish\n", Opcode);
+}
+void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+
+ SW.startLine()
+ << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
+ ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
+ if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
+ PrintGPR((Opcode1 & 0x0f));
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ", Opcode);
+
+ SmallVector<uint8_t, 4> ULEB;
+ do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
+
+ for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
+ OS << format("0x%02X ", ULEB[BI]);
+
+ uint64_t Value = 0;
+ for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
+ Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
+
+ OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
+}
+void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
+ uint8_t Start = ((Opcode1 & 0xf0) >> 4);
+ uint8_t Count = ((Opcode1 & 0x0f) >> 0);
+ PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; spare\n", Opcode);
+}
+void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; pop ", Opcode);
+ PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
+ uint8_t Start = ((Opcode1 & 0xf0) >> 4);
+ uint8_t Count = ((Opcode1 & 0x0f) >> 0);
+ PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+ SW.startLine()
+ << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
+ ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
+ if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
+ PrintRegisters(Opcode1 & 0x0f, "wCGR");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
+ uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
+ uint8_t Count = ((Opcode1 & 0x0f) >> 0);
+ PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
+ uint8_t Opcode0 = Opcodes[OI++ ^ 3];
+ uint8_t Opcode1 = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
+ uint8_t Start = ((Opcode1 & 0xf0) >> 4);
+ uint8_t Count = ((Opcode1 & 0x0f) >> 0);
+ PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; spare\n", Opcode);
+}
+void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; pop ", Opcode);
+ PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; pop ", Opcode);
+ PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
+ OS << '\n';
+}
+void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) {
+ uint8_t Opcode = Opcodes[OI++ ^ 3];
+ SW.startLine() << format("0x%02X ; spare\n", Opcode);
+}
+
+void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
+ static const char *GPRRegisterNames[16] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "fp", "ip", "sp", "lr", "pc"
+ };
+
+ OS << '{';
+ bool Comma = false;
+ for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {
+ if (GPRMask & (1 << RI)) {
+ if (Comma)
+ OS << ", ";
+ OS << GPRRegisterNames[RI];
+ Comma = true;
+ }
+ }
+ OS << '}';
+}
+
+void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
+ OS << '{';
+ bool Comma = false;
+ for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
+ if (VFPMask & (1 << RI)) {
+ if (Comma)
+ OS << ", ";
+ OS << Prefix << RI;
+ Comma = true;
+ }
+ }
+ OS << '}';
+}
+
+void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) {
+ for (unsigned OCI = Offset; OCI < Length + Offset; ) {
+ bool Decoded = false;
+ for (unsigned REI = 0, REE = countof(Ring); REI != REE && !Decoded; ++REI) {
+ if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) {
+ (this->*Ring[REI].Routine)(Opcodes, OCI);
+ Decoded = true;
+ break;
+ }
+ }
+ if (!Decoded)
+ SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]);
+ }
+}
+
+template <typename ET>
+class PrinterContext {
+ StreamWriter &SW;
+ const object::ELFFile<ET> *ELF;
+
+ typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym;
+ typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr;
+
+ typedef typename object::ELFFile<ET>::Elf_Rel_Iter Elf_Rel_iterator;
+ typedef typename object::ELFFile<ET>::Elf_Sym_Iter Elf_Sym_iterator;
+ typedef typename object::ELFFile<ET>::Elf_Shdr_Iter Elf_Shdr_iterator;
+
+ static const size_t IndexTableEntrySize;
+
+ static uint64_t PREL31(uint32_t Address, uint32_t Place) {
+ uint64_t Location = Address & 0x7fffffff;
+ if (Location & 0x04000000)
+ Location |= (uint64_t) ~0x7fffffff;
+ return Location + Place;
+ }
+
+ ErrorOr<StringRef> FunctionAtAddress(unsigned Section, uint64_t Address) const;
+ const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,
+ off_t IndexTableOffset) const;
+
+ void PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const;
+ void PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT,
+ uint64_t TableEntryOffset) const;
+ void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;
+
+public:
+ PrinterContext(StreamWriter &Writer, const object::ELFFile<ET> *File)
+ : SW(Writer), ELF(File) {}
+
+ void PrintUnwindInformation() const;
+};
+
+template <typename ET>
+const size_t PrinterContext<ET>::IndexTableEntrySize = 8;
+
+template <typename ET>
+ErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(unsigned Section,
+ uint64_t Address) const {
+ for (Elf_Sym_iterator SI = ELF->begin_symbols(), SE = ELF->end_symbols();
+ SI != SE; ++SI)
+ if (SI->st_shndx == Section && SI->st_value == Address &&
+ SI->getType() == ELF::STT_FUNC)
+ return ELF->getSymbolName(SI);
+ return readobj_error::unknown_symbol;
+}
+
+template <typename ET>
+const typename object::ELFFile<ET>::Elf_Shdr *
+PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
+ off_t IndexTableOffset) const {
+ /// Iterate through the sections, searching for the relocation section
+ /// associated with the unwind index table section specified by
+ /// IndexSectionIndex. Iterate the associated section searching for the
+ /// relocation associated with the index table entry specified by
+ /// IndexTableOffset. The symbol is the section symbol for the exception
+ /// handling table. Use this symbol to recover the actual exception handling
+ /// table.
+
+ for (Elf_Shdr_iterator SI = ELF->begin_sections(), SE = ELF->end_sections();
+ SI != SE; ++SI) {
+ if (SI->sh_type == ELF::SHT_REL && SI->sh_info == IndexSectionIndex) {
+ for (Elf_Rel_iterator RI = ELF->begin_rel(&*SI), RE = ELF->end_rel(&*SI);
+ RI != RE; ++RI) {
+ if (RI->r_offset == static_cast<unsigned>(IndexTableOffset)) {
+ typename object::ELFFile<ET>::Elf_Rela RelA;
+ RelA.r_offset = RI->r_offset;
+ RelA.r_info = RI->r_info;
+ RelA.r_addend = 0;
+
+ std::pair<const Elf_Shdr *, const Elf_Sym *> Symbol =
+ ELF->getRelocationSymbol(&(*SI), &RelA);
+
+ return ELF->getSection(Symbol.second);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+template <typename ET>
+void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT,
+ const Elf_Shdr *EHT,
+ uint64_t TableEntryOffset) const {
+ ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT);
+ if (!Contents)
+ return;
+
+ /// ARM EHABI Section 6.2 - The generic model
+ ///
+ /// An exception-handling table entry for the generic model is laid out as:
+ ///
+ /// 3 3
+ /// 1 0 0
+ /// +-+------------------------------+
+ /// |0| personality routine offset |
+ /// +-+------------------------------+
+ /// | personality routine data ... |
+ ///
+ ///
+ /// ARM EHABI Section 6.3 - The ARM-defined compact model
+ ///
+ /// An exception-handling table entry for the compact model looks like:
+ ///
+ /// 3 3 2 2 2 2
+ /// 1 0 8 7 4 3 0
+ /// +-+---+----+-----------------------+
+ /// |1| 0 | Ix | data for pers routine |
+ /// +-+---+----+-----------------------+
+ /// | more personality routine data |
+
+ const support::ulittle32_t Word =
+ *reinterpret_cast<const support::ulittle32_t *>(Contents->data() + TableEntryOffset);
+
+ if (Word & 0x80000000) {
+ SW.printString("Model", StringRef("Compact"));
+
+ unsigned PersonalityIndex = (Word & 0x0f000000) >> 24;
+ SW.printNumber("PersonalityIndex", PersonalityIndex);
+
+ switch (PersonalityIndex) {
+ case AEABI_UNWIND_CPP_PR0:
+ PrintOpcodes(Contents->data() + TableEntryOffset, 3, 1);
+ break;
+ case AEABI_UNWIND_CPP_PR1:
+ case AEABI_UNWIND_CPP_PR2:
+ unsigned AdditionalWords = (Word & 0x00ff0000) >> 16;
+ PrintOpcodes(Contents->data() + TableEntryOffset, 2 + 4 * AdditionalWords,
+ 2);
+ break;
+ }
+ } else {
+ SW.printString("Model", StringRef("Generic"));
+
+ uint64_t Address = PREL31(Word, EHT->sh_addr);
+ SW.printHex("PersonalityRoutineAddress", Address);
+ if (ErrorOr<StringRef> Name = FunctionAtAddress(EHT->sh_link, Address))
+ SW.printString("PersonalityRoutineName", *Name);
+ }
+}
+
+template <typename ET>
+void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,
+ size_t Length, off_t Offset) const {
+ ListScope OCC(SW, "Opcodes");
+ OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
+}
+
+template <typename ET>
+void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex,
+ const Elf_Shdr *IT) const {
+ ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT);
+ if (!Contents)
+ return;
+
+ /// ARM EHABI Section 5 - Index Table Entries
+ /// * The first word contains a PREL31 offset to the start of a function with
+ /// bit 31 clear
+ /// * The second word contains one of:
+ /// - The PREL31 offset of the start of the table entry for the function,
+ /// with bit 31 clear
+ /// - The exception-handling table entry itself with bit 31 set
+ /// - The special bit pattern EXIDX_CANTUNWIND, indicating that associated
+ /// frames cannot be unwound
+
+ const support::ulittle32_t *Data =
+ reinterpret_cast<const support::ulittle32_t *>(Contents->data());
+ const unsigned Entries = IT->sh_size / IndexTableEntrySize;
+
+ ListScope E(SW, "Entries");
+ for (unsigned Entry = 0; Entry < Entries; ++Entry) {
+ DictScope E(SW, "Entry");
+
+ const support::ulittle32_t Word0 =
+ Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 0];
+ const support::ulittle32_t Word1 =
+ Data[Entry * (IndexTableEntrySize / sizeof(*Data)) + 1];
+
+ if (Word0 & 0x80000000) {
+ errs() << "corrupt unwind data in section " << SectionIndex << "\n";
+ continue;
+ }
+
+ const uint64_t Offset = PREL31(Word0, IT->sh_addr);
+ SW.printHex("FunctionAddress", Offset);
+ if (ErrorOr<StringRef> Name = FunctionAtAddress(IT->sh_link, Offset))
+ SW.printString("FunctionName", *Name);
+
+ if (Word1 == EXIDX_CANTUNWIND) {
+ SW.printString("Model", StringRef("CantUnwind"));
+ continue;
+ }
+
+ if (Word1 & 0x80000000) {
+ SW.printString("Model", StringRef("Compact (Inline)"));
+
+ unsigned PersonalityIndex = (Word1 & 0x0f000000) >> 24;
+ SW.printNumber("PersonalityIndex", PersonalityIndex);
+
+ PrintOpcodes(Contents->data() + Entry * IndexTableEntrySize + 4, 3, 1);
+ } else {
+ const Elf_Shdr *EHT =
+ FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4);
+
+ if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT))
+ SW.printString("ExceptionHandlingTable", *Name);
+
+ uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr);
+ SW.printHex("TableEntryOffset", TableEntryOffset);
+
+ PrintExceptionTable(IT, EHT, TableEntryOffset);
+ }
+ }
+}
+
+template <typename ET>
+void PrinterContext<ET>::PrintUnwindInformation() const {
+ DictScope UI(SW, "UnwindInformation");
+
+ int SectionIndex = 0;
+ for (Elf_Shdr_iterator SI = ELF->begin_sections(), SE = ELF->end_sections();
+ SI != SE; ++SI, ++SectionIndex) {
+ if (SI->sh_type == ELF::SHT_ARM_EXIDX) {
+ const Elf_Shdr *IT = &(*SI);
+
+ DictScope UIT(SW, "UnwindIndexTable");
+
+ SW.printNumber("SectionIndex", SectionIndex);
+ if (ErrorOr<StringRef> SectionName = ELF->getSectionName(IT))
+ SW.printString("SectionName", *SectionName);
+ SW.printHex("SectionOffset", IT->sh_offset);
+
+ PrintIndexTable(SectionIndex, IT);
+ }
+ }
+}
+}
+}
+}
+
+#endif
+
diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt
index 90997a8..036185d 100644
--- a/tools/llvm-readobj/CMakeLists.txt
+++ b/tools/llvm-readobj/CMakeLists.txt
@@ -1,7 +1,8 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
- bitreader
- object)
+ Object
+ Support
+ )
add_llvm_tool(llvm-readobj
llvm-readobj.cpp
@@ -11,4 +12,5 @@ add_llvm_tool(llvm-readobj
MachODumper.cpp
Error.cpp
StreamWriter.cpp
+ ARMAttributeParser.cpp
)
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 2f309e3..cd40da7 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -13,23 +13,22 @@
//===----------------------------------------------------------------------===//
#include "llvm-readobj.h"
-#include "ObjDumper.h"
-
#include "Error.h"
+#include "ObjDumper.h"
#include "StreamWriter.h"
-
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/COFF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Win64EH.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-
#include <algorithm>
#include <cstring>
#include <time.h>
@@ -48,22 +47,23 @@ public:
cacheRelocations();
}
- virtual void printFileHeaders() LLVM_OVERRIDE;
- virtual void printSections() LLVM_OVERRIDE;
- virtual void printRelocations() LLVM_OVERRIDE;
- virtual void printSymbols() LLVM_OVERRIDE;
- virtual void printDynamicSymbols() LLVM_OVERRIDE;
- virtual void printUnwindInfo() LLVM_OVERRIDE;
+ virtual void printFileHeaders() override;
+ virtual void printSections() override;
+ virtual void printRelocations() override;
+ virtual void printSymbols() override;
+ virtual void printDynamicSymbols() override;
+ virtual void printUnwindInfo() override;
private:
- void printSymbol(symbol_iterator SymI);
-
- void printRelocation(section_iterator SecI, relocation_iterator RelI);
-
+ void printSymbol(const SymbolRef &Sym);
+ void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
void printDataDirectory(uint32_t Index, const std::string &FieldName);
-
void printX64UnwindInfo();
+ template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
+ void printBaseOfDataField(const pe32_header *Hdr);
+ void printBaseOfDataField(const pe32plus_header *Hdr);
+
void printRuntimeFunction(
const RuntimeFunction& RTF,
uint64_t OffsetInSection,
@@ -74,7 +74,9 @@ private:
uint64_t OffsetInSection,
const std::vector<RelocationRef> &Rels);
- void printUnwindCode(const Win64EH::UnwindInfo& UI, ArrayRef<UnwindCode> UCs);
+ void printUnwindCode(const Win64EH::UnwindInfo &UI, ArrayRef<UnwindCode> UCs);
+
+ void printCodeViewLineTables(const SectionRef &Section);
void cacheRelocations();
@@ -102,9 +104,8 @@ private:
namespace llvm {
-error_code createCOFFDumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result) {
+error_code createCOFFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
if (!COFFObj)
return readobj_error::unsupported_obj_file_format;
@@ -183,11 +184,11 @@ static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
if (error_code EC = Sym.getAddress(ResolvedAddr))
return EC;
- section_iterator iter(Obj->begin_sections());
+ section_iterator iter(Obj->section_begin());
if (error_code EC = Sym.getSection(iter))
return EC;
- ResolvedSection = Obj->getCOFFSection(iter);
+ ResolvedSection = Obj->getCOFFSection(*iter);
return object_error::success;
}
@@ -227,7 +228,7 @@ static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),
- LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMV7 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ),
@@ -279,6 +280,7 @@ static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
};
static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ),
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 ),
@@ -428,30 +430,9 @@ static const EnumEntry<unsigned> UnwindOpInfo[] = {
// Some additional COFF structures not defined by llvm::object.
namespace {
- struct coff_aux_function_definition {
- support::ulittle32_t TagIndex;
- support::ulittle32_t TotalSize;
- support::ulittle32_t PointerToLineNumber;
- support::ulittle32_t PointerToNextFunction;
- uint8_t Unused[2];
- };
-
- struct coff_aux_weak_external_definition {
- support::ulittle32_t TagIndex;
- support::ulittle32_t Characteristics;
- uint8_t Unused[10];
- };
-
struct coff_aux_file_record {
char FileName[18];
};
-
- struct coff_aux_clr_token {
- support::ulittle8_t AuxType;
- support::ulittle8_t Reserved;
- support::ulittle32_t SymbolTableIndex;
- uint8_t Unused[12];
- };
} // namespace
static uint64_t getOffsetOfLSDA(const Win64EH::UnwindInfo& UI) {
@@ -538,23 +519,11 @@ error_code COFFDumper::getSection(
}
void COFFDumper::cacheRelocations() {
- error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC))
- break;
-
- const coff_section *Section = Obj->getCOFFSection(SecI);
-
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC))
- break;
+ for (const SectionRef &S : Obj->sections()) {
+ const coff_section *Section = Obj->getCOFFSection(S);
- RelocMap[Section].push_back(*RelI);
- }
+ for (const RelocationRef &Reloc : S.relocations())
+ RelocMap[Section].push_back(Reloc);
// Sort relocations by address.
std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
@@ -598,73 +567,239 @@ void COFFDumper::printFileHeaders() {
const pe32_header *PEHeader = 0;
if (error(Obj->getPE32Header(PEHeader)))
return;
+ if (PEHeader)
+ printPEHeader<pe32_header>(PEHeader);
+
+ const pe32plus_header *PEPlusHeader = 0;
+ if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
+ return;
+ if (PEPlusHeader)
+ printPEHeader<pe32plus_header>(PEPlusHeader);
+}
+
+template <class PEHeader>
+void COFFDumper::printPEHeader(const PEHeader *Hdr) {
+ DictScope D(W, "ImageOptionalHeader");
+ W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
+ W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
+ W.printNumber("SizeOfCode", Hdr->SizeOfCode);
+ W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
+ W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
+ W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
+ W.printHex ("BaseOfCode", Hdr->BaseOfCode);
+ printBaseOfDataField(Hdr);
+ W.printHex ("ImageBase", Hdr->ImageBase);
+ W.printNumber("SectionAlignment", Hdr->SectionAlignment);
+ W.printNumber("FileAlignment", Hdr->FileAlignment);
+ W.printNumber("MajorOperatingSystemVersion",
+ Hdr->MajorOperatingSystemVersion);
+ W.printNumber("MinorOperatingSystemVersion",
+ Hdr->MinorOperatingSystemVersion);
+ W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
+ W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
+ W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
+ W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
+ W.printNumber("SizeOfImage", Hdr->SizeOfImage);
+ W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
+ W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
+ W.printFlags ("Subsystem", Hdr->DLLCharacteristics,
+ makeArrayRef(PEDLLCharacteristics));
+ W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
+ W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
+ W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
+ W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
+ W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
+
+ if (Hdr->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 < Hdr->NumberOfRvaAndSize; ++i) {
+ printDataDirectory(i, directory[i]);
+ }
+ }
+}
+
+void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
+ W.printHex("BaseOfData", Hdr->BaseOfData);
+}
+
+void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
+
+void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
+ StringRef Data;
+ if (error(Section.getContents(Data)))
+ return;
+
+ SmallVector<StringRef, 10> FunctionNames;
+ StringMap<StringRef> FunctionLineTables;
+ StringRef FileIndexToStringOffsetTable;
+ StringRef StringTable;
+
+ ListScope D(W, "CodeViewLineTables");
+ {
+ DataExtractor DE(Data, true, 4);
+ uint32_t Offset = 0,
+ Magic = DE.getU32(&Offset);
+ W.printHex("Magic", Magic);
+ if (Magic != COFF::DEBUG_SECTION_MAGIC) {
+ error(object_error::parse_failed);
+ return;
+ }
+
+ bool Finished = false;
+ while (DE.isValidOffset(Offset) && !Finished) {
+ // The section consists of a number of subsection in the following format:
+ // |Type|PayloadSize|Payload...|
+ uint32_t SubSectionType = DE.getU32(&Offset),
+ PayloadSize = DE.getU32(&Offset);
+ ListScope S(W, "Subsection");
+ W.printHex("Type", SubSectionType);
+ W.printHex("PayloadSize", PayloadSize);
+ if (PayloadSize > Data.size() - Offset) {
+ error(object_error::parse_failed);
+ return;
+ }
+
+ // Print the raw contents to simplify debugging if anything goes wrong
+ // afterwards.
+ StringRef Contents = Data.substr(Offset, PayloadSize);
+ W.printBinaryBlock("Contents", Contents);
+
+ switch (SubSectionType) {
+ case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
+ // Holds a PC to file:line table. Some data to parse this subsection is
+ // stored in the other subsections, so just check sanity and store the
+ // pointers for deferred processing.
+
+ if (PayloadSize < 12) {
+ // There should be at least three words to store two function
+ // relocations and size of the code.
+ error(object_error::parse_failed);
+ return;
+ }
+
+ StringRef FunctionName;
+ if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(Section)],
+ Offset, FunctionName)))
+ return;
+ W.printString("FunctionName", FunctionName);
+ if (FunctionLineTables.count(FunctionName) != 0) {
+ // Saw debug info for this function already?
+ error(object_error::parse_failed);
+ return;
+ }
+
+ FunctionLineTables[FunctionName] = Contents;
+ FunctionNames.push_back(FunctionName);
+ break;
+ }
+ case COFF::DEBUG_STRING_TABLE_SUBSECTION:
+ if (PayloadSize == 0 || StringTable.data() != 0 ||
+ Contents.back() != '\0') {
+ // Empty or duplicate or non-null-terminated subsection.
+ error(object_error::parse_failed);
+ return;
+ }
+ StringTable = Contents;
+ break;
+ case COFF::DEBUG_INDEX_SUBSECTION:
+ // Holds the translation table from file indices
+ // to offsets in the string table.
+
+ if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) {
+ // Empty or duplicate subsection.
+ error(object_error::parse_failed);
+ return;
+ }
+ FileIndexToStringOffsetTable = Contents;
+ break;
+ }
+ Offset += PayloadSize;
+
+ // Align the reading pointer by 4.
+ Offset += (-Offset) % 4;
+ }
+ }
+
+ // Dump the line tables now that we've read all the subsections and know all
+ // the required information.
+ for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
+ StringRef Name = FunctionNames[I];
+ ListScope S(W, "FunctionLineTable");
+ W.printString("FunctionName", Name);
+
+ DataExtractor DE(FunctionLineTables[Name], true, 4);
+ uint32_t Offset = 8; // Skip relocations.
+ uint32_t FunctionSize = DE.getU32(&Offset);
+ W.printHex("CodeSize", FunctionSize);
+ while (DE.isValidOffset(Offset)) {
+ // For each range of lines with the same filename, we have a segment
+ // in the line table. The filename string is accessed using double
+ // indirection to the string table subsection using the index subsection.
+ uint32_t OffsetInIndex = DE.getU32(&Offset),
+ SegmentLength = DE.getU32(&Offset),
+ FullSegmentSize = DE.getU32(&Offset);
+ if (FullSegmentSize != 12 + 8 * SegmentLength) {
+ error(object_error::parse_failed);
+ return;
+ }
+
+ uint32_t FilenameOffset;
+ {
+ DataExtractor SDE(FileIndexToStringOffsetTable, true, 4);
+ uint32_t OffsetInSDE = OffsetInIndex;
+ if (!SDE.isValidOffset(OffsetInSDE)) {
+ error(object_error::parse_failed);
+ return;
+ }
+ FilenameOffset = SDE.getU32(&OffsetInSDE);
+ }
- 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]);
+ if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() ||
+ StringTable.data()[FilenameOffset - 1] != '\0') {
+ // Each string in an F3 subsection should be preceded by a null
+ // character.
+ error(object_error::parse_failed);
+ return;
+ }
+
+ StringRef Filename(StringTable.data() + FilenameOffset);
+ ListScope S(W, "FilenameSegment");
+ W.printString("Filename", Filename);
+ for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
+ ++J) {
+ // Then go the (PC, LineNumber) pairs. The line number is stored in the
+ // least significant 31 bits of the respective word in the table.
+ uint32_t PC = DE.getU32(&Offset),
+ LineNumber = DE.getU32(&Offset) & 0x7fffffff;
+ if (PC >= FunctionSize) {
+ error(object_error::parse_failed);
+ return;
+ }
+ char Buffer[32];
+ format("+0x%X", PC).snprint(Buffer, 32);
+ W.printNumber(Buffer, LineNumber);
}
}
}
}
void COFFDumper::printSections() {
- error_code EC;
-
ListScope SectionsD(W, "Sections");
int SectionNumber = 0;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC))
- break;
-
+ for (const SectionRef &Sec : Obj->sections()) {
++SectionNumber;
- const coff_section *Section = Obj->getCOFFSection(SecI);
+ const coff_section *Section = Obj->getCOFFSection(Sec);
StringRef Name;
- if (error(SecI->getName(Name)))
- Name = "";
+ if (error(Sec.getName(Name)))
+ Name = "";
DictScope D(W, "Section");
W.printNumber("Number", SectionNumber);
@@ -683,33 +818,28 @@ void COFFDumper::printSections() {
if (opts::SectionRelocations) {
ListScope D(W, "Relocations");
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
- printRelocation(SecI, RelI);
- }
+ for (const RelocationRef &Reloc : Sec.relocations())
+ printRelocation(Sec, Reloc);
}
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SymbolRef &Symbol : Obj->symbols()) {
bool Contained = false;
- if (SecI->containsSymbol(*SymI, Contained) || !Contained)
+ if (Sec.containsSymbol(Symbol, Contained) || !Contained)
continue;
- printSymbol(SymI);
+ printSymbol(Symbol);
}
}
+ if (Name == ".debug$S" && opts::CodeViewLineTables)
+ printCodeViewLineTables(Sec);
+
if (opts::SectionData) {
StringRef Data;
- if (error(SecI->getContents(Data))) break;
+ if (error(Sec.getContents(Data)))
+ break;
W.printBinaryBlock("SectionData", Data);
}
@@ -719,32 +849,22 @@ void COFFDumper::printSections() {
void COFFDumper::printRelocations() {
ListScope D(W, "Relocations");
- error_code EC;
int SectionNumber = 0;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
+ for (const SectionRef &Section : Obj->sections()) {
++SectionNumber;
- if (error(EC))
- break;
-
StringRef Name;
- if (error(SecI->getName(Name)))
+ if (error(Section.getName(Name)))
continue;
bool PrintedGroup = false;
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const RelocationRef &Reloc : Section.relocations()) {
if (!PrintedGroup) {
W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
W.indent();
PrintedGroup = true;
}
- printRelocation(SecI, RelI);
+ printRelocation(Section, Reloc);
}
if (PrintedGroup) {
@@ -754,19 +874,24 @@ void COFFDumper::printRelocations() {
}
}
-void COFFDumper::printRelocation(section_iterator SecI,
- relocation_iterator RelI) {
+void COFFDumper::printRelocation(const SectionRef &Section,
+ const RelocationRef &Reloc) {
uint64_t Offset;
uint64_t RelocType;
SmallString<32> RelocName;
StringRef SymbolName;
StringRef Contents;
- if (error(RelI->getOffset(Offset))) return;
- if (error(RelI->getType(RelocType))) return;
- if (error(RelI->getTypeName(RelocName))) return;
- symbol_iterator Symbol = RelI->getSymbol();
- if (error(Symbol->getName(SymbolName))) return;
- if (error(SecI->getContents(Contents))) return;
+ if (error(Reloc.getOffset(Offset)))
+ return;
+ if (error(Reloc.getType(RelocType)))
+ return;
+ if (error(Reloc.getTypeName(RelocName)))
+ return;
+ symbol_iterator Symbol = Reloc.getSymbol();
+ if (error(Symbol->getName(SymbolName)))
+ return;
+ if (error(Section.getContents(Contents)))
+ return;
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
@@ -785,24 +910,16 @@ void COFFDumper::printRelocation(section_iterator SecI,
void COFFDumper::printSymbols() {
ListScope Group(W, "Symbols");
- error_code EC;
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
- printSymbol(SymI);
- }
+ for (const SymbolRef &Symbol : Obj->symbols())
+ printSymbol(Symbol);
}
-void COFFDumper::printDynamicSymbols() {
- ListScope Group(W, "DynamicSymbols");
-}
+void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
-void COFFDumper::printSymbol(symbol_iterator SymI) {
+void COFFDumper::printSymbol(const SymbolRef &Sym) {
DictScope D(W, "Symbol");
- const coff_symbol *Symbol = Obj->getCOFFSymbol(SymI);
+ const coff_symbol *Symbol = Obj->getCOFFSymbol(Sym);
const coff_section *Section;
if (error_code EC = Obj->getSection(Symbol->SectionNumber, Section)) {
W.startLine() << "Invalid section number: " << EC.message() << "\n";
@@ -829,10 +946,7 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols);
for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) {
- if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- Symbol->getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
- Symbol->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
- Symbol->SectionNumber > 0) {
+ if (Symbol->isFunctionDefinition()) {
const coff_aux_function_definition *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
@@ -840,16 +954,12 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
DictScope AS(W, "AuxFunctionDef");
W.printNumber("TagIndex", Aux->TagIndex);
W.printNumber("TotalSize", Aux->TotalSize);
- W.printHex("PointerToLineNumber", Aux->PointerToLineNumber);
+ W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
W.printBinary("Unused", makeArrayRef(Aux->Unused));
- } else if (
- Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
- (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- Symbol->SectionNumber == 0 &&
- Symbol->Value == 0)) {
- const coff_aux_weak_external_definition *Aux;
+ } else if (Symbol->isWeakExternal()) {
+ const coff_aux_weak_external *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
@@ -866,9 +976,9 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
W.printNumber("Linked", LinkedName, Aux->TagIndex);
W.printEnum ("Search", Aux->Characteristics,
makeArrayRef(WeakExternalCharacteristics));
- W.printBinary("Unused", Aux->Unused);
+ W.printBinary("Unused", makeArrayRef(Aux->Unused));
- } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_FILE) {
+ } else if (Symbol->isFileRecord()) {
const coff_aux_file_record *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
@@ -876,9 +986,7 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
DictScope AS(W, "AuxFileRecord");
W.printString("FileName", StringRef(Aux->FileName));
- } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC ||
- (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- Symbol->SectionNumber != COFF::IMAGE_SYM_UNDEFINED)) {
+ } else if (Symbol->isSectionDefinition()) {
const coff_aux_section_definition *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
@@ -905,16 +1013,25 @@ void COFFDumper::printSymbol(symbol_iterator SymI) {
W.printNumber("AssocSection", AssocName, Aux->Number);
}
- } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN) {
+ } else if (Symbol->isCLRToken()) {
const coff_aux_clr_token *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
+ const coff_symbol *ReferredSym;
+ StringRef ReferredName;
+ error_code EC;
+ if ((EC = Obj->getSymbol(Aux->SymbolTableIndex, ReferredSym)) ||
+ (EC = Obj->getSymbolName(ReferredSym, ReferredName))) {
+ ReferredName = "";
+ error(EC);
+ }
+
DictScope AS(W, "AuxCLRToken");
W.printNumber("AuxType", Aux->AuxType);
W.printNumber("Reserved", Aux->Reserved);
- W.printNumber("SymbolTableIndex", Aux->SymbolTableIndex);
- W.printBinary("Unused", Aux->Unused);
+ W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex);
+ W.printBinary("Unused", makeArrayRef(Aux->Unused));
} else {
W.startLine() << "<unhandled auxiliary record>\n";
@@ -938,23 +1055,17 @@ void COFFDumper::printUnwindInfo() {
}
void COFFDumper::printX64UnwindInfo() {
- error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(SecI->getName(Name)))
+ if (error(Section.getName(Name)))
continue;
if (Name != ".pdata" && !Name.startswith(".pdata$"))
continue;
- const coff_section *PData = Obj->getCOFFSection(SecI);
+ const coff_section *PData = Obj->getCOFFSection(Section);
ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(PData, Contents)) ||
- Contents.empty())
+ if (error(Obj->getSectionContents(PData, Contents)) || Contents.empty())
continue;
ArrayRef<RuntimeFunction> RFs(
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 07a9083..4cd3393 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -13,12 +13,15 @@
//===----------------------------------------------------------------------===//
#include "llvm-readobj.h"
+#include "ARMAttributeParser.h"
+#include "ARMEHABIPrinter.h"
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
-
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
@@ -39,16 +42,18 @@ public:
ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
: ObjDumper(Writer), Obj(Obj) {}
- virtual void printFileHeaders() LLVM_OVERRIDE;
- virtual void printSections() LLVM_OVERRIDE;
- virtual void printRelocations() LLVM_OVERRIDE;
- virtual void printSymbols() LLVM_OVERRIDE;
- virtual void printDynamicSymbols() LLVM_OVERRIDE;
- virtual void printUnwindInfo() LLVM_OVERRIDE;
+ void printFileHeaders() override;
+ void printSections() override;
+ void printRelocations() override;
+ void printSymbols() override;
+ void printDynamicSymbols() override;
+ void printUnwindInfo() override;
+
+ void printDynamicTable() override;
+ void printNeededLibraries() override;
+ void printProgramHeaders() override;
- virtual void printDynamicTable() LLVM_OVERRIDE;
- virtual void printNeededLibraries() LLVM_OVERRIDE;
- virtual void printProgramHeaders() LLVM_OVERRIDE;
+ void printAttributes() override;
private:
typedef ELFFile<ELFT> ELFO;
@@ -65,7 +70,7 @@ private:
template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) {
if (!Val) {
- error(Val);
+ error(Val.getError());
return Default;
}
@@ -78,14 +83,13 @@ namespace llvm {
template <class ELFT>
static error_code createELFDumper(const ELFFile<ELFT> *Obj,
StreamWriter &Writer,
- OwningPtr<ObjDumper> &Result) {
+ std::unique_ptr<ObjDumper> &Result) {
Result.reset(new ELFDumper<ELFT>(Obj, Writer));
return readobj_error::success;
}
-error_code createELFDumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result) {
+error_code createELFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
// Little-endian 32-bit
if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
return createELFDumper(ELFObj->getELFFile(), Writer, Result);
@@ -621,8 +625,30 @@ void ELFDumper<ELFT>::printDynamicSymbols() {
template <class ELFT>
void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
StringRef SymbolName = errorOrDefault(Obj->getSymbolName(Symbol));
- const Elf_Shdr *Sec = Obj->getSection(&*Symbol);
- StringRef SectionName = Sec ? errorOrDefault(Obj->getSectionName(Sec)) : "";
+
+ unsigned SectionIndex = Symbol->st_shndx;
+ StringRef SectionName;
+ if (SectionIndex == SHN_UNDEF) {
+ SectionName = "Undefined";
+ } else if (SectionIndex >= SHN_LOPROC && SectionIndex <= SHN_HIPROC) {
+ SectionName = "Processor Specific";
+ } else if (SectionIndex >= SHN_LOOS && SectionIndex <= SHN_HIOS) {
+ SectionName = "Operating System Specific";
+ } else if (SectionIndex > SHN_HIOS && SectionIndex < SHN_ABS) {
+ SectionName = "Reserved";
+ } else if (SectionIndex == SHN_ABS) {
+ SectionName = "Absolute";
+ } else if (SectionIndex == SHN_COMMON) {
+ SectionName = "Common";
+ } else {
+ if (SectionIndex == SHN_XINDEX)
+ SectionIndex = Obj->getSymbolTableIndex(&*Symbol);
+ assert(SectionIndex != SHN_XINDEX &&
+ "getSymbolTableIndex should handle this");
+ const Elf_Shdr *Sec = Obj->getSection(SectionIndex);
+ SectionName = errorOrDefault(Obj->getSectionName(Sec));
+ }
+
std::string FullSymbolName(SymbolName);
if (Symbol.isDynamic()) {
bool IsDefault;
@@ -631,7 +657,7 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
FullSymbolName += (IsDefault ? "@@" : "@");
FullSymbolName += *Version;
} else
- error(Version);
+ error(Version.getError());
}
DictScope D(W, "Symbol");
@@ -642,7 +668,7 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
makeArrayRef(ElfSymbolBindings));
W.printEnum ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes));
W.printNumber("Other", Symbol->st_other);
- W.printHex ("Section", SectionName, Symbol->st_shndx);
+ W.printHex("Section", SectionName, SectionIndex);
}
#define LLVM_READOBJ_TYPE_CASE(name) \
@@ -693,6 +719,8 @@ static const char *getTypeString(uint64_t Type) {
LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO);
LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO);
LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM);
+ LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP);
+ LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT);
default: return "unknown";
}
}
@@ -731,6 +759,8 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_MIPS_FLAGS:
case DT_MIPS_BASE_ADDRESS:
case DT_MIPS_GOTSYM:
+ case DT_MIPS_RLD_MAP:
+ case DT_MIPS_PLTGOT:
OS << format("0x%" PRIX64, Value);
break;
case DT_VERNEEDNUM:
@@ -770,6 +800,18 @@ void ELFDumper<ELFT>::printUnwindInfo() {
W.startLine() << "UnwindInfo not implemented.\n";
}
+namespace {
+template <>
+void ELFDumper<ELFType<support::little, 2, false> >::printUnwindInfo() {
+ const unsigned Machine = Obj->getHeader()->e_machine;
+ if (Machine == EM_ARM) {
+ ARM::EHABI::PrinterContext<ELFType<support::little, 2, false> > Ctx(W, Obj);
+ return Ctx.PrintUnwindInformation();
+ }
+ W.startLine() << "UnwindInfo not implemented.\n";
+}
+}
+
template<class ELFT>
void ELFDumper<ELFT>::printDynamicTable() {
typedef typename ELFO::Elf_Dyn_Iter EDI;
@@ -839,3 +881,42 @@ void ELFDumper<ELFT>::printProgramHeaders() {
W.printNumber("Alignment", PI->p_align);
}
}
+
+template <class ELFT>
+void ELFDumper<ELFT>::printAttributes() {
+ W.startLine() << "Attributes not implemented.\n";
+}
+
+namespace {
+template <>
+void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() {
+ if (Obj->getHeader()->e_machine != EM_ARM) {
+ W.startLine() << "Attributes not implemented.\n";
+ return;
+ }
+
+ DictScope BA(W, "BuildAttributes");
+ for (ELFO::Elf_Shdr_Iter SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; ++SI) {
+ if (SI->sh_type != ELF::SHT_ARM_ATTRIBUTES)
+ continue;
+
+ ErrorOr<ArrayRef<uint8_t> > Contents = Obj->getSectionContents(&(*SI));
+ if (!Contents)
+ continue;
+
+ if ((*Contents)[0] != ARMBuildAttrs::Format_Version) {
+ errs() << "unrecognised FormatVersion: 0x" << utohexstr((*Contents)[0])
+ << '\n';
+ continue;
+ }
+
+ W.printHex("FormatVersion", (*Contents)[0]);
+ if (Contents->size() == 1)
+ continue;
+
+ ARMAttributeParser(W).Parse(*Contents);
+ }
+}
+}
+
diff --git a/tools/llvm-readobj/Error.cpp b/tools/llvm-readobj/Error.cpp
index a6c6132..83ed6a7 100644
--- a/tools/llvm-readobj/Error.cpp
+++ b/tools/llvm-readobj/Error.cpp
@@ -17,11 +17,11 @@
using namespace llvm;
namespace {
-class _readobj_error_category : public _do_message {
+class _readobj_error_category : public error_category {
public:
- virtual const char* name() const;
- virtual std::string message(int ev) const;
- virtual error_condition default_error_condition(int ev) const;
+ const char* name() const override;
+ std::string message(int ev) const override;
+ error_condition default_error_condition(int ev) const override;
};
} // namespace
diff --git a/tools/llvm-readobj/Error.h b/tools/llvm-readobj/Error.h
index cf68da8..5129b4e 100644
--- a/tools/llvm-readobj/Error.h
+++ b/tools/llvm-readobj/Error.h
@@ -40,8 +40,8 @@ inline error_code make_error_code(readobj_error e) {
return error_code(static_cast<int>(e), readobj_category());
}
-template <> struct is_error_code_enum<readobj_error> : true_type { };
-template <> struct is_error_code_enum<readobj_error::_> : true_type { };
+template <> struct is_error_code_enum<readobj_error> : std::true_type { };
+template <> struct is_error_code_enum<readobj_error::_> : std::true_type { };
} // namespace llvm
diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp
index b97166b..2fd5d4a 100644
--- a/tools/llvm-readobj/MachODumper.cpp
+++ b/tools/llvm-readobj/MachODumper.cpp
@@ -15,7 +15,6 @@
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
-
#include "llvm/ADT/SmallString.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
@@ -31,20 +30,19 @@ public:
: ObjDumper(Writer)
, Obj(Obj) { }
- virtual void printFileHeaders() LLVM_OVERRIDE;
- virtual void printSections() LLVM_OVERRIDE;
- virtual void printRelocations() LLVM_OVERRIDE;
- virtual void printSymbols() LLVM_OVERRIDE;
- virtual void printDynamicSymbols() LLVM_OVERRIDE;
- virtual void printUnwindInfo() LLVM_OVERRIDE;
+ virtual void printFileHeaders() override;
+ virtual void printSections() override;
+ virtual void printRelocations() override;
+ virtual void printSymbols() override;
+ virtual void printDynamicSymbols() override;
+ virtual void printUnwindInfo() override;
private:
- void printSymbol(symbol_iterator SymI);
+ void printSymbol(const SymbolRef &Symbol);
- void printRelocation(section_iterator SecI, relocation_iterator RelI);
+ void printRelocation(const RelocationRef &Reloc);
- void printRelocation(const MachOObjectFile *Obj,
- section_iterator SecI, relocation_iterator RelI);
+ void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc);
void printSections(const MachOObjectFile *Obj);
@@ -57,8 +55,8 @@ private:
namespace llvm {
error_code createMachODumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result) {
+ StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj);
if (!MachOObj)
return readobj_error::unsupported_obj_file_format;
@@ -126,19 +124,13 @@ static const EnumEntry<unsigned> MachOSymbolFlags[] = {
static const EnumEntry<unsigned> MachOSymbolTypes[] = {
{ "Undef", 0x0 },
- { "External", 0x1 },
{ "Abs", 0x2 },
{ "Indirect", 0xA },
{ "PreboundUndef", 0xC },
- { "Section", 0xE },
- { "PrivateExternal", 0x10 }
+ { "Section", 0xE }
};
namespace {
- enum {
- N_STAB = 0xE0
- };
-
struct MachOSection {
ArrayRef<char> Name;
ArrayRef<char> SegmentName;
@@ -223,21 +215,16 @@ void MachODumper::printSections(const MachOObjectFile *Obj) {
ListScope Group(W, "Sections");
int SectionIndex = -1;
- error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SectionRef &Section : Obj->sections()) {
++SectionIndex;
- MachOSection Section;
- getSection(Obj, SecI->getRawDataRefImpl(), Section);
- DataRefImpl DR = SecI->getRawDataRefImpl();
+ MachOSection MOSection;
+ getSection(Obj, Section.getRawDataRefImpl(), MOSection);
+ DataRefImpl DR = Section.getRawDataRefImpl();
StringRef Name;
- if (error(SecI->getName(Name)))
- Name = "";
+ if (error(Section.getName(Name)))
+ Name = "";
ArrayRef<char> RawName = Obj->getSectionRawName(DR);
StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
@@ -247,48 +234,40 @@ void MachODumper::printSections(const MachOObjectFile *Obj) {
W.printNumber("Index", SectionIndex);
W.printBinary("Name", Name, RawName);
W.printBinary("Segment", SegmentName, RawSegmentName);
- W.printHex ("Address", Section.Address);
- W.printHex ("Size", Section.Size);
- W.printNumber("Offset", Section.Offset);
- W.printNumber("Alignment", Section.Alignment);
- W.printHex ("RelocationOffset", Section.RelocationTableOffset);
- W.printNumber("RelocationCount", Section.NumRelocationTableEntries);
- W.printEnum ("Type", Section.Flags & 0xFF,
- makeArrayRef(MachOSectionAttributes));
- W.printFlags ("Attributes", Section.Flags >> 8,
- makeArrayRef(MachOSectionAttributes));
- W.printHex ("Reserved1", Section.Reserved1);
- W.printHex ("Reserved2", Section.Reserved2);
+ W.printHex("Address", MOSection.Address);
+ W.printHex("Size", MOSection.Size);
+ W.printNumber("Offset", MOSection.Offset);
+ W.printNumber("Alignment", MOSection.Alignment);
+ W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
+ W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
+ W.printEnum("Type", MOSection.Flags & 0xFF,
+ makeArrayRef(MachOSectionAttributes));
+ W.printFlags("Attributes", MOSection.Flags >> 8,
+ makeArrayRef(MachOSectionAttributes));
+ W.printHex("Reserved1", MOSection.Reserved1);
+ W.printHex("Reserved2", MOSection.Reserved2);
if (opts::SectionRelocations) {
ListScope D(W, "Relocations");
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
- printRelocation(SecI, RelI);
- }
+ for (const RelocationRef &Reloc : Section.relocations())
+ printRelocation(Reloc);
}
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SymbolRef &Symbol : Obj->symbols()) {
bool Contained = false;
- if (SecI->containsSymbol(*SymI, Contained) || !Contained)
+ if (Section.containsSymbol(Symbol, Contained) || !Contained)
continue;
- printSymbol(SymI);
+ printSymbol(Symbol);
}
}
if (opts::SectionData) {
StringRef Data;
- if (error(SecI->getContents(Data))) break;
+ if (error(Section.getContents(Data)))
+ break;
W.printBinaryBlock("SectionData", Data);
}
@@ -299,28 +278,20 @@ void MachODumper::printRelocations() {
ListScope D(W, "Relocations");
error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(SecI->getName(Name)))
+ if (error(Section.getName(Name)))
continue;
bool PrintedGroup = false;
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const RelocationRef &Reloc : Section.relocations()) {
if (!PrintedGroup) {
W.startLine() << "Section " << Name << " {\n";
W.indent();
PrintedGroup = true;
}
- printRelocation(SecI, RelI);
+ printRelocation(Reloc);
}
if (PrintedGroup) {
@@ -330,25 +301,24 @@ void MachODumper::printRelocations() {
}
}
-void MachODumper::printRelocation(section_iterator SecI,
- relocation_iterator RelI) {
- return printRelocation(Obj, SecI, RelI);
+void MachODumper::printRelocation(const RelocationRef &Reloc) {
+ return printRelocation(Obj, Reloc);
}
void MachODumper::printRelocation(const MachOObjectFile *Obj,
- section_iterator SecI,
- relocation_iterator RelI) {
+ const RelocationRef &Reloc) {
uint64_t Offset;
SmallString<32> RelocName;
StringRef SymbolName;
- if (error(RelI->getOffset(Offset))) return;
- if (error(RelI->getTypeName(RelocName))) return;
- symbol_iterator Symbol = RelI->getSymbol();
- if (Symbol != Obj->end_symbols() &&
- error(Symbol->getName(SymbolName)))
+ if (error(Reloc.getOffset(Offset)))
+ return;
+ if (error(Reloc.getTypeName(RelocName)))
+ return;
+ symbol_iterator Symbol = Reloc.getSymbol();
+ if (Symbol != Obj->symbol_end() && error(Symbol->getName(SymbolName)))
return;
- DataRefImpl DR = RelI->getRawDataRefImpl();
+ DataRefImpl DR = Reloc.getRawDataRefImpl();
MachO::any_relocation_info RE = Obj->getRelocation(DR);
bool IsScattered = Obj->isRelocationScattered(RE);
@@ -383,13 +353,8 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj,
void MachODumper::printSymbols() {
ListScope Group(W, "Symbols");
- error_code EC;
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
- printSymbol(SymI);
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ printSymbol(Symbol);
}
}
@@ -397,33 +362,37 @@ void MachODumper::printDynamicSymbols() {
ListScope Group(W, "DynamicSymbols");
}
-void MachODumper::printSymbol(symbol_iterator SymI) {
+void MachODumper::printSymbol(const SymbolRef &Symbol) {
StringRef SymbolName;
- if (SymI->getName(SymbolName))
+ if (Symbol.getName(SymbolName))
SymbolName = "";
- MachOSymbol Symbol;
- getSymbol(Obj, SymI->getRawDataRefImpl(), Symbol);
+ MachOSymbol MOSymbol;
+ getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);
StringRef SectionName = "";
- section_iterator SecI(Obj->end_sections());
- if (!error(SymI->getSection(SecI)) &&
- SecI != Obj->end_sections())
- error(SecI->getName(SectionName));
+ section_iterator SecI(Obj->section_begin());
+ if (!error(Symbol.getSection(SecI)) && SecI != Obj->section_end())
+ error(SecI->getName(SectionName));
DictScope D(W, "Symbol");
- W.printNumber("Name", SymbolName, Symbol.StringIndex);
- if (Symbol.Type & N_STAB) {
- W.printHex ("Type", "SymDebugTable", Symbol.Type);
+ W.printNumber("Name", SymbolName, MOSymbol.StringIndex);
+ if (MOSymbol.Type & MachO::N_STAB) {
+ W.printHex("Type", "SymDebugTable", MOSymbol.Type);
} else {
- W.printEnum("Type", Symbol.Type, makeArrayRef(MachOSymbolTypes));
+ if (MOSymbol.Type & MachO::N_PEXT)
+ W.startLine() << "PrivateExtern\n";
+ if (MOSymbol.Type & MachO::N_EXT)
+ W.startLine() << "Extern\n";
+ W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),
+ makeArrayRef(MachOSymbolTypes));
}
- W.printHex ("Section", SectionName, Symbol.SectionIndex);
- W.printEnum ("RefType", static_cast<uint16_t>(Symbol.Flags & 0xF),
- makeArrayRef(MachOSymbolRefTypes));
- W.printFlags ("Flags", static_cast<uint16_t>(Symbol.Flags & ~0xF),
- makeArrayRef(MachOSymbolFlags));
- W.printHex ("Value", Symbol.Value);
+ W.printHex("Section", SectionName, MOSymbol.SectionIndex);
+ W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0xF),
+ makeArrayRef(MachOSymbolRefTypes));
+ W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0xF),
+ makeArrayRef(MachOSymbolFlags));
+ W.printHex("Value", MOSymbol.Value);
}
void MachODumper::printUnwindInfo() {
diff --git a/tools/llvm-readobj/ObjDumper.cpp b/tools/llvm-readobj/ObjDumper.cpp
index 61f5117..f500a05 100644
--- a/tools/llvm-readobj/ObjDumper.cpp
+++ b/tools/llvm-readobj/ObjDumper.cpp
@@ -13,10 +13,8 @@
//===----------------------------------------------------------------------===//
#include "ObjDumper.h"
-
#include "Error.h"
#include "StreamWriter.h"
-
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h
index 6918e28..9e0fd2f 100644
--- a/tools/llvm-readobj/ObjDumper.h
+++ b/tools/llvm-readobj/ObjDumper.h
@@ -10,6 +10,8 @@
#ifndef LLVM_READOBJ_OBJDUMPER_H
#define LLVM_READOBJ_OBJDUMPER_H
+#include <memory>
+
namespace llvm {
namespace object {
@@ -18,9 +20,6 @@ namespace object {
class error_code;
-template<typename T>
-class OwningPtr;
-
class StreamWriter;
class ObjDumper {
@@ -40,21 +39,22 @@ public:
virtual void printNeededLibraries() { }
virtual void printProgramHeaders() { }
+ // Only implemented for ARM ELF at this time.
+ virtual void printAttributes() { }
+
protected:
StreamWriter& W;
};
-error_code createCOFFDumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result);
+error_code createCOFFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result);
-error_code createELFDumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result);
+error_code createELFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result);
error_code createMachODumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result);
+ StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result);
} // namespace llvm
diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h
index 129f6e7..c40077a 100644
--- a/tools/llvm-readobj/StreamWriter.h
+++ b/tools/llvm-readobj/StreamWriter.h
@@ -11,8 +11,8 @@
#define LLVM_READOBJ_STREAMWRITER_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
@@ -172,6 +172,19 @@ public:
startLine() << Label << ": " << int(Value) << "\n";
}
+ template <typename T_>
+ void printList(StringRef Label, const SmallVectorImpl<T_> &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (unsigned LI = 0, LE = List.size(); LI != LE; ++LI) {
+ if (Comma)
+ OS << ", ";
+ OS << List[LI];
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
template<typename T>
void printHex(StringRef Label, T Value) {
startLine() << Label << ": " << hex(Value) << "\n";
diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp
index f84a72f..5be959f 100644
--- a/tools/llvm-readobj/llvm-readobj.cpp
+++ b/tools/llvm-readobj/llvm-readobj.cpp
@@ -20,11 +20,9 @@
//===----------------------------------------------------------------------===//
#include "llvm-readobj.h"
-
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
-
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
@@ -38,7 +36,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
-
#include <string>
@@ -128,6 +125,16 @@ namespace opts {
// -expand-relocs
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
+
+ // -codeview-linetables
+ cl::opt<bool> CodeViewLineTables("codeview-linetables",
+ cl::desc("Display CodeView line table information"));
+
+ // -arm-attributes, -a
+ cl::opt<bool> ARMAttributes("arm-attributes",
+ cl::desc("Display the ARM attributes section"));
+ cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"),
+ cl::aliasopt(ARMAttributes));
} // namespace opts
static int ReturnValue = EXIT_SUCCESS;
@@ -172,9 +179,8 @@ static void reportError(StringRef Input, StringRef Message) {
}
/// @brief Creates an format-specific object file dumper.
-static error_code createDumper(const ObjectFile *Obj,
- StreamWriter &Writer,
- OwningPtr<ObjDumper> &Result) {
+static error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
if (!Obj)
return readobj_error::unsupported_file_format;
@@ -192,7 +198,7 @@ static error_code createDumper(const ObjectFile *Obj,
/// @brief Dumps the specified object file.
static void dumpObject(const ObjectFile *Obj) {
StreamWriter Writer(outs());
- OwningPtr<ObjDumper> Dumper;
+ std::unique_ptr<ObjDumper> Dumper;
if (error_code EC = createDumper(Obj, Writer, Dumper)) {
reportError(Obj->getFileName(), EC);
return;
@@ -226,15 +232,18 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printNeededLibraries();
if (opts::ProgramHeaders)
Dumper->printProgramHeaders();
+ if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
+ if (opts::ARMAttributes)
+ Dumper->printAttributes();
}
/// @brief Dumps each object file in \a Arc;
static void dumpArchive(const Archive *Arc) {
- for (Archive::child_iterator ArcI = Arc->begin_children(),
- ArcE = Arc->end_children();
+ for (Archive::child_iterator ArcI = Arc->child_begin(),
+ ArcE = Arc->child_end();
ArcI != ArcE; ++ArcI) {
- OwningPtr<Binary> child;
+ std::unique_ptr<Binary> child;
if (error_code EC = ArcI->getAsBinary(child)) {
// Ignore non-object files.
if (EC != object_error::invalid_file_type)
@@ -259,11 +268,12 @@ static void dumpInput(StringRef File) {
}
// Attempt to open the binary.
- OwningPtr<Binary> Binary;
- if (error_code EC = createBinary(File, Binary)) {
+ ErrorOr<Binary *> BinaryOrErr = createBinary(File);
+ if (error_code EC = BinaryOrErr.getError()) {
reportError(File, EC);
return;
}
+ std::unique_ptr<Binary> Binary(BinaryOrErr.get());
if (Archive *Arc = dyn_cast<Archive>(Binary.get()))
dumpArchive(Arc);
diff --git a/tools/llvm-readobj/llvm-readobj.h b/tools/llvm-readobj/llvm-readobj.h
index 3f75610..cc5c85d 100644
--- a/tools/llvm-readobj/llvm-readobj.h
+++ b/tools/llvm-readobj/llvm-readobj.h
@@ -38,6 +38,8 @@ namespace opts {
extern llvm::cl::opt<bool> DynamicSymbols;
extern llvm::cl::opt<bool> UnwindInfo;
extern llvm::cl::opt<bool> ExpandRelocs;
+ extern llvm::cl::opt<bool> CodeViewLineTables;
+ extern llvm::cl::opt<bool> ARMAttributes;
} // namespace opts
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \
diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt
index 8d161d3..3ad127f 100644
--- a/tools/llvm-rtdyld/CMakeLists.txt
+++ b/tools/llvm-rtdyld/CMakeLists.txt
@@ -1,4 +1,9 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT debuginfo)
+set(LLVM_LINK_COMPONENTS
+ DebugInfo
+ ExecutionEngine
+ RuntimeDyld
+ Support
+ )
add_llvm_tool(llvm-rtdyld
llvm-rtdyld.cpp
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 531595e..ac43653 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/ExecutionEngine/ObjectBuffer.h"
@@ -62,17 +61,18 @@ public:
SmallVector<sys::MemoryBlock, 16> DataMemory;
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, StringRef SectionName);
+ unsigned SectionID,
+ StringRef SectionName) override;
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
- bool IsReadOnly);
+ bool IsReadOnly) override;
- virtual void *getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure = true) {
+ void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure = true) override {
return 0;
}
- bool finalizeMemory(std::string *ErrMsg) { return false; }
+ bool finalizeMemory(std::string *ErrMsg) override { return false; }
// Invalidate instruction cache for sections with execute permissions.
// Some platforms with separate data cache and instruction cache require
@@ -133,14 +133,14 @@ static int printLineInfoForInput() {
RuntimeDyld Dyld(&MemMgr);
// Load the input memory buffer.
- OwningPtr<MemoryBuffer> InputBuffer;
- OwningPtr<ObjectImage> LoadedObject;
+ std::unique_ptr<MemoryBuffer> InputBuffer;
+ std::unique_ptr<ObjectImage> LoadedObject;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
InputBuffer))
return Error("unable to read input: '" + ec.message() + "'");
// Load the object file
- LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
+ LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.release())));
if (!LoadedObject) {
return Error(Dyld.getErrorString());
}
@@ -148,14 +148,13 @@ static int printLineInfoForInput() {
// Resolve all the relocations we can.
Dyld.resolveRelocations();
- OwningPtr<DIContext> Context(DIContext::getDWARFContext(LoadedObject->getObjectFile()));
+ std::unique_ptr<DIContext> Context(
+ DIContext::getDWARFContext(LoadedObject->getObjectFile()));
// Use symbol info to iterate functions in the object.
- error_code ec;
for (object::symbol_iterator I = LoadedObject->begin_symbols(),
E = LoadedObject->end_symbols();
- I != E && !ec;
- I.increment(ec)) {
+ I != E; ++I) {
object::SymbolRef::Type SymType;
if (I->getType(SymType)) continue;
if (SymType == object::SymbolRef::ST_Function) {
@@ -193,14 +192,14 @@ static int executeInput() {
InputFileList.push_back("-");
for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
// Load the input memory buffer.
- OwningPtr<MemoryBuffer> InputBuffer;
- OwningPtr<ObjectImage> LoadedObject;
+ std::unique_ptr<MemoryBuffer> InputBuffer;
+ std::unique_ptr<ObjectImage> LoadedObject;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
InputBuffer))
return Error("unable to read input: '" + ec.message() + "'");
// Load the object file
- LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
+ LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.release())));
if (!LoadedObject) {
return Error(Dyld.getErrorString());
}
diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile
index 92f3132..7bbc24c 100644
--- a/tools/llvm-shlib/Makefile
+++ b/tools/llvm-shlib/Makefile
@@ -10,10 +10,12 @@
LEVEL := ../..
LIBRARYNAME = LLVM-$(LLVMVersion)
+LIBRARYALIASNAME = LLVM-$(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR)$(LLVM_VERSION_SUFFIX)
NO_BUILD_ARCHIVE := 1
LINK_LIBS_IN_SHARED := 1
SHARED_LIBRARY := 1
+SHARED_ALIAS := 1
include $(LEVEL)/Makefile.config
@@ -49,17 +51,6 @@ ifeq ($(HOST_OS),Darwin)
endif
# Include everything from the .a's into the shared library.
LLVMLibsOptions := $(LLVMLibsOptions) -all_load
- # extra options to override libtool defaults
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-dead_strip
-
- # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
- DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
- ifneq ($(DARWIN_VERS),8)
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-install_name \
- -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
- endif
endif
ifeq ($(HOST_OS), $(filter $(HOST_OS), DragonFly Linux FreeBSD GNU/kFreeBSD OpenBSD GNU Bitrig))
diff --git a/tools/llvm-size/CMakeLists.txt b/tools/llvm-size/CMakeLists.txt
index 933cc75..6034573 100644
--- a/tools/llvm-size/CMakeLists.txt
+++ b/tools/llvm-size/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS object)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_tool(llvm-size
llvm-size.cpp
diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp
index 3de6605..d1bd45a 100644
--- a/tools/llvm-size/llvm-size.cpp
+++ b/tools/llvm-size/llvm-size.cpp
@@ -85,10 +85,10 @@ static size_t getNumLengthAsString(uint64_t num) {
return result.size();
}
-/// @brief Print the size of each section in @p o.
+/// @brief Print the size of each section in @p Obj.
///
/// The format used is determined by @c OutputFormat and @c Radix.
-static void PrintObjectSectionSizes(ObjectFile *o) {
+static void PrintObjectSectionSizes(ObjectFile *Obj) {
uint64_t total = 0;
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
@@ -111,21 +111,18 @@ static void PrintObjectSectionSizes(ObjectFile *o) {
std::size_t max_name_len = strlen("section");
std::size_t max_size_len = strlen("size");
std::size_t max_addr_len = strlen("addr");
- error_code ec;
- for (section_iterator i = o->begin_sections(),
- e = o->end_sections(); i != e;
- i.increment(ec)) {
- if (error(ec))
- return;
+ for (const SectionRef &Section : Obj->sections()) {
uint64_t size = 0;
- if (error(i->getSize(size)))
+ if (error(Section.getSize(size)))
return;
total += size;
StringRef name;
uint64_t addr = 0;
- if (error(i->getName(name))) return;
- if (error(i->getAddress(addr))) return;
+ if (error(Section.getName(name)))
+ return;
+ if (error(Section.getAddress(addr)))
+ return;
max_name_len = std::max(max_name_len, name.size());
max_size_len = std::max(max_size_len, getNumLengthAsString(size));
max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
@@ -154,24 +151,19 @@ static void PrintObjectSectionSizes(ObjectFile *o) {
<< "%#" << max_addr_len << radix_fmt << "\n";
// Print each section.
- for (section_iterator i = o->begin_sections(),
- e = o->end_sections(); i != e;
- i.increment(ec)) {
- if (error(ec))
- return;
-
+ for (const SectionRef &Section : Obj->sections()) {
StringRef name;
uint64_t size = 0;
uint64_t addr = 0;
- if (error(i->getName(name))) return;
- if (error(i->getSize(size))) return;
- if (error(i->getAddress(addr))) return;
+ if (error(Section.getName(name)))
+ return;
+ if (error(Section.getSize(size)))
+ return;
+ if (error(Section.getAddress(addr)))
+ return;
std::string namestr = name;
- outs() << format(fmt.str().c_str(),
- namestr.c_str(),
- size,
- addr);
+ outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr);
}
// Print total.
@@ -189,21 +181,19 @@ static void PrintObjectSectionSizes(ObjectFile *o) {
uint64_t total_bss = 0;
// Make one pass over the section table to calculate sizes.
- error_code ec;
- for (section_iterator i = o->begin_sections(),
- e = o->end_sections(); i != e;
- i.increment(ec)) {
- if (error(ec))
- return;
-
+ for (const SectionRef &Section : Obj->sections()) {
uint64_t size = 0;
bool isText = false;
bool isData = false;
bool isBSS = false;
- if (error(i->getSize(size))) return;
- if (error(i->isText(isText))) return;
- if (error(i->isData(isData))) return;
- if (error(i->isBSS(isBSS))) return;
+ if (error(Section.getSize(size)))
+ return;
+ if (error(Section.isText(isText)))
+ return;
+ if (error(Section.isData(isData)))
+ return;
+ if (error(Section.isBSS(isBSS)))
+ return;
if (isText)
total_text += size;
else if (isData)
@@ -244,17 +234,18 @@ static void PrintFileSectionSizes(StringRef file) {
}
// Attempt to open the binary.
- OwningPtr<Binary> binary;
- if (error_code ec = createBinary(file, binary)) {
- errs() << ToolName << ": " << file << ": " << ec.message() << ".\n";
+ ErrorOr<Binary *> BinaryOrErr = createBinary(file);
+ if (error_code EC = BinaryOrErr.getError()) {
+ errs() << ToolName << ": " << file << ": " << EC.message() << ".\n";
return;
}
+ std::unique_ptr<Binary> binary(BinaryOrErr.get());
if (Archive *a = dyn_cast<Archive>(binary.get())) {
// This is an archive. Iterate over each member and display its sizes.
- for (object::Archive::child_iterator i = a->begin_children(),
- e = a->end_children(); i != e; ++i) {
- OwningPtr<Binary> child;
+ for (object::Archive::child_iterator i = a->child_begin(),
+ e = a->child_end(); i != e; ++i) {
+ std::unique_ptr<Binary> child;
if (error_code ec = i->getAsBinary(child)) {
errs() << ToolName << ": " << file << ": " << ec.message() << ".\n";
continue;
diff --git a/tools/llvm-stress/CMakeLists.txt b/tools/llvm-stress/CMakeLists.txt
index e2d07a5..106ced1 100644
--- a/tools/llvm-stress/CMakeLists.txt
+++ b/tools/llvm-stress/CMakeLists.txt
@@ -1,5 +1,10 @@
-set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo)
+set(LLVM_LINK_COMPONENTS
+ Core
+ IPA
+ Support
+ )
add_llvm_tool(llvm-stress
llvm-stress.cpp
)
+set_target_properties(llvm-stress PROPERTIES ENABLE_EXPORTS 1)
diff --git a/tools/llvm-stress/Makefile b/tools/llvm-stress/Makefile
index 8767cbe..29245af 100644
--- a/tools/llvm-stress/Makefile
+++ b/tools/llvm-stress/Makefile
@@ -12,7 +12,4 @@ TOOLNAME := llvm-stress
LINK_COMPONENTS := object
LINK_COMPONENTS := bitreader bitwriter asmparser irreader instrumentation scalaropts ipo
-# This tool has no plugins, optimize startup time.
-TOOL_NO_EXPORTS = 1
-
include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp
index fd10baf..18f1e6c 100644
--- a/tools/llvm-stress/llvm-stress.cpp
+++ b/tools/llvm-stress/llvm-stress.cpp
@@ -11,18 +11,18 @@
// different components in LLVM.
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/ADT/OwningPtr.h"
+
#include "llvm/Analysis/CallGraphSCCPass.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/Instruction.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/PassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -288,8 +288,8 @@ protected:
struct LoadModifier: public Modifier {
LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
- // Try to use predefined pointers. If non exist, use undef pointer value;
+ void Act() override {
+ // Try to use predefined pointers. If non-exist, use undef pointer value;
Value *Ptr = getRandomPointerValue();
Value *V = new LoadInst(Ptr, "L", BB->getTerminator());
PT->push_back(V);
@@ -298,8 +298,8 @@ struct LoadModifier: public Modifier {
struct StoreModifier: public Modifier {
StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
- // Try to use predefined pointers. If non exist, use undef pointer value;
+ void Act() override {
+ // Try to use predefined pointers. If non-exist, use undef pointer value;
Value *Ptr = getRandomPointerValue();
Type *Tp = Ptr->getType();
Value *Val = getRandomValue(Tp->getContainedType(0));
@@ -317,7 +317,7 @@ struct StoreModifier: public Modifier {
struct BinModifier: public Modifier {
BinModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *Val0 = getRandomVal();
Value *Val1 = getRandomValue(Val0->getType());
@@ -360,7 +360,7 @@ struct BinModifier: public Modifier {
/// Generate constant values.
struct ConstModifier: public Modifier {
ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Type *Ty = pickType();
if (Ty->isVectorTy()) {
@@ -407,7 +407,7 @@ struct ConstModifier: public Modifier {
struct AllocaModifier: public Modifier {
AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R){}
- virtual void Act() {
+ void Act() override {
Type *Tp = pickType();
PT->push_back(new AllocaInst(Tp, "A", BB->getFirstNonPHI()));
}
@@ -417,7 +417,7 @@ struct ExtractElementModifier: public Modifier {
ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R):
Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *Val0 = getRandomVectorValue();
Value *V = ExtractElementInst::Create(Val0,
ConstantInt::get(Type::getInt32Ty(BB->getContext()),
@@ -429,7 +429,7 @@ struct ExtractElementModifier: public Modifier {
struct ShuffModifier: public Modifier {
ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *Val0 = getRandomVectorValue();
Value *Val1 = getRandomValue(Val0->getType());
@@ -458,7 +458,7 @@ struct InsertElementModifier: public Modifier {
InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R):
Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *Val0 = getRandomVectorValue();
Value *Val1 = getRandomValue(Val0->getType()->getScalarType());
@@ -473,7 +473,7 @@ struct InsertElementModifier: public Modifier {
struct CastModifier: public Modifier {
CastModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *V = getRandomVal();
Type *VTy = V->getType();
@@ -560,7 +560,7 @@ struct SelectModifier: public Modifier {
SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R):
Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
// Try a bunch of different select configuration until a valid one is found.
Value *Val0 = getRandomVal();
Value *Val1 = getRandomValue(Val0->getType());
@@ -583,7 +583,7 @@ struct SelectModifier: public Modifier {
struct CmpModifier: public Modifier {
CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {}
- virtual void Act() {
+ void Act() override {
Value *Val0 = getRandomVal();
Value *Val1 = getRandomValue(Val0->getType());
@@ -625,15 +625,15 @@ static void FillFunction(Function *F, Random &R) {
// List of modifiers which add new random instructions.
std::vector<Modifier*> Modifiers;
- OwningPtr<Modifier> LM(new LoadModifier(BB, &PT, &R));
- OwningPtr<Modifier> SM(new StoreModifier(BB, &PT, &R));
- OwningPtr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R));
- OwningPtr<Modifier> SHM(new ShuffModifier(BB, &PT, &R));
- OwningPtr<Modifier> IE(new InsertElementModifier(BB, &PT, &R));
- OwningPtr<Modifier> BM(new BinModifier(BB, &PT, &R));
- OwningPtr<Modifier> CM(new CastModifier(BB, &PT, &R));
- OwningPtr<Modifier> SLM(new SelectModifier(BB, &PT, &R));
- OwningPtr<Modifier> PM(new CmpModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> LM(new LoadModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> SM(new StoreModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> SHM(new ShuffModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> IE(new InsertElementModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> BM(new BinModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> CM(new CastModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> SLM(new SelectModifier(BB, &PT, &R));
+ std::unique_ptr<Modifier> PM(new CmpModifier(BB, &PT, &R));
Modifiers.push_back(LM.get());
Modifiers.push_back(SM.get());
Modifiers.push_back(EE.get());
@@ -687,7 +687,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
llvm_shutdown_obj Y;
- OwningPtr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext()));
+ std::unique_ptr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext()));
Function *F = GenEmptyFunction(M.get());
// Pick an initial seed value
@@ -698,14 +698,14 @@ int main(int argc, char **argv) {
IntroduceControlFlow(F, R);
// Figure out what stream we are supposed to write to...
- OwningPtr<tool_output_file> Out;
+ std::unique_ptr<tool_output_file> Out;
// Default to standard output.
if (OutputFilename.empty())
OutputFilename = "-";
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- sys::fs::F_Binary));
+ sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
@@ -713,7 +713,7 @@ int main(int argc, char **argv) {
PassManager Passes;
Passes.add(createVerifierPass());
- Passes.add(createPrintModulePass(&Out->os()));
+ Passes.add(createPrintModulePass(Out->os()));
Passes.run(*M.get());
Out->keep();
diff --git a/tools/llvm-symbolizer/CMakeLists.txt b/tools/llvm-symbolizer/CMakeLists.txt
index 5967b89..9e76248 100644
--- a/tools/llvm-symbolizer/CMakeLists.txt
+++ b/tools/llvm-symbolizer/CMakeLists.txt
@@ -6,6 +6,7 @@
set(LLVM_LINK_COMPONENTS
DebugInfo
Object
+ Support
)
add_llvm_tool(llvm-symbolizer
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 320ab3f..13f2f8f 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -14,6 +14,7 @@
#include "LLVMSymbolize.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
+#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
@@ -21,7 +22,6 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-
#include <sstream>
#include <stdlib.h>
@@ -53,43 +53,51 @@ static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
: Module(Obj), DebugInfoContext(DICtx) {
- error_code ec;
- for (symbol_iterator si = Module->begin_symbols(), se = Module->end_symbols();
- si != se; si.increment(ec)) {
- if (error(ec))
- return;
- SymbolRef::Type SymbolType;
- if (error(si->getType(SymbolType)))
- continue;
- if (SymbolType != SymbolRef::ST_Function &&
- SymbolType != SymbolRef::ST_Data)
- continue;
- uint64_t SymbolAddress;
- if (error(si->getAddress(SymbolAddress)) ||
- SymbolAddress == UnknownAddressOrSize)
- continue;
- uint64_t SymbolSize;
- // Getting symbol size is linear for Mach-O files, so assume that symbol
- // occupies the memory range up to the following symbol.
- if (isa<MachOObjectFile>(Obj))
- SymbolSize = 0;
- else if (error(si->getSize(SymbolSize)) ||
- SymbolSize == UnknownAddressOrSize)
- continue;
- 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;
- SymbolDesc SD = { SymbolAddress, SymbolSize };
- M.insert(std::make_pair(SD, SymbolName));
+ for (const SymbolRef &Symbol : Module->symbols()) {
+ addSymbol(Symbol);
+ }
+ bool NoSymbolTable = (Module->symbol_begin() == Module->symbol_end());
+ if (NoSymbolTable && Module->isELF()) {
+ // Fallback to dynamic symbol table, if regular symbol table is stripped.
+ std::pair<symbol_iterator, symbol_iterator> IDyn =
+ getELFDynamicSymbolIterators(Module);
+ for (symbol_iterator si = IDyn.first, se = IDyn.second; si != se; ++si) {
+ addSymbol(*si);
+ }
}
}
+void ModuleInfo::addSymbol(const SymbolRef &Symbol) {
+ SymbolRef::Type SymbolType;
+ if (error(Symbol.getType(SymbolType)))
+ return;
+ if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
+ return;
+ uint64_t SymbolAddress;
+ if (error(Symbol.getAddress(SymbolAddress)) ||
+ SymbolAddress == UnknownAddressOrSize)
+ return;
+ uint64_t SymbolSize;
+ // Getting symbol size is linear for Mach-O files, so assume that symbol
+ // occupies the memory range up to the following symbol.
+ if (isa<MachOObjectFile>(Module))
+ SymbolSize = 0;
+ else if (error(Symbol.getSize(SymbolSize)) ||
+ SymbolSize == UnknownAddressOrSize)
+ return;
+ StringRef SymbolName;
+ if (error(Symbol.getName(SymbolName)))
+ return;
+ // 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;
+ SymbolDesc SD = { SymbolAddress, SymbolSize };
+ M.insert(std::make_pair(SD, SymbolName));
+}
+
bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const {
@@ -196,7 +204,7 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
if (Opts.UseSymbolTable) {
if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
- Name = DemangleGlobalName(Name);
+ Name = DemangleName(Name);
}
}
std::stringstream ss;
@@ -221,7 +229,7 @@ static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
}
static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
- OwningPtr<MemoryBuffer> MB;
+ std::unique_ptr<MemoryBuffer> MB;
if (MemoryBuffer::getFileOrSTDIN(Path, MB))
return false;
return !zlib::isAvailable() || CRCHash == zlib::crc32(MB->getBuffer());
@@ -269,15 +277,13 @@ static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName,
const ObjectFile *Obj = dyn_cast<ObjectFile>(Bin);
if (!Obj)
return false;
- error_code EC;
- for (section_iterator I = Obj->begin_sections(), E = Obj->end_sections();
- I != E; I.increment(EC)) {
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- I->getName(Name);
+ Section.getName(Name);
Name = Name.substr(Name.find_first_not_of("._"));
if (Name == "gnu_debuglink") {
StringRef Data;
- I->getContents(Data);
+ Section.getContents(Data);
DataExtractor DE(Data, Obj->isLittleEndian(), 0);
uint32_t Offset = 0;
if (const char *DebugNameStr = DE.getCStr(&Offset)) {
@@ -302,22 +308,21 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
return I->second;
Binary *Bin = 0;
Binary *DbgBin = 0;
- OwningPtr<Binary> ParsedBinary;
- OwningPtr<Binary> ParsedDbgBinary;
- if (!error(createBinary(Path, ParsedBinary))) {
+ ErrorOr<Binary *> BinaryOrErr = createBinary(Path);
+ if (!error(BinaryOrErr.getError())) {
+ std::unique_ptr<Binary> ParsedBinary(BinaryOrErr.get());
// Check if it's a universal binary.
- Bin = ParsedBinary.take();
+ Bin = ParsedBinary.release();
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();
+ BinaryOrErr = createBinary(ResourcePath);
+ error_code EC = BinaryOrErr.getError();
+ if (EC != errc::no_such_file_or_directory && !error(EC)) {
+ DbgBin = BinaryOrErr.get();
ParsedBinariesAndObjects.push_back(DbgBin);
}
}
@@ -327,10 +332,12 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
uint32_t CRCHash;
std::string DebugBinaryPath;
if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) &&
- findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath) &&
- !error(createBinary(DebugBinaryPath, ParsedDbgBinary))) {
- DbgBin = ParsedDbgBinary.take();
- ParsedBinariesAndObjects.push_back(DbgBin);
+ findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
+ BinaryOrErr = createBinary(DebugBinaryPath);
+ if (!error(BinaryOrErr.getError())) {
+ DbgBin = BinaryOrErr.get();
+ ParsedBinariesAndObjects.push_back(DbgBin);
+ }
}
}
}
@@ -351,9 +358,9 @@ LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName
std::make_pair(UB, ArchName));
if (I != ObjectFileForArch.end())
return I->second;
- OwningPtr<ObjectFile> ParsedObj;
+ std::unique_ptr<ObjectFile> ParsedObj;
if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
- Res = ParsedObj.take();
+ Res = ParsedObj.release();
ParsedBinariesAndObjects.push_back(Res);
}
ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
@@ -424,6 +431,10 @@ extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
#if !defined(_MSC_VER)
+ // We can spoil names of symbols with C linkage, so use an heuristic
+ // approach to check if the name should be demangled.
+ if (Name.substr(0, 2) != "_Z")
+ return Name;
int status = 0;
char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
if (status != 0)
@@ -436,11 +447,5 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
#endif
}
-std::string LLVMSymbolizer::DemangleGlobalName(const std::string &Name) {
- // We can spoil names of globals with C linkage, so use an heuristic
- // approach to check if the name should be demangled.
- return (Name.substr(0, 2) == "_Z") ? DemangleName(Name) : Name;
-}
-
} // namespace symbolize
} // namespace llvm
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h
index eb2666a..288be80 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -13,7 +13,6 @@
#ifndef LLVM_SYMBOLIZE_H
#define LLVM_SYMBOLIZE_H
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Object/MachOUniversal.h"
@@ -71,7 +70,6 @@ private:
ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);
std::string printDILineInfo(DILineInfo LineInfo) const;
- static std::string DemangleGlobalName(const std::string &Name);
// Owns all the parsed binaries and object files.
SmallVector<Binary*, 4> ParsedBinariesAndObjects;
@@ -103,8 +101,9 @@ private:
bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const;
+ void addSymbol(const SymbolRef &Symbol);
ObjectFile *Module;
- OwningPtr<DIContext> DebugInfoContext;
+ std::unique_ptr<DIContext> DebugInfoContext;
struct SymbolDesc {
uint64_t Addr;
diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp
index c32e949..83f5c5e 100644
--- a/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -51,6 +51,11 @@ static cl::opt<std::string> ClDefaultArch("default-arch", cl::init(""),
cl::desc("Default architecture "
"(for multi-arch objects)"));
+static cl::opt<std::string>
+ClBinaryName("obj", cl::init(""),
+ cl::desc("Path to object file to be symbolized (if not provided, "
+ "object file should be specified for each input line)"));
+
static bool parseCommand(bool &IsData, std::string &ModuleName,
uint64_t &ModuleOffset) {
const char *kDataCmd = "DATA ";
@@ -62,7 +67,6 @@ static bool parseCommand(bool &IsData, std::string &ModuleName,
return false;
IsData = false;
ModuleName = "";
- std::string ModuleOffsetStr = "";
char *pos = InputString;
if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
IsData = true;
@@ -74,26 +78,29 @@ static bool parseCommand(bool &IsData, std::string &ModuleName,
// If no cmd, assume it's CODE.
IsData = false;
}
- // Skip delimiters and parse input filename.
- pos += strspn(pos, kDelimiters);
- if (*pos == '"' || *pos == '\'') {
- char quote = *pos;
- pos++;
- char *end = strchr(pos, quote);
- if (end == 0)
- return false;
- ModuleName = std::string(pos, end - pos);
- pos = end + 1;
+ // Skip delimiters and parse input filename (if needed).
+ if (ClBinaryName == "") {
+ pos += strspn(pos, kDelimiters);
+ if (*pos == '"' || *pos == '\'') {
+ char quote = *pos;
+ pos++;
+ char *end = strchr(pos, quote);
+ if (end == 0)
+ return false;
+ ModuleName = std::string(pos, end - pos);
+ pos = end + 1;
+ } else {
+ int name_length = strcspn(pos, kDelimiters);
+ ModuleName = std::string(pos, name_length);
+ pos += name_length;
+ }
} else {
- int name_length = strcspn(pos, kDelimiters);
- ModuleName = std::string(pos, name_length);
- pos += name_length;
+ ModuleName = ClBinaryName;
}
// Skip delimiters and parse module offset.
pos += strspn(pos, kDelimiters);
int offset_length = strcspn(pos, kDelimiters);
- ModuleOffsetStr = std::string(pos, offset_length);
- if (StringRef(ModuleOffsetStr).getAsInteger(0, ModuleOffset))
+ if (StringRef(pos, offset_length).getAsInteger(0, ModuleOffset))
return false;
return true;
}
@@ -104,7 +111,7 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n");
+ cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n");
LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
ClPrintInlining, ClDemangle, ClDefaultArch);
LLVMSymbolizer Symbolizer(Opts);
diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt
index 957a9f0..542053b 100644
--- a/tools/lto/CMakeLists.txt
+++ b/tools/lto/CMakeLists.txt
@@ -1,6 +1,11 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
- ipo scalaropts linker bitreader bitwriter lto mcdisassembler vectorize)
+ Core
+ LTO
+ MC
+ MCDisassembler
+ Support
+ )
add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" )
@@ -9,43 +14,13 @@ set(SOURCES
lto.cpp
)
-if( NOT CYGWIN AND LLVM_ENABLE_PIC )
- if ( WIN32 )
- # Create .def file containing a list of exports preceeded by
- # 'EXPORTS'. The file "lto.exports" already contains the list, so we
- # massage it into the correct format here to create "lto.exports.def".
- set(LTO_EXPORTS_DEF ${CMAKE_CURRENT_BINARY_DIR}/lto.exports.def)
- set(LTO_EXPORTS_DEF_TEMP ${LTO_EXPORTS_DEF}.txt)
- file(READ "lto.exports" exports_list)
- file(WRITE ${LTO_EXPORTS_DEF_TEMP} "LIBRARY LTO\n")
- file(APPEND ${LTO_EXPORTS_DEF_TEMP} "EXPORTS\n")
- file(APPEND ${LTO_EXPORTS_DEF_TEMP} ${exports_list})
-
- # Copy the file only if it has changed.
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
- ${LTO_EXPORTS_DEF_TEMP} ${LTO_EXPORTS_DEF})
-
- set(SHARED_LIB_SOURCES ${SOURCES} ${LTO_EXPORTS_DEF})
- else()
- set(SHARED_LIB_SOURCES ${SOURCES})
- endif()
+set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/lto.exports)
- set(bsl ${BUILD_SHARED_LIBS})
- set(BUILD_SHARED_LIBS ON)
- add_llvm_library(LTO ${SHARED_LIB_SOURCES})
- set_property(TARGET LTO PROPERTY OUTPUT_NAME "LTO")
- set(BUILD_SHARED_LIBS ${bsl})
- set(LTO_STATIC_TARGET_NAME LTO_static)
-else()
- set(LTO_STATIC_TARGET_NAME LTO)
+if(NOT CYGWIN AND LLVM_ENABLE_PIC)
+ set(ENABLE_SHARED SHARED)
endif()
-if( NOT BUILD_SHARED_LIBS )
- add_llvm_library(${LTO_STATIC_TARGET_NAME} ${SOURCES})
- set_property(TARGET ${LTO_STATIC_TARGET_NAME} PROPERTY OUTPUT_NAME "LTO")
-endif()
+add_llvm_library(LTO ${ENABLE_SHARED} STATIC ${SOURCES})
-if( NOT CYGWIN )
- install(FILES ${LLVM_MAIN_INCLUDE_DIR}/llvm-c/lto.h
- DESTINATION include/llvm-c)
-endif()
+install(FILES ${LLVM_MAIN_INCLUDE_DIR}/llvm-c/lto.h
+ DESTINATION include/llvm-c)
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index cedbee1..a4fe9ac 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -9,8 +9,7 @@
LEVEL := ../..
LIBRARYNAME := LTO
-LINK_COMPONENTS := all-targets ipo scalaropts linker bitreader bitwriter \
- lto mcdisassembler vectorize
+LINK_COMPONENTS := all-targets core lto mc mcdisassembler support
LINK_LIBS_IN_SHARED := 1
SHARED_LIBRARY := 1
@@ -37,17 +36,6 @@ ifeq ($(HOST_OS),Darwin)
-Wl,$(LTO_LIBRARY_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
-Wl,-compatibility_version -Wl,1
endif
- # extra options to override libtool defaults
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-dead_strip
-
- # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
- DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
- ifneq ($(DARWIN_VERS),8)
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-install_name \
- -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
- endif
# If we're doing an Apple-style build, add the LTO object path.
ifeq ($(RC_XBS),YES)
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
index 7bfddcd..cc8318a 100644
--- a/tools/lto/lto.cpp
+++ b/tools/lto/lto.cpp
@@ -13,11 +13,11 @@
//===----------------------------------------------------------------------===//
#include "llvm-c/lto.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Target.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/LTO/LTOCodeGenerator.h"
#include "llvm/LTO/LTOModule.h"
-#include "llvm-c/Core.h"
-#include "llvm-c/Target.h"
// extra command-line flags needed for LTOCodeGenerator
static cl::opt<bool>
@@ -56,28 +56,6 @@ static void lto_initialize() {
}
}
-static void lto_set_target_options(llvm::TargetOptions &Options) {
- Options.LessPreciseFPMADOption = EnableFPMAD;
- Options.NoFramePointerElim = DisableFPElim;
- Options.AllowFPOpFusion = FuseFPOps;
- Options.UnsafeFPMath = EnableUnsafeFPMath;
- Options.NoInfsFPMath = EnableNoInfsFPMath;
- Options.NoNaNsFPMath = EnableNoNaNsFPMath;
- Options.HonorSignDependentRoundingFPMathOption =
- EnableHonorSignDependentRoundingFPMath;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
- if (FloatABIForCalls != llvm::FloatABI::Default)
- Options.FloatABIType = FloatABIForCalls;
- Options.NoZerosInBSS = DontPlaceZerosInBSS;
- Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
- Options.DisableTailCalls = DisableTailCalls;
- Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.TrapFuncName = TrapFuncName;
- Options.PositionIndependentExecutable = EnablePIE;
- Options.EnableSegmentedStacks = SegmentedStacks;
- Options.UseInitArray = UseInitArray;
-}
-
/// lto_get_version - Returns a printable string.
extern const char* lto_get_version() {
return LTOCodeGenerator::getVersionString();
@@ -120,8 +98,7 @@ lto_module_is_object_file_in_memory_for_target(const void* mem,
/// (check lto_get_error_message() for details).
lto_module_t lto_module_create(const char* path) {
lto_initialize();
- llvm::TargetOptions Options;
- lto_set_target_options(Options);
+ llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return LTOModule::makeLTOModule(path, Options, sLastErrorString);
}
@@ -129,8 +106,7 @@ lto_module_t lto_module_create(const char* path) {
/// error (check lto_get_error_message() for details).
lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
lto_initialize();
- llvm::TargetOptions Options;
- lto_set_target_options(Options);
+ llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return LTOModule::makeLTOModule(fd, path, size, Options, sLastErrorString);
}
@@ -141,8 +117,7 @@ lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
size_t map_size,
off_t offset) {
lto_initialize();
- llvm::TargetOptions Options;
- lto_set_target_options(Options);
+ llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return LTOModule::makeLTOModule(fd, path, map_size, offset, Options,
sLastErrorString);
}
@@ -151,11 +126,20 @@ lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
/// NULL on error (check lto_get_error_message() for details).
lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
lto_initialize();
- llvm::TargetOptions Options;
- lto_set_target_options(Options);
+ llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return LTOModule::makeLTOModule(mem, length, Options, sLastErrorString);
}
+/// Loads an object file from memory with an extra path argument.
+/// Returns NULL on error (check lto_get_error_message() for details).
+lto_module_t lto_module_create_from_memory_with_path(const void* mem,
+ size_t length,
+ const char *path) {
+ lto_initialize();
+ llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+ return LTOModule::makeLTOModule(mem, length, Options, sLastErrorString, path);
+}
+
/// lto_module_dispose - Frees all memory for a module. Upon return the
/// lto_module_t is no longer valid.
void lto_module_dispose(lto_module_t mod) {
@@ -193,13 +177,41 @@ lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
return mod->getSymbolAttributes(index);
}
+/// lto_module_get_num_deplibs - Returns the number of dependent libraries in
+/// the object module.
+unsigned int lto_module_get_num_deplibs(lto_module_t mod) {
+ return mod->getDependentLibraryCount();
+}
+
+/// lto_module_get_deplib - Returns the ith dependent library in the module.
+const char* lto_module_get_deplib(lto_module_t mod, unsigned int index) {
+ return mod->getDependentLibrary(index);
+}
+
+/// lto_module_get_num_linkeropts - Returns the number of linker options in the
+/// object module.
+unsigned int lto_module_get_num_linkeropts(lto_module_t mod) {
+ return mod->getLinkerOptCount();
+}
+
+/// lto_module_get_linkeropt - Returns the ith linker option in the module.
+const char* lto_module_get_linkeropt(lto_module_t mod, unsigned int index) {
+ return mod->getLinkerOpt(index);
+}
+
+/// Set a diagnostic handler.
+void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
+ lto_diagnostic_handler_t diag_handler,
+ void *ctxt) {
+ cg->setDiagnosticHandler(diag_handler, ctxt);
+}
+
/// lto_codegen_create - Instantiates a code generator. Returns NULL if there
/// is an error.
lto_code_gen_t lto_codegen_create(void) {
lto_initialize();
- TargetOptions Options;
- lto_set_target_options(Options);
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
LTOCodeGenerator *CodeGen = new LTOCodeGenerator();
if (CodeGen)
diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports
index 46d0d74..b10ab1a 100644
--- a/tools/lto/lto.exports
+++ b/tools/lto/lto.exports
@@ -5,6 +5,11 @@ lto_module_create
lto_module_create_from_fd
lto_module_create_from_fd_at_offset
lto_module_create_from_memory
+lto_module_create_from_memory_with_path
+lto_module_get_deplib
+lto_module_get_linkeropt
+lto_module_get_num_deplibs
+lto_module_get_num_linkeropts
lto_module_get_num_symbols
lto_module_get_symbol_attribute
lto_module_get_symbol_name
@@ -15,6 +20,7 @@ lto_module_is_object_file_for_target
lto_module_is_object_file_in_memory
lto_module_is_object_file_in_memory_for_target
lto_module_dispose
+lto_codegen_set_diagnostic_handler
lto_codegen_add_module
lto_codegen_add_must_preserve_symbol
lto_codegen_compile
diff --git a/tools/macho-dump/CMakeLists.txt b/tools/macho-dump/CMakeLists.txt
index d55e1d5..bc2dfbf 100644
--- a/tools/macho-dump/CMakeLists.txt
+++ b/tools/macho-dump/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support object)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_tool(macho-dump
macho-dump.cpp
diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp
index 0dfbd5f..886487b 100644
--- a/tools/macho-dump/macho-dump.cpp
+++ b/tools/macho-dump/macho-dump.cpp
@@ -96,9 +96,9 @@ static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index,
// Dump the relocation entries.
outs() << " ('_relocations', [\n";
unsigned RelNum = 0;
- error_code EC;
for (relocation_iterator I = Obj.section_rel_begin(Index),
- E = Obj.section_rel_end(Index); I != E; I.increment(EC), ++RelNum) {
+ E = Obj.section_rel_end(Index);
+ I != E; ++I, ++RelNum) {
MachO::any_relocation_info RE = Obj.getRelocation(I->getRawDataRefImpl());
outs() << " # Relocation " << RelNum << "\n";
outs() << " (('word-0', " << format("0x%x", RE.r_word0) << "),\n";
@@ -201,11 +201,9 @@ static int DumpSymtabCommand(const MachOObjectFile &Obj) {
// Dump the symbol table.
outs() << " ('_symbols', [\n";
- error_code EC;
unsigned SymNum = 0;
- for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
- I.increment(EC), ++SymNum) {
- DataRefImpl DRI = I->getRawDataRefImpl();
+ for (const SymbolRef &Symbol : Obj.symbols()) {
+ DataRefImpl DRI = Symbol.getRawDataRefImpl();
if (Obj.is64Bit()) {
MachO::nlist_64 STE = Obj.getSymbol64TableEntry(DRI);
DumpSymbolTableEntryData(Obj, SymNum, STE.n_strx, STE.n_type,
@@ -217,6 +215,7 @@ static int DumpSymtabCommand(const MachOObjectFile &Obj) {
STE.n_sect, STE.n_desc, STE.n_value,
StringTable);
}
+ SymNum++;
}
outs() << " ])\n";
@@ -320,6 +319,15 @@ DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
return 0;
}
+static int
+DumpVersionMin(const MachOObjectFile &Obj,
+ const MachOObjectFile::LoadCommandInfo &LCI) {
+ MachO::version_min_command VMLC = Obj.getVersionMinLoadCommand(LCI);
+ outs() << " ('version, " << VMLC.version << ")\n"
+ << " ('reserved, " << VMLC.reserved << ")\n";
+ return 0;
+}
+
static int DumpLoadCommand(const MachOObjectFile &Obj,
MachOObjectFile::LoadCommandInfo &LCI) {
switch (LCI.C.cmd) {
@@ -339,6 +347,9 @@ static int DumpLoadCommand(const MachOObjectFile &Obj,
return DumpDataInCodeDataCommand(Obj, LCI);
case MachO::LC_LINKER_OPTIONS:
return DumpLinkerOptionsCommand(Obj, LCI);
+ case MachO::LC_VERSION_MIN_IPHONEOS:
+ case MachO::LC_VERSION_MIN_MACOSX:
+ return DumpVersionMin(Obj, LCI);
default:
Warning("unknown load command: " + Twine(LCI.C.cmd));
return 0;
@@ -379,9 +390,10 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
- OwningPtr<Binary> Binary;
- if (error_code EC = createBinary(InputFile, Binary))
+ ErrorOr<Binary *> BinaryOrErr = createBinary(InputFile);
+ if (error_code EC = BinaryOrErr.getError())
return Error("unable to read input: '" + EC.message() + "'");
+ std::unique_ptr<Binary> Binary(BinaryOrErr.get());
const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(Binary.get());
if (!InputObject)
diff --git a/tools/msbuild/CMakeLists.txt b/tools/msbuild/CMakeLists.txt
index 08b8aee..b7be71d 100644
--- a/tools/msbuild/CMakeLists.txt
+++ b/tools/msbuild/CMakeLists.txt
@@ -1,41 +1,57 @@
if (WIN32)
- set(prop_file_in "Microsoft.Cpp.Win32.llvm.props.in")
- set(prop_file_v100 "Microsoft.Cpp.Win32.LLVM-vs2010.props")
- set(prop_file_v110 "Microsoft.Cpp.Win32.LLVM-vs2012.props")
- set(prop_file_v110_xp "Microsoft.Cpp.Win32.LLVM-vs2012_xp.props")
- set(prop_file_v120 "toolset-vs2013.props")
- set(prop_file_v120_xp "toolset-vs2013_xp.props")
-
# CPack will install a registry key in this format that we wish to reference.
set(REG_KEY "${CPACK_PACKAGE_INSTALL_REGISTRY_KEY}")
+ set(LIB_PATH_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
+
+ foreach (platform "Win32" "x64")
+ set(prop_file_in "Microsoft.Cpp.Win32.llvm.props.in")
+ set(prop_file_v100 "Microsoft.Cpp.${platform}.LLVM-vs2010.props")
+ set(prop_file_v110 "Microsoft.Cpp.${platform}.LLVM-vs2012.props")
+ set(prop_file_v110_xp "Microsoft.Cpp.${platform}.LLVM-vs2012_xp.props")
+ set(prop_file_v120 "toolset-vs2013.props")
+ set(prop_file_v120_xp "toolset-vs2013_xp.props")
+
+ if (platform STREQUAL "Win32")
+ set(mflag "m32")
+ else()
+ set(mflag "m64")
+ endif()
+ set(VS_VERSION "v100")
+ set(MSC_VERSION "1600")
+ configure_file(${prop_file_in} ${platform}/${prop_file_v100})
+ set(VS_VERSION "v110")
+ set(MSC_VERSION "1700")
+ configure_file(${prop_file_in} ${platform}/${prop_file_v110})
+ set(VS_VERSION "v110_xp")
+ configure_file(${prop_file_in} ${platform}/${prop_file_v110_xp})
+ set(VS_VERSION "v120")
+ set(MSC_VERSION "1800")
+ configure_file(${prop_file_in} ${platform}/${prop_file_v120})
+ set(VS_VERSION "v120_xp")
+ configure_file(${prop_file_in} ${platform}/${prop_file_v120_xp})
+ set(VS_VERSION)
+ set(MSC_VERSION)
+ set(mflag)
+
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v100}" DESTINATION tools/msbuild/${platform})
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v110}" DESTINATION tools/msbuild/${platform})
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v110_xp}" DESTINATION tools/msbuild/${platform})
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v120}" DESTINATION tools/msbuild/${platform})
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v120_xp}" DESTINATION tools/msbuild/${platform})
- set(VS_VERSION "v100")
- set(MSC_VERSION "1600")
- configure_file(${prop_file_in} ${prop_file_v100})
- set(VS_VERSION "v110")
- set(MSC_VERSION "1700")
- configure_file(${prop_file_in} ${prop_file_v110})
- set(VS_VERSION "v110_xp")
- configure_file(${prop_file_in} ${prop_file_v110_xp})
- set(VS_VERSION "v120")
- set(MSC_VERSION "1800")
- configure_file(${prop_file_in} ${prop_file_v120})
- set(VS_VERSION "v120_xp")
- configure_file(${prop_file_in} ${prop_file_v120_xp})
+ install(FILES "Microsoft.Cpp.Win32.LLVM-vs2010.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2010.targets")
+ install(FILES "Microsoft.Cpp.Win32.LLVM-vs2012.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2012.targets")
+ install(FILES "Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2012_xp.targets")
+ install(FILES "toolset-vs2013.targets" DESTINATION "tools/msbuild/${platform}")
+ install(FILES "toolset-vs2013_xp.targets" DESTINATION "tools/msbuild/${platform}")
+ endforeach()
+ set(LIB_PATH_VERSION)
set(REG_KEY)
- set(VS_VERSION)
- set(MSC_VERSION)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${prop_file_v100}" DESTINATION tools/msbuild)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${prop_file_v110}" DESTINATION tools/msbuild)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${prop_file_v110_xp}" DESTINATION tools/msbuild)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${prop_file_v120}" DESTINATION tools/msbuild)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${prop_file_v120_xp}" DESTINATION tools/msbuild)
install(DIRECTORY .
DESTINATION tools/msbuild
FILES_MATCHING
- PATTERN "*.targets"
PATTERN "*.bat"
PATTERN ".svn" EXCLUDE
)
diff --git a/tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in b/tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in
index a6ef4ea..a775c31 100644
--- a/tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in
+++ b/tools/msbuild/Microsoft.Cpp.Win32.llvm.props.in
@@ -6,13 +6,13 @@
<LLVMInstallDir>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\LLVM\@REG_KEY@)</LLVMInstallDir>
<LLVMInstallDir Condition="'$(LLVMInstallDir)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\@REG_KEY@)</LLVMInstallDir>
<ExecutablePath>$(LLVMInstallDir)\msbuild-bin;$(ExecutablePath)</ExecutablePath>
- <LibraryPath>$(LLVMInstallDir)\lib\clang\3.4\lib\windows;$(LibraryPath)</LibraryPath>
+ <LibraryPath>$(LLVMInstallDir)\lib\clang\@LIB_PATH_VERSION@\lib\windows;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<!-- Set the value of _MSC_VER to claim for compatibility -->
- <AdditionalOptions>-fmsc-version=@MSC_VERSION@ %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>-@mflag@ -fmsc-version=@MSC_VERSION@ %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
diff --git a/tools/msbuild/install.bat b/tools/msbuild/install.bat
index c4c61ac..9880fb2 100644
--- a/tools/msbuild/install.bat
+++ b/tools/msbuild/install.bat
@@ -6,24 +6,31 @@ set SUCCESS=0
REM Change to the directory of this batch file.
cd /d %~dp0
+set PLATFORM=None
+:START
+IF %PLATFORM% == x64 GOTO LOOPEND
+IF %PLATFORM% == Win32 SET PLATFORM=x64
+IF %PLATFORM% == None SET PLATFORM=Win32
+
REM Search for the MSBuild toolsets directory.
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V100
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V100
:TRY_V110
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V110
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V110
:TRY_V120
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V120
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D% GOTO FOUND_V120
+:LOOPEND
IF %SUCCESS% == 1 goto DONE
echo Failed to find MSBuild toolsets directory.
goto FAILED
@@ -32,9 +39,9 @@ goto FAILED
:FOUND_V100
IF NOT EXIST %D%\LLVM-vs2010 mkdir %D%\LLVM-vs2010
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2010.props %D%\LLVM-vs2010
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.props %D%\LLVM-vs2010
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2010.targets %D%\LLVM-vs2010
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.targets %D%\LLVM-vs2010
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
set SUCCESS=1
GOTO TRY_V110
@@ -42,15 +49,15 @@ GOTO TRY_V110
:FOUND_V110
IF NOT EXIST %D%\LLVM-vs2012 mkdir %D%\LLVM-vs2012
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2012.props %D%\LLVM-vs2012
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.props %D%\LLVM-vs2012
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2012.targets %D%\LLVM-vs2012
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.targets %D%\LLVM-vs2012
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
IF NOT EXIST %D%\LLVM-vs2012_xp mkdir %D%\LLVM-vs2012_xp
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2012_xp.props %D%\LLVM-vs2012_xp
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.props %D%\LLVM-vs2012_xp
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets %D%\LLVM-vs2012_xp
+copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.targets %D%\LLVM-vs2012_xp
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
set SUCCESS=1
GOTO TRY_V120
@@ -58,16 +65,19 @@ GOTO TRY_V120
:FOUND_V120
IF NOT EXIST %D%\LLVM-vs2013 mkdir %D%\LLVM-vs2013
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy toolset-vs2013.props %D%\LLVM-vs2013\toolset.props
+copy %PLATFORM%\toolset-vs2013.props %D%\LLVM-vs2013\toolset.props
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy toolset-vs2013.targets %D%\LLVM-vs2013\toolset.targets
+copy %PLATFORM%\toolset-vs2013.targets %D%\LLVM-vs2013\toolset.targets
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
IF NOT EXIST %D%\LLVM-vs2013_xp mkdir %D%\LLVM-vs2013_xp
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy toolset-vs2013_xp.props %D%\LLVM-vs2013_xp\toolset.props
+copy %PLATFORM%\toolset-vs2013_xp.props %D%\LLVM-vs2013_xp\toolset.props
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
-copy toolset-vs2013_xp.targets %D%\LLVM-vs2013_xp\toolset.targets
+copy %PLATFORM%\toolset-vs2013_xp.targets %D%\LLVM-vs2013_xp\toolset.targets
IF NOT %ERRORLEVEL% == 0 GOTO FAILED
+set SUCCESS=1
+GOTO START
+
:DONE
echo Done!
diff --git a/tools/msbuild/uninstall.bat b/tools/msbuild/uninstall.bat
index 7e94f87..b0bc943 100644
--- a/tools/msbuild/uninstall.bat
+++ b/tools/msbuild/uninstall.bat
@@ -5,41 +5,45 @@ echo Uninstalling MSVC integration...
REM CD to the directory of this batch file.
cd /d %~dp0
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets"
-IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.Win32.LLVM-vs2010.props
-IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.Win32.LLVM-vs2010.targets
-IF EXIST %D%\LLVM-vs2010 rmdir %D%\LLVM-vs2010
+set PLATFORM=None
+:START
+IF %PLATFORM% == x64 GOTO END
+IF %PLATFORM% == Win32 SET PLATFORM=x64
+IF %PLATFORM% == None SET PLATFORM=Win32
+
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets"
-IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.Win32.LLVM-vs2010.props
-IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.Win32.LLVM-vs2010.targets
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets"
+IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.props
+IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.targets
+IF EXIST %D%\LLVM-vs2010 rmdir %D%\LLVM-vs2010
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets"
+IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.props
+IF EXIST %D%\LLVM-vs2010 del %D%\LLVM-vs2010\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.targets
IF EXIST %D%\LLVM-vs2010 rmdir %D%\LLVM-vs2010
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\Win32\PlatformToolsets"
-IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.Win32.LLVM-vs2012.props
-IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.Win32.LLVM-vs2012.targets
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\%PLATFORM%\PlatformToolsets"
+IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.props
+IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.targets
IF EXIST %D%\LLVM-vs2012 rmdir %D%\LLVM-vs2012
-IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.Win32.LLVM-vs2012_xp.props
-IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets
+IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.props
+IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.targets
IF EXIST %D%\LLVM-vs2012_xp rmdir %D%\LLVM-vs2012_xp
-
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\Win32\PlatformToolsets"
-IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.Win32.LLVM-vs2012.props
-IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.Win32.LLVM-vs2012.targets
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\%PLATFORM%\PlatformToolsets"
+IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.props
+IF EXIST %D%\LLVM-vs2012 del %D%\LLVM-vs2012\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.targets
IF EXIST %D%\LLVM-vs2012 rmdir %D%\LLVM-vs2012
-IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.Win32.LLVM-vs2012_xp.props
-IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets
+IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.props
+IF EXIST %D%\LLVM-vs2012_xp del %D%\LLVM-vs2012_xp\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012_xp.targets
IF EXIST %D%\LLVM-vs2012_xp rmdir %D%\LLVM-vs2012_xp
-SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D%\LLVM-vs2013 del %D%\LLVM-vs2013\toolset.props
IF EXIST %D%\LLVM-vs2013 del %D%\LLVM-vs2013\toolset.targets
IF EXIST %D%\LLVM-vs2013 rmdir %D%\LLVM-vs2013
IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.props
IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.targets
IF EXIST %D%\LLVM-vs2013_xp rmdir %D%\LLVM-vs2013_xp
-
-SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\PlatformToolsets"
+SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\%PLATFORM%\PlatformToolsets"
IF EXIST %D%\LLVM-vs2013 del %D%\LLVM-vs2013\toolset.props
IF EXIST %D%\LLVM-vs2013 del %D%\LLVM-vs2013\toolset.targets
IF EXIST %D%\LLVM-vs2013 rmdir %D%\LLVM-vs2013
@@ -47,4 +51,8 @@ IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.props
IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.targets
IF EXIST %D%\LLVM-vs2013_xp rmdir %D%\LLVM-vs2013_xp
+
+GOTO START
+
+:END
echo Done!
diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt
index 6b39193..9c10c04 100644
--- a/tools/obj2yaml/CMakeLists.txt
+++ b/tools/obj2yaml/CMakeLists.txt
@@ -1,7 +1,8 @@
-set(LLVM_LINK_COMPONENTS object)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_utility(obj2yaml
obj2yaml.cpp coff2yaml.cpp
)
-
-target_link_libraries(obj2yaml LLVMSupport)
diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp
index 02d7ebf..ef70922 100644
--- a/tools/obj2yaml/coff2yaml.cpp
+++ b/tools/obj2yaml/coff2yaml.cpp
@@ -51,11 +51,8 @@ void COFFDumper::dumpHeader(const object::coff_file_header *Header) {
void COFFDumper::dumpSections(unsigned NumSections) {
std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections;
- error_code ec;
- for (object::section_iterator iter = Obj.begin_sections();
- iter != Obj.end_sections(); iter.increment(ec)) {
- check(ec);
- const object::coff_section *Sect = Obj.getCOFFSection(iter);
+ for (const auto &Section : Obj.sections()) {
+ const object::coff_section *Sect = Obj.getCOFFSection(Section);
COFFYAML::Section Sec;
Sec.Name = Sect->Name; // FIXME: check the null termination!
uint32_t Characteristics = Sect->Characteristics;
@@ -67,11 +64,10 @@ void COFFDumper::dumpSections(unsigned NumSections) {
Sec.SectionData = object::yaml::BinaryRef(sectionData);
std::vector<COFFYAML::Relocation> Relocations;
- for (object::relocation_iterator rIter = iter->begin_relocations();
- rIter != iter->end_relocations(); rIter.increment(ec)) {
- const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter);
+ for (const auto &Reloc : Section.relocations()) {
+ const object::coff_relocation *reloc = Obj.getCOFFRelocation(Reloc);
COFFYAML::Relocation Rel;
- object::symbol_iterator Sym = rIter->getSymbol();
+ object::symbol_iterator Sym = Reloc.getSymbol();
Sym->getName(Rel.SymbolName);
Rel.VirtualAddress = reloc->VirtualAddress;
Rel.Type = reloc->Type;
@@ -82,13 +78,65 @@ void COFFDumper::dumpSections(unsigned NumSections) {
}
}
+static void
+dumpFunctionDefinition(COFFYAML::Symbol *Sym,
+ const object::coff_aux_function_definition *ObjFD) {
+ COFF::AuxiliaryFunctionDefinition YAMLFD;
+ YAMLFD.TagIndex = ObjFD->TagIndex;
+ YAMLFD.TotalSize = ObjFD->TotalSize;
+ YAMLFD.PointerToLinenumber = ObjFD->PointerToLinenumber;
+ YAMLFD.PointerToNextFunction = ObjFD->PointerToNextFunction;
+
+ Sym->FunctionDefinition = YAMLFD;
+}
+
+static void
+dumpbfAndEfLineInfo(COFFYAML::Symbol *Sym,
+ const object::coff_aux_bf_and_ef_symbol *ObjBES) {
+ COFF::AuxiliarybfAndefSymbol YAMLAAS;
+ YAMLAAS.Linenumber = ObjBES->Linenumber;
+ YAMLAAS.PointerToNextFunction = ObjBES->PointerToNextFunction;
+
+ Sym->bfAndefSymbol = YAMLAAS;
+}
+
+static void dumpWeakExternal(COFFYAML::Symbol *Sym,
+ const object::coff_aux_weak_external *ObjWE) {
+ COFF::AuxiliaryWeakExternal YAMLWE;
+ YAMLWE.TagIndex = ObjWE->TagIndex;
+ YAMLWE.Characteristics = ObjWE->Characteristics;
+
+ Sym->WeakExternal = YAMLWE;
+}
+
+static void
+dumpSectionDefinition(COFFYAML::Symbol *Sym,
+ const object::coff_aux_section_definition *ObjSD) {
+ COFF::AuxiliarySectionDefinition YAMLASD;
+ YAMLASD.Length = ObjSD->Length;
+ YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations;
+ YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers;
+ YAMLASD.CheckSum = ObjSD->CheckSum;
+ YAMLASD.Number = ObjSD->Number;
+ YAMLASD.Selection = ObjSD->Selection;
+
+ Sym->SectionDefinition = YAMLASD;
+}
+
+static void
+dumpCLRTokenDefinition(COFFYAML::Symbol *Sym,
+ const object::coff_aux_clr_token *ObjCLRToken) {
+ COFF::AuxiliaryCLRToken YAMLCLRToken;
+ YAMLCLRToken.AuxType = ObjCLRToken->AuxType;
+ YAMLCLRToken.SymbolTableIndex = ObjCLRToken->SymbolTableIndex;
+
+ Sym->CLRToken = YAMLCLRToken;
+}
+
void COFFDumper::dumpSymbols(unsigned NumSymbols) {
- error_code ec;
std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
- for (object::symbol_iterator iter = Obj.begin_symbols();
- iter != Obj.end_symbols(); iter.increment(ec)) {
- check(ec);
- const object::coff_symbol *Symbol = Obj.getCOFFSymbol(iter);
+ for (const auto &S : Obj.symbols()) {
+ const object::coff_symbol *Symbol = Obj.getCOFFSymbol(S);
COFFYAML::Symbol Sym;
Obj.getSymbolName(Symbol, Sym.Name);
Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType());
@@ -97,7 +145,63 @@ void COFFDumper::dumpSymbols(unsigned NumSymbols) {
Sym.Header.Value = Symbol->Value;
Sym.Header.SectionNumber = Symbol->SectionNumber;
Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols;
- Sym.AuxiliaryData = object::yaml::BinaryRef(Obj.getSymbolAuxData(Symbol));
+
+ if (Symbol->NumberOfAuxSymbols > 0) {
+ ArrayRef<uint8_t> AuxData = Obj.getSymbolAuxData(Symbol);
+ if (Symbol->isFunctionDefinition()) {
+ // This symbol represents a function definition.
+ assert(Symbol->NumberOfAuxSymbols == 1 &&
+ "Expected a single aux symbol to describe this function!");
+
+ const object::coff_aux_function_definition *ObjFD =
+ reinterpret_cast<const object::coff_aux_function_definition *>(
+ AuxData.data());
+ dumpFunctionDefinition(&Sym, ObjFD);
+ } else if (Symbol->isFunctionLineInfo()) {
+ // This symbol describes function line number information.
+ assert(Symbol->NumberOfAuxSymbols == 1 &&
+ "Exepected a single aux symbol to describe this section!");
+
+ const object::coff_aux_bf_and_ef_symbol *ObjBES =
+ reinterpret_cast<const object::coff_aux_bf_and_ef_symbol *>(
+ AuxData.data());
+ dumpbfAndEfLineInfo(&Sym, ObjBES);
+ } else if (Symbol->isWeakExternal()) {
+ // This symbol represents a weak external definition.
+ assert(Symbol->NumberOfAuxSymbols == 1 &&
+ "Exepected a single aux symbol to describe this section!");
+
+ const object::coff_aux_weak_external *ObjWE =
+ reinterpret_cast<const object::coff_aux_weak_external *>(
+ AuxData.data());
+ dumpWeakExternal(&Sym, ObjWE);
+ } else if (Symbol->isFileRecord()) {
+ // This symbol represents a file record.
+ Sym.File = StringRef(reinterpret_cast<const char *>(AuxData.data()),
+ Symbol->NumberOfAuxSymbols * COFF::SymbolSize)
+ .rtrim(StringRef("\0", /*length=*/1));
+ } else if (Symbol->isSectionDefinition()) {
+ // This symbol represents a section definition.
+ assert(Symbol->NumberOfAuxSymbols == 1 &&
+ "Expected a single aux symbol to describe this section!");
+
+ const object::coff_aux_section_definition *ObjSD =
+ reinterpret_cast<const object::coff_aux_section_definition *>(
+ AuxData.data());
+ dumpSectionDefinition(&Sym, ObjSD);
+ } else if (Symbol->isCLRToken()) {
+ // This symbol represents a CLR token definition.
+ assert(Symbol->NumberOfAuxSymbols == 1 &&
+ "Expected a single aux symbol to describe this CLR Token");
+
+ const object::coff_aux_clr_token *ObjCLRToken =
+ reinterpret_cast<const object::coff_aux_clr_token *>(
+ AuxData.data());
+ dumpCLRTokenDefinition(&Sym, ObjCLRToken);
+ } else {
+ llvm_unreachable("Unhandled auxiliary symbol!");
+ }
+ }
Symbols.push_back(Sym);
}
}
diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp
index 8d128b3..38779fe 100644
--- a/tools/obj2yaml/obj2yaml.cpp
+++ b/tools/obj2yaml/obj2yaml.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "obj2yaml.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/CommandLine.h"
@@ -38,14 +37,14 @@ int main(int argc, char *argv[]) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Process the input file
- OwningPtr<MemoryBuffer> buf;
+ std::unique_ptr<MemoryBuffer> buf;
// TODO: If this is an archive, then burst it and dump each entry
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, buf)) {
errs() << "Error: '" << ec.message() << "' opening file '" << InputFilename
<< "'\n";
} else {
- ec = coff2yaml(outs(), buf.take());
+ ec = coff2yaml(outs(), buf.release());
if (ec)
errs() << "Error: " << ec.message() << " dumping COFF file\n";
}
diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp
index 55f544f..4bdc268 100644
--- a/tools/opt/AnalysisWrappers.cpp
+++ b/tools/opt/AnalysisWrappers.cpp
@@ -18,9 +18,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/CallGraph.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
-#include "llvm/Support/CallSite.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -32,19 +32,18 @@ namespace {
struct ExternalFunctionsPassedConstants : public ModulePass {
static char ID; // Pass ID, replacement for typeid
ExternalFunctionsPassedConstants() : ModulePass(ID) {}
- virtual bool runOnModule(Module &M) {
+ bool runOnModule(Module &M) override {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->isDeclaration()) continue;
-
+
bool PrintedFn = false;
- for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
- UI != E; ++UI) {
- Instruction *User = dyn_cast<Instruction>(*UI);
- if (!User) continue;
-
- CallSite CS(cast<Value>(User));
+ for (User *U : I->users()) {
+ Instruction *UI = dyn_cast<Instruction>(U);
+ if (!UI) continue;
+
+ CallSite CS(cast<Value>(UI));
if (!CS) continue;
-
+
for (CallSite::arg_iterator AI = CS.arg_begin(),
E = CS.arg_end(); AI != E; ++AI) {
if (!isa<Constant>(*AI)) continue;
@@ -53,7 +52,7 @@ namespace {
errs() << "Function '" << I->getName() << "':\n";
PrintedFn = true;
}
- errs() << *User;
+ errs() << *UI;
break;
}
}
@@ -62,7 +61,7 @@ namespace {
return false;
}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
@@ -78,12 +77,12 @@ namespace {
static char ID; // Pass ID, replacement for typeid
CallGraphPrinter() : ModulePass(ID) {}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequiredTransitive<CallGraph>();
+ AU.addRequiredTransitive<CallGraphWrapperPass>();
}
- virtual bool runOnModule(Module &M) {
- getAnalysis<CallGraph>().print(errs(), &M);
+ bool runOnModule(Module &M) override {
+ getAnalysis<CallGraphWrapperPass>().print(errs(), &M);
return false;
}
};
diff --git a/tools/opt/Android.mk b/tools/opt/Android.mk
index 77183aa..9ba9584 100644
--- a/tools/opt/Android.mk
+++ b/tools/opt/Android.mk
@@ -58,6 +58,7 @@ include $(BUILD_HOST_EXECUTABLE)
# opt command line tool (target)
#===---------------------------------------------------------------===
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
include $(CLEAR_VARS)
LOCAL_MODULE := opt
@@ -70,10 +71,11 @@ LOCAL_STATIC_LIBRARIES := $(llvm_opt_STATIC_LIBRARIES)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
- libstlport
+ libcxx
include $(LLVM_ROOT_PATH)/llvm.mk
include $(LLVM_DEVICE_BUILD_MK)
include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_EXECUTABLE)
+endif
diff --git a/tools/opt/BreakpointPrinter.cpp b/tools/opt/BreakpointPrinter.cpp
new file mode 100644
index 0000000..44f4a11
--- /dev/null
+++ b/tools/opt/BreakpointPrinter.cpp
@@ -0,0 +1,82 @@
+//===- BreakpointPrinter.cpp - Breakpoint location printer ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Breakpoint location printer.
+///
+//===----------------------------------------------------------------------===//
+#include "BreakpointPrinter.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+struct BreakpointPrinter : public ModulePass {
+ raw_ostream &Out;
+ static char ID;
+ DITypeIdentifierMap TypeIdentifierMap;
+
+ BreakpointPrinter(raw_ostream &out) : ModulePass(ID), Out(out) {}
+
+ void getContextName(DIDescriptor Context, std::string &N) {
+ if (Context.isNameSpace()) {
+ DINameSpace NS(Context);
+ if (!NS.getName().empty()) {
+ getContextName(NS.getContext(), N);
+ N = N + NS.getName().str() + "::";
+ }
+ } else if (Context.isType()) {
+ DIType TY(Context);
+ if (!TY.getName().empty()) {
+ getContextName(TY.getContext().resolve(TypeIdentifierMap), N);
+ N = N + TY.getName().str() + "::";
+ }
+ }
+ }
+
+ bool runOnModule(Module &M) override {
+ TypeIdentifierMap.clear();
+ NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
+ if (CU_Nodes)
+ TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
+
+ StringSet<> Processed;
+ if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp"))
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ std::string Name;
+ DISubprogram SP(NMD->getOperand(i));
+ assert((!SP || SP.isSubprogram()) &&
+ "A MDNode in llvm.dbg.sp should be null or a DISubprogram.");
+ if (!SP)
+ continue;
+ getContextName(SP.getContext().resolve(TypeIdentifierMap), Name);
+ Name = Name + SP.getDisplayName().str();
+ if (!Name.empty() && Processed.insert(Name)) {
+ Out << Name << "\n";
+ }
+ }
+ return false;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+};
+
+char BreakpointPrinter::ID = 0;
+}
+
+ModulePass *llvm::createBreakpointPrinter(raw_ostream &out) {
+ return new BreakpointPrinter(out);
+}
diff --git a/tools/opt/BreakpointPrinter.h b/tools/opt/BreakpointPrinter.h
new file mode 100644
index 0000000..81c88e1
--- /dev/null
+++ b/tools/opt/BreakpointPrinter.h
@@ -0,0 +1,25 @@
+//===- BreakpointPrinter.h - Breakpoint location printer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Breakpoint location printer.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
+#define LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
+
+namespace llvm {
+
+class ModulePass;
+class raw_ostream;
+
+ModulePass *createBreakpointPrinter(raw_ostream &out);
+}
+
+#endif // LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
index 9195911..1d3f08d 100644
--- a/tools/opt/CMakeLists.txt
+++ b/tools/opt/CMakeLists.txt
@@ -1,9 +1,43 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser bitwriter irreader instrumentation scalaropts objcarcopts ipo vectorize)
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Analysis
+ BitWriter
+ CodeGen
+ Core
+ IPA
+ IPO
+ IRReader
+ InstCombine
+ Instrumentation
+ MC
+ ObjCARCOpts
+ ScalarOpts
+ Support
+ Target
+ TransformUtils
+ Vectorize
+ )
+
+# Support plugins.
+set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(opt
AnalysisWrappers.cpp
+ BreakpointPrinter.cpp
GraphPrinters.cpp
+ NewPMDriver.cpp
+ Passes.cpp
+ PassPrinters.cpp
PrintSCC.cpp
opt.cpp
)
set_target_properties(opt PROPERTIES ENABLE_EXPORTS 1)
+
+if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
+ target_link_libraries(opt Polly)
+ if(POLLY_LINK_LIBS)
+ foreach(lib ${POLLY_LINK_LIBS})
+ target_link_libraries(opt ${lib})
+ endforeach(lib)
+ endif(POLLY_LINK_LIBS)
+endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp
index f271966..640edfe 100644
--- a/tools/opt/GraphPrinters.cpp
+++ b/tools/opt/GraphPrinters.cpp
@@ -14,7 +14,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/Dominators.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/Pass.h"
using namespace llvm;
@@ -29,14 +29,13 @@ namespace {
static char ID; // Pass identification, replacement for typeid
DomInfoPrinter() : FunctionPass(ID) {}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequired<DominatorTree>();
-
+ AU.addRequired<DominatorTreeWrapperPass>();
}
- virtual bool runOnFunction(Function &F) {
- getAnalysis<DominatorTree>().dump();
+ bool runOnFunction(Function &F) override {
+ getAnalysis<DominatorTreeWrapperPass>().dump();
return false;
}
};
diff --git a/tools/opt/LLVMBuild.txt b/tools/opt/LLVMBuild.txt
index 77b9446..b3589f8 100644
--- a/tools/opt/LLVMBuild.txt
+++ b/tools/opt/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = opt
parent = Tools
-required_libraries = AsmParser BitReader BitWriter IRReader IPO Instrumentation Scalar ObjCARC all-targets
+required_libraries = AsmParser BitReader BitWriter CodeGen IRReader IPO Instrumentation Scalar ObjCARC all-targets
diff --git a/tools/opt/Makefile b/tools/opt/Makefile
index a451005..cfa9c31 100644
--- a/tools/opt/Makefile
+++ b/tools/opt/Makefile
@@ -9,6 +9,9 @@
LEVEL := ../..
TOOLNAME := opt
-LINK_COMPONENTS := bitreader bitwriter asmparser irreader instrumentation scalaropts objcarcopts ipo vectorize all-targets
+LINK_COMPONENTS := bitreader bitwriter asmparser irreader instrumentation scalaropts objcarcopts ipo vectorize all-targets codegen
+
+# Support plugins.
+NO_DEAD_STRIP := 1
include $(LEVEL)/Makefile.common
diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp
new file mode 100644
index 0000000..fc4a1bf
--- /dev/null
+++ b/tools/opt/NewPMDriver.cpp
@@ -0,0 +1,81 @@
+//===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file is just a split of the code that logically belongs in opt.cpp but
+/// that includes the new pass manager headers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "NewPMDriver.h"
+#include "Passes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace llvm;
+using namespace opt_tool;
+
+bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
+ tool_output_file *Out, StringRef PassPipeline,
+ OutputKind OK, VerifierKind VK) {
+ FunctionAnalysisManager FAM;
+ ModuleAnalysisManager MAM;
+
+ // FIXME: Lift this registration of analysis passes into a .def file adjacent
+ // to the one used to associate names with passes.
+ MAM.registerPass(LazyCallGraphAnalysis());
+
+ // Cross register the analysis managers through their proxies.
+ MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
+ FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
+
+ ModulePassManager MPM;
+ if (VK > VK_NoVerifier)
+ MPM.addPass(VerifierPass());
+
+ if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) {
+ errs() << Arg0 << ": unable to parse pass pipeline description.\n";
+ return false;
+ }
+
+ if (VK > VK_NoVerifier)
+ MPM.addPass(VerifierPass());
+
+ // Add any relevant output pass at the end of the pipeline.
+ switch (OK) {
+ case OK_NoOutput:
+ break; // No output pass needed.
+ case OK_OutputAssembly:
+ MPM.addPass(PrintModulePass(Out->os()));
+ break;
+ case OK_OutputBitcode:
+ MPM.addPass(BitcodeWriterPass(Out->os()));
+ break;
+ }
+
+ // Before executing passes, print the final values of the LLVM options.
+ cl::PrintOptionValues();
+
+ // Now that we have all of the passes ready, run them.
+ MPM.run(&M, &MAM);
+
+ // Declare success.
+ if (OK != OK_NoOutput)
+ Out->keep();
+ return true;
+}
diff --git a/tools/opt/NewPMDriver.h b/tools/opt/NewPMDriver.h
new file mode 100644
index 0000000..3661d3e
--- /dev/null
+++ b/tools/opt/NewPMDriver.h
@@ -0,0 +1,55 @@
+//===- NewPMDriver.h - Function to drive opt with the new PM ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A single function which is called to drive the opt behavior for the new
+/// PassManager.
+///
+/// This is only in a separate TU with a header to avoid including all of the
+/// old pass manager headers and the new pass manager headers into the same
+/// file. Eventually all of the routines here will get folded back into
+/// opt.cpp.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OPT_NEW_PM_DRIVER_H
+#define LLVM_TOOLS_OPT_NEW_PM_DRIVER_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+class LLVMContext;
+class Module;
+class tool_output_file;
+
+namespace opt_tool {
+enum OutputKind {
+ OK_NoOutput,
+ OK_OutputAssembly,
+ OK_OutputBitcode
+};
+enum VerifierKind {
+ VK_NoVerifier,
+ VK_VerifyInAndOut,
+ VK_VerifyEachPass
+};
+}
+
+/// \brief Driver function to run the new pass manager over a module.
+///
+/// This function only exists factored away from opt.cpp in order to prevent
+/// inclusion of the new pass manager headers and the old headers into the same
+/// file. It's interface is consequentially somewhat ad-hoc, but will go away
+/// when the transition finishes.
+bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
+ tool_output_file *Out, StringRef PassPipeline,
+ opt_tool::OutputKind OK, opt_tool::VerifierKind VK);
+}
+
+#endif
diff --git a/tools/opt/PassPrinters.cpp b/tools/opt/PassPrinters.cpp
new file mode 100644
index 0000000..d699489
--- /dev/null
+++ b/tools/opt/PassPrinters.cpp
@@ -0,0 +1,260 @@
+//===- PassPrinters.cpp - Utilities to print analysis info for passes -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Utilities to print analysis info for various kinds of passes.
+///
+//===----------------------------------------------------------------------===//
+#include "PassPrinters.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/RegionPass.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Pass.h"
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+struct FunctionPassPrinter : public FunctionPass {
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ static char ID;
+ std::string PassName;
+ bool QuietPass;
+
+ FunctionPassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : FunctionPass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "FunctionPass Printer: " + PassToPrintName;
+ }
+
+ bool runOnFunction(Function &F) override {
+ if (!QuietPass)
+ Out << "Printing analysis '" << PassToPrint->getPassName()
+ << "' for function '" << F.getName() << "':\n";
+
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, F.getParent());
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char FunctionPassPrinter::ID = 0;
+
+struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ std::string PassName;
+ bool QuietPass;
+
+ CallGraphSCCPassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : CallGraphSCCPass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "CallGraphSCCPass Printer: " + PassToPrintName;
+ }
+
+ bool runOnSCC(CallGraphSCC &SCC) override {
+ if (!QuietPass)
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+
+ // Get and print pass...
+ for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
+ Function *F = (*I)->getFunction();
+ if (F)
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo())
+ .print(Out, F->getParent());
+ }
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char CallGraphSCCPassPrinter::ID = 0;
+
+struct ModulePassPrinter : public ModulePass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ std::string PassName;
+ bool QuietPass;
+
+ ModulePassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : ModulePass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "ModulePass Printer: " + PassToPrintName;
+ }
+
+ bool runOnModule(Module &M) override {
+ if (!QuietPass)
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, &M);
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char ModulePassPrinter::ID = 0;
+
+struct LoopPassPrinter : public LoopPass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ std::string PassName;
+ bool QuietPass;
+
+ LoopPassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : LoopPass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "LoopPass Printer: " + PassToPrintName;
+ }
+
+ bool runOnLoop(Loop *L, LPPassManager &LPM) override {
+ if (!QuietPass)
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo())
+ .print(Out, L->getHeader()->getParent()->getParent());
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char LoopPassPrinter::ID = 0;
+
+struct RegionPassPrinter : public RegionPass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ std::string PassName;
+ bool QuietPass;
+
+ RegionPassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : RegionPass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "RegionPass Printer: " + PassToPrintName;
+ }
+
+ bool runOnRegion(Region *R, RGPassManager &RGM) override {
+ if (!QuietPass) {
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "' for "
+ << "region: '" << R->getNameStr() << "' in function '"
+ << R->getEntry()->getParent()->getName() << "':\n";
+ }
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo())
+ .print(Out, R->getEntry()->getParent()->getParent());
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char RegionPassPrinter::ID = 0;
+
+struct BasicBlockPassPrinter : public BasicBlockPass {
+ const PassInfo *PassToPrint;
+ raw_ostream &Out;
+ static char ID;
+ std::string PassName;
+ bool QuietPass;
+
+ BasicBlockPassPrinter(const PassInfo *PI, raw_ostream &out, bool Quiet)
+ : BasicBlockPass(ID), PassToPrint(PI), Out(out), QuietPass(Quiet) {
+ std::string PassToPrintName = PassToPrint->getPassName();
+ PassName = "BasicBlockPass Printer: " + PassToPrintName;
+ }
+
+ bool runOnBasicBlock(BasicBlock &BB) override {
+ if (!QuietPass)
+ Out << "Printing Analysis info for BasicBlock '" << BB.getName()
+ << "': Pass " << PassToPrint->getPassName() << ":\n";
+
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo())
+ .print(Out, BB.getParent()->getParent());
+ return false;
+ }
+
+ const char *getPassName() const override { return PassName.c_str(); }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(PassToPrint->getTypeInfo());
+ AU.setPreservesAll();
+ }
+};
+
+char BasicBlockPassPrinter::ID = 0;
+}
+
+FunctionPass *llvm::createFunctionPassPrinter(const PassInfo *PI,
+ raw_ostream &OS, bool Quiet) {
+ return new FunctionPassPrinter(PI, OS, Quiet);
+}
+
+CallGraphSCCPass *llvm::createCallGraphPassPrinter(const PassInfo *PI,
+ raw_ostream &OS,
+ bool Quiet) {
+ return new CallGraphSCCPassPrinter(PI, OS, Quiet);
+}
+
+ModulePass *llvm::createModulePassPrinter(const PassInfo *PI, raw_ostream &OS,
+ bool Quiet) {
+ return new ModulePassPrinter(PI, OS, Quiet);
+}
+
+LoopPass *llvm::createLoopPassPrinter(const PassInfo *PI, raw_ostream &OS,
+ bool Quiet) {
+ return new LoopPassPrinter(PI, OS, Quiet);
+}
+
+RegionPass *llvm::createRegionPassPrinter(const PassInfo *PI, raw_ostream &OS,
+ bool Quiet) {
+ return new RegionPassPrinter(PI, OS, Quiet);
+}
+
+BasicBlockPass *llvm::createBasicBlockPassPrinter(const PassInfo *PI,
+ raw_ostream &OS, bool Quiet) {
+ return new BasicBlockPassPrinter(PI, OS, Quiet);
+}
diff --git a/tools/opt/PassPrinters.h b/tools/opt/PassPrinters.h
new file mode 100644
index 0000000..cf46ef9
--- /dev/null
+++ b/tools/opt/PassPrinters.h
@@ -0,0 +1,47 @@
+//===- PassPrinters.h - Utilities to print analysis info for passes -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Utilities to print analysis info for various kinds of passes.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_OPT_PASSPRINTERS_H
+#define LLVM_TOOLS_OPT_PASSPRINTERS_H
+
+namespace llvm {
+
+class BasicBlockPass;
+class CallGraphSCCPass;
+class FunctionPass;
+class ModulePass;
+class LoopPass;
+class PassInfo;
+class RegionPass;
+class raw_ostream;
+
+FunctionPass *createFunctionPassPrinter(const PassInfo *PI, raw_ostream &out,
+ bool Quiet);
+
+CallGraphSCCPass *createCallGraphPassPrinter(const PassInfo *PI,
+ raw_ostream &out, bool Quiet);
+
+ModulePass *createModulePassPrinter(const PassInfo *PI, raw_ostream &out,
+ bool Quiet);
+
+LoopPass *createLoopPassPrinter(const PassInfo *PI, raw_ostream &out,
+ bool Quiet);
+
+RegionPass *createRegionPassPrinter(const PassInfo *PI, raw_ostream &out,
+ bool Quiet);
+
+BasicBlockPass *createBasicBlockPassPrinter(const PassInfo *PI,
+ raw_ostream &out, bool Quiet);
+}
+
+#endif // LLVM_TOOLS_OPT_PASSPRINTERS_H
diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp
new file mode 100644
index 0000000..ffdf9bf
--- /dev/null
+++ b/tools/opt/Passes.cpp
@@ -0,0 +1,209 @@
+//===- Passes.cpp - Parsing, selection, and running of passes -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file provides the infrastructure to parse and build a custom pass
+/// manager based on a commandline flag. It also provides helpers to aid in
+/// analyzing, debugging, and testing pass structures.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+namespace {
+
+/// \brief No-op module pass which does nothing.
+struct NoOpModulePass {
+ PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }
+ static StringRef name() { return "NoOpModulePass"; }
+};
+
+/// \brief No-op function pass which does nothing.
+struct NoOpFunctionPass {
+ PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); }
+ static StringRef name() { return "NoOpFunctionPass"; }
+};
+
+} // End anonymous namespace.
+
+// FIXME: Factor all of the parsing logic into a .def file that we include
+// under different macros.
+static bool isModulePassName(StringRef Name) {
+ if (Name == "no-op-module") return true;
+ if (Name == "print") return true;
+ if (Name == "print-cg") return true;
+
+ return false;
+}
+
+static bool isFunctionPassName(StringRef Name) {
+ if (Name == "no-op-function") return true;
+ if (Name == "print") return true;
+
+ return false;
+}
+
+static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {
+ if (Name == "no-op-module") {
+ MPM.addPass(NoOpModulePass());
+ return true;
+ }
+ if (Name == "print") {
+ MPM.addPass(PrintModulePass(dbgs()));
+ return true;
+ }
+ if (Name == "print-cg") {
+ MPM.addPass(LazyCallGraphPrinterPass(dbgs()));
+ return true;
+ }
+ return false;
+}
+
+static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
+ if (Name == "no-op-function") {
+ FPM.addPass(NoOpFunctionPass());
+ return true;
+ }
+ if (Name == "print") {
+ FPM.addPass(PrintFunctionPass(dbgs()));
+ return true;
+ }
+ return false;
+}
+
+static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
+ StringRef &PipelineText,
+ bool VerifyEachPass) {
+ for (;;) {
+ // Parse nested pass managers by recursing.
+ if (PipelineText.startswith("function(")) {
+ FunctionPassManager NestedFPM;
+
+ // Parse the inner pipeline inte the nested manager.
+ PipelineText = PipelineText.substr(strlen("function("));
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
+ PipelineText.empty())
+ return false;
+ assert(PipelineText[0] == ')');
+ PipelineText = PipelineText.substr(1);
+
+ // Add the nested pass manager with the appropriate adaptor.
+ FPM.addPass(std::move(NestedFPM));
+ } else {
+ // Otherwise try to parse a pass name.
+ size_t End = PipelineText.find_first_of(",)");
+ if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
+ return false;
+ if (VerifyEachPass)
+ FPM.addPass(VerifierPass());
+
+ PipelineText = PipelineText.substr(End);
+ }
+
+ if (PipelineText.empty() || PipelineText[0] == ')')
+ return true;
+
+ assert(PipelineText[0] == ',');
+ PipelineText = PipelineText.substr(1);
+ }
+}
+
+static bool parseModulePassPipeline(ModulePassManager &MPM,
+ StringRef &PipelineText,
+ bool VerifyEachPass) {
+ for (;;) {
+ // Parse nested pass managers by recursing.
+ if (PipelineText.startswith("module(")) {
+ ModulePassManager NestedMPM;
+
+ // Parse the inner pipeline into the nested manager.
+ PipelineText = PipelineText.substr(strlen("module("));
+ if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) ||
+ PipelineText.empty())
+ return false;
+ assert(PipelineText[0] == ')');
+ PipelineText = PipelineText.substr(1);
+
+ // Now add the nested manager as a module pass.
+ MPM.addPass(std::move(NestedMPM));
+ } else if (PipelineText.startswith("function(")) {
+ FunctionPassManager NestedFPM;
+
+ // Parse the inner pipeline inte the nested manager.
+ PipelineText = PipelineText.substr(strlen("function("));
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
+ PipelineText.empty())
+ return false;
+ assert(PipelineText[0] == ')');
+ PipelineText = PipelineText.substr(1);
+
+ // Add the nested pass manager with the appropriate adaptor.
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
+ } else {
+ // Otherwise try to parse a pass name.
+ size_t End = PipelineText.find_first_of(",)");
+ if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
+ return false;
+ if (VerifyEachPass)
+ MPM.addPass(VerifierPass());
+
+ PipelineText = PipelineText.substr(End);
+ }
+
+ if (PipelineText.empty() || PipelineText[0] == ')')
+ return true;
+
+ assert(PipelineText[0] == ',');
+ PipelineText = PipelineText.substr(1);
+ }
+}
+
+// Primary pass pipeline description parsing routine.
+// FIXME: Should this routine accept a TargetMachine or require the caller to
+// pre-populate the analysis managers with target-specific stuff?
+bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
+ bool VerifyEachPass) {
+ // Look at the first entry to figure out which layer to start parsing at.
+ if (PipelineText.startswith("module("))
+ return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
+ PipelineText.empty();
+ if (PipelineText.startswith("function(")) {
+ FunctionPassManager FPM;
+ if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
+ !PipelineText.empty())
+ return false;
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ return true;
+ }
+
+ // This isn't a direct pass manager name, look for the end of a pass name.
+ StringRef FirstName =
+ PipelineText.substr(0, PipelineText.find_first_of(",)"));
+ if (isModulePassName(FirstName))
+ return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
+ PipelineText.empty();
+
+ if (isFunctionPassName(FirstName)) {
+ FunctionPassManager FPM;
+ if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
+ !PipelineText.empty())
+ return false;
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ return true;
+ }
+
+ return false;
+}
diff --git a/tools/opt/Passes.h b/tools/opt/Passes.h
new file mode 100644
index 0000000..3bd6752
--- /dev/null
+++ b/tools/opt/Passes.h
@@ -0,0 +1,57 @@
+//===- Passes.h - Parsing, selection, and running of passes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Interfaces for producing common pass manager configurations and parsing
+/// textual pass specifications.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OPT_PASSES_H
+#define LLVM_TOOLS_OPT_PASSES_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+class ModulePassManager;
+
+/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
+///
+/// The format of the textual pass pipeline description looks something like:
+///
+/// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...)
+///
+/// Pass managers have ()s describing the nest structure of passes. All passes
+/// are comma separated. As a special shortcut, if the very first pass is not
+/// a module pass (as a module pass manager is), this will automatically form
+/// the shortest stack of pass managers that allow inserting that first pass.
+/// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes
+/// 'lpassN', all of these are valid:
+///
+/// fpass1,fpass2,fpass3
+/// cgpass1,cgpass2,cgpass3
+/// lpass1,lpass2,lpass3
+///
+/// And they are equivalent to the following (resp.):
+///
+/// module(function(fpass1,fpass2,fpass3))
+/// module(cgscc(cgpass1,cgpass2,cgpass3))
+/// module(function(loop(lpass1,lpass2,lpass3)))
+///
+/// This shortcut is especially useful for debugging and testing small pass
+/// combinations. Note that these shortcuts don't introduce any other magic. If
+/// the sequence of passes aren't all the exact same kind of pass, it will be
+/// an error. You cannot mix different levels implicitly, you must explicitly
+/// form a pass manager in which to nest passes.
+bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
+ bool VerifyEachPass = true);
+
+}
+
+#endif
diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp
index a502fa7..cbc0a55 100644
--- a/tools/opt/PrintSCC.cpp
+++ b/tools/opt/PrintSCC.cpp
@@ -27,9 +27,9 @@
#include "llvm/ADT/SCCIterator.h"
#include "llvm/Analysis/CallGraph.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -37,11 +37,11 @@ namespace {
struct CFGSCC : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
CFGSCC() : FunctionPass(ID) {}
- bool runOnFunction(Function& func);
+ bool runOnFunction(Function& func) override;
- void print(raw_ostream &O, const Module* = 0) const { }
+ void print(raw_ostream &O, const Module* = 0) const override { }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
@@ -51,14 +51,14 @@ namespace {
CallGraphSCC() : ModulePass(ID) {}
// run - Print out SCCs in the call graph for the specified module.
- bool runOnModule(Module &M);
+ bool runOnModule(Module &M) override;
- void print(raw_ostream &O, const Module* = 0) const { }
+ void print(raw_ostream &O, const Module* = 0) const override { }
// getAnalysisUsage - This pass requires the CallGraph.
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
- AU.addRequired<CallGraph>();
+ AU.addRequired<CallGraphWrapperPass>();
}
};
}
@@ -74,8 +74,7 @@ Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
bool CFGSCC::runOnFunction(Function &F) {
unsigned sccNum = 0;
errs() << "SCCs for Function " << F.getName() << " in PostOrder:";
- for (scc_iterator<Function*> SCCI = scc_begin(&F),
- E = scc_end(&F); SCCI != E; ++SCCI) {
+ for (scc_iterator<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) {
std::vector<BasicBlock*> &nextSCC = *SCCI;
errs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
@@ -92,11 +91,11 @@ bool CFGSCC::runOnFunction(Function &F) {
// run - Print out SCCs in the call graph for the specified module.
bool CallGraphSCC::runOnModule(Module &M) {
- CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
+ CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
unsigned sccNum = 0;
errs() << "SCCs for the program in PostOrder:";
- for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
- E = scc_end(rootNode); SCCI != E; ++SCCI) {
+ for (scc_iterator<CallGraph*> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
+ ++SCCI) {
const std::vector<CallGraphNode*> &nextSCC = *SCCI;
errs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index dba16f7..5a19881 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -12,28 +12,30 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/ADT/StringSet.h"
+#include "BreakpointPrinter.h"
+#include "NewPMDriver.h"
+#include "PassPrinters.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/PassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
@@ -48,6 +50,7 @@
#include <algorithm>
#include <memory>
using namespace llvm;
+using namespace opt_tool;
// The OptimizationList is automatically populated with registered Passes by the
// PassNameParser.
@@ -55,6 +58,15 @@ using namespace llvm;
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Optimizations available:"));
+// This flag specifies a textual description of the optimization pass pipeline
+// to run over the module. This flag switches opt to use the new pass manager
+// infrastructure, completely disabling all of the flags specific to the old
+// pass management.
+static cl::opt<std::string> PassPipeline(
+ "passes",
+ cl::desc("A textual description of the pass pipeline for optimizing"),
+ cl::Hidden);
+
// Other command line options...
//
static cl::opt<std::string>
@@ -172,265 +184,7 @@ DefaultDataLayout("default-data-layout",
cl::desc("data layout string to use if not specified by module"),
cl::value_desc("layout-string"), cl::init(""));
-// ---------- Define Printers for module and function passes ------------
-namespace {
-
-struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
- static char ID;
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- std::string PassName;
-
- CallGraphSCCPassPrinter(const PassInfo *PI, raw_ostream &out) :
- CallGraphSCCPass(ID), PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "CallGraphSCCPass Printer: " + PassToPrintName;
- }
-
- virtual bool runOnSCC(CallGraphSCC &SCC) {
- if (!Quiet)
- Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
-
- // Get and print pass...
- for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
- Function *F = (*I)->getFunction();
- if (F)
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
- F->getParent());
- }
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char CallGraphSCCPassPrinter::ID = 0;
-
-struct ModulePassPrinter : public ModulePass {
- static char ID;
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- std::string PassName;
-
- ModulePassPrinter(const PassInfo *PI, raw_ostream &out)
- : ModulePass(ID), PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "ModulePass Printer: " + PassToPrintName;
- }
-
- virtual bool runOnModule(Module &M) {
- if (!Quiet)
- Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
-
- // Get and print pass...
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, &M);
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char ModulePassPrinter::ID = 0;
-struct FunctionPassPrinter : public FunctionPass {
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- static char ID;
- std::string PassName;
-
- FunctionPassPrinter(const PassInfo *PI, raw_ostream &out)
- : FunctionPass(ID), PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "FunctionPass Printer: " + PassToPrintName;
- }
-
- virtual bool runOnFunction(Function &F) {
- if (!Quiet)
- Out << "Printing analysis '" << PassToPrint->getPassName()
- << "' for function '" << F.getName() << "':\n";
-
- // Get and print pass...
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
- F.getParent());
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char FunctionPassPrinter::ID = 0;
-
-struct LoopPassPrinter : public LoopPass {
- static char ID;
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- std::string PassName;
-
- LoopPassPrinter(const PassInfo *PI, raw_ostream &out) :
- LoopPass(ID), PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "LoopPass Printer: " + PassToPrintName;
- }
-
-
- virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
- if (!Quiet)
- Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
-
- // Get and print pass...
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
- L->getHeader()->getParent()->getParent());
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char LoopPassPrinter::ID = 0;
-
-struct RegionPassPrinter : public RegionPass {
- static char ID;
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- std::string PassName;
-
- RegionPassPrinter(const PassInfo *PI, raw_ostream &out) : RegionPass(ID),
- PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "RegionPass Printer: " + PassToPrintName;
- }
-
- virtual bool runOnRegion(Region *R, RGPassManager &RGM) {
- if (!Quiet) {
- Out << "Printing analysis '" << PassToPrint->getPassName() << "' for "
- << "region: '" << R->getNameStr() << "' in function '"
- << R->getEntry()->getParent()->getName() << "':\n";
- }
- // Get and print pass...
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
- R->getEntry()->getParent()->getParent());
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char RegionPassPrinter::ID = 0;
-
-struct BasicBlockPassPrinter : public BasicBlockPass {
- const PassInfo *PassToPrint;
- raw_ostream &Out;
- static char ID;
- std::string PassName;
-
- BasicBlockPassPrinter(const PassInfo *PI, raw_ostream &out)
- : BasicBlockPass(ID), PassToPrint(PI), Out(out) {
- std::string PassToPrintName = PassToPrint->getPassName();
- PassName = "BasicBlockPass Printer: " + PassToPrintName;
- }
-
- virtual bool runOnBasicBlock(BasicBlock &BB) {
- if (!Quiet)
- Out << "Printing Analysis info for BasicBlock '" << BB.getName()
- << "': Pass " << PassToPrint->getPassName() << ":\n";
-
- // Get and print pass...
- getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
- BB.getParent()->getParent());
- return false;
- }
-
- virtual const char *getPassName() const { return PassName.c_str(); }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint->getTypeInfo());
- AU.setPreservesAll();
- }
-};
-
-char BasicBlockPassPrinter::ID = 0;
-
-struct BreakpointPrinter : public ModulePass {
- raw_ostream &Out;
- static char ID;
- DITypeIdentifierMap TypeIdentifierMap;
-
- BreakpointPrinter(raw_ostream &out)
- : ModulePass(ID), Out(out) {
- }
-
- void getContextName(DIDescriptor Context, std::string &N) {
- if (Context.isNameSpace()) {
- DINameSpace NS(Context);
- if (!NS.getName().empty()) {
- getContextName(NS.getContext(), N);
- N = N + NS.getName().str() + "::";
- }
- } else if (Context.isType()) {
- DIType TY(Context);
- if (!TY.getName().empty()) {
- getContextName(TY.getContext().resolve(TypeIdentifierMap), N);
- N = N + TY.getName().str() + "::";
- }
- }
- }
-
- virtual bool runOnModule(Module &M) {
- TypeIdentifierMap.clear();
- NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
- if (CU_Nodes)
- TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
-
- StringSet<> Processed;
- if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp"))
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- std::string Name;
- DISubprogram SP(NMD->getOperand(i));
- assert((!SP || SP.isSubprogram()) &&
- "A MDNode in llvm.dbg.sp should be null or a DISubprogram.");
- if (!SP)
- continue;
- getContextName(SP.getContext().resolve(TypeIdentifierMap), Name);
- Name = Name + SP.getDisplayName().str();
- if (!Name.empty() && Processed.insert(Name)) {
- Out << Name << "\n";
- }
- }
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
-};
-
-} // anonymous namespace
-
-char BreakpointPrinter::ID = 0;
static inline void addPass(PassManagerBase &PM, Pass *P) {
// Add the pass to the pass manager...
@@ -456,14 +210,7 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
if (DisableInline) {
// No inlining pass
} else if (OptLevel > 1) {
- unsigned Threshold = 225;
- if (SizeLevel == 1) // -Os
- Threshold = 75;
- else if (SizeLevel == 2) // -Oz
- Threshold = 25;
- if (OptLevel > 2)
- Threshold = 275;
- Builder.Inliner = createFunctionInliningPass(Threshold);
+ Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel);
} else {
Builder.Inliner = createAlwaysInlinerPass();
}
@@ -471,8 +218,14 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
Builder.DisableUnrollLoops = (DisableLoopUnrolling.getNumOccurrences() > 0) ?
DisableLoopUnrolling : OptLevel == 0;
- Builder.LoopVectorize =
- DisableLoopVectorization ? false : OptLevel > 1 && SizeLevel < 2;
+ // This is final, unless there is a #pragma vectorize enable
+ if (DisableLoopVectorization)
+ Builder.LoopVectorize = false;
+ // If option wasn't forced via cmd line (-vectorize-loops, -loop-vectorize)
+ else if (!Builder.LoopVectorize)
+ Builder.LoopVectorize = OptLevel > 1 && SizeLevel < 2;
+
+ // When #pragma vectorize is on for SLP, do the same as above
Builder.SLPVectorize =
DisableSLPVectorization ? false : OptLevel > 1 && SizeLevel < 2;
@@ -514,29 +267,6 @@ static void AddStandardLinkPasses(PassManagerBase &PM) {
//===----------------------------------------------------------------------===//
// CodeGen-related helper functions.
//
-static TargetOptions GetTargetOptions() {
- TargetOptions Options;
- Options.LessPreciseFPMADOption = EnableFPMAD;
- Options.NoFramePointerElim = DisableFPElim;
- Options.AllowFPOpFusion = FuseFPOps;
- Options.UnsafeFPMath = EnableUnsafeFPMath;
- Options.NoInfsFPMath = EnableNoInfsFPMath;
- Options.NoNaNsFPMath = EnableNoNaNsFPMath;
- Options.HonorSignDependentRoundingFPMathOption =
- EnableHonorSignDependentRoundingFPMath;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
- if (FloatABIForCalls != FloatABI::Default)
- Options.FloatABIType = FloatABIForCalls;
- Options.NoZerosInBSS = DontPlaceZerosInBSS;
- Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
- Options.DisableTailCalls = DisableTailCalls;
- Options.StackAlignmentOverride = OverrideStackAlignment;
- Options.TrapFuncName = TrapFuncName;
- Options.PositionIndependentExecutable = EnablePIE;
- Options.EnableSegmentedStacks = SegmentedStacks;
- Options.UseInitArray = UseInitArray;
- return Options;
-}
CodeGenOpt::Level GetCodeGenOptLevel() {
if (OptLevelO1)
@@ -568,11 +298,18 @@ static TargetMachine* GetTargetMachine(Triple TheTriple) {
}
return TheTarget->createTargetMachine(TheTriple.getTriple(),
- MCPU, FeaturesStr, GetTargetOptions(),
+ MCPU, FeaturesStr,
+ InitTargetOptionsFromCodeGenFlags(),
RelocModel, CMModel,
GetCodeGenOptLevel());
}
+#ifdef LINK_POLLY_INTO_TOOLS
+namespace polly {
+void initializePollyPasses(llvm::PassRegistry &Registry);
+}
+#endif
+
//===----------------------------------------------------------------------===//
// main for opt
//
@@ -603,6 +340,13 @@ int main(int argc, char **argv) {
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
+ // For codegen passes, only passes that do IR to IR transformation are
+ // supported. For now, just add CodeGenPrepare.
+ initializeCodeGenPreparePass(Registry);
+
+#ifdef LINK_POLLY_INTO_TOOLS
+ polly::initializePollyPasses(Registry);
+#endif
cl::ParseCommandLineOptions(argc, argv,
"llvm .bc -> .bc modular optimizer and analysis printer\n");
@@ -615,7 +359,7 @@ int main(int argc, char **argv) {
SMDiagnostic Err;
// Load the input module...
- OwningPtr<Module> M;
+ std::unique_ptr<Module> M;
M.reset(ParseIRFile(InputFilename, Err, Context));
if (M.get() == 0) {
@@ -628,7 +372,7 @@ int main(int argc, char **argv) {
M->setTargetTriple(Triple::normalize(TargetTriple));
// Figure out what stream we are supposed to write to...
- OwningPtr<tool_output_file> Out;
+ std::unique_ptr<tool_output_file> Out;
if (NoOutput) {
if (!OutputFilename.empty())
errs() << "WARNING: The -o (output filename) option is ignored when\n"
@@ -640,7 +384,7 @@ int main(int argc, char **argv) {
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- sys::fs::F_Binary));
+ sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
@@ -654,6 +398,26 @@ int main(int argc, char **argv) {
if (CheckBitcodeOutputToConsole(Out->os(), !Quiet))
NoOutput = true;
+ if (PassPipeline.getNumOccurrences() > 0) {
+ OutputKind OK = OK_NoOutput;
+ if (!NoOutput)
+ OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode;
+
+ VerifierKind VK = VK_VerifyInAndOut;
+ if (NoVerify)
+ VK = VK_NoVerifier;
+ else if (VerifyEach)
+ VK = VK_VerifyEachPass;
+
+ // The user has asked to use the new pass manager and provided a pipeline
+ // string. Hand off the rest of the functionality to the new code for that
+ // layer.
+ return runPassPipeline(argv[0], Context, *M.get(), Out.get(), PassPipeline,
+ OK, VK)
+ ? 0
+ : 1;
+ }
+
// Create a PassManager to hold and optimize the collection of passes we are
// about to build.
//
@@ -668,31 +432,30 @@ int main(int argc, char **argv) {
Passes.add(TLI);
// Add an appropriate DataLayout instance for this module.
- DataLayout *TD = 0;
- const std::string &ModuleDataLayout = M.get()->getDataLayout();
- if (!ModuleDataLayout.empty())
- TD = new DataLayout(ModuleDataLayout);
- else if (!DefaultDataLayout.empty())
- TD = new DataLayout(DefaultDataLayout);
+ const DataLayout *DL = M.get()->getDataLayout();
+ if (!DL && !DefaultDataLayout.empty()) {
+ M->setDataLayout(DefaultDataLayout);
+ DL = M.get()->getDataLayout();
+ }
- if (TD)
- Passes.add(TD);
+ if (DL)
+ Passes.add(new DataLayoutPass(M.get()));
Triple ModuleTriple(M->getTargetTriple());
TargetMachine *Machine = 0;
if (ModuleTriple.getArch())
Machine = GetTargetMachine(Triple(ModuleTriple));
- OwningPtr<TargetMachine> TM(Machine);
+ std::unique_ptr<TargetMachine> TM(Machine);
// Add internal analysis passes from the target machine.
if (TM.get())
TM->addAnalysisPasses(Passes);
- OwningPtr<FunctionPassManager> FPasses;
+ std::unique_ptr<FunctionPassManager> FPasses;
if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) {
FPasses.reset(new FunctionPassManager(M.get()));
- if (TD)
- FPasses->add(new DataLayout(*TD));
+ if (DL)
+ FPasses->add(new DataLayoutPass(M.get()));
if (TM.get())
TM->addAnalysisPasses(*FPasses);
@@ -706,13 +469,13 @@ int main(int argc, char **argv) {
std::string ErrorInfo;
Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
- sys::fs::F_Binary));
+ sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
}
- Passes.add(new BreakpointPrinter(Out->os()));
+ Passes.add(createBreakpointPrinter(Out->os()));
NoOutput = true;
}
@@ -764,7 +527,9 @@ int main(int argc, char **argv) {
const PassInfo *PassInf = PassList[i];
Pass *P = 0;
- if (PassInf->getNormalCtor())
+ if (PassInf->getTargetMachineCtor())
+ P = PassInf->getTargetMachineCtor()(TM.get());
+ else if (PassInf->getNormalCtor())
P = PassInf->getNormalCtor()();
else
errs() << argv[0] << ": cannot create pass: "
@@ -776,29 +541,29 @@ int main(int argc, char **argv) {
if (AnalyzeOnly) {
switch (Kind) {
case PT_BasicBlock:
- Passes.add(new BasicBlockPassPrinter(PassInf, Out->os()));
+ Passes.add(createBasicBlockPassPrinter(PassInf, Out->os(), Quiet));
break;
case PT_Region:
- Passes.add(new RegionPassPrinter(PassInf, Out->os()));
+ Passes.add(createRegionPassPrinter(PassInf, Out->os(), Quiet));
break;
case PT_Loop:
- Passes.add(new LoopPassPrinter(PassInf, Out->os()));
+ Passes.add(createLoopPassPrinter(PassInf, Out->os(), Quiet));
break;
case PT_Function:
- Passes.add(new FunctionPassPrinter(PassInf, Out->os()));
+ Passes.add(createFunctionPassPrinter(PassInf, Out->os(), Quiet));
break;
case PT_CallGraphSCC:
- Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os()));
+ Passes.add(createCallGraphPassPrinter(PassInf, Out->os(), Quiet));
break;
default:
- Passes.add(new ModulePassPrinter(PassInf, Out->os()));
+ Passes.add(createModulePassPrinter(PassInf, Out->os(), Quiet));
break;
}
}
}
if (PrintEachXForm)
- Passes.add(createPrintModulePass(&errs()));
+ Passes.add(createPrintModulePass(errs()));
}
// If -std-compile-opts was specified at the end of the pass list, add them.
@@ -841,7 +606,7 @@ int main(int argc, char **argv) {
// Write bitcode or assembly to the output as the last step...
if (!NoOutput && !AnalyzeOnly) {
if (OutputAssembly)
- Passes.add(createPrintModulePass(&Out->os()));
+ Passes.add(createPrintModulePass(Out->os()));
else
Passes.add(createBitcodeWriterPass(Out->os()));
}
diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt
index 8d9d652..5e63dfb 100644
--- a/tools/yaml2obj/CMakeLists.txt
+++ b/tools/yaml2obj/CMakeLists.txt
@@ -1,9 +1,10 @@
-set(LLVM_LINK_COMPONENTS object)
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ )
add_llvm_utility(yaml2obj
yaml2obj.cpp
yaml2coff.cpp
yaml2elf.cpp
)
-
-target_link_libraries(yaml2obj LLVMSupport)
diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp
index c757eb6..a0ede24 100644
--- a/tools/yaml2obj/yaml2coff.cpp
+++ b/tools/yaml2obj/yaml2coff.cpp
@@ -14,6 +14,7 @@
#include "yaml2obj.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
@@ -153,13 +154,22 @@ static bool layoutCOFF(COFFParser &CP) {
for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
e = CP.Obj.Symbols.end();
i != e; ++i) {
- unsigned AuxBytes = i->AuxiliaryData.binary_size();
- if (AuxBytes % COFF::SymbolSize != 0) {
- errs() << "AuxiliaryData size not a multiple of symbol size!\n";
- return false;
- }
- i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize;
- NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols;
+ uint32_t NumberOfAuxSymbols = 0;
+ if (i->FunctionDefinition)
+ NumberOfAuxSymbols += 1;
+ if (i->bfAndefSymbol)
+ NumberOfAuxSymbols += 1;
+ if (i->WeakExternal)
+ NumberOfAuxSymbols += 1;
+ if (!i->File.empty())
+ NumberOfAuxSymbols +=
+ (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
+ if (i->SectionDefinition)
+ NumberOfAuxSymbols += 1;
+ if (i->CLRToken)
+ NumberOfAuxSymbols += 1;
+ i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols;
+ NumberOfSymbols += 1 + NumberOfAuxSymbols;
}
// Store all the allocated start addresses in the header.
@@ -194,6 +204,24 @@ binary_le_impl<value_type> binary_le(value_type V) {
return binary_le_impl<value_type>(V);
}
+template <size_t NumBytes>
+struct zeros_impl {
+ zeros_impl() {}
+};
+
+template <size_t NumBytes>
+raw_ostream &operator<<(raw_ostream &OS, const zeros_impl<NumBytes> &) {
+ char Buffer[NumBytes];
+ memset(Buffer, 0, sizeof(Buffer));
+ OS.write(Buffer, sizeof(Buffer));
+ return OS;
+}
+
+template <typename T>
+zeros_impl<sizeof(T)> zeros(const T &) {
+ return zeros_impl<sizeof(T)>();
+}
+
bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
OS << binary_le(CP.Obj.Header.Machine)
<< binary_le(CP.Obj.Header.NumberOfSections)
@@ -253,7 +281,45 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
<< binary_le(i->Header.Type)
<< binary_le(i->Header.StorageClass)
<< binary_le(i->Header.NumberOfAuxSymbols);
- i->AuxiliaryData.writeAsBinary(OS);
+
+ if (i->FunctionDefinition)
+ OS << binary_le(i->FunctionDefinition->TagIndex)
+ << binary_le(i->FunctionDefinition->TotalSize)
+ << binary_le(i->FunctionDefinition->PointerToLinenumber)
+ << binary_le(i->FunctionDefinition->PointerToNextFunction)
+ << zeros(i->FunctionDefinition->unused);
+ if (i->bfAndefSymbol)
+ OS << zeros(i->bfAndefSymbol->unused1)
+ << binary_le(i->bfAndefSymbol->Linenumber)
+ << zeros(i->bfAndefSymbol->unused2)
+ << binary_le(i->bfAndefSymbol->PointerToNextFunction)
+ << zeros(i->bfAndefSymbol->unused3);
+ if (i->WeakExternal)
+ OS << binary_le(i->WeakExternal->TagIndex)
+ << binary_le(i->WeakExternal->Characteristics)
+ << zeros(i->WeakExternal->unused);
+ if (!i->File.empty()) {
+ uint32_t NumberOfAuxRecords =
+ (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
+ uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize;
+ uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
+ OS.write(i->File.data(), i->File.size());
+ for (uint32_t Padding = 0; Padding < NumZeros; ++Padding)
+ OS.write(0);
+ }
+ if (i->SectionDefinition)
+ OS << binary_le(i->SectionDefinition->Length)
+ << binary_le(i->SectionDefinition->NumberOfRelocations)
+ << binary_le(i->SectionDefinition->NumberOfLinenumbers)
+ << binary_le(i->SectionDefinition->CheckSum)
+ << binary_le(i->SectionDefinition->Number)
+ << binary_le(i->SectionDefinition->Selection)
+ << zeros(i->SectionDefinition->unused);
+ if (i->CLRToken)
+ OS << binary_le(i->CLRToken->AuxType)
+ << zeros(i->CLRToken->unused1)
+ << binary_le(i->CLRToken->SymbolTableIndex)
+ << zeros(i->CLRToken->unused2);
}
// Output string table.
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index d46e154..21506d9 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -134,94 +134,125 @@ 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>
class ELFState {
+ typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
+ typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
/// \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::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
- /// \brief The ELF file header.
- Elf_Ehdr &Header;
- SectionNameToIdxMap &SN2I;
+ /// \brief The future ".shstrtab" section.
+ StringTableBuilder DotShStrtab;
-public:
+ SectionNameToIdxMap SN2I;
+ const ELFYAML::Object &Doc;
+
+ bool buildSectionIndex();
+ void initELFHeader(Elf_Ehdr &Header);
+ bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
+ ContiguousBlobAccumulator &CBA);
+ void initSymtabSectionHeader(Elf_Shdr &SHeader,
+ ContiguousBlobAccumulator &CBA);
+ void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
+ StringTableBuilder &STB,
+ ContiguousBlobAccumulator &CBA);
+ void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
+ std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
+
+ // - 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 (.shstrtab) (placed last)
+ unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; }
+ unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; }
+ unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; }
+ unsigned getSectionCount() const { return Doc.Sections.size() + 4; }
- ELFState(Elf_Ehdr &Header_, ContiguousBlobAccumulator &Accum,
- unsigned DotStrtabSecNo_, SectionNameToIdxMap &SN2I_)
- : DotStrtab(), DotStrtabSecNo(DotStrtabSecNo_),
- SectionContentAccum(Accum), Header(Header_), SN2I(SN2I_) {}
+ ELFState(const ELFYAML::Object &D) : Doc(D) {}
- unsigned getDotStrTabSecNo() const { return DotStrtabSecNo; }
- StringTableBuilder &getStringTable() { return DotStrtab; }
- ContiguousBlobAccumulator &getSectionContentAccum() {
- return SectionContentAccum;
- }
- SectionNameToIdxMap &getSN2I() { return SN2I; }
+public:
+ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
};
} // 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::ELFFile<ELFT>::Elf_Sym> &Syms,
- unsigned SymbolBinding) {
- typedef typename object::ELFFile<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()) {
+void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
+ using namespace llvm::ELF;
+ zero(Header);
+ Header.e_ident[EI_MAG0] = 0x7f;
+ Header.e_ident[EI_MAG1] = 'E';
+ Header.e_ident[EI_MAG2] = 'L';
+ Header.e_ident[EI_MAG3] = 'F';
+ 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;
+ Header.e_ident[EI_OSABI] = Doc.Header.OSABI;
+ Header.e_ident[EI_ABIVERSION] = 0;
+ Header.e_type = Doc.Header.Type;
+ Header.e_machine = Doc.Header.Machine;
+ Header.e_version = EV_CURRENT;
+ Header.e_entry = Doc.Header.Entry;
+ Header.e_flags = Doc.Header.Flags;
+ Header.e_ehsize = sizeof(Elf_Ehdr);
+ Header.e_shentsize = sizeof(Elf_Shdr);
+ // Immediately following the ELF header.
+ Header.e_shoff = sizeof(Header);
+ Header.e_shnum = getSectionCount();
+ Header.e_shstrndx = getDotShStrTabSecNo();
+}
+
+template <class ELFT>
+bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
+ ContiguousBlobAccumulator &CBA) {
+ // Ensure SHN_UNDEF entry is present. An all-zero section header is a
+ // valid SHN_UNDEF entry since SHT_NULL == 0.
+ Elf_Shdr SHeader;
+ zero(SHeader);
+ SHeaders.push_back(SHeader);
+
+ for (const auto &Sec : Doc.Sections) {
+ zero(SHeader);
+ SHeader.sh_name = DotShStrtab.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 (State.getSN2I().lookupSection(Sym.Section, Index)) {
- errs() << "error: Unknown section referenced: '" << Sym.Section
- << "' by YAML symbol " << Sym.Name << ".\n";
- exit(1);
+ if (SN2I.lookupSection(Sec.Link, Index)) {
+ errs() << "error: Unknown section referenced: '" << Sec.Link
+ << "' at YAML section '" << Sec.Name << "'.\n";
+ return false;;
}
- 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);
+ SHeader.sh_link = Index;
+ }
+ SHeader.sh_info = 0;
+ SHeader.sh_addralign = Sec.AddressAlign;
+ SHeader.sh_entsize = 0;
+ SHeaders.push_back(SHeader);
}
+ return true;
}
template <class ELFT>
-static void
-handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols,
- ELFState<ELFT> &State,
- typename object::ELFFile<ELFT>::Elf_Shdr &SHeader) {
-
- typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
+ ContiguousBlobAccumulator &CBA) {
+ zero(SHeader);
+ SHeader.sh_name = DotShStrtab.addString(StringRef(".symtab"));
SHeader.sh_type = ELF::SHT_SYMTAB;
- SHeader.sh_link = State.getDotStrTabSecNo();
+ SHeader.sh_link = getDotStrTabSecNo();
// One greater than symbol table index of the last local symbol.
- SHeader.sh_info = Symbols.Local.size() + 1;
+ SHeader.sh_info = Doc.Symbols.Local.size() + 1;
SHeader.sh_entsize = sizeof(Elf_Sym);
std::vector<Elf_Sym> Syms;
@@ -231,134 +262,109 @@ handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols,
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);
+ addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
+ addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
+ addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
- ContiguousBlobAccumulator &CBA = State.getSectionContentAccum();
writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset),
makeArrayRef(Syms));
SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
}
template <class ELFT>
-static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
- using namespace llvm::ELF;
- typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
- typedef typename object::ELFFile<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';
- Header.e_ident[EI_MAG3] = 'F';
- 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;
- 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(Elf_Ehdr);
+void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
+ StringTableBuilder &STB,
+ ContiguousBlobAccumulator &CBA) {
+ zero(SHeader);
+ SHeader.sh_name = DotShStrtab.addString(Name);
+ SHeader.sh_type = ELF::SHT_STRTAB;
+ STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
+ SHeader.sh_size = STB.size();
+ SHeader.sh_addralign = 1;
+}
- // TODO: Flesh out section header support.
- // TODO: Program headers.
+template <class ELFT>
+void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
+ std::vector<Elf_Sym> &Syms,
+ unsigned SymbolBinding) {
+ for (const auto &Sym : Symbols) {
+ Elf_Sym Symbol;
+ zero(Symbol);
+ if (!Sym.Name.empty())
+ Symbol.st_name = DotStrtab.addString(Sym.Name);
+ Symbol.setBindingAndType(SymbolBinding, Sym.Type);
+ if (!Sym.Section.empty()) {
+ unsigned Index;
+ if (SN2I.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);
+ }
+}
- 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;
+template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
+ SN2I.addName(".symtab", getDotSymTabSecNo());
+ SN2I.addName(".strtab", getDotStrTabSecNo());
+ SN2I.addName(".shstrtab", getDotShStrTabSecNo());
- // 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;
+ for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
+ StringRef Name = Doc.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;
+ return false;
}
}
+ return true;
+}
- ELFState<ELFT> State(Header, CBA, DotStrtabSecNo, SN2I);
+template <class ELFT>
+int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
+ ELFState<ELFT> State(Doc);
+ if (!State.buildSectionIndex())
+ return 1;
- 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;
+ Elf_Ehdr Header;
+ State.initELFHeader(Header);
- Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
- SHeader.sh_size = Sec.Content.binary_size();
+ // TODO: Flesh out section header support.
+ // TODO: Program headers.
- 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);
- }
+ // 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);
+
+ std::vector<Elf_Shdr> SHeaders;
+ if(!State.initSectionHeaders(SHeaders, CBA))
+ return 1;
// .symtab section.
Elf_Shdr SymtabSHeader;
- zero(SymtabSHeader);
- SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab"));
- handleSymtabSectionHeader<ELFT>(Doc.Symbols, State, SymtabSHeader);
+ State.initSymtabSectionHeader(SymtabSHeader, CBA);
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);
+ State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab,
+ CBA);
SHeaders.push_back(DotStrTabSHeader);
- // Section header string table header.
- Elf_Shdr SHStrTabSHeader;
- zero(SHStrTabSHeader);
- createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA);
- SHeaders.push_back(SHStrTabSHeader);
+ // .shstrtab string table header.
+ Elf_Shdr ShStrTabSHeader;
+ State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab,
+ CBA);
+ SHeaders.push_back(ShStrTabSHeader);
OS.write((const char *)&Header, sizeof(Header));
writeArrayData(OS, makeArrayRef(SHeaders));
@@ -389,13 +395,13 @@ int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
typedef ELFType<support::big, 4, false> BE32;
if (is64Bit(Doc)) {
if (isLittleEndian(Doc))
- return writeELF<LE64>(outs(), Doc);
+ return ELFState<LE64>::writeELF(outs(), Doc);
else
- return writeELF<BE64>(outs(), Doc);
+ return ELFState<BE64>::writeELF(outs(), Doc);
} else {
if (isLittleEndian(Doc))
- return writeELF<LE32>(outs(), Doc);
+ return ELFState<LE32>::writeELF(outs(), Doc);
else
- return writeELF<BE32>(outs(), Doc);
+ return ELFState<BE32>::writeELF(outs(), Doc);
}
}
diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp
index 6d1107c..cc0fecc 100644
--- a/tools/yaml2obj/yaml2obj.cpp
+++ b/tools/yaml2obj/yaml2obj.cpp
@@ -15,7 +15,6 @@
//===----------------------------------------------------------------------===//
#include "yaml2obj.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -57,7 +56,7 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- OwningPtr<MemoryBuffer> Buf;
+ std::unique_ptr<MemoryBuffer> Buf;
if (MemoryBuffer::getFileOrSTDIN(Input, Buf))
return 1;
if (Format == YOF_COFF) {