diff options
Diffstat (limited to 'lldb/source/Core')
-rw-r--r-- | lldb/source/Core/DataExtractor.cpp | 155 | ||||
-rw-r--r-- | lldb/source/Core/DataVisualization.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Core/FormatClasses.cpp | 80 | ||||
-rw-r--r-- | lldb/source/Core/FormatManager.cpp | 39 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 380 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectChild.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectConstResult.cpp | 90 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectConstResultChild.cpp | 82 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectConstResultImpl.cpp | 221 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectVariable.cpp | 25 |
10 files changed, 804 insertions, 313 deletions
diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp index d869aaef669..2cfced03800 100644 --- a/lldb/source/Core/DataExtractor.cpp +++ b/lldb/source/Core/DataExtractor.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/MathExtras.h" +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/Log.h" @@ -178,15 +179,6 @@ DataExtractor::Clear () } //------------------------------------------------------------------ -// Returns the total number of bytes that this object refers to -//------------------------------------------------------------------ -size_t -DataExtractor::GetByteSize () const -{ - return m_end - m_start; -} - -//------------------------------------------------------------------ // If this object contains shared data, this function returns the // offset into that shared data. Else zero is returned. //------------------------------------------------------------------ @@ -210,16 +202,6 @@ DataExtractor::GetSharedDataOffset () const } //------------------------------------------------------------------ -// Returns true if OFFSET is a valid offset into the data in this -// object. -//------------------------------------------------------------------ -bool -DataExtractor::ValidOffset (uint32_t offset) const -{ - return offset < GetByteSize(); -} - -//------------------------------------------------------------------ // Returns true if there are LENGTH bytes availabe starting OFFSET // into the data that is in this object. //------------------------------------------------------------------ @@ -245,65 +227,6 @@ DataExtractor::ValidOffsetForDataOfSize (uint32_t offset, uint32_t length) const return ((offset + length) <= size); } -//------------------------------------------------------------------ -// Returns a pointer to the first byte contained in this object's -// data, or NULL of there is no data in this object. -//------------------------------------------------------------------ -const uint8_t * -DataExtractor::GetDataStart () const -{ - return m_start; -} -//------------------------------------------------------------------ -// Returns a pointer to the byte past the last byte contained in -// this object's data, or NULL of there is no data in this object. -//------------------------------------------------------------------ -const uint8_t * -DataExtractor::GetDataEnd () const -{ - return m_end; -} - -//------------------------------------------------------------------ -// Returns true if this object will endian swap values as it -// extracts data. -//------------------------------------------------------------------ -ByteOrder -DataExtractor::GetByteOrder () const -{ - return m_byte_order; -} -//------------------------------------------------------------------ -// Set whether this object will endian swap values as it extracts -// data. -//------------------------------------------------------------------ -void -DataExtractor::SetByteOrder (ByteOrder endian) -{ - m_byte_order = endian; -} - - -//------------------------------------------------------------------ -// Return the size in bytes of any address values this object will -// extract -//------------------------------------------------------------------ -uint8_t -DataExtractor::GetAddressByteSize () const -{ - return m_addr_size; -} - -//------------------------------------------------------------------ -// Set the size in bytes that will be used when extracting any -// address values from data contained in this object. -//------------------------------------------------------------------ -void -DataExtractor::SetAddressByteSize (uint8_t addr_size) -{ - m_addr_size = addr_size; -} - //---------------------------------------------------------------------- // Set the data with which this object will extract from to data // starting at BYTES and set the length of the data to LENGTH bytes @@ -1901,3 +1824,79 @@ DataExtractor::DumpHexBytes (Stream *s, base_addr, // Base address 0, 0); // Bitfield info } + +size_t +DataExtractor::Copy (DataExtractor &dest_data) const +{ + if (m_data_sp.get()) + { + // we can pass along the SP to the data + dest_data.SetData(m_data_sp); + } + else + { + const uint8_t *base_ptr = m_start; + size_t data_size = GetByteSize(); + dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); + } + return GetByteSize(); +} + +bool +DataExtractor::Append(DataExtractor& rhs) +{ + if (rhs.GetByteOrder() != GetByteOrder()) + return false; + + if (rhs.GetByteSize() == 0) + return true; + + if (GetByteSize() == 0) + return (rhs.Copy(*this) > 0); + + size_t bytes = GetByteSize() + rhs.GetByteSize(); + + DataBufferHeap *buffer_heap_ptr = NULL; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (buffer_sp.get() == NULL || buffer_heap_ptr == NULL) + return false; + + uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); + + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); + + SetData(buffer_sp); + + return true; +} + +bool +DataExtractor::Append(void* buf, uint32_t length) +{ + if (buf == NULL) + return false; + + if (length == 0) + return true; + + size_t bytes = GetByteSize() + length; + + DataBufferHeap *buffer_heap_ptr = NULL; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (buffer_sp.get() == NULL || buffer_heap_ptr == NULL) + return false; + + uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); + + if (GetByteSize() > 0) + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + + memcpy(bytes_ptr + GetByteSize(), buf, length); + + SetData(buffer_sp); + + return true; +}
\ No newline at end of file diff --git a/lldb/source/Core/DataVisualization.cpp b/lldb/source/Core/DataVisualization.cpp index 6974132617a..7c326ed6ec0 100644 --- a/lldb/source/Core/DataVisualization.cpp +++ b/lldb/source/Core/DataVisualization.cpp @@ -106,14 +106,14 @@ DataVisualization::AnyMatches (ConstString type_name, bool DataVisualization::Categories::Get (const ConstString &category, lldb::FormatCategorySP &entry) { - entry = GetFormatManager().Category(category); + entry = GetFormatManager().GetCategory(category); return true; } void DataVisualization::Categories::Add (const ConstString &category) { - GetFormatManager().Category(category); + GetFormatManager().GetCategory(category); } bool @@ -132,13 +132,13 @@ DataVisualization::Categories::Clear () void DataVisualization::Categories::Clear (ConstString &category) { - GetFormatManager().Category(category)->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); + GetFormatManager().GetCategory(category)->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); } void DataVisualization::Categories::Enable (ConstString& category) { - if (GetFormatManager().Category(category)->IsEnabled() == false) + if (GetFormatManager().GetCategory(category)->IsEnabled() == false) GetFormatManager().EnableCategory(category); else { @@ -150,7 +150,7 @@ DataVisualization::Categories::Enable (ConstString& category) void DataVisualization::Categories::Disable (ConstString& category) { - if (GetFormatManager().Category(category)->IsEnabled() == true) + if (GetFormatManager().GetCategory(category)->IsEnabled() == true) GetFormatManager().DisableCategory(category); } diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp index a23225d3825..ee689307ac1 100644 --- a/lldb/source/Core/FormatClasses.cpp +++ b/lldb/source/Core/FormatClasses.cpp @@ -41,30 +41,6 @@ ValueFormat::ValueFormat (lldb::Format f, { } -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"); - } -} - SummaryFormat::SummaryFormat(bool casc, bool skipptr, bool skipref, @@ -186,29 +162,8 @@ ScriptSummaryFormat::ScriptSummaryFormat(bool casc, 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(LLDB_INVALID_ADDRESS); - 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()); + object).c_str()); } std::string @@ -282,25 +237,6 @@ SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass, 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(LLDB_INVALID_ADDRESS); - 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) @@ -315,19 +251,7 @@ SyntheticScriptProvider::FrontEnd::GetChildAtIndex (uint32_t idx, bool can_creat if (m_wrapper == NULL || m_interpreter == NULL) return lldb::ValueObjectSP(); - PyObject* py_return = (PyObject*)m_interpreter->GetChildAtIndex(m_wrapper, idx); - if (py_return == NULL || py_return == Py_None) - { - Py_XDECREF(py_return); - return lldb::ValueObjectSP(); - } - - lldb::SBValue *sb_ptr = m_interpreter->CastPyObjectToSBValue(py_return); - - if (py_return == NULL || sb_ptr == NULL) - return lldb::ValueObjectSP(); - - return sb_ptr->m_opaque_sp; + return m_interpreter->GetChildAtIndex(m_wrapper, idx); } std::string diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 40d3a81da39..f9bb3e1a6e9 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -482,11 +482,11 @@ CategoryMap::LoopThrough(CallbackType callback, void* param) } lldb::FormatCategorySP -FormatManager::Category (const ConstString& category_name, +FormatManager::GetCategory (const ConstString& category_name, bool can_create) { if (!category_name) - return Category(m_default_category_name); + return GetCategory(m_default_category_name); lldb::FormatCategorySP category; if (m_categories_map.Get(category_name, category)) return category; @@ -495,7 +495,7 @@ FormatManager::Category (const ConstString& category_name, return lldb::FormatCategorySP(); m_categories_map.Add(category_name,lldb::FormatCategorySP(new FormatCategory(this, category_name.AsCString()))); - return Category(category_name); + return GetCategory(category_name); } lldb::Format @@ -566,11 +566,13 @@ FormatManager::FormatManager() : lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); - Category(m_system_category_name)->GetSummaryNavigator()->Add(ConstString("char *"), string_format); - Category(m_system_category_name)->GetSummaryNavigator()->Add(ConstString("const char *"), string_format); - Category(m_system_category_name)->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format); + FormatCategory::SharedPointer sys_category_sp = GetCategory(m_system_category_name); - Category(m_default_category_name); // this call is there to force LLDB into creating an empty "default" category + sys_category_sp->GetSummaryNavigator()->Add(ConstString("char *"), string_format); + sys_category_sp->GetSummaryNavigator()->Add(ConstString("const char *"), string_format); + sys_category_sp->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format); + + GetCategory(m_default_category_name); // this call is there to force LLDB into creating an empty "default" category // WARNING: temporary code!! // The platform should be responsible for initializing its own formatters @@ -586,24 +588,27 @@ FormatManager::FormatManager() : true, false, "${var._M_dataplus._M_p}")); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::string"), - std_string_summary_sp); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::basic_string<char>"), - std_string_summary_sp); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), - std_string_summary_sp); - - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::vector<")), + + FormatCategory::SharedPointer gnu_category_sp = GetCategory(m_gnu_cpp_category_name); + + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::string"), + std_string_summary_sp); + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char>"), + std_string_summary_sp); + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), + std_string_summary_sp); + + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?vector<.+>$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, "gnu_libstdcpp.StdVectorSynthProvider"))); - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::map<")), + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?map<.+> >$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, "gnu_libstdcpp.StdMapSynthProvider"))); - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::list<")), + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?list<.+>$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 2ab5ac4cbcf..78e18ac9f3d 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -89,14 +89,13 @@ ValueObject::ValueObject (ValueObject &parent) : m_value_did_change (false), m_children_count_valid (false), m_old_value_valid (false), - m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_expression_result(parent.m_is_expression_result), - m_dump_printable_counter(0) + m_dump_printable_counter(0), + m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid) { m_manager->ManageObject(this); } @@ -104,7 +103,8 @@ ValueObject::ValueObject (ValueObject &parent) : //---------------------------------------------------------------------- // ValueObject constructor //---------------------------------------------------------------------- -ValueObject::ValueObject (ExecutionContextScope *exe_scope) : +ValueObject::ValueObject (ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type) : UserID (++g_value_obj_uid), // Unique identifier for every value object m_parent (NULL), m_update_point (exe_scope), @@ -135,14 +135,13 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_value_did_change (false), m_children_count_valid (false), m_old_value_valid (false), - m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_expression_result(false), - m_dump_printable_counter(0) + m_dump_printable_counter(0), + m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type) { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -165,13 +164,24 @@ bool ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_format) { + bool did_change_formats = false; + if (update_format) - UpdateFormatsIfNeeded(use_dynamic); + did_change_formats = UpdateFormatsIfNeeded(use_dynamic); // If this is a constant value, then our success is predicated on whether // we have an error or not if (GetIsConstant()) + { + // if you were asked to update your formatters, but did not get a chance to do it + // clear your own values (this serves the purpose of faking a stop-id for frozen + // objects (which are regarded as constant, but could have changes behind their backs + // because of the frozen-pointer depth limit) + // TODO: decouple summary from value and then remove this code and only force-clear the summary + if (update_format && !did_change_formats) + m_summary_str.clear(); return m_error.Success(); + } bool first_update = m_update_point.IsFirstEvaluation(); @@ -216,7 +226,7 @@ ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_form return m_error.Success(); } -void +bool ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); @@ -225,10 +235,14 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) GetName().GetCString(), m_last_format_mgr_revision, DataVisualization::GetCurrentRevision()); + + bool any_change = false; + if (HasCustomSummaryFormat() && m_update_point.GetModID() != m_user_id_of_forced_summary) { ClearCustomSummaryFormat(); m_summary_str.clear(); + any_change = true; } if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision()) || m_last_format_mgr_dynamic != use_dynamic) @@ -242,6 +256,7 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) m_synthetic_value = NULL; + any_change = true; DataVisualization::ValueFormats::Get(*this, eNoDynamicValues, m_last_value_format); DataVisualization::GetSummaryFormat(*this, use_dynamic, m_last_summary_format); DataVisualization::GetSyntheticChildren(*this, use_dynamic, m_last_synthetic_filter); @@ -251,6 +266,9 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) ClearUserVisibleData(); } + + return any_change; + } void @@ -538,10 +556,11 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent); - if (m_pointers_point_to_load_addrs) - valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); - } + child_is_deref_of_parent, + eAddressTypeInvalid); + //if (valobj) + // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid); + } return valobj; } @@ -578,8 +597,7 @@ ValueObject::GetSummaryAsCString () if (ClangASTContext::IsFunctionPointerType (clang_type)) { AddressType func_ptr_address_type = eAddressTypeInvalid; - addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - + addr_t func_ptr_address = GetPointerValue (&func_ptr_address_type); if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) { switch (func_ptr_address_type) @@ -643,10 +661,157 @@ ValueObject::IsCStringContainer(bool check_pointer) return true; addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; - cstr_address = GetAddressOf (cstr_address_type, true); + cstr_address = GetAddressOf (true, &cstr_address_type); return (cstr_address != LLDB_INVALID_ADDRESS); } +size_t +ValueObject::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + if (!IsPointerType() && !IsArrayType()) + return 0; + + if (item_count == 0) + return 0; + + uint32_t stride = 0; + + ClangASTType type(GetClangAST(), + GetClangType()); + + const uint64_t item_type_size = (IsPointerType() ? ClangASTType::GetTypeByteSize(GetClangAST(), type.GetPointeeType()) : + ClangASTType::GetTypeByteSize(GetClangAST(), type.GetArrayElementType(stride))); + + const uint64_t bytes = item_count * item_type_size; + + const uint64_t offset = item_idx * item_type_size; + + if (item_idx == 0 && item_count == 1) // simply a deref + { + if (IsPointerType()) + { + Error error; + ValueObjectSP pointee_sp = Dereference(error); + if (error.Fail() || pointee_sp.get() == NULL) + return 0; + return pointee_sp->GetDataExtractor().Copy(data); + } + else + { + ValueObjectSP child_sp = GetChildAtIndex(0, true); + if (child_sp.get() == NULL) + return 0; + return child_sp->GetDataExtractor().Copy(data); + } + return true; + } + else /* (items > 1) */ + { + Error error; + lldb_private::DataBufferHeap* heap_buf_ptr = NULL; + lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap()); + + AddressType addr_type; + lldb::addr_t addr = IsPointerType() ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type); + + ExecutionContextScope *exe_scope = m_update_point.GetExecutionContextScope(); + + + switch (addr_type) + { + case eAddressTypeFile: + { + Module* module = GetModule(); + if (module) + { + Address so_addr; + module->ResolveFileAddress(addr, so_addr); + if (exe_scope) + { + Target* target = exe_scope->CalculateTarget(); + if (target) + { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = target->ReadMemory(so_addr, false, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success()) + { + data.SetData(data_sp); + return bytes_read; + } + } + } + } + } + break; + case eAddressTypeLoad: + if (exe_scope) + { + Process *process = exe_scope->CalculateProcess(); + if (process) + { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success()) + { + data.SetData(data_sp); + return bytes_read; + } + } + } + break; + case eAddressTypeHost: + { + heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes); + data.SetData(data_sp); + return bytes; + } + break; + case eAddressTypeInvalid: + default: + break; + } + } + return 0; +} + +size_t +ValueObject::GetData (DataExtractor& data) +{ + UpdateValueIfNeeded(false); + ExecutionContext exe_ctx; + GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + Error error = m_value.GetValueAsData(&exe_ctx, GetClangAST(), data, 0, GetModule()); + if (error.Fail()) + return 0; + data.SetAddressByteSize(m_data.GetAddressByteSize()); + data.SetByteOrder(m_data.GetByteOrder()); + return data.GetByteSize(); +} + +// will compute strlen(str), but without consuming more than +// maxlen bytes out of str (this serves the purpose of reading +// chunks of a string without having to worry about +// missing NULL terminators in the chunk) +// of course, if strlen(str) > maxlen, the function will return +// maxlen_value (which should be != maxlen, because that allows you +// to know whether strlen(str) == maxlen or strlen(str) > maxlen) +static uint32_t +strlen_or_inf (const char* str, + uint32_t maxlen, + uint32_t maxlen_value) +{ + uint32_t len = 0; + while(*str) + { + len++;str++; + if (len > maxlen) + return maxlen_value; + } + return len; +} + void ValueObject::ReadPointedString(Stream& s, Error& error, @@ -656,7 +821,7 @@ ValueObject::ReadPointedString(Stream& s, { if (max_length == 0) - max_length = 128; // FIXME this should be a setting, or a formatting parameter + max_length = GetUpdatePoint().GetTargetSP()->GetMaximumSizeOfStringSummary(); clang_type_t clang_type = GetClangType(); clang_type_t elem_or_pointee_clang_type; @@ -690,14 +855,14 @@ ValueObject::ReadPointedString(Stream& s, capped_data = true; cstr_len = max_length; } - cstr_address = GetAddressOf (cstr_address_type, true); + cstr_address = GetAddressOf (true, &cstr_address_type); } else { // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); + cstr_address = GetPointerValue (&cstr_address_type); } - if (cstr_address == LLDB_INVALID_ADDRESS) + if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) { s << "<invalid address for data>"; } @@ -706,18 +871,13 @@ ValueObject::ReadPointedString(Stream& s, Address cstr_so_addr (NULL, cstr_address); DataExtractor data; size_t bytes_read = 0; - std::vector<char> data_buffer; - bool prefer_file_cache = false; if (cstr_len > 0 && honor_array) { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) + // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this + GetPointeeData(data, 0, cstr_len); + + if ( (bytes_read = data.GetByteSize()) > 0) { s << '"'; data.Dump (&s, @@ -740,29 +900,31 @@ ValueObject::ReadPointedString(Stream& s, { cstr_len = max_length; const size_t k_max_buf_size = 64; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - s << '"'; + + size_t offset = 0; bool any_data = false; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) + bool finished = false; + // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this + while ( (bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0 ) { - any_data = true; - size_t len = strlen(&data_buffer.front()); + size_t len = strlen_or_inf(data.PeekCStr(0), k_max_buf_size, k_max_buf_size+1); + if (len > k_max_buf_size) + len = k_max_buf_size; + if (!any_data) + { + s << '"'; + any_data = true; + } if (len == 0) break; if (len > bytes_read) len = bytes_read; if (len > cstr_len) len = cstr_len; + else + finished = true; data.Dump (&s, 0, // Start offset in "data" @@ -776,19 +938,22 @@ ValueObject::ReadPointedString(Stream& s, if (len < k_max_buf_size) break; + if (len >= cstr_len) - { - s << "..."; break; - } + cstr_len -= len; - cstr_so_addr.Slide (k_max_buf_size); + offset += len; } if (any_data == false) s << "<data not available>"; - - s << '"'; + else + { + s << '"'; + if (finished == false) + s << "..."; + } } } } @@ -868,39 +1033,40 @@ ValueObject::GetValueAsCString () case Value::eContextTypeLLDBType: case Value::eContextTypeVariable: { + lldb::Format my_format = GetFormat(); clang_type_t clang_type = GetClangType (); if (clang_type) { - if (m_format == lldb::eFormatDefault && m_last_value_format) - { - m_value_str = m_last_value_format->FormatObject(GetSP()); - } - else + if (m_format == lldb::eFormatDefault) { - StreamString sstr; - Format format = GetFormat(); - if (format == eFormatDefault) - format = (m_is_bitfield_for_scalar ? eFormatUnsigned : - ClangASTType::GetFormat(clang_type)); - - if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST - clang_type, // The clang type to display - &sstr, - format, // Format to display this type with - m_data, // Data to extract from - 0, // Byte offset into "m_data" - GetByteSize(), // Byte size of item in "m_data" - GetBitfieldBitSize(), // Bitfield bit size - GetBitfieldBitOffset())) // Bitfield bit offset - m_value_str.swap(sstr.GetString()); + if (m_last_value_format) + my_format = m_last_value_format->GetFormat(); else { - m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", - m_data.GetByteSize(), - GetByteSize()); - m_value_str.clear(); + if (m_is_bitfield_for_scalar) + my_format = eFormatUnsigned; + else + my_format = ClangASTType::GetFormat(clang_type); } } + StreamString sstr; + if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST + clang_type, // The clang type to display + &sstr, + my_format, // Format to display this type with + m_data, // Data to extract from + 0, // Byte offset into "m_data" + GetByteSize(), // Byte size of item in "m_data" + GetBitfieldBitSize(), // Bitfield bit size + GetBitfieldBitOffset())) // Bitfield bit offset + m_value_str.swap(sstr.GetString()); + else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); + m_value_str.clear(); + } } } break; @@ -1218,7 +1384,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, } addr_t -ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address) +ValueObject::GetAddressOf (bool scalar_is_load_address, AddressType *address_type) { if (!UpdateValueIfNeeded(false)) return LLDB_INVALID_ADDRESS; @@ -1228,7 +1394,8 @@ ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_addres case Value::eValueTypeScalar: if (scalar_is_load_address) { - address_type = eAddressTypeLoad; + if(address_type) + *address_type = eAddressTypeLoad; return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); } break; @@ -1237,20 +1404,23 @@ ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_addres case Value::eValueTypeFileAddress: case Value::eValueTypeHostAddress: { - address_type = m_value.GetValueAddressType (); + if(address_type) + *address_type = m_value.GetValueAddressType (); return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); } break; } - address_type = eAddressTypeInvalid; + if (address_type) + *address_type = eAddressTypeInvalid; return LLDB_INVALID_ADDRESS; } addr_t -ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_address) +ValueObject::GetPointerValue (AddressType *address_type) { addr_t address = LLDB_INVALID_ADDRESS; - address_type = eAddressTypeInvalid; + if(address_type) + *address_type = eAddressTypeInvalid; if (!UpdateValueIfNeeded(false)) return address; @@ -1258,28 +1428,21 @@ ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_add switch (m_value.GetValueType()) { case Value::eValueTypeScalar: - if (scalar_is_load_address) - { - address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - address_type = eAddressTypeLoad; - } + address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); break; + case Value::eValueTypeHostAddress: case Value::eValueTypeLoadAddress: case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: { uint32_t data_offset = 0; address = m_data.GetPointer(&data_offset); - address_type = m_value.GetValueAddressType(); - if (address_type == eAddressTypeInvalid) - address_type = eAddressTypeLoad; } break; } - if (m_pointers_point_to_load_addrs) - address_type = eAddressTypeLoad; + if (address_type) + *address_type = GetAddressTypeOfChildren(); return address; } @@ -1553,7 +1716,8 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre to-from+1, from, false, - false); + false, + eAddressTypeInvalid); // Cache the value if we got one back... if (synthetic_child) @@ -1633,7 +1797,8 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type 0, 0, false, - false); + false, + eAddressTypeInvalid); if (synthetic_child) { AddSyntheticChild(name_const_str, synthetic_child); @@ -2950,7 +3115,7 @@ ValueObject::DumpValueObject // We have a pointer or reference whose value is an address. // Make sure that address is not NULL AddressType ptr_address_type; - if (valobj->GetPointerValue (ptr_address_type, true) == 0) + if (valobj->GetPointerValue (&ptr_address_type) == 0) print_children = false; else if (is_ref && curr_depth == 0) @@ -3084,7 +3249,8 @@ ValueObject::CreateConstantValue (const ConstString &name) ast, GetClangType(), name, - data); + data, + GetAddressOf()); } } @@ -3152,7 +3318,8 @@ ValueObject::Dereference (Error &error) child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent); + child_is_deref_of_parent, + eAddressTypeInvalid); } } @@ -3182,7 +3349,7 @@ ValueObject::AddressOf (Error &error) AddressType address_type = eAddressTypeInvalid; const bool scalar_is_load_address = false; - addr_t addr = GetAddressOf (address_type, scalar_is_load_address); + addr_t addr = GetAddressOf (scalar_is_load_address, &address_type); error.Clear(); if (addr != LLDB_INVALID_ADDRESS) { @@ -3228,8 +3395,7 @@ ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type) { ValueObjectSP valobj_sp; AddressType address_type; - const bool scalar_is_load_address = true; - addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address); + addr_t ptr_value = GetPointerValue (&address_type); if (ptr_value != LLDB_INVALID_ADDRESS) { @@ -3248,8 +3414,7 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp) { ValueObjectSP valobj_sp; AddressType address_type; - const bool scalar_is_load_address = true; - addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address); + addr_t ptr_value = GetPointerValue (&address_type); if (ptr_value != LLDB_INVALID_ADDRESS) { @@ -3540,3 +3705,14 @@ ValueObject::ClearUserVisibleData() m_summary_str.clear(); m_object_desc_str.clear(); } + +SymbolContextScope * +ValueObject::GetSymbolContextScope() +{ + if (m_parent) + { + if (!m_parent->IsPointerOrReferenceType()) + return m_parent->GetSymbolContextScope(); + } + return NULL; +} diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index 4075f60ebb3..b07b38c7544 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -35,7 +35,8 @@ ValueObjectChild::ValueObjectChild uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool is_base_class, - bool is_deref_of_parent + bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type ) : ValueObject (parent), m_clang_ast (clang_ast), @@ -48,6 +49,7 @@ ValueObjectChild::ValueObjectChild m_is_deref_of_parent (is_deref_of_parent) { m_name = name; + SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); } ValueObjectChild::~ValueObjectChild() @@ -108,10 +110,7 @@ ValueObjectChild::UpdateValue () if (ClangASTContext::IsPointerOrReferenceType (parent->GetClangType())) { - const bool scalar_is_load_address = true; - AddressType address_type; - - lldb::addr_t addr = parent->GetPointerValue (address_type, scalar_is_load_address); + lldb::addr_t addr = parent->GetPointerValue (); m_value.GetScalar() = addr; if (addr == LLDB_INVALID_ADDRESS) @@ -125,10 +124,28 @@ ValueObjectChild::UpdateValue () else { m_value.GetScalar() += m_byte_offset; - if (m_pointers_point_to_load_addrs || - value_type == Value::eValueTypeScalar || - value_type == Value::eValueTypeFileAddress) - m_value.SetValueType (Value::eValueTypeLoadAddress); + AddressType addr_type = parent->GetAddressTypeOfChildren(); + + switch (addr_type) + { + case eAddressTypeFile: + if (m_update_point.GetProcessSP().get() != NULL && m_update_point.GetProcessSP()->IsAlive() == true) + m_value.SetValueType (Value::eValueTypeLoadAddress); + else + m_value.SetValueType(Value::eValueTypeFileAddress); + break; + case eAddressTypeLoad: + m_value.SetValueType (Value::eValueTypeLoadAddress); + break; + case eAddressTypeHost: + m_value.SetValueType(Value::eValueTypeHostAddress); + break; + case eAddressTypeInvalid: + default: + // TODO: does this make sense? + m_value.SetValueType(Value::eValueTypeScalar); + break; + } } } else diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp index 7ceddc99607..9a23ca82a1b 100644 --- a/lldb/source/Core/ValueObjectConstResult.cpp +++ b/lldb/source/Core/ValueObjectConstResult.cpp @@ -9,6 +9,8 @@ #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultChild.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectList.h" @@ -31,30 +33,34 @@ ValueObjectConstResult::Create ( ExecutionContextScope *exe_scope, ByteOrder byte_order, - uint32_t addr_byte_size + uint32_t addr_byte_size, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, byte_order, - addr_byte_size))->GetSP(); + addr_byte_size, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult ( ExecutionContextScope *exe_scope, ByteOrder byte_order, - uint32_t addr_byte_size + uint32_t addr_byte_size, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (NULL), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { SetIsConstant (); SetValueIsValid(true); m_data.SetByteOrder(byte_order); m_data.SetAddressByteSize(addr_byte_size); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -64,14 +70,16 @@ ValueObjectConstResult::Create clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data + const DataExtractor &data, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, clang_ast, clang_type, name, - data))->GetSP(); + data, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult @@ -80,12 +88,14 @@ ValueObjectConstResult::ValueObjectConstResult clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data + const DataExtractor &data, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_data = data; m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); @@ -94,7 +104,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -106,7 +116,8 @@ ValueObjectConstResult::Create const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, - uint8_t data_addr_size + uint8_t data_addr_size, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, @@ -115,7 +126,8 @@ ValueObjectConstResult::Create name, data_sp, data_byte_order, - data_addr_size))->GetSP(); + data_addr_size, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult @@ -126,12 +138,14 @@ ValueObjectConstResult::ValueObjectConstResult const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, - uint8_t data_addr_size + uint8_t data_addr_size, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_data.SetByteOrder(data_byte_order); m_data.SetAddressByteSize(data_addr_size); @@ -142,7 +156,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -179,7 +193,8 @@ ValueObjectConstResult::ValueObjectConstResult ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_value.GetScalar() = address; m_data.SetAddressByteSize(addr_byte_size); @@ -197,7 +212,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -217,11 +232,11 @@ ValueObjectConstResult::ValueObjectConstResult ( ValueObject (exe_scope), m_clang_ast (NULL), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this) { m_error = error; SetIsConstant (); - m_pointers_point_to_load_addrs = true; } ValueObjectConstResult::~ValueObjectConstResult() @@ -244,10 +259,7 @@ size_t ValueObjectConstResult::GetByteSize() { if (m_byte_size == 0) - { - uint64_t bit_width = ClangASTType::GetClangTypeBitWidth (GetClangAST(), GetClangType()); - m_byte_size = (bit_width + 7 ) / 8; - } + m_byte_size = ClangASTType::GetTypeByteSize(GetClangAST(), GetClangType()); return m_byte_size; } @@ -293,3 +305,35 @@ ValueObjectConstResult::IsInScope () // information needed to contain the constant value. return true; } + +lldb::ValueObjectSP +ValueObjectConstResult::Dereference (Error &error) +{ + return m_impl.Dereference(error); +} + +lldb::ValueObjectSP +ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +{ + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); +} + +lldb::ValueObjectSP +ValueObjectConstResult::AddressOf (Error &error) +{ + return m_impl.AddressOf(error); +} + +ValueObject * +ValueObjectConstResult::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +} + +size_t +ValueObjectConstResult::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + return m_impl.GetPointeeData(data, item_idx, item_count); +} diff --git a/lldb/source/Core/ValueObjectConstResultChild.cpp b/lldb/source/Core/ValueObjectConstResultChild.cpp new file mode 100644 index 00000000000..2a305a1bea5 --- /dev/null +++ b/lldb/source/Core/ValueObjectConstResultChild.cpp @@ -0,0 +1,82 @@ +//===-- ValueObjectConstResultChild.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ValueObjectConstResultChild.h" + +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectList.h" + +#include "lldb/Symbol/ClangASTContext.h" + +using namespace lldb_private; + +ValueObjectConstResultChild::ValueObjectConstResultChild +( + ValueObject &parent, + clang::ASTContext *clang_ast, + void *clang_type, + const ConstString &name, + uint32_t byte_size, + int32_t byte_offset, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool is_base_class, + bool is_deref_of_parent +) : + ValueObjectChild (parent, + clang_ast, + clang_type, + name, + byte_size, + byte_offset, + bitfield_bit_size, + bitfield_bit_offset, + is_base_class, + is_deref_of_parent, + eAddressTypeLoad), + m_impl(this) +{ + m_name = name; +} + +ValueObjectConstResultChild::~ValueObjectConstResultChild() +{ +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::Dereference (Error &error) +{ + return m_impl.Dereference(error); +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +{ + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::AddressOf (Error &error) +{ + return m_impl.AddressOf(error); +} + +ValueObject * +ValueObjectConstResultChild::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +} + +size_t +ValueObjectConstResultChild::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + return m_impl.GetPointeeData(data, item_idx, item_count); +} diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp new file mode 100644 index 00000000000..119ba015590 --- /dev/null +++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp @@ -0,0 +1,221 @@ +//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ValueObjectConstResultImpl.h" + +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectConstResultChild.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectList.h" + +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/Variable.h" + +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +// this macro enables a simpler implementation for some method calls in this object that relies only upon +// ValueObject knowning how to set the address type of its children correctly. the alternative implementation +// relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less +// efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower +// implementations) can go +#define TRIVIAL_IMPL 1 + +ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj, + lldb::addr_t live_address) : + m_impl_backend(valobj), + m_live_address(live_address), + m_load_addr_backend(), + m_address_of_backend() +{ +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::DerefOnTarget() +{ + if (m_load_addr_backend.get() == NULL) + { + lldb::addr_t tgt_address = m_impl_backend->GetPointerValue(); + m_load_addr_backend = ValueObjectConstResult::Create (m_impl_backend->GetExecutionContextScope(), + m_impl_backend->GetClangAST(), + m_impl_backend->GetClangType(), + m_impl_backend->GetName(), + tgt_address, + eAddressTypeLoad, + m_impl_backend->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); + } + return m_load_addr_backend; +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::Dereference (Error &error) +{ + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::Dereference(error); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget()) + return DerefOnTarget()->Dereference(error); + else + return m_impl_backend->ValueObject::Dereference(error); +#endif +} + +ValueObject * +ValueObjectConstResultImpl::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + if (m_impl_backend == NULL) + return NULL; + + m_impl_backend->UpdateValueIfNeeded(false); + + ValueObjectConstResultChild *valobj = NULL; + + bool omit_empty_base_classes = true; + bool ignore_array_bounds = synthetic_array_member; + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + + const bool transparent_pointers = synthetic_array_member == false; + clang::ASTContext *clang_ast = m_impl_backend->GetClangAST(); + lldb::clang_type_t clang_type = m_impl_backend->GetClangType(); + lldb::clang_type_t child_clang_type; + + ExecutionContext exe_ctx; + m_impl_backend->GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); + + child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, + clang_ast, + m_impl_backend->GetName().GetCString(), + clang_type, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name_str, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (child_clang_type && child_byte_size) + { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString (child_name_str.c_str()); + + valobj = new ValueObjectConstResultChild (*m_impl_backend, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset); + } + + return valobj; +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create) +{ + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget()) + return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create); + else + return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); +#endif +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::AddressOf (Error &error) +{ + if (m_address_of_backend.get() != NULL) + return m_address_of_backend; + + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + if (m_live_address != LLDB_INVALID_ADDRESS) + { + ClangASTType type(m_impl_backend->GetClangAST(), m_impl_backend->GetClangType()); + + lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t))); + + std::string new_name("&"); + new_name.append(m_impl_backend->GetName().AsCString("")); + + m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetUpdatePoint().GetExecutionContextScope(), + type.GetASTContext(), + type.GetPointerType(), + ConstString(new_name.c_str()), + buffer, + lldb::endian::InlHostByteOrder(), + m_impl_backend->GetExecutionContextScope()->CalculateProcess()->GetAddressByteSize()); + + m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); + m_address_of_backend->GetValue().GetScalar() = m_live_address; + + return m_address_of_backend; + } + else + return lldb::ValueObjectSP(); +} + +size_t +ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + if (m_impl_backend == NULL) + return 0; +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType()) + return DerefOnTarget()->GetPointeeData(data, item_idx, item_count); + else + return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); +#endif +} diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 2b381d7cb6b..5717406ba20 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -145,6 +145,23 @@ ValueObjectVariable::UpdateValue () m_value.SetContext(Value::eContextTypeVariable, variable); Value::ValueType value_type = m_value.GetValueType(); + + switch (value_type) + { + case Value::eValueTypeFileAddress: + SetAddressTypeOfChildren(eAddressTypeFile); + break; + case Value::eValueTypeHostAddress: + SetAddressTypeOfChildren(eAddressTypeHost); + break; + case Value::eValueTypeLoadAddress: + SetAddressTypeOfChildren(eAddressTypeLoad); + break; + case Value::eValueTypeScalar: + // TODO: is this the right thing to do? + SetAddressTypeOfChildren(eAddressTypeInvalid); + break; + } switch (value_type) { @@ -250,4 +267,10 @@ ValueObjectVariable::GetModule() return NULL; } - +SymbolContextScope * +ValueObjectVariable::GetSymbolContextScope() +{ + if (m_variable_sp) + return m_variable_sp->GetSymbolContextScope(); + return NULL; +} |