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
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index ea3ff95..44f1e53 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -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 @@
//===----------------------------------------------------------------------===//
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- 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;
+}
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index f856f72..a7e7ac0 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -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 @@
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 @@
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()
{
+ 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 @@
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 @@
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 @@
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;
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 2b9bd2c..4eefddd 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -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 @@
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 ()
{
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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");
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index c911c27..de5b0c1 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -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 @@
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 ()
{
+ 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 @@
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 @@
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
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 17bd03a..d50802a 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -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 @@
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 ()
+{
+}
void
IRExecutionUnit::MemoryManager::setMemoryWritable ()
{
@@ -464,8 +472,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
(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();
+}
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index 0ec3525..a1fa653 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -157,7 +157,7 @@
return true;
}
-bool
+IRForTarget::LookupResult
IRForTarget::GetFunctionAddress (llvm::Function *fun,
uint64_t &fun_addr,
lldb_private::ConstString &name,
@@ -182,7 +182,7 @@
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 @@
name = g_memset_str;
}
break;
+ case Intrinsic::dbg_declare:
+ return LookupResult::Ignore;
}
if (log && name)
@@ -258,7 +260,7 @@
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 @@
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 @@
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;
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index f927e8b..7bc2ed0 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -185,7 +185,7 @@
}
ExecutionContextScope *
-IRMemoryMap::GetBestExecutionContextScope()
+IRMemoryMap::GetBestExecutionContextScope() const
{
lldb::ProcessSP process_sp = m_process_wp.lock();