summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/Debugger.h4
-rw-r--r--lldb/include/lldb/Core/FormatManager.h212
-rw-r--r--lldb/include/lldb/Core/ValueObject.h26
-rw-r--r--lldb/include/lldb/Symbol/ClangASTType.h3
-rw-r--r--lldb/include/lldb/Target/ObjCLanguageRuntime.h14
-rw-r--r--lldb/include/lldb/lldb-enumerations.h3
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp3
-rw-r--r--lldb/source/Core/Debugger.cpp23
-rw-r--r--lldb/source/Core/FormatClasses.cpp45
-rw-r--r--lldb/source/Core/ValueObject.cpp107
-rw-r--r--lldb/source/Core/ValueObjectChild.cpp2
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp8
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h24
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h25
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp86
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h16
-rw-r--r--lldb/source/Symbol/ClangASTType.cpp11
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py2
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py23
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-objc/main.m2
20 files changed, 546 insertions, 93 deletions
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 3eb5b0de197..17d48d3b108 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -486,7 +486,7 @@ public:
{
public:
static bool
- Get(ValueObject& vobj, ValueFormat::SharedPointer &entry);
+ Get(ValueObject& vobj, lldb::DynamicValueType use_dynamic, ValueFormat::SharedPointer &entry);
static void
Add(const ConstString &type, const ValueFormat::SharedPointer &entry);
@@ -509,9 +509,11 @@ public:
static bool
GetSummaryFormat(ValueObject& vobj,
+ lldb::DynamicValueType use_dynamic,
lldb::SummaryFormatSP& entry);
static bool
GetSyntheticFilter(ValueObject& vobj,
+ lldb::DynamicValueType use_dynamic,
lldb::SyntheticChildrenSP& entry);
class NamedSummaryFormats
diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h
index c8a2fdddcad..14bd709fa98 100644
--- a/lldb/include/lldb/Core/FormatManager.h
+++ b/lldb/include/lldb/Core/FormatManager.h
@@ -55,7 +55,9 @@ namespace std
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Platform.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/TargetList.h"
@@ -189,6 +191,8 @@ private:
typedef FormatMap<KeyType,ValueType> BackEndType;
BackEndType m_format_map;
+
+ std::string m_name;
public:
typedef typename BackEndType::MapType MapType;
@@ -201,8 +205,10 @@ public:
friend class FormatCategory;
- FormatNavigator(IFormatChangeListener* lst = NULL) :
- m_format_map(lst)
+ FormatNavigator(std::string name,
+ IFormatChangeListener* lst = NULL) :
+ m_format_map(lst),
+ m_name(name)
{
}
@@ -223,11 +229,12 @@ public:
bool
Get(ValueObject& vobj,
MapValueType& entry,
+ lldb::DynamicValueType use_dynamic,
uint32_t* why = NULL)
{
uint32_t value = lldb::eFormatterChoiceCriterionDirectChoice;
clang::QualType type = clang::QualType::getFromOpaquePtr(vobj.GetClangType());
- bool ret = Get(vobj, type, entry, value);
+ bool ret = Get(vobj, type, entry, use_dynamic, value);
if (ret)
entry = MapValueType(entry);
else
@@ -267,9 +274,64 @@ private:
return m_format_map.Get(type, entry);
}
+ bool Get_ObjC(ValueObject& vobj,
+ ObjCLanguageRuntime::ObjCISA isa,
+ MapValueType& entry,
+ uint32_t& reason)
+ {
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ if (log)
+ log->Printf("going to an Objective-C dynamic scanning");
+ Process* process = vobj.GetUpdatePoint().GetProcessSP().get();
+ ObjCLanguageRuntime* runtime = process->GetObjCLanguageRuntime();
+ if (runtime == NULL)
+ {
+ if (log)
+ log->Printf("no valid ObjC runtime, bailing out");
+ return false;
+ }
+ if (runtime->IsValidISA(isa) == false)
+ {
+ if (log)
+ log->Printf("invalid ISA, bailing out");
+ return false;
+ }
+ ConstString name = runtime->GetActualTypeName(isa);
+ if (log)
+ log->Printf("looking for formatter for %s", name.GetCString());
+ if (Get(name.GetCString(), entry))
+ {
+ if (log)
+ log->Printf("direct match found, returning");
+ return true;
+ }
+ if (log)
+ log->Printf("no direct match");
+ ObjCLanguageRuntime::ObjCISA parent = runtime->GetParentClass(isa);
+ if (runtime->IsValidISA(parent) == false)
+ {
+ if (log)
+ log->Printf("invalid parent ISA, bailing out");
+ return false;
+ }
+ if (parent == isa)
+ {
+ if (log)
+ log->Printf("parent-child loop, bailing out");
+ return false;
+ }
+ if (Get_ObjC(vobj, parent, entry, reason))
+ {
+ reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses;
+ return true;
+ }
+ return false;
+ }
+
bool Get(ValueObject& vobj,
clang::QualType type,
MapValueType& entry,
+ lldb::DynamicValueType use_dynamic,
uint32_t& reason)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
@@ -299,7 +361,10 @@ private:
log->Printf("appended bitfield info, final result is %s", name.GetCString());
}
if (log)
- log->Printf("trying to get format for VO name %s of type %s",vobj.GetName().AsCString(),name.AsCString());
+ log->Printf("trying to get %s for VO name %s of type %s",
+ m_name.c_str(),
+ vobj.GetName().AsCString(),
+ name.AsCString());
if (Get(name.GetCString(), entry))
{
if (log)
@@ -313,17 +378,48 @@ private:
{
if (log)
log->Printf("stripping reference");
- if (Get(vobj,type.getNonReferenceType(),entry, reason) && !entry->m_skip_references)
+ if (Get(vobj,type.getNonReferenceType(),entry, use_dynamic, reason) && !entry->m_skip_references)
{
reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference;
return true;
}
}
+ if (use_dynamic != lldb::eNoDynamicValues &&
+ typePtr == vobj.GetClangAST()->ObjCBuiltinIdTy.getTypePtr())
+ {
+ if (log)
+ log->Printf("this is an ObjC 'id', let's do dynamic search");
+ Process* process = vobj.GetUpdatePoint().GetProcessSP().get();
+ ObjCLanguageRuntime* runtime = process->GetObjCLanguageRuntime();
+ if (runtime == NULL)
+ {
+ if (log)
+ log->Printf("no valid ObjC runtime, skipping dynamic");
+ }
+ else
+ {
+ if (Get_ObjC(vobj, runtime->GetISA(vobj), entry, reason))
+ {
+ reason |= lldb::eFormatterChoiceCriterionDynamicObjCHierarchy;
+ return true;
+ }
+ }
+ }
+ else if (use_dynamic != lldb::eNoDynamicValues && log)
+ {
+ log->Printf("typename: %s, typePtr = %p, id = %p",
+ name.AsCString(), typePtr, vobj.GetClangAST()->ObjCBuiltinIdTy.getTypePtr());
+ }
+ else if (log)
+ {
+ log->Printf("no dynamic");
+ }
if (typePtr->isPointerType())
{
if (log)
log->Printf("stripping pointer");
- if (Get(vobj, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers)
+ clang::QualType pointee = typePtr->getPointeeType();
+ if (Get(vobj, pointee, entry, use_dynamic, reason) && !entry->m_skip_pointers)
{
reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference;
return true;
@@ -331,6 +427,27 @@ private:
}
if (typePtr->isObjCObjectPointerType())
{
+ if (use_dynamic != lldb::eNoDynamicValues &&
+ name.GetCString() == ConstString("id").GetCString())
+ {
+ if (log)
+ log->Printf("this is an ObjC 'id', let's do dynamic search");
+ Process* process = vobj.GetUpdatePoint().GetProcessSP().get();
+ ObjCLanguageRuntime* runtime = process->GetObjCLanguageRuntime();
+ if (runtime == NULL)
+ {
+ if (log)
+ log->Printf("no valid ObjC runtime, skipping dynamic");
+ }
+ else
+ {
+ if (Get_ObjC(vobj, runtime->GetISA(vobj), entry, reason))
+ {
+ reason |= lldb::eFormatterChoiceCriterionDynamicObjCHierarchy;
+ return true;
+ }
+ }
+ }
if (log)
log->Printf("stripping ObjC pointer");
/*
@@ -343,7 +460,7 @@ private:
ValueObject* target = vobj.Dereference(error).get();
if (error.Fail() || !target)
return false;
- if (Get(*target, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers)
+ if (Get(*target, typePtr->getPointeeType(), entry, use_dynamic, reason) && !entry->m_skip_pointers)
{
reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference;
return true;
@@ -368,7 +485,7 @@ private:
if (log)
log->Printf("got a parent class for this ObjC class");
clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl));
- if (Get(vobj, ivar_qual_type, entry, reason) && entry->m_cascades)
+ if (Get(vobj, ivar_qual_type, entry, use_dynamic, reason) && entry->m_cascades)
{
reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses;
return true;
@@ -397,7 +514,7 @@ private:
end = record->bases_end();
for (pos = record->bases_begin(); pos != end; pos++)
{
- if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades)
+ if ((Get(vobj, pos->getType(), entry, use_dynamic, reason)) && entry->m_cascades)
{
reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses;
return true;
@@ -411,7 +528,7 @@ private:
end = record->vbases_end();
for (pos = record->vbases_begin(); pos != end; pos++)
{
- if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades)
+ if ((Get(vobj, pos->getType(), entry, use_dynamic, reason)) && entry->m_cascades)
{
reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses;
return true;
@@ -427,7 +544,7 @@ private:
{
if (log)
log->Printf("stripping typedef");
- if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry, reason)) && entry->m_cascades)
+ if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry, use_dynamic, reason)) && entry->m_cascades)
{
reason |= lldb::eFormatterChoiceCriterionNavigatedTypedefs;
return true;
@@ -495,9 +612,9 @@ public:
FormatCategory(IFormatChangeListener* clist,
std::string name) :
- m_summary_nav(new SummaryNavigator(clist)),
- m_regex_summary_nav(new RegexSummaryNavigator(clist)),
- m_filter_nav(new FilterNavigator(clist)),
+ m_summary_nav(new SummaryNavigator("summary",clist)),
+ m_regex_summary_nav(new RegexSummaryNavigator("regex-summary",clist)),
+ m_filter_nav(new FilterNavigator("filter",clist)),
m_enabled(false),
m_change_listener(clist),
m_mutex(Mutex::eMutexTypeRecursive),
@@ -531,13 +648,14 @@ public:
bool
Get(ValueObject& vobj,
lldb::SummaryFormatSP& entry,
+ lldb::DynamicValueType use_dynamic,
uint32_t* reason = NULL)
{
if (!IsEnabled())
return false;
- if (Summary()->Get(vobj, entry, reason))
+ if (Summary()->Get(vobj, entry, use_dynamic, reason))
return true;
- bool regex = RegexSummary()->Get(vobj, entry, reason);
+ bool regex = RegexSummary()->Get(vobj, entry, use_dynamic, reason);
if (regex && reason)
*reason |= lldb::eFormatterChoiceCriterionRegularExpressionSummary;
return regex;
@@ -546,11 +664,12 @@ public:
bool
Get(ValueObject& vobj,
lldb::SyntheticChildrenSP& entry,
+ lldb::DynamicValueType use_dynamic,
uint32_t* reason = NULL)
{
if (!IsEnabled())
return false;
- return (Filter()->Get(vobj, entry, reason));
+ return (Filter()->Get(vobj, entry, use_dynamic, reason));
}
// just a shortcut for Summary()->Clear; RegexSummary()->Clear()
@@ -760,43 +879,44 @@ public:
bool
Get(ValueObject& vobj,
- lldb::SummaryFormatSP& entry)
+ lldb::SummaryFormatSP& entry,
+ lldb::DynamicValueType use_dynamic)
{
Mutex::Locker(m_map_mutex);
- uint32_t reason_why;
- bool first = true;
-
+ uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
for (begin = m_active_categories.begin(); begin != end; begin++)
{
FormatCategory::SharedPointer category = *begin;
lldb::SummaryFormatSP current_format;
- if (!category->Get(vobj, current_format, &reason_why))
+ if (!category->Get(vobj, current_format, use_dynamic, &reason_why))
continue;
- if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice)
- {
- entry = current_format;
- return true;
- }
- else if (first)
- {
- entry = current_format;
- first = false;
- }
+ /*if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice)
+ {
+ entry = current_format;
+ return true;
+ }
+ else if (first)
+ {
+ entry = current_format;
+ first = false;
+ }*/
+ entry = current_format;
+ return true;
}
- return !first;
+ return false;
}
bool
Get(ValueObject& vobj,
- lldb::SyntheticChildrenSP& entry)
+ lldb::SyntheticChildrenSP& entry,
+ lldb::DynamicValueType use_dynamic)
{
Mutex::Locker(m_map_mutex);
uint32_t reason_why;
- bool first = true;
ActiveCategoriesIterator begin, end = m_active_categories.end();
@@ -804,9 +924,9 @@ public:
{
FormatCategory::SharedPointer category = *begin;
lldb::SyntheticChildrenSP current_format;
- if (!category->Get(vobj, current_format, &reason_why))
+ if (!category->Get(vobj, current_format, use_dynamic, &reason_why))
continue;
- if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice)
+ /*if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice)
{
entry = current_format;
return true;
@@ -815,9 +935,11 @@ public:
{
entry = current_format;
first = false;
- }
+ }*/
+ entry = current_format;
+ return true;
}
- return !first;
+ return false;
}
};
@@ -847,7 +969,7 @@ public:
typedef bool (*CategoryCallback)(void*, const char*, const FormatCategory::SharedPointer&);
FormatManager() :
- m_value_nav(this),
+ m_value_nav("format",this),
m_named_summaries_map(this),
m_last_revision(0),
m_categories_map(this)
@@ -941,15 +1063,17 @@ public:
bool
Get(ValueObject& vobj,
- lldb::SummaryFormatSP& entry)
+ lldb::SummaryFormatSP& entry,
+ lldb::DynamicValueType use_dynamic)
{
- return m_categories_map.Get(vobj, entry);
+ return m_categories_map.Get(vobj, entry, use_dynamic);
}
bool
Get(ValueObject& vobj,
- lldb::SyntheticChildrenSP& entry)
+ lldb::SyntheticChildrenSP& entry,
+ lldb::DynamicValueType use_dynamic)
{
- return m_categories_map.Get(vobj, entry);
+ return m_categories_map.Get(vobj, entry, use_dynamic);
}
static bool
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index da75b46be15..1bff914ed3f 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -443,6 +443,9 @@ public:
virtual const char *
GetValueAsCString ();
+
+ virtual unsigned long long
+ GetValueAsUnsigned();
virtual bool
SetValueFromCString (const char *value_str);
@@ -513,8 +516,11 @@ public:
bool
UpdateValueIfNeeded (bool update_format = true);
+ bool
+ UpdateValueIfNeeded (lldb::DynamicValueType use_dynamic, bool update_format = true);
+
void
- UpdateFormatsIfNeeded();
+ UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic = lldb::eNoDynamicValues);
DataExtractor &
GetDataExtractor ();
@@ -640,6 +646,18 @@ public:
}
void
+ SetIsExpressionResult(bool expr)
+ {
+ m_is_expression_result = expr;
+ }
+
+ bool
+ GetIsExpressionResult()
+ {
+ return m_is_expression_result;
+ }
+
+ void
SetFormat (lldb::Format format)
{
if (format != m_format)
@@ -677,7 +695,7 @@ public:
lldb::SummaryFormatSP
GetSummaryFormat()
{
- UpdateFormatsIfNeeded();
+ UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
if (HasCustomSummaryFormat())
return m_forced_summary_format;
return m_last_summary_format;
@@ -744,6 +762,7 @@ protected:
lldb::Format m_format;
uint32_t m_last_format_mgr_revision;
+ lldb::DynamicValueType m_last_format_mgr_dynamic;
lldb::SummaryFormatSP m_last_summary_format;
lldb::SummaryFormatSP m_forced_summary_format;
lldb::ValueFormatSP m_last_value_format;
@@ -759,7 +778,8 @@ protected:
m_is_array_item_for_pointer:1,
m_is_bitfield_for_scalar:1,
m_is_expression_path_child:1,
- m_is_child_at_offset:1;
+ m_is_child_at_offset:1,
+ m_is_expression_result:1;
// used to prevent endless looping into GetpPrintableRepresentation()
uint32_t m_dump_printable_counter;
diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h
index b19e2726ac7..e50735beb7b 100644
--- a/lldb/include/lldb/Symbol/ClangASTType.h
+++ b/lldb/include/lldb/Symbol/ClangASTType.h
@@ -98,7 +98,8 @@ public:
GetMinimumLanguage ();
static lldb::LanguageType
- GetMinimumLanguage (lldb::clang_type_t clang_type);
+ GetMinimumLanguage (clang::ASTContext *ctx,
+ lldb::clang_type_t clang_type);
void
DumpValue (ExecutionContext *exe_ctx,
diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index e508da9e7a4..5dc88b6bda0 100644
--- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -72,6 +72,20 @@ public:
{
return eObjC_VersionUnknown;
}
+
+ typedef lldb::addr_t ObjCISA;
+
+ virtual bool
+ IsValidISA(ObjCISA isa) = 0;
+
+ virtual ObjCISA
+ GetISA(ValueObject& valobj) = 0;
+
+ virtual ConstString
+ GetActualTypeName(ObjCISA isa) = 0;
+
+ virtual ObjCISA
+ GetParentClass(ObjCISA isa) = 0;
// Finds the byte offset of the child_type ivar in parent_type. If it can't find the
// offset, returns LLDB_INVALID_IVAR_OFFSET.
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index b9c504b3437..34e9a6cc3ef 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -505,7 +505,8 @@ namespace lldb {
eFormatterChoiceCriterionStrippedPointerReference = 0x00000001,
eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002,
eFormatterChoiceCriterionNavigatedBaseClasses = 0x00000004,
- eFormatterChoiceCriterionRegularExpressionSummary = 0x00000008
+ eFormatterChoiceCriterionRegularExpressionSummary = 0x00000008,
+ eFormatterChoiceCriterionDynamicObjCHierarchy = 0x00000010
} FormatterChoiceCriterion;
//----------------------------------------------------------------------
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 6109b643fdc..86c2fd7d9a9 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -321,6 +321,9 @@ 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/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index a217ddb36ec..9442600a4d7 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1010,22 +1010,35 @@ Debugger::FormatPrompt
if (!vobj)
break;
+ if (log)
+ log->Printf("initial string: %s",var_name_begin);
+
// check for *var and *svar
if (*var_name_begin == '*')
{
do_deref_pointer = true;
var_name_begin++;
}
+
+ if (log)
+ log->Printf("initial string: %s",var_name_begin);
+
if (*var_name_begin == 's')
{
vobj = vobj->GetSyntheticValue(lldb::eUseSyntheticFilter).get();
var_name_begin++;
}
+ if (log)
+ log->Printf("initial string: %s",var_name_begin);
+
// should be a 'v' by now
if (*var_name_begin != 'v')
break;
+ if (log)
+ log->Printf("initial string: %s",var_name_begin);
+
ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
ValueObject::eDereference : ValueObject::eNothing);
ValueObject::GetValueForExpressionPathOptions options;
@@ -1765,9 +1778,9 @@ Debugger::Formatting::ForceUpdate()
}
bool
-Debugger::Formatting::ValueFormats::Get(ValueObject& vobj, ValueFormat::SharedPointer &entry)
+Debugger::Formatting::ValueFormats::Get(ValueObject& vobj, lldb::DynamicValueType use_dynamic, ValueFormat::SharedPointer &entry)
{
- return GetFormatManager().Value().Get(vobj,entry);
+ return GetFormatManager().Value().Get(vobj,entry, use_dynamic);
}
void
@@ -1808,15 +1821,17 @@ Debugger::Formatting::ValueFormats::GetCount()
bool
Debugger::Formatting::GetSummaryFormat(ValueObject& vobj,
+ lldb::DynamicValueType use_dynamic,
lldb::SummaryFormatSP& entry)
{
- return GetFormatManager().Get(vobj, entry);
+ return GetFormatManager().Get(vobj, entry, use_dynamic);
}
bool
Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj,
+ lldb::DynamicValueType use_dynamic,
lldb::SyntheticChildrenSP& entry)
{
- return GetFormatManager().Get(vobj, entry);
+ return GetFormatManager().Get(vobj, entry, use_dynamic);
}
bool
diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp
index 046cc705d00..48097087253 100644
--- a/lldb/source/Core/FormatClasses.cpp
+++ b/lldb/source/Core/FormatClasses.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatClasses.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Target/StackFrame.h"
@@ -121,8 +122,29 @@ StringSummaryFormat::GetDescription()
std::string
ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object)
{
+ lldb::ValueObjectSP target_object;
+ if (object->GetIsExpressionResult() &&
+ ClangASTContext::IsPointerType(object->GetClangType()) &&
+ object->GetValue().GetValueType() == Value::eValueTypeHostAddress)
+ {
+ // when using the expression parser, an additional layer of "frozen data"
+ // can be created, which is basically a byte-exact copy of the data returned
+ // by the expression, but in host memory. because Python code might need to read
+ // into the object memory in non-obvious ways, we need to hand it the target version
+ // of the expression output
+ lldb::addr_t tgt_address = object->GetValueAsUnsigned();
+ target_object = ValueObjectConstResult::Create (object->GetExecutionContextScope(),
+ object->GetClangAST(),
+ object->GetClangType(),
+ object->GetName(),
+ tgt_address,
+ eAddressTypeLoad,
+ object->GetUpdatePoint().GetProcessSP()->GetAddressByteSize());
+ }
+ else
+ target_object = object;
return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(),
- object).c_str());
+ target_object).c_str());
}
std::string
@@ -171,7 +193,26 @@ m_python_class(pclass)
return;
}
- m_interpreter = be->GetUpdatePoint().GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (be->GetIsExpressionResult() &&
+ ClangASTContext::IsPointerType(be->GetClangType()) &&
+ be->GetValue().GetValueType() == Value::eValueTypeHostAddress)
+ {
+ // when using the expression parser, an additional layer of "frozen data"
+ // can be created, which is basically a byte-exact copy of the data returned
+ // by the expression, but in host memory. because Python code might need to read
+ // into the object memory in non-obvious ways, we need to hand it the target version
+ // of the expression output
+ lldb::addr_t tgt_address = be->GetValueAsUnsigned();
+ m_backend = ValueObjectConstResult::Create (be->GetExecutionContextScope(),
+ be->GetClangAST(),
+ be->GetClangType(),
+ be->GetName(),
+ tgt_address,
+ eAddressTypeLoad,
+ be->GetUpdatePoint().GetProcessSP()->GetAddressByteSize());
+ }
+
+ m_interpreter = m_backend->GetUpdatePoint().GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (m_interpreter == NULL)
m_wrapper = NULL;
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index fce3646c47e..77ee5c14e52 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -39,6 +39,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
@@ -76,6 +77,7 @@ ValueObject::ValueObject (ValueObject &parent) :
m_deref_valobj(NULL),
m_format (eFormatDefault),
m_last_format_mgr_revision(0),
+ m_last_format_mgr_dynamic(lldb::eNoDynamicValues),
m_last_summary_format(),
m_forced_summary_format(),
m_last_value_format(),
@@ -91,6 +93,7 @@ ValueObject::ValueObject (ValueObject &parent) :
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_manager->ManageObject(this);
@@ -120,6 +123,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) :
m_deref_valobj(NULL),
m_format (eFormatDefault),
m_last_format_mgr_revision(0),
+ m_last_format_mgr_dynamic(lldb::eNoDynamicValues),
m_last_summary_format(),
m_forced_summary_format(),
m_last_value_format(),
@@ -135,6 +139,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) :
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_manager = new ValueObjectManager();
@@ -151,9 +156,15 @@ ValueObject::~ValueObject ()
bool
ValueObject::UpdateValueIfNeeded (bool update_format)
{
+ return UpdateValueIfNeeded(m_last_format_mgr_dynamic, update_format);
+}
+
+bool
+ValueObject::UpdateValueIfNeeded (lldb::DynamicValueType use_dynamic, bool update_format)
+{
if (update_format)
- UpdateFormatsIfNeeded();
+ UpdateFormatsIfNeeded(use_dynamic);
// If this is a constant value, then our success is predicated on whether
// we have an error or not
@@ -204,7 +215,7 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
}
void
-ValueObject::UpdateFormatsIfNeeded()
+ValueObject::UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
if (log)
@@ -217,7 +228,8 @@ ValueObject::UpdateFormatsIfNeeded()
ClearCustomSummaryFormat();
m_summary_str.clear();
}
- if (m_last_format_mgr_revision != Debugger::Formatting::ValueFormats::GetCurrentRevision())
+ if ( (m_last_format_mgr_revision != Debugger::Formatting::ValueFormats::GetCurrentRevision()) ||
+ m_last_format_mgr_dynamic != use_dynamic)
{
if (m_last_summary_format.get())
m_last_summary_format.reset((StringSummaryFormat*)NULL);
@@ -228,11 +240,12 @@ ValueObject::UpdateFormatsIfNeeded()
m_synthetic_value = NULL;
- Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format);
- Debugger::Formatting::GetSummaryFormat(*this, m_last_summary_format);
- Debugger::Formatting::GetSyntheticFilter(*this, m_last_synthetic_filter);
+ Debugger::Formatting::ValueFormats::Get(*this, use_dynamic, m_last_value_format);
+ Debugger::Formatting::GetSummaryFormat(*this, use_dynamic, m_last_summary_format);
+ Debugger::Formatting::GetSyntheticFilter(*this, use_dynamic, m_last_synthetic_filter);
m_last_format_mgr_revision = Debugger::Formatting::ValueFormats::GetCurrentRevision();
+ m_last_format_mgr_dynamic = use_dynamic;
ClearUserVisibleData();
}
@@ -241,14 +254,14 @@ ValueObject::UpdateFormatsIfNeeded()
DataExtractor &
ValueObject::GetDataExtractor ()
{
- UpdateValueIfNeeded();
+ UpdateValueIfNeeded(false);
return m_data;
}
const Error &
ValueObject::GetError()
{
- UpdateValueIfNeeded();
+ UpdateValueIfNeeded(false);
return m_error;
}
@@ -261,7 +274,7 @@ ValueObject::GetName() const
const char *
ValueObject::GetLocationAsCString ()
{
- if (UpdateValueIfNeeded())
+ if (UpdateValueIfNeeded(false))
{
if (m_location_str.empty())
{
@@ -358,7 +371,7 @@ ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
ValueObjectSP child_sp;
// We may need to update our value if we are dynamic
if (IsPossibleDynamicType ())
- UpdateValueIfNeeded();
+ UpdateValueIfNeeded(false);
if (idx < GetNumChildren())
{
// Check if we have already made the child value object?
@@ -395,7 +408,7 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
// We may need to update our value if we are dynamic
if (IsPossibleDynamicType ())
- UpdateValueIfNeeded();
+ UpdateValueIfNeeded(false);
std::vector<uint32_t> child_indexes;
clang::ASTContext *clang_ast = GetClangAST();
@@ -519,7 +532,7 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3
const char *
ValueObject::GetSummaryAsCString ()
{
- if (UpdateValueIfNeeded ())
+ if (UpdateValueIfNeeded (m_last_format_mgr_dynamic, true))
{
if (m_summary_str.empty())
{
@@ -775,7 +788,7 @@ const char *
ValueObject::GetObjectDescription ()
{
- if (!UpdateValueIfNeeded ())
+ if (!UpdateValueIfNeeded (m_last_format_mgr_dynamic, true))
return NULL;
if (!m_object_desc_str.empty())
@@ -826,7 +839,7 @@ ValueObject::GetValueAsCString ()
// If our byte size is zero this is an aggregate type that has children
if (ClangASTContext::IsAggregateType (GetClangType()) == false)
{
- if (UpdateValueIfNeeded())
+ if (UpdateValueIfNeeded(true))
{
if (m_value_str.empty())
{
@@ -841,7 +854,7 @@ ValueObject::GetValueAsCString ()
clang_type_t clang_type = GetClangType ();
if (clang_type)
{
- if (m_last_value_format)
+ if (m_format == lldb::eFormatDefault && m_last_value_format)
{
m_value_str = m_last_value_format->FormatObject(GetSP());
}
@@ -905,6 +918,24 @@ ValueObject::GetValueAsCString ()
return m_value_str.c_str();
}
+// if > 8bytes, 0 is returned. this method should mostly be used
+// to read address values out of pointers
+unsigned long long
+ValueObject::GetValueAsUnsigned()
+{
+ // If our byte size is zero this is an aggregate type that has children
+ if (ClangASTContext::IsAggregateType (GetClangType()) == false)
+ {
+ if (UpdateValueIfNeeded(true))
+ {
+ uint32_t offset = 0;
+ return m_data.GetMaxU64(&offset,
+ m_data.GetByteSize());
+ }
+ }
+ return 0;
+}
+
// this call should only return pointers to data that needs no special memory management
// (either because they are hardcoded strings, or because they are backed by some other
// object); returning any new()-ed or malloc()-ed data here, will lead to leaks!
@@ -1092,7 +1123,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
addr_t
ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address)
{
- if (!UpdateValueIfNeeded())
+ if (!UpdateValueIfNeeded(false))
return LLDB_INVALID_ADDRESS;
switch (m_value.GetValueType())
@@ -1124,7 +1155,7 @@ ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_add
lldb::addr_t address = LLDB_INVALID_ADDRESS;
address_type = eAddressTypeInvalid;
- if (!UpdateValueIfNeeded())
+ if (!UpdateValueIfNeeded(false))
return address;
switch (m_value.GetValueType())
@@ -1161,7 +1192,7 @@ ValueObject::SetValueFromCString (const char *value_str)
{
// Make sure our value is up to date first so that our location and location
// type is valid.
- if (!UpdateValueIfNeeded())
+ if (!UpdateValueIfNeeded(false))
return false;
uint32_t count = 0;
@@ -1256,7 +1287,8 @@ ValueObject::Write ()
lldb::LanguageType
ValueObject::GetObjectRuntimeLanguage ()
{
- return ClangASTType::GetMinimumLanguage (GetClangType());
+ return ClangASTType::GetMinimumLanguage (GetClangAST(),
+ GetClangType());
}
void
@@ -1521,7 +1553,7 @@ ValueObject::CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic)
if (use_synthetic == lldb::eNoSyntheticFilter)
return;
- UpdateFormatsIfNeeded();
+ UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
if (m_last_synthetic_filter.get() == NULL)
return;
@@ -1601,7 +1633,7 @@ ValueObject::GetSyntheticValue (SyntheticValueType use_synthetic)
if (use_synthetic == lldb::eNoSyntheticFilter)
return GetSP();
- UpdateFormatsIfNeeded();
+ UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
if (m_last_synthetic_filter.get() == NULL)
return GetSP();
@@ -2537,7 +2569,7 @@ ValueObject::DumpValueObject
{
if (valobj)
{
- bool update_success = valobj->UpdateValueIfNeeded ();
+ bool update_success = valobj->UpdateValueIfNeeded (use_dynamic, true);
if (update_success && use_dynamic != lldb::eNoDynamicValues)
{
@@ -2566,7 +2598,33 @@ ValueObject::DumpValueObject
// Always show the type for the top level items.
if (show_types || (curr_depth == 0 && !flat_output))
- s.Printf("(%s) ", valobj->GetTypeName().AsCString("<invalid type>"));
+ {
+ s.Printf("(%s", valobj->GetTypeName().AsCString("<invalid type>"));
+ if (use_dynamic != lldb::eNoDynamicValues &&
+ strcmp(valobj->GetTypeName().AsCString("NULL"), "id") == 0)
+ {
+ Process* process = valobj->GetUpdatePoint().GetProcessSP().get();
+ if (process == NULL)
+ s.Printf(") ");
+ else
+ {
+ ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
+ if (runtime == NULL)
+ s.Printf(") ");
+ else
+ {
+ ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(*valobj);
+ if (!runtime->IsValidISA(isa))
+ s.Printf(") ");
+ else
+ s.Printf(", dynamic type: %s) ",
+ runtime->GetActualTypeName(isa).GetCString());
+ }
+ }
+ }
+ else
+ s.Printf(") ");
+ }
if (flat_output)
@@ -2758,7 +2816,7 @@ ValueObject::CreateConstantValue (const ConstString &name)
{
ValueObjectSP valobj_sp;
- if (UpdateValueIfNeeded() && m_error.Success())
+ if (UpdateValueIfNeeded(false) && m_error.Success())
{
ExecutionContextScope *exe_scope = GetExecutionContextScope();
if (exe_scope)
@@ -2957,7 +3015,6 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
return valobj_sp;
}
-
ValueObject::EvaluationPoint::EvaluationPoint () :
m_thread_id (LLDB_INVALID_UID),
m_stop_id (0)
diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp
index 8ddf195b51f..2ded7b50e82 100644
--- a/lldb/source/Core/ValueObjectChild.cpp
+++ b/lldb/source/Core/ValueObjectChild.cpp
@@ -97,7 +97,7 @@ ValueObjectChild::UpdateValue ()
ValueObject* parent = m_parent;
if (parent)
{
- if (parent->UpdateValueIfNeeded())
+ if (parent->UpdateValueIfNeeded(false))
{
m_value.SetContext(Value::eContextTypeClangType, m_clang_type);
diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp
index 885e68fd3bd..beecaa95238 100644
--- a/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -60,7 +60,7 @@ ValueObjectDynamicValue::GetClangType ()
ConstString
ValueObjectDynamicValue::GetTypeName()
{
- const bool success = UpdateValueIfNeeded();
+ const bool success = UpdateValueIfNeeded(false);
if (success && m_type_sp)
return ClangASTType::GetConstTypeName (GetClangType());
else
@@ -70,7 +70,7 @@ ValueObjectDynamicValue::GetTypeName()
uint32_t
ValueObjectDynamicValue::CalculateNumChildren()
{
- const bool success = UpdateValueIfNeeded();
+ const bool success = UpdateValueIfNeeded(false);
if (success && m_type_sp)
return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
else
@@ -90,7 +90,7 @@ ValueObjectDynamicValue::GetClangAST ()
size_t
ValueObjectDynamicValue::GetByteSize()
{
- const bool success = UpdateValueIfNeeded();
+ const bool success = UpdateValueIfNeeded(false);
if (success && m_type_sp)
return m_value.GetValueByteSize(GetClangAST(), NULL);
else
@@ -109,7 +109,7 @@ ValueObjectDynamicValue::UpdateValue ()
SetValueIsValid (false);
m_error.Clear();
- if (!m_parent->UpdateValueIfNeeded())
+ if (!m_parent->UpdateValueIfNeeded(false))
{
// The dynamic value failed to get an error, pass the error along
if (m_error.Success() && m_parent->GetError().Fail())
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
index c0d8dcdfc94..43178772955 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -63,6 +63,30 @@ public:
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (Thread &thread, bool stop_others);
+ virtual bool
+ IsValidISA(ObjCISA isa)
+ {
+ return false;
+ }
+
+ virtual ObjCISA
+ GetISA(ValueObject& valobj)
+ {
+ return 0;
+ }
+
+ virtual ConstString
+ GetActualTypeName(ObjCISA isa)
+ {
+ return ConstString(NULL);
+ }
+
+ virtual ObjCISA
+ GetParentClass(ObjCISA isa)
+ {
+ return 0;
+ }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 5596b179929..0e7d87ce2f2 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -72,6 +72,31 @@ public:
{
return eAppleObjC_V1;
}
+
+ virtual bool
+ IsValidISA(ObjCISA isa)
+ {
+ return false;
+ }
+
+ virtual ObjCISA
+ GetISA(ValueObject& valobj)
+ {
+ return 0;
+ }
+
+ virtual ConstString
+ GetActualTypeName(ObjCISA isa)
+ {
+ return ConstString(NULL);
+ }
+
+ virtual ObjCISA
+ GetParentClass(ObjCISA isa)
+ {
+ return 0;
+ }
+
protected:
private:
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 9f2a93c9e06..753d1e29055 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -563,4 +563,90 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const c
return ivar_offset;
}
+lldb_private::ObjCLanguageRuntime::ObjCISA
+AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
+{
+ if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != lldb::eLanguageTypeObjC)
+ return 0;
+
+ uint32_t offset = 0;
+ uint64_t isa_pointer = valobj.GetDataExtractor().GetPointer(&offset);
+
+ uint8_t pointer_size = valobj.GetUpdatePoint().GetProcessSP()->GetAddressByteSize();
+
+ Error error;
+ lldb_private::ObjCLanguageRuntime::ObjCISA isa =
+ valobj.GetUpdatePoint().GetProcessSP()->ReadUnsignedIntegerFromMemory(isa_pointer,
+ pointer_size,
+ 0,
+ error);
+ return isa;
+}
+
+ConstString
+AppleObjCRuntimeV2::GetActualTypeName(lldb_private::ObjCLanguageRuntime::ObjCISA isa)
+{
+ if (!IsValidISA(isa))
+ return ConstString(NULL);
+
+ uint8_t pointer_size = m_process->GetAddressByteSize();
+ Error error;
+ lldb::addr_t rw_pointer = isa + (4 * pointer_size);
+ //printf("rw_pointer: %llx\n", rw_pointer);
+
+ uint64_t data_pointer = m_process->ReadUnsignedIntegerFromMemory(rw_pointer,
+ pointer_size,
+ 0,
+ error);
+ if (error.Fail())
+ return ConstString("unknown");
+
+ data_pointer += 8;
+ //printf("data_pointer: %llx\n", data_pointer);
+ uint64_t ro_pointer = m_process->ReadUnsignedIntegerFromMemory(data_pointer,
+ pointer_size,
+ 0,
+ error);
+ if (error.Fail())
+ return ConstString("unknown");
+
+ ro_pointer += 12;
+ if (pointer_size == 8)
+ ro_pointer += 4;
+ ro_pointer += pointer_size;
+ //printf("ro_pointer: %llx\n", ro_pointer);
+ uint64_t name_pointer = m_process->ReadUnsignedIntegerFromMemory(ro_pointer,
+ pointer_size,
+ 0,
+ error);
+ if (error.Fail())
+ return ConstString("unknown");
+
+ //printf("name_pointer: %llx\n", name_pointer);
+ char* cstr = new char[512];
+ if (m_process->ReadCStringFromMemory(name_pointer, cstr, 512) > 0)
+ return ConstString(cstr);
+ else
+ return ConstString("unknown");
+}
+
+lldb_private::ObjCLanguageRuntime::ObjCISA
+AppleObjCRuntimeV2::GetParentClass(lldb_private::ObjCLanguageRuntime::ObjCISA isa)
+{
+ if (!IsValidISA(isa))
+ return 0;
+
+ uint8_t pointer_size = m_process->GetAddressByteSize();
+ Error error;
+ lldb::addr_t parent_pointer = isa + pointer_size;
+ //printf("rw_pointer: %llx\n", rw_pointer);
+
+ uint64_t parent_isa = m_process->ReadUnsignedIntegerFromMemory(parent_pointer,
+ pointer_size,
+ 0,
+ error);
+ if (error.Fail())
+ return 0;
+ return parent_isa;
+}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index b6bd5b8fbd5..63bb994f28d 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -76,7 +76,21 @@ public:
virtual size_t
GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
-
+
+ virtual bool
+ IsValidISA(ObjCISA isa)
+ {
+ return (isa != 0);
+ }
+
+ virtual ObjCISA
+ GetISA(ValueObject& valobj);
+
+ virtual ConstString
+ GetActualTypeName(ObjCISA isa);
+
+ virtual ObjCISA
+ GetParentClass(ObjCISA isa);
protected:
diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp
index 1de409d8cff..6f57347b256 100644
--- a/lldb/source/Symbol/ClangASTType.cpp
+++ b/lldb/source/Symbol/ClangASTType.cpp
@@ -159,11 +159,13 @@ ClangASTType::GetEncoding (uint32_t &count)
lldb::LanguageType
ClangASTType::GetMinimumLanguage ()
{
- return ClangASTType::GetMinimumLanguage (m_type);
+ return ClangASTType::GetMinimumLanguage (m_ast,
+ m_type);
}
lldb::LanguageType
-ClangASTType::GetMinimumLanguage (lldb::clang_type_t clang_type)
+ClangASTType::GetMinimumLanguage (clang::ASTContext *ctx,
+ lldb::clang_type_t clang_type)
{
if (clang_type == NULL)
return lldb::eLanguageTypeC;
@@ -182,6 +184,8 @@ ClangASTType::GetMinimumLanguage (lldb::clang_type_t clang_type)
return lldb::eLanguageTypeObjC;
if (pointee_type->isObjCClassType())
return lldb::eLanguageTypeObjC;
+ if (pointee_type.getTypePtr() == ctx->ObjCBuiltinIdTy.getTypePtr())
+ return lldb::eLanguageTypeObjC;
}
else
{
@@ -238,7 +242,8 @@ ClangASTType::GetMinimumLanguage (lldb::clang_type_t clang_type)
}
break;
case clang::Type::Typedef:
- return GetMinimumLanguage(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ return GetMinimumLanguage(ctx,
+ llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
}
}
return lldb::eLanguageTypeC;
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py b/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
index ac370f70a18..fea3e669abd 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
+++ b/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py
@@ -286,7 +286,7 @@ class DataFormatterTestCase(TestBase):
substrs = ['ACircle',
'ARectangle',
'ACircle',
- 'ARectangleStar'])
+ 'ARectangle'])
# Check that abruptly deleting an enabled category does not crash us
self.runCmd("type category delete RectangleCategory")
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
index e17b6fc195b..31a64a439e8 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
+++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
@@ -164,7 +164,7 @@ class DataFormatterTestCase(TestBase):
'inline = ',
'explicit = ',
'content = ',
- 'a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+ 'a very much boring task to write a string this way!!\\xcf\\x83'])
self.expect('frame variable str10 -P 1 -Y',
substrs = ['mutable =',
@@ -215,7 +215,7 @@ class DataFormatterTestCase(TestBase):
self.expect('frame variable str8',
substrs = ['hasVeryLongExtensionThisTime'])
self.expect('frame variable str9',
- substrs = ['a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+ substrs = ['a very much boring task to write a string this way!!\\xcf\\x83'])
self.expect('frame variable str10',
substrs = ['This is a Unicode string \\xcf\\x83 number 4 right here'])
self.expect('frame variable str11',
@@ -224,6 +224,25 @@ class DataFormatterTestCase(TestBase):
substrs = ['a.out'])
self.expect('frame variable str12',
substrs = ['Process Name: a.out Process Id:'])
+ self.expect('frame variable dyn_test', matching=False,
+ substrs = ['Process Name: a.out Process Id:'])
+ self.expect('frame variable dyn_test -d run-target',
+ substrs = ['(id, dynamic type:',
+ 'Process Name: a.out Process Id:'])
+
+
+ # check that we can format stuff out of the expression parser
+ self.expect('expression ((id)@"Hello")', matching=False,
+ substrs = ['Hello'])
+
+ self.expect('expression -d true -- ((id)@"Hello")',
+ substrs = ['Hello'])
+
+ self.expect('expr -d true -- label1',
+ substrs = ['Process Name'])
+
+ self.expect('expr -d true -- @"Hello"',
+ substrs = ['Hello'])
if __name__ == '__main__':
import atexit
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/main.m b/lldb/test/functionalities/data-formatter/data-formatter-objc/main.m
index 132d70b5382..326e49d5b3d 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-objc/main.m
+++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/main.m
@@ -117,6 +117,8 @@ int main (int argc, const char * argv[])
NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];
NSString *str12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID];
+ id dyn_test = str12;
+
// Set break point at this line.
[pool drain];
return 0;
OpenPOWER on IntegriCloud