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 &section_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();