Index: include/llvm/Target/TargetOptions.h =================================================================== --- include/llvm/Target/TargetOptions.h (revision 105825) +++ include/llvm/Target/TargetOptions.h (working copy) @@ -115,6 +115,11 @@ /// debug information and notify a debugger about it. extern bool JITEmitDebugInfo; + /// JITEmitDebugInfoFunctionRange - This flag indicates that the JIT should emit + /// brief debug information (function address and name) for some debugging + /// tools, like addr2line from binutils does + extern bool JITEmitDebugInfoFunctionRange; + /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write /// the object files generated by the JITEmitDebugInfo flag to disk. This /// flag is hidden and is only for debugging the debug info. Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp (revision 105825) +++ lib/Target/TargetMachine.cpp (working copy) @@ -24,6 +24,7 @@ // namespace llvm { + class raw_fd_ostream; bool LessPreciseFPMADOption; bool PrintMachineCode; bool NoFramePointerElim; @@ -38,6 +39,8 @@ bool NoZerosInBSS; bool JITExceptionHandling; bool JITEmitDebugInfo; + bool JITEmitDebugInfoFunctionRange; + raw_fd_ostream* JITEmitDebugInfoFunctionRangeStream(NULL); bool JITEmitDebugInfoToDisk; bool UnwindTablesMandatory; Reloc::Model RelocationModel; @@ -131,6 +134,11 @@ cl::init(EMIT_DEBUG)); #undef EMIT_DEBUG static cl::opt +EmitJitDebugInfoFunctionRange("jit-emit-debug-function-range", + cl::desc("Emit debon memory address range information, one line per function"), + cl::location(JITEmitDebugInfoFunctionRange), + cl::init(false)); +static cl::opt EmitJitDebugInfoToDisk("jit-emit-debug-to-disk", cl::Hidden, cl::desc("Emit debug info objfiles to disk"), Index: lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp =================================================================== --- lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp (revision 105825) +++ lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp (working copy) @@ -31,6 +31,8 @@ namespace llvm { +extern raw_fd_ostream *JITEmitDebugInfoFunctionRangeStream; + // This must be kept in sync with gdb/gdb/jit.h . extern "C" { @@ -137,6 +139,11 @@ std::string Buffer = MakeELF(F, I); + // write brief debug info is requested + if (JITEmitDebugInfoFunctionRange) { + *JITEmitDebugInfoFunctionRangeStream << I.FnStart << " " << I.FnEnd << " " << F->getName() << "\n"; + } + jit_code_entry *JITCodeEntry = new jit_code_entry(); JITCodeEntry->symfile_addr = Buffer.c_str(); JITCodeEntry->symfile_size = Buffer.size(); Index: lib/ExecutionEngine/JIT/JIT.cpp =================================================================== --- lib/ExecutionEngine/JIT/JIT.cpp (revision 105825) +++ lib/ExecutionEngine/JIT/JIT.cpp (working copy) @@ -26,12 +26,14 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetJITInfo.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MutexGuard.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/Config/config.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -55,6 +57,10 @@ extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); #endif +namespace llvm { + extern raw_fd_ostream *JITEmitDebugInfoFunctionRangeStream; +} + namespace { static struct RegisterJIT { @@ -651,6 +657,31 @@ } } +class FRangeDebugObject { +private: + raw_fd_ostream *os; +public: + FRangeDebugObject() : os(NULL) { + if (JITEmitDebugInfoFunctionRange && JITEmitDebugInfoFunctionRangeStream==NULL) { + std::string ErrorInfo; + static bool first_pass = true; + os = JITEmitDebugInfoFunctionRangeStream = new raw_fd_ostream("/tmp/llvm_debug_functions.txt", ErrorInfo, first_pass?0:raw_fd_ostream::F_Append); + if (!ErrorInfo.empty()) { + errs() << "Error writing debug info file: " << ErrorInfo << "\n"; + exit(1); + } + first_pass = false; + } + } + ~FRangeDebugObject() { + if (os!=NULL) { + os->flush(); + delete os; + os = JITEmitDebugInfoFunctionRangeStream = NULL; + } + } +}; + /// getPointerToFunction - This method is used to get the address of the /// specified function, compiling it if neccesary. /// @@ -661,6 +692,9 @@ MutexGuard locked(lock); + // function-range debug output object: it's only active if JITEmitDebugInfoFunctionRange is set + FRangeDebugObject frange_debug; + // Now that this thread owns the lock, make sure we read in the function if it // exists in this Module. std::string ErrorMsg;