diff options
Diffstat (limited to 'lldb/source')
24 files changed, 1679 insertions, 552 deletions
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 5b3371b62bc..95e1cbc2ad2 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -334,7 +334,7 @@ LLDBSwigPythonCreateSyntheticProvider extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor); extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); -extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue (void* data); +extern "C" void* LLDBSWIGPython_CastPyObjectToSBValue (void* data); extern "C" void LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); extern "C" bool LLDBSwigPythonCallCommand diff --git a/lldb/source/API/SBData.cpp b/lldb/source/API/SBData.cpp new file mode 100644 index 00000000000..cee63164859 --- /dev/null +++ b/lldb/source/API/SBData.cpp @@ -0,0 +1,489 @@ +//===-- SBData.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/API/SBData.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBStream.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +SBData::SBData () +{ +} + +SBData::SBData (const lldb::DataExtractorSP& data_sp) : + m_opaque_sp (data_sp) +{ +} + +SBData::SBData(const SBData &rhs) : + m_opaque_sp (rhs.m_opaque_sp) +{ +} + +const SBData & +SBData::operator = (const SBData &rhs) +{ + if (this != &rhs) + m_opaque_sp = rhs.m_opaque_sp; + return *this; +} + +SBData::~SBData () +{ +} + +void +SBData::SetOpaque (const lldb::DataExtractorSP &data_sp) +{ + m_opaque_sp = data_sp; +} + +lldb_private::DataExtractor * +SBData::get() const +{ + return m_opaque_sp.get(); +} + +lldb_private::DataExtractor * +SBData::operator->() const +{ + return m_opaque_sp.operator->(); +} + +lldb::DataExtractorSP & +SBData::operator*() +{ + return m_opaque_sp; +} + +const lldb::DataExtractorSP & +SBData::operator*() const +{ + return m_opaque_sp; +} + +bool +SBData::IsValid() +{ + return m_opaque_sp.get() != NULL; +} + +uint8_t +SBData::GetAddressByteSize () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint8_t value = 0; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetAddressByteSize(); + if (log) + log->Printf ("SBData::GetAddressByteSize () => " + "(%i)", value); + return value; +} + +void +SBData::Clear () +{ + if (m_opaque_sp.get()) + m_opaque_sp->Clear(); +} + +size_t +SBData::GetByteSize () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + size_t value = 0; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetByteSize(); + if (log) + log->Printf ("SBData::GetByteSize () => " + "(%i)", value); + return value; +} + +lldb::ByteOrder +SBData::GetByteOrder () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + lldb::ByteOrder value = eByteOrderInvalid; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetByteOrder(); + if (log) + log->Printf ("SBData::GetByteOrder () => " + "(%i)", value); + return value; +} + +float +SBData::GetFloat (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + float value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetFloat(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetFloat (error=%p,offset=%d) => " + "(%f)", error.get(), offset, value); + return value; +} + +double +SBData::GetDouble (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + double value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetDouble(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetDouble (error=%p,offset=%d) => " + "(%f)", error.get(), offset, value); + return value; +} + +long double +SBData::GetLongDouble (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + long double value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetLongDouble(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetLongDouble (error=%p,offset=%d) => " + "(%lf)", error.get(), offset, value); + return value; +} + +lldb::addr_t +SBData::GetAddress (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + lldb::addr_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetAddress(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetAddress (error=%p,offset=%d) => " + "(%p)", error.get(), offset, (void*)value); + return value; +} + +uint8_t +SBData::GetUnsignedInt8 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint8_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU8(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt8 (error=%p,offset=%d) => " + "(%c)", error.get(), offset, value); + return value; +} + +uint16_t +SBData::GetUnsignedInt16 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint16_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU16(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt16 (error=%p,offset=%d) => " + "(%hd)", error.get(), offset, value); + return value; +} + +uint32_t +SBData::GetUnsignedInt32 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint32_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU32(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt32 (error=%p,offset=%d) => " + "(%d)", error.get(), offset, value); + return value; +} + +uint64_t +SBData::GetUnsignedInt64 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint64_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU64(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt64 (error=%p,offset=%d) => " + "(%q)", error.get(), offset, value); + return value; +} + +int8_t +SBData::GetSignedInt8 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int8_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int8_t)m_opaque_sp->GetMaxS64(&offset, 1); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt8 (error=%p,offset=%d) => " + "(%c)", error.get(), offset, value); + return value; +} + +int16_t +SBData::GetSignedInt16 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int16_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int16_t)m_opaque_sp->GetMaxS64(&offset, 2); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt16 (error=%p,offset=%d) => " + "(%hd)", error.get(), offset, value); + return value; +} + +int32_t +SBData::GetSignedInt32 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int32_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int32_t)m_opaque_sp->GetMaxS64(&offset, 4); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt32 (error=%p,offset=%d) => " + "(%d)", error.get(), offset, value); + return value; +} + +int64_t +SBData::GetSignedInt64 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int64_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int64_t)m_opaque_sp->GetMaxS64(&offset, 8); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt64 (error=%p,offset=%d) => " + "(%q)", error.get(), offset, value); + return value; +} + +const char* +SBData::GetString (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + const char* value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetCStr(&offset); + if (offset == old_offset || (value == NULL)) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetString (error=%p,offset=%d) => " + "(%p)", error.get(), offset, value); + return value; +} + +bool +SBData::GetDescription (lldb::SBStream &description) +{ + if (m_opaque_sp) + { + description.ref(); + m_opaque_sp->Dump(description.get(), + 0, + lldb::eFormatBytesWithASCII, + 1, + m_opaque_sp->GetByteSize(), + 16, + LLDB_INVALID_ADDRESS, + 0, + 0); + } + else + description.Printf ("No Value"); + + return true; +} + +size_t +SBData::ReadRawData (lldb::SBError& error, + uint32_t offset, + void *buf, + size_t size) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + void* ok = NULL; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + ok = m_opaque_sp->GetU8(&offset, buf, size); + if ((offset == old_offset) || (ok == NULL)) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::ReadRawData (error=%p,offset=%d,buf=%p,size=%d) => " + "(%p)", error.get(), offset, buf, size, ok); + return ok ? size : 0; +} + +void +SBData::SetData(lldb::SBError& error, + const void *buf, + size_t size, + lldb::ByteOrder endian, + uint8_t addr_size) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (!m_opaque_sp.get()) + m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size)); + else + m_opaque_sp->SetData(buf, size, endian); + if (log) + log->Printf ("SBData::SetData (error=%p,buf=%p,size=%d,endian=%d,addr_size=%c) => " + "(%p)", error.get(), buf, size, endian, addr_size, m_opaque_sp.get()); +} + +bool +SBData::Append(const SBData& rhs) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + bool value = false; + if (m_opaque_sp.get() && rhs.m_opaque_sp.get()) + value = m_opaque_sp.get()->Append(*rhs.m_opaque_sp); + if (log) + log->Printf ("SBData::Append (rhs=%p) => " + "(%s)", rhs.get(), value ? "true" : "false"); + return value; +}
\ No newline at end of file diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index a58957b9a9b..ea7ebf8c13e 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -479,6 +479,38 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, const SB return result; } +lldb::SBValue +SBValue::CreateValueFromData (const char* name, + const SBData& data, + const SBType& type) +{ + SBValue result; + + AddressType addr_of_children_priv = eAddressTypeLoad; + + if (m_opaque_sp) + { + ValueObjectSP valobj_sp; + valobj_sp = ValueObjectConstResult::Create (m_opaque_sp->GetExecutionContextScope(), + type.m_opaque_sp->GetASTContext() , + type.m_opaque_sp->GetOpaqueQualType(), + ConstString(name), + *data.m_opaque_sp, + LLDB_INVALID_ADDRESS); + valobj_sp->SetAddressTypeOfChildren(addr_of_children_priv); + result = SBValue(valobj_sp); + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + { + if (result.IsValid()) + log->Printf ("SBValue(%p)::GetChildFromExpression => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp.get()); + else + log->Printf ("SBValue(%p)::GetChildFromExpression => NULL", m_opaque_sp.get()); + } + return result; +} + SBValue SBValue::GetChildAtIndex (uint32_t idx) { @@ -812,9 +844,10 @@ SBValue::GetProcess() SBProcess result; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) { - result = SBProcess(lldb::ProcessSP(m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetProcessSP())); + result = SBProcess(lldb::ProcessSP(target->GetProcessSP())); } } LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -967,10 +1000,10 @@ SBValue::AddressOf() SBValue sb_value; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); - + Mutex::Locker api_locker (target->GetAPIMutex()); Error error; sb_value = m_opaque_sp->AddressOf (error); } @@ -981,3 +1014,127 @@ SBValue::AddressOf() return sb_value; } + +lldb::addr_t +SBValue::GetLoadAddress() +{ + lldb::addr_t value = LLDB_INVALID_ADDRESS; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + Mutex::Locker api_locker (target->GetAPIMutex()); + const bool scalar_is_load_address = true; + AddressType addr_type; + value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); + if (addr_type == eAddressTypeFile) + { + Module* module = m_opaque_sp->GetModule(); + if (!module) + value = LLDB_INVALID_ADDRESS; + else + { + Address addr; + module->ResolveFileAddress(value, addr); + value = addr.GetLoadAddress(m_opaque_sp->GetUpdatePoint().GetTargetSP().get()); + } + } + else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeInvalid) + value = LLDB_INVALID_ADDRESS; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetLoadAddress () => (%llu)", m_opaque_sp.get(), value); + + return value; +} + +lldb::SBAddress +SBValue::GetAddress() +{ + Address addr; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + lldb::addr_t value = LLDB_INVALID_ADDRESS; + Mutex::Locker api_locker (target->GetAPIMutex()); + const bool scalar_is_load_address = true; + AddressType addr_type; + value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); + if (addr_type == eAddressTypeFile) + { + Module* module = m_opaque_sp->GetModule(); + if (module) + module->ResolveFileAddress(value, addr); + } + else if (addr_type == eAddressTypeLoad) + { + // no need to check the return value on this.. if it can actually do the resolve + // addr will be in the form (section,offset), otherwise it will simply be returned + // as (NULL, value) + addr.SetLoadAddress(value, target); + } + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", m_opaque_sp.get(), (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"), addr.GetOffset()); + return SBAddress(new Address(addr)); +} + +lldb::SBData +SBValue::GetPointeeData (uint32_t item_idx, + uint32_t item_count) +{ + lldb::SBData sb_data; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + DataExtractorSP data_sp(new DataExtractor()); + Mutex::Locker api_locker (target->GetAPIMutex()); + m_opaque_sp->GetPointeeData(*data_sp, item_idx, item_count); + if (data_sp->GetByteSize() > 0) + *sb_data = data_sp; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetPointeeData (%d, %d) => SBData(%p)", + m_opaque_sp.get(), + item_idx, + item_count, + sb_data.get()); + + return sb_data; +} + +lldb::SBData +SBValue::GetData () +{ + lldb::SBData sb_data; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + DataExtractorSP data_sp(new DataExtractor()); + Mutex::Locker api_locker (target->GetAPIMutex()); + m_opaque_sp->GetData(*data_sp); + if (data_sp->GetByteSize() > 0) + *sb_data = data_sp; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetData () => SBData(%p)", + m_opaque_sp.get(), + sb_data.get()); + + return sb_data; +} diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 8f63bf29009..da0af986247 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1514,7 +1514,7 @@ public: OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypeName, "Name of a Python function to use."}, + { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 694c904391e..4be9b8de3ad 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -321,9 +321,6 @@ CommandObjectExpression::EvaluateExpression { if (result_valobj_sp->GetError().Success()) { - - result_valobj_sp.get()->SetIsExpressionResult(true); - if (m_options.format != eFormatDefault) result_valobj_sp->SetFormat (m_options.format); diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index e12427a50c8..2e82df060c6 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -1082,8 +1082,8 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, - { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, - { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, + { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."}, + { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."}, { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, @@ -3262,7 +3262,7 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, - { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."}, + { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } @@ -3548,7 +3548,7 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, - { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."}, + { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; 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; +} diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 1607d8e11c2..b1eafd5e30f 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -697,8 +697,8 @@ SummaryStringHelpTextCallback() "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" - " ${var.x.y}). In expression paths you can use either . or -> without any difference in meaning. You can also use ${*var followed by an expression path and in that case" - " the object referred by the path will be dereferenced before being displayed. If the object is not a pointer, doing so will cause an error.\n" + " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed." + " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n" "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" " path refers to:\n" @@ -706,7 +706,41 @@ SummaryStringHelpTextCallback() " and displayed as an individual variable\n" " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" - "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1."; + "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n" + "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the" + " special symbols only allowed as part of a variable:\n" + " %V: show the value of the object by default\n" + " %S: show the summary of the object by default\n" + " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n" + " %L: show the location of the object (memory address or a register name)\n" + " %#: show the number of children of the object\n" + " %T: show the type of the object\n" + "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses" + " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would" + " count the number of actual elements stored in an std::list:\n" + "type summary add -s \"${svar%#}\" -x \"std::list<\""; +} + +static const char * +ExprPathHelpTextCallback() +{ + return + "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n" + "For instance, given a class:\n" + " class foo {\n" + " int a;\n" + " int b; .\n" + " foo* next;\n" + " };\n" + "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n" + "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n" + "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n" + "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n" + "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n" + "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract" + " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index" + " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the" + " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; } const char * @@ -742,6 +776,7 @@ CommandObject::g_arguments_data[] = { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." }, { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL }, @@ -764,6 +799,9 @@ CommandObject::g_arguments_data[] = { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." }, { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." }, + { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." }, + { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." }, + { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." }, { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." }, { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." }, { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." }, diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 0f508de7c5d..bbaa8b9ad06 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -18,9 +18,7 @@ #include <string> -#include "lldb/API/SBFrame.h" -#include "lldb/API/SBBreakpointLocation.h" -#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" @@ -90,6 +88,36 @@ ReleasePythonLock () PythonMutexPredicate().SetValue (LLDB_INVALID_THREAD_ID, eBroadcastAlways); } +ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *pi, + FILE* tmp_fh, + bool ns) : + m_need_session(ns), + m_release_lock(false), + m_python_interpreter(pi), + m_tmp_fh(tmp_fh) +{ + // if Enter/LeaveSession() must be called, then m_python_interpreter must be != NULL + assert(m_need_session && m_python_interpreter); + if (!CurrentThreadHasPythonLock()) + { + while (!GetPythonLock (1)) + if (tmp_fh) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + m_release_lock = true; + } + if (m_need_session) + m_python_interpreter->EnterSession (); +} + +ScriptInterpreterPython::Locker::~Locker() +{ + if (m_need_session) + m_python_interpreter->LeaveSession (); + if (m_release_lock) + ReleasePythonLock (); +} + ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) : ScriptInterpreter (interpreter, eScriptLanguagePython), m_embedded_python_pty (), @@ -226,21 +254,10 @@ ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) m_dbg_stdout = fh; FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout); - if (!CurrentThreadHasPythonLock ()) - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, "Python interpreter locked on another thread; waiting to acquire lock...\n"); - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - ReleasePythonLock (); - } - else - { - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - } + + Locker py_lock(this, tmp_fh); + + m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); } void @@ -1400,25 +1417,12 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name void* ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(this, tmp_fh); ret_val = g_swig_synthetic_script (class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_synthetic_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1526,25 +1530,12 @@ ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_n && *python_function_name) { FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_typescript_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_typescript_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } } else @@ -1595,27 +1586,13 @@ ScriptInterpreterPython::BreakpointCallbackFunction { bool ret_val = true; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_breakpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - bp_loc_sp); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_breakpoint_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, bp_loc_sp); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } @@ -1758,55 +1735,47 @@ ScriptInterpreterPython::CalculateNumChildren (void *implementor) uint32_t ret_val = 0; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } -void* +lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex (void *implementor, uint32_t idx) { if (!implementor) - return 0; + return lldb::ValueObjectSP(); - if (!g_swig_get_child_index) - return 0; + if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) + return lldb::ValueObjectSP(); ScriptInterpreterPython *python_interpreter = this; - void* ret_val = NULL; + void* child_ptr = NULL; + lldb::SBValue* value_sb = NULL; + lldb::ValueObjectSP ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - ReleasePythonLock (); + Locker py_lock(python_interpreter, tmp_fh); + child_ptr = g_swig_get_child_index (implementor,idx); + if (child_ptr != NULL && child_ptr != Py_None) + { + value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); + if (value_sb == NULL) + Py_XDECREF(child_ptr); + else + ret_val = value_sb->get_sp(); + } + else + { + Py_XDECREF(child_ptr); + } } return ret_val; @@ -1826,21 +1795,10 @@ ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* int ret_val = UINT32_MAX; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1858,60 +1816,15 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) ScriptInterpreterPython *python_interpreter = this; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return; } -lldb::SBValue* -ScriptInterpreterPython::CastPyObjectToSBValue (void* data) -{ - if (!data) - return NULL; - - if (!g_swig_cast_to_sbvalue) - return NULL; - - ScriptInterpreterPython *python_interpreter = this; - - lldb::SBValue* ret_val = NULL; - - FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - ReleasePythonLock (); - } - - return ret_val; -} - bool ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, @@ -1939,31 +1852,15 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, std::string err_msg; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_call_command (impl_function, - python_interpreter->m_dictionary_name.c_str(), - debugger_sp, - args, - err_msg, - cmd_retobj); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_call_command (impl_function, python_interpreter->m_dictionary_name.c_str(), debugger_sp, args, err_msg, cmd_retobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } if (!ret_val) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 52e07ce4fe7..90b17d1c084 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -62,7 +62,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, // First job, pull out the address at 0 offset from the object. AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(address_type, true); + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); if (original_ptr == LLDB_INVALID_ADDRESS) return false; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 5c84f710b72..1dfb3645473 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -49,17 +49,11 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &object) return NULL; // Make the argument list: we pass one arg, the address of our pointer, to the print function. - Scalar scalar; + Value val; - if (!ClangASTType::GetValueAsScalar (object.GetClangAST(), - object.GetClangType(), - object.GetDataExtractor(), - 0, - object.GetByteSize(), - scalar)) + if (!object.ResolveValue(val.GetScalar())) return NULL; - Value val(scalar); return GetObjectDescription(str, val, object.GetExecutionContextScope()); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 9e97f3b9923..4d4d4fbebf5 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -245,7 +245,7 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, { // First job, pull out the address at 0 offset from the object That will be the ISA pointer. AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(address_type, true); + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); // ObjC only has single inheritance, so the objects all start at the same pointer value. address.SetSection (NULL); @@ -584,26 +584,6 @@ AppleObjCRuntimeV2::IsTaggedPointer(lldb::addr_t ptr) lldb_private::ObjCLanguageRuntime::ObjCISA AppleObjCRuntimeV2::GetISA(ValueObject& valobj) { - - if (valobj.GetIsExpressionResult() && - valobj.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 this code reads memory without - // taking the debug-info-provided object layout, we need to hand it the target version - // of the expression output - lldb::addr_t tgt_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - ValueObjectSP target_object = ValueObjectConstResult::Create (valobj.GetExecutionContextScope(), - valobj.GetClangAST(), - valobj.GetClangType(), - valobj.GetName(), - tgt_address, - eAddressTypeLoad, - valobj.GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); - return GetISA(*target_object); - } - if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != lldb::eLanguageTypeObjC) return 0; @@ -613,8 +593,7 @@ AppleObjCRuntimeV2::GetISA(ValueObject& valobj) if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid) return 0; - uint32_t offset = 0; - uint64_t isa_pointer = valobj.GetDataExtractor().GetPointer(&offset); + lldb::addr_t isa_pointer = valobj.GetPointerValue(); // tagged pointer if (IsTaggedPointer(isa_pointer)) diff --git a/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp b/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp index 2fdd3b099b3..c5f3e40bd34 100644 --- a/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp +++ b/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp @@ -156,9 +156,9 @@ OperatingSystemDarwinKernel::GetDynamicRegisterInfo () ValueObjectSP gpr_valobj_sp (m_thread_list_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create)); if (gpr_valobj_sp->IsPointerType ()) - base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true); + base_addr = gpr_valobj_sp->GetPointerValue (&addr_type); else - base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true); + base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type); ValueObjectSP child_valobj_sp; if (gpr_valobj_sp) @@ -188,7 +188,7 @@ OperatingSystemDarwinKernel::GetDynamicRegisterInfo () { // Adjust the byte size and the offset to match the layout of registers in our struct reg_info.byte_size = child_valobj_sp->GetByteSize(); - reg_info.byte_offset = child_valobj_sp->GetAddressOf(addr_type, true) - base_addr; + reg_info.byte_offset = child_valobj_sp->GetAddressOf(true, &addr_type) - base_addr; reg_info.kinds[eRegisterKindLLDB] = reg_num++; m_register_info_ap->AddRegister (reg_info, reg_name, empty_name, gpr_name); } @@ -290,9 +290,9 @@ OperatingSystemDarwinKernel::CreateRegisterContextForThread (Thread *thread) if (gpr_valobj_sp) { if (gpr_valobj_sp->IsPointerType ()) - base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true); + base_addr = gpr_valobj_sp->GetPointerValue (&addr_type); else - base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true); + base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type); reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), base_addr)); } } diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index b94692bf004..931bd5e7273 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -154,6 +154,53 @@ ClangASTType::GetPointeeType (clang_type_t clang_type) return NULL; } +lldb::clang_type_t +ClangASTType::GetArrayElementType (uint32_t& stride) +{ + return GetArrayElementType(m_ast, m_type, stride); +} + +lldb::clang_type_t +ClangASTType::GetArrayElementType (clang::ASTContext* ast, + lldb::clang_type_t opaque_clang_qual_type, + uint32_t& stride) +{ + if (opaque_clang_qual_type) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)); + + lldb::clang_type_t ret_type = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified().getAsOpaquePtr(); + + // TODO: the real stride will be >= this value.. find the real one! + stride = GetTypeByteSize(ast, ret_type); + + return ret_type; + + } + return NULL; + +} + +lldb::clang_type_t +ClangASTType::GetPointerType () +{ + return GetPointerType (m_ast, + m_type); +} + +lldb::clang_type_t +ClangASTType::GetPointerType (clang::ASTContext *ast_context, + lldb::clang_type_t opaque_clang_qual_type) +{ + if (opaque_clang_qual_type) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)); + + return ast_context->getPointerType(qual_type).getAsOpaquePtr(); + } + return NULL; +} + lldb::Encoding ClangASTType::GetEncoding (uint32_t &count) { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 25d37435ff6..812d906dbf4 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -623,10 +623,20 @@ Target::ReadMemoryFromFileCache (const Address& addr, void *dst, size_t dst_len, } size_t -Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size_t dst_len, Error &error) +Target::ReadMemory (const Address& addr, + bool prefer_file_cache, + void *dst, + size_t dst_len, + Error &error, + lldb::addr_t *load_addr_ptr) { error.Clear(); + // if we end up reading this from process memory, we will fill this + // with the actual load address + if (load_addr_ptr) + *load_addr_ptr = LLDB_INVALID_ADDRESS; + bool process_is_valid = m_process_sp && m_process_sp->IsAlive(); size_t bytes_read = 0; @@ -692,7 +702,11 @@ Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size } } if (bytes_read) + { + if (load_addr_ptr) + *load_addr_ptr = load_addr; return bytes_read; + } // If the address is not section offset we have an address that // doesn't resolve to any address in any currently loaded shared // libaries and we failed to read memory so there isn't anything @@ -1579,6 +1593,7 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name) #define TSC_SKIP_PROLOGUE "skip-prologue" #define TSC_SOURCE_MAP "source-map" #define TSC_MAX_CHILDREN "max-children-count" +#define TSC_MAX_STRLENSUMMARY "max-string-summary-length" static const ConstString & @@ -1623,6 +1638,12 @@ GetSettingNameForMaxChildren () return g_const_string; } +static const ConstString & +GetSettingNameForMaxStringSummaryLength () +{ + static ConstString g_const_string (TSC_MAX_STRLENSUMMARY); + return g_const_string; +} bool Target::SettingsController::SetGlobalVariable (const ConstString &var_name, @@ -1676,7 +1697,8 @@ TargetInstanceSettings::TargetInstanceSettings m_prefer_dynamic_value (2), m_skip_prologue (true, true), m_source_map (NULL, NULL), - m_max_children_display(256) + m_max_children_display(256), + m_max_strlen_length(1024) { // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called // until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers. @@ -1703,7 +1725,8 @@ TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rh m_prefer_dynamic_value (rhs.m_prefer_dynamic_value), m_skip_prologue (rhs.m_skip_prologue), m_source_map (rhs.m_source_map), - m_max_children_display(rhs.m_max_children_display) + m_max_children_display(rhs.m_max_children_display), + m_max_strlen_length(rhs.m_max_strlen_length) { if (m_instance_name != InstanceSettings::GetDefaultName()) { @@ -1787,6 +1810,13 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n if (ok) m_max_children_display = new_value; } + else if (var_name == GetSettingNameForMaxStringSummaryLength()) + { + bool ok; + uint32_t new_value = Args::StringToUInt32(value, 0, 10, &ok); + if (ok) + m_max_strlen_length = new_value; + } else if (var_name == GetSettingNameForSourcePathMap ()) { switch (op) @@ -1858,6 +1888,7 @@ TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &ne m_prefer_dynamic_value = new_settings_ptr->m_prefer_dynamic_value; m_skip_prologue = new_settings_ptr->m_skip_prologue; m_max_children_display = new_settings_ptr->m_max_children_display; + m_max_strlen_length = new_settings_ptr->m_max_strlen_length; } bool @@ -1893,6 +1924,12 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry, count_str.Printf ("%d", m_max_children_display); value.AppendString (count_str.GetData()); } + else if (var_name == GetSettingNameForMaxStringSummaryLength()) + { + StreamString count_str; + count_str.Printf ("%d", m_max_strlen_length); + value.AppendString (count_str.GetData()); + } else { if (err) @@ -1940,12 +1977,13 @@ Target::SettingsController::global_settings_table[] = SettingEntry Target::SettingsController::instance_settings_table[] = { - // var-name var-type default enum init'd hidden help-text - // ================= ================== =============== ======================= ====== ====== ========================================================================= - { TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." }, - { TSC_PREFER_DYNAMIC, eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." }, - { TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." }, - { TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." }, - { TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." }, - { NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL } + // var-name var-type default enum init'd hidden help-text + // ================= ================== =============== ======================= ====== ====== ========================================================================= + { TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." }, + { TSC_PREFER_DYNAMIC , eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." }, + { TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." }, + { TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." }, + { TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." }, + { TSC_MAX_STRLENSUMMARY , eSetVarTypeInt , "1024" , NULL, true, false, "Maximum number of characters to show when using %s in summary strings." }, + { NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL } }; |