lldb::SBValue SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dynamic) { SBValue sb_value; Mutex::Locker api_locker; LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (var_path == NULL || var_path[0] == '\0') { if (log) log->Printf ("SBFrame::GetValueForVariablePath called with empty variable path."); return sb_value; } ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); StackFrame *frame = exe_ctx.GetFramePtr(); Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) { frame = exe_ctx.GetFramePtr(); if (frame) { VariableSP var_sp; Error error; ValueObjectSP value_sp (frame->GetValueForVariableExpressionPath (var_path, eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, var_sp, error)); sb_value.SetSP(value_sp, use_dynamic); } else { if (log) log->Printf ("SBFrame::GetValueForVariablePath () => error: could not reconstruct frame object for this SBFrame."); } } else { if (log) log->Printf ("SBFrame::GetValueForVariablePath () => error: process is running"); } } return sb_value; }
bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures it // is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); Stream &s = result.GetOutputStream(); // Be careful about the stack frame, if any summary formatter runs code, it // might clear the StackFrameList // for the thread. So hold onto a shared pointer to the frame so it stays // alive. VariableList *variable_list = frame->GetVariableList(m_option_variable.show_globals); VariableSP var_sp; ValueObjectSP valobj_sp; const char *name_cstr = nullptr; size_t idx; TypeSummaryImplSP summary_format_sp; if (!m_option_variable.summary.IsCurrentValueEmpty()) DataVisualization::NamedSummaryFormats::GetSummaryFormat( ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat( TypeSummaryImpl::Flags(), m_option_variable.summary_string.GetCurrentValue())); DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault, summary_format_sp)); const SymbolContext &sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) m_option_variable.show_globals = true; if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); if (!command.empty()) { VariableList regex_var_list; // If we have any args to the variable command, we will make // variable objects from them... for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr; ++idx) { if (m_option_variable.use_regex) { const size_t regex_start_index = regex_var_list.GetSize(); llvm::StringRef name_str(name_cstr); RegularExpression regex(name_str); if (regex.Compile(name_str)) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches); if (num_new_regex_vars > 0) { for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); regex_idx < end_index; ++regex_idx) { var_sp = regex_var_list.GetVariableAtIndex(regex_idx); if (var_sp) { valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format // != // eFormatDefault) // valobj_sp->SetFormat // (format); std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { bool show_fullpaths = false; bool show_module = true; if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString(": "); } valobj_sp->Dump(result.GetOutputStream(), options); } } } } else if (num_matches == 0) { result.GetErrorStream().Printf("error: no variables matched " "the regular expression '%s'.\n", name_cstr); } } else { char regex_error[1024]; if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) result.GetErrorStream().Printf("error: %s\n", regex_error); else result.GetErrorStream().Printf( "error: unknown regex error when compiling '%s'\n", name_cstr); } } else // No regex, either exact variable names or variable // expressions. { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath( name_cstr, m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : nullptr); valobj_sp->Dump(output_stream, options); } else { const char *error_cstr = error.AsCString(nullptr); if (error_cstr) result.GetErrorStream().Printf("error: %s\n", error_cstr); else result.GetErrorStream().Printf("error: unable to find any " "variable expression path that " "matches '%s'.\n", name_cstr); } } } } else // No command arg specified. Use variable_list, instead. { const size_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (size_t i = 0; i < num_variables; i++) { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; std::string scope_string; if (dump_variable && m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (dump_variable) { // Use the variable object code to make sure we are // using the same APIs as the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat // (format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope()) { if (!valobj_sp->GetTargetSP() ->GetDisplayRuntimeSupportValues() && valobj_sp->IsRuntimeSupportValue()) continue; if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); options.SetRootValueObjectName(name_cstr); valobj_sp->Dump(result.GetOutputStream(), options); } } } } } } result.SetStatus(eReturnStatusSuccessFinishResult); } if (m_interpreter.TruncationWarningNecessary()) { result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), m_cmd_name.c_str()); m_interpreter.TruncationWarningGiven(); } return result.Succeeded(); }
virtual bool DoExecute (Args& command, CommandReturnObject &result) { ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { result.AppendError ("you must be stopped in a valid stack frame to view frame variables."); result.SetStatus (eReturnStatusFailed); return false; } Stream &s = result.GetOutputStream(); bool get_file_globals = true; // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList // for the thread. So hold onto a shared pointer to the frame so it stays alive. VariableList *variable_list = frame->GetVariableList (get_file_globals); VariableSP var_sp; ValueObjectSP valobj_sp; const char *name_cstr = NULL; size_t idx; TypeSummaryImplSP summary_format_sp; if (!m_option_variable.summary.IsCurrentValueEmpty()) DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); ValueObject::DumpValueObjectOptions options; options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) .SetMaximumDepth(m_varobj_options.max_depth) .SetShowTypes(m_varobj_options.show_types) .SetShowLocation(m_varobj_options.show_location) .SetUseObjectiveC(m_varobj_options.use_objc) .SetUseDynamicType(m_varobj_options.use_dynamic) .SetUseSyntheticValue(m_varobj_options.use_synth) .SetFlatOutput(m_varobj_options.flat_output) .SetOmitSummaryDepth(m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.ignore_cap) .SetSummary(summary_format_sp); if (m_varobj_options.be_raw) options.SetRawDisplay(true); if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); if (command.GetArgumentCount() > 0) { VariableList regex_var_list; // If we have any args to the variable command, we will make // variable objects from them... for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx) { if (m_option_variable.use_regex) { const uint32_t regex_start_index = regex_var_list.GetSize(); RegularExpression regex (name_cstr); if (regex.Compile(name_cstr)) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches); if (num_new_regex_vars > 0) { for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); regex_idx < end_index; ++regex_idx) { var_sp = regex_var_list.GetVariableAtIndex (regex_idx); if (var_sp) { valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { bool show_fullpaths = false; bool show_module = true; if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), options); } } } } else if (num_matches == 0) { result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr); } } else { char regex_error[1024]; if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) result.GetErrorStream().Printf ("error: %s\n", regex_error); else result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr); } } else // No regex, either exact variable names or variable expressions. { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } options.SetFormat(format); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); ValueObject::DumpValueObject (output_stream, valobj_sp.get(), options); } else { const char *error_cstr = error.AsCString(NULL); if (error_cstr) result.GetErrorStream().Printf("error: %s\n", error_cstr); else result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr); } } } } else // No command arg specified. Use variable_list, instead. { const uint32_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (uint32_t i=0; i<num_variables; i++) { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; switch (var_sp->GetScope()) { case eValueTypeVariableGlobal: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) s.PutCString("GLOBAL: "); break; case eValueTypeVariableStatic: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) s.PutCString("STATIC: "); break; case eValueTypeVariableArgument: dump_variable = m_option_variable.show_args; if (dump_variable && m_option_variable.show_scope) s.PutCString(" ARG: "); break; case eValueTypeVariableLocal: dump_variable = m_option_variable.show_locals; if (dump_variable && m_option_variable.show_scope) s.PutCString(" LOCAL: "); break; default: break; } if (dump_variable) { // Use the variable object code to make sure we are // using the same APIs as the the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope ()) { if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } options.SetFormat(format); options.SetRootValueObjectName(name_cstr); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), options); } } } } } } result.SetStatus (eReturnStatusSuccessFinishResult); } if (m_interpreter.TruncationWarningNecessary()) { result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), m_cmd_name.c_str()); m_interpreter.TruncationWarningGiven(); } return result.Succeeded(); }