diff options
Diffstat (limited to 'tools')
68 files changed, 2008 insertions, 1083 deletions
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 2d1b903..cecccbe 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -70,12 +70,16 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout, unsigned memlimit, bool use_valgrind, LLVMContext& ctxt) : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), - Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), - run_find_bugs(find_bugs), Timeout(timeout), + Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr), + gcc(nullptr), run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit), UseValgrind(use_valgrind) {} BugDriver::~BugDriver() { delete Program; + if (Interpreter != SafeInterpreter) + delete Interpreter; + delete SafeInterpreter; + delete gcc; } @@ -112,18 +116,18 @@ Module *llvm::ParseInputFile(const std::string &Filename, // parsed), and false on success. // bool BugDriver::addSources(const std::vector<std::string> &Filenames) { - assert(Program == 0 && "Cannot call addSources multiple times!"); + assert(!Program && "Cannot call addSources multiple times!"); assert(!Filenames.empty() && "Must specify at least on input filename!"); // Load the first input file. Program = ParseInputFile(Filenames[0], Context); - if (Program == 0) return true; + if (!Program) return true; outs() << "Read input file : '" << Filenames[0] << "'\n"; for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { std::unique_ptr<Module> M(ParseInputFile(Filenames[i], Context)); - if (M.get() == 0) return true; + if (!M.get()) return true; outs() << "Linking in input file: '" << Filenames[i] << "'\n"; std::string ErrorMessage; diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index c01bbe5..3169d29 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -202,7 +202,7 @@ public: const std::string &BitcodeFile = "", const std::string &SharedObj = "", bool RemoveBitcode = false, - std::string *Error = 0) const; + std::string *Error = nullptr) const; /// EmitProgressBitcode - This function is used to output M to a file named /// "bugpoint-ID.bc". @@ -244,7 +244,7 @@ public: /// this method will never return null. Module *runPassesOn(Module *M, const std::vector<std::string> &Passes, bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0, - const char * const *ExtraArgs = NULL); + const char * const *ExtraArgs = nullptr); /// runPasses - Run the specified passes on Program, outputting a bitcode /// file and writting the filename into OutputFile if successful. If the @@ -259,7 +259,7 @@ public: const std::vector<std::string> &PassesToRun, std::string &OutputFilename, bool DeleteOutput = false, bool Quiet = false, unsigned NumExtraArgs = 0, - const char * const *ExtraArgs = NULL) const; + const char * const *ExtraArgs = nullptr) const; /// runManyPasses - Take the specified pass list and create different /// combinations of passes to compile the program with. Compile the program with diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index bdaa6c9..8bd61b3 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -63,7 +63,7 @@ ReducePassList::doTest(std::vector<std::string> &Prefix, std::vector<std::string> &Suffix, std::string &Error) { std::string PrefixOutput; - Module *OrigProgram = 0; + Module *OrigProgram = nullptr; if (!Prefix.empty()) { outs() << "Checking to see if these passes crash: " << getPassesString(Prefix) << ": "; @@ -73,7 +73,7 @@ ReducePassList::doTest(std::vector<std::string> &Prefix, OrigProgram = BD.Program; BD.Program = ParseInputFile(PrefixOutput, BD.getContext()); - if (BD.Program == 0) { + if (BD.Program == nullptr) { errs() << BD.getToolName() << ": Error reading bitcode file '" << PrefixOutput << "'!\n"; exit(1); @@ -149,7 +149,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer() && !GVSet.count(I)) { - I->setInitializer(0); + I->setInitializer(nullptr); I->setLinkage(GlobalValue::ExternalLinkage); } @@ -410,6 +410,7 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> // Verify that this is still valid. PassManager Passes; Passes.add(createVerifierPass()); + Passes.add(createDebugInfoVerifierPass()); Passes.run(*M); // Try running on the hacked up program... @@ -446,7 +447,7 @@ static bool DebugACrash(BugDriver &BD, for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) { - I->setInitializer(0); + I->setInitializer(nullptr); I->setLinkage(GlobalValue::ExternalLinkage); DeletedInit = true; } diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 609de03..5ed7d2c 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -145,7 +145,7 @@ bool BugDriver::initializeExecutionEnvironment() { // Create an instance of the AbstractInterpreter interface as specified on // the command line - SafeInterpreter = 0; + SafeInterpreter = nullptr; std::string Message; switch (InterpreterSel) { @@ -256,7 +256,7 @@ bool BugDriver::initializeExecutionEnvironment() { if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } // If there was an error creating the selected interpreter, quit with error. - return Interpreter == 0; + return Interpreter == nullptr; } /// compileProgram - Try to compile the specified module, returning false and @@ -298,7 +298,7 @@ std::string BugDriver::executeProgram(const Module *Program, const std::string &SharedObj, AbstractInterpreter *AI, std::string *Error) const { - if (AI == 0) AI = Interpreter; + if (!AI) AI = Interpreter; assert(AI && "Interpreter should have been created already!"); bool CreatedBitcode = false; if (BitcodeFile.empty()) { @@ -445,7 +445,7 @@ bool BugDriver::diffProgram(const Module *Program, std::string *ErrMsg) const { // Execute the program, generating an output file... std::string Output( - executeProgram(Program, "", BitcodeFile, SharedObject, 0, ErrMsg)); + executeProgram(Program, "", BitcodeFile, SharedObject, nullptr, ErrMsg)); if (!ErrMsg->empty()) return false; diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 8bcae8a..38cdf24 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -34,6 +34,8 @@ #include <set> using namespace llvm; +#define DEBUG_TYPE "bugpoint" + namespace llvm { bool DisableSimplifyCFG = false; extern cl::opt<std::string> OutputPrefix; @@ -49,7 +51,7 @@ namespace { Function* globalInitUsesExternalBA(GlobalVariable* GV) { if (!GV->hasInitializer()) - return 0; + return nullptr; Constant *I = GV->getInitializer(); @@ -76,7 +78,7 @@ namespace { Todo.push_back(C); } } - return 0; + return nullptr; } } // end anonymous namespace @@ -148,7 +150,7 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) { CleanupPasses.push_back("deadargelim"); Module *New = runPassesOn(M, CleanupPasses); - if (New == 0) { + if (!New) { errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n"; return M; } @@ -165,11 +167,11 @@ Module *BugDriver::ExtractLoop(Module *M) { LoopExtractPasses.push_back("loop-extract-single"); Module *NewM = runPassesOn(M, LoopExtractPasses); - if (NewM == 0) { + if (!NewM) { outs() << "*** Loop extraction failed: "; EmitProgressBitcode(M, "loopextraction", true); outs() << "*** Sorry. :( Please report a bug!\n"; - return 0; + return nullptr; } // Check to see if we created any new functions. If not, no loops were @@ -178,7 +180,7 @@ Module *BugDriver::ExtractLoop(Module *M) { static unsigned NumExtracted = 32; if (M->size() == NewM->size() || --NumExtracted == 0) { delete NewM; - return 0; + return nullptr; } else { assert(M->size() < NewM->size() && "Loop extract removed functions?"); Module::iterator MI = NewM->begin(); @@ -335,10 +337,10 @@ llvm::SplitFunctionsOutOfModule(Module *M, << "' and from test function '" << TestFn->getName() << "'.\n"; exit(1); } - I->setInitializer(0); // Delete the initializer to make it external + I->setInitializer(nullptr); // Delete the initializer to make it external } else { // If we keep it in the safe module, then delete it in the test module - GV->setInitializer(0); + GV->setInitializer(nullptr); } } @@ -370,7 +372,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const outs() << "*** Basic Block extraction failed!\n"; errs() << "Error creating temporary file: " << EC.message() << "\n"; EmitProgressBitcode(M, "basicblockextractfail", true); - return 0; + return nullptr; } sys::RemoveFileOnSignal(Filename); @@ -389,7 +391,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const errs() << "Error writing list of blocks to not extract\n"; EmitProgressBitcode(M, "basicblockextractfail", true); BlocksToNotExtractFile.os().clear_error(); - return 0; + return nullptr; } BlocksToNotExtractFile.keep(); @@ -403,7 +405,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const sys::fs::remove(Filename.c_str()); - if (Ret == 0) { + if (!Ret) { outs() << "*** Basic Block extraction failed, please report a bug!\n"; EmitProgressBitcode(M, "basicblockextractfail", true); } diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp index e2941f6..a0c859b 100644 --- a/tools/bugpoint/FindBugs.cpp +++ b/tools/bugpoint/FindBugs.cpp @@ -45,7 +45,7 @@ bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, return false; } - srand(time(NULL)); + srand(time(nullptr)); unsigned num = 1; while(1) { diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index fecae60..f5936ac 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -235,7 +235,7 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, if (!Error.empty()) { // Delete the linked module delete M1; - return NULL; + return nullptr; } return M1; } @@ -592,7 +592,7 @@ static bool ExtractBlocks(BugDriver &BD, MiscompiledFunctions, VMap); Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract); - if (Extracted == 0) { + if (!Extracted) { // Weird, extraction should have worked. errs() << "Nondeterministic problem extracting blocks??\n"; delete ProgClone; @@ -845,7 +845,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, Safe->getOrInsertFunction("getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), Type::getInt8PtrTy(Safe->getContext()), - (Type *)0); + (Type *)nullptr); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index f91f493..b2722e6 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -36,6 +36,8 @@ using namespace llvm; +#define DEBUG_TYPE "bugpoint" + namespace llvm { extern cl::opt<std::string> OutputPrefix; } @@ -194,7 +196,7 @@ bool BugDriver::runPasses(Module *Program, Args.push_back(InputFilename.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) Args.push_back(*ExtraArgs); - Args.push_back(0); + Args.push_back(nullptr); DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = Args.size()-1; i != e; ++i) @@ -210,12 +212,12 @@ bool BugDriver::runPasses(Module *Program, // Redirect stdout and stderr to nowhere if SilencePasses is given StringRef Nowhere; - const StringRef *Redirects[3] = {0, &Nowhere, &Nowhere}; + const StringRef *Redirects[3] = {nullptr, &Nowhere, &Nowhere}; std::string ErrMsg; - int result = sys::ExecuteAndWait(Prog, Args.data(), 0, - (SilencePasses ? Redirects : 0), Timeout, - MemoryLimit, &ErrMsg); + int result = sys::ExecuteAndWait(Prog, Args.data(), nullptr, + (SilencePasses ? Redirects : nullptr), + Timeout, MemoryLimit, &ErrMsg); // If we are supposed to delete the bitcode file or if the passes crashed, // remove it now. This may fail if the file was never created, but that's ok. @@ -262,11 +264,11 @@ Module *BugDriver::runPassesOn(Module *M, EmitProgressBitcode(M, "pass-error", false); exit(debugOptimizerCrash()); } - return 0; + return nullptr; } Module *Ret = ParseInputFile(BitcodeResult, Context); - if (Ret == 0) { + if (!Ret) { errs() << getToolName() << ": Error reading bitcode file '" << BitcodeResult << "'!\n"; exit(1); diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index f0fb4bf..c481b03 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" #include "llvm/Config/config.h" // for HAVE_LINK_R #include "llvm/Support/CommandLine.h" @@ -24,6 +23,8 @@ #include <sstream> using namespace llvm; +#define DEBUG_TYPE "toolrunner" + namespace llvm { cl::opt<bool> SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); @@ -61,7 +62,7 @@ static int RunProgramWithTimeout(StringRef ProgramPath, StringRef StdErrFile, unsigned NumSeconds = 0, unsigned MemoryLimit = 0, - std::string *ErrMsg = 0) { + std::string *ErrMsg = nullptr) { const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; #if 0 // For debug purposes @@ -73,7 +74,7 @@ static int RunProgramWithTimeout(StringRef ProgramPath, } #endif - return sys::ExecuteAndWait(ProgramPath, Args, 0, Redirects, + return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds, MemoryLimit, ErrMsg); } @@ -102,7 +103,7 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, #endif // Run the program remotely with the remote client - int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, 0, + int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr, Redirects, NumSeconds, MemoryLimit); // Has the remote client fail? @@ -218,7 +219,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode, // Add optional parameters to the running program from Argv for (unsigned i=0, e = Args.size(); i != e; ++i) LLIArgs.push_back(Args[i].c_str()); - LLIArgs.push_back(0); + LLIArgs.push_back(nullptr); outs() << "<lli>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; @@ -276,7 +277,7 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, } Message = "Cannot find `lli' in executable directory!\n"; - return 0; + return nullptr; } //===---------------------------------------------------------------------===// @@ -327,7 +328,7 @@ void CustomCompiler::compileProgram(const std::string &Bitcode, for (std::size_t i = 0; i < CompilerArgs.size(); ++i) ProgramArgs.push_back(CompilerArgs.at(i).c_str()); ProgramArgs.push_back(Bitcode.c_str()); - ProgramArgs.push_back(0); + ProgramArgs.push_back(nullptr); // Add optional parameters to the running program from Argv for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) @@ -384,7 +385,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); ProgramArgs.push_back(Bitcode.c_str()); - ProgramArgs.push_back(0); + ProgramArgs.push_back(nullptr); // Add optional parameters to the running program from Argv for (unsigned i = 0, e = Args.size(); i != e; ++i) @@ -447,7 +448,7 @@ AbstractInterpreter *AbstractInterpreter::createCustomCompiler( std::vector<std::string> Args; lexCommand(Message, CompileCommandLine, CmdPath, Args); if (CmdPath.empty()) - return 0; + return nullptr; return new CustomCompiler(CmdPath, Args); } @@ -463,7 +464,7 @@ AbstractInterpreter *AbstractInterpreter::createCustomExecutor( std::vector<std::string> Args; lexCommand(Message, ExecCommandLine, CmdPath, Args); if (CmdPath.empty()) - return 0; + return nullptr; return new CustomExecutor(CmdPath, Args); } @@ -498,7 +499,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, if (UseIntegratedAssembler) LLCArgs.push_back("-filetype=obj"); - LLCArgs.push_back (0); + LLCArgs.push_back (nullptr); outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); outs().flush(); @@ -558,7 +559,7 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC); if (LLCPath.empty()) { Message = "Cannot find `llc' in executable directory!\n"; - return 0; + return nullptr; } GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); @@ -624,7 +625,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, // Add optional parameters to the running program from Argv for (unsigned i=0, e = Args.size(); i != e; ++i) JITArgs.push_back(Args[i].c_str()); - JITArgs.push_back(0); + JITArgs.push_back(nullptr); outs() << "<jit>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; @@ -650,7 +651,7 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, } Message = "Cannot find `lli' in executable directory!\n"; - return 0; + return nullptr; } //===---------------------------------------------------------------------===// @@ -736,7 +737,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, #endif if (TargetTriple.getArch() == Triple::sparc) GCCArgs.push_back("-mcpu=v9"); - GCCArgs.push_back(0); // NULL terminator + GCCArgs.push_back(nullptr); // NULL terminator outs() << "<gcc>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; @@ -785,7 +786,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, // Add optional parameters to the running program from Argv for (unsigned i = 0, e = Args.size(); i != e; ++i) ProgramArgs.push_back(Args[i].c_str()); - ProgramArgs.push_back(0); // NULL terminator + ProgramArgs.push_back(nullptr); // NULL terminator // Now that we have a binary, run it! outs() << "<program>"; outs().flush(); @@ -884,7 +885,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, // command line, so this should be safe. for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) GCCArgs.push_back(ArgsForGCC[i].c_str()); - GCCArgs.push_back(0); // NULL terminator + GCCArgs.push_back(nullptr); // NULL terminator @@ -909,7 +910,7 @@ GCC *GCC::create(std::string &Message, std::string GCCPath = sys::FindProgramByName(GCCBinary); if (GCCPath.empty()) { Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; - return 0; + return nullptr; } std::string RemoteClientPath; diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 38a5835..6e7b95c 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -63,7 +63,7 @@ public: FileType fileType, const std::string &InputFile, const std::string &OutputFile, - std::string *Error = 0, + std::string *Error = nullptr, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), unsigned Timeout = 0, @@ -89,15 +89,17 @@ class AbstractInterpreter { public: static LLC *createLLC(const char *Argv0, std::string &Message, const std::string &GCCBinary, - const std::vector<std::string> *Args = 0, - const std::vector<std::string> *GCCArgs = 0, + const std::vector<std::string> *Args = nullptr, + const std::vector<std::string> *GCCArgs = nullptr, bool UseIntegratedAssembler = false); - static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message, - const std::vector<std::string> *Args=0); + static AbstractInterpreter* + createLLI(const char *Argv0, std::string &Message, + const std::vector<std::string> *Args = nullptr); - static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, - const std::vector<std::string> *Args=0); + static AbstractInterpreter* + createJIT(const char *Argv0, std::string &Message, + const std::vector<std::string> *Args = nullptr); static AbstractInterpreter* createCustomCompiler(std::string &Message, diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 5c03b41..c7dae0f 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -99,7 +99,7 @@ namespace { class AddToDriver : public FunctionPassManager { BugDriver &D; public: - AddToDriver(BugDriver &_D) : FunctionPassManager(0), D(_D) {} + AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {} void add(Pass *P) override { const void *ID = P->getPassID(); diff --git a/tools/llc/Android.mk b/tools/llc/Android.mk index 391ba39..f9c87fe 100644 --- a/tools/llc/Android.mk +++ b/tools/llc/Android.mk @@ -56,7 +56,8 @@ llvm_llc_STATIC_LIBRARIES := \ libLLVMAnalysis \ libLLVMTarget \ libLLVMCore \ - libLLVMSupport + libLLVMSupport \ + libLLVMObject llvm_llc_arm64_STATIC_LIBRARIES := \ libLLVMARM64Info \ diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 8fbdc49..09ff461 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -28,6 +28,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" @@ -74,15 +75,24 @@ OptLevel("O", static cl::opt<std::string> TargetTriple("mtriple", cl::desc("Override target triple for module")); -cl::opt<bool> NoVerify("disable-verify", cl::Hidden, - cl::desc("Do not verify input module")); +static cl::opt<bool> NoVerify("disable-verify", cl::Hidden, + cl::desc("Do not verify input module")); -cl::opt<bool> -DisableSimplifyLibCalls("disable-simplify-libcalls", - cl::desc("Disable simplify-libcalls"), - cl::init(false)); +static cl::opt<bool> DisableSimplifyLibCalls("disable-simplify-libcalls", + cl::desc("Disable simplify-libcalls")); -static int compileModule(char**, LLVMContext&); +static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden, + cl::desc("Show encoding in .s output")); + +static cl::opt<bool> EnableDwarfDirectory( + "enable-dwarf-directory", cl::Hidden, + cl::desc("Use .file directives with an explicit directory.")); + +static cl::opt<bool> AsmVerbose("asm-verbose", + cl::desc("Add comments to directives."), + cl::init(true)); + +static int compileModule(char **, LLVMContext &); // GetFileNameRoot - Helper function to get the basename of a filename. static inline std::string @@ -157,7 +167,7 @@ static tool_output_file *GetOutputStream(const char *TargetName, if (!error.empty()) { errs() << error << '\n'; delete FDOut; - return 0; + return nullptr; } return FDOut; @@ -207,17 +217,23 @@ static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; std::unique_ptr<Module> M; - Module *mod = 0; + Module *mod = nullptr; Triple TheTriple; bool SkipModule = MCPU == "help" || (!MAttrs.empty() && MAttrs.front() == "help"); + // If user asked for the 'native' CPU, autodetect here. If autodection fails, + // this will set the CPU to an empty string which tells the target to + // pick a basic default. + if (MCPU == "native") + MCPU = sys::getHostCPUName(); + // If user just wants to list available options, skip module loading if (!SkipModule) { M.reset(ParseIRFile(InputFilename, Err, Context)); mod = M.get(); - if (mod == 0) { + if (mod == nullptr) { Err.print(argv[0], errs()); return 1; } @@ -265,19 +281,23 @@ static int compileModule(char **argv, LLVMContext &Context) { TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); Options.DisableIntegratedAS = NoIntegratedAssembler; + Options.MCOptions.ShowMCEncoding = ShowMCEncoding; + Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; + Options.MCOptions.AsmVerbose = AsmVerbose; 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 (DisableCFI) - Target.setMCUseCFI(false); + // If we don't have a module then just exit now. We do this down + // here since the CPU/Feature help is underneath the target machine + // creation. + if (SkipModule) + return 0; - if (EnableDwarfDirectory) - Target.setMCUseDwarfDirectory(true); + assert(mod && "Should have exited if we didn't have a module!"); + TargetMachine &Target = *target.get(); if (GenerateSoftFloatCalls) FloatABIForCalls = FloatABI::Soft; @@ -301,22 +321,16 @@ static int compileModule(char **argv, LLVMContext &Context) { mod->setDataLayout(DL); PM.add(new DataLayoutPass(mod)); - // Override default to generate verbose assembly. - Target.setAsmVerbosityDefault(true); - - if (RelaxAll) { - if (FileType != TargetMachine::CGFT_ObjectFile) - errs() << argv[0] + if (RelaxAll.getNumOccurrences() > 0 && + FileType != TargetMachine::CGFT_ObjectFile) + errs() << argv[0] << ": warning: ignoring -mc-relax-all because filetype != obj"; - else - Target.setMCRelaxAll(true); - } { formatted_raw_ostream FOS(Out->os()); - AnalysisID StartAfterID = 0; - AnalysisID StopAfterID = 0; + AnalysisID StartAfterID = nullptr; + AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); if (!StartAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StartAfter); diff --git a/tools/lli/RemoteMemoryManager.cpp b/tools/lli/RemoteMemoryManager.cpp index e9f4d53..200ab75 100644 --- a/tools/lli/RemoteMemoryManager.cpp +++ b/tools/lli/RemoteMemoryManager.cpp @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "lli" #include "RemoteMemoryManager.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectImage.h" @@ -21,6 +20,8 @@ using namespace llvm; +#define DEBUG_TYPE "lli" + RemoteMemoryManager::~RemoteMemoryManager() { for (SmallVector<Allocation, 2>::iterator I = AllocatedSections.begin(), E = AllocatedSections.end(); @@ -178,16 +179,16 @@ void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexp void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); } uint8_t *RemoteMemoryManager::getGOTBase() const { llvm_unreachable("Unexpected!"); - return 0; + return nullptr; } uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){ llvm_unreachable("Unexpected!"); - return 0; + return nullptr; } uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize, unsigned Alignment) { llvm_unreachable("Unexpected!"); - return 0; + return nullptr; } void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart, uint8_t *FunctionEnd) { @@ -195,11 +196,11 @@ void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionSt } uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { llvm_unreachable("Unexpected!"); - return 0; + return nullptr; } uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) { llvm_unreachable("Unexpected!"); - return 0; + return nullptr; } void RemoteMemoryManager::deallocateFunctionBody(void *Body) { llvm_unreachable("Unexpected!"); diff --git a/tools/lli/RemoteMemoryManager.h b/tools/lli/RemoteMemoryManager.h index 11f600f..cf5d7c6 100644 --- a/tools/lli/RemoteMemoryManager.h +++ b/tools/lli/RemoteMemoryManager.h @@ -63,7 +63,7 @@ private: RemoteTarget *Target; public: - RemoteMemoryManager() : Target(NULL) {} + RemoteMemoryManager() : Target(nullptr) {} virtual ~RemoteMemoryManager(); uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp index 55fc064..850fdc5 100644 --- a/tools/lli/RemoteTarget.cpp +++ b/tools/lli/RemoteTarget.cpp @@ -30,9 +30,9 @@ using namespace llvm; bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address) { - sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL; + sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : nullptr; sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg); - if (Mem.base() == NULL) + if (Mem.base() == nullptr) return false; if ((uintptr_t)Mem.base() % Alignment) { ErrorMsg = "unable to allocate sufficiently aligned memory"; diff --git a/tools/lli/RemoteTargetExternal.cpp b/tools/lli/RemoteTargetExternal.cpp index c1bc8df..fe46248 100644 --- a/tools/lli/RemoteTargetExternal.cpp +++ b/tools/lli/RemoteTargetExternal.cpp @@ -26,6 +26,8 @@ using namespace llvm; +#define DEBUG_TYPE "lli" + bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address) { DEBUG(dbgs() << "Message [allocate space] size: " << Size << diff --git a/tools/lli/Unix/RPCChannel.inc b/tools/lli/Unix/RPCChannel.inc index 4d245d6..6a9ae14 100644 --- a/tools/lli/Unix/RPCChannel.inc +++ b/tools/lli/Unix/RPCChannel.inc @@ -60,7 +60,7 @@ bool RPCChannel::createServer() { } // Execute the child process. - char *args[1] = { NULL }; + char *args[1] = { nullptr }; int rc = execv(ChildName.c_str(), args); if (rc != 0) perror("Error executing child process: "); @@ -84,7 +84,7 @@ bool RPCChannel::createClient() { return true; } -void RPCChannel::Wait() { wait(NULL); } +void RPCChannel::Wait() { wait(nullptr); } static bool CheckError(int rc, size_t Size, const char *Desc) { if (rc < 0) { diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index c0c0f9d..4cde105 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -13,7 +13,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "lli" #include "llvm/IR/LLVMContext.h" #include "RemoteMemoryManager.h" #include "RemoteTarget.h" @@ -64,6 +63,8 @@ using namespace llvm; +#define DEBUG_TYPE "lli" + namespace { cl::opt<std::string> InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-")); @@ -282,13 +283,13 @@ public: const std::string ModuleID = M->getModuleIdentifier(); std::string CacheName; if (!getCacheFilename(ModuleID, CacheName)) - return NULL; + return nullptr; // 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; + return nullptr; // 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 @@ -319,8 +320,8 @@ private: } }; -static ExecutionEngine *EE = 0; -static LLIObjectCache *CacheManager = 0; +static ExecutionEngine *EE = nullptr; +static LLIObjectCache *CacheManager = nullptr; static void do_shutdown() { // Cygwin-1.5 invokes DLL's dtors before atexit handler. @@ -449,7 +450,7 @@ int main(int argc, char **argv, char * const *envp) { Mod->setTargetTriple(Triple::normalize(TargetTriple)); // Enable MCJIT if desired. - RTDyldMemoryManager *RTDyldMM = 0; + RTDyldMemoryManager *RTDyldMM = nullptr; if (UseMCJIT && !ForceInterpreter) { builder.setUseMCJIT(true); if (RemoteMCJIT) @@ -462,7 +463,7 @@ int main(int argc, char **argv, char * const *envp) { errs() << "error: Remote process execution requires -use-mcjit\n"; exit(1); } - builder.setJITMemoryManager(ForceInterpreter ? 0 : + builder.setJITMemoryManager(ForceInterpreter ? nullptr : JITMemoryManager::CreateDefaultMemManager()); } @@ -533,7 +534,7 @@ int main(int argc, char **argv, char * const *envp) { Err.print(argv[0], errs()); return 1; } - EE->addObjectFile(Obj.get()); + EE->addObjectFile(std::unique_ptr<object::ObjectFile>(Obj.get())); } for (unsigned i = 0, e = ExtraArchives.size(); i != e; ++i) { diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 047f54e..ed7291e 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -516,7 +516,7 @@ computeInsertAction(ArchiveOperation Operation, // We could try to optimize this to a fstat, but it is not a common // operation. sys::fs::file_status Status; - failIfError(sys::fs::status(*MI, Status)); + failIfError(sys::fs::status(*MI, Status), *MI); if (Status.getLastModificationTime() < I->getLastModified()) { if (PosName.empty()) return IA_AddOldMember; @@ -856,7 +856,7 @@ static void performWriteOperation(ArchiveOperation Operation, Output.keep(); Out.close(); sys::fs::rename(TemporaryOutput, ArchiveName); - TemporaryOutput = NULL; + TemporaryOutput = nullptr; } static void createSymbolTable(object::Archive *OldArchive) { @@ -969,6 +969,6 @@ static int performOperation(ArchiveOperation Operation) { } } - performOperation(Operation, NULL); + performOperation(Operation, nullptr); return 0; } diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 7583b12..007241c 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -94,7 +95,7 @@ int main(int argc, char **argv) { // Parse the file now... SMDiagnostic Err; std::unique_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context)); - if (M.get() == 0) { + if (!M.get()) { Err.print(argv[0], errs()); return 1; } diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 9e17783..dfdaa03 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -84,7 +84,7 @@ static const char *GetBlockName(unsigned BlockID, if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { if (BlockID == bitc::BLOCKINFO_BLOCK_ID) return "BLOCKINFO_BLOCK"; - return 0; + return nullptr; } // Check to see if we have a blockinfo record for this block, with a name. @@ -95,10 +95,10 @@ static const char *GetBlockName(unsigned BlockID, } - if (CurStreamType != LLVMIRBitstream) return 0; + if (CurStreamType != LLVMIRBitstream) return nullptr; switch (BlockID) { - default: return 0; + default: return nullptr; case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK"; case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK"; case bitc::PARAMATTR_GROUP_BLOCK_ID: return "PARAMATTR_GROUP_BLOCK_ID"; @@ -120,13 +120,13 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::BLOCKINFO_CODE_SETBID: return "SETBID"; case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME"; case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME"; } } - return 0; + return nullptr; } // Check to see if we have a blockinfo record for this record, with a name. @@ -138,13 +138,13 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } - if (CurStreamType != LLVMIRBitstream) return 0; + if (CurStreamType != LLVMIRBitstream) return nullptr; switch (BlockID) { - default: return 0; + default: return nullptr; case bitc::MODULE_BLOCK_ID: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::MODULE_CODE_VERSION: return "VERSION"; case bitc::MODULE_CODE_TRIPLE: return "TRIPLE"; case bitc::MODULE_CODE_DATALAYOUT: return "DATALAYOUT"; @@ -159,14 +159,14 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } case bitc::PARAMATTR_BLOCK_ID: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::PARAMATTR_CODE_ENTRY_OLD: return "ENTRY"; case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY"; case bitc::PARAMATTR_GRP_CODE_ENTRY: return "ENTRY"; } case bitc::TYPE_BLOCK_ID_NEW: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::TYPE_CODE_NUMENTRY: return "NUMENTRY"; case bitc::TYPE_CODE_VOID: return "VOID"; case bitc::TYPE_CODE_FLOAT: return "FLOAT"; @@ -189,7 +189,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::CONSTANTS_BLOCK_ID: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::CST_CODE_SETTYPE: return "SETTYPE"; case bitc::CST_CODE_NULL: return "NULL"; case bitc::CST_CODE_UNDEF: return "UNDEF"; @@ -215,7 +215,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } case bitc::FUNCTION_BLOCK_ID: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::FUNC_CODE_DECLAREBLOCKS: return "DECLAREBLOCKS"; case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP"; @@ -249,18 +249,18 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } case bitc::VALUE_SYMTAB_BLOCK_ID: switch (CodeID) { - default: return 0; + default: return nullptr; case bitc::VST_CODE_ENTRY: return "ENTRY"; case bitc::VST_CODE_BBENTRY: return "BBENTRY"; } case bitc::METADATA_ATTACHMENT_ID: switch(CodeID) { - default:return 0; + default:return nullptr; case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT"; } case bitc::METADATA_BLOCK_ID: switch(CodeID) { - default:return 0; + default:return nullptr; case bitc::METADATA_STRING: return "METADATA_STRING"; case bitc::METADATA_NAME: return "METADATA_NAME"; case bitc::METADATA_KIND: return "METADATA_KIND"; @@ -270,7 +270,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, } case bitc::USELIST_BLOCK_ID: switch(CodeID) { - default:return 0; + default:return nullptr; case bitc::USELIST_CODE_ENTRY: return "USELIST_CODE_ENTRY"; } } @@ -345,7 +345,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, if (Stream.EnterSubBlock(BlockID, &NumWords)) return Error("Malformed block record"); - const char *BlockName = 0; + const char *BlockName = nullptr; if (Dump) { outs() << Indent << "<"; if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) diff --git a/tools/llvm-c-test/object.c b/tools/llvm-c-test/object.c index 2792928..a5421d9 100644 --- a/tools/llvm-c-test/object.c +++ b/tools/llvm-c-test/object.c @@ -72,9 +72,8 @@ int object_list_symbols(void) { while (!LLVMIsSymbolIteratorAtEnd(O, sym)) { LLVMMoveToContainingSection(sect, sym); - printf("%s @0x%08" PRIx64 "/0x%08" PRIx64 " +%" PRIu64 " (%s)\n", - LLVMGetSymbolName(sym), LLVMGetSymbolAddress(sym), - LLVMGetSymbolFileOffset(sym), LLVMGetSymbolSize(sym), + printf("%s @0x%08" PRIx64 " +%" PRIu64 " (%s)\n", LLVMGetSymbolName(sym), + LLVMGetSymbolAddress(sym), LLVMGetSymbolSize(sym), LLVMGetSectionName(sect)); LLVMMoveToNextSymbol(sym); diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index 6f29a82..8d83762 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -16,7 +16,8 @@ set(LLVM_OBJ_ROOT ${LLVM_BINARY_DIR}) set(LLVM_CPPFLAGS "${CMAKE_CPP_FLAGS} ${CMAKE_CPP_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") set(LLVM_CFLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") set(LLVM_CXXFLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") -set(LLVM_LDFLAGS ${CMAKE_SHARED_LINKER_FLAGS}) +# Use the C++ link flags, since they should be a superset of C link flags. +set(LLVM_LDFLAGS "${CMAKE_CXX_LINK_FLAGS}") set(LLVM_BUILDMODE ${CMAKE_BUILD_TYPE}) set(LLVM_SYSTEM_LIBS ${SYSTEM_LIBS}) string(REPLACE ";" " " LLVM_TARGETS_BUILT "${LLVM_TARGETS_TO_BUILD}") diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp index 587ee11..9463609 100644 --- a/tools/llvm-cov/llvm-cov.cpp +++ b/tools/llvm-cov/llvm-cov.cpp @@ -26,34 +26,42 @@ using namespace llvm; static cl::opt<std::string> SourceFile(cl::Positional, cl::Required, cl::desc("SOURCEFILE")); -static cl::opt<bool> AllBlocks("a", cl::init(false), +static cl::opt<bool> AllBlocks("a", cl::Grouping, cl::init(false), cl::desc("Display all basic blocks")); static cl::alias AllBlocksA("all-blocks", cl::aliasopt(AllBlocks)); -static cl::opt<bool> BranchProb("b", cl::init(false), +static cl::opt<bool> BranchProb("b", cl::Grouping, 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), +static cl::opt<bool> BranchCount("c", cl::Grouping, 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), +static cl::opt<bool> LongNames("l", cl::Grouping, cl::init(false), + cl::desc("Prefix filenames with the main file")); +static cl::alias LongNamesA("long-file-names", cl::aliasopt(LongNames)); + +static cl::opt<bool> FuncSummary("f", cl::Grouping, cl::init(false), cl::desc("Show coverage for each function")); static cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary)); +static cl::opt<bool> NoOutput("n", cl::Grouping, cl::init(false), + cl::desc("Do not output any .gcov files")); +static cl::alias NoOutputA("no-output", cl::aliasopt(NoOutput)); + static cl::opt<std::string> 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), +static cl::opt<bool> PreservePaths("p", cl::Grouping, 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), +static cl::opt<bool> UncondBranch("u", cl::Grouping, cl::init(false), cl::desc("Display unconditional branch info " "(requires -b)")); static cl::alias UncondBranchA("unconditional-branches", @@ -126,9 +134,9 @@ int main(int argc, char **argv) { GF.dump(); GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary, - PreservePaths, UncondBranch); + PreservePaths, UncondBranch, LongNames, NoOutput); FileInfo FI(Options); GF.collectLineCounts(FI); - FI.print(InputGCNO, InputGCDA); + FI.print(SourceFile, InputGCNO, InputGCDA); return 0; } diff --git a/tools/llvm-diff/DiffLog.cpp b/tools/llvm-diff/DiffLog.cpp index caf779b..24a1b08 100644 --- a/tools/llvm-diff/DiffLog.cpp +++ b/tools/llvm-diff/DiffLog.cpp @@ -35,11 +35,11 @@ void DiffLogBuilder::addMatch(Instruction *L, Instruction *R) { } void DiffLogBuilder::addLeft(Instruction *L) { // HACK: VS 2010 has a bug in the stdlib that requires this. - Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); + Diff.push_back(DiffRecord(L, DiffRecord::second_type(nullptr))); } void DiffLogBuilder::addRight(Instruction *R) { // HACK: VS 2010 has a bug in the stdlib that requires this. - Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); + Diff.push_back(DiffRecord(DiffRecord::first_type(nullptr), R)); } unsigned DiffLogBuilder::getNumLines() const { return Diff.size(); } diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h index 73bf6eb..4470968 100644 --- a/tools/llvm-diff/DifferenceEngine.h +++ b/tools/llvm-diff/DifferenceEngine.h @@ -59,7 +59,7 @@ namespace llvm { }; DifferenceEngine(Consumer &consumer) - : consumer(consumer), globalValueOracle(0) {} + : consumer(consumer), globalValueOracle(nullptr) {} void diff(Module *L, Module *R); void diff(Function *L, Function *R); diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index c6f0dcf..0df7328 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" @@ -135,7 +136,7 @@ int main(int argc, char **argv) { DisplayFilename = InputFilename; M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context, &ErrorMessage)); - if(M.get() != 0) { + if(M.get()) { if (error_code EC = M->materializeAllPermanently()) { ErrorMessage = EC.message(); M.reset(); @@ -143,7 +144,7 @@ int main(int argc, char **argv) { } } - if (M.get() == 0) { + if (!M.get()) { errs() << argv[0] << ": "; if (ErrorMessage.size()) errs() << ErrorMessage << "\n"; diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index f4a9ae8..46ac36e 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -38,19 +38,6 @@ static cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input object files>"), cl::ZeroOrMore); -static cl::opt<unsigned long long> -Address("address", cl::init(-1ULL), - cl::desc("Print line information for a given address")); - -static cl::opt<bool> -PrintFunctions("functions", cl::init(false), - cl::desc("Print function names as well as line information " - "for a given address")); - -static cl::opt<bool> -PrintInlining("inlining", cl::init(false), - cl::desc("Print all inlined frames for a given address")); - static cl::opt<DIDumpType> DumpType("debug-dump", cl::init(DIDT_All), cl::desc("Dump of debug sections:"), @@ -78,14 +65,6 @@ DumpType("debug-dump", cl::init(DIDT_All), clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo", ".debug_str_offsets.dwo"), clEnumValEnd)); -static void PrintDILineInfo(DILineInfo dli) { - if (PrintFunctions) - outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>") - << "\n"; - outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':' - << dli.getLine() << ':' << dli.getColumn() << '\n'; -} - static void DumpInput(const StringRef &Filename) { std::unique_ptr<MemoryBuffer> Buff; @@ -103,35 +82,10 @@ static void DumpInput(const StringRef &Filename) { std::unique_ptr<DIContext> DICtx(DIContext::getDWARFContext(Obj.get())); - if (Address == -1ULL) { - outs() << Filename - << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; - // Dump the complete DWARF structure. - DICtx->dump(outs(), DumpType); - } else { - // Print line info for the specified address. - int SpecFlags = DILineInfoSpecifier::FileLineInfo | - DILineInfoSpecifier::AbsoluteFilePath; - if (PrintFunctions) - SpecFlags |= DILineInfoSpecifier::FunctionName; - if (PrintInlining) { - DIInliningInfo InliningInfo = - DICtx->getInliningInfoForAddress(Address, SpecFlags); - uint32_t n = InliningInfo.getNumberOfFrames(); - if (n == 0) { - // Print one empty debug line info in any case. - PrintDILineInfo(DILineInfo()); - } else { - for (uint32_t i = 0; i < n; i++) { - DILineInfo dli = InliningInfo.getFrame(i); - PrintDILineInfo(dli); - } - } - } else { - DILineInfo dli = DICtx->getLineInfoForAddress(Address, SpecFlags); - PrintDILineInfo(dli); - } - } + outs() << Filename + << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; + // Dump the complete DWARF structure. + DICtx->dump(outs(), DumpType); } int main(int argc, char **argv) { diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 2e5a2af..0f70868 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -22,6 +22,7 @@ #include "llvm/IRReader/IRReader.h" #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Regex.h" @@ -103,7 +104,7 @@ int main(int argc, char **argv) { std::unique_ptr<Module> M; M.reset(getLazyIRFileModule(InputFilename, Err, Context)); - if (M.get() == 0) { + if (!M.get()) { Err.print(argv[0], errs()); return 1; } @@ -165,10 +166,9 @@ int main(int argc, char **argv) { "invalid regex: " << Error; } bool match = false; - for (Module::global_iterator GV = M->global_begin(), - E = M->global_end(); GV != E; GV++) { - if (RegEx.match(GV->getName())) { - GVs.insert(&*GV); + for (auto &GV : M->globals()) { + if (RegEx.match(GV.getName())) { + GVs.insert(&GV); match = true; } } @@ -228,22 +228,19 @@ int main(int argc, char **argv) { else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) { - GlobalVariable *G = I; - if (!GVSet.count(G) && G->isMaterializable()) { + for (auto &G : M->globals()) { + if (!GVSet.count(&G) && G.isMaterializable()) { std::string ErrInfo; - if (G->Materialize(&ErrInfo)) { + if (G.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - Function *F = I; - if (!GVSet.count(F) && F->isMaterializable()) { + for (auto &F : *M) { + if (!GVSet.count(&F) && F.isMaterializable()) { std::string ErrInfo; - if (F->Materialize(&ErrInfo)) { + if (F.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 1f0e224..ed8c06e 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" @@ -61,13 +62,13 @@ static inline Module *LoadFile(const char *argv0, const std::string &FN, LLVMContext& Context) { SMDiagnostic Err; if (Verbose) errs() << "Loading '" << FN << "'\n"; - Module* Result = 0; + Module* Result = nullptr; Result = ParseIRFile(FN, Err, Context); if (Result) return Result; // Load successful! Err.print(argv0, errs()); - return NULL; + return nullptr; } int main(int argc, char **argv) { @@ -84,7 +85,7 @@ int main(int argc, char **argv) { std::unique_ptr<Module> Composite( LoadFile(argv[0], InputFilenames[BaseArg], Context)); - if (Composite.get() == 0) { + if (!Composite.get()) { errs() << argv[0] << ": error loading file '" << InputFilenames[BaseArg] << "'\n"; return 1; @@ -93,7 +94,7 @@ int main(int argc, char **argv) { Linker L(Composite.get(), SuppressWarnings); for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { std::unique_ptr<Module> M(LoadFile(argv[0], InputFilenames[i], Context)); - if (M.get() == 0) { + if (!M.get()) { errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; } diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index ec3f0fa..8c2d1cd 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -17,6 +17,7 @@ #include "llvm/LTO/LTOCodeGenerator.h" #include "llvm/LTO/LTOModule.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -83,7 +84,20 @@ int main(int argc, char **argv) { LTOCodeGenerator CodeGen; - CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC); + switch (RelocModel) { + case Reloc::Static: + CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC); + break; + case Reloc::PIC_: + CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC); + break; + case Reloc::DynamicNoPIC: + CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC); + break; + default: + CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT); + } + CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); @@ -130,12 +144,22 @@ int main(int argc, char **argv) { for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); + std::string attrs; + for (unsigned i = 0; i < MAttrs.size(); ++i) { + if (i > 0) + attrs.append(","); + attrs.append(MAttrs[i]); + } + + if (!attrs.empty()) + CodeGen.setAttr(attrs.c_str()); + if (!OutputFilename.empty()) { size_t len = 0; std::string ErrorInfo; const void *Code = CodeGen.compile(&len, DisableOpt, DisableInline, DisableGVNLoadPRE, ErrorInfo); - if (Code == NULL) { + if (!Code) { errs() << argv[0] << ": error compiling the code: " << ErrorInfo << "\n"; return 1; @@ -152,7 +176,7 @@ int main(int argc, char **argv) { FileStream.write(reinterpret_cast<const char *>(Code), len); } else { std::string ErrorInfo; - const char *OutputName = NULL; + const char *OutputName = nullptr; if (!CodeGen.compile_to_file(&OutputName, DisableOpt, DisableInline, DisableGVNLoadPRE, ErrorInfo)) { errs() << argv[0] diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 9c402f2..9367590 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -14,8 +14,11 @@ #include "Disassembler.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/MemoryBuffer.h" @@ -158,7 +161,24 @@ int Disassembler::disassemble(const Target &T, MemoryBuffer &Buffer, SourceMgr &SM, raw_ostream &Out) { - std::unique_ptr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI)); + + std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); + if (!MRI) { + errs() << "error: no register info for target " << Triple << "\n"; + return -1; + } + + std::unique_ptr<const MCAsmInfo> MAI(T.createMCAsmInfo(*MRI, Triple)); + if (!MAI) { + errs() << "error: no assembly info for target " << Triple << "\n"; + return -1; + } + + // Set up the MCContext for creating symbols and MCExpr's. + MCContext Ctx(MAI.get(), MRI.get(), nullptr); + + std::unique_ptr<const MCDisassembler> DisAsm( + T.createMCDisassembler(STI, Ctx)); if (!DisAsm) { errs() << "error: no disassembler for target " << Triple << "\n"; return -1; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 61fd2c4..84d578b 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/FileUtilities.h" @@ -64,12 +65,6 @@ static cl::opt<unsigned> OutputAsmVariant("output-asm-variant", cl::desc("Syntax variant to use for output printing")); -static cl::opt<bool> -RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); - -static cl::opt<bool> -NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); - enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -147,12 +142,12 @@ NoInitialTextSection("n", cl::desc("Don't assume assembly file starts " "in the text section")); static cl::opt<bool> -SaveTempLabels("L", cl::desc("Don't discard temporary labels")); - -static cl::opt<bool> GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " "source files")); +static cl::opt<int> +DwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::init(4)); + static cl::opt<std::string> DebugCompilationDir("fdebug-compilation-dir", cl::desc("Specifies the debug info's compilation dir")); @@ -161,6 +156,12 @@ static cl::opt<std::string> MainFileName("main-file-name", cl::desc("Specifies the name we should consider the input file")); +static cl::opt<bool> SaveTempLabels("save-temp-labels", + cl::desc("Don't discard temporary labels")); + +static cl::opt<bool> NoExecStack("no-exec-stack", + cl::desc("File doesn't need an exec stack")); + enum ActionType { AC_AsLex, AC_Assemble, @@ -197,7 +198,7 @@ static const Target *GetTarget(const char *ProgName) { Error); if (!TheTarget) { errs() << ProgName << ": " << Error; - return 0; + return nullptr; } // Update the triple name and return the found target. @@ -215,7 +216,7 @@ static tool_output_file *GetOutputStream() { if (!Err.empty()) { errs() << Err << '\n'; delete Out; - return 0; + return nullptr; } return Out; @@ -320,9 +321,11 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) static int AssembleInput(const char *ProgName, const Target *TheTarget, SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str, MCAsmInfo &MAI, MCSubtargetInfo &STI, MCInstrInfo &MCII) { - std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, Str, MAI)); + std::unique_ptr<MCAsmParser> Parser( + createMCAsmParser(SrcMgr, Ctx, Str, MAI)); std::unique_ptr<MCTargetAsmParser> TAP( - TheTarget->createMCAsmParser(STI, *Parser, MCII)); + TheTarget->createMCAsmParser(STI, *Parser, MCII, + InitMCTargetOptionsFromFlags())); if (!TAP) { errs() << ProgName << ": error: this target does not support assembly parsing.\n"; @@ -403,6 +406,12 @@ int main(int argc, char **argv) { Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); + if (DwarfVersion < 2 || DwarfVersion > 4) { + errs() << ProgName << ": Dwarf version " << DwarfVersion + << " is not supported." << '\n'; + return 1; + } + Ctx.setDwarfVersion(DwarfVersion); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty()) @@ -432,20 +441,19 @@ int main(int argc, char **argv) { std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); - MCInstPrinter *IP = NULL; + MCInstPrinter *IP = nullptr; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); - MCCodeEmitter *CE = 0; - MCAsmBackend *MAB = 0; + MCCodeEmitter *CE = nullptr; + MCAsmBackend *MAB = nullptr; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true, - /*UseCFI*/ true, - /*useDwarfDirectory*/ - true, IP, CE, MAB, ShowInst)); + /*useDwarfDirectory*/ true, IP, CE, + MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 22e019a..3be9247 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -181,11 +181,30 @@ static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { return false; } +static char isSymbolList64Bit(SymbolicFile *Obj) { + if (isa<IRObjectFile>(Obj)) + return false; + else if (isa<COFFObjectFile>(Obj)) + return false; + else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj)) + return MachO->is64Bit(); + else if (isa<ELF32LEObjectFile>(Obj)) + return false; + else if (isa<ELF64LEObjectFile>(Obj)) + return true; + else if (isa<ELF32BEObjectFile>(Obj)) + return false; + else if(isa<ELF64BEObjectFile>(Obj)) + return true; + else + return false; +} + static StringRef CurrentFilename; typedef std::vector<NMSymbol> SymbolListT; static SymbolListT SymbolList; -static void sortAndPrintSymbolList() { +static void sortAndPrintSymbolList(SymbolicFile *Obj) { if (!NoSort) { if (NumericSort) std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress); @@ -205,6 +224,15 @@ static void sortAndPrintSymbolList() { << " Size Line Section\n"; } + const char *printBlanks, *printFormat; + if (isSymbolList64Bit(Obj)) { + printBlanks = " "; + printFormat = "%016" PRIx64; + } else { + printBlanks = " "; + printFormat = "%08" PRIx64; + } + for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); I != E; ++I) { if ((I->TypeChar != 'U') && UndefinedOnly) @@ -214,19 +242,19 @@ static void sortAndPrintSymbolList() { if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize) continue; - char SymbolAddrStr[10] = ""; - char SymbolSizeStr[10] = ""; + char SymbolAddrStr[18] = ""; + char SymbolSizeStr[18] = ""; if (OutputFormat == sysv || I->Address == UnknownAddressOrSize) - strcpy(SymbolAddrStr, " "); + strcpy(SymbolAddrStr, printBlanks); if (OutputFormat == sysv) - strcpy(SymbolSizeStr, " "); + strcpy(SymbolSizeStr, printBlanks); if (I->Address != UnknownAddressOrSize) - format("%08" PRIx64, I->Address) + format(printFormat, I->Address) .print(SymbolAddrStr, sizeof(SymbolAddrStr)); if (I->Size != UnknownAddressOrSize) - format("%08" PRIx64, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); + format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); if (OutputFormat == posix) { outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr @@ -392,7 +420,7 @@ static char getSymbolNMTypeChar(const GlobalValue &GV) { if (isa<GlobalVariable>(GV)) return 'd'; const GlobalAlias *GA = cast<GlobalAlias>(&GV); - const GlobalValue *AliasedGV = GA->getAliasedGlobal(); + const GlobalValue *AliasedGV = GA->getAliasee(); return getSymbolNMTypeChar(*AliasedGV); } @@ -514,7 +542,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj) { } CurrentFilename = Obj->getFileName(); - sortAndPrintSymbolList(); + sortAndPrintSymbolList(Obj); } static void dumpSymbolNamesFromFile(std::string &Filename) { @@ -567,10 +595,24 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { E = UB->end_objects(); I != E; ++I) { std::unique_ptr<ObjectFile> Obj; + std::unique_ptr<Archive> A; if (!I->getAsObjectFile(Obj)) { outs() << Obj->getFileName() << ":\n"; dumpSymbolNamesFromObject(Obj.get()); } + else if (!I->getAsArchive(A)) { + for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); + AI != AE; ++AI) { + std::unique_ptr<Binary> Child; + if (AI->getAsBinary(Child, &Context)) + continue; + if (SymbolicFile *O = dyn_cast<SymbolicFile>(Child.get())) { + outs() << A->getFileName() << ":"; + outs() << O->getFileName() << ":\n"; + dumpSymbolNamesFromObject(O); + } + } + } } return; } diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 89b038f..3ca582f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" @@ -64,7 +65,7 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj) { errs() << "llvm-objdump: error: unable to get target for '" << TripleName << "', see --version and --triple.\n"; - return 0; + return nullptr; } struct SymbolSorter { @@ -225,8 +226,9 @@ static void DisassembleInputMachO2(StringRef Filename, TheTarget->createMCAsmInfo(*MRI, TripleName)); std::unique_ptr<const MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, "", "")); + MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); std::unique_ptr<const MCDisassembler> DisAsm( - TheTarget->createMCDisassembler(*STI)); + TheTarget->createMCDisassembler(*STI, Ctx)); int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI)); @@ -419,9 +421,9 @@ static void DisassembleInputMachO2(StringRef Filename, DILineInfo dli = diContext->getLineInfoForAddress(SectAddress + Index); // Print valid line info if it changed. - if (dli != lastLine && dli.getLine() != 0) - outs() << "\t## " << dli.getFileName() << ':' - << dli.getLine() << ':' << dli.getColumn(); + if (dli != lastLine && dli.Line != 0) + outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' + << dli.Column; lastLine = dli; } outs() << "\n"; diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 729fcba..a4fc6d0 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -157,7 +157,7 @@ bool llvm::error(error_code EC) { return true; } -static const Target *getTarget(const ObjectFile *Obj = NULL) { +static const Target *getTarget(const ObjectFile *Obj = nullptr) { // Figure out the target triple. llvm::Triple TheTriple("unknown-unknown-unknown"); if (TripleName.empty()) { @@ -167,6 +167,12 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { // the best we can do here is indicate that it is mach-o. if (Obj->isMachO()) TheTriple.setObjectFormat(Triple::MachO); + + if (Obj->isCOFF()) { + const auto COFFObj = dyn_cast<COFFObjectFile>(Obj); + if (COFFObj->getArch() == Triple::thumb) + TheTriple.setTriple("thumbv7-windows"); + } } } else TheTriple.setTriple(Triple::normalize(TripleName)); @@ -177,7 +183,7 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { Error); if (!TheTarget) { errs() << ToolName << ": " << Error; - return 0; + return nullptr; } // Update the triple name and return the found target. @@ -309,24 +315,25 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } - std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); + std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo); + MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get()); + + std::unique_ptr<MCDisassembler> DisAsm( + TheTarget->createMCDisassembler(*STI, Ctx)); + if (!DisAsm) { errs() << "error: no disassembler for target " << TripleName << "\n"; return; } - 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())); std::unique_ptr<MCRelocationInfo> RelInfo( - TheTarget->createMCRelocationInfo(TripleName, *Ctx.get())); + TheTarget->createMCRelocationInfo(TripleName, Ctx)); if (RelInfo) { std::unique_ptr<MCSymbolizer> Symzer( - MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), - std::move(RelInfo), Obj)); + MCObjectSymbolizer::createObjectSymbolizer(Ctx, std::move(RelInfo), + Obj)); if (Symzer) DisAsm->setSymbolizer(std::move(Symzer)); } @@ -664,16 +671,33 @@ static void PrintSectionContents(const ObjectFile *Obj) { static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { const coff_file_header *header; - if (error(coff->getHeader(header))) return; - int aux_count = 0; - const coff_symbol *symbol = 0; - for (int i = 0, e = header->NumberOfSymbols; i != e; ++i) { - if (aux_count--) { - // Figure out which type of aux this is. - if (symbol->isSectionDefinition()) { // Section definition. + if (error(coff->getHeader(header))) + return; + + for (unsigned SI = 0, SE = header->NumberOfSymbols; SI != SE; ++SI) { + const coff_symbol *Symbol; + StringRef Name; + if (error(coff->getSymbol(SI, Symbol))) + return; + + if (error(coff->getSymbolName(Symbol, Name))) + return; + + outs() << "[" << format("%2d", SI) << "]" + << "(sec " << format("%2d", int(Symbol->SectionNumber)) << ")" + << "(fl 0x00)" // Flag bits, which COFF doesn't have. + << "(ty " << format("%3x", unsigned(Symbol->Type)) << ")" + << "(scl " << format("%3x", unsigned(Symbol->StorageClass)) << ") " + << "(nx " << unsigned(Symbol->NumberOfAuxSymbols) << ") " + << "0x" << format("%08x", unsigned(Symbol->Value)) << " " + << Name << "\n"; + + for (unsigned AI = 0, AE = Symbol->NumberOfAuxSymbols; AI < AE; ++AI, ++SI) { + if (Symbol->isSectionDefinition()) { const coff_aux_section_definition *asd; - if (error(coff->getAuxSymbol<coff_aux_section_definition>(i, asd))) + if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd))) return; + outs() << "AUX " << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " , unsigned(asd->Length) @@ -683,21 +707,20 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { << format("assoc %d comdat %d\n" , unsigned(asd->Number) , unsigned(asd->Selection)); - } else + } else if (Symbol->isFileRecord()) { + const coff_aux_file *AF; + if (error(coff->getAuxSymbol<coff_aux_file>(SI + 1, AF))) + return; + + StringRef Name(AF->FileName, + Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n'; + + SI = SI + Symbol->NumberOfAuxSymbols; + break; + } else { outs() << "AUX Unknown\n"; - } else { - StringRef name; - if (error(coff->getSymbol(i, symbol))) return; - if (error(coff->getSymbolName(symbol, name))) return; - outs() << "[" << format("%2d", i) << "]" - << "(sec " << format("%2d", int(symbol->SectionNumber)) << ")" - << "(fl 0x00)" // Flag bits, which COFF doesn't have. - << "(ty " << format("%3x", unsigned(symbol->Type)) << ")" - << "(scl " << format("%3x", unsigned(symbol->StorageClass)) << ") " - << "(nx " << unsigned(symbol->NumberOfAuxSymbols) << ") " - << "0x" << format("%08x", unsigned(symbol->Value)) << " " - << name << "\n"; - aux_count = symbol->NumberOfAuxSymbols; + } } } } diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index 397b523..fdde32a 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -15,6 +15,7 @@ #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" @@ -39,16 +40,15 @@ int merge_main(int argc, const char *argv[]) { 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::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::Required, + cl::aliasopt(OutputFilename)); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); - if (OutputFilename.empty()) - OutputFilename = "-"; + if (OutputFilename.compare("-") == 0) + exitWithError("Cannot write indexed profdata format to stdout."); 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); @@ -112,6 +112,7 @@ int show_main(int argc, const char *argv[]) { Func.Name.find(ShowFunction) != Func.Name.npos); ++TotalFunctions; + assert(Func.Counts.size() > 0 && "function missing entry counter"); if (Func.Counts[0] > MaxFunctionCount) MaxFunctionCount = Func.Counts[0]; @@ -156,7 +157,7 @@ int main(int argc, const char *argv[]) { StringRef ProgName(sys::path::filename(argv[0])); if (argc > 1) { - int (*func)(int, const char *[]) = 0; + int (*func)(int, const char *[]) = nullptr; if (strcmp(argv[1], "merge") == 0) func = merge_main; diff --git a/tools/llvm-readobj/ARMAttributeParser.cpp b/tools/llvm-readobj/ARMAttributeParser.cpp index 5857547..d35cd14 100644 --- a/tools/llvm-readobj/ARMAttributeParser.cpp +++ b/tools/llvm-readobj/ARMAttributeParser.cpp @@ -9,6 +9,7 @@ #include "ARMAttributeParser.h" #include "StreamWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/LEB128.h" @@ -22,11 +23,6 @@ static const EnumEntry<unsigned> TagNames[] = { { "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_ } @@ -129,7 +125,8 @@ void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -155,7 +152,8 @@ void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -164,7 +162,8 @@ void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -176,7 +175,8 @@ void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -185,7 +185,8 @@ void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -196,7 +197,8 @@ void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -208,7 +210,8 @@ void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -217,7 +220,8 @@ void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -228,7 +232,8 @@ void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -237,7 +242,8 @@ void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Absolute", "PC-relative", "Not Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -246,7 +252,8 @@ void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Direct", "GOT-Indirect" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -257,7 +264,8 @@ void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -266,7 +274,8 @@ void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "IEEE-754", "Runtime" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -275,7 +284,8 @@ void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -284,7 +294,8 @@ void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "IEEE-754" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -294,7 +305,8 @@ void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag, static const char *Strings[] = { "Not Permitted", "IEEE-754" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -305,7 +317,8 @@ void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -318,7 +331,7 @@ void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data, uint64_t Value = ParseInteger(Data, Offset); std::string Description; - if (Value < countof(Strings)) + if (Value < array_lengthof(Strings)) Description = std::string(Strings[Value]); else if (Value <= 12) Description = std::string("8-byte alignment, ") + utostr(1 << Value) @@ -339,7 +352,7 @@ void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data, uint64_t Value = ParseInteger(Data, Offset); std::string Description; - if (Value < countof(Strings)) + if (Value < array_lengthof(Strings)) Description = std::string(Strings[Value]); else if (Value <= 12) Description = std::string("8-byte stack alignment, ") + utostr(1 << Value) @@ -357,7 +370,8 @@ void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -368,7 +382,8 @@ void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -379,7 +394,8 @@ void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -388,7 +404,8 @@ void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -401,7 +418,8 @@ void ARMAttributeParser::ABI_optimization_goals(AttrType Tag, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -414,7 +432,8 @@ void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -445,7 +464,8 @@ void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "v6-style" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -454,7 +474,8 @@ void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "If Available", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -463,7 +484,8 @@ void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -472,7 +494,8 @@ void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -483,7 +506,8 @@ void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -492,7 +516,8 @@ void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -504,7 +529,8 @@ void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -534,7 +560,7 @@ void ARMAttributeParser::ParseAttributeList(const uint8_t *Data, Offset += Length; bool Handled = false; - for (unsigned AHI = 0, AHE = countof(DisplayRoutines); + for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines); AHI != AHE && !Handled; ++AHI) { if (DisplayRoutines[AHI].Attribute == Tag) { (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag), diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h index 75e2bee..7608cfb 100644 --- a/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/tools/llvm-readobj/ARMEHABIPrinter.h @@ -12,6 +12,7 @@ #include "Error.h" #include "StreamWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Support/ARMEHABI.h" @@ -20,13 +21,6 @@ #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 { @@ -296,7 +290,8 @@ void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) { 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) { + for (unsigned REI = 0, REE = array_lengthof(Ring); + REI != REE && !Decoded; ++REI) { if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) { (this->*Ring[REI].Routine)(Opcodes, OCI); Decoded = true; @@ -390,7 +385,7 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, } } } - return NULL; + return nullptr; } template <typename ET> diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt index 036185d..b057dcd 100644 --- a/tools/llvm-readobj/CMakeLists.txt +++ b/tools/llvm-readobj/CMakeLists.txt @@ -5,12 +5,13 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_tool(llvm-readobj - llvm-readobj.cpp - ObjDumper.cpp + ARMAttributeParser.cpp COFFDumper.cpp ELFDumper.cpp - MachODumper.cpp Error.cpp + llvm-readobj.cpp + MachODumper.cpp + ObjDumper.cpp StreamWriter.cpp - ARMAttributeParser.cpp + Win64EHDumper.cpp ) diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index cd40da7..91f2a57 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -16,6 +16,7 @@ #include "Error.h" #include "ObjDumper.h" #include "StreamWriter.h" +#include "Win64EHDumper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/Object/COFF.h" @@ -58,45 +59,24 @@ private: 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, - const std::vector<RelocationRef> &Rels); - - void printUnwindInfo( - const Win64EH::UnwindInfo& UI, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels); - - void printUnwindCode(const Win64EH::UnwindInfo &UI, ArrayRef<UnwindCode> UCs); - void printCodeViewLineTables(const SectionRef &Section); void cacheRelocations(); - error_code getSectionContents( - const std::vector<RelocationRef> &Rels, - uint64_t Offset, - ArrayRef<uint8_t> &Contents, - uint64_t &Addr); - - error_code getSection( - const std::vector<RelocationRef> &Rels, - uint64_t Offset, - const coff_section **Section, - uint64_t *AddrPtr); + error_code resolveSymbol(const coff_section *Section, uint64_t Offset, + SymbolRef &Sym); + error_code resolveSymbolName(const coff_section *Section, uint64_t Offset, + StringRef &Name); typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; const llvm::object::COFFObjectFile *Obj; RelocMapTy RelocMap; - std::vector<RelocationRef> EmptyRelocs; }; } // namespace @@ -116,110 +96,33 @@ error_code createCOFFDumper(const object::ObjectFile *Obj, StreamWriter &Writer, } // namespace llvm - -// Returns the name of the unwind code. -static StringRef getUnwindCodeTypeName(uint8_t Code) { - switch(Code) { - default: llvm_unreachable("Invalid unwind code"); - case UOP_PushNonVol: return "PUSH_NONVOL"; - case UOP_AllocLarge: return "ALLOC_LARGE"; - case UOP_AllocSmall: return "ALLOC_SMALL"; - case UOP_SetFPReg: return "SET_FPREG"; - case UOP_SaveNonVol: return "SAVE_NONVOL"; - case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR"; - case UOP_SaveXMM128: return "SAVE_XMM128"; - case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR"; - case UOP_PushMachFrame: return "PUSH_MACHFRAME"; - } -} - -// Returns the name of a referenced register. -static StringRef getUnwindRegisterName(uint8_t Reg) { - switch(Reg) { - default: llvm_unreachable("Invalid register"); - case 0: return "RAX"; - case 1: return "RCX"; - case 2: return "RDX"; - case 3: return "RBX"; - case 4: return "RSP"; - case 5: return "RBP"; - case 6: return "RSI"; - case 7: return "RDI"; - case 8: return "R8"; - case 9: return "R9"; - case 10: return "R10"; - case 11: return "R11"; - case 12: return "R12"; - case 13: return "R13"; - case 14: return "R14"; - case 15: return "R15"; - } -} - -// Calculates the number of array slots required for the unwind code. -static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { - switch (UnwindCode.getUnwindOp()) { - default: llvm_unreachable("Invalid unwind code"); - case UOP_PushNonVol: - case UOP_AllocSmall: - case UOP_SetFPReg: - case UOP_PushMachFrame: - return 1; - case UOP_SaveNonVol: - case UOP_SaveXMM128: - return 2; - case UOP_SaveNonVolBig: - case UOP_SaveXMM128Big: - return 3; - case UOP_AllocLarge: - return (UnwindCode.getOpInfo() == 0) ? 2 : 3; - } -} - -// Given a symbol sym this functions returns the address and section of it. -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->section_begin()); - if (error_code EC = Sym.getSection(iter)) - return EC; - - ResolvedSection = Obj->getCOFFSection(*iter); - return object_error::success; -} - -// Given a vector of relocations for a section and an offset into this section -// the function returns the symbol used for the relocation at the offset. -static error_code resolveSymbol(const std::vector<RelocationRef> &Rels, - uint64_t Offset, SymbolRef &Sym) { - for (std::vector<RelocationRef>::const_iterator RelI = Rels.begin(), - RelE = Rels.end(); - RelI != RelE; ++RelI) { - uint64_t Ofs; - if (error_code EC = RelI->getOffset(Ofs)) +// Given a a section and an offset into this section the function returns the +// symbol used for the relocation at the offset. +error_code COFFDumper::resolveSymbol(const coff_section *Section, + uint64_t Offset, SymbolRef &Sym) { + const auto &Relocations = RelocMap[Section]; + for (const auto &Relocation : Relocations) { + uint64_t RelocationOffset; + if (error_code EC = Relocation.getOffset(RelocationOffset)) return EC; - if (Ofs == Offset) { - Sym = *RelI->getSymbol(); + if (RelocationOffset == Offset) { + Sym = *Relocation.getSymbol(); return readobj_error::success; } } - return readobj_error::unknown_symbol; } -// Given a vector of relocations for a section and an offset into this section -// the function returns the name of the symbol used for the relocation at the -// offset. -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; +// Given a section and an offset into this section the function returns the name +// of the symbol used for the relocation at the offset. +error_code COFFDumper::resolveSymbolName(const coff_section *Section, + uint64_t Offset, StringRef &Name) { + SymbolRef Symbol; + if (error_code EC = resolveSymbol(Section, Offset, Symbol)) + return EC; + if (error_code EC = Symbol.getName(Name)) + return EC; return object_error::success; } @@ -403,50 +306,6 @@ WeakExternalCharacteristics[] = { { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS } }; -static const EnumEntry<unsigned> UnwindFlags[] = { - { "ExceptionHandler", Win64EH::UNW_ExceptionHandler }, - { "TerminateHandler", Win64EH::UNW_TerminateHandler }, - { "ChainInfo" , Win64EH::UNW_ChainInfo } -}; - -static const EnumEntry<unsigned> UnwindOpInfo[] = { - { "RAX", 0 }, - { "RCX", 1 }, - { "RDX", 2 }, - { "RBX", 3 }, - { "RSP", 4 }, - { "RBP", 5 }, - { "RSI", 6 }, - { "RDI", 7 }, - { "R8", 8 }, - { "R9", 9 }, - { "R10", 10 }, - { "R11", 11 }, - { "R12", 12 }, - { "R13", 13 }, - { "R14", 14 }, - { "R15", 15 } -}; - -// Some additional COFF structures not defined by llvm::object. -namespace { - struct coff_aux_file_record { - char FileName[18]; - }; -} // namespace - -static uint64_t getOffsetOfLSDA(const Win64EH::UnwindInfo& UI) { - return static_cast<const char*>(UI.getLanguageSpecificData()) - - reinterpret_cast<const char*>(&UI); -} - -static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UCs) { - if (UCs.size() < 3) - return 0; - - return UCs[1].FrameOffset + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16); -} - template<typename T> static error_code getSymbolAuxData(const COFFObjectFile *Obj, const coff_symbol *Symbol, const T* &Aux) { @@ -455,69 +314,6 @@ static error_code getSymbolAuxData(const COFFObjectFile *Obj, return readobj_error::success; } -static std::string formatSymbol(const std::vector<RelocationRef> &Rels, - uint64_t Offset, uint32_t Disp) { - std::string Buffer; - raw_string_ostream Str(Buffer); - - StringRef Sym; - if (resolveSymbolName(Rels, Offset, Sym)) { - Str << format(" (0x%" PRIX64 ")", Offset); - return Str.str(); - } - - Str << Sym; - if (Disp > 0) { - Str << format(" +0x%X (0x%" PRIX64 ")", Disp, Offset); - } else { - Str << format(" (0x%" PRIX64 ")", Offset); - } - - return Str.str(); -} - -// Given a vector of relocations for a section and an offset into this section -// the function resolves the symbol used for the relocation at the offset and -// returns the section content and the address inside the content pointed to -// by the symbol. -error_code COFFDumper::getSectionContents( - const std::vector<RelocationRef> &Rels, uint64_t Offset, - ArrayRef<uint8_t> &Contents, uint64_t &Addr) { - - SymbolRef Sym; - const coff_section *Section; - - if (error_code EC = resolveSymbol(Rels, Offset, Sym)) - 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; -} - -error_code COFFDumper::getSection( - const std::vector<RelocationRef> &Rels, uint64_t Offset, - const coff_section **SectionPtr, uint64_t *AddrPtr) { - - SymbolRef Sym; - if (error_code EC = resolveSymbol(Rels, Offset, Sym)) - return EC; - - const coff_section *Section; - uint64_t Addr; - if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr)) - return EC; - - if (SectionPtr) - *SectionPtr = Section; - if (AddrPtr) - *AddrPtr = Addr; - - return object_error::success; -} - void COFFDumper::cacheRelocations() { for (const SectionRef &S : Obj->sections()) { const coff_section *Section = Obj->getCOFFSection(S); @@ -541,7 +337,7 @@ void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName void COFFDumper::printFileHeaders() { // Print COFF header - const coff_file_header *COFFHeader = 0; + const coff_file_header *COFFHeader = nullptr; if (error(Obj->getCOFFHeader(COFFHeader))) return; @@ -564,13 +360,13 @@ void COFFDumper::printFileHeaders() { // Print PE header. This header does not exist if this is an object file and // not an executable. - const pe32_header *PEHeader = 0; + const pe32_header *PEHeader = nullptr; if (error(Obj->getPE32Header(PEHeader))) return; if (PEHeader) printPEHeader<pe32_header>(PEHeader); - const pe32plus_header *PEPlusHeader = 0; + const pe32plus_header *PEPlusHeader = nullptr; if (error(Obj->getPE32PlusHeader(PEPlusHeader))) return; if (PEPlusHeader) @@ -685,8 +481,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { } StringRef FunctionName; - if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(Section)], - Offset, FunctionName))) + if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset, + FunctionName))) return; W.printString("FunctionName", FunctionName); if (FunctionLineTables.count(FunctionName) != 0) { @@ -700,7 +496,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { break; } case COFF::DEBUG_STRING_TABLE_SUBSECTION: - if (PayloadSize == 0 || StringTable.data() != 0 || + if (PayloadSize == 0 || StringTable.data() != nullptr || Contents.back() != '\0') { // Empty or duplicate or non-null-terminated subsection. error(object_error::parse_failed); @@ -712,7 +508,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { // Holds the translation table from file indices // to offsets in the string table. - if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) { + if (PayloadSize == 0 || + FileIndexToStringOffsetTable.data() != nullptr) { // Empty or duplicate subsection. error(object_error::parse_failed); return; @@ -979,13 +776,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printBinary("Unused", makeArrayRef(Aux->Unused)); } else if (Symbol->isFileRecord()) { - const coff_aux_file_record *Aux; + const coff_aux_file *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; DictScope AS(W, "AuxFileRecord"); - W.printString("FileName", StringRef(Aux->FileName)); + StringRef Name(Aux->FileName, + Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + W.printString("FileName", Name.rtrim(StringRef("\0", 1))); + break; } else if (Symbol->isSectionDefinition()) { const coff_aux_section_definition *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) @@ -1045,181 +845,23 @@ void COFFDumper::printUnwindInfo() { return; ListScope D(W, "UnwindInformation"); - if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { - W.startLine() << "Unsupported image machine type " - "(currently only AMD64 is supported).\n"; - return; - } - - printX64UnwindInfo(); -} - -void COFFDumper::printX64UnwindInfo() { - for (const SectionRef &Section : Obj->sections()) { - StringRef Name; - if (error(Section.getName(Name))) - continue; - if (Name != ".pdata" && !Name.startswith(".pdata$")) - continue; - - const coff_section *PData = Obj->getCOFFSection(Section); - - ArrayRef<uint8_t> Contents; - if (error(Obj->getSectionContents(PData, Contents)) || Contents.empty()) - continue; - - 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 OffsetInSection = std::distance(RFs.begin(), I) - * sizeof(RuntimeFunction); - - printRuntimeFunction(*I, OffsetInSection, RelocMap[PData]); - } - } -} - -void COFFDumper::printRuntimeFunction( - const RuntimeFunction& RTF, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels) { - - DictScope D(W, "RuntimeFunction"); - W.printString("StartAddress", - formatSymbol(Rels, OffsetInSection + 0, RTF.StartAddress)); - W.printString("EndAddress", - formatSymbol(Rels, OffsetInSection + 4, RTF.EndAddress)); - W.printString("UnwindInfoAddress", - formatSymbol(Rels, OffsetInSection + 8, RTF.UnwindInfoOffset)); - - const coff_section* XData = 0; - uint64_t UnwindInfoOffset = 0; - if (error(getSection(Rels, OffsetInSection + 8, &XData, &UnwindInfoOffset))) - return; - - ArrayRef<uint8_t> XContents; - if (error(Obj->getSectionContents(XData, XContents)) || XContents.empty()) - return; - - UnwindInfoOffset += RTF.UnwindInfoOffset; - if (UnwindInfoOffset > XContents.size()) - return; - - const Win64EH::UnwindInfo *UI = - reinterpret_cast<const Win64EH::UnwindInfo *>( - XContents.data() + UnwindInfoOffset); - - printUnwindInfo(*UI, UnwindInfoOffset, RelocMap[XData]); -} - -void COFFDumper::printUnwindInfo( - const Win64EH::UnwindInfo& UI, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels) { - DictScope D(W, "UnwindInfo"); - W.printNumber("Version", UI.getVersion()); - W.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags)); - W.printNumber("PrologSize", UI.PrologSize); - if (UI.getFrameRegister() != 0) { - W.printEnum("FrameRegister", UI.getFrameRegister(), - makeArrayRef(UnwindOpInfo)); - W.printHex("FrameOffset", UI.getFrameOffset()); - } else { - W.printString("FrameRegister", StringRef("-")); - W.printString("FrameOffset", StringRef("-")); - } - - W.printNumber("UnwindCodeCount", UI.NumCodes); - { - ListScope CodesD(W, "UnwindCodes"); - ArrayRef<UnwindCode> UCs(&UI.UnwindCodes[0], UI.NumCodes); - for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ++I) { - unsigned UsedSlots = getNumUsedSlots(*I); - if (UsedSlots > UCs.size()) { - errs() << "Corrupt unwind data"; - return; - } - printUnwindCode(UI, ArrayRef<UnwindCode>(I, E)); - I += UsedSlots - 1; - } - } - - uint64_t LSDAOffset = OffsetInSection + getOffsetOfLSDA(UI); - if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { - W.printString("Handler", formatSymbol(Rels, LSDAOffset, - UI.getLanguageSpecificHandlerOffset())); - } else if (UI.getFlags() & UNW_ChainInfo) { - const RuntimeFunction *Chained = UI.getChainedFunctionEntry(); - if (Chained) { - DictScope D(W, "Chained"); - W.printString("StartAddress", formatSymbol(Rels, LSDAOffset + 0, - Chained->StartAddress)); - W.printString("EndAddress", formatSymbol(Rels, LSDAOffset + 4, - Chained->EndAddress)); - W.printString("UnwindInfoAddress", formatSymbol(Rels, LSDAOffset + 8, - Chained->UnwindInfoOffset)); - } - } -} - -// Prints one unwind code. Because an unwind code can occupy up to 3 slots in -// the unwind codes array, this function requires that the correct number of -// slots is provided. -void COFFDumper::printUnwindCode(const Win64EH::UnwindInfo& UI, - ArrayRef<UnwindCode> UCs) { - assert(UCs.size() >= getNumUsedSlots(UCs[0])); - - W.startLine() << format("0x%02X: ", unsigned(UCs[0].u.CodeOffset)) - << getUnwindCodeTypeName(UCs[0].getUnwindOp()); - - uint32_t AllocSize = 0; - - switch (UCs[0].getUnwindOp()) { - case UOP_PushNonVol: - outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo()); + switch (Header->Machine) { + case COFF::IMAGE_FILE_MACHINE_AMD64: { + Win64EH::Dumper Dumper(W); + Win64EH::Dumper::SymbolResolver Resolver = + [](const object::coff_section *Section, uint64_t Offset, + SymbolRef &Symbol, void *user_data) -> error_code { + COFFDumper *Dumper = reinterpret_cast<COFFDumper*>(user_data); + return Dumper->resolveSymbol(Section, Offset, Symbol); + }; + Win64EH::Dumper::Context Ctx(*Obj, Resolver, this); + Dumper.printData(Ctx); break; - - case UOP_AllocLarge: - if (UCs[0].getOpInfo() == 0) { - AllocSize = UCs[1].FrameOffset * 8; - } else { - AllocSize = getLargeSlotValue(UCs); - } - outs() << " size=" << AllocSize; - break; - case UOP_AllocSmall: - outs() << " size=" << ((UCs[0].getOpInfo() + 1) * 8); - break; - case UOP_SetFPReg: - if (UI.getFrameRegister() == 0) { - outs() << " reg=<invalid>"; - } else { - outs() << " reg=" << getUnwindRegisterName(UI.getFrameRegister()) - << format(", offset=0x%X", UI.getFrameOffset() * 16); - } - break; - case UOP_SaveNonVol: - outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo()) - << format(", offset=0x%X", UCs[1].FrameOffset * 8); - break; - case UOP_SaveNonVolBig: - outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo()) - << format(", offset=0x%X", getLargeSlotValue(UCs)); - break; - case UOP_SaveXMM128: - outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo()) - << format(", offset=0x%X", UCs[1].FrameOffset * 16); - break; - case UOP_SaveXMM128Big: - outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo()) - << format(", offset=0x%X", getLargeSlotValue(UCs)); - break; - case UOP_PushMachFrame: - outs() << " errcode=" << (UCs[0].getOpInfo() == 0 ? "no" : "yes"); + } + default: + W.printEnum("unsupported Image Machine", Header->Machine, + makeArrayRef(ImageFileMachineType)); break; } - - outs() << "\n"; } + diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 4cd3393..de4c207 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -437,6 +437,29 @@ static const EnumEntry<unsigned> ElfSegmentFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, PF_R) }; +static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6) +}; + template<class ELFT> void ELFDumper<ELFT>::printFileHeaders() { const typename ELFO::Elf_Ehdr *Header = Obj->getHeader(); @@ -464,7 +487,11 @@ void ELFDumper<ELFT>::printFileHeaders() { W.printHex ("Entry", Header->e_entry); W.printHex ("ProgramHeaderOffset", Header->e_phoff); W.printHex ("SectionHeaderOffset", Header->e_shoff); - W.printFlags ("Flags", Header->e_flags); + if (Header->e_machine == EM_MIPS) + W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags), + unsigned(ELF::EF_MIPS_ARCH)); + else + W.printFlags("Flags", Header->e_flags); W.printNumber("HeaderSize", Header->e_ehsize); W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize); W.printNumber("ProgramHeaderCount", Header->e_phnum); @@ -652,7 +679,8 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) { std::string FullSymbolName(SymbolName); if (Symbol.isDynamic()) { bool IsDefault; - ErrorOr<StringRef> Version = Obj->getSymbolVersion(0, &*Symbol, IsDefault); + ErrorOr<StringRef> Version = Obj->getSymbolVersion(nullptr, &*Symbol, + IsDefault); if (Version) { FullSymbolName += (IsDefault ? "@@" : "@"); FullSymbolName += *Version; @@ -712,6 +740,8 @@ static const char *getTypeString(uint64_t Type) { LLVM_READOBJ_TYPE_CASE(VERNEED); LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); LLVM_READOBJ_TYPE_CASE(VERSYM); + LLVM_READOBJ_TYPE_CASE(RELCOUNT); + LLVM_READOBJ_TYPE_CASE(GNU_HASH); LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); @@ -727,6 +757,57 @@ static const char *getTypeString(uint64_t Type) { #undef LLVM_READOBJ_TYPE_CASE +#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ + { #enum, prefix##_##enum } + +static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { + LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), + LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), + LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), + LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), + LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) +}; + +static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { + LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), + LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), + LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), + LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), + LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), + LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), + LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), + LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) +}; + +#undef LLVM_READOBJ_DT_FLAG_ENT + +template <typename T, typename TFlag> +void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { + typedef EnumEntry<TFlag> FlagEntry; + typedef SmallVector<FlagEntry, 10> FlagVector; + FlagVector SetFlags; + + for (const auto &Flag : Flags) { + if (Flag.Value == 0) + continue; + + if ((Value & Flag.Value) == Flag.Value) + SetFlags.push_back(Flag); + } + + for (const auto &Flag : SetFlags) { + OS << Flag.Name << " "; + } +} + template <class ELFT> static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, bool Is64, raw_ostream &OS) { @@ -755,14 +836,15 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_DEBUG: case DT_VERNEED: case DT_VERSYM: + case DT_GNU_HASH: case DT_NULL: - 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_RELCOUNT: case DT_VERNEEDNUM: case DT_MIPS_RLD_VERSION: case DT_MIPS_LOCAL_GOTNO: @@ -792,6 +874,12 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_RUNPATH: OS << O->getDynamicString(Value); break; + case DT_MIPS_FLAGS: + printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); + break; + case DT_FLAGS: + printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); + break; } } diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h index c40077a..9282dcc 100644 --- a/tools/llvm-readobj/StreamWriter.h +++ b/tools/llvm-readobj/StreamWriter.h @@ -81,9 +81,9 @@ public: ArrayRef<EnumEntry<TEnum> > EnumValues) { StringRef Name; bool Found = false; - for (size_t i = 0; i < EnumValues.size(); ++i) { - if (EnumValues[i].Value == Value) { - Name = EnumValues[i].Name; + for (const auto &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + Name = EnumItem.Name; Found = true; break; } @@ -103,25 +103,22 @@ public: typedef SmallVector<FlagEntry, 10> FlagVector; FlagVector SetFlags; - for (typename ArrayRef<FlagEntry>::const_iterator I = Flags.begin(), - E = Flags.end(); I != E; ++I) { - if (I->Value == 0) + for (const auto &Flag : Flags) { + if (Flag.Value == 0) continue; - bool IsEnum = (I->Value & EnumMask) != 0; - if ((!IsEnum && (Value & I->Value) == I->Value) || - (IsEnum && (Value & EnumMask) == I->Value)) { - SetFlags.push_back(*I); + bool IsEnum = (Flag.Value & EnumMask) != 0; + if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || + (IsEnum && (Value & EnumMask) == Flag.Value)) { + SetFlags.push_back(Flag); } } std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); startLine() << Label << " [ (" << hex(Value) << ")\n"; - for (typename FlagVector::const_iterator I = SetFlags.begin(), - E = SetFlags.end(); - I != E; ++I) { - startLine() << " " << I->Name << " (" << hex(I->Value) << ")\n"; + for (const auto &Flag : SetFlags) { + startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; } startLine() << "]\n"; } @@ -176,10 +173,10 @@ public: void printList(StringRef Label, const SmallVectorImpl<T_> &List) { startLine() << Label << ": ["; bool Comma = false; - for (unsigned LI = 0, LE = List.size(); LI != LE; ++LI) { + for (const auto &Item : List) { if (Comma) OS << ", "; - OS << List[LI]; + OS << Item; Comma = true; } OS << "]\n"; diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp new file mode 100644 index 0000000..c64d362 --- /dev/null +++ b/tools/llvm-readobj/Win64EHDumper.cpp @@ -0,0 +1,328 @@ +//===- Win64EHDumper.cpp - Win64 EH Printer ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Win64EHDumper.h" +#include "llvm-readobj.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::Win64EH; + +static const EnumEntry<unsigned> UnwindFlags[] = { + { "ExceptionHandler", UNW_ExceptionHandler }, + { "TerminateHandler", UNW_TerminateHandler }, + { "ChainInfo" , UNW_ChainInfo } +}; + +static const EnumEntry<unsigned> UnwindOpInfo[] = { + { "RAX", 0 }, + { "RCX", 1 }, + { "RDX", 2 }, + { "RBX", 3 }, + { "RSP", 4 }, + { "RBP", 5 }, + { "RSI", 6 }, + { "RDI", 7 }, + { "R8", 8 }, + { "R9", 9 }, + { "R10", 10 }, + { "R11", 11 }, + { "R12", 12 }, + { "R13", 13 }, + { "R14", 14 }, + { "R15", 15 } +}; + +static uint64_t getOffsetOfLSDA(const UnwindInfo& UI) { + return static_cast<const char*>(UI.getLanguageSpecificData()) + - reinterpret_cast<const char*>(&UI); +} + +static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UC) { + if (UC.size() < 3) + return 0; + return UC[1].FrameOffset + (static_cast<uint32_t>(UC[2].FrameOffset) << 16); +} + +// Returns the name of the unwind code. +static StringRef getUnwindCodeTypeName(uint8_t Code) { + switch (Code) { + default: llvm_unreachable("Invalid unwind code"); + case UOP_PushNonVol: return "PUSH_NONVOL"; + case UOP_AllocLarge: return "ALLOC_LARGE"; + case UOP_AllocSmall: return "ALLOC_SMALL"; + case UOP_SetFPReg: return "SET_FPREG"; + case UOP_SaveNonVol: return "SAVE_NONVOL"; + case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR"; + case UOP_SaveXMM128: return "SAVE_XMM128"; + case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR"; + case UOP_PushMachFrame: return "PUSH_MACHFRAME"; + } +} + +// Returns the name of a referenced register. +static StringRef getUnwindRegisterName(uint8_t Reg) { + switch (Reg) { + default: llvm_unreachable("Invalid register"); + case 0: return "RAX"; + case 1: return "RCX"; + case 2: return "RDX"; + case 3: return "RBX"; + case 4: return "RSP"; + case 5: return "RBP"; + case 6: return "RSI"; + case 7: return "RDI"; + case 8: return "R8"; + case 9: return "R9"; + case 10: return "R10"; + case 11: return "R11"; + case 12: return "R12"; + case 13: return "R13"; + case 14: return "R14"; + case 15: return "R15"; + } +} + +// Calculates the number of array slots required for the unwind code. +static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { + switch (UnwindCode.getUnwindOp()) { + default: llvm_unreachable("Invalid unwind code"); + case UOP_PushNonVol: + case UOP_AllocSmall: + case UOP_SetFPReg: + case UOP_PushMachFrame: + return 1; + case UOP_SaveNonVol: + case UOP_SaveXMM128: + return 2; + case UOP_SaveNonVolBig: + case UOP_SaveXMM128Big: + return 3; + case UOP_AllocLarge: + return (UnwindCode.getOpInfo() == 0) ? 2 : 3; + } +} + +static std::string formatSymbol(const Dumper::Context &Ctx, + const coff_section *Section, uint64_t Offset, + uint32_t Displacement) { + std::string Buffer; + raw_string_ostream OS(Buffer); + + StringRef Name; + SymbolRef Symbol; + if (Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData) || + Symbol.getName(Name)) { + OS << format(" (0x%" PRIX64 ")", Offset); + return OS.str(); + } + + OS << Name; + if (Displacement > 0) + OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset); + else + OS << format(" (0x%" PRIX64 ")", Offset); + return OS.str(); +} + +static error_code resolveRelocation(const Dumper::Context &Ctx, + const coff_section *Section, + uint64_t Offset, + const coff_section *&ResolvedSection, + uint64_t &ResolvedAddress) { + SymbolRef Symbol; + if (error_code EC = Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData)) + return EC; + + if (error_code EC = Symbol.getAddress(ResolvedAddress)) + return EC; + + section_iterator SI = Ctx.COFF.section_begin(); + if (error_code EC = Symbol.getSection(SI)) + return EC; + + ResolvedSection = Ctx.COFF.getCOFFSection(*SI); + return object_error::success; +} + +namespace llvm { +namespace Win64EH { +void Dumper::printRuntimeFunctionEntry(const Context &Ctx, + const coff_section *Section, + uint64_t Offset, + const RuntimeFunction &RF) { + SW.printString("StartAddress", + formatSymbol(Ctx, Section, Offset + 0, RF.StartAddress)); + SW.printString("EndAddress", + formatSymbol(Ctx, Section, Offset + 4, RF.EndAddress)); + SW.printString("UnwindInfoAddress", + formatSymbol(Ctx, Section, Offset + 8, RF.UnwindInfoOffset)); +} + +// Prints one unwind code. Because an unwind code can occupy up to 3 slots in +// the unwind codes array, this function requires that the correct number of +// slots is provided. +void Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) { + assert(UC.size() >= getNumUsedSlots(UC[0])); + + SW.startLine() << format("0x%02X: ", unsigned(UC[0].u.CodeOffset)) + << getUnwindCodeTypeName(UC[0].getUnwindOp()); + + switch (UC[0].getUnwindOp()) { + case UOP_PushNonVol: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()); + break; + + case UOP_AllocLarge: + OS << " size=" + << ((UC[0].getOpInfo() == 0) ? UC[1].FrameOffset * 8 + : getLargeSlotValue(UC)); + break; + + case UOP_AllocSmall: + OS << " size=" << (UC[0].getOpInfo() + 1) * 8; + break; + + case UOP_SetFPReg: + if (UI.getFrameRegister() == 0) + OS << " reg=<invalid>"; + else + OS << " reg=" << getUnwindRegisterName(UI.getFrameRegister()) + << format(", offset=0x%X", UI.getFrameOffset() * 16); + break; + + case UOP_SaveNonVol: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) + << format(", offset=0x%X", UC[1].FrameOffset * 8); + break; + + case UOP_SaveNonVolBig: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) + << format(", offset=0x%X", getLargeSlotValue(UC)); + break; + + case UOP_SaveXMM128: + OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) + << format(", offset=0x%X", UC[1].FrameOffset * 16); + break; + + case UOP_SaveXMM128Big: + OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) + << format(", offset=0x%X", getLargeSlotValue(UC)); + break; + + case UOP_PushMachFrame: + OS << " errcode=" << (UC[0].getOpInfo() == 0 ? "no" : "yes"); + break; + } + + OS << "\n"; +} + +void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section, + off_t Offset, const UnwindInfo &UI) { + DictScope UIS(SW, "UnwindInfo"); + SW.printNumber("Version", UI.getVersion()); + SW.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags)); + SW.printNumber("PrologSize", UI.PrologSize); + if (UI.getFrameRegister()) { + SW.printEnum("FrameRegister", UI.getFrameRegister(), + makeArrayRef(UnwindOpInfo)); + SW.printHex("FrameOffset", UI.getFrameOffset()); + } else { + SW.printString("FrameRegister", StringRef("-")); + SW.printString("FrameOffset", StringRef("-")); + } + + SW.printNumber("UnwindCodeCount", UI.NumCodes); + { + ListScope UCS(SW, "UnwindCodes"); + ArrayRef<UnwindCode> UC(&UI.UnwindCodes[0], UI.NumCodes); + for (const UnwindCode *UCI = UC.begin(), *UCE = UC.end(); UCI < UCE; ++UCI) { + unsigned UsedSlots = getNumUsedSlots(*UCI); + if (UsedSlots > UC.size()) { + errs() << "corrupt unwind data"; + return; + } + + printUnwindCode(UI, ArrayRef<UnwindCode>(UCI, UCE)); + UCI = UCI + UsedSlots - 1; + } + } + + uint64_t LSDAOffset = Offset + getOffsetOfLSDA(UI); + if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { + SW.printString("Handler", + formatSymbol(Ctx, Section, LSDAOffset, + UI.getLanguageSpecificHandlerOffset())); + } else if (UI.getFlags() & UNW_ChainInfo) { + if (const RuntimeFunction *Chained = UI.getChainedFunctionEntry()) { + DictScope CS(SW, "Chained"); + printRuntimeFunctionEntry(Ctx, Section, LSDAOffset, *Chained); + } + } +} + +void Dumper::printRuntimeFunction(const Context &Ctx, + const coff_section *Section, + uint64_t SectionOffset, + const RuntimeFunction &RF) { + DictScope RFS(SW, "RuntimeFunction"); + printRuntimeFunctionEntry(Ctx, Section, SectionOffset, RF); + + const coff_section *XData; + uint64_t Offset; + if (error(resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset))) + return; + + ArrayRef<uint8_t> Contents; + if (error(Ctx.COFF.getSectionContents(XData, Contents)) || Contents.empty()) + return; + + Offset = Offset + RF.UnwindInfoOffset; + if (Offset > Contents.size()) + return; + + const auto UI = reinterpret_cast<const UnwindInfo*>(Contents.data() + Offset); + printUnwindInfo(Ctx, XData, Offset, *UI); +} + +void Dumper::printData(const Context &Ctx) { + for (const auto &Section : Ctx.COFF.sections()) { + StringRef Name; + if (error(Section.getName(Name))) + continue; + + if (Name != ".pdata" && !Name.startswith(".pdata$")) + continue; + + const coff_section *PData = Ctx.COFF.getCOFFSection(Section); + ArrayRef<uint8_t> Contents; + if (error(Ctx.COFF.getSectionContents(PData, Contents)) || Contents.empty()) + continue; + + const RuntimeFunction *Entries = + reinterpret_cast<const RuntimeFunction *>(Contents.data()); + const size_t Count = Contents.size() / sizeof(RuntimeFunction); + ArrayRef<RuntimeFunction> RuntimeFunctions(Entries, Count); + + size_t Index = 0; + for (const auto &RF : RuntimeFunctions) { + printRuntimeFunction(Ctx, Ctx.COFF.getCOFFSection(Section), + Index * sizeof(RuntimeFunction), RF); + ++Index; + } + } +} +} +} + diff --git a/tools/llvm-readobj/Win64EHDumper.h b/tools/llvm-readobj/Win64EHDumper.h new file mode 100644 index 0000000..2eac810 --- /dev/null +++ b/tools/llvm-readobj/Win64EHDumper.h @@ -0,0 +1,62 @@ +//===- Win64EHDumper.h - Win64 EH Printing ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H +#define LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H + +#include "StreamWriter.h" +#include "llvm/Support/Win64EH.h" + +namespace llvm { +namespace object { +class COFFObjectFile; +class SymbolRef; +struct coff_section; +} + +namespace Win64EH { +class Dumper { + StreamWriter &SW; + raw_ostream &OS; + +public: + typedef error_code (*SymbolResolver)(const object::coff_section *, uint64_t, + object::SymbolRef &, void *); + + struct Context { + const object::COFFObjectFile &COFF; + SymbolResolver ResolveSymbol; + void *UserData; + + Context(const object::COFFObjectFile &COFF, SymbolResolver Resolver, + void *UserData) + : COFF(COFF), ResolveSymbol(Resolver), UserData(UserData) {} + }; + +private: + void printRuntimeFunctionEntry(const Context &Ctx, + const object::coff_section *Section, + uint64_t SectionOffset, + const RuntimeFunction &RF); + void printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC); + void printUnwindInfo(const Context &Ctx, const object::coff_section *Section, + off_t Offset, const UnwindInfo &UI); + void printRuntimeFunction(const Context &Ctx, + const object::coff_section *Section, + uint64_t SectionOffset, const RuntimeFunction &RF); + +public: + Dumper(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {} + + void printData(const Context &Ctx); +}; +} +} + +#endif diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index ac43653..be5c345 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -18,6 +18,7 @@ #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" @@ -51,6 +52,11 @@ EntryPoint("entry", cl::desc("Function to call as entry point."), cl::init("_main")); +static cl::list<std::string> +Dylibs("dylib", + cl::desc("Add library."), + cl::ZeroOrMore); + /* *** */ // A trivial memory manager that doesn't do anything fancy, just uses the @@ -69,7 +75,7 @@ public: void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) override { - return 0; + return nullptr; } bool finalizeMemory(std::string *ErrMsg) override { return false; } @@ -85,7 +91,7 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) { - sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); FunctionMemory.push_back(MB); return (uint8_t*)MB.base(); } @@ -95,7 +101,7 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, unsigned SectionID, StringRef SectionName, bool IsReadOnly) { - sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); DataMemory.push_back(MB); return (uint8_t*)MB.base(); } @@ -121,9 +127,25 @@ static int Error(const Twine &Msg) { return 1; } +static void loadDylibs() { + for (const std::string &Dylib : Dylibs) { + if (sys::fs::is_regular_file(Dylib)) { + std::string ErrMsg; + if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg)) + llvm::errs() << "Error loading '" << Dylib << "': " + << ErrMsg << "\n"; + } else + llvm::errs() << "Dylib not found: '" << Dylib << "'.\n"; + } +} + + /* *** */ static int printLineInfoForInput() { + // Load any dylibs requested on the command line. + loadDylibs(); + // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); @@ -172,8 +194,7 @@ static int printLineInfoForInput() { DILineInfoTable::iterator End = Lines.end(); for (DILineInfoTable::iterator It = Begin; It != End; ++It) { outs() << " Line info @ " << It->first - Addr << ": " - << It->second.getFileName() - << ", line:" << It->second.getLine() << "\n"; + << It->second.FileName << ", line:" << It->second.Line << "\n"; } } } @@ -183,6 +204,9 @@ static int printLineInfoForInput() { } static int executeInput() { + // Load any dylibs requested on the command line. + loadDylibs(); + // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(&MemMgr); @@ -214,7 +238,7 @@ static int executeInput() { // Get the address of the entry point (_main by default). void *MainAddress = Dyld.getSymbolAddress(EntryPoint); - if (MainAddress == 0) + if (!MainAddress) return Error("no definition for '" + EntryPoint + "'"); // Invalidate the instruction cache for each loaded function. @@ -235,7 +259,7 @@ static int executeInput() { const char **Argv = new const char*[2]; // Use the name of the first input object module as argv[0] for the target. Argv[0] = InputFileList[0].c_str(); - Argv[1] = 0; + Argv[1] = nullptr; return Main(1, Argv); } diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile index 7bbc24c..19077a3 100644 --- a/tools/llvm-shlib/Makefile +++ b/tools/llvm-shlib/Makefile @@ -9,8 +9,8 @@ LEVEL := ../.. -LIBRARYNAME = LLVM-$(LLVMVersion) -LIBRARYALIASNAME = LLVM-$(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR)$(LLVM_VERSION_SUFFIX) +LIBRARYNAME = LLVM-$(LLVM_VERSION_MAJOR).$(LLVM_VERSION_MINOR)$(LLVM_VERSION_SUFFIX) +LIBRARYALIASNAME = LLVM-$(LLVMVersion) NO_BUILD_ARCHIVE := 1 LINK_LIBS_IN_SHARED := 1 diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index d1bd45a..58eafd4 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -93,7 +93,7 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - const char *radix_fmt = 0; + const char *radix_fmt = nullptr; switch (Radix) { case octal: radix_fmt = PRIo64; diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 18f1e6c..23d3b63 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/PassManager.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" @@ -245,7 +246,7 @@ protected: /// Pick a random scalar type. Type *pickScalarType() { - Type *t = 0; + Type *t = nullptr; do { switch (Ran->Rand() % 30) { case 0: t = Type::getInt1Ty(Context); break; @@ -271,7 +272,7 @@ protected: case 29: if (GenX86MMX) t = Type::getX86_MMXTy(Context); break; default: llvm_unreachable("Invalid scalar value"); } - } while (t == 0); + } while (t == nullptr); return t; } @@ -713,6 +714,7 @@ int main(int argc, char **argv) { PassManager Passes; Passes.add(createVerifierPass()); + Passes.add(createDebugInfoVerifierPass()); Passes.add(createPrintModulePass(Out->os())); Passes.run(*M.get()); Out->keep(); diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index 13f2f8f..3e71111 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -35,20 +35,11 @@ static bool error(error_code ec) { return true; } -static uint32_t -getDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) { - uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo | - llvm::DILineInfoSpecifier::AbsoluteFilePath; - if (Opts.PrintFunctions) - Flags |= llvm::DILineInfoSpecifier::FunctionName; - return Flags; -} - -static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName, - DILineInfo &LineInfo) { - std::string FileName = LineInfo.getFileName(); - LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName), - LineInfo.getLine(), LineInfo.getColumn()); +static DILineInfoSpecifier +getDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) { + return DILineInfoSpecifier( + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + Opts.PrintFunctions); } ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx) @@ -122,15 +113,15 @@ DILineInfo ModuleInfo::symbolizeCode( DILineInfo LineInfo; if (DebugInfoContext) { LineInfo = DebugInfoContext->getLineInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags(Opts)); + ModuleOffset, getDILineInfoSpecifier(Opts)); } // Override function name from symbol table if necessary. - if (Opts.PrintFunctions && Opts.UseSymbolTable) { + if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) { std::string FunctionName; uint64_t Start, Size; if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, FunctionName, Start, Size)) { - patchFunctionNameInDILineInfo(FunctionName, LineInfo); + LineInfo.FunctionName = FunctionName; } } return LineInfo; @@ -141,14 +132,14 @@ DIInliningInfo ModuleInfo::symbolizeInlinedCode( DIInliningInfo InlinedContext; if (DebugInfoContext) { InlinedContext = DebugInfoContext->getInliningInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags(Opts)); + ModuleOffset, getDILineInfoSpecifier(Opts)); } // Make sure there is at least one frame in context. if (InlinedContext.getNumberOfFrames() == 0) { InlinedContext.addFrame(DILineInfo()); } // Override the function name in lower frame with name from symbol table. - if (Opts.PrintFunctions && Opts.UseSymbolTable) { + if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) { DIInliningInfo PatchedInlinedContext; for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) { DILineInfo LineInfo = InlinedContext.getFrame(i); @@ -157,7 +148,7 @@ DIInliningInfo ModuleInfo::symbolizeInlinedCode( uint64_t Start, Size; if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, FunctionName, Start, Size)) { - patchFunctionNameInDILineInfo(FunctionName, LineInfo); + LineInfo.FunctionName = FunctionName; } } PatchedInlinedContext.addFrame(LineInfo); @@ -178,7 +169,7 @@ const char LLVMSymbolizer::kBadString[] = "??"; std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset) { ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); - if (Info == 0) + if (!Info) return printDILineInfo(DILineInfo()); if (Opts.PrintInlining) { DIInliningInfo InlinedContext = @@ -214,7 +205,6 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, void LLVMSymbolizer::flush() { DeleteContainerSeconds(Modules); - DeleteContainerPointers(ParsedBinariesAndObjects); BinaryForPath.clear(); ObjectFileForArch.clear(); } @@ -240,7 +230,7 @@ static bool findDebugBinary(const std::string &OrigPath, std::string &Result) { std::string OrigRealPath = OrigPath; #if defined(HAVE_REALPATH) - if (char *RP = realpath(OrigPath.c_str(), NULL)) { + if (char *RP = realpath(OrigPath.c_str(), nullptr)) { OrigRealPath = RP; free(RP); } @@ -306,14 +296,14 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { BinaryMapTy::iterator I = BinaryForPath.find(Path); if (I != BinaryForPath.end()) return I->second; - Binary *Bin = 0; - Binary *DbgBin = 0; + Binary *Bin = nullptr; + Binary *DbgBin = nullptr; 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.release(); - ParsedBinariesAndObjects.push_back(Bin); + Bin = ParsedBinary.get(); + ParsedBinariesAndObjects.push_back(std::move(ParsedBinary)); if (Bin->isMachO() || Bin->isMachOUniversalBinary()) { // On Darwin we may find DWARF in separate object file in // resource directory. @@ -323,11 +313,11 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { error_code EC = BinaryOrErr.getError(); if (EC != errc::no_such_file_or_directory && !error(EC)) { DbgBin = BinaryOrErr.get(); - ParsedBinariesAndObjects.push_back(DbgBin); + ParsedBinariesAndObjects.push_back(std::unique_ptr<Binary>(DbgBin)); } } // Try to locate the debug binary using .gnu_debuglink section. - if (DbgBin == 0) { + if (!DbgBin) { std::string DebuglinkName; uint32_t CRCHash; std::string DebugBinaryPath; @@ -336,12 +326,12 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { BinaryOrErr = createBinary(DebugBinaryPath); if (!error(BinaryOrErr.getError())) { DbgBin = BinaryOrErr.get(); - ParsedBinariesAndObjects.push_back(DbgBin); + ParsedBinariesAndObjects.push_back(std::unique_ptr<Binary>(DbgBin)); } } } } - if (DbgBin == 0) + if (!DbgBin) DbgBin = Bin; BinaryPair Res = std::make_pair(Bin, DbgBin); BinaryForPath[Path] = Res; @@ -350,9 +340,9 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { ObjectFile * LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) { - if (Bin == 0) - return 0; - ObjectFile *Res = 0; + if (!Bin) + return nullptr; + ObjectFile *Res = nullptr; if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) { ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find( std::make_pair(UB, ArchName)); @@ -360,8 +350,8 @@ LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName return I->second; std::unique_ptr<ObjectFile> ParsedObj; if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) { - Res = ParsedObj.release(); - ParsedBinariesAndObjects.push_back(Res); + Res = ParsedObj.get(); + ParsedBinariesAndObjects.push_back(std::move(ParsedObj)); } ObjectFileForArch[std::make_pair(UB, ArchName)] = Res; } else if (Bin->isObject()) { @@ -390,10 +380,10 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName); ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName); - if (Obj == 0) { + if (!Obj) { // Failed to find valid object file. - Modules.insert(make_pair(ModuleName, (ModuleInfo *)0)); - return 0; + Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr)); + return nullptr; } DIContext *Context = DIContext::getDWARFContext(DbgObj); assert(Context); @@ -407,19 +397,18 @@ std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const { // cannot fetch. We replace it to "??" to make our output closer to addr2line. static const std::string kDILineInfoBadString = "<invalid>"; std::stringstream Result; - if (Opts.PrintFunctions) { - std::string FunctionName = LineInfo.getFunctionName(); + if (Opts.PrintFunctions != FunctionNameKind::None) { + std::string FunctionName = LineInfo.FunctionName; if (FunctionName == kDILineInfoBadString) FunctionName = kBadString; else if (Opts.Demangle) FunctionName = DemangleName(FunctionName); Result << FunctionName << "\n"; } - std::string Filename = LineInfo.getFileName(); + std::string Filename = LineInfo.FileName; if (Filename == kDILineInfoBadString) Filename = kBadString; - Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn() - << "\n"; + Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n"; return Result.str(); } @@ -436,7 +425,7 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name) { if (Name.substr(0, 2) != "_Z") return Name; int status = 0; - char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status); + char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status); if (status != 0) return Name; std::string Result = DemangledName; diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index 288be80..45febe0 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -19,10 +19,12 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" #include <map> +#include <memory> #include <string> namespace llvm { +typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; using namespace object; namespace symbolize { @@ -33,17 +35,17 @@ class LLVMSymbolizer { public: struct Options { bool UseSymbolTable : 1; - bool PrintFunctions : 1; + FunctionNameKind PrintFunctions; bool PrintInlining : 1; bool Demangle : 1; std::string DefaultArch; - Options(bool UseSymbolTable = true, bool PrintFunctions = true, + Options(bool UseSymbolTable = true, + FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, bool PrintInlining = true, bool Demangle = true, std::string DefaultArch = "") : UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions), PrintInlining(PrintInlining), Demangle(Demangle), - DefaultArch(DefaultArch) { - } + DefaultArch(DefaultArch) {} }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} @@ -72,7 +74,7 @@ private: std::string printDILineInfo(DILineInfo LineInfo) const; // Owns all the parsed binaries and object files. - SmallVector<Binary*, 4> ParsedBinariesAndObjects; + SmallVector<std::unique_ptr<Binary>, 4> ParsedBinariesAndObjects; // Owns module info objects. typedef std::map<std::string, ModuleInfo *> ModuleMapTy; ModuleMapTy Modules; diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index 83f5c5e..29db172 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -35,10 +35,15 @@ ClUseSymbolTable("use-symbol-table", cl::init(true), cl::desc("Prefer names in symbol table to names " "in debug info")); -static cl::opt<bool> -ClPrintFunctions("functions", cl::init(true), - cl::desc("Print function names as well as line " - "information for a given address")); +static cl::opt<FunctionNameKind> ClPrintFunctions( + "functions", cl::init(FunctionNameKind::LinkageName), + cl::desc("Print function name for a given address:"), + cl::values(clEnumValN(FunctionNameKind::None, "none", "omit function name"), + clEnumValN(FunctionNameKind::ShortName, "short", + "print short function name"), + clEnumValN(FunctionNameKind::LinkageName, "linkage", + "print function linkage name"), + clEnumValEnd)); static cl::opt<bool> ClPrintInlining("inlining", cl::init(true), @@ -85,7 +90,7 @@ static bool parseCommand(bool &IsData, std::string &ModuleName, char quote = *pos; pos++; char *end = strchr(pos, quote); - if (end == 0) + if (!end) return false; ModuleName = std::string(pos, end - pos); pos = end + 1; diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index cc8318a..64abf5c 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -56,37 +56,45 @@ static void lto_initialize() { } } -/// lto_get_version - Returns a printable string. +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOCodeGenerator, lto_code_gen_t) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) + +// Convert the subtarget features into a string to pass to LTOCodeGenerator. +static void lto_add_attrs(lto_code_gen_t cg) { + LTOCodeGenerator *CG = unwrap(cg); + if (MAttrs.size()) { + std::string attrs; + for (unsigned i = 0; i < MAttrs.size(); ++i) { + if (i > 0) + attrs.append(","); + attrs.append(MAttrs[i]); + } + + CG->setAttr(attrs.c_str()); + } +} + extern const char* lto_get_version() { return LTOCodeGenerator::getVersionString(); } -/// lto_get_error_message - Returns the last error string or NULL if last -/// operation was successful. const char* lto_get_error_message() { return sLastErrorString.c_str(); } -/// lto_module_is_object_file - Validates if a file is a loadable object file. bool lto_module_is_object_file(const char* path) { return LTOModule::isBitcodeFile(path); } -/// lto_module_is_object_file_for_target - Validates if a file is a loadable -/// object file compilable for requested target. bool lto_module_is_object_file_for_target(const char* path, const char* target_triplet_prefix) { return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix); } -/// lto_module_is_object_file_in_memory - Validates if a buffer is a loadable -/// object file. bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { return LTOModule::isBitcodeFile(mem, length); } -/// lto_module_is_object_file_in_memory_for_target - Validates if a buffer is a -/// loadable object file compilable for the target. bool lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, @@ -94,120 +102,89 @@ lto_module_is_object_file_in_memory_for_target(const void* mem, return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix); } -/// lto_module_create - Loads an object file from disk. Returns NULL on error -/// (check lto_get_error_message() for details). lto_module_t lto_module_create(const char* path) { lto_initialize(); llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - return LTOModule::makeLTOModule(path, Options, sLastErrorString); + return wrap(LTOModule::makeLTOModule(path, Options, sLastErrorString)); } -/// lto_module_create_from_fd - Loads an object file from disk. Returns NULL on -/// 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 = InitTargetOptionsFromCodeGenFlags(); - return LTOModule::makeLTOModule(fd, path, size, Options, sLastErrorString); + return wrap( + LTOModule::makeLTOModule(fd, path, size, Options, sLastErrorString)); } -/// lto_module_create_from_fd_at_offset - Loads an object file from disk. -/// Returns NULL on error (check lto_get_error_message() for details). lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, size_t map_size, off_t offset) { lto_initialize(); llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - return LTOModule::makeLTOModule(fd, path, map_size, offset, Options, - sLastErrorString); + return wrap(LTOModule::makeLTOModule(fd, path, map_size, offset, Options, + sLastErrorString)); } -/// lto_module_create_from_memory - Loads an object file from memory. Returns -/// 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 = InitTargetOptionsFromCodeGenFlags(); - return LTOModule::makeLTOModule(mem, length, Options, sLastErrorString); + return wrap(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); + return wrap( + 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) { - delete mod; -} +void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); } -/// lto_module_get_target_triple - Returns triplet string which the object -/// module was compiled under. const char* lto_module_get_target_triple(lto_module_t mod) { - return mod->getTargetTriple(); + return unwrap(mod)->getTargetTriple(); } -/// lto_module_set_target_triple - Sets triple string with which the object will -/// be codegened. void lto_module_set_target_triple(lto_module_t mod, const char *triple) { - return mod->setTargetTriple(triple); + return unwrap(mod)->setTargetTriple(triple); } -/// lto_module_get_num_symbols - Returns the number of symbols in the object -/// module. unsigned int lto_module_get_num_symbols(lto_module_t mod) { - return mod->getSymbolCount(); + return unwrap(mod)->getSymbolCount(); } -/// lto_module_get_symbol_name - Returns the name of the ith symbol in the -/// object module. const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { - return mod->getSymbolName(index); + return unwrap(mod)->getSymbolName(index); } -/// lto_module_get_symbol_attribute - Returns the attributes of the ith symbol -/// in the object module. lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index) { - return mod->getSymbolAttributes(index); + return unwrap(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(); + return unwrap(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); + return unwrap(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(); + return unwrap(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); + return unwrap(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); + unwrap(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(); @@ -216,102 +193,76 @@ lto_code_gen_t lto_codegen_create(void) { LTOCodeGenerator *CodeGen = new LTOCodeGenerator(); if (CodeGen) CodeGen->setTargetOptions(Options); - return CodeGen; + return wrap(CodeGen); } -/// lto_codegen_dispose - Frees all memory for a code generator. Upon return the -/// lto_code_gen_t is no longer valid. -void lto_codegen_dispose(lto_code_gen_t cg) { - delete cg; -} +void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); } -/// lto_codegen_add_module - Add an object module to the set of modules for -/// which code will be generated. Returns true on error (check -/// lto_get_error_message() for details). bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { - return !cg->addModule(mod, sLastErrorString); + return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString); } -/// lto_codegen_set_debug_model - Sets what if any format of debug info should -/// be generated. Returns true on error (check lto_get_error_message() for -/// details). bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { - cg->setDebugInfo(debug); + unwrap(cg)->setDebugInfo(debug); return false; } -/// lto_codegen_set_pic_model - Sets what code model to generated. Returns true -/// on error (check lto_get_error_message() for details). bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) { - cg->setCodePICModel(model); + unwrap(cg)->setCodePICModel(model); return false; } -/// lto_codegen_set_cpu - Sets the cpu to generate code for. void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) { - return cg->setCpu(cpu); + return unwrap(cg)->setCpu(cpu); +} + +void lto_codegen_set_attr(lto_code_gen_t cg, const char *attr) { + return unwrap(cg)->setAttr(attr); } -/// lto_codegen_set_assembler_path - Sets the path to the assembler tool. void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) { // In here only for backwards compatibility. We use MC now. } -/// lto_codegen_set_assembler_args - Sets extra arguments that libLTO should -/// pass to the assembler. void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, int nargs) { // In here only for backwards compatibility. We use MC now. } -/// lto_codegen_add_must_preserve_symbol - Adds to a list of all global symbols -/// that must exist in the final generated code. If a function is not listed -/// there, it might be inlined into every usage and optimized away. void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char *symbol) { - cg->addMustPreserveSymbol(symbol); + unwrap(cg)->addMustPreserveSymbol(symbol); } -/// lto_codegen_write_merged_modules - Writes a new file at the specified path -/// that contains the merged contents of all modules added so far. Returns true -/// on error (check lto_get_error_message() for details). bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { if (!parsedOptions) { - cg->parseCodeGenDebugOptions(); + unwrap(cg)->parseCodeGenDebugOptions(); + lto_add_attrs(cg); parsedOptions = true; } - return !cg->writeMergedModules(path, sLastErrorString); + return !unwrap(cg)->writeMergedModules(path, sLastErrorString); } -/// lto_codegen_compile - Generates code for all added modules into one native -/// object file. On success returns a pointer to a generated mach-o/ELF buffer -/// and length set to the buffer size. The buffer is owned by the lto_code_gen_t -/// object and will be freed when lto_codegen_dispose() is called, or -/// lto_codegen_compile() is called again. On failure, returns NULL (check -/// lto_get_error_message() for details). const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { if (!parsedOptions) { - cg->parseCodeGenDebugOptions(); + unwrap(cg)->parseCodeGenDebugOptions(); + lto_add_attrs(cg); parsedOptions = true; } - return cg->compile(length, DisableOpt, DisableInline, DisableGVNLoadPRE, - sLastErrorString); + return unwrap(cg)->compile(length, DisableOpt, DisableInline, + DisableGVNLoadPRE, sLastErrorString); } -/// lto_codegen_compile_to_file - Generates code for all added modules into one -/// native object file. The name of the file is written to name. Returns true on -/// error. bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { if (!parsedOptions) { - cg->parseCodeGenDebugOptions(); + unwrap(cg)->parseCodeGenDebugOptions(); + lto_add_attrs(cg); parsedOptions = true; } - return !cg->compile_to_file(name, DisableOpt, DisableInline, DisableGVNLoadPRE, - sLastErrorString); + return !unwrap(cg)->compile_to_file(name, DisableOpt, DisableInline, + DisableGVNLoadPRE, sLastErrorString); } -/// lto_codegen_debug_options - Used to pass extra options to the code -/// generator. void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { - cg->setCodeGenDebugOptions(opt); + unwrap(cg)->setCodeGenDebugOptions(opt); } diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt index 9c10c04..f167ed5 100644 --- a/tools/obj2yaml/CMakeLists.txt +++ b/tools/obj2yaml/CMakeLists.txt @@ -4,5 +4,5 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_utility(obj2yaml - obj2yaml.cpp coff2yaml.cpp + obj2yaml.cpp coff2yaml.cpp elf2yaml.cpp Error.cpp ) diff --git a/tools/obj2yaml/Error.cpp b/tools/obj2yaml/Error.cpp new file mode 100644 index 0000000..7be468d --- /dev/null +++ b/tools/obj2yaml/Error.cpp @@ -0,0 +1,54 @@ +//===- Error.cpp - system_error extensions for obj2yaml ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class _obj2yaml_error_category : public error_category { +public: + const char *name() const override; + std::string message(int ev) const override; + error_condition default_error_condition(int ev) const override; +}; +} // namespace + +const char *_obj2yaml_error_category::name() const { return "obj2yaml"; } + +std::string _obj2yaml_error_category::message(int ev) const { + switch (ev) { + case obj2yaml_error::success: + return "Success"; + case obj2yaml_error::file_not_found: + return "No such file."; + case obj2yaml_error::unrecognized_file_format: + return "Unrecognized file type."; + case obj2yaml_error::unsupported_obj_file_format: + return "Unsupported object file format."; + default: + llvm_unreachable("An enumerator of obj2yaml_error does not have a message " + "defined."); + } +} + +error_condition +_obj2yaml_error_category::default_error_condition(int ev) const { + if (ev == obj2yaml_error::success) + return errc::success; + return errc::invalid_argument; +} + +namespace llvm { +const error_category &obj2yaml_category() { + static _obj2yaml_error_category o; + return o; +} +} // namespace llvm diff --git a/tools/obj2yaml/Error.h b/tools/obj2yaml/Error.h new file mode 100644 index 0000000..a326664 --- /dev/null +++ b/tools/obj2yaml/Error.h @@ -0,0 +1,42 @@ +//===- Error.h - system_error extensions for obj2yaml -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_ERROR_H +#define LLVM_TOOLS_ERROR_H + +#include "llvm/Support/system_error.h" + +namespace llvm { + +const error_category &obj2yaml_category(); + +struct obj2yaml_error { + enum _ { + success = 0, + file_not_found, + unrecognized_file_format, + unsupported_obj_file_format + }; + _ v_; + + obj2yaml_error(_ v) : v_(v) {} + explicit obj2yaml_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + +inline error_code make_error_code(obj2yaml_error e) { + return error_code(static_cast<int>(e), obj2yaml_category()); +} + +template <> struct is_error_code_enum<obj2yaml_error> : std::true_type { }; +template <> struct is_error_code_enum<obj2yaml_error::_> : std::true_type { }; + +} // namespace llvm + +#endif diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index ef70922..42b09d3 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -210,10 +210,7 @@ COFFYAML::Object &COFFDumper::getYAMLObj() { return YAMLObj; } -error_code coff2yaml(raw_ostream &Out, MemoryBuffer *Buff) { - error_code ec; - object::COFFObjectFile Obj(Buff, ec); - check(ec); +error_code coff2yaml(raw_ostream &Out, const object::COFFObjectFile &Obj) { COFFDumper Dumper(Obj); yaml::Output Yout(Out); diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp new file mode 100644 index 0000000..7642921 --- /dev/null +++ b/tools/obj2yaml/elf2yaml.cpp @@ -0,0 +1,290 @@ +//===------ utils/elf2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "obj2yaml.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ELFYAML.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/YAMLTraits.h" + +using namespace llvm; + +namespace { + +template <class ELFT> +class ELFDumper { + typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename object::ELFFile<ELFT>::Elf_Sym_Iter Elf_Sym_Iter; + + const object::ELFFile<ELFT> &Obj; + + error_code dumpSymbol(Elf_Sym_Iter Sym, ELFYAML::Symbol &S); + error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); + template <class RelT> + error_code dumpRelocation(const Elf_Shdr *Shdr, const RelT *Rel, + ELFYAML::Relocation &R); + + ErrorOr<ELFYAML::RelocationSection *> dumpRelSection(const Elf_Shdr *Shdr); + ErrorOr<ELFYAML::RelocationSection *> dumpRelaSection(const Elf_Shdr *Shdr); + ErrorOr<ELFYAML::RawContentSection *> + dumpContentSection(const Elf_Shdr *Shdr); + +public: + ELFDumper(const object::ELFFile<ELFT> &O); + ErrorOr<ELFYAML::Object *> dump(); +}; + +} + +template <class ELFT> +ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O) + : Obj(O) {} + +template <class ELFT> +ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() { + auto Y = make_unique<ELFYAML::Object>(); + + // Dump header + Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass()); + Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding()); + Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI]; + Y->Header.Type = Obj.getHeader()->e_type; + Y->Header.Machine = Obj.getHeader()->e_machine; + Y->Header.Flags = Obj.getHeader()->e_flags; + Y->Header.Entry = Obj.getHeader()->e_entry; + + // Dump sections + for (const Elf_Shdr &Sec : Obj.sections()) { + switch (Sec.sh_type) { + case ELF::SHT_NULL: + case ELF::SHT_SYMTAB: + case ELF::SHT_DYNSYM: + case ELF::SHT_STRTAB: + // Do not dump these sections. + break; + case ELF::SHT_RELA: { + ErrorOr<ELFYAML::RelocationSection *> S = dumpRelaSection(&Sec); + if (error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + break; + } + case ELF::SHT_REL: { + ErrorOr<ELFYAML::RelocationSection *> S = dumpRelSection(&Sec); + if (error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + break; + } + default: { + ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec); + if (error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + } + } + } + + // Dump symbols + bool IsFirstSym = true; + for (auto SI = Obj.begin_symbols(), SE = Obj.end_symbols(); SI != SE; ++SI) { + if (IsFirstSym) { + IsFirstSym = false; + continue; + } + + ELFYAML::Symbol S; + if (error_code EC = ELFDumper<ELFT>::dumpSymbol(SI, S)) + return EC; + + switch (SI->getBinding()) + { + case ELF::STB_LOCAL: + Y->Symbols.Local.push_back(S); + break; + case ELF::STB_GLOBAL: + Y->Symbols.Global.push_back(S); + break; + case ELF::STB_WEAK: + Y->Symbols.Weak.push_back(S); + break; + default: + llvm_unreachable("Unknown ELF symbol binding"); + } + } + + return Y.release(); +} + +template <class ELFT> +error_code ELFDumper<ELFT>::dumpSymbol(Elf_Sym_Iter Sym, ELFYAML::Symbol &S) { + S.Type = Sym->getType(); + S.Value = Sym->st_value; + S.Size = Sym->st_size; + + ErrorOr<StringRef> NameOrErr = Obj.getSymbolName(Sym); + if (error_code EC = NameOrErr.getError()) + return EC; + S.Name = NameOrErr.get(); + + const Elf_Shdr *Shdr = Obj.getSection(&*Sym); + if (!Shdr) + return obj2yaml_error::success; + + NameOrErr = Obj.getSectionName(Shdr); + if (error_code EC = NameOrErr.getError()) + return EC; + S.Section = NameOrErr.get(); + + return obj2yaml_error::success; +} + +template <class ELFT> +template <class RelT> +error_code ELFDumper<ELFT>::dumpRelocation(const Elf_Shdr *Shdr, + const RelT *Rel, + ELFYAML::Relocation &R) { + R.Type = Rel->getType(Obj.isMips64EL()); + R.Offset = Rel->r_offset; + R.Addend = 0; + + auto NamePair = Obj.getRelocationSymbol(Shdr, Rel); + if (!NamePair.first) + return obj2yaml_error::success; + + ErrorOr<StringRef> NameOrErr = + Obj.getSymbolName(NamePair.first, NamePair.second); + if (error_code EC = NameOrErr.getError()) + return EC; + R.Symbol = NameOrErr.get(); + + return obj2yaml_error::success; +} + +template <class ELFT> +error_code ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr, + ELFYAML::Section &S) { + S.Type = Shdr->sh_type; + S.Flags = Shdr->sh_flags; + S.Address = Shdr->sh_addr; + S.AddressAlign = Shdr->sh_addralign; + + ErrorOr<StringRef> NameOrErr = Obj.getSectionName(Shdr); + if (error_code EC = NameOrErr.getError()) + return EC; + S.Name = NameOrErr.get(); + + if (Shdr->sh_link != ELF::SHN_UNDEF) { + if (const Elf_Shdr *LinkSection = Obj.getSection(Shdr->sh_link)) { + NameOrErr = Obj.getSectionName(LinkSection); + if (error_code EC = NameOrErr.getError()) + return EC; + S.Link = NameOrErr.get(); + } + } + if (Shdr->sh_info != ELF::SHN_UNDEF) { + if (const Elf_Shdr *InfoSection = Obj.getSection(Shdr->sh_info)) { + NameOrErr = Obj.getSectionName(InfoSection); + if (error_code EC = NameOrErr.getError()) + return EC; + S.Info = NameOrErr.get(); + } + } + return obj2yaml_error::success; +} + +template <class ELFT> +ErrorOr<ELFYAML::RelocationSection *> +ELFDumper<ELFT>::dumpRelSection(const Elf_Shdr *Shdr) { + assert(Shdr->sh_type == ELF::SHT_REL && "Section type is not SHT_REL"); + auto S = make_unique<ELFYAML::RelocationSection>(); + + if (error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + for (auto RI = Obj.begin_rel(Shdr), RE = Obj.end_rel(Shdr); RI != RE; + ++RI) { + ELFYAML::Relocation R; + if (error_code EC = dumpRelocation(Shdr, &*RI, R)) + return EC; + S->Relocations.push_back(R); + } + + return S.release(); +} + +template <class ELFT> +ErrorOr<ELFYAML::RelocationSection *> +ELFDumper<ELFT>::dumpRelaSection(const Elf_Shdr *Shdr) { + assert(Shdr->sh_type == ELF::SHT_RELA && "Section type is not SHT_RELA"); + auto S = make_unique<ELFYAML::RelocationSection>(); + + if (error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + for (auto RI = Obj.begin_rela(Shdr), RE = Obj.end_rela(Shdr); RI != RE; + ++RI) { + ELFYAML::Relocation R; + if (error_code EC = dumpRelocation(Shdr, &*RI, R)) + return EC; + R.Addend = RI->r_addend; + S->Relocations.push_back(R); + } + + return S.release(); +} + +template <class ELFT> +ErrorOr<ELFYAML::RawContentSection *> +ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { + auto S = make_unique<ELFYAML::RawContentSection>(); + + if (error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + ErrorOr<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(Shdr); + if (error_code EC = ContentOrErr.getError()) + return EC; + S->Content = object::yaml::BinaryRef(ContentOrErr.get()); + S->Size = S->Content.binary_size(); + + return S.release(); +} + +template <class ELFT> +static error_code elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj) { + ELFDumper<ELFT> Dumper(Obj); + ErrorOr<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); + if (error_code EC = YAMLOrErr.getError()) + return EC; + + std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); + yaml::Output Yout(Out); + Yout << *YAML; + + return object::object_error::success; +} + +error_code elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { + if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj)) + return elf2yaml(Out, *ELFObj->getELFFile()); + + if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj)) + return elf2yaml(Out, *ELFObj->getELFFile()); + + if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj)) + return elf2yaml(Out, *ELFObj->getELFFile()); + + if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj)) + return elf2yaml(Out, *ELFObj->getELFFile()); + + return obj2yaml_error::unsupported_obj_file_format; +} diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp index 38779fe..7fe034d 100644 --- a/tools/obj2yaml/obj2yaml.cpp +++ b/tools/obj2yaml/obj2yaml.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "Error.h" #include "obj2yaml.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" @@ -16,16 +17,32 @@ #include "llvm/Support/Signals.h" using namespace llvm; +using namespace llvm::object; -namespace { -enum ObjectFileType { - coff -}; +static error_code dumpObject(const ObjectFile &Obj) { + if (Obj.isCOFF()) + return coff2yaml(outs(), cast<COFFObjectFile>(Obj)); + if (Obj.isELF()) + return elf2yaml(outs(), Obj); + + return obj2yaml_error::unsupported_obj_file_format; } -cl::opt<ObjectFileType> InputFormat( - cl::desc("Choose input format"), - cl::values(clEnumVal(coff, "process COFF object files"), clEnumValEnd)); +static error_code dumpInput(StringRef File) { + if (File != "-" && !sys::fs::exists(File)) + return obj2yaml_error::file_not_found; + + ErrorOr<Binary *> BinaryOrErr = createBinary(File); + if (error_code EC = BinaryOrErr.getError()) + return EC; + + std::unique_ptr<Binary> Binary(BinaryOrErr.get()); + // TODO: If this is an archive, then burst it and dump each entry + if (ObjectFile *Obj = dyn_cast<ObjectFile>(Binary.get())) + return dumpObject(*Obj); + + return obj2yaml_error::unrecognized_file_format; +} cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); @@ -36,17 +53,9 @@ int main(int argc, char *argv[]) { PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - // Process the input file - 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.release()); - if (ec) - errs() << "Error: " << ec.message() << " dumping COFF file\n"; + if (error_code EC = dumpInput(InputFilename)) { + errs() << "Error: '" << EC.message() << "'\n"; + return 1; } return 0; diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h index bde82e6..73c58fa 100644 --- a/tools/obj2yaml/obj2yaml.h +++ b/tools/obj2yaml/obj2yaml.h @@ -13,10 +13,13 @@ #ifndef LLVM_TOOLS_OBJ2YAML_H #define LLVM_TOOLS_OBJ2YAML_H -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -llvm::error_code coff2yaml(llvm::raw_ostream &Out, llvm::MemoryBuffer *TheObj); +llvm::error_code coff2yaml(llvm::raw_ostream &Out, + const llvm::object::COFFObjectFile &Obj); +llvm::error_code elf2yaml(llvm::raw_ostream &Out, + const llvm::object::ObjectFile &Obj); #endif diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp index fc4a1bf..8076ff4 100644 --- a/tools/opt/NewPMDriver.cpp +++ b/tools/opt/NewPMDriver.cpp @@ -16,6 +16,7 @@ #include "NewPMDriver.h" #include "Passes.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/IR/IRPrintingPasses.h" @@ -34,14 +35,27 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, tool_output_file *Out, StringRef PassPipeline, OutputKind OK, VerifierKind VK) { FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; 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()); +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + MAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" + +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + CGAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" + +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + FAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" // Cross register the analysis managers through their proxies. MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); + MAM.registerPass(CGSCCAnalysisManagerModuleProxy(CGAM)); + CGAM.registerPass(FunctionAnalysisManagerCGSCCProxy(FAM)); + CGAM.registerPass(ModuleAnalysisManagerCGSCCProxy(MAM)); + FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM)); FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); ModulePassManager MPM; diff --git a/tools/opt/PassRegistry.def b/tools/opt/PassRegistry.def new file mode 100644 index 0000000..e1e4900 --- /dev/null +++ b/tools/opt/PassRegistry.def @@ -0,0 +1,51 @@ +//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the core LLVM +// libraries. This file describes both transformation passes and analyses +// Analyses are registered while transformation passes have names registered +// that can be used when providing a textual pass pipeline. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_ANALYSIS +#define MODULE_ANALYSIS(NAME, CREATE_PASS) +#endif +MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis()) +#undef MODULE_ANALYSIS + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS) +#endif +MODULE_PASS("print", PrintModulePass(dbgs())) +MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs())) +#undef MODULE_PASS + +#ifndef CGSCC_ANALYSIS +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) +#endif +#undef CGSCC_ANALYSIS + +#ifndef CGSCC_PASS +#define CGSCC_PASS(NAME, CREATE_PASS) +#endif +#undef CGSCC_PASS + +#ifndef FUNCTION_ANALYSIS +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif +#undef FUNCTION_ANALYSIS + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, CREATE_PASS) +#endif +FUNCTION_PASS("print", PrintFunctionPass(dbgs())) +#undef FUNCTION_PASS diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index ffdf9bf..a171f42 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "Passes.h" +#include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" @@ -31,6 +32,14 @@ struct NoOpModulePass { static StringRef name() { return "NoOpModulePass"; } }; +/// \brief No-op CGSCC pass which does nothing. +struct NoOpCGSCCPass { + PreservedAnalyses run(LazyCallGraph::SCC *C) { + return PreservedAnalyses::all(); + } + static StringRef name() { return "NoOpCGSCCPass"; } +}; + /// \brief No-op function pass which does nothing. struct NoOpFunctionPass { PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); } @@ -39,19 +48,29 @@ struct 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; + +#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#include "PassRegistry.def" + + return false; +} + +static bool isCGSCCPassName(StringRef Name) { + if (Name == "no-op-cgscc") return true; + +#define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#include "PassRegistry.def" return false; } static bool isFunctionPassName(StringRef Name) { if (Name == "no-op-function") return true; - if (Name == "print") return true; + +#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#include "PassRegistry.def" return false; } @@ -61,14 +80,30 @@ static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { MPM.addPass(NoOpModulePass()); return true; } - if (Name == "print") { - MPM.addPass(PrintModulePass(dbgs())); - return true; + +#define MODULE_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(CREATE_PASS); \ + return true; \ } - if (Name == "print-cg") { - MPM.addPass(LazyCallGraphPrinterPass(dbgs())); +#include "PassRegistry.def" + + return false; +} + +static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) { + if (Name == "no-op-cgscc") { + CGPM.addPass(NoOpCGSCCPass()); return true; } + +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(CREATE_PASS); \ + return true; \ + } +#include "PassRegistry.def" + return false; } @@ -77,10 +112,14 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { FPM.addPass(NoOpFunctionPass()); return true; } - if (Name == "print") { - FPM.addPass(PrintFunctionPass(dbgs())); - return true; + +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + FPM.addPass(CREATE_PASS); \ + return true; \ } +#include "PassRegistry.def" + return false; } @@ -121,6 +160,55 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM, } } +static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, + StringRef &PipelineText, + bool VerifyEachPass) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("cgscc(")) { + CGSCCPassManager NestedCGPM; + + // Parse the inner pipeline into the nested manager. + PipelineText = PipelineText.substr(strlen("cgscc(")); + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + CGPM.addPass(std::move(NestedCGPM)); + } 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. + CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM))); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End))) + return false; + // FIXME: No verifier support for CGSCC passes! + + 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) { @@ -139,6 +227,20 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // Now add the nested manager as a module pass. MPM.addPass(std::move(NestedMPM)); + } else if (PipelineText.startswith("cgscc(")) { + CGSCCPassManager NestedCGPM; + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("cgscc(")); + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + MPM.addPass( + createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM))); } else if (PipelineText.startswith("function(")) { FunctionPassManager NestedFPM; @@ -180,6 +282,14 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, if (PipelineText.startswith("module(")) return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && PipelineText.empty(); + if (PipelineText.startswith("cgscc(")) { + CGSCCPassManager CGPM; + if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + return true; + } if (PipelineText.startswith("function(")) { FunctionPassManager FPM; if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || @@ -196,6 +306,15 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && PipelineText.empty(); + if (isCGSCCPassName(FirstName)) { + CGSCCPassManager CGPM; + if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + return true; + } + if (isFunctionPassName(FirstName)) { FunctionPassManager FPM; if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp index cbc0a55..78ede2b 100644 --- a/tools/opt/PrintSCC.cpp +++ b/tools/opt/PrintSCC.cpp @@ -39,7 +39,7 @@ namespace { CFGSCC() : FunctionPass(ID) {} bool runOnFunction(Function& func) override; - void print(raw_ostream &O, const Module* = 0) const override { } + void print(raw_ostream &O, const Module* = nullptr) const override { } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); @@ -53,7 +53,7 @@ namespace { // run - Print out SCCs in the call graph for the specified module. bool runOnModule(Module &M) override; - void print(raw_ostream &O, const Module* = 0) const override { } + void print(raw_ostream &O, const Module* = nullptr) const override { } // getAnalysisUsage - This pass requires the CallGraph. void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -75,7 +75,7 @@ bool CFGSCC::runOnFunction(Function &F) { unsigned sccNum = 0; errs() << "SCCs for Function " << F.getName() << " in PostOrder:"; for (scc_iterator<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) { - std::vector<BasicBlock*> &nextSCC = *SCCI; + const std::vector<BasicBlock *> &nextSCC = *SCCI; errs() << "\nSCC #" << ++sccNum << " : "; for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(), E = nextSCC.end(); I != E; ++I) diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 5a19881..6f0fbf6 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -35,6 +35,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/PassManager.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" @@ -191,7 +192,10 @@ static inline void addPass(PassManagerBase &PM, Pass *P) { PM.add(P); // If we are verifying all of the intermediate steps, add the verifier... - if (VerifyEach) PM.add(createVerifierPass()); + if (VerifyEach) { + PM.add(createVerifierPass()); + PM.add(createDebugInfoVerifierPass()); + } } /// AddOptimizationPasses - This routine adds optimization passes @@ -201,7 +205,8 @@ static inline void addPass(PassManagerBase &PM, Pass *P) { /// OptLevel - Optimization Level static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM, unsigned OptLevel, unsigned SizeLevel) { - FPM.add(createVerifierPass()); // Verify that input is correct + FPM.add(createVerifierPass()); // Verify that input is correct + MPM.add(createDebugInfoVerifierPass()); // Verify that debug info is correct PassManagerBuilder Builder; Builder.OptLevel = OptLevel; @@ -240,6 +245,9 @@ static void AddStandardCompilePasses(PassManagerBase &PM) { if (StripDebug) addPass(PM, createStripSymbolsPass(true)); + // Verify debug info only after it's (possibly) stripped. + PM.add(createDebugInfoVerifierPass()); + if (DisableOptimizations) return; // -std-compile-opts adds the same module passes as -O3. @@ -257,6 +265,9 @@ static void AddStandardLinkPasses(PassManagerBase &PM) { if (StripDebug) addPass(PM, createStripSymbolsPass(true)); + // Verify debug info only after it's (possibly) stripped. + PM.add(createDebugInfoVerifierPass()); + if (DisableOptimizations) return; PassManagerBuilder Builder; @@ -285,7 +296,7 @@ static TargetMachine* GetTargetMachine(Triple TheTriple) { Error); // Some modules don't specify a triple, and this is okay. if (!TheTarget) { - return 0; + return nullptr; } // Package up features to be passed to target/subtarget @@ -341,8 +352,9 @@ int main(int argc, char **argv) { initializeInstrumentation(Registry); initializeTarget(Registry); // For codegen passes, only passes that do IR to IR transformation are - // supported. For now, just add CodeGenPrepare. + // supported. initializeCodeGenPreparePass(Registry); + initializeAtomicExpandLoadLinkedPass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); @@ -362,7 +374,7 @@ int main(int argc, char **argv) { std::unique_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); - if (M.get() == 0) { + if (!M.get()) { Err.print(argv[0], errs()); return 1; } @@ -442,7 +454,7 @@ int main(int argc, char **argv) { Passes.add(new DataLayoutPass(M.get())); Triple ModuleTriple(M->getTargetTriple()); - TargetMachine *Machine = 0; + TargetMachine *Machine = nullptr; if (ModuleTriple.getArch()) Machine = GetTargetMachine(Triple(ModuleTriple)); std::unique_ptr<TargetMachine> TM(Machine); @@ -526,7 +538,7 @@ int main(int argc, char **argv) { } const PassInfo *PassInf = PassList[i]; - Pass *P = 0; + Pass *P = nullptr; if (PassInf->getTargetMachineCtor()) P = PassInf->getTargetMachineCtor()(TM.get()); else if (PassInf->getNormalCtor()) @@ -600,8 +612,10 @@ int main(int argc, char **argv) { } // Check that the module is well formed on completion of optimization - if (!NoVerify && !VerifyEach) + if (!NoVerify && !VerifyEach) { Passes.add(createVerifierPass()); + Passes.add(createDebugInfoVerifierPass()); + } // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 21506d9..bb52cda 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFYAML.h" +#include "llvm/Object/StringTableBuilder.h" #include "llvm/Support/ELF.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/YAMLTraits.h" @@ -23,47 +24,6 @@ using namespace llvm; -// There is similar code in yaml2coff, but with some slight COFF-specific -// variations like different initial state. Might be able to deduplicate -// some day, but also want to make sure that the Mach-O use case is served. -// -// This class has a deliberately small interface, since a lot of -// implementation variation is possible. -// -// TODO: Use an ordered container with a suffix-based comparison in order -// to deduplicate suffixes. std::map<> with a custom comparator is likely -// to be the simplest implementation, but a suffix trie could be more -// suitable for the job. -namespace { -class StringTableBuilder { - /// \brief Indices of strings currently present in `Buf`. - StringMap<unsigned> StringIndices; - /// \brief The contents of the string table as we build it. - std::string Buf; -public: - StringTableBuilder() { - Buf.push_back('\0'); - } - /// \returns Index of string in string table. - unsigned addString(StringRef S) { - StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S); - unsigned &I = Entry.getValue(); - if (I != 0) - return I; - I = Buf.size(); - Buf.append(S.begin(), S.end()); - Buf.push_back('\0'); - return I; - } - size_t size() const { - return Buf.size(); - } - void writeToStream(raw_ostream &OS) { - OS.write(Buf.data(), Buf.size()); - } -}; -} // end anonymous namespace - // This class is used to build up a contiguous binary blob while keeping // track of an offset in the output (which notionally begins at // `InitialOffset`). @@ -94,23 +54,23 @@ public: }; } // end anonymous namespace -// Used to keep track of section names, so that in the YAML file sections -// can be referenced by name instead of by index. +// Used to keep track of section and symbol names, so that in the YAML file +// sections and symbols can be referenced by name instead of by index. namespace { -class SectionNameToIdxMap { +class NameToIdxMap { StringMap<int> Map; public: /// \returns true if name is already present in the map. - bool addName(StringRef SecName, unsigned i) { - StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1); + bool addName(StringRef Name, unsigned i) { + StringMapEntry<int> &Entry = Map.GetOrCreateValue(Name, -1); if (Entry.getValue() != -1) return true; Entry.setValue((int)i); return false; } /// \returns true if name is not present in the map - bool lookupSection(StringRef SecName, unsigned &Idx) const { - StringMap<int>::const_iterator I = Map.find(SecName); + bool lookup(StringRef Name, unsigned &Idx) const { + StringMap<int>::const_iterator I = Map.find(Name); if (I == Map.end()) return true; Idx = I->getValue(); @@ -143,6 +103,8 @@ 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; + typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel; + typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela; /// \brief The future ".strtab" section. StringTableBuilder DotStrtab; @@ -150,10 +112,13 @@ class ELFState { /// \brief The future ".shstrtab" section. StringTableBuilder DotShStrtab; - SectionNameToIdxMap SN2I; + NameToIdxMap SN2I; + NameToIdxMap SymN2I; const ELFYAML::Object &Doc; bool buildSectionIndex(); + bool buildSymbolIndex(std::size_t &StartIndex, + const std::vector<ELFYAML::Symbol> &Symbols); void initELFHeader(Elf_Ehdr &Header); bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, ContiguousBlobAccumulator &CBA); @@ -164,6 +129,12 @@ class ELFState { ContiguousBlobAccumulator &CBA); void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, std::vector<Elf_Sym> &Syms, unsigned SymbolBinding); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RawContentSection &Section, + ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelocationSection &Section, + ContiguousBlobAccumulator &CBA); // - SHT_NULL entry (placed first, i.e. 0'th entry) // - symbol table (.symtab) (placed third to last) @@ -217,28 +188,48 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, zero(SHeader); SHeaders.push_back(SHeader); + for (const auto &Sec : Doc.Sections) + DotShStrtab.add(Sec->Name); + DotShStrtab.finalize(); + 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(); + SHeader.sh_name = DotShStrtab.getOffset(Sec->Name); + SHeader.sh_type = Sec->Type; + SHeader.sh_flags = Sec->Flags; + SHeader.sh_addr = Sec->Address; + SHeader.sh_addralign = Sec->AddressAlign; - if (!Sec.Link.empty()) { + if (!Sec->Link.empty()) { unsigned Index; - if (SN2I.lookupSection(Sec.Link, Index)) { - errs() << "error: Unknown section referenced: '" << Sec.Link - << "' at YAML section '" << Sec.Name << "'.\n"; - return false;; + if (SN2I.lookup(Sec->Link, Index)) { + errs() << "error: Unknown section referenced: '" << Sec->Link + << "' at YAML section '" << Sec->Name << "'.\n"; + return false; } SHeader.sh_link = Index; } - SHeader.sh_info = 0; - SHeader.sh_addralign = Sec.AddressAlign; - SHeader.sh_entsize = 0; + + if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec.get())) + writeSectionContent(SHeader, *S, CBA); + else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec.get())) { + if (S->Link.empty()) + // For relocation section set link to .symtab by default. + SHeader.sh_link = getDotSymTabSecNo(); + + unsigned Index; + if (SN2I.lookup(S->Info, Index)) { + errs() << "error: Unknown section referenced: '" << S->Info + << "' at YAML section '" << S->Name << "'.\n"; + return false; + } + SHeader.sh_info = Index; + + if (!writeSectionContent(SHeader, *S, CBA)) + return false; + } else + llvm_unreachable("Unknown section type"); + SHeaders.push_back(SHeader); } return true; @@ -248,7 +239,7 @@ template <class ELFT> void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, ContiguousBlobAccumulator &CBA) { zero(SHeader); - SHeader.sh_name = DotShStrtab.addString(StringRef(".symtab")); + SHeader.sh_name = DotShStrtab.getOffset(".symtab"); SHeader.sh_type = ELF::SHT_SYMTAB; SHeader.sh_link = getDotStrTabSecNo(); // One greater than symbol table index of the last local symbol. @@ -262,6 +253,16 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, zero(Sym); Syms.push_back(Sym); } + + // Add symbol names to .strtab. + for (const auto &Sym : Doc.Symbols.Local) + DotStrtab.add(Sym.Name); + for (const auto &Sym : Doc.Symbols.Global) + DotStrtab.add(Sym.Name); + for (const auto &Sym : Doc.Symbols.Weak) + DotStrtab.add(Sym.Name); + DotStrtab.finalize(); + addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL); addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK); @@ -276,10 +277,10 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, StringTableBuilder &STB, ContiguousBlobAccumulator &CBA) { zero(SHeader); - SHeader.sh_name = DotShStrtab.addString(Name); + SHeader.sh_name = DotShStrtab.getOffset(Name); SHeader.sh_type = ELF::SHT_STRTAB; - STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); - SHeader.sh_size = STB.size(); + CBA.getOSAndAlignedOffset(SHeader.sh_offset) << STB.data(); + SHeader.sh_size = STB.data().size(); SHeader.sh_addralign = 1; } @@ -291,11 +292,11 @@ void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, Elf_Sym Symbol; zero(Symbol); if (!Sym.Name.empty()) - Symbol.st_name = DotStrtab.addString(Sym.Name); + Symbol.st_name = DotStrtab.getOffset(Sym.Name); Symbol.setBindingAndType(SymbolBinding, Sym.Type); if (!Sym.Section.empty()) { unsigned Index; - if (SN2I.lookupSection(Sym.Section, Index)) { + if (SN2I.lookup(Sym.Section, Index)) { errs() << "error: Unknown section referenced: '" << Sym.Section << "' by YAML symbol " << Sym.Name << ".\n"; exit(1); @@ -308,13 +309,71 @@ void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, } } +template <class ELFT> +void +ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RawContentSection &Section, + ContiguousBlobAccumulator &CBA) { + assert(Section.Size >= Section.Content.binary_size() && + "Section size and section content are inconsistent"); + raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + Section.Content.writeAsBinary(OS); + for (auto i = Section.Content.binary_size(); i < Section.Size; ++i) + OS.write(0); + SHeader.sh_entsize = 0; + SHeader.sh_size = Section.Size; +} + +template <class ELFT> +bool +ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelocationSection &Section, + ContiguousBlobAccumulator &CBA) { + if (Section.Type != llvm::ELF::SHT_REL && + Section.Type != llvm::ELF::SHT_RELA) { + errs() << "error: Invalid relocation section type.\n"; + return false; + } + + bool IsRela = Section.Type == llvm::ELF::SHT_RELA; + SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); + SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size(); + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + + for (const auto &Rel : Section.Relocations) { + unsigned SymIdx; + if (SymN2I.lookup(Rel.Symbol, SymIdx)) { + errs() << "error: Unknown symbol referenced: '" << Rel.Symbol + << "' at YAML relocation.\n"; + return false; + } + + if (IsRela) { + Elf_Rela REntry; + zero(REntry); + REntry.r_offset = Rel.Offset; + REntry.r_addend = Rel.Addend; + REntry.setSymbolAndType(SymIdx, Rel.Type); + OS.write((const char *)&REntry, sizeof(REntry)); + } else { + Elf_Rel REntry; + zero(REntry); + REntry.r_offset = Rel.Offset; + REntry.setSymbolAndType(SymIdx, Rel.Type); + OS.write((const char *)&REntry, sizeof(REntry)); + } + } + return true; +} + template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() { SN2I.addName(".symtab", getDotSymTabSecNo()); SN2I.addName(".strtab", getDotStrTabSecNo()); SN2I.addName(".shstrtab", getDotShStrTabSecNo()); for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { - StringRef Name = Doc.Sections[i].Name; + StringRef Name = Doc.Sections[i]->Name; if (Name.empty()) continue; // "+ 1" to take into account the SHT_NULL entry. @@ -328,11 +387,33 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() { } template <class ELFT> +bool +ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex, + const std::vector<ELFYAML::Symbol> &Symbols) { + for (const auto &Sym : Symbols) { + ++StartIndex; + if (Sym.Name.empty()) + continue; + if (SymN2I.addName(Sym.Name, StartIndex)) { + errs() << "error: Repeated symbol name: '" << Sym.Name << "'.\n"; + return false; + } + } + return true; +} + +template <class ELFT> int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { ELFState<ELFT> State(Doc); if (!State.buildSectionIndex()) return 1; + std::size_t StartSymIndex = 0; + if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) || + !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) || + !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak)) + return 1; + Elf_Ehdr Header; State.initELFHeader(Header); @@ -345,6 +426,12 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { Header.e_ehsize + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); + // Doc might not contain .symtab, .strtab and .shstrtab sections, + // but we will emit them, so make sure to add them to ShStrTabSHeader. + State.DotShStrtab.add(".symtab"); + State.DotShStrtab.add(".strtab"); + State.DotShStrtab.add(".shstrtab"); + std::vector<Elf_Shdr> SHeaders; if(!State.initSectionHeaders(SHeaders, CBA)) return 1; @@ -395,13 +482,13 @@ int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) { typedef ELFType<support::big, 4, false> BE32; if (is64Bit(Doc)) { if (isLittleEndian(Doc)) - return ELFState<LE64>::writeELF(outs(), Doc); + return ELFState<LE64>::writeELF(Out, Doc); else - return ELFState<BE64>::writeELF(outs(), Doc); + return ELFState<BE64>::writeELF(Out, Doc); } else { if (isLittleEndian(Doc)) - return ELFState<LE32>::writeELF(outs(), Doc); + return ELFState<LE32>::writeELF(Out, Doc); else - return ELFState<BE32>::writeELF(outs(), Doc); + return ELFState<BE32>::writeELF(Out, Doc); } } diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp index cc0fecc..2493b48 100644 --- a/tools/yaml2obj/yaml2obj.cpp +++ b/tools/yaml2obj/yaml2obj.cpp @@ -16,12 +16,14 @@ #include "yaml2obj.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.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" #include "llvm/Support/system_error.h" +#include "llvm/Support/ToolOutputFile.h" using namespace llvm; @@ -49,6 +51,8 @@ cl::opt<YAMLObjectFormat> Format( clEnumValN(YOF_ELF, "elf", "ELF object file format"), clEnumValEnd)); +static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), + cl::value_desc("filename")); int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); @@ -56,15 +60,31 @@ int main(int argc, char **argv) { PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::string ErrorInfo; + 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; + } + std::unique_ptr<MemoryBuffer> Buf; if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) return 1; - if (Format == YOF_COFF) { - return yaml2coff(outs(), Buf.get()); - } else if (Format == YOF_ELF) { - return yaml2elf(outs(), Buf.get()); - } else { + + int Res = 1; + if (Format == YOF_COFF) + Res = yaml2coff(Out->os(), Buf.get()); + else if (Format == YOF_ELF) + Res = yaml2elf(Out->os(), Buf.get()); + else errs() << "Not yet implemented\n"; - return 1; - } + + if (Res == 0) + Out->keep(); + + return Res; } |