forked from OSchip/llvm-project
JITed functions can now have debug info and be debugged with debug and source info:
(lldb) b puts (lldb) expr -g -i0 -- (int)puts("hello") First we will stop at the entry point of the expression before it runs, then we can step over a few times and hit the breakpoint in "puts", then we can continue and finishing stepping and fininsh the expression. Main features: - New ObjectFileJIT class that can be easily created for JIT functions - debug info can now be enabled when parsing expressions - source for any function that is run throught the JIT is now saved in LLDB process specific temp directory and cleaned up on exit - "expr -g --" allows you to single step through your expression function with source code <rdar://problem/16382881> llvm-svn: 204682
This commit is contained in:
parent
2256d0dced
commit
23f8c95a44
|
@ -92,6 +92,10 @@ public:
|
|||
const TimeValue *object_mod_time_ptr = NULL);
|
||||
|
||||
Module (const ModuleSpec &module_spec);
|
||||
|
||||
static lldb::ModuleSP
|
||||
CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor.
|
||||
//------------------------------------------------------------------
|
||||
|
@ -1170,7 +1174,9 @@ protected:
|
|||
friend class SymbolFile;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Module (); // Only used internally by CreateJITModule ()
|
||||
|
||||
size_t
|
||||
FindTypes_Impl (const SymbolContext& sc,
|
||||
const ConstString &name,
|
||||
|
|
|
@ -51,7 +51,8 @@ public:
|
|||
/// The expression to be parsed.
|
||||
//------------------------------------------------------------------
|
||||
ClangExpressionParser (ExecutionContextScope *exe_scope,
|
||||
ClangExpression &expr);
|
||||
ClangExpression &expr,
|
||||
bool generate_debug_info);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor
|
||||
|
@ -84,9 +85,9 @@ public:
|
|||
/// and func_end do not delimit an allocated region; the allocated
|
||||
/// region may begin before func_addr.)
|
||||
///
|
||||
/// @param[in] execution_unit_ap
|
||||
/// @param[in] execution_unit_sp
|
||||
/// After parsing, ownership of the execution unit for
|
||||
/// for the expression is handed to this unique pointer.
|
||||
/// for the expression is handed to this shared pointer.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to write the function into.
|
||||
|
@ -112,7 +113,7 @@ public:
|
|||
Error
|
||||
PrepareForExecution (lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
std::unique_ptr<IRExecutionUnit> &execution_unit_ap,
|
||||
std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
|
||||
ExecutionContext &exe_ctx,
|
||||
bool &can_interpret,
|
||||
lldb_private::ExecutionPolicy execution_policy);
|
||||
|
@ -134,6 +135,9 @@ public:
|
|||
DisassembleFunction (Stream &stream,
|
||||
ExecutionContext &exe_ctx);
|
||||
|
||||
bool
|
||||
GetGenerateDebugInfo () const;
|
||||
|
||||
private:
|
||||
ClangExpression & m_expr; ///< The expression to be parsed
|
||||
std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into
|
||||
|
@ -143,7 +147,6 @@ private:
|
|||
std::unique_ptr<clang::SelectorTable> m_selector_table; ///< Selector table for Objective-C methods
|
||||
std::unique_ptr<clang::ASTContext> m_ast_context; ///< The AST context used to hold types and names for the parser
|
||||
std::unique_ptr<clang::CodeGenerator> m_code_generator; ///< The Clang object that generates IR
|
||||
std::unique_ptr<IRExecutionUnit> m_execution_unit; ///< The container for the finished Module
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -410,7 +410,8 @@ private:
|
|||
//------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function.
|
||||
std::unique_ptr<IRExecutionUnit> m_execution_unit_ap;
|
||||
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
|
||||
lldb::ModuleWP m_jit_module_wp;
|
||||
|
||||
Function *m_function_ptr; ///< The function we're going to call. May be NULL if we don't have debug info for the function.
|
||||
Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type.
|
||||
|
|
|
@ -105,7 +105,8 @@ public:
|
|||
Parse (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb_private::ExecutionPolicy execution_policy,
|
||||
bool keep_result_in_memory);
|
||||
bool keep_result_in_memory,
|
||||
bool generate_debug_info);
|
||||
|
||||
bool
|
||||
CanInterpret ()
|
||||
|
@ -344,11 +345,11 @@ private:
|
|||
std::string m_transformed_text; ///< The text of the expression, as send to the parser
|
||||
ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression.
|
||||
|
||||
std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression.
|
||||
std::unique_ptr<IRExecutionUnit> m_execution_unit_ap; ///< The execution unit the expression is stored in.
|
||||
std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression.
|
||||
std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed.
|
||||
|
||||
std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression.
|
||||
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in.
|
||||
std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression.
|
||||
std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed.
|
||||
lldb::ModuleWP m_jit_module_wp;
|
||||
bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method.
|
||||
bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
|
||||
bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method).
|
||||
|
|
|
@ -168,10 +168,10 @@ public:
|
|||
|
||||
private:
|
||||
std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
|
||||
std::unique_ptr<IRExecutionUnit> m_execution_unit_ap;
|
||||
|
||||
std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
|
||||
std::string m_function_name; ///< The name of the function.
|
||||
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
|
||||
lldb::ModuleWP m_jit_module_wp;
|
||||
std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
|
||||
std::string m_function_name; ///< The name of the function.
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "lldb/Expression/ClangExpressionParser.h"
|
||||
#include "lldb/Expression/IRMemoryMap.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
@ -60,7 +61,10 @@ class Error;
|
|||
/// into the target process, the IRExecutionUnit knows how to copy the
|
||||
/// emitted code into the target process.
|
||||
//----------------------------------------------------------------------
|
||||
class IRExecutionUnit : public IRMemoryMap
|
||||
class IRExecutionUnit :
|
||||
public std::enable_shared_from_this<IRExecutionUnit>,
|
||||
public IRMemoryMap,
|
||||
public ObjectFileJITDelegate
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
|
@ -77,12 +81,14 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
~IRExecutionUnit();
|
||||
|
||||
llvm::Module *GetModule()
|
||||
llvm::Module *
|
||||
GetModule()
|
||||
{
|
||||
return m_module;
|
||||
}
|
||||
|
||||
llvm::Function *GetFunction()
|
||||
llvm::Function *
|
||||
GetFunction()
|
||||
{
|
||||
if (m_module)
|
||||
return m_module->getFunction (m_name.AsCString());
|
||||
|
@ -90,9 +96,10 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void GetRunnableInfo(Error &error,
|
||||
lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end);
|
||||
void
|
||||
GetRunnableInfo (Error &error,
|
||||
lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Accessors for IRForTarget and other clients that may want binary
|
||||
|
@ -100,11 +107,36 @@ public:
|
|||
/// IRExecutionUnit unless the client explicitly chooses to free it.
|
||||
//------------------------------------------------------------------
|
||||
|
||||
lldb::addr_t WriteNow(const uint8_t *bytes,
|
||||
size_t size,
|
||||
Error &error);
|
||||
lldb::addr_t
|
||||
WriteNow (const uint8_t *bytes,
|
||||
size_t size,
|
||||
Error &error);
|
||||
|
||||
void FreeNow(lldb::addr_t allocation);
|
||||
void
|
||||
FreeNow (lldb::addr_t allocation);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// ObjectFileJITDelegate overrides
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::ByteOrder
|
||||
GetByteOrder () const;
|
||||
|
||||
virtual uint32_t
|
||||
GetAddressByteSize () const;
|
||||
|
||||
virtual void
|
||||
PopulateSymtab (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::Symtab &symtab);
|
||||
|
||||
virtual void
|
||||
PopulateSectionList (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::SectionList §ion_list);
|
||||
|
||||
virtual bool
|
||||
GetArchitecture (lldb_private::ArchSpec &arch);
|
||||
|
||||
lldb::ModuleSP
|
||||
GetJITModule ();
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
|
@ -180,6 +212,7 @@ private:
|
|||
public:
|
||||
MemoryManager (IRExecutionUnit &parent);
|
||||
|
||||
virtual ~MemoryManager();
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
|
@ -455,26 +488,42 @@ private:
|
|||
/// Allocations made by the JIT are first queued up and then applied in
|
||||
/// bulk to the underlying process.
|
||||
//----------------------------------------------------------------------
|
||||
enum class AllocationKind {
|
||||
Stub, Code, Data, Global, Bytes
|
||||
};
|
||||
|
||||
static lldb::SectionType
|
||||
GetSectionTypeFromSectionName (const llvm::StringRef &name,
|
||||
AllocationKind alloc_kind);
|
||||
|
||||
struct AllocationRecord {
|
||||
lldb::addr_t m_process_address;
|
||||
uintptr_t m_host_address;
|
||||
uint32_t m_permissions;
|
||||
size_t m_size;
|
||||
unsigned m_alignment;
|
||||
unsigned m_section_id;
|
||||
std::string m_name;
|
||||
lldb::addr_t m_process_address;
|
||||
uintptr_t m_host_address;
|
||||
uint32_t m_permissions;
|
||||
lldb::SectionType m_sect_type;
|
||||
size_t m_size;
|
||||
unsigned m_alignment;
|
||||
unsigned m_section_id;
|
||||
|
||||
AllocationRecord (uintptr_t host_address,
|
||||
uint32_t permissions,
|
||||
lldb::SectionType sect_type,
|
||||
size_t size,
|
||||
unsigned alignment,
|
||||
unsigned section_id = eSectionIDInvalid) :
|
||||
unsigned section_id,
|
||||
const char *name) :
|
||||
m_name (),
|
||||
m_process_address(LLDB_INVALID_ADDRESS),
|
||||
m_host_address(host_address),
|
||||
m_permissions(permissions),
|
||||
m_sect_type (sect_type),
|
||||
m_size(size),
|
||||
m_alignment(alignment),
|
||||
m_section_id(section_id)
|
||||
{
|
||||
if (name && name[0])
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void dump (Log *log);
|
||||
|
|
|
@ -61,6 +61,12 @@ namespace lldb_private {
|
|||
class IRForTarget : public llvm::ModulePass
|
||||
{
|
||||
public:
|
||||
enum class LookupResult {
|
||||
Success,
|
||||
Fail,
|
||||
Ignore
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
///
|
||||
|
@ -201,7 +207,7 @@ private:
|
|||
/// @return
|
||||
/// The pointer.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
LookupResult
|
||||
GetFunctionAddress (llvm::Function *function,
|
||||
uint64_t &ptr,
|
||||
lldb_private::ConstString &name,
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
uint32_t GetAddressByteSize();
|
||||
|
||||
// This function can return NULL.
|
||||
ExecutionContextScope *GetBestExecutionContextScope();
|
||||
ExecutionContextScope *GetBestExecutionContextScope() const;
|
||||
|
||||
protected:
|
||||
// This function should only be used if you know you are using the JIT.
|
||||
|
|
|
@ -538,6 +538,9 @@ public:
|
|||
static Error
|
||||
MakeDirectory (const char* path, uint32_t mode);
|
||||
|
||||
static Error
|
||||
RemoveDirectory (const char* path, bool recurse);
|
||||
|
||||
static Error
|
||||
GetFilePermissions (const char* path, uint32_t &file_permissions);
|
||||
|
||||
|
|
|
@ -21,6 +21,36 @@
|
|||
#include "lldb/Symbol/UnwindTable.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ObjectFileJITDelegate
|
||||
{
|
||||
public:
|
||||
ObjectFileJITDelegate ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~ObjectFileJITDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
virtual lldb::ByteOrder
|
||||
GetByteOrder () const = 0;
|
||||
|
||||
virtual uint32_t
|
||||
GetAddressByteSize () const = 0;
|
||||
|
||||
virtual void
|
||||
PopulateSymtab (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::Symtab &symtab) = 0;
|
||||
|
||||
virtual void
|
||||
PopulateSectionList (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::SectionList §ion_list) = 0;
|
||||
|
||||
virtual bool
|
||||
GetArchitecture (lldb_private::ArchSpec &arch) = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class ObjectFile ObjectFile.h "lldb/Symbol/ObjectFile.h"
|
||||
|
@ -68,6 +98,7 @@ public:
|
|||
eTypeObjectFile, /// An intermediate object file
|
||||
eTypeSharedLibrary, /// A shared library that can be used during execution
|
||||
eTypeStubLibrary, /// A library that can be linked against but not used for execution
|
||||
eTypeJIT, /// JIT code that has symbols, sections and possibly debug info
|
||||
eTypeUnknown
|
||||
} Type;
|
||||
|
||||
|
@ -77,7 +108,8 @@ public:
|
|||
eStrataUnknown,
|
||||
eStrataUser,
|
||||
eStrataKernel,
|
||||
eStrataRawImage
|
||||
eStrataRawImage,
|
||||
eStrataJIT
|
||||
} Strata;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -91,7 +123,7 @@ public:
|
|||
const FileSpec *file_spec_ptr,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
const lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset);
|
||||
|
||||
ObjectFile (const lldb::ModuleSP &module_sp,
|
||||
|
@ -756,12 +788,12 @@ public:
|
|||
size_t
|
||||
CopyData (off_t offset, size_t length, void *dst) const;
|
||||
|
||||
size_t
|
||||
virtual size_t
|
||||
ReadSectionData (const Section *section,
|
||||
off_t section_offset,
|
||||
void *dst,
|
||||
size_t dst_len) const;
|
||||
size_t
|
||||
virtual size_t
|
||||
ReadSectionData (const Section *section,
|
||||
DataExtractor& section_data) const;
|
||||
|
||||
|
|
|
@ -201,6 +201,7 @@ public:
|
|||
m_stop_others(true),
|
||||
m_debug(false),
|
||||
m_trap_exceptions(true),
|
||||
m_generate_debug_info(false),
|
||||
m_use_dynamic(lldb::eNoDynamicValues),
|
||||
m_timeout_usec(default_timeout)
|
||||
{}
|
||||
|
@ -335,6 +336,20 @@ public:
|
|||
SetDebug(bool b)
|
||||
{
|
||||
m_debug = b;
|
||||
if (m_debug)
|
||||
m_generate_debug_info = true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetGenerateDebugInfo() const
|
||||
{
|
||||
return m_generate_debug_info;
|
||||
}
|
||||
|
||||
void
|
||||
SetGenerateDebugInfo(bool b)
|
||||
{
|
||||
m_generate_debug_info = b;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -360,6 +375,7 @@ private:
|
|||
bool m_stop_others;
|
||||
bool m_debug;
|
||||
bool m_trap_exceptions;
|
||||
bool m_generate_debug_info;
|
||||
lldb::DynamicValueType m_use_dynamic;
|
||||
uint32_t m_timeout_usec;
|
||||
};
|
||||
|
|
|
@ -128,6 +128,7 @@ class OptionGroup;
|
|||
class OptionGroupOptions;
|
||||
class OptionGroupPlatform;
|
||||
class ObjectFile;
|
||||
class ObjectFileJITDelegate;
|
||||
class OperatingSystem;
|
||||
class Options;
|
||||
class OptionValue;
|
||||
|
@ -316,6 +317,8 @@ namespace lldb {
|
|||
typedef std::weak_ptr<lldb_private::Module> ModuleWP;
|
||||
typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP;
|
||||
typedef std::weak_ptr<lldb_private::ObjectFile> ObjectFileWP;
|
||||
typedef std::shared_ptr<lldb_private::ObjectFileJITDelegate> ObjectFileJITDelegateSP;
|
||||
typedef std::weak_ptr<lldb_private::ObjectFileJITDelegate> ObjectFileJITDelegateWP;
|
||||
typedef std::shared_ptr<lldb_private::OptionValue> OptionValueSP;
|
||||
typedef std::weak_ptr<lldb_private::OptionValue> OptionValueWP;
|
||||
typedef std::shared_ptr<lldb_private::OptionValueArch> OptionValueArchSP;
|
||||
|
|
|
@ -118,7 +118,7 @@ typedef enum PathType
|
|||
ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory
|
||||
ePathTypeLLDBSystemPlugins, // System plug-ins directory
|
||||
ePathTypeLLDBUserPlugins, // User plug-ins directory
|
||||
ePathTypeLLDBTempSystemDir // The LLDB temp directory for this system
|
||||
ePathTypeLLDBTempSystemDir // The LLDB temp directory for this system that will be cleaned up on exit
|
||||
|
||||
} PathType;
|
||||
|
||||
|
|
|
@ -542,6 +542,8 @@
|
|||
26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E152231419CACA007967D0 /* ObjectFilePECOFF.cpp */; };
|
||||
26ECA04313665FED008D1F18 /* ARM_DWARF_Registers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */; };
|
||||
26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; };
|
||||
26EFC4CD18CFAF0D00865D87 /* ObjectFileJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */; };
|
||||
26EFC4CE18CFAF0D00865D87 /* ObjectFileJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 26EFC4CB18CFAF0D00865D87 /* ObjectFileJIT.h */; };
|
||||
26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */; };
|
||||
26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; };
|
||||
26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; };
|
||||
|
@ -1593,6 +1595,8 @@
|
|||
26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARM_DWARF_Registers.cpp; path = source/Utility/ARM_DWARF_Registers.cpp; sourceTree = "<group>"; };
|
||||
26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupVariable.cpp; path = source/Interpreter/OptionGroupVariable.cpp; sourceTree = "<group>"; };
|
||||
26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupVariable.h; path = include/lldb/Interpreter/OptionGroupVariable.h; sourceTree = "<group>"; };
|
||||
26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileJIT.cpp; sourceTree = "<group>"; };
|
||||
26EFC4CB18CFAF0D00865D87 /* ObjectFileJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileJIT.h; sourceTree = "<group>"; };
|
||||
26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadMemory.cpp; path = Utility/ThreadMemory.cpp; sourceTree = "<group>"; };
|
||||
26F4A21B13FBA31A0064B613 /* ThreadMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadMemory.h; path = Utility/ThreadMemory.h; sourceTree = "<group>"; };
|
||||
26F5C26A10F3D9A4009D5894 /* lldb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lldb; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -2184,6 +2188,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
260C898310F57C5600BB2B04 /* ELF */,
|
||||
26EFC4C718CFAF0D00865D87 /* JIT */,
|
||||
260C898710F57C5600BB2B04 /* Mach-O */,
|
||||
26E152221419CACA007967D0 /* PECOFF */,
|
||||
);
|
||||
|
@ -3582,6 +3587,15 @@
|
|||
path = PECOFF;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
26EFC4C718CFAF0D00865D87 /* JIT */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */,
|
||||
26EFC4CB18CFAF0D00865D87 /* ObjectFileJIT.h */,
|
||||
);
|
||||
path = JIT;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
26F5C22410F3D950009D5894 /* Tools */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3973,6 +3987,7 @@
|
|||
26474CCE18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.h in Headers */,
|
||||
26474CAD18D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.h in Headers */,
|
||||
490A36C2180F0E9300BA31F8 /* PlatformWindows.h in Headers */,
|
||||
26EFC4CE18CFAF0D00865D87 /* ObjectFileJIT.h in Headers */,
|
||||
260CC63615D04377002BF2E0 /* OptionValueFormat.h in Headers */,
|
||||
26D1804516CEE12500EDFB5B /* KQueue.h in Headers */,
|
||||
260CC63715D04377002BF2E0 /* OptionValueSInt64.h in Headers */,
|
||||
|
@ -4759,6 +4774,7 @@
|
|||
49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
|
||||
49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */,
|
||||
B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */,
|
||||
26EFC4CD18CFAF0D00865D87 /* ObjectFileJIT.cpp in Sources */,
|
||||
49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */,
|
||||
494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */,
|
||||
49DA65031485C92A005FF180 /* AppleObjCTypeVendor.cpp in Sources */,
|
||||
|
|
|
@ -289,7 +289,8 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
|
|||
if (!m_user_expression_sp->Parse(errors,
|
||||
exe_ctx,
|
||||
eExecutionPolicyOnlyWhenNeeded,
|
||||
true))
|
||||
true,
|
||||
false))
|
||||
{
|
||||
error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
|
||||
errors.GetData());
|
||||
|
|
|
@ -288,6 +288,12 @@ CommandObjectExpression::EvaluateExpression
|
|||
options.SetTryAllThreads(m_command_options.try_all_threads);
|
||||
options.SetDebug(m_command_options.debug);
|
||||
|
||||
// If there is any chance we are going to stop and want to see
|
||||
// what went wrong with our expression, we should generate debug info
|
||||
if (!m_command_options.ignore_breakpoints ||
|
||||
!m_command_options.unwind_on_error)
|
||||
options.SetGenerateDebugInfo(true);
|
||||
|
||||
if (m_command_options.timeout > 0)
|
||||
options.SetTimeoutUsec(m_command_options.timeout);
|
||||
else
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Symbol/SymbolFile.h"
|
||||
|
||||
#include "Plugins/ObjectFile/JIT/ObjectFileJIT.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -145,6 +147,7 @@ Module::Module (const ModuleSpec &module_spec) :
|
|||
m_symfile_ap (),
|
||||
m_ast (),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
m_did_load_symbol_vendor (false),
|
||||
m_did_parse_uuid (false),
|
||||
|
@ -219,6 +222,7 @@ Module::Module(const FileSpec& file_spec,
|
|||
m_symfile_ap (),
|
||||
m_ast (),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
m_did_load_symbol_vendor (false),
|
||||
m_did_parse_uuid (false),
|
||||
|
@ -250,6 +254,35 @@ Module::Module(const FileSpec& file_spec,
|
|||
m_object_name.IsEmpty() ? "" : ")");
|
||||
}
|
||||
|
||||
Module::Module () :
|
||||
m_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_mod_time (),
|
||||
m_arch (),
|
||||
m_uuid (),
|
||||
m_file (),
|
||||
m_platform_file(),
|
||||
m_remote_install_file (),
|
||||
m_symfile_spec (),
|
||||
m_object_name (),
|
||||
m_object_offset (0),
|
||||
m_object_mod_time (),
|
||||
m_objfile_sp (),
|
||||
m_symfile_ap (),
|
||||
m_ast (),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
m_did_load_symbol_vendor (false),
|
||||
m_did_parse_uuid (false),
|
||||
m_did_init_ast (false),
|
||||
m_is_dynamic_loader_module (false),
|
||||
m_file_has_changed (false),
|
||||
m_first_file_changed_log (false)
|
||||
{
|
||||
Mutex::Locker locker (GetAllocationModuleCollectionMutex());
|
||||
GetModuleCollection().push_back(this);
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
// Lock our module down while we tear everything down to make sure
|
||||
|
@ -1722,3 +1755,27 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
|
|||
match_name_after_lookup = false;
|
||||
}
|
||||
}
|
||||
|
||||
ModuleSP
|
||||
Module::CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp)
|
||||
{
|
||||
if (delegate_sp)
|
||||
{
|
||||
// Must create a module and place it into a shared pointer before
|
||||
// we can create an object file since it has a std::weak_ptr back
|
||||
// to the module, so we need to control the creation carefully in
|
||||
// this static function
|
||||
ModuleSP module_sp(new Module());
|
||||
module_sp->m_objfile_sp.reset (new ObjectFileJIT (module_sp, delegate_sp));
|
||||
if (module_sp->m_objfile_sp)
|
||||
{
|
||||
// Once we get the object file, update our module with the object file's
|
||||
// architecture since it might differ in vendor/os if some parts were
|
||||
// unknown.
|
||||
module_sp->m_objfile_sp->GetArchitecture (module_sp->m_arch);
|
||||
}
|
||||
return module_sp;
|
||||
}
|
||||
return ModuleSP();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Disassembler.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "lldb/Expression/IRExecutionUnit.h"
|
||||
#include "lldb/Expression/IRDynamicChecks.h"
|
||||
#include "lldb/Expression/IRInterpreter.h"
|
||||
#include "lldb/Host/File.h"
|
||||
#include "lldb/Symbol/SymbolVendor.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
@ -93,7 +96,8 @@ std::string GetBuiltinIncludePath(const char *Argv0) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
|
||||
ClangExpression &expr) :
|
||||
ClangExpression &expr,
|
||||
bool generate_debug_info) :
|
||||
m_expr (expr),
|
||||
m_compiler (),
|
||||
m_code_generator ()
|
||||
|
@ -228,6 +232,10 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
|
|||
m_compiler->getCodeGenOpts().InstrumentFunctions = false;
|
||||
m_compiler->getCodeGenOpts().DisableFPElim = true;
|
||||
m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
|
||||
if (generate_debug_info)
|
||||
m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo);
|
||||
else
|
||||
m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo);
|
||||
|
||||
// Disable some warnings.
|
||||
m_compiler->getDiagnostics().setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, SourceLocation());
|
||||
|
@ -299,8 +307,48 @@ ClangExpressionParser::Parse (Stream &stream)
|
|||
|
||||
diag_buf->FlushDiagnostics (m_compiler->getDiagnostics());
|
||||
|
||||
MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__);
|
||||
m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
|
||||
const char *expr_text = m_expr.Text();
|
||||
|
||||
bool created_main_file = false;
|
||||
if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo)
|
||||
{
|
||||
std::string temp_source_path;
|
||||
|
||||
FileSpec tmpdir_file_spec;
|
||||
if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
|
||||
{
|
||||
tmpdir_file_spec.GetFilename().SetCString("expr.XXXXXX");
|
||||
temp_source_path = std::move(tmpdir_file_spec.GetPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_source_path = "/tmp/expr.XXXXXX";
|
||||
}
|
||||
|
||||
if (mktemp(&temp_source_path[0]))
|
||||
{
|
||||
lldb_private::File file (temp_source_path.c_str(),
|
||||
File::eOpenOptionWrite | File::eOpenOptionCanCreateNewOnly,
|
||||
lldb::eFilePermissionsFileDefault);
|
||||
const size_t expr_text_len = strlen(expr_text);
|
||||
size_t bytes_written = expr_text_len;
|
||||
if (file.Write(expr_text, bytes_written).Success())
|
||||
{
|
||||
if (bytes_written == expr_text_len)
|
||||
{
|
||||
file.Close();
|
||||
m_compiler->getSourceManager().createMainFileID(m_file_manager->getFile(temp_source_path));
|
||||
created_main_file = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!created_main_file)
|
||||
{
|
||||
MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
|
||||
m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
|
||||
}
|
||||
|
||||
diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
|
||||
|
||||
|
@ -370,7 +418,7 @@ static bool FindFunctionInModule (ConstString &mangled_name,
|
|||
Error
|
||||
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
std::unique_ptr<IRExecutionUnit> &execution_unit_ap,
|
||||
std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
|
||||
ExecutionContext &exe_ctx,
|
||||
bool &can_interpret,
|
||||
ExecutionPolicy execution_policy)
|
||||
|
@ -379,13 +427,11 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
func_end = LLDB_INVALID_ADDRESS;
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
std::unique_ptr<llvm::ExecutionEngine> execution_engine_ap;
|
||||
|
||||
Error err;
|
||||
|
||||
std::unique_ptr<llvm::Module> module_ap (m_code_generator->ReleaseModule());
|
||||
std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());
|
||||
|
||||
if (!module_ap.get())
|
||||
if (!llvm_module_ap.get())
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString("IR doesn't contain a module");
|
||||
|
@ -396,7 +442,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
|
||||
ConstString function_name;
|
||||
|
||||
if (!FindFunctionInModule(function_name, module_ap.get(), m_expr.FunctionName()))
|
||||
if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
|
||||
|
@ -408,12 +454,12 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
|
||||
}
|
||||
|
||||
m_execution_unit.reset(new IRExecutionUnit(m_llvm_context, // handed off here
|
||||
module_ap, // handed off here
|
||||
function_name,
|
||||
exe_ctx.GetTargetSP(),
|
||||
m_compiler->getTargetOpts().Features));
|
||||
|
||||
execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
|
||||
llvm_module_ap, // handed off here
|
||||
function_name,
|
||||
exe_ctx.GetTargetSP(),
|
||||
m_compiler->getTargetOpts().Features));
|
||||
|
||||
ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
|
||||
|
||||
if (decl_map)
|
||||
|
@ -425,15 +471,15 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
|
||||
IRForTarget ir_for_target(decl_map,
|
||||
m_expr.NeedsVariableResolution(),
|
||||
*m_execution_unit,
|
||||
*execution_unit_sp,
|
||||
error_stream,
|
||||
function_name.AsCString());
|
||||
|
||||
bool ir_can_run = ir_for_target.runOnModule(*m_execution_unit->GetModule());
|
||||
bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
|
||||
|
||||
Error interpret_error;
|
||||
|
||||
can_interpret = IRInterpreter::CanInterpret(*m_execution_unit->GetModule(), *m_execution_unit->GetFunction(), interpret_error);
|
||||
can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);
|
||||
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
|
||||
|
@ -483,7 +529,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
|
||||
IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
|
||||
|
||||
if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
|
||||
if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
|
||||
{
|
||||
err.SetErrorToGenericError();
|
||||
err.SetErrorString("Couldn't add dynamic checks to the expression");
|
||||
|
@ -491,15 +537,21 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
|
|||
}
|
||||
}
|
||||
|
||||
m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
|
||||
execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
|
||||
execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
|
||||
}
|
||||
|
||||
execution_unit_ap.reset (m_execution_unit.release());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangExpressionParser::GetGenerateDebugInfo () const
|
||||
{
|
||||
if (m_compiler)
|
||||
return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,18 +22,20 @@
|
|||
#include "llvm/IR/Module.h"
|
||||
|
||||
// Project includes
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/ValueObjectList.h"
|
||||
#include "lldb/Expression/ASTStructExtractor.h"
|
||||
#include "lldb/Expression/ClangExpressionParser.h"
|
||||
#include "lldb/Expression/ClangFunction.h"
|
||||
#include "lldb/Expression/IRExecutionUnit.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/ValueObjectList.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/Function.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
|
@ -41,7 +43,6 @@
|
|||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/ThreadPlan.h"
|
||||
#include "lldb/Target/ThreadPlanCallFunction.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -55,6 +56,9 @@ ClangFunction::ClangFunction
|
|||
const Address& functionAddress,
|
||||
const ValueList &arg_value_list
|
||||
) :
|
||||
m_parser(),
|
||||
m_execution_unit_sp(),
|
||||
m_jit_module_wp(),
|
||||
m_function_ptr (NULL),
|
||||
m_function_addr (functionAddress),
|
||||
m_function_return_type(return_type),
|
||||
|
@ -87,7 +91,7 @@ ClangFunction::ClangFunction
|
|||
m_compiled (false),
|
||||
m_JITted (false)
|
||||
{
|
||||
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
|
||||
m_jit_process_wp = exe_scope.CalculateProcess();
|
||||
// Can't make a ClangFunction without a process.
|
||||
assert (m_jit_process_wp.lock());
|
||||
|
||||
|
@ -100,6 +104,13 @@ ClangFunction::ClangFunction
|
|||
//----------------------------------------------------------------------
|
||||
ClangFunction::~ClangFunction()
|
||||
{
|
||||
lldb::ProcessSP process_sp (m_jit_process_wp.lock());
|
||||
if (process_sp)
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
|
||||
if (jit_module_sp)
|
||||
process_sp->GetTarget().GetImages().Remove(jit_module_sp);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
@ -222,7 +233,8 @@ ClangFunction::CompileFunction (Stream &errors)
|
|||
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
|
||||
if (jit_process_sp)
|
||||
{
|
||||
m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this));
|
||||
const bool generate_debug_info = true;
|
||||
m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
|
||||
|
||||
num_errors = m_parser->Parse (errors);
|
||||
}
|
||||
|
@ -263,7 +275,7 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
|
|||
|
||||
Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
|
||||
m_jit_end_addr,
|
||||
m_execution_unit_ap,
|
||||
m_execution_unit_sp,
|
||||
exe_ctx,
|
||||
can_interpret,
|
||||
eExecutionPolicyAlways));
|
||||
|
@ -271,8 +283,22 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
|
|||
if (!jit_error.Success())
|
||||
return false;
|
||||
|
||||
if (m_parser->GetGenerateDebugInfo())
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
|
||||
|
||||
if (jit_module_sp)
|
||||
{
|
||||
ConstString const_func_name(FunctionName());
|
||||
FileSpec jit_file;
|
||||
jit_file.GetFilename() = const_func_name;
|
||||
jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
|
||||
m_jit_module_wp = jit_module_sp;
|
||||
process->GetTarget().GetImages().Append(jit_module_sp);
|
||||
}
|
||||
}
|
||||
if (process && m_jit_start_addr)
|
||||
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
|
||||
m_jit_process_wp = process->shared_from_this();
|
||||
|
||||
m_JITted = true;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Core/ValueObjectConstResult.h"
|
||||
|
@ -36,6 +37,8 @@
|
|||
#include "lldb/Symbol/Block.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/Function.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/SymbolVendor.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
|
||||
#include "lldb/Symbol/VariableList.h"
|
||||
|
@ -63,6 +66,11 @@ ClangUserExpression::ClangUserExpression (const char *expr,
|
|||
m_language (language),
|
||||
m_transformed_text (),
|
||||
m_desired_type (desired_type),
|
||||
m_expr_decl_map(),
|
||||
m_execution_unit_sp(),
|
||||
m_materializer_ap(),
|
||||
m_result_synthesizer(),
|
||||
m_jit_module_wp(),
|
||||
m_enforce_valid_object (true),
|
||||
m_cplusplus (false),
|
||||
m_objectivec (false),
|
||||
|
@ -91,6 +99,12 @@ ClangUserExpression::ClangUserExpression (const char *expr,
|
|||
|
||||
ClangUserExpression::~ClangUserExpression ()
|
||||
{
|
||||
if (m_target)
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
|
||||
if (jit_module_sp)
|
||||
m_target->GetImages().Remove(jit_module_sp);
|
||||
}
|
||||
}
|
||||
|
||||
clang::ASTConsumer *
|
||||
|
@ -415,7 +429,8 @@ bool
|
|||
ClangUserExpression::Parse (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb_private::ExecutionPolicy execution_policy,
|
||||
bool keep_result_in_memory)
|
||||
bool keep_result_in_memory,
|
||||
bool generate_debug_info)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
|
@ -514,7 +529,7 @@ ClangUserExpression::Parse (Stream &error_stream,
|
|||
if (!exe_scope)
|
||||
exe_scope = exe_ctx.GetTargetPtr();
|
||||
|
||||
ClangExpressionParser parser(exe_scope, *this);
|
||||
ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
|
||||
|
||||
unsigned num_errors = parser.Parse (error_stream);
|
||||
|
||||
|
@ -533,11 +548,42 @@ ClangUserExpression::Parse (Stream &error_stream,
|
|||
|
||||
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
|
||||
m_jit_end_addr,
|
||||
m_execution_unit_ap,
|
||||
m_execution_unit_sp,
|
||||
exe_ctx,
|
||||
m_can_interpret,
|
||||
execution_policy);
|
||||
|
||||
if (generate_debug_info)
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
|
||||
|
||||
if (jit_module_sp)
|
||||
{
|
||||
ConstString const_func_name(FunctionName());
|
||||
FileSpec jit_file;
|
||||
jit_file.GetFilename() = const_func_name;
|
||||
jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
|
||||
m_jit_module_wp = jit_module_sp;
|
||||
target->GetImages().Append(jit_module_sp);
|
||||
}
|
||||
// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
|
||||
// StreamFile strm (stdout, false);
|
||||
// if (jit_obj_file)
|
||||
// {
|
||||
// jit_obj_file->GetSectionList();
|
||||
// jit_obj_file->GetSymtab();
|
||||
// jit_obj_file->Dump(&strm);
|
||||
// }
|
||||
// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
|
||||
// if (jit_sym_vendor)
|
||||
// {
|
||||
// lldb_private::SymbolContextList sc_list;
|
||||
// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
|
||||
// sc_list.Dump(&strm, target);
|
||||
// jit_sym_vendor->Dump(&strm);
|
||||
// }
|
||||
}
|
||||
|
||||
m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
|
||||
|
||||
if (jit_error.Success())
|
||||
|
@ -667,7 +713,7 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
|
|||
|
||||
IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
|
||||
|
||||
m_materialized_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
|
||||
m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
|
||||
m_materializer_ap->GetStructAlignment(),
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
policy,
|
||||
|
@ -688,7 +734,7 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
|
|||
|
||||
const size_t stack_frame_size = 512 * 1024;
|
||||
|
||||
m_stack_frame_bottom = m_execution_unit_ap->Malloc(stack_frame_size,
|
||||
m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
|
||||
8,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
IRMemoryMap::eAllocationPolicyHostOnly,
|
||||
|
@ -705,7 +751,7 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
|
|||
|
||||
Error materialize_error;
|
||||
|
||||
m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error);
|
||||
m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
|
||||
|
||||
if (!materialize_error.Success())
|
||||
{
|
||||
|
@ -781,8 +827,8 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
|
||||
if (m_can_interpret)
|
||||
{
|
||||
llvm::Module *module = m_execution_unit_ap->GetModule();
|
||||
llvm::Function *function = m_execution_unit_ap->GetFunction();
|
||||
llvm::Module *module = m_execution_unit_sp->GetModule();
|
||||
llvm::Function *function = m_execution_unit_sp->GetFunction();
|
||||
|
||||
if (!module || !function)
|
||||
{
|
||||
|
@ -810,7 +856,7 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
IRInterpreter::Interpret (*module,
|
||||
*function,
|
||||
args,
|
||||
*m_execution_unit_ap.get(),
|
||||
*m_execution_unit_sp.get(),
|
||||
interpreter_error,
|
||||
function_stack_bottom,
|
||||
function_stack_top);
|
||||
|
@ -965,8 +1011,13 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
|||
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
|
||||
|
||||
const bool keep_expression_in_memory = true;
|
||||
const bool generate_debug_info = options.GetGenerateDebugInfo();
|
||||
|
||||
if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
|
||||
if (!user_expression_sp->Parse (error_stream,
|
||||
exe_ctx,
|
||||
execution_policy,
|
||||
keep_expression_in_memory,
|
||||
generate_debug_info))
|
||||
{
|
||||
if (error_stream.GetString().empty())
|
||||
error.SetErrorString ("expression failed to parse, unknown error");
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
||||
|
@ -42,6 +43,9 @@ using namespace lldb_private;
|
|||
ClangUtilityFunction::ClangUtilityFunction (const char *text,
|
||||
const char *name) :
|
||||
ClangExpression (),
|
||||
m_expr_decl_map (),
|
||||
m_execution_unit_sp (),
|
||||
m_jit_module_wp (),
|
||||
m_function_text (ExpressionSourceCode::g_expression_prefix),
|
||||
m_function_name (name)
|
||||
{
|
||||
|
@ -51,6 +55,14 @@ ClangUtilityFunction::ClangUtilityFunction (const char *text,
|
|||
|
||||
ClangUtilityFunction::~ClangUtilityFunction ()
|
||||
{
|
||||
lldb::ProcessSP process_sp (m_jit_process_wp.lock());
|
||||
if (process_sp)
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
|
||||
if (jit_module_sp)
|
||||
process_sp->GetTarget().GetImages().Remove(jit_module_sp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -108,8 +120,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
|
|||
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
|
||||
|
||||
const bool generate_debug_info = true;
|
||||
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info);
|
||||
|
||||
unsigned num_errors = parser.Parse (error_stream);
|
||||
|
||||
|
@ -130,13 +143,29 @@ ClangUtilityFunction::Install (Stream &error_stream,
|
|||
|
||||
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
|
||||
m_jit_end_addr,
|
||||
m_execution_unit_ap,
|
||||
m_execution_unit_sp,
|
||||
exe_ctx,
|
||||
can_interpret,
|
||||
eExecutionPolicyAlways);
|
||||
|
||||
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
|
||||
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
|
||||
{
|
||||
m_jit_process_wp = process->shared_from_this();
|
||||
if (parser.GetGenerateDebugInfo())
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
|
||||
|
||||
if (jit_module_sp)
|
||||
{
|
||||
ConstString const_func_name(FunctionName());
|
||||
FileSpec jit_file;
|
||||
jit_file.GetFilename() = const_func_name;
|
||||
jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
|
||||
m_jit_module_wp = jit_module_sp;
|
||||
target->GetImages().Append(jit_module_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// jingham: look here
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/Disassembler.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Expression/IRExecutionUnit.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
@ -333,6 +335,9 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
|
|||
m_module_ap.release(); // ownership was transferred
|
||||
}
|
||||
|
||||
// Make sure we see all sections, including ones that don't have relocations...
|
||||
m_execution_engine_ap->setProcessAllSections(true);
|
||||
|
||||
m_execution_engine_ap->DisableLazyCompilation();
|
||||
|
||||
// We don't actually need the function pointer here, this just forces it to get resolved.
|
||||
|
@ -433,6 +438,9 @@ IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
|
|||
{
|
||||
}
|
||||
|
||||
IRExecutionUnit::MemoryManager::~MemoryManager ()
|
||||
{
|
||||
}
|
||||
void
|
||||
IRExecutionUnit::MemoryManager::setMemoryWritable ()
|
||||
{
|
||||
|
@ -464,8 +472,11 @@ IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
|
|||
|
||||
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Stub),
|
||||
StubSize,
|
||||
Alignment));
|
||||
Alignment,
|
||||
eSectionIDInvalid,
|
||||
NULL));
|
||||
|
||||
if (log)
|
||||
{
|
||||
|
@ -484,6 +495,115 @@ IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
|
|||
m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
|
||||
}
|
||||
|
||||
lldb::SectionType
|
||||
IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind)
|
||||
{
|
||||
lldb::SectionType sect_type = lldb::eSectionTypeCode;
|
||||
switch (alloc_kind)
|
||||
{
|
||||
case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break;
|
||||
case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break;
|
||||
case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break;
|
||||
case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break;
|
||||
case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break;
|
||||
}
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
if (name.equals("__text") || name.equals(".text"))
|
||||
sect_type = lldb::eSectionTypeCode;
|
||||
else if (name.equals("__data") || name.equals(".data"))
|
||||
sect_type = lldb::eSectionTypeCode;
|
||||
else if (name.startswith("__debug_") || name.startswith(".debug_"))
|
||||
{
|
||||
const uint32_t name_idx = name[0] == '_' ? 8 : 7;
|
||||
llvm::StringRef dwarf_name(name.substr(name_idx));
|
||||
switch (dwarf_name[0])
|
||||
{
|
||||
case 'a':
|
||||
if (dwarf_name.equals("abbrev"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
|
||||
else if (dwarf_name.equals("aranges"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugAranges;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (dwarf_name.equals("frame"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugFrame;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if (dwarf_name.equals("info"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugInfo;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (dwarf_name.equals("line"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugLine;
|
||||
else if (dwarf_name.equals("loc"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugLoc;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (dwarf_name.equals("macinfo"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (dwarf_name.equals("pubnames"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugPubNames;
|
||||
else if (dwarf_name.equals("pubtypes"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (dwarf_name.equals("str"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugStr;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (dwarf_name.equals("ranges"))
|
||||
sect_type = lldb::eSectionTypeDWARFDebugRanges;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (name.startswith("__apple_") || name.startswith(".apple_"))
|
||||
{
|
||||
#if 0
|
||||
const uint32_t name_idx = name[0] == '_' ? 8 : 7;
|
||||
llvm::StringRef apple_name(name.substr(name_idx));
|
||||
switch (apple_name[0])
|
||||
{
|
||||
case 'n':
|
||||
if (apple_name.equals("names"))
|
||||
sect_type = lldb::eSectionTypeDWARFAppleNames;
|
||||
else if (apple_name.equals("namespac") || apple_name.equals("namespaces"))
|
||||
sect_type = lldb::eSectionTypeDWARFAppleNamespaces;
|
||||
break;
|
||||
case 't':
|
||||
if (apple_name.equals("types"))
|
||||
sect_type = lldb::eSectionTypeDWARFAppleTypes;
|
||||
break;
|
||||
case 'o':
|
||||
if (apple_name.equals("objc"))
|
||||
sect_type = lldb::eSectionTypeDWARFAppleObjC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
sect_type = lldb::eSectionTypeInvalid;
|
||||
#endif
|
||||
}
|
||||
else if (name.equals("__objc_imageinfo"))
|
||||
sect_type = lldb::eSectionTypeOther;
|
||||
}
|
||||
return sect_type;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
|
||||
{
|
||||
|
@ -493,8 +613,11 @@ IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
|
|||
|
||||
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Bytes),
|
||||
Size,
|
||||
Alignment));
|
||||
Alignment,
|
||||
eSectionIDInvalid,
|
||||
NULL));
|
||||
|
||||
if (log)
|
||||
{
|
||||
|
@ -517,9 +640,11 @@ IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
|
|||
|
||||
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
|
||||
GetSectionTypeFromSectionName (SectionName, AllocationKind::Code),
|
||||
Size,
|
||||
Alignment,
|
||||
SectionID));
|
||||
SectionID,
|
||||
SectionName.str().c_str()));
|
||||
|
||||
if (log)
|
||||
{
|
||||
|
@ -542,10 +667,12 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
|
|||
uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
|
||||
|
||||
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
lldb::ePermissionsReadable | (IsReadOnly ? 0 : lldb::ePermissionsWritable),
|
||||
GetSectionTypeFromSectionName (SectionName, AllocationKind::Data),
|
||||
Size,
|
||||
Alignment,
|
||||
SectionID));
|
||||
SectionID,
|
||||
SectionName.str().c_str()));
|
||||
if (log)
|
||||
{
|
||||
log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
|
||||
|
@ -565,8 +692,11 @@ IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
|
|||
|
||||
m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Global),
|
||||
Size,
|
||||
Alignment));
|
||||
Alignment,
|
||||
eSectionIDInvalid,
|
||||
NULL));
|
||||
|
||||
if (log)
|
||||
{
|
||||
|
@ -646,12 +776,34 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
|
|||
if (record.m_process_address != LLDB_INVALID_ADDRESS)
|
||||
continue;
|
||||
|
||||
|
||||
record.m_process_address = Malloc(record.m_size,
|
||||
record.m_alignment,
|
||||
record.m_permissions,
|
||||
eAllocationPolicyProcessOnly,
|
||||
err);
|
||||
switch (record.m_sect_type)
|
||||
{
|
||||
case lldb::eSectionTypeInvalid:
|
||||
case lldb::eSectionTypeDWARFDebugAbbrev:
|
||||
case lldb::eSectionTypeDWARFDebugAranges:
|
||||
case lldb::eSectionTypeDWARFDebugFrame:
|
||||
case lldb::eSectionTypeDWARFDebugInfo:
|
||||
case lldb::eSectionTypeDWARFDebugLine:
|
||||
case lldb::eSectionTypeDWARFDebugLoc:
|
||||
case lldb::eSectionTypeDWARFDebugMacInfo:
|
||||
case lldb::eSectionTypeDWARFDebugPubNames:
|
||||
case lldb::eSectionTypeDWARFDebugPubTypes:
|
||||
case lldb::eSectionTypeDWARFDebugRanges:
|
||||
case lldb::eSectionTypeDWARFDebugStr:
|
||||
case lldb::eSectionTypeDWARFAppleNames:
|
||||
case lldb::eSectionTypeDWARFAppleTypes:
|
||||
case lldb::eSectionTypeDWARFAppleNamespaces:
|
||||
case lldb::eSectionTypeDWARFAppleObjC:
|
||||
err.Clear();
|
||||
break;
|
||||
default:
|
||||
record.m_process_address = Malloc (record.m_size,
|
||||
record.m_alignment,
|
||||
record.m_permissions,
|
||||
eAllocationPolicyProcessOnly,
|
||||
err);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!err.Success())
|
||||
{
|
||||
|
@ -696,17 +848,18 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
|
|||
bool
|
||||
IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
|
||||
{
|
||||
bool wrote_something = false;
|
||||
for (AllocationRecord &record : m_records)
|
||||
{
|
||||
if (record.m_process_address == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
|
||||
lldb_private::Error err;
|
||||
|
||||
WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
|
||||
if (record.m_process_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
lldb_private::Error err;
|
||||
WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
|
||||
if (err.Success())
|
||||
wrote_something = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return wrote_something;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -722,3 +875,79 @@ IRExecutionUnit::AllocationRecord::dump (Log *log)
|
|||
(unsigned)m_alignment,
|
||||
(unsigned)m_section_id);
|
||||
}
|
||||
|
||||
|
||||
lldb::ByteOrder
|
||||
IRExecutionUnit::GetByteOrder () const
|
||||
{
|
||||
ExecutionContext exe_ctx (GetBestExecutionContextScope());
|
||||
return exe_ctx.GetByteOrder();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
IRExecutionUnit::GetAddressByteSize () const
|
||||
{
|
||||
ExecutionContext exe_ctx (GetBestExecutionContextScope());
|
||||
return exe_ctx.GetAddressByteSize();
|
||||
}
|
||||
|
||||
void
|
||||
IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::Symtab &symtab)
|
||||
{
|
||||
// No symbols yet...
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file,
|
||||
lldb_private::SectionList §ion_list)
|
||||
{
|
||||
for (AllocationRecord &record : m_records)
|
||||
{
|
||||
if (record.m_size > 0)
|
||||
{
|
||||
lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(),
|
||||
obj_file,
|
||||
record.m_section_id,
|
||||
ConstString(record.m_name),
|
||||
record.m_sect_type,
|
||||
record.m_process_address,
|
||||
record.m_size,
|
||||
record.m_host_address, // file_offset (which is the host address for the data)
|
||||
record.m_size, // file_size
|
||||
record.m_permissions)); // flags
|
||||
section_list.AddSection (section_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch)
|
||||
{
|
||||
ExecutionContext exe_ctx (GetBestExecutionContextScope());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
if (target)
|
||||
arch = target->GetArchitecture();
|
||||
else
|
||||
arch.Clear();
|
||||
return arch.IsValid();
|
||||
}
|
||||
|
||||
lldb::ModuleSP
|
||||
IRExecutionUnit::GetJITModule ()
|
||||
{
|
||||
ExecutionContext exe_ctx (GetBestExecutionContextScope());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
if (target)
|
||||
{
|
||||
lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this()));
|
||||
if (jit_module_sp)
|
||||
{
|
||||
bool changed = false;
|
||||
jit_module_sp->SetLoadAddress(*target, 0, true, changed);
|
||||
}
|
||||
return jit_module_sp;
|
||||
}
|
||||
return lldb::ModuleSP();
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IRForTarget::LookupResult
|
||||
IRForTarget::GetFunctionAddress (llvm::Function *fun,
|
||||
uint64_t &fun_addr,
|
||||
lldb_private::ConstString &name,
|
||||
|
@ -182,7 +182,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
|
|||
if (m_error_stream)
|
||||
m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
|
||||
|
||||
return false;
|
||||
return LookupResult::Fail;
|
||||
case Intrinsic::memcpy:
|
||||
{
|
||||
static lldb_private::ConstString g_memcpy_str ("memcpy");
|
||||
|
@ -195,6 +195,8 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
|
|||
name = g_memset_str;
|
||||
}
|
||||
break;
|
||||
case Intrinsic::dbg_declare:
|
||||
return LookupResult::Ignore;
|
||||
}
|
||||
|
||||
if (log && name)
|
||||
|
@ -258,7 +260,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
|
|||
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
|
||||
mangled_name.GetName().GetCString());
|
||||
}
|
||||
return false;
|
||||
return LookupResult::Fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,14 +274,14 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
|
|||
if (m_error_stream)
|
||||
m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
|
||||
|
||||
return false;
|
||||
return LookupResult::Fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr);
|
||||
|
||||
return true;
|
||||
return LookupResult::Success;
|
||||
}
|
||||
|
||||
llvm::Constant *
|
||||
|
@ -339,34 +341,46 @@ IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
|
|||
lldb_private::ConstString name;
|
||||
Constant **value_ptr = NULL;
|
||||
|
||||
if (!GetFunctionAddress(fun,
|
||||
addr,
|
||||
name,
|
||||
value_ptr))
|
||||
LookupResult result = GetFunctionAddress(fun,
|
||||
addr,
|
||||
name,
|
||||
value_ptr);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case LookupResult::Fail:
|
||||
return false; // GetFunctionAddress reports its own errors
|
||||
|
||||
Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
|
||||
|
||||
RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
|
||||
|
||||
if (value_ptr)
|
||||
*value_ptr = value;
|
||||
|
||||
case LookupResult::Ignore:
|
||||
break; // Nothing to do
|
||||
|
||||
case LookupResult::Success:
|
||||
{
|
||||
Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
|
||||
|
||||
RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
|
||||
|
||||
if (value_ptr)
|
||||
*value_ptr = value;
|
||||
|
||||
// If we are replacing a function with the nobuiltin attribute, it may
|
||||
// be called with the builtin attribute on call sites. Remove any such
|
||||
// attributes since it's illegal to have a builtin call to something
|
||||
// other than a nobuiltin function.
|
||||
if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
|
||||
llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
|
||||
// If we are replacing a function with the nobuiltin attribute, it may
|
||||
// be called with the builtin attribute on call sites. Remove any such
|
||||
// attributes since it's illegal to have a builtin call to something
|
||||
// other than a nobuiltin function.
|
||||
if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
|
||||
llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
|
||||
|
||||
for (auto u : fun->users()) {
|
||||
if (auto call = dyn_cast<CallInst>(u)) {
|
||||
call->removeAttribute(AttributeSet::FunctionIndex, builtin);
|
||||
for (auto u : fun->users()) {
|
||||
if (auto call = dyn_cast<CallInst>(u)) {
|
||||
call->removeAttribute(AttributeSet::FunctionIndex, builtin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun->replaceAllUsesWith(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
fun->replaceAllUsesWith(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -185,7 +185,7 @@ IRMemoryMap::GetAddressByteSize()
|
|||
}
|
||||
|
||||
ExecutionContextScope *
|
||||
IRMemoryMap::GetBestExecutionContextScope()
|
||||
IRMemoryMap::GetBestExecutionContextScope() const
|
||||
{
|
||||
lldb::ProcessSP process_sp = m_process_wp.lock();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// C includes
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include "lldb/Host/windows/windows.h"
|
||||
|
@ -1008,6 +1009,20 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
static void CleanupProcessSpecificLLDBTempDir ()
|
||||
{
|
||||
// Get the process specific LLDB temporary directory and delete it.
|
||||
FileSpec tmpdir_file_spec;
|
||||
if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
|
||||
{
|
||||
// Remove the LLDB temporary directory if we have one. Set "recurse" to
|
||||
// true to all files that were created for the LLDB process can be cleaned up.
|
||||
const bool recurse = true;
|
||||
Host::RemoveDirectory(tmpdir_file_spec.GetDirectory().GetCString(), recurse);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
{
|
||||
|
@ -1279,9 +1294,22 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
|||
}
|
||||
if (tmpdir_cstr)
|
||||
{
|
||||
g_lldb_tmp_dir.SetCString(tmpdir_cstr);
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_lldb_tmp_dir.GetCString());
|
||||
StreamString pid_tmpdir;
|
||||
pid_tmpdir.Printf("%s/lldb", tmpdir_cstr);
|
||||
if (Host::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
|
||||
{
|
||||
pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
|
||||
if (Host::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
|
||||
{
|
||||
// Make an atexit handler to clean up the process specify LLDB temp dir
|
||||
// and all of its contents.
|
||||
::atexit (CleanupProcessSpecificLLDBTempDir);
|
||||
g_lldb_tmp_dir.SetCString(pid_tmpdir.GetString().c_str());
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_lldb_tmp_dir.GetCString());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_tmp_dir;
|
||||
|
@ -2141,6 +2169,14 @@ Host::Unlink (const char *path)
|
|||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::RemoveDirectory (const char* path, bool recurse)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Error
|
||||
|
@ -2189,6 +2225,33 @@ Host::MakeDirectory (const char* path, uint32_t file_permissions)
|
|||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::RemoveDirectory (const char* path, bool recurse)
|
||||
{
|
||||
Error error;
|
||||
if (path && path[0])
|
||||
{
|
||||
if (recurse)
|
||||
{
|
||||
StreamString command;
|
||||
command.Printf("rm -rf \"%s\"", path);
|
||||
int status = ::system(command.GetString().c_str());
|
||||
if (status != 0)
|
||||
error.SetError(status, eErrorTypeGeneric);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (::rmdir(path) != 0)
|
||||
error.SetErrorToErrno();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("empty path");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_lldb_library(lldbPluginObjectFileJIT
|
||||
ObjectFileJIT.cpp
|
||||
)
|
|
@ -0,0 +1,14 @@
|
|||
##===- source/Plugins/ObjectFile/JIT/Makefile --------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LLDB_LEVEL := ../../../..
|
||||
LIBRARYNAME := lldbPluginObjectFileJIT
|
||||
BUILD_ARCHIVE = 1
|
||||
|
||||
include $(LLDB_LEVEL)/Makefile
|
|
@ -0,0 +1,364 @@
|
|||
//===-- ObjectFileJIT.cpp ---------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include "ObjectFileJIT.h"
|
||||
|
||||
#include "lldb/lldb-private-log.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/DataBuffer.h"
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/FileSpecList.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/ModuleSpec.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/RangeMap.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Core/UUID.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/SectionLoadList.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include "Utility/UuidCompatibility.h"
|
||||
#endif
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
||||
void
|
||||
ObjectFileJIT::Initialize()
|
||||
{
|
||||
PluginManager::RegisterPlugin (GetPluginNameStatic(),
|
||||
GetPluginDescriptionStatic(),
|
||||
CreateInstance,
|
||||
CreateMemoryInstance,
|
||||
GetModuleSpecifications);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFileJIT::Terminate()
|
||||
{
|
||||
PluginManager::UnregisterPlugin (CreateInstance);
|
||||
}
|
||||
|
||||
|
||||
lldb_private::ConstString
|
||||
ObjectFileJIT::GetPluginNameStatic()
|
||||
{
|
||||
static ConstString g_name("jit");
|
||||
return g_name;
|
||||
}
|
||||
|
||||
const char *
|
||||
ObjectFileJIT::GetPluginDescriptionStatic()
|
||||
{
|
||||
return "JIT code object file";
|
||||
}
|
||||
|
||||
ObjectFile *
|
||||
ObjectFileJIT::CreateInstance (const lldb::ModuleSP &module_sp,
|
||||
DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset,
|
||||
const FileSpec* file,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length)
|
||||
{
|
||||
// JIT'ed object file is backed by the ObjectFileJITDelegate, never
|
||||
// read from a file
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ObjectFile *
|
||||
ObjectFileJIT::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
|
||||
DataBufferSP& data_sp,
|
||||
const ProcessSP &process_sp,
|
||||
lldb::addr_t header_addr)
|
||||
{
|
||||
// JIT'ed object file is backed by the ObjectFileJITDelegate, never
|
||||
// read from memory
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ObjectFileJIT::GetModuleSpecifications (const lldb_private::FileSpec& file,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length,
|
||||
lldb_private::ModuleSpecList &specs)
|
||||
{
|
||||
// JIT'ed object file can't be read from a file on disk
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjectFileJIT::ObjectFileJIT (const lldb::ModuleSP &module_sp,
|
||||
const ObjectFileJITDelegateSP &delegate_sp) :
|
||||
ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0),
|
||||
m_delegate_wp ()
|
||||
{
|
||||
if (delegate_sp)
|
||||
{
|
||||
m_delegate_wp = delegate_sp;
|
||||
m_data.SetByteOrder(delegate_sp->GetByteOrder());
|
||||
m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
ObjectFileJIT::~ObjectFileJIT()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ObjectFileJIT::ParseHeader ()
|
||||
{
|
||||
// JIT code is never in a file, nor is it required to have any header
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteOrder
|
||||
ObjectFileJIT::GetByteOrder () const
|
||||
{
|
||||
return m_data.GetByteOrder();
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectFileJIT::IsExecutable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ObjectFileJIT::GetAddressByteSize () const
|
||||
{
|
||||
return m_data.GetAddressByteSize();
|
||||
}
|
||||
|
||||
|
||||
Symtab *
|
||||
ObjectFileJIT::GetSymtab()
|
||||
{
|
||||
ModuleSP module_sp(GetModule());
|
||||
if (module_sp)
|
||||
{
|
||||
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
|
||||
if (m_symtab_ap.get() == NULL)
|
||||
{
|
||||
m_symtab_ap.reset(new Symtab(this));
|
||||
Mutex::Locker symtab_locker (m_symtab_ap->GetMutex());
|
||||
ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
|
||||
if (delegate_sp)
|
||||
delegate_sp->PopulateSymtab(this, *m_symtab_ap);
|
||||
// TODO: get symbols from delegate
|
||||
m_symtab_ap->Finalize ();
|
||||
}
|
||||
}
|
||||
return m_symtab_ap.get();
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectFileJIT::IsStripped ()
|
||||
{
|
||||
return false; // JIT code that is in a module is never stripped
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFileJIT::CreateSections (SectionList &unified_section_list)
|
||||
{
|
||||
if (!m_sections_ap.get())
|
||||
{
|
||||
m_sections_ap.reset(new SectionList());
|
||||
ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
|
||||
if (delegate_sp)
|
||||
{
|
||||
delegate_sp->PopulateSectionList(this, *m_sections_ap);
|
||||
unified_section_list = *m_sections_ap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFileJIT::Dump (Stream *s)
|
||||
{
|
||||
ModuleSP module_sp(GetModule());
|
||||
if (module_sp)
|
||||
{
|
||||
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
|
||||
s->Printf("%p: ", this);
|
||||
s->Indent();
|
||||
s->PutCString("ObjectFileJIT");
|
||||
|
||||
ArchSpec arch;
|
||||
if (GetArchitecture(arch))
|
||||
*s << ", arch = " << arch.GetArchitectureName();
|
||||
|
||||
s->EOL();
|
||||
|
||||
SectionList *sections = GetSectionList();
|
||||
if (sections)
|
||||
sections->Dump(s, NULL, true, UINT32_MAX);
|
||||
|
||||
if (m_symtab_ap.get())
|
||||
m_symtab_ap->Dump(s, NULL, eSortOrderNone);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectFileJIT::GetUUID (lldb_private::UUID* uuid)
|
||||
{
|
||||
// TODO: maybe get from delegate, not needed for first pass
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
ObjectFileJIT::GetDependentModules (FileSpecList& files)
|
||||
{
|
||||
// JIT modules don't have dependencies, but they could
|
||||
// if external functions are called and we know where they are
|
||||
files.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
lldb_private::Address
|
||||
ObjectFileJIT::GetEntryPointAddress ()
|
||||
{
|
||||
return Address();
|
||||
}
|
||||
|
||||
lldb_private::Address
|
||||
ObjectFileJIT::GetHeaderAddress ()
|
||||
{
|
||||
return Address();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ObjectFile::Type
|
||||
ObjectFileJIT::CalculateType()
|
||||
{
|
||||
return eTypeJIT;
|
||||
}
|
||||
|
||||
ObjectFile::Strata
|
||||
ObjectFileJIT::CalculateStrata()
|
||||
{
|
||||
return eStrataJIT;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ObjectFileJIT::GetArchitecture (ArchSpec &arch)
|
||||
{
|
||||
ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
|
||||
if (delegate_sp)
|
||||
return delegate_sp->GetArchitecture(arch);
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
lldb_private::ConstString
|
||||
ObjectFileJIT::GetPluginName()
|
||||
{
|
||||
return GetPluginNameStatic();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ObjectFileJIT::GetPluginVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ObjectFileJIT::SetLoadAddress (Target &target,
|
||||
lldb::addr_t value,
|
||||
bool value_is_offset)
|
||||
{
|
||||
bool changed = false;
|
||||
size_t num_loaded_sections = 0;
|
||||
SectionList *section_list = GetSectionList ();
|
||||
if (section_list)
|
||||
{
|
||||
const size_t num_sections = section_list->GetSize();
|
||||
// "value" is an offset to apply to each top level segment
|
||||
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
|
||||
{
|
||||
// Iterate through the object file sections to find all
|
||||
// of the sections that size on disk (to avoid __PAGEZERO)
|
||||
// and load them
|
||||
SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
|
||||
if (section_sp &&
|
||||
section_sp->GetFileSize() > 0 &&
|
||||
section_sp->IsThreadSpecific() == false)
|
||||
{
|
||||
if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value))
|
||||
++num_loaded_sections;
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = num_loaded_sections > 0;
|
||||
return num_loaded_sections > 0;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
|
||||
off_t section_offset,
|
||||
void *dst,
|
||||
size_t dst_len) const
|
||||
{
|
||||
lldb::offset_t file_size = section->GetFileSize();
|
||||
if (section_offset < file_size)
|
||||
{
|
||||
uint64_t src_len = file_size - section_offset;
|
||||
if (src_len > dst_len)
|
||||
src_len = dst_len;
|
||||
const uint8_t *src = ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
|
||||
|
||||
memcpy (dst, src, src_len);
|
||||
return src_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
size_t
|
||||
ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
|
||||
lldb_private::DataExtractor& section_data) const
|
||||
{
|
||||
if (section->GetFileSize())
|
||||
{
|
||||
const void *src = (void *)(uintptr_t)section->GetFileOffset();
|
||||
|
||||
DataBufferSP data_sp (new lldb_private::DataBufferHeap(src, section->GetFileSize()));
|
||||
if (data_sp)
|
||||
{
|
||||
section_data.SetData (data_sp, 0, data_sp->GetByteSize());
|
||||
section_data.SetByteOrder (GetByteOrder());
|
||||
section_data.SetAddressByteSize (GetAddressByteSize());
|
||||
return section_data.GetByteSize();
|
||||
}
|
||||
}
|
||||
section_data.Clear();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
//===-- ObjectFileJIT.h -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_ObjectFileJIT_h_
|
||||
#define liblldb_ObjectFileJIT_h_
|
||||
|
||||
#include "lldb/Core/Address.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This class needs to be hidden as eventually belongs in a plugin that
|
||||
// will export the ObjectFile protocol
|
||||
//----------------------------------------------------------------------
|
||||
class ObjectFileJIT :
|
||||
public lldb_private::ObjectFile
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
// Static Functions
|
||||
//------------------------------------------------------------------
|
||||
static void
|
||||
Initialize();
|
||||
|
||||
static void
|
||||
Terminate();
|
||||
|
||||
static lldb_private::ConstString
|
||||
GetPluginNameStatic();
|
||||
|
||||
static const char *
|
||||
GetPluginDescriptionStatic();
|
||||
|
||||
static lldb_private::ObjectFile *
|
||||
CreateInstance (const lldb::ModuleSP &module_sp,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset,
|
||||
const lldb_private::FileSpec* file,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length);
|
||||
|
||||
static lldb_private::ObjectFile *
|
||||
CreateMemoryInstance (const lldb::ModuleSP &module_sp,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
const lldb::ProcessSP &process_sp,
|
||||
lldb::addr_t header_addr);
|
||||
|
||||
static size_t
|
||||
GetModuleSpecifications (const lldb_private::FileSpec& file,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length,
|
||||
lldb_private::ModuleSpecList &specs);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Member Functions
|
||||
//------------------------------------------------------------------
|
||||
ObjectFileJIT (const lldb::ModuleSP &module_sp,
|
||||
const lldb::ObjectFileJITDelegateSP &delegate_sp);
|
||||
|
||||
virtual
|
||||
~ObjectFileJIT();
|
||||
|
||||
virtual bool
|
||||
ParseHeader ();
|
||||
|
||||
virtual bool
|
||||
SetLoadAddress(lldb_private::Target &target,
|
||||
lldb::addr_t value,
|
||||
bool value_is_offset);
|
||||
|
||||
virtual lldb::ByteOrder
|
||||
GetByteOrder () const;
|
||||
|
||||
virtual bool
|
||||
IsExecutable () const;
|
||||
|
||||
virtual uint32_t
|
||||
GetAddressByteSize () const;
|
||||
|
||||
virtual lldb_private::Symtab *
|
||||
GetSymtab();
|
||||
|
||||
virtual bool
|
||||
IsStripped ();
|
||||
|
||||
virtual void
|
||||
CreateSections (lldb_private::SectionList &unified_section_list);
|
||||
|
||||
virtual void
|
||||
Dump (lldb_private::Stream *s);
|
||||
|
||||
virtual bool
|
||||
GetArchitecture (lldb_private::ArchSpec &arch);
|
||||
|
||||
virtual bool
|
||||
GetUUID (lldb_private::UUID* uuid);
|
||||
|
||||
virtual uint32_t
|
||||
GetDependentModules (lldb_private::FileSpecList& files);
|
||||
|
||||
virtual size_t
|
||||
ReadSectionData (const lldb_private::Section *section,
|
||||
off_t section_offset,
|
||||
void *dst,
|
||||
size_t dst_len) const;
|
||||
virtual size_t
|
||||
ReadSectionData (const lldb_private::Section *section,
|
||||
lldb_private::DataExtractor& section_data) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb_private::ConstString
|
||||
GetPluginName();
|
||||
|
||||
virtual uint32_t
|
||||
GetPluginVersion();
|
||||
|
||||
virtual lldb_private::Address
|
||||
GetEntryPointAddress ();
|
||||
|
||||
virtual lldb_private::Address
|
||||
GetHeaderAddress ();
|
||||
|
||||
virtual ObjectFile::Type
|
||||
CalculateType();
|
||||
|
||||
virtual ObjectFile::Strata
|
||||
CalculateStrata();
|
||||
protected:
|
||||
lldb::ObjectFileJITDelegateWP m_delegate_wp;
|
||||
};
|
||||
|
||||
#endif // liblldb_ObjectFileJIT_h_
|
|
@ -163,15 +163,17 @@ RegisterContextLLDB::InitializeZerothFrame()
|
|||
UnwindLogMsg ("using architectural default unwind method");
|
||||
}
|
||||
|
||||
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
|
||||
// We require either a symbol or function in the symbols context to be successfully
|
||||
// filled in or this context is of no use to us.
|
||||
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
|
||||
if (pc_module_sp.get()
|
||||
&& (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
|
||||
&& (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, resolve_scope, m_sym_ctx) & resolve_scope))
|
||||
{
|
||||
m_sym_ctx_valid = true;
|
||||
}
|
||||
|
||||
AddressRange addr_range;
|
||||
m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
|
||||
m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range);
|
||||
|
||||
if (IsTrapHandlerSymbol (process, m_sym_ctx))
|
||||
{
|
||||
|
@ -417,18 +419,20 @@ RegisterContextLLDB::InitializeNonZerothFrame()
|
|||
// a function/symbol because it is beyond the bounds of the correct
|
||||
// function and there's no symbol there. ResolveSymbolContextForAddress
|
||||
// will fail to find a symbol, back up the pc by 1 and re-search.
|
||||
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
|
||||
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
|
||||
eSymbolContextFunction | eSymbolContextSymbol,
|
||||
resolve_scope,
|
||||
m_sym_ctx, resolve_tail_call_address);
|
||||
|
||||
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
|
||||
if ((resolved_scope & eSymbolContextSymbol) == eSymbolContextSymbol)
|
||||
// We require either a symbol or function in the symbols context to be successfully
|
||||
// filled in or this context is of no use to us.
|
||||
if (resolve_scope & resolved_scope)
|
||||
{
|
||||
m_sym_ctx_valid = true;
|
||||
}
|
||||
|
||||
AddressRange addr_range;
|
||||
if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
|
||||
if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
|
||||
{
|
||||
m_sym_ctx_valid = false;
|
||||
}
|
||||
|
@ -461,13 +465,12 @@ RegisterContextLLDB::InitializeNonZerothFrame()
|
|||
temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
|
||||
m_sym_ctx.Clear(false);
|
||||
m_sym_ctx_valid = false;
|
||||
if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
|
||||
uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
|
||||
|
||||
if (pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope)
|
||||
{
|
||||
m_sym_ctx_valid = true;
|
||||
}
|
||||
if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
|
||||
{
|
||||
m_sym_ctx_valid = false;
|
||||
if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
|
||||
m_sym_ctx_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,7 +710,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
|
|||
// Note, if we have a symbol context & a symbol, we don't want to follow this code path. This is
|
||||
// for jumping to memory regions without any information available.
|
||||
|
||||
if ((!m_sym_ctx_valid || m_sym_ctx.symbol == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
|
||||
if ((!m_sym_ctx_valid || (m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) && behaves_like_zeroth_frame && m_current_pc.IsValid())
|
||||
{
|
||||
uint32_t permissions;
|
||||
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
|
||||
|
|
|
@ -244,6 +244,7 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
|
|||
case ObjectFile::eTypeObjectFile:
|
||||
case ObjectFile::eTypeSharedLibrary:
|
||||
case ObjectFile::eTypeStubLibrary:
|
||||
case ObjectFile::eTypeJIT:
|
||||
return false;
|
||||
case ObjectFile::eTypeExecutable:
|
||||
case ObjectFile::eTypeDynamicLinker:
|
||||
|
|
|
@ -341,6 +341,7 @@ SymbolFileDWARFDebugMap::InitOSO()
|
|||
case ObjectFile::eTypeObjectFile:
|
||||
case ObjectFile::eTypeStubLibrary:
|
||||
case ObjectFile::eTypeUnknown:
|
||||
case ObjectFile::eTypeJIT:
|
||||
return;
|
||||
|
||||
case ObjectFile::eTypeExecutable:
|
||||
|
|
|
@ -239,7 +239,7 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
|
|||
const FileSpec *file_spec_ptr,
|
||||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
const lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset
|
||||
) :
|
||||
ModuleChild (module_sp),
|
||||
|
|
|
@ -1142,32 +1142,39 @@ void
|
|||
Target::ModuleAdded (const ModuleList& module_list, const ModuleSP &module_sp)
|
||||
{
|
||||
// A module is being added to this target for the first time
|
||||
ModuleList my_module_list;
|
||||
my_module_list.Append(module_sp);
|
||||
LoadScriptingResourceForModule(module_sp, this);
|
||||
ModulesDidLoad (my_module_list);
|
||||
if (m_valid)
|
||||
{
|
||||
ModuleList my_module_list;
|
||||
my_module_list.Append(module_sp);
|
||||
LoadScriptingResourceForModule(module_sp, this);
|
||||
ModulesDidLoad (my_module_list);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Target::ModuleRemoved (const ModuleList& module_list, const ModuleSP &module_sp)
|
||||
{
|
||||
// A module is being added to this target for the first time
|
||||
ModuleList my_module_list;
|
||||
my_module_list.Append(module_sp);
|
||||
ModulesDidUnload (my_module_list, false);
|
||||
if (m_valid)
|
||||
{
|
||||
ModuleList my_module_list;
|
||||
my_module_list.Append(module_sp);
|
||||
ModulesDidUnload (my_module_list, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Target::ModuleUpdated (const ModuleList& module_list, const ModuleSP &old_module_sp, const ModuleSP &new_module_sp)
|
||||
{
|
||||
// A module is replacing an already added module
|
||||
m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
|
||||
if (m_valid)
|
||||
m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
|
||||
}
|
||||
|
||||
void
|
||||
Target::ModulesDidLoad (ModuleList &module_list)
|
||||
{
|
||||
if (module_list.GetSize())
|
||||
if (m_valid && module_list.GetSize())
|
||||
{
|
||||
m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
|
||||
if (m_process_sp)
|
||||
|
@ -1182,7 +1189,7 @@ Target::ModulesDidLoad (ModuleList &module_list)
|
|||
void
|
||||
Target::SymbolsDidLoad (ModuleList &module_list)
|
||||
{
|
||||
if (module_list.GetSize())
|
||||
if (m_valid && module_list.GetSize())
|
||||
{
|
||||
if (m_process_sp)
|
||||
{
|
||||
|
@ -1202,7 +1209,7 @@ Target::SymbolsDidLoad (ModuleList &module_list)
|
|||
void
|
||||
Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
|
||||
{
|
||||
if (module_list.GetSize())
|
||||
if (m_valid && module_list.GetSize())
|
||||
{
|
||||
m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
|
||||
// TODO: make event data that packages up the module_list
|
||||
|
|
Loading…
Reference in New Issue