| //===-- FormatClasses.cpp ----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // C Includes |
| |
| // C++ Includes |
| #include <ostream> |
| |
| // Other libraries and framework includes |
| |
| // Project includes |
| #include "lldb/lldb-public.h" |
| #include "lldb/lldb-enumerations.h" |
| |
| #include "lldb/Core/Debugger.h" |
| #include "lldb/Core/FormatClasses.h" |
| #include "lldb/Core/StreamString.h" |
| #include "lldb/Core/ValueObjectConstResult.h" |
| #include "lldb/Interpreter/CommandInterpreter.h" |
| #include "lldb/Symbol/ClangASTType.h" |
| #include "lldb/Target/StackFrame.h" |
| #include "lldb/Target/Target.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| std::string |
| ValueFormat::FormatObject(lldb::ValueObjectSP object) |
| { |
| if (!object.get()) |
| return "NULL"; |
| |
| StreamString sstr; |
| |
| if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST |
| object->GetClangType(), // The clang type to display |
| &sstr, |
| m_format, // Format to display this type with |
| object->GetDataExtractor(), // Data to extract from |
| 0, // Byte offset into "data" |
| object->GetByteSize(), // Byte size of item in "data" |
| object->GetBitfieldBitSize(), // Bitfield bit size |
| object->GetBitfieldBitOffset())) // Bitfield bit offset |
| return (sstr.GetString()); |
| else |
| { |
| return ("unsufficient data for value"); |
| } |
| } |
| |
| std::string |
| StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) |
| { |
| if (!object.get()) |
| return "NULL"; |
| |
| StreamString s; |
| ExecutionContext exe_ctx; |
| object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); |
| SymbolContext sc; |
| if (exe_ctx.frame) |
| sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); |
| |
| if (m_show_members_oneliner) |
| { |
| ValueObjectSP synth_vobj = object->GetSyntheticValue(lldb::eUseSyntheticFilter); |
| const uint32_t num_children = synth_vobj->GetNumChildren(); |
| if (num_children) |
| { |
| s.PutChar('('); |
| |
| for (uint32_t idx=0; idx<num_children; ++idx) |
| { |
| lldb::ValueObjectSP child_sp(synth_vobj->GetChildAtIndex(idx, true)); |
| if (child_sp.get()) |
| { |
| if (idx) |
| s.PutCString(", "); |
| s.PutCString(child_sp.get()->GetName().AsCString()); |
| s.PutChar('='); |
| child_sp.get()->GetPrintableRepresentation(s); |
| } |
| } |
| |
| s.PutChar(')'); |
| |
| return s.GetString(); |
| } |
| else |
| return ""; |
| |
| } |
| else |
| { |
| if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) |
| return s.GetString(); |
| else |
| return ""; |
| } |
| } |
| |
| std::string |
| StringSummaryFormat::GetDescription() |
| { |
| StreamString sstr; |
| sstr.Printf ("`%s`%s%s%s%s%s%s", m_format.c_str(), |
| m_cascades ? "" : " (not cascading)", |
| m_dont_show_children ? "" : " (show children)", |
| m_dont_show_value ? " (hide value)" : "", |
| m_show_members_oneliner ? " (one-line printout)" : "", |
| m_skip_pointers ? " (skip pointers)" : "", |
| m_skip_references ? " (skip references)" : ""); |
| return sstr.GetString(); |
| } |
| |
| std::string |
| ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object) |
| { |
| lldb::ValueObjectSP target_object; |
| if (object->GetIsExpressionResult() && |
| ClangASTContext::IsPointerType(object->GetClangType()) && |
| object->GetValue().GetValueType() == Value::eValueTypeHostAddress) |
| { |
| // when using the expression parser, an additional layer of "frozen data" |
| // can be created, which is basically a byte-exact copy of the data returned |
| // by the expression, but in host memory. because Python code might need to read |
| // into the object memory in non-obvious ways, we need to hand it the target version |
| // of the expression output |
| lldb::addr_t tgt_address = object->GetValueAsUnsigned(); |
| target_object = ValueObjectConstResult::Create (object->GetExecutionContextScope(), |
| object->GetClangAST(), |
| object->GetClangType(), |
| object->GetName(), |
| tgt_address, |
| eAddressTypeLoad, |
| object->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); |
| } |
| else |
| target_object = object; |
| return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), |
| target_object).c_str()); |
| } |
| |
| std::string |
| ScriptSummaryFormat::GetDescription() |
| { |
| StreamString sstr; |
| sstr.Printf ("%s%s%s%s%s%s\n%s", m_cascades ? "" : " (not cascading)", |
| m_dont_show_children ? "" : " (show children)", |
| m_dont_show_value ? " (hide value)" : "", |
| m_show_members_oneliner ? " (one-line printout)" : "", |
| m_skip_pointers ? " (skip pointers)" : "", |
| m_skip_references ? " (skip references)" : "", |
| m_python_script.c_str()); |
| return sstr.GetString(); |
| |
| } |
| |
| std::string |
| SyntheticFilter::GetDescription() |
| { |
| StreamString sstr; |
| sstr.Printf("%s%s%s {\n", |
| m_cascades ? "" : " (not cascading)", |
| m_skip_pointers ? " (skip pointers)" : "", |
| m_skip_references ? " (skip references)" : ""); |
| |
| for (int i = 0; i < GetCount(); i++) |
| { |
| sstr.Printf(" %s\n", |
| GetExpressionPathAtIndex(i).c_str()); |
| } |
| |
| sstr.Printf("}"); |
| return sstr.GetString(); |
| } |
| |
| SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass, |
| lldb::ValueObjectSP be) : |
| SyntheticChildrenFrontEnd(be), |
| m_python_class(pclass) |
| { |
| if (be.get() == NULL) |
| { |
| m_interpreter = NULL; |
| m_wrapper = NULL; |
| return; |
| } |
| |
| if (be->GetIsExpressionResult() && |
| ClangASTContext::IsPointerType(be->GetClangType()) && |
| be->GetValue().GetValueType() == Value::eValueTypeHostAddress) |
| { |
| // when using the expression parser, an additional layer of "frozen data" |
| // can be created, which is basically a byte-exact copy of the data returned |
| // by the expression, but in host memory. because Python code might need to read |
| // into the object memory in non-obvious ways, we need to hand it the target version |
| // of the expression output |
| lldb::addr_t tgt_address = be->GetValueAsUnsigned(); |
| m_backend = ValueObjectConstResult::Create (be->GetExecutionContextScope(), |
| be->GetClangAST(), |
| be->GetClangType(), |
| be->GetName(), |
| tgt_address, |
| eAddressTypeLoad, |
| be->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); |
| } |
| |
| m_interpreter = m_backend->GetUpdatePoint().GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); |
| |
| if (m_interpreter == NULL) |
| m_wrapper = NULL; |
| else |
| m_wrapper = (PyObject*)m_interpreter->CreateSyntheticScriptedProvider(m_python_class, m_backend); |
| } |
| |
| std::string |
| SyntheticScriptProvider::GetDescription() |
| { |
| StreamString sstr; |
| sstr.Printf("%s%s%s Python class %s", |
| m_cascades ? "" : " (not cascading)", |
| m_skip_pointers ? " (skip pointers)" : "", |
| m_skip_references ? " (skip references)" : "", |
| m_python_class.c_str()); |
| |
| return sstr.GetString(); |
| } |