예제 #1
0
bool
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const char *plugin_name,
    const char *flavor,
    const ExecutionContext &exe_ctx,
    const ConstString &name,
    Module *module,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    SymbolContextList sc_list;
    if (name)
    {
        const bool include_symbols = true;
        const bool include_inlines = true;
        if (module)
        {
            module->FindFunctions (name,
                                   NULL,
                                   eFunctionNameTypeAuto, 
                                   include_symbols,
                                   include_inlines,
                                   true,
                                   sc_list);
        }
        else if (exe_ctx.GetTargetPtr())
        {
            exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name, 
                                                               eFunctionNameTypeAuto,
                                                               include_symbols,
                                                               include_inlines,
                                                               false,
                                                               sc_list);
        }
    }
    
    if (sc_list.GetSize ())
    {
        return Disassemble (debugger, 
                            arch, 
                            plugin_name,
                            flavor,
                            exe_ctx, 
                            sc_list,
                            num_instructions, 
                            num_mixed_context_lines, 
                            options,
                            strm);
    }
    return false;
}
bool UnwindAssembly_x86::FirstNonPrologueInsn(
    AddressRange &func, const ExecutionContext &exe_ctx,
    Address &first_non_prologue_insn) {

  if (!func.GetBaseAddress().IsValid())
    return false;

  Target *target = exe_ctx.GetTargetPtr();
  if (target == nullptr)
    return false;

  if (m_assembly_inspection_engine == nullptr)
    return false;

  const bool prefer_file_cache = true;
  std::vector<uint8_t> function_text(func.GetByteSize());
  Status error;
  if (target->ReadMemory(func.GetBaseAddress(), prefer_file_cache,
                         function_text.data(), func.GetByteSize(),
                         error) == func.GetByteSize()) {
    size_t offset;
    if (m_assembly_inspection_engine->FindFirstNonPrologueInstruction(
            function_text.data(), func.GetByteSize(), offset)) {
      first_non_prologue_insn = func.GetBaseAddress();
      first_non_prologue_insn.Slide(offset);
    }
    return true;
  }
  return false;
}
예제 #3
0
static void
ResolveAddress (const ExecutionContext &exe_ctx,
                const Address &addr, 
                Address &resolved_addr)
{
    if (!addr.IsSectionOffset())
    {
        // If we weren't passed in a section offset address range,
        // try and resolve it to something
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
        {
            if (target->GetSectionLoadList().IsEmpty())
            {
                target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
            }
            else
            {
                target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
            }
            // We weren't able to resolve the address, just treat it as a
            // raw address
            if (resolved_addr.IsValid())
                return;
        }
    }
    resolved_addr = addr;
}
예제 #4
0
lldb::ExpressionResults
GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                            ExecutionContext &exe_ctx,
                            const EvaluateExpressionOptions &options,
                            lldb::UserExpressionSP &shared_ptr_to_me,
                            lldb::ExpressionVariableSP &result) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
  lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();
  Target *target = exe_ctx.GetTargetPtr();

  if (target == nullptr || process == nullptr ||
      process->GetState() != lldb::eStateStopped) {
    if (execution_policy == eExecutionPolicyAlways) {
      if (log)
        log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
                    "but is not constant ==");

      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression needed to run but couldn't");

      return execution_results;
    }
  }

  m_interpreter->set_use_dynamic(options.GetUseDynamic());
  ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
  Error err = m_interpreter->error();
  m_interpreter.reset();

  if (!result_val_sp) {
    const char *error_cstr = err.AsCString();
    if (error_cstr && error_cstr[0])
      diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
    else
      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression can't be interpreted or run");
    return lldb::eExpressionDiscarded;
  }
  result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
  result->m_live_sp = result->m_frozen_sp = result_val_sp;
  result->m_flags |= ExpressionVariable::EVIsProgramReference;
  PersistentExpressionState *pv =
      target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
  if (pv != nullptr) {
    result->SetName(pv->GetNextPersistentVariableName());
    pv->AddVariable(result);
  }
  return lldb::eExpressionCompleted;
}
예제 #5
0
lldb::ExpressionResults
UserExpression::Execute(DiagnosticManager &diagnostic_manager,
                        ExecutionContext &exe_ctx,
                        const EvaluateExpressionOptions &options,
                        lldb::UserExpressionSP &shared_ptr_to_me,
                        lldb::ExpressionVariableSP &result_var)
{
    lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
    Target *target = exe_ctx.GetTargetPtr();
    if (options.GetResultIsInternal() && result_var && target)
    {
        target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var);
    }
    return expr_result;
}
bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
                                 ExecutionContext &exe_ctx) {
  if (Target *target = exe_ctx.GetTargetPtr()) {
    if (PersistentExpressionState *persistent_state =
            target->GetPersistentExpressionStateForLanguage(
                lldb::eLanguageTypeC)) {
      m_result_delegate.RegisterPersistentState(persistent_state);
    } else {
      diagnostic_manager.PutString(
          eDiagnosticSeverityError,
          "couldn't start parsing (no persistent data)");
      return false;
    }
  } else {
    diagnostic_manager.PutString(eDiagnosticSeverityError,
                                 "error: couldn't start parsing (no target)");
    return false;
  }
  return true;
}
bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
                                ExecutionContext &exe_ctx,
                                lldb_private::ExecutionPolicy execution_policy,
                                bool keep_result_in_memory,
                                bool generate_debug_info) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

  if (!PrepareForParsing(diagnostic_manager, exe_ctx))
    return false;

  if (log)
    log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

  ////////////////////////////////////
  // Set up the target and compiler
  //

  Target *target = exe_ctx.GetTargetPtr();

  if (!target) {
    diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
    return false;
  }

  //////////////////////////
  // Parse the expression
  //

  m_materializer_ap.reset(new Materializer());

  ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);

  OnExit on_exit([this]() { ResetDeclMap(); });

  if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
    diagnostic_manager.PutString(
        eDiagnosticSeverityError,
        "current process state is unsuitable for expression parsing");
    return false;
  }

  if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
    DeclMap()->SetLookupsEnabled(true);
  }

  Process *process = exe_ctx.GetProcessPtr();
  ExecutionContextScope *exe_scope = process;

  if (!exe_scope)
    exe_scope = exe_ctx.GetTargetPtr();

  // We use a shared pointer here so we can use the original parser - if it
  // succeeds or the rewrite parser we might make if it fails.  But the
  // parser_sp will never be empty.

  ClangExpressionParser parser(exe_scope, *this, generate_debug_info);

  unsigned num_errors = parser.Parse(diagnostic_manager);

  // Check here for FixItHints.  If there are any try to apply the fixits and
  // set the fixed text in m_fixed_text before returning an error.
  if (num_errors) {
    if (diagnostic_manager.HasFixIts()) {
      if (parser.RewriteExpression(diagnostic_manager)) {
        size_t fixed_start;
        size_t fixed_end;
        const std::string &fixed_expression =
            diagnostic_manager.GetFixedExpression();
        if (ExpressionSourceCode::GetOriginalBodyBounds(
                fixed_expression, m_expr_lang, fixed_start, fixed_end))
          m_fixed_text =
              fixed_expression.substr(fixed_start, fixed_end - fixed_start);
      }
    }
    return false;
  }

  //////////////////////////////////////////////////////////////////////////////////////////
  // Prepare the output of the parser for execution, evaluating it statically
  // if possible
  //

  {
    Status jit_error = parser.PrepareForExecution(
        m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
        m_can_interpret, execution_policy);

    if (!jit_error.Success()) {
      const char *error_cstr = jit_error.AsCString();
      if (error_cstr && error_cstr[0])
        diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
      else
        diagnostic_manager.PutString(eDiagnosticSeverityError,
                                     "expression can't be interpreted or run");
      return false;
    }
  }

  if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) {
    Status static_init_error =
        parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx);

    if (!static_init_error.Success()) {
      const char *error_cstr = static_init_error.AsCString();
      if (error_cstr && error_cstr[0])
        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                  "couldn't run static initializers: %s\n",
                                  error_cstr);
      else
        diagnostic_manager.PutString(eDiagnosticSeverityError,
                                     "couldn't run static initializers\n");
      return false;
    }
  }

  if (m_execution_unit_sp) {
    bool register_execution_unit = false;

    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
      register_execution_unit = true;
    }

    // If there is more than one external function in the execution unit, it
    // needs to keep living even if it's not top level, because the result
    // could refer to that function.

    if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
      register_execution_unit = true;
    }

    if (register_execution_unit) {
      llvm::cast<PersistentExpressionState>(
          exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
              m_language))
          ->RegisterExecutionUnit(m_execution_unit_sp);
    }
  }

  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);
    }
  }

  if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
    m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
  return true;
}
예제 #8
0
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] error_stream
///     A stream to print parse errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool
ClangUtilityFunction::Install (Stream &error_stream,
                               ExecutionContext &exe_ctx)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
    {
        error_stream.PutCString("error: already installed\n");
        return false;
    }

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (!process)
    {
        error_stream.PutCString ("error: invalid process\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    bool keep_result_in_memory = false;

    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));

    m_data_allocator.reset(new ProcessDataAllocator(*process));

    if (!m_expr_decl_map->WillParse(exe_ctx))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
        return false;
    }

    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);

        m_expr_decl_map.reset();

        return false;
    }

    //////////////////////////////////
    // JIT the output of the parser
    //

    lldb::ClangExpressionVariableSP const_result;

    bool evaluated_statically = false; // should stay that way

    Error jit_error = parser.PrepareForExecution (m_jit_alloc,
                      m_jit_start_addr,
                      m_jit_end_addr,
                      exe_ctx,
                      m_data_allocator.get(),
                      evaluated_statically,
                      const_result,
                      eExecutionPolicyAlways);

    if (log)
    {
        StreamString dump_string;
        m_data_allocator->Dump(dump_string);

        log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
    }

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());

#if 0
    // jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr,
                    m_function_name.c_str(),
                    m_function_text.c_str());
#endif

    m_expr_decl_map->DidParse();

    m_expr_decl_map.reset();

    if (jit_error.Success())
    {
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
예제 #9
0
void
ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
        log->Printf("ClangUserExpression::ScanContext()");

    m_target = exe_ctx.GetTargetPtr();

    if (!(m_allow_cxx || m_allow_objc))
    {
        if (log)
            log->Printf("  [CUE::SC] Settings inhibit C++ and Objective-C");
        return;
    }

    StackFrame *frame = exe_ctx.GetFramePtr();
    if (frame == NULL)
    {
        if (log)
            log->Printf("  [CUE::SC] Null stack frame");
        return;
    }

    SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);

    if (!sym_ctx.function)
    {
        if (log)
            log->Printf("  [CUE::SC] Null function");
        return;
    }

    // Find the block that defines the function represented by "sym_ctx"
    Block *function_block = sym_ctx.GetFunctionBlock();

    if (!function_block)
    {
        if (log)
            log->Printf("  [CUE::SC] Null function block");
        return;
    }

    clang::DeclContext *decl_context = function_block->GetClangDeclContext();

    if (!decl_context)
    {
        if (log)
            log->Printf("  [CUE::SC] Null decl context");
        return;
    }

    if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
    {
        if (m_allow_cxx && method_decl->isInstance())
        {
            if (m_enforce_valid_object)
            {
                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));

                const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";

                if (!variable_list_sp)
                {
                    err.SetErrorString(thisErrorString);
                    return;
                }

                lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));

                if (!this_var_sp ||
                    !this_var_sp->IsInScope(frame) ||
                    !this_var_sp->LocationIsValidForFrame (frame))
                {
                    err.SetErrorString(thisErrorString);
                    return;
                }
            }

            m_cplusplus = true;
            m_needs_object_ptr = true;
        }
    }
    else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
    {
        if (m_allow_objc)
        {
            if (m_enforce_valid_object)
            {
                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));

                const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";

                if (!variable_list_sp)
                {
                    err.SetErrorString(selfErrorString);
                    return;
                }

                lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));

                if (!self_variable_sp ||
                    !self_variable_sp->IsInScope(frame) ||
                    !self_variable_sp->LocationIsValidForFrame (frame))
                {
                    err.SetErrorString(selfErrorString);
                    return;
                }
            }

            m_objectivec = true;
            m_needs_object_ptr = true;

            if (!method_decl->isInstanceMethod())
                m_static_method = true;
        }
    }
    else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context))
    {
        // We might also have a function that said in the debug information that it captured an
        // object pointer.  The best way to deal with getting to the ivars at present it by pretending
        // that this is a method of a class in whatever runtime the debug info says the object pointer
        // belongs to.  Do that here.

        ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl);
        if (metadata && metadata->HasObjectPtr())
        {
            lldb::LanguageType language = metadata->GetObjectPtrLanguage();
            if (language == lldb::eLanguageTypeC_plus_plus)
            {
                if (m_enforce_valid_object)
                {
                    lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));

                    const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";

                    if (!variable_list_sp)
                    {
                        err.SetErrorString(thisErrorString);
                        return;
                    }

                    lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));

                    if (!this_var_sp ||
                        !this_var_sp->IsInScope(frame) ||
                        !this_var_sp->LocationIsValidForFrame (frame))
                    {
                        err.SetErrorString(thisErrorString);
                        return;
                    }
                }

                m_cplusplus = true;
                m_needs_object_ptr = true;
            }
            else if (language == lldb::eLanguageTypeObjC)
            {
                if (m_enforce_valid_object)
                {
                    lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));

                    const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";

                    if (!variable_list_sp)
                    {
                        err.SetErrorString(selfErrorString);
                        return;
                    }

                    lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));

                    if (!self_variable_sp ||
                        !self_variable_sp->IsInScope(frame) ||
                        !self_variable_sp->LocationIsValidForFrame (frame))
                    {
                        err.SetErrorString(selfErrorString);
                        return;
                    }

                    Type *self_type = self_variable_sp->GetType();

                    if (!self_type)
                    {
                        err.SetErrorString(selfErrorString);
                        return;
                    }

                    ClangASTType self_clang_type = self_type->GetClangForwardType();

                    if (!self_clang_type)
                    {
                        err.SetErrorString(selfErrorString);
                        return;
                    }

                    if (self_clang_type.IsObjCClassType())
                    {
                        return;
                    }
                    else if (self_clang_type.IsObjCObjectPointerType())
                    {
                        m_objectivec = true;
                        m_needs_object_ptr = true;
                    }
                    else
                    {
                        err.SetErrorString(selfErrorString);
                        return;
                    }
                }
                else
                {
                    m_objectivec = true;
                    m_needs_object_ptr = true;
                }
            }
        }
    }
}
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] error_stream
///     A stream to print parse errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool
ClangUtilityFunction::Install (Stream &error_stream,
                               ExecutionContext &exe_ctx)
{
    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
    {
        error_stream.PutCString("error: already installed\n");
        return false;
    }
    
    ////////////////////////////////////
    // Set up the target and compiler
    //
    
    Target *target = exe_ctx.GetTargetPtr();
    
    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }
    
    Process *process = exe_ctx.GetProcessPtr();
    
    if (!process)
    {
        error_stream.PutCString ("error: invalid process\n");
        return false;
    }
        
    //////////////////////////
    // Parse the expression
    //
    
    bool keep_result_in_memory = false;
    
    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
    
    if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
        return false;
    }
        
    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
    
    unsigned num_errors = parser.Parse (error_stream);
    
    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
        
        m_expr_decl_map.reset();
        
        return false;
    }
    
    //////////////////////////////////
    // JIT the output of the parser
    //
        
    bool can_interpret = false; // should stay that way
    
    Error jit_error = parser.PrepareForExecution (m_jit_start_addr, 
                                                  m_jit_end_addr,
                                                  m_execution_unit_ap,
                                                  exe_ctx,
                                                  can_interpret,
                                                  eExecutionPolicyAlways);
    
    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
    
#if 0
	// jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr, 
                    m_function_name.c_str(), 
                    m_function_text.c_str());
#endif

    m_expr_decl_map->DidParse();
    
    m_expr_decl_map.reset();
    
    if (jit_error.Success())
    {
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
예제 #11
0
lldb_private::Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
                                            lldb::addr_t &func_end,
                                            lldb::IRExecutionUnitSP &execution_unit_sp,
                                            ExecutionContext &exe_ctx,
                                            bool &can_interpret,
                                            ExecutionPolicy execution_policy)
{
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    lldb_private::Error err;

    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());

    if (!llvm_module_ap.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }

    ConstString function_name;

    if (execution_policy != eExecutionPolicyTopLevel)
    {
        // Find the actual name of the function (it's often mangled somehow)

        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());
            return err;
        }
        else
        {
            if (log)
                log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
        }
    }

    SymbolContext sc;

    if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP())
    {
        sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
    }
    else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP())
    {
        sc.target_sp = target_sp;
    }

    LLVMUserExpression::IRPasses custom_passes;
    {
        auto lang = m_expr.Language();
        if (log)
            log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__,
                        Language::GetNameForLanguageType(lang));

        if (lang != lldb::eLanguageTypeUnknown)
        {
            auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang);
            if (runtime)
                runtime->GetIRPasses(custom_passes);
        }
    }

    if (custom_passes.EarlyPasses)
    {
        if (log)
            log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__,
                        m_expr.FunctionName());

        custom_passes.EarlyPasses->run(*llvm_module_ap);
    }

    execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
                                                 llvm_module_ap, // handed off here
                                                 function_name,
                                                 exe_ctx.GetTargetSP(),
                                                 sc,
                                                 m_compiler->getTargetOpts().Features));

    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
    ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL

    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = target->GetDebugger().GetErrorFile().get();

        IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream,
                                  function_name.AsCString());

        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

        Process *process = exe_ctx.GetProcessPtr();

        if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel)
        {
            lldb_private::Error interpret_error;

            bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
            can_interpret =
                IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
                                            interpret_error, interpret_function_calls);

            if (!can_interpret && execution_policy == eExecutionPolicyNever)
            {
                err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
                return err;
            }
        }

        if (!ir_can_run)
        {
            err.SetErrorString("The expression could not be prepared to run in the target");
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyAlways)
        {
            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyTopLevel)
        {
            err.SetErrorString(
                "Top-level code needs to be inserted into a runnable target, but the target can't be run");
            return err;
        }

        if (execution_policy == eExecutionPolicyAlways ||
            (execution_policy != eExecutionPolicyTopLevel && !can_interpret))
        {
            if (m_expr.NeedsValidation() && process)
            {
                if (!process->GetDynamicCheckers())
                {
                    DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();

                    DiagnosticManager install_diagnostics;

                    if (!dynamic_checkers->Install(install_diagnostics, exe_ctx))
                    {
                        if (install_diagnostics.Diagnostics().size())
                            err.SetErrorString("couldn't install checkers, unknown error");
                        else
                            err.SetErrorString(install_diagnostics.GetString().c_str());

                        return err;
                    }

                    process->SetDynamicCheckers(dynamic_checkers);

                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
                }

                IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());

                llvm::Module *module = execution_unit_sp->GetModule();
                if (!module || !ir_dynamic_checks.runOnModule(*module))
                {
                    err.SetErrorToGenericError();
                    err.SetErrorString("Couldn't add dynamic checks to the expression");
                    return err;
                }

                if (custom_passes.LatePasses)
                {
                    if (log)
                        log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'",
                                    __FUNCTION__, m_expr.FunctionName());

                    custom_passes.LatePasses->run(*module);
                }
            }
        }

        if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel ||
            !can_interpret)
        {
            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
        }
    }
    else
    {
        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }

    return err;
}
예제 #12
0
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, 
                                            lldb::addr_t &func_addr, 
                                            lldb::addr_t &func_end, 
                                            ExecutionContext &exe_ctx,
                                            IRForTarget::StaticDataAllocator *data_allocator,
                                            bool &evaluated_statically,
                                            lldb::ClangExpressionVariableSP &const_result,
                                            ExecutionPolicy execution_policy)
{
    func_allocation_addr = LLDB_INVALID_ADDRESS;
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;
    
    llvm::Module *module = m_code_generator->ReleaseModule();

    if (!module)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }
    
    // Find the actual name of the function (it's often mangled somehow)
    
    std::string function_name;
    
    if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
        return err;
    }
    else
    {
        if (log)
            log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName());
    }
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
    
    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = &target->GetDebugger().GetErrorStream();
    
        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  execution_policy,
                                  const_result,
                                  data_allocator,
                                  error_stream,
                                  function_name.c_str());
        
        if (!ir_for_target.runOnModule(*module))
        {
            err.SetErrorToGenericError();
            err.SetErrorString("Couldn't prepare the expression for execution in the target");
            return err;
        }
        
        if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess())
        {
            evaluated_statically = true;
            err.Clear();
            return err;
        }
        
        Process *process = exe_ctx.GetProcessPtr();

        if (!process || execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorToGenericError();
            err.SetErrorString("Execution needed to run in the target, but the target can't be run");
            return err;
        }
        
        if (execution_policy != eExecutionPolicyNever &&
            m_expr.NeedsValidation() && 
            process)
        {
            if (!process->GetDynamicCheckers())
            {                
                DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
                
                StreamString install_errors;
                
                if (!dynamic_checkers->Install(install_errors, exe_ctx))
                {
                    if (install_errors.GetString().empty())
                        err.SetErrorString ("couldn't install checkers, unknown error");
                    else
                        err.SetErrorString (install_errors.GetString().c_str());
                    
                    return err;
                }
                
                process->SetDynamicCheckers(dynamic_checkers);
                
                if (log)
                    log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
            }
            
            IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str());
        
            if (!ir_dynamic_checks.runOnModule(*module))
            {
                err.SetErrorToGenericError();
                err.SetErrorString("Couldn't add dynamic checks to the expression");
                return err;
            }
        }
    }
    
    // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called 
    // below so we don't need to free it.
    RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager();
    
    std::string error_string;

    if (log)
    {
        std::string s;
        raw_string_ostream oss(s);
        
        module->print(oss, NULL);
        
        oss.flush();
        
        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }
    
#if defined (USE_STANDARD_JIT)
    m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
                                                               &error_string, 
                                                               jit_memory_manager,
                                                               CodeGenOpt::Less,
                                                               true,
                                                               Reloc::Default,
                                                               CodeModel::Small));
#else
    EngineBuilder builder(module);
    builder.setEngineKind(EngineKind::JIT)
        .setErrorStr(&error_string)
        .setRelocationModel(llvm::Reloc::PIC_)
        .setJITMemoryManager(jit_memory_manager)
        .setOptLevel(CodeGenOpt::Less)
        .setAllocateGVsWithCode(true)
        .setCodeModel(CodeModel::Small)
        .setUseMCJIT(true);
    m_execution_engine.reset(builder.create());
#endif
        
    if (!m_execution_engine.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return err;
    }
    
    m_execution_engine->DisableLazyCompilation();
    
    llvm::Function *function = module->getFunction (function_name.c_str());
    
    // We don't actually need the function pointer here, this just forces it to get resolved.
    
    void *fun_ptr = m_execution_engine->getPointerToFunction(function);
    
    // Errors usually cause failures in the JIT, but if we're lucky we get here.
    
    if (!function)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str());
        return err;
    }
    
    if (!fun_ptr)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str());
        return err;
    }
    
    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr));
    

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
        return err;
    }
    
    // Look over the regions allocated for the function compiled.  The JIT
    // tries to allocate the functions & stubs close together, so we should try to
    // write them that way too...
    // For now I only write functions with no stubs, globals, exception tables,
    // etc.  So I only need to write the functions.
    
    size_t alloc_size = 0;
    
    std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin();
    std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end();

    for (; fun_pos != fun_end; ++fun_pos)
    {
        size_t mem_size = fun_pos->second - fun_pos->first;
        if (log)
            log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size);
        alloc_size += mem_size;
    }
    
    Error alloc_error;
    func_allocation_addr = process->AllocateMemory (alloc_size, 
                                                                lldb::ePermissionsReadable|lldb::ePermissionsExecutable, 
                                                                alloc_error);
    
    if (func_allocation_addr == LLDB_INVALID_ADDRESS)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
        return err;
    }
    
    lldb::addr_t cursor = func_allocation_addr;
        
    for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++)
    {
        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
        size_t size = lend - lstart;
        
        Error write_error;
        
        if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
        {
            err.SetErrorToGenericError();
            err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error"));
            return err;
        }
            
        jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor);
        cursor += size;
    }
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos != end; pos++)
    {
        (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr);
    
        if (!(*pos).m_name.compare(function_name.c_str()))
        {
            func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).second;
            func_addr = (*pos).m_remote_addr;
        }
    }
    
    if (log)
    {
        log->Printf("Code can be run in the target.");
        
        StreamString disassembly_stream;
        
        Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager);
        
        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }
    }
    
    err.Clear();
    return err;
}
예제 #13
0
lldb::ExpressionResults
LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                              ExecutionContext &exe_ctx,
                              const EvaluateExpressionOptions &options,
                              lldb::UserExpressionSP &shared_ptr_to_me,
                              lldb::ExpressionVariableSP &result) {
  // The expression log is quite verbose, and if you're just tracking the
  // execution of the
  // expression, it's quite convenient to have these logs come out with the STEP
  // log as well.
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
    lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;

    if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
                                       struct_address)) {
      diagnostic_manager.Printf(
          eDiagnosticSeverityError,
          "errored out in %s, couldn't PrepareToExecuteJITExpression",
          __FUNCTION__);
      return lldb::eExpressionSetupError;
    }

    lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
    lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;

    lldb::ValueObjectSP error_backstop_result_sp;

    if (m_can_interpret) {
      llvm::Module *module = m_execution_unit_sp->GetModule();
      llvm::Function *function = m_execution_unit_sp->GetFunction();

      if (!module || !function) {
        diagnostic_manager.PutCString(
            eDiagnosticSeverityError,
            "supposed to interpret, but nothing is there");
        return lldb::eExpressionSetupError;
      }

      Error interpreter_error;

      std::vector<lldb::addr_t> args;

      if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                  "errored out in %s, couldn't AddArguments",
                                  __FUNCTION__);
        return lldb::eExpressionSetupError;
      }

      function_stack_bottom = m_stack_frame_bottom;
      function_stack_top = m_stack_frame_top;

      IRInterpreter::Interpret(*module, *function, args,
                               *m_execution_unit_sp.get(), interpreter_error,
                               function_stack_bottom, function_stack_top,
                               exe_ctx);

      if (!interpreter_error.Success()) {
        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                  "supposed to interpret, but failed: %s",
                                  interpreter_error.AsCString());
        return lldb::eExpressionDiscarded;
      }
    } else {
      if (!exe_ctx.HasThreadScope()) {
        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                  "%s called with no thread selected",
                                  __FUNCTION__);
        return lldb::eExpressionSetupError;
      }

      Address wrapper_address(m_jit_start_addr);

      std::vector<lldb::addr_t> args;

      if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
        diagnostic_manager.Printf(eDiagnosticSeverityError,
                                  "errored out in %s, couldn't AddArguments",
                                  __FUNCTION__);
        return lldb::eExpressionSetupError;
      }

      lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
          exe_ctx.GetThreadRef(), wrapper_address, args, options,
          shared_ptr_to_me));

      StreamString ss;
      if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
        diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData());
        return lldb::eExpressionSetupError;
      }

      ThreadPlanCallUserExpression *user_expression_plan =
          static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());

      lldb::addr_t function_stack_pointer =
          user_expression_plan->GetFunctionStackPointer();

      function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
      function_stack_top = function_stack_pointer;

      if (log)
        log->Printf(
            "-- [UserExpression::Execute] Execution of expression begins --");

      if (exe_ctx.GetProcessPtr())
        exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);

      lldb::ExpressionResults execution_result =
          exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
                                                diagnostic_manager);

      if (exe_ctx.GetProcessPtr())
        exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);

      if (log)
        log->Printf("-- [UserExpression::Execute] Execution of expression "
                    "completed --");

      if (execution_result == lldb::eExpressionInterrupted ||
          execution_result == lldb::eExpressionHitBreakpoint) {
        const char *error_desc = NULL;

        if (call_plan_sp) {
          lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
          if (real_stop_info_sp)
            error_desc = real_stop_info_sp->GetDescription();
        }
        if (error_desc)
          diagnostic_manager.Printf(eDiagnosticSeverityError,
                                    "Execution was interrupted, reason: %s.",
                                    error_desc);
        else
          diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                        "Execution was interrupted.");

        if ((execution_result == lldb::eExpressionInterrupted &&
             options.DoesUnwindOnError()) ||
            (execution_result == lldb::eExpressionHitBreakpoint &&
             options.DoesIgnoreBreakpoints()))
          diagnostic_manager.AppendMessageToDiagnostic(
              "The process has been returned to the state before expression "
              "evaluation.");
        else {
          if (execution_result == lldb::eExpressionHitBreakpoint)
            user_expression_plan->TransferExpressionOwnership();
          diagnostic_manager.AppendMessageToDiagnostic(
              "The process has been left at the point where it was "
              "interrupted, "
              "use \"thread return -x\" to return to the state before "
              "expression evaluation.");
        }

        return execution_result;
      } else if (execution_result == lldb::eExpressionStoppedForDebug) {
        diagnostic_manager.PutCString(
            eDiagnosticSeverityRemark,
            "Execution was halted at the first instruction of the expression "
            "function because \"debug\" was requested.\n"
            "Use \"thread return -x\" to return to the state before expression "
            "evaluation.");
        return execution_result;
      } else if (execution_result == lldb::eExpressionCompleted) {
        if (user_expression_plan->HitErrorBackstop()) {
          // This should only happen in Playground & REPL.  The code threw an
          // uncaught error, so we already rolled up
          // the stack past our execution point.  We're not going to be able to
          // get any or our expression variables
          // since they've already gone out of scope.  But at least we can
          // gather the error result...
          if (user_expression_plan->GetReturnValueObject() &&
              user_expression_plan->GetReturnValueObject()
                  ->GetError()
                  .Success()) {
            error_backstop_result_sp =
                user_expression_plan->GetReturnValueObject();
          }
        }
      } else {
        diagnostic_manager.Printf(
            eDiagnosticSeverityError,
            "Couldn't execute function; result was %s",
            Process::ExecutionResultAsCString(execution_result));
        return execution_result;
      }
    }

    if (error_backstop_result_sp) {
      // This should only happen in Playground & REPL.  The code threw an
      // uncaught error, so we already rolled up
      // the stack past our execution point.  We're not going to be able to get
      // any or our expression variables
      // since they've already gone out of scope.  But at least we can gather
      // the error result...
      Target *target = exe_ctx.GetTargetPtr();
      PersistentExpressionState *expression_state =
          target->GetPersistentExpressionStateForLanguage(Language());
      if (expression_state)
        result = expression_state->CreatePersistentVariable(
            error_backstop_result_sp);

      return lldb::eExpressionCompleted;
    } else if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
                                    function_stack_bottom,
                                    function_stack_top)) {
      return lldb::eExpressionCompleted;
    } else {
      return lldb::eExpressionResultUnavailable;
    }
  } else {
    diagnostic_manager.PutCString(
        eDiagnosticSeverityError,
        "Expression can't be run, because there is no JIT compiled function");
    return lldb::eExpressionSetupError;
  }
}
예제 #14
0
bool FunctionCaller::WriteFunctionArguments(
    ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
    ValueList &arg_values, DiagnosticManager &diagnostic_manager) {
  // All the information to reconstruct the struct is provided by the
  // StructExtractor.
  if (!m_struct_valid) {
    diagnostic_manager.PutString(eDiagnosticSeverityError,
                                 "Argument information was not correctly "
                                 "parsed, so the function cannot be called.");
    return false;
  }

  Status error;
  lldb::ExpressionResults return_value = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();

  if (process == NULL)
    return return_value;

  lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());

  if (process != jit_process_sp.get())
    return false;

  if (args_addr_ref == LLDB_INVALID_ADDRESS) {
    args_addr_ref = process->AllocateMemory(
        m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
        error);
    if (args_addr_ref == LLDB_INVALID_ADDRESS)
      return false;
    m_wrapper_args_addrs.push_back(args_addr_ref);
  } else {
    // Make sure this is an address that we've already handed out.
    if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
             args_addr_ref) == m_wrapper_args_addrs.end()) {
      return false;
    }
  }

  // TODO: verify fun_addr needs to be a callable address
  Scalar fun_addr(
      m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
  uint64_t first_offset = m_member_offsets[0];
  process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr,
                               process->GetAddressByteSize(), error);

  // FIXME: We will need to extend this for Variadic functions.

  Status value_error;

  size_t num_args = arg_values.GetSize();
  if (num_args != m_arg_values.GetSize()) {
    diagnostic_manager.Printf(
        eDiagnosticSeverityError,
        "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
        (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
    return false;
  }

  for (size_t i = 0; i < num_args; i++) {
    // FIXME: We should sanity check sizes.

    uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes.
    Value *arg_value = arg_values.GetValueAtIndex(i);

    // FIXME: For now just do scalars:

    // Special case: if it's a pointer, don't do anything (the ABI supports
    // passing cstrings)

    if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
        arg_value->GetContextType() == Value::eContextTypeInvalid &&
        arg_value->GetCompilerType().IsPointerType())
      continue;

    const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);

    if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar,
                                      arg_scalar.GetByteSize(), error))
      return false;
  }

  return true;
}
bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
                                   CompletionRequest &request,
                                   unsigned complete_pos) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

  // We don't want any visible feedback when completing an expression. Mostly
  // because the results we get from an incomplete invocation are probably not
  // correct.
  DiagnosticManager diagnostic_manager;

  if (!PrepareForParsing(diagnostic_manager, exe_ctx))
    return false;

  if (log)
    log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

  //////////////////////////
  // Parse the expression
  //

  m_materializer_ap.reset(new Materializer());

  ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);

  OnExit on_exit([this]() { ResetDeclMap(); });

  if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
    diagnostic_manager.PutString(
        eDiagnosticSeverityError,
        "current process state is unsuitable for expression parsing");

    return false;
  }

  if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
    DeclMap()->SetLookupsEnabled(true);
  }

  Process *process = exe_ctx.GetProcessPtr();
  ExecutionContextScope *exe_scope = process;

  if (!exe_scope)
    exe_scope = exe_ctx.GetTargetPtr();

  ClangExpressionParser parser(exe_scope, *this, false);

  // We have to find the source code location where the user text is inside
  // the transformed expression code. When creating the transformed text, we
  // already stored the absolute position in the m_transformed_text string. The
  // only thing left to do is to transform it into the line:column format that
  // Clang expects.

  // The line and column of the user expression inside the transformed source
  // code.
  unsigned user_expr_line, user_expr_column;
  if (m_user_expression_start_pos.hasValue())
    AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
                          user_expr_line, user_expr_column);
  else
    return false;

  // The actual column where we have to complete is the start column of the
  // user expression + the offset inside the user code that we were given.
  const unsigned completion_column = user_expr_column + complete_pos;
  parser.Complete(request, user_expr_line, completion_column, complete_pos);

  return true;
}
예제 #16
0
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] diagnostic_manager
///     A diagnostic manager to report errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
                                   ExecutionContext &exe_ctx) {
  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
    diagnostic_manager.PutCString(eDiagnosticSeverityWarning,
                                  "already installed");
    return false;
  }

  ////////////////////////////////////
  // Set up the target and compiler
  //

  Target *target = exe_ctx.GetTargetPtr();

  if (!target) {
    diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
    return false;
  }

  Process *process = exe_ctx.GetProcessPtr();

  if (!process) {
    diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process");
    return false;
  }

  //////////////////////////
  // Parse the expression
  //

  bool keep_result_in_memory = false;

  ResetDeclMap(exe_ctx, keep_result_in_memory);

  if (!DeclMap()->WillParse(exe_ctx, NULL)) {
    diagnostic_manager.PutCString(
        eDiagnosticSeverityError,
        "current process state is unsuitable for expression parsing");
    return false;
  }

  const bool generate_debug_info = true;
  ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
                               generate_debug_info);

  unsigned num_errors = parser.Parse(diagnostic_manager);

  if (num_errors) {
    ResetDeclMap();

    return false;
  }

  //////////////////////////////////
  // JIT the output of the parser
  //

  bool can_interpret = false; // should stay that way

  Error jit_error = parser.PrepareForExecution(
      m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
      can_interpret, eExecutionPolicyAlways);

  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
    m_jit_process_wp = process->shared_from_this();
    if (parser.GetGenerateDebugInfo())
      m_execution_unit_sp->CreateJITModule(FunctionName());
  }

#if 0
	// jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr, 
                    m_function_name.c_str(), 
                    m_function_text.c_str());
#endif

  DeclMap()->DidParse();

  ResetDeclMap();

  if (jit_error.Success()) {
    return true;
  } else {
    const char *error_cstr = jit_error.AsCString();
    if (error_cstr && error_cstr[0]) {
      diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
    } else {
      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression can't be interpreted or run");
    }
    return false;
  }
}
예제 #17
0
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, 
                                            lldb::addr_t &func_addr, 
                                            lldb::addr_t &func_end, 
                                            ExecutionContext &exe_ctx,
                                            IRForTarget::StaticDataAllocator *data_allocator,
                                            bool &evaluated_statically,
                                            lldb::ClangExpressionVariableSP &const_result,
                                            ExecutionPolicy execution_policy)
{
    func_allocation_addr = LLDB_INVALID_ADDRESS;
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    std::auto_ptr<llvm::ExecutionEngine> execution_engine;
    
    Error err;
    
    llvm::Module *module = m_code_generator->ReleaseModule();

    if (!module)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }
    
    // Find the actual name of the function (it's often mangled somehow)
    
    std::string function_name;
    
    if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
        return err;
    }
    else
    {
        if (log)
            log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName());
    }
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
    
    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = &target->GetDebugger().GetErrorStream();
    
        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  execution_policy,
                                  const_result,
                                  data_allocator,
                                  error_stream,
                                  function_name.c_str());
        
        ir_for_target.runOnModule(*module);
        
        Error &interpreter_error(ir_for_target.getInterpreterError());
        
        if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success())
        {
            if (const_result)
                const_result->TransferAddress();
            evaluated_statically = true;
            err.Clear();
            return err;
        }
        
        Process *process = exe_ctx.GetProcessPtr();

        if (!process || execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorToGenericError();
            if (execution_policy == eExecutionPolicyAlways)
                err.SetErrorString("Execution needed to run in the target, but the target can't be run");
            else
                err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString());

            return err;
        }
        
        if (execution_policy != eExecutionPolicyNever &&
            m_expr.NeedsValidation() && 
            process)
        {
            if (!process->GetDynamicCheckers())
            {                
                DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
                
                StreamString install_errors;
                
                if (!dynamic_checkers->Install(install_errors, exe_ctx))
                {
                    if (install_errors.GetString().empty())
                        err.SetErrorString ("couldn't install checkers, unknown error");
                    else
                        err.SetErrorString (install_errors.GetString().c_str());
                    
                    return err;
                }
                
                process->SetDynamicCheckers(dynamic_checkers);
                
                if (log)
                    log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
            }
            
            IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str());
        
            if (!ir_dynamic_checks.runOnModule(*module))
            {
                err.SetErrorToGenericError();
                err.SetErrorString("Couldn't add dynamic checks to the expression");
                return err;
            }
        }
    }
    
    // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called 
    // below so we don't need to free it.
    RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager();
    
    std::string error_string;

    if (log)
    {
        std::string s;
        raw_string_ostream oss(s);
        
        module->print(oss, NULL);
        
        oss.flush();
        
        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }
    
    EngineBuilder builder(module);
    builder.setEngineKind(EngineKind::JIT)
        .setErrorStr(&error_string)
        .setRelocationModel(llvm::Reloc::PIC_)
        .setJITMemoryManager(jit_memory_manager)
        .setOptLevel(CodeGenOpt::Less)
        .setAllocateGVsWithCode(true)
        .setCodeModel(CodeModel::Small)
        .setUseMCJIT(true);
    execution_engine.reset(builder.create());
        
    if (!execution_engine.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return err;
    }
    
    execution_engine->DisableLazyCompilation();
    
    llvm::Function *function = module->getFunction (function_name.c_str());
    
    // We don't actually need the function pointer here, this just forces it to get resolved.
    
    void *fun_ptr = execution_engine->getPointerToFunction(function);
        
    // Errors usually cause failures in the JIT, but if we're lucky we get here.
    
    if (!function)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str());
        return err;
    }
    
    if (!fun_ptr)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str());
        return err;
    }
    
    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr));
    

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
        return err;
    }
        
    jit_memory_manager->CommitAllocations(*process);
    jit_memory_manager->ReportAllocations(*execution_engine);
    jit_memory_manager->WriteData(*process);
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos != end; pos++)
    {
        (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr);
    
        if (!(*pos).m_name.compare(function_name.c_str()))
        {
            RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr);
            func_end = func_range.first + func_range.second;
            func_addr = (*pos).m_remote_addr;
        }
    }
    
    if (log)
    {
        log->Printf("Code can be run in the target.");
        
        StreamString disassembly_stream;
        
        Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager);
        
        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }
    }
    
    execution_engine.reset();
    
    err.Clear();
    return err;
}
예제 #18
0
bool
ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, 
                                       lldb::addr_t &args_addr_ref, 
                                       Address function_address, 
                                       ValueList &arg_values, 
                                       Stream &errors)
{
    // All the information to reconstruct the struct is provided by the
    // StructExtractor.
    if (!m_struct_valid)
    {
        errors.Printf("Argument information was not correctly parsed, so the function cannot be called.");
        return false;
    }
        
    Error error;
    using namespace clang;
    ExecutionResults return_value = eExecutionSetupError;

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL)
        return return_value;

    if (process != m_jit_process_sp.get())
        return false;
                
    if (args_addr_ref == LLDB_INVALID_ADDRESS)
    {
        args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
        if (args_addr_ref == LLDB_INVALID_ADDRESS)
            return false;
        m_wrapper_args_addrs.push_back (args_addr_ref);
    } 
    else 
    {
        // Make sure this is an address that we've already handed out.
        if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end())
        {
            return false;
        }
    }

    // TODO: verify fun_addr needs to be a callable address
    Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
    int first_offset = m_member_offsets[0];
    process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);

    // FIXME: We will need to extend this for Variadic functions.

    Error value_error;
    
    size_t num_args = arg_values.GetSize();
    if (num_args != m_arg_values.GetSize())
    {
        errors.Printf ("Wrong number of arguments - was: %lu should be: %lu", num_args, m_arg_values.GetSize());
        return false;
    }
    
    for (size_t i = 0; i < num_args; i++)
    {
        // FIXME: We should sanity check sizes.

        int offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
        Value *arg_value = arg_values.GetValueAtIndex(i);
        
        // FIXME: For now just do scalars:
        
        // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings)
        
        if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
            arg_value->GetContextType() == Value::eContextTypeClangType &&
            ClangASTContext::IsPointerType(arg_value->GetClangType()))
            continue;
        
        const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext());

        if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error))
            return false;
    }

    return true;
}
예제 #19
0
Error
ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    
    const char *name = m_expr.FunctionName();
    
    Error ret;
    
    ret.Clear();
    
    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos < end; pos++)
    {
        if (strstr(pos->m_name.c_str(), name))
        {
            func_local_addr = pos->m_local_addr;
            func_remote_addr = pos->m_remote_addr;
        }
    }
    
    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
        return ret;
    }
    
    if (log)
        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
    
    std::pair <lldb::addr_t, lldb::addr_t> func_range;
    
    func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr);
    
    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
        return ret;
    }
    
    if (log)
        log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second);
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
    }
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
    
    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
    
    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }
    
    ArchSpec arch(target->GetArchitecture());
    
    Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL);
    
    if (disassembler == NULL)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }
    
    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }
    
    DataExtractor extractor(buffer_sp, 
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());
    
    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log.get(),
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }
    
    disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
    
    InstructionList &instruction_list = disassembler->GetInstructionList();
    const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
         instruction_index < num_instructions; 
         ++instruction_index)
    {
        Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
        instruction->Dump (&stream,
                           max_opcode_byte_size,
                           true,
                           true,
                           &exe_ctx);
        stream.PutChar('\n');
    }
    
    return ret;
}
예제 #20
0
bool
ClangUserExpression::Parse (Stream &error_stream,
                            ExecutionContext &exe_ctx,
                            lldb_private::ExecutionPolicy execution_policy,
                            bool keep_result_in_memory,
                            bool generate_debug_info)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    InstallContext(exe_ctx);

    ScanContext(exe_ctx, err);

    if (!err.Success())
    {
        error_stream.Printf("warning: %s\n", err.AsCString());
    }

    StreamString m_transformed_stream;

    ////////////////////////////////////
    // Generate the expression
    //

    ApplyObjcCastHack(m_expr_text);
    //ApplyUnicharHack(m_expr_text);

    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));

    lldb::LanguageType lang_type;

    if (m_cplusplus)
        lang_type = lldb::eLanguageTypeC_plus_plus;
    else if(m_objectivec)
        lang_type = lldb::eLanguageTypeObjC;
    else
        lang_type = lldb::eLanguageTypeC;

    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx))
    {
        error_stream.PutCString ("error: couldn't construct expression body");
        return false;
    }

    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    m_materializer_ap.reset(new Materializer());

    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));

    class OnExit
    {
    public:
        typedef std::function <void (void)> Callback;

        OnExit (Callback const &callback) :
            m_callback(callback)
        {
        }

        ~OnExit ()
        {
            m_callback();
        }
    private:
        Callback m_callback;
    };

    OnExit on_exit([this]() { m_expr_decl_map.reset(); });

    if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    Process *process = exe_ctx.GetProcessPtr();
    ExecutionContextScope *exe_scope = process;

    if (!exe_scope)
        exe_scope = exe_ctx.GetTargetPtr();

    ClangExpressionParser parser(exe_scope, *this, generate_debug_info);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    // Prepare the output of the parser for execution, evaluating it statically if possible
    //

    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
                                                  m_jit_end_addr,
                                                  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())
    {
        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
예제 #21
0
lldb::ExpressionResults
UserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error,
                               uint32_t line_offset,
                               lldb::ModuleSP *jit_module_sp_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        if (log)
            log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
        return lldb::eExpressionSetupError;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;

    const char *full_prefix = NULL;
    const char *option_prefix = options.GetPrefix();
    std::string full_prefix_storage;
    if (expr_prefix && option_prefix)
    {
        full_prefix_storage.assign(expr_prefix);
        full_prefix_storage.append(option_prefix);
        if (!full_prefix_storage.empty())
            full_prefix = full_prefix_storage.c_str();
    }
    else if (expr_prefix)
        full_prefix = expr_prefix;
    else
        full_prefix = option_prefix;
    
    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }


    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }

    lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
                                                                                    full_prefix,
                                                                                    language,
                                                                                    desired_type,
                                                                                    options,
                                                                                    error));
    if (error.Fail())
    {
        if (log)
            log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
        return lldb::eExpressionSetupError;
    }
 
    StreamString error_stream;

    if (log)
        log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    if (!user_expression_sp->Parse (error_stream,
                                    exe_ctx,
                                    execution_policy,
                                    keep_expression_in_memory,
                                    generate_debug_info,
                                    0))
    {
        execution_results = lldb::eExpressionParseError;
        if (error_stream.GetString().empty())
            error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
        else
            error.SetExpressionError (execution_results, error_stream.GetString().c_str());
    }
    else
    {
        // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
        if (jit_module_sp_ptr)
            *jit_module_sp_ptr = user_expression_sp->GetJITModule();

        lldb::ExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (error_stream.GetString().empty())
                error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            error_stream.GetString().clear();

            if (log)
                log->Printf("== [UserExpression::Evaluate] Executing expression ==");

            execution_results = user_expression_sp->Execute (error_stream,
                                                             exe_ctx,
                                                             options,
                                                             user_expression_sp,
                                                             expr_result);

            if (options.GetResultIsInternal() && expr_result && process)
            {
                process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
            }

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");

                if (error_stream.GetString().empty())
                    error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError (execution_results, error_stream.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
                                            lldb::addr_t &func_end,
                                            std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
                                            ExecutionContext &exe_ctx,
                                            bool &can_interpret,
                                            ExecutionPolicy execution_policy)
{
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());

    if (!llvm_module_ap.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }

    // Find the actual name of the function (it's often mangled somehow)

    ConstString function_name;

    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());
        return err;
    }
    else
    {
        if (log)
            log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
    }

    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)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = target->GetDebugger().GetErrorFile().get();

        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  *execution_unit_sp,
                                  error_stream,
                                  function_name.AsCString());

        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

        Error interpret_error;

        can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);

        Process *process = exe_ctx.GetProcessPtr();

        if (!ir_can_run)
        {
            err.SetErrorString("The expression could not be prepared to run in the target");
            return err;
        }

        if (!can_interpret && execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyAlways)
        {
            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
            return err;
        }

        if (execution_policy == eExecutionPolicyAlways || !can_interpret)
        {
            if (m_expr.NeedsValidation() && process)
            {
                if (!process->GetDynamicCheckers())
                {
                    DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();

                    StreamString install_errors;

                    if (!dynamic_checkers->Install(install_errors, exe_ctx))
                    {
                        if (install_errors.GetString().empty())
                            err.SetErrorString ("couldn't install checkers, unknown error");
                        else
                            err.SetErrorString (install_errors.GetString().c_str());

                        return err;
                    }

                    process->SetDynamicCheckers(dynamic_checkers);

                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
                }

                IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());

                if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
                {
                    err.SetErrorToGenericError();
                    err.SetErrorString("Couldn't add dynamic checks to the expression");
                    return err;
                }
            }

            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
        }
    }
    else
    {
        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }

    return err;
}
예제 #23
0
lldb::ExpressionResults
UserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error,
                               uint32_t line_offset,
                               std::string *fixed_expression,
                               lldb::ModuleSP *jit_module_sp_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        if (log)
            log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
        return lldb::eExpressionSetupError;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;
    
    // We need to set the expression execution thread here, turns out parse can call functions in the process of
    // looking up symbols, which will escape the context set by exe_ctx passed to Execute.
    lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
    ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp);

    const char *full_prefix = NULL;
    const char *option_prefix = options.GetPrefix();
    std::string full_prefix_storage;
    if (expr_prefix && option_prefix)
    {
        full_prefix_storage.assign(expr_prefix);
        full_prefix_storage.append(option_prefix);
        if (!full_prefix_storage.empty())
            full_prefix = full_prefix_storage.c_str();
    }
    else if (expr_prefix)
        full_prefix = expr_prefix;
    else
        full_prefix = option_prefix;

    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }

    lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
                                                                                    full_prefix,
                                                                                    language,
                                                                                    desired_type,
                                                                                    options,
                                                                                    error));
    if (error.Fail())
    {
        if (log)
            log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
        return lldb::eExpressionSetupError;
    }

    if (log)
        log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    DiagnosticManager diagnostic_manager;

    bool parse_success = user_expression_sp->Parse(diagnostic_manager,
                                                   exe_ctx,
                                                   execution_policy,
                                                   keep_expression_in_memory,
                                                   generate_debug_info);
    
    // Calculate the fixed expression always, since we need it for errors.
    std::string tmp_fixed_expression;
    if (fixed_expression == nullptr)
        fixed_expression = &tmp_fixed_expression;

    const char *fixed_text = user_expression_sp->GetFixedText();
    if (fixed_text != nullptr)
            fixed_expression->append(fixed_text);
    
    // If there is a fixed expression, try to parse it:
    if (!parse_success)
    {
        execution_results = lldb::eExpressionParseError;
        if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts())
        {
            lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(),
                                                                                             full_prefix,
                                                                                             language,
                                                                                             desired_type,
                                                                                             options,
                                                                                             error));
            DiagnosticManager fixed_diagnostic_manager;
            parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager,
                                                       exe_ctx,
                                                       execution_policy,
                                                       keep_expression_in_memory,
                                                       generate_debug_info);
            if (parse_success)
            {
                diagnostic_manager.Clear();
                user_expression_sp = fixed_expression_sp;
            }
            else
            {
                // If the fixed expression failed to parse, don't tell the user about, that won't help.
                fixed_expression->clear();
            }
        }
        
        if (!parse_success)
        {
            if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts())
            {
                error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n  %s",
                                                   fixed_expression->c_str());
            }
            else
            {
                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
        }
    }
    
    if (parse_success)
    {
        // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
        if (jit_module_sp_ptr)
            *jit_module_sp_ptr = user_expression_sp->GetJITModule();

        lldb::ExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (!diagnostic_manager.Diagnostics().size())
                error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else if (execution_policy == eExecutionPolicyTopLevel)
        {
            error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
            return lldb::eExpressionCompleted;
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            diagnostic_manager.Clear();

            if (log)
                log->Printf("== [UserExpression::Evaluate] Executing expression ==");

            execution_results =
                user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result);

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");

                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}