static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
  if (ClangModulesDeclVendor *decl_vendor =
          target->GetClangModulesDeclVendor()) {
    const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
        llvm::cast<ClangPersistentVariables>(
            target->GetPersistentExpressionStateForLanguage(
                lldb::eLanguageTypeC))
            ->GetHandLoadedClangModules();
    ClangModulesDeclVendor::ModuleVector modules_for_macros;

    for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
      modules_for_macros.push_back(module);
    }

    if (target->GetEnableAutoImportClangModules()) {
      if (StackFrame *frame = exe_ctx.GetFramePtr()) {
        if (Block *block = frame->GetFrameBlock()) {
          SymbolContext sc;

          block->CalculateSymbolContext(&sc);

          if (sc.comp_unit) {
            StreamString error_stream;

            decl_vendor->AddModulesForCompileUnit(
                *sc.comp_unit, modules_for_macros, error_stream);
          }
        }
      }
    }
  }
}
Exemple #2
0
bool
Disassembler::Disassemble
(
    Debugger &debugger,
    const ArchSpec &arch,
    const char *plugin_name,
    const char *flavor,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    AddressRange range;
    StackFrame *frame = exe_ctx.GetFramePtr();
    if (frame)
    {
        SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
        if (sc.function)
        {
            range = sc.function->GetAddressRange();
        }
        else if (sc.symbol && sc.symbol->ValueIsAddress())
        {
            range.GetBaseAddress() = sc.symbol->GetAddress();
            range.SetByteSize (sc.symbol->GetByteSize());
        }
        else
        {
            range.GetBaseAddress() = frame->GetFrameCodeAddress();
        }

        if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
            range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
    }

    return Disassemble (debugger, 
                        arch, 
                        plugin_name,
                        flavor,
                        exe_ctx, 
                        range, 
                        num_instructions, 
                        num_mixed_context_lines, 
                        options, 
                        strm);
}
Exemple #3
0
size_t
Variable::AutoComplete (const ExecutionContext &exe_ctx,
                        const char *partial_path_cstr,
                        StringList &matches,
                        bool &word_complete)
{
    word_complete = false;
    std::string partial_path;
    std::string prefix_path;
    CompilerType compiler_type;
    if (partial_path_cstr && partial_path_cstr[0])
        partial_path = partial_path_cstr;

    PrivateAutoComplete (exe_ctx.GetFramePtr(),
                         partial_path,
                         prefix_path,
                         compiler_type,
                         matches,
                         word_complete);

    return matches.GetSize();
}
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;
                }
            }
        }
    }
}
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);
    
    if (Target *target = exe_ctx.GetTargetPtr())
    {
        if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
        {
            m_result_delegate.RegisterPersistentState(persistent_state);
        }
        else
        {
            error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
            return false;
        }
    }
    else
    {
        error_stream.PutCString ("error: couldn't start parsing (no target)");
        return false;
    }

    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::string prefix = m_expr_prefix;
    
    if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
    {
        const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules();
        ClangModulesDeclVendor::ModuleVector modules_for_macros;
        
        for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
        {
            modules_for_macros.push_back(module);
        }

        if (m_target->GetEnableAutoImportClangModules())
        {
            if (StackFrame *frame = exe_ctx.GetFramePtr())
            {
                if (Block *block = frame->GetFrameBlock())
                {
                    SymbolContext sc;
                    
                    block->CalculateSymbolContext(&sc);
                    
                    if (sc.comp_unit)
                    {
                        StreamString error_stream;
                        
                        decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
                    }
                }
            }
        }
    }
    
    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
    
    lldb::LanguageType lang_type;

    if (m_in_cplusplus_method)
        lang_type = lldb::eLanguageTypeC_plus_plus;
    else if (m_in_objectivec_method)
        lang_type = lldb::eLanguageTypeObjC;
    else
        lang_type = lldb::eLanguageTypeC;

    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_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());

    ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);

    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]() { ResetDeclMap(); });

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

        ResetDeclMap(); // 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);

        ResetDeclMap(); // 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);
//        }
    }

    ResetDeclMap(); // 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;
    }
}
Exemple #6
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    StackFrame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
    {
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    }
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;

    const FormatEntity::Entry *disassembly_format = NULL;
    FormatEntity::Entry format;
    if (exe_ctx.HasTargetScope())
    {
        disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat ();
    }
    else
    {
        FormatEntity::Parse("${addr}: ", format);
        disassembly_format = &format;
    }

    // First pass: step through the list of instructions, 
    // find how long the initial addresses strings are, insert padding 
    // in the second pass so the opcodes all line up nicely.
    size_t address_text_size = 0;
    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol;
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
                if (resolved_mask)
                {
                    StreamString strmstr;
                    Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr);
                    size_t cur_line = strmstr.GetSizeOfLastLine();
                    if (cur_line > address_text_size)
                        address_text_size = cur_line;
                }
                sc.Clear(false);
            }
        }
    }

    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}
size_t
UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
{
    m_cursors.clear();
    
    Frame *first_frame = exe_ctx.GetFramePtr();

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
        return 0;
    
    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;

    struct Frame_i386
    {
        uint32_t fp;
        uint32_t pc;
    };

    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
    assert (reg_ctx);

    Cursor cursor;
    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
    cursor.fp = reg_ctx->GetFP (0);
    
    Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };

    m_cursors.push_back(cursor);

    const size_t k_frame_size = sizeof(frame);
    Error error;
    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
    {
        // Read both the FP and PC (8 bytes)
        if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
            break;
        if (frame.pc >= 0x1000)
        {
            cursor.pc = frame.pc;
            cursor.fp = frame.fp;
            m_cursors.push_back (cursor);
        }
    }
    if (!m_cursors.empty())
    {
        lldb::addr_t first_frame_pc = m_cursors.front().pc;
        if (first_frame_pc != LLDB_INVALID_ADDRESS)
        {
            const uint32_t resolve_scope = eSymbolContextModule |
                                           eSymbolContextCompUnit |
                                           eSymbolContextFunction |
                                           eSymbolContextSymbol;

            SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
            const AddressRange *addr_range_ptr = NULL;
            AddressRange range;
            if (first_frame_sc.function)
                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
            else if (first_frame_sc.symbol)
            {
                range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
                range.SetByteSize (first_frame_sc.symbol->GetByteSize());
                addr_range_ptr = &range;
            }

            if (addr_range_ptr)
            {
                if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
                {
                    // We are at the first instruction, so we can recover the
                    // previous PC by dereferencing the SP
                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
                    // Read the real second frame return address into frame.pc
                    if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
                    {
                        cursor.fp = m_cursors.front().fp;
                        cursor.pc = frame.pc;           // Set the new second frame PC

                        // Insert the second frame
                        m_cursors.insert(m_cursors.begin()+1, cursor);
                        
                        m_cursors.front().fp = first_frame_sp;
                    }
                }
            }
        }
    }
//    uint32_t i=0;
//    printf("      PC                 FP\n");
//    printf("      ------------------ ------------------ \n");
//    for (i=0; i<m_cursors.size(); ++i)
//    {
//        printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
//    }
    return m_cursors.size();
}
Exemple #8
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;
}
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;
}
Exemple #10
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
    Frame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;
    for (size_t i=0; i<num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                    else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol))
                    {
                        if (prev_sc.function || prev_sc.symbol)
                            strm.EOL();

                        bool show_fullpaths = false;
                        bool show_module = true;
                        bool show_inlined_frames = true;
                        sc.DumpStopContext (&strm, 
                                            exe_scope, 
                                            addr, 
                                            show_fullpaths,
                                            show_module,
                                            show_inlined_frames);
                        
                        strm << ":\n";
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
            {
                strm.PutCString(inst_is_at_pc ? "-> " : "   ");
            }
            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}