[Lldb-commits] [lldb] r134679 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Interpreter/CommandObject.h lldb.xcodeproj/project.pbxproj source/Core/Debugger.cpp source/Core/ValueObject.cpp source/Interpreter/CommandObject.cpp test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py test/functionalities/data-formatter/data-formatter-advanced/main.cpp test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py www/varformats.html
Enrico Granata
granata.enrico at gmail.com
Thu Jul 7 19:51:02 PDT 2011
Author: enrico
Date: Thu Jul 7 21:51:01 2011
New Revision: 134679
URL: http://llvm.org/viewvc/llvm-project?rev=134679&view=rev
Log:
final fix for the global constructors issue
new GetValueForExpressionPath() method in ValueObject to navigate expression paths in a more bitfield vs slices aware way
changes to the varformats.html document (WIP)
Modified:
lldb/trunk/include/lldb/Core/ValueObject.h
lldb/trunk/include/lldb/Interpreter/CommandObject.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Core/Debugger.cpp
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Interpreter/CommandObject.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
lldb/trunk/www/varformats.html
Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Thu Jul 7 21:51:01 2011
@@ -73,10 +73,111 @@
enum ValueObjectRepresentationStyle
{
- eDisplayValue,
+ eDisplayValue = 1,
eDisplaySummary,
eDisplayLanguageSpecific
};
+
+ enum ExpressionPathScanEndReason
+ {
+ eEndOfString = 1, // out of data to parse
+ eNoSuchChild, // child element not found
+ eEmptyRangeNotAllowed, // [] only allowed for arrays
+ eDotInsteadOfArrow, // . used when -> should be used
+ eArrowInsteadOfDot, // -> used when . should be used
+ eFragileIVarNotAllowed, // ObjC ivar expansion not allowed
+ eRangeOperatorNotAllowed, // [] not allowed by options
+ eRangeOperatorInvalid, // [] not valid on objects other than scalars, pointers or arrays
+ eArrayRangeOperatorMet, // [] is good for arrays, but I cannot parse it
+ eBitfieldRangeOperatorMet, // [] is good for bitfields, but I cannot parse after it
+ eUnexpectedSymbol, // something is malformed in the expression
+ eTakingAddressFailed, // impossible to apply & operator
+ eDereferencingFailed, // impossible to apply * operator
+ eUnknown = 0xFFFF
+ };
+
+ enum ExpressionPathEndResultType
+ {
+ ePlain = 1, // anything but...
+ eBitfield, // a bitfield
+ eBoundedRange, // a range [low-high]
+ eUnboundedRange, // a range []
+ eInvalid = 0xFFFF
+ };
+
+ enum ExpressionPathAftermath
+ {
+ eNothing = 1, // just return it
+ eDereference, // dereference the target
+ eTakeAddress // take target's address
+ };
+
+ struct GetValueForExpressionPathOptions
+ {
+ bool m_check_dot_vs_arrow_syntax;
+ bool m_no_fragile_ivar;
+ bool m_allow_bitfields_syntax;
+
+ GetValueForExpressionPathOptions(bool dot = false,
+ bool no_ivar = false,
+ bool bitfield = true) :
+ m_check_dot_vs_arrow_syntax(dot),
+ m_no_fragile_ivar(no_ivar),
+ m_allow_bitfields_syntax(bitfield)
+ {
+ }
+
+ GetValueForExpressionPathOptions&
+ DoCheckDotVsArrowSyntax()
+ {
+ m_check_dot_vs_arrow_syntax = true;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DontCheckDotVsArrowSyntax()
+ {
+ m_check_dot_vs_arrow_syntax = false;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DoAllowFragileIVar()
+ {
+ m_no_fragile_ivar = false;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DontAllowFragileIVar()
+ {
+ m_no_fragile_ivar = true;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DoAllowBitfieldSyntax()
+ {
+ m_allow_bitfields_syntax = true;
+ return *this;
+ }
+
+ GetValueForExpressionPathOptions&
+ DontAllowBitfieldSyntax()
+ {
+ m_allow_bitfields_syntax = false;
+ return *this;
+ }
+
+ static const GetValueForExpressionPathOptions
+ DefaultOptions()
+ {
+ static GetValueForExpressionPathOptions g_default_options;
+
+ return g_default_options;
+ }
+
+ };
class EvaluationPoint
{
@@ -280,6 +381,14 @@
virtual void
GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eDereferencePointers);
+ lldb::ValueObjectSP
+ GetValueForExpressionPath(const char* expression,
+ const char** first_unparsed = NULL,
+ ExpressionPathScanEndReason* reason_to_stop = NULL,
+ ExpressionPathEndResultType* final_value_type = NULL,
+ const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(),
+ ExpressionPathAftermath* final_task_on_target = NULL);
+
virtual bool
IsInScope ()
{
@@ -636,6 +745,15 @@
//------------------------------------------------------------------
// For ValueObject only
//------------------------------------------------------------------
+
+ lldb::ValueObjectSP
+ GetValueForExpressionPath_Impl(const char* expression,
+ const char** first_unparsed,
+ ExpressionPathScanEndReason* reason_to_stop,
+ ExpressionPathEndResultType* final_value_type,
+ const GetValueForExpressionPathOptions& options,
+ ExpressionPathAftermath* final_task_on_target);
+
DISALLOW_COPY_AND_ASSIGN (ValueObject);
};
Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Thu Jul 7 21:51:01 2011
@@ -33,6 +33,18 @@
{
ArgumentHelpCallbackFunction *help_callback;
bool self_formatting;
+
+ const char*
+ operator () () const
+ {
+ return (*help_callback)();
+ }
+
+ operator bool() const
+ {
+ return (help_callback != NULL);
+ }
+
};
struct ArgumentTableEntry // Entries in the main argument information table
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 7 21:51:01 2011
@@ -1786,12 +1786,12 @@
26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */,
26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */,
26F996A8119B79C300412154 /* ARM_GCC_Registers.h */,
- 2660D9F611922A1300958FBD /* StringExtractor.cpp */,
2660D9F711922A1300958FBD /* StringExtractor.h */,
- 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */,
+ 2660D9F611922A1300958FBD /* StringExtractor.cpp */,
2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */,
- 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */,
+ 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */,
2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */,
+ 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */,
);
name = Utility;
sourceTree = "<group>";
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Thu Jul 7 21:51:01 2011
@@ -694,7 +694,7 @@
}
}
-// #define VERBOSE_FORMATPROMPT_OUTPUT
+//#define VERBOSE_FORMATPROMPT_OUTPUT
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
#define IFERROR_PRINT_IT if (error.Fail()) \
{ \
@@ -832,35 +832,41 @@
ExpandIndexedExpression(ValueObject* vobj,
uint32_t index,
StackFrame* frame,
- Error error)
+ bool deref_pointer)
{
- ValueObjectSP item;
- bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
-
- if (is_array)
- return vobj->GetChildAtIndex(index, true);
- else
- {
- const char* ptr_deref_format = "%s[%d]";
- char* ptr_deref_buffer = new char[1024];
- StreamString expr_path_string;
- vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers);
- const char* expr_path = expr_path_string.GetData();
+ const char* ptr_deref_format = "[%d]";
+ std::auto_ptr<char> ptr_deref_buffer(new char[10]);
+ ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index);
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 0: %s\n",expr_path);
+ printf("name to deref: %s\n",ptr_deref_buffer.get());
#endif //VERBOSE_FORMATPROMPT_OUTPUT
- ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index);
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 1: %s\n",ptr_deref_buffer);
+ const char* first_unparsed;
+ ValueObject::GetValueForExpressionPathOptions options;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eDereference : ValueObject::eNothing);
+ ValueObjectSP item = vobj->GetValueForExpressionPath (ptr_deref_buffer.get(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next);
+ if (!item)
+ {
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
#endif //VERBOSE_FORMATPROMPT_OUTPUT
- lldb::VariableSP var_sp;
- item = frame->GetValueForVariableExpressionPath (ptr_deref_buffer,
- eNoDynamicValues,
- 0,
- var_sp,
- error);
- delete ptr_deref_buffer;
}
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ else
+ {
+ printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
return item;
}
@@ -954,8 +960,9 @@
const RegisterInfo *reg_info = NULL;
RegisterContext *reg_ctx = NULL;
bool do_deref_pointer = false;
- bool did_deref_pointer = true;
-
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+
// Each variable must set success to true below...
bool var_success = false;
switch (var_name_begin[0])
@@ -971,6 +978,10 @@
case 'v':
{
+ ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
+ ValueObject::eDereference : ValueObject::eNothing);
+ ValueObject::GetValueForExpressionPathOptions options;
+ options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar();
ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary;
ValueObject* target = NULL;
lldb::Format custom_format = eFormatInvalid;
@@ -980,6 +991,8 @@
int64_t index_lower = -1;
int64_t index_higher = -1;
bool is_array_range = false;
+ const char* first_unparsed;
+
if (!vobj) break;
// simplest case ${var}, just print vobj's value
if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0)
@@ -1025,57 +1038,47 @@
&index_higher);
Error error;
- target = ExpandExpressionPath (vobj,
- exe_ctx->frame,
- &do_deref_pointer,
- var_name_begin,
- var_name_final,
- error).get();
-
- if (error.Fail() || !target)
+
+ std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]);
+ ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1);
+ memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3);
+
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("symbol to expand: %s\n",expr_path.get());
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+
+ target = vobj->GetValueForExpressionPath(expr_path.get(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next).get();
+
+ if (!target)
{
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("ERROR: %s\n",error.AsCString("unknown"));
+ printf("ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
#endif //VERBOSE_FORMATPROMPT_OUTPUT
- if (var_name_final_if_array_range)
- {
- target = ExpandExpressionPath(vobj,
- exe_ctx->frame,
- &do_deref_pointer,
- var_name_begin,
- var_name_final_if_array_range,
- error).get();
- }
-
- if (var_name_final_if_array_range && (error.Fail() || !target))
- {
- bool fake_do_deref = false;
- target = ExpandExpressionPath(vobj,
- exe_ctx->frame,
- &fake_do_deref,
- var_name_begin,
- var_name_final_if_array_range,
- error).get();
-
- did_deref_pointer = false;
-
- if (target && ClangASTContext::IsArrayType(target->GetClangType()))
- error.Clear();
- else
- error.SetErrorString("error in expression");
- }
-
- IFERROR_PRINT_IT
- else
- is_array_range = true;
+ break;
}
-
- if (did_deref_pointer)
- do_deref_pointer = false; // I have honored the request to deref
-
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ else
+ {
+ printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
}
else
break;
+
+ is_array_range = (final_value_type == ValueObject::eBoundedRange ||
+ final_value_type == ValueObject::eUnboundedRange);
+
+ do_deref_pointer = (what_next == ValueObject::eDereference);
if (do_deref_pointer && !is_array_range)
{
@@ -1092,30 +1095,22 @@
var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
else
{
- bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
- bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType());
+ bool is_array = ClangASTContext::IsArrayType(target->GetClangType());
+ bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType());
if (!is_array && !is_pointer)
break;
- char* special_directions = NULL;
+ const char* special_directions = NULL;
+ StreamString special_directions_writer;
if (close_bracket_position && (var_name_end-close_bracket_position > 1))
{
- int base_len = var_name_end-close_bracket_position;
- special_directions = new char[7+base_len];
- int star_offset = (do_deref_pointer ? 1 : 0);
- special_directions[0] = '$';
- special_directions[1] = '{';
- if (do_deref_pointer)
- special_directions[2] = '*';
- special_directions[2+star_offset] = 'v';
- special_directions[3+star_offset] = 'a';
- special_directions[4+star_offset] = 'r';
- memcpy(special_directions+5+star_offset, close_bracket_position+1, base_len);
- special_directions[base_len+5+star_offset] = '\0';
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("%s\n",special_directions);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ ConstString additional_data;
+ additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
+ special_directions_writer.Printf("${%svar%s}",
+ do_deref_pointer ? "*" : "",
+ additional_data.GetCString());
+ special_directions = special_directions_writer.GetData();
}
// let us display items index_lower thru index_higher of this array
@@ -1127,13 +1122,24 @@
for (;index_lower<=index_higher;index_lower++)
{
- Error error;
- ValueObject* item = ExpandIndexedExpression(vobj,
+ ValueObject* item = ExpandIndexedExpression(target,
index_lower,
exe_ctx->frame,
- error).get();
+ false).get();
- IFERROR_PRINT_IT
+ if (!item)
+ {
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("ERROR\n");
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ }
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ else
+ {
+ printf("special_directions: %s\n",special_directions);
+ }
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+
if (!special_directions)
var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
else
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Jul 7 21:51:01 2011
@@ -1366,6 +1366,412 @@
}
}
+lldb::ValueObjectSP
+ValueObject::GetValueForExpressionPath(const char* expression,
+ const char** first_unparsed,
+ ExpressionPathScanEndReason* reason_to_stop,
+ ExpressionPathEndResultType* final_value_type,
+ const GetValueForExpressionPathOptions& options,
+ ExpressionPathAftermath* final_task_on_target)
+{
+
+ const char* dummy_first_unparsed;
+ ExpressionPathScanEndReason dummy_reason_to_stop;
+ ExpressionPathEndResultType dummy_final_value_type;
+ ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing;
+
+ ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression,
+ first_unparsed ? first_unparsed : &dummy_first_unparsed,
+ reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
+ final_value_type ? final_value_type : &dummy_final_value_type,
+ options,
+ final_task_on_target ? final_task_on_target : &dummy_final_task_on_target);
+
+ if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing)
+ {
+ return ret_val;
+ }
+ if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects
+ {
+ if (*final_task_on_target == ValueObject::eDereference)
+ {
+ Error error;
+ ValueObjectSP final_value = ret_val->Dereference(error);
+ if (error.Fail() || !final_value.get())
+ {
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_value_type = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *final_task_on_target = ValueObject::eNothing;
+ return final_value;
+ }
+ }
+ if (*final_task_on_target == ValueObject::eTakeAddress)
+ {
+ Error error;
+ ValueObjectSP final_value = ret_val->AddressOf(error);
+ if (error.Fail() || !final_value.get())
+ {
+ *reason_to_stop = ValueObject::eTakingAddressFailed;
+ *final_value_type = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *final_task_on_target = ValueObject::eNothing;
+ return final_value;
+ }
+ }
+ }
+ return ret_val; // final_task_on_target will still have its original value, so you know I did not do it
+}
+
+lldb::ValueObjectSP
+ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
+ const char** first_unparsed,
+ ExpressionPathScanEndReason* reason_to_stop,
+ ExpressionPathEndResultType* final_result,
+ const GetValueForExpressionPathOptions& options,
+ ExpressionPathAftermath* what_next)
+{
+ ValueObjectSP root = GetSP();
+
+ if (!root.get())
+ return ValueObjectSP();
+
+ *first_unparsed = expression_cstr;
+
+ while (true)
+ {
+
+ const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
+
+ lldb::clang_type_t root_clang_type = root->GetClangType();
+
+ if (!expression_cstr || *expression_cstr == '\0')
+ {
+ *reason_to_stop = ValueObject::eEndOfString;
+ return root;
+ }
+
+ switch (*expression_cstr)
+ {
+ case '-':
+ {
+ if (options.m_check_dot_vs_arrow_syntax &&
+ !ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use -> on a non-pointer and I must catch the error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eArrowInsteadOfDot;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (root_clang_type, NULL, NULL);
+ if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden
+ (pointer_type_flags & ClangASTContext::eTypeIsPointer) &&
+ options.m_no_fragile_ivar)
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eFragileIVarNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (expression_cstr[1] != '>')
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ expression_cstr++; // skip the -
+ }
+ case '.': // or fallthrough from ->
+ {
+ if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' &&
+ ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use . on a pointer and I must catch the error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDotInsteadOfArrow;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ expression_cstr++; // skip .
+ const char *next_separator = strpbrk(expression_cstr+1,"-.[");
+ ConstString child_name;
+ if (!next_separator) // if no other separator just expand this last layer
+ {
+ child_name.SetCString (expression_cstr);
+ root = root->GetChildMemberWithName(child_name, true);
+ if (root.get()) // we know we are done, so just return
+ {
+ *first_unparsed = '\0';
+ *reason_to_stop = ValueObject::eEndOfString;
+ *final_result = ValueObject::ePlain;
+ return root;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ else // other layers do expand
+ {
+ child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr);
+ root = root->GetChildMemberWithName(child_name, true);
+ if (root.get()) // store the new root and move on
+ {
+ *first_unparsed = next_separator;
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ break;
+ }
+ case '[':
+ {
+ if (!ClangASTContext::IsArrayType(root_clang_type) && !ClangASTContext::IsPointerType(root_clang_type)) // if this is not a T[] nor a T*
+ {
+ if (!ClangASTContext::IsScalarType(root_clang_type)) // if this is not even a scalar, this syntax is just plain wrong!
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorInvalid;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
+ {
+ if (!ClangASTContext::IsArrayType(root_clang_type))
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eEmptyRangeNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else // even if something follows, we cannot expand unbounded ranges, just let the caller do it
+ {
+ *first_unparsed = expression_cstr+2;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eUnboundedRange;
+ return root;
+ }
+ }
+ const char *separator_position = ::strchr(expression_cstr+1,'-');
+ const char *close_bracket_position = ::strchr(expression_cstr+1,']');
+ if (!close_bracket_position) // if there is no ], this is a syntax error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N]
+ {
+ char *end = NULL;
+ unsigned long index = ::strtoul (expression_cstr+1, &end, 0);
+ if (!end || end != close_bracket_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
+ {
+ if (ClangASTContext::IsArrayType(root_clang_type))
+ {
+ *first_unparsed = expression_cstr+2;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eUnboundedRange;
+ return root;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eEmptyRangeNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ // from here on we do have a valid index
+ if (ClangASTContext::IsArrayType(root_clang_type))
+ {
+ root = root->GetChildAtIndex(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ }
+ else if (ClangASTContext::IsPointerType(root_clang_type))
+ {
+ if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr()))
+ {
+ Error error;
+ root = root->Dereference(error);
+ if (error.Fail() || !root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *what_next = eNothing;
+ continue;
+ }
+ }
+ else
+ {
+ root = root->GetSyntheticArrayMemberFromPointer(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ }
+ }
+ else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+ {
+ root = root->GetSyntheticBitFieldChild(index, index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
+ {
+ *first_unparsed = end+1; // skip ]
+ *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet;
+ *final_result = ValueObject::eBitfield;
+ return root;
+ }
+ }
+ }
+ else // we have a low and a high index
+ {
+ char *end = NULL;
+ unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0);
+ if (!end || end != separator_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ unsigned long index_higher = ::strtoul (separator_position+1, &end, 0);
+ if (!end || end != close_bracket_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (index_lower > index_higher) // swap indices if required
+ {
+ unsigned long temp = index_lower;
+ index_lower = index_higher;
+ index_higher = temp;
+ }
+ if (ClangASTContext::IsScalarType(root_clang_type)) // expansion only works for scalars
+ {
+ root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet;
+ *final_result = ValueObject::eBitfield;
+ return root;
+ }
+ }
+ else if (ClangASTContext::IsPointerType(root_clang_type) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ *what_next == ValueObject::eDereference &&
+ ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr()))
+ {
+ Error error;
+ root = root->Dereference(error);
+ if (error.Fail() || !root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *what_next = ValueObject::eNothing;
+ continue;
+ }
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eBoundedRange;
+ return root;
+ }
+ }
+ break;
+ }
+ default: // some non-separator is in the way
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ break;
+ }
+ }
+ }
+}
+
void
ValueObject::DumpValueObject
(
Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jul 7 21:51:01 2011
@@ -469,9 +469,9 @@
StreamString name_str;
name_str.Printf ("<%s>", entry->arg_name);
- if (entry->help_function.help_callback)
+ if (entry->help_function)
{
- const char* help_text = (*entry->help_function.help_callback)();
+ const char* help_text = entry->help_function();
if (!entry->help_function.self_formatting)
{
interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py Thu Jul 7 21:51:01 2011
@@ -159,6 +159,19 @@
substrs = ['0x',
'7'])
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -f \"${*var[].x[0-3]%hex} is a bitfield on a set of integers\" -x \"SimpleWithPointers \[[0-9]\]\"")
+ self.runCmd("type summary add -f \"${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}\" Couple")
+
+ self.expect("frame variable couple",
+ substrs = ['1 are low bits of integer 9.',
+ 'If I pretend it is an array I get [9,'])
+
+ self.expect("frame variable sparray",
+ substrs = ['[0x0000000f,0x0000000c,0x00000009]'])
+
+
if __name__ == '__main__':
import atexit
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp Thu Jul 7 21:51:01 2011
@@ -41,6 +41,38 @@
IWrapPointers() : int_pointer(new int(4)), float_pointer(new float(1.111)) {}
};
+struct Simple
+{
+ int x;
+ float y;
+ char z;
+ Simple(int X, float Y, char Z) :
+ x(X),
+ y(Y),
+ z(Z)
+ {}
+};
+
+struct SimpleWithPointers
+{
+ int *x;
+ float *y;
+ char *z;
+ SimpleWithPointers(int X, float Y, char Z) :
+ x(new int (X)),
+ y(new float (Y)),
+ z(new char (Z))
+ {}
+};
+
+struct Couple
+{
+ SimpleWithPointers sp;
+ Simple* s;
+ Couple(int X, float Y, char Z) : sp(X,Y,Z),
+ s(new Simple(X,Y,Z)) {}
+};
+
int main (int argc, const char * argv[])
{
@@ -66,6 +98,13 @@
int* pointer = &cool_array[4].integer;
IWrapPointers *wrap_pointer = &wrapper;
-
+
+ Couple couple(9,9.99,'X');
+
+ SimpleWithPointers sparray[] =
+ {SimpleWithPointers(-1,-2,'3'),
+ SimpleWithPointers(-4,-5,'6'),
+ SimpleWithPointers(-7,-8,'9')};
+
return 0; // Set break point at this line.
}
\ No newline at end of file
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Thu Jul 7 21:51:01 2011
@@ -99,6 +99,12 @@
self.expect("frame variable iAmSomewhere",
substrs = ['y=0x'])
+
+ self.runCmd("type summary add -f \"y=${var.y},x=${var.x}\" Point")
+
+ self.expect("frame variable iAmSomewhere",
+ substrs = ['y=6',
+ 'x=4'])
self.runCmd("type summary add -f \"hello\" Point -e")
Modified: lldb/trunk/www/varformats.html
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=134679&r1=134678&r2=134679&view=diff
==============================================================================
--- lldb/trunk/www/varformats.html (original)
+++ lldb/trunk/www/varformats.html Thu Jul 7 21:51:01 2011
@@ -1,576 +1,717 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Homepage</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Variable display</h1>
- <div class="postcontent">
- <p>LLDB was recently modified to allow users to define the
- format of the variables display on a per-type basis.</p>
-
- <p>Usually, when you type <code>frame
- variable</code> or run some <code>expression</code>
- LLDB will automatically choose the <i>best</i> way
- to display your results according to its own
- logic:</p> <p> <code> (SimpleWithPointers [3])
- sparray = {<br/> (SimpleWithPointers) [0] = {<br/>
- (int *) x = 0x00000001001000f0<br/> (float *) y =
- 0x0000000100100100<br/> (char *) z =
- 0x0000000100100110 "3"<br/>
- }<br/>
- (SimpleWithPointers) [1] = {<br/> (int *) x =
- 0x0000000100100120<br/> (float *) y =
- 0x0000000100100130<br/> (char *) z =
- 0x0000000100100140 "6"<br/>
- }<br/>
- (SimpleWithPointers) [2] = {<br/> (int *) x =
- 0x0000000100100150<br/> (float *) y =
- 0x0000000100100160<br/> (char *) z =
- 0x0000000100100170 "9"<br/>
- }<br/>
- }<br/>
- </code> </p>
-
- <p>However, there are cases in which your idea of
- <i>best</i> is different from LLDB's. Now there are two
- new commands that enable you to give hints to the debugger
- as to how datatypes should be displayed.</p>
-
- <p>Using them you can obtain a format like this one for
- <code>sparray</code>, instead of the default shown above:
- </p>
-
- <p>
- <code>
- (SimpleWithPointers [3]) sparray = {<br/>
- [0] = (x=0x00000001001000f0 -> -1, y=0x0000000100100100 -> -2, z="3")<br/>
- [1] = (x=0x0000000100100120 -> -4, y=0x0000000100100130 -> -5, z="6")<br/>
- [2] = (x=0x0000000100100150 -> -7, y=0x0000000100100160 -> -8, z="9")<br/>
-}<br/>
-</code>
-</p>
- <p>Variable formatting can be set using the <b>type</b> commands:</p>
- <p><code>type format</code></p>
- <p><code>type summary</code></p>
- <p>Each of these commands has four subcommands:</p>
- <p><code>add</code>: adds a new entry</p>
- <p><code>delete</code>: deletes an existing entry</p>
- <p><code>list</code>: provides a listing of all entries</p>
- <p><code>clear</code>: deletes all entries</p>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">type format</h1>
- <div class="postcontent">
-
- <p>Type formats enable you to quickly override the default format for displaying primitive types (the usual basic C/C++/ObjC types: int, float, char, ...).</p>
- <p>LLDB has a list of formatting options available out of which you can pick:</p>
-
- <table border="1">
- <tr valign=top><td width=23%><b>Format name</b></td><td><b>Abbreviation</b></td><td><b>Description</b></td></tr>
- <tr valign=top><td><b>default</b></td><td></td><td>the default LLDB algorithm is used to pick a format</td></tr>
- <tr valign=top><td><b>boolean</b></td><td>B</td><td>show this as a true/false boolean, using the customary rule that 0 is false and everything else is true</td></tr>
- <tr valign=top><td><b>binary</b></td><td>b</td><td>show this as a sequence of bits</td></tr>
- <tr valign=top><td><b>bytes</b></td><td>y</td><td>show the bytes one after the other<br/>e.g. <code>(int) s.x = 07 00 00 00</code></td></tr>
- <tr valign=top><td><b>bytes with ASCII</b></td><td>Y</td><td>show the bytes, but try to print them as ASCII characters<br/>e.g. <code>(int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....</code></td></tr>
- <tr valign=top><td><b>character</b></td><td>c</td><td>show the bytes printed as ASCII characters<br/>e.g. <code>(int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0</code></td></tr>
- <tr valign=top><td><b>printable character</b></td><td>C</td><td>show the bytes printed as printable ASCII characters<br/> e.g. <code>(int *) c.sp.x = P.._....</code></td></tr>
- <tr valign=top><td><b>complex float</b></td><td>F</td><td>interpret this value as the real and imaginary part of a complex floating-point number<br/>e.g. <code>(int *) c.sp.x = 2.76658e+19 + 4.59163e-41i</code></td></tr>
- <tr valign=top><td><b>c-string</b></td><td>s</td><td>show this as a 0-terminated C string</td></tr>
- <tr valign=top><td><b>signed decimal</b></td><td>i</td><td>show this as a signed integer number (this does not perform a cast, it simply shows the bytes as signed integer)</td></tr>
- <tr valign=top><td><b>enumeration</b></td><td>E</td><td>show this as an enumeration, printing the value's name if available or the integer value otherwise<br/>e.g. <code>(enum enumType) val_type = eValue2</code></td></tr>
- <tr valign=top><td><b>hex</b></td><td>x</td><td>show this as in hexadecimal notation (this does not perform a cast, it simply shows the bytes as hex)</td></tr>
- <tr valign=top><td><b>float</b></td><td>f</td><td>show this as a floating-point number (this does not perform a cast, it simply interprets the bytes as an IEEE754 floating-point value)</td></tr>
- <tr valign=top><td><b>octal</b></td><td>o</td><td>show this in octal notation</td></tr>
- <tr valign=top><td><b>OSType</b></td><td>O</td><td>show this as a MacOS OSType<br/>e.g. <code>(float) *c.sp.y = '\n\x1f\xd7\n'</code></td></tr>
- <tr valign=top><td><b>unicode16</b></td><td>U</td><td>show this as UTF-16 characters<br/> e.g. <code>(float) *c.sp.y = 0xd70a 0x411f</code></td></tr>
- <tr valign=top><td><b>unicode32</b></td><td></td><td>show this as UTF-32 characters<br/> e.g. <code>(float) *c.sp.y = 0x411fd70a</code></td></tr>
- <tr valign=top><td><b>unsigned decimal</b></td><td>u</td><td>show this as an unsigned integer number (this does not perform a cast, it simply shows the bytes as unsigned integer)</td></tr>
- <tr valign=top><td><b>pointer</b></td><td>p</td><td>show this as a native pointer (unless this is really a pointer, the resulting address will probably be invalid)</td></tr>
- <tr valign=top><td><b>char[]</b></td><td></td><td>show this as an array of characters<br/>e.g. <code>(char) *c.sp.z = {X}</code></td></tr>
- <tr valign=top><td><b>int8_t[], uint8_t[]<br/>int16_t[], uint16_t[]<br/>int32_t[], uint32_t[]<br/>int64_t[], uint64_t[]<br>uint128_t[]</b></td><td></td><td>show this as an array of the corresponding integer type<br/>e.g.<br/><code>(int) sarray[0].x = {1 0 0 0}</code><br/><code>(int) sarray[0].x = {0x00000001}</code></td></tr>
- <tr valign=top><td><b>float32[], float64[]</b></td><td></td><td>show this as an array of the corresponding floating-point type<br/>e.g. <code>(int *) pointer = {1.46991e-39 1.4013e-45}</code></td></tr>
- <tr valign=top><td><b>complex integer</b></td><td>I</td><td>interpret this value as the real and imaginary part of a complex integer number<br/> e.g. <code>(int *) pointer = 1048960 + 1i</code></td></tr>
- <tr valign=top><td><b>character array</b></td><td>a</td><td>show this as a character array<br/>e.g. <code>(int *) pointer = \x80\x01\x10\0\x01\0\0\0</code></td></tr>
- </table>
-
- <p>Some of the examples shown are willingfully
- unnatural ways to print some values, and meant to
- show that there is no casting or data-loss occurring
- when you change the format of a type. All that lldb
- does when you ask it to change format is reinterpret
- the bytes for display, leaving the original value
- unaltered.</p>
-
- <p>There are two ways to modify the format, one is
- temporary and per-variable, the other is permanent
- and per-type.</p> <p>In the first case you can simply
- use the <code>-f</code> option to <b><code>frame
- variable</code></b>, passing it one of the format
- names or abbreviations in the previous table:</p>
- <p><code>frame variable counter -f hex</code></p>
- <p>This has the effect of displaying the value of
- <code>counter</code> as an hexadecimal number, and
- will keep showing it this way until you either pick a
- different format or a subsequent stoppoint is
- hit.</p> <p>Obviously, if you have two
- <code>int</code> variables, and you format one as
- hex, the other will be left untouched. If for some
- reason, you want all <code>int</code> variables to
- print out as hex, you must add a format to the
- <code>int</code> type.</p> <p>This is done by typing
- <code>type format add -f hex int</code> at the LLDB
- command line.</p> <p>The <code>-f</code> option
- accepts one of the format names or abbreviations, and
- after that you can give out a list of names to which
- you want the new format applied.</p> <p>A frequent
- scenario is that your program has a
- <code>typedef</code> for a numeric type that you know
- represents something that must be printed in a
- certain way. Again, you can add a format just to that
- typedef by using <code>type format add</code> with
- the name alias.</p> <p>But things can quickly get
- hierarchical. Let's say you have a situation like the
- following:</p> <p><code>typedef int A;<br/>typedef A
- B;<br/>typedef B C;<br/>typedef C D;</code></p>
- <p>and you want to show all <code>A</code>s as hex,
- all <code>C</code>s as pointers and leave the
- defaults untouched for other types.</p> <p>If you
- simply type <br/><code>type format add -f hex
- A<br/>type format add -f pointer C</code><br/> values
- of type <code>B</code> will be shown as hex and
- values of type <code>D</code> as pointers.</p>
- <p>This is because by default LLDB <i>cascades</i>
- formats through typedef chains. In order to avoid
- that you can use the option <code>-C no</code> to
- prevent cascading, thus making the two commands
- required to achieve your goal:<br/> <code> type
- format add -f hex -C no A<br/> type format add -f
- pointer -C no C </code></p> <p>Two additional options
- that you will want to look at are <code>-p</code> and
- <code>-r</code>. These two options prevent LLDB from
- applying a format for type <code>T</code> to values
- of type <code>T*</code> and <code>T&</code>
- respectively.</p>
- <p>
- <code>
- <b>(lldb)</b> type format add -f float32[] int<br/>
- <b>(lldb)</b> fr var pointer *pointer -T<br/>
- (int *) pointer = {1.46991e-39 1.4013e-45}<br/>
- (int) *pointer = {1.53302e-42}<br/>
- <b>(lldb)</b> type format add -f float32[] int -p<br/>
- <b>(lldb)</b> fr var pointer *pointer -T<br/>
- (int *) pointer = 0x0000000100100180<br/>
- (int) *pointer = {1.53302e-42}<br/>
- </code>
- </p>
- <p>As the previous example highlights, you will most
- probably want to use <code>-p</code> for your
- formats.</p> <p>If you need to delete a custom format
- simply type <code>type format delete</code> followed
- by the name of the type to which the format applies.
- To delete ALL formats, use <code>type format
- clear</code>. To see all the formats defined, type
- <code>type format list</code>.</p>
-
- </div> <div class="postfooter"></div> </div>
-
- <div class="post"> <h1 class ="postheader">type
- summary</h1> <div class="postcontent">
-
- <p>Type summaries enable you to add more information
- to the default viewing format for a type, or to
- completely replace it with your own display option.
- Unlike formats which only apply to basic types,
- summaries can be used on every type (basic types,
- classes (C++ and Objective-C), arrays, ...).</p>
- <p>The basic idea beneath type summaries is
- extracting information from variables and arranging
- it in a format that is suitable for display:</p> <p>
- <i>before adding a summary...</i><br/> <code> <b>(lldb)</b>
- fr var -T one<br/> (i_am_cool) one = {<br/> (int)
- integer = 3<br/> (float) floating = 3.14159<br/>
- (char) character = 'E'<br/>
- }<br/>
- </code> <br/> <i>after adding a summary...</i><br/>
- <code> <b>(lldb)</b> fr var one<br/> (i_am_cool) one = int
- = 3, float = 3.14159, char = 69<br/> </code> </p>
-
- <p>Evidently, somehow we managed to tell LLDB to grab
- the three member variables of the
- <code>i_am_cool</code> datatype, mix their values
- with some text, and even ask it to display the
- <code>character</code> member using a custom
- format.</p> <p>The way to do this is add a <i>summary
- string</i> to the datatype using the <code>type
- summary add</code> command.</p> <p>Its syntax is
- similar to <code>type format add</code>, but some
- more options are supported that will be described in
- the follow-up.</p> <p>The main option to <code>type
- summary add</code> is <code>-f</code> which accepts
- as parameter a summary string. After that, you can
- type as many type names as you want to associate the
- given summary string to them.</p>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Summary Strings</h1>
- <div class="postcontent">
-
- <p>So what is the format of the summary strings?
- Summary strings can contain plain text, control
- characters and special symbols that have access to
- information about the current object and the overall
- program state.</p>
-
- <p>Normal characters are any text that doesn't
- contain a <code><b>'{'</b></code>,
- <code><b>'}'</b></code>, <code><b>'$'</b></code>, or
- <code><b>'\'</b></code> character.</p>
-
- <p>Variable names are found in between a
- <code><b>"${"</b></code> prefix, and end with a
- <code><b>"}"</b></code> suffix. In other words, a
- variable looks like
- <code>"<b>${frame.pc}</b>"</code>.</p>
-
- <p>Basically, all the variables described in <a
- href="formats.html">Frame and Thread Formatting</a>
- are accepted. Also acceptable are the control
- characters and scoping features described in that
- page. Additionally, <code>${var</code> and
- <code>${*var</code> become acceptable symbols in this
- scenario.</p> <p>The simplest thing you can do is
- grab a member variable of a class or structure by
- typing its <i>expression path</i>. In the previous
- example, the expression path for the floating member
- is simply <code>.floating</code>, because all you
- have to do to get at it given an object of type
- <code>i_am_cool</code> is access it straight away.
- Thus, to ask the summary string to display
- <code>floating</code> you would type
- <code>${var.floating}</code> (<code>${var</code> is a
- placeholder token replaced with whatever variable is
- being displayed).</p> <p>If you have code like the
- following: <br/> <code> struct A {<br/> int x;<br/>
- int y;<br/>
- };<br/>
- struct B {<br/> A x;<br/> A y;<br/> int z;<br/>
- };<br/>
- </code> the expression path for the <code>y</code>
- member of the <code>x</code> member of an object of
- type <code>B</code> would be <code>.x.y</code> and
- you would type <code>${var.x.y}</code> to display it
- in a summary string for type <code>B</code>. </p>
- <p>As you could be using a summary string for both
- displaying objects of type <code>T</code> or
- <code>T*</code> (unless <code>-p</code> is used to
- prevent this), the expression paths do not
- differentiate between <code>.</code> and
- <code>-></code>, and the above expression path
- <code>.x.y</code> would be just as good if you were
- displaying a <code>B*</code>, or even if the actual
- definition of <code>B</code> were:
- <code><br/>
- struct B {<br/>
- A *x;<br/>
- A y;<br/>
- int z;<br/>
- };<br/>
- </code>
- </p>
- <p>This is unlike the behaviour of <code>frame
- variable</code> which, on the contrary, will enforce
- the distinction. As hinted above, the rationale for
- this choice is that waiving this distinction enables
- one to write a summary string once for type
- <code>T</code> and use it for both <code>T</code> and
- <code>T*</code> instances. As a summary string is
- mostly about extracting nested members' information,
- a pointer to an object is just as good as the object
- itself for the purpose.</p>
-
- <p>Of course, you can have multiple entries in one
- summary string. For instance, the command used to
- produce the above summary string for i_am_cool was:
- <br/><code>type summary add -f "int = ${var.integer},
- float = ${var.floating}, char = ${var.character%u}"
- i_am_cool </code> </p> <p>As you can see, the last
- expression path also contains a <code>%u</code>
- symbol which is nowhere to be found in the actual
- member variable name. The symbol is reminding of a
- <code>printf()</code> format symbol, and in fact it
- has a similar effect. If you add a % sign followed by
- any one format name or abbreviation from the above
- table after an expression path, the resulting object
- will be displyed using exactly that format instead of
- the LLDB default one.
- </p>
- <p>There are two more special format symbols that you
- can use only as part of a summary string:
- <code>%V</code> and <code>%@</code>. The first one
- tells LLDB to ignore summary strings for the type of
- the object referred by the expression path and
- instead print the object's value. The second is only
- applicable to Objective-C classes, and tells LLDB to
- get the object's description from the Objective-C
- runtime. By default, if no format is provided, LLDB
- will try to get the object's summary, and if empty
- the object's value. If neither can be obtained,
- nothing will be displayed.</p>
- <p>As previously said, pointers and values are
- treated the same way when getting to their members in
- an expression path. However, if your expression path
- leads to a pointer, LLDB will not automatically
- dereference it. In order to obtain The deferenced
- value for a pointer, your expression path must start
- with <code>${*var</code> instead of
- <code>${var</code>. Because there is no need to
- dereference pointers along your way, the
- dereferencing symbol only applies to the result of
- the whole expression path traversing.
- <br/>
- e.g.
- <code>
- <br/>
- <b>(lldb)</b> fr var -T c<br/>
-(Couple) c = {<br/>
- (SimpleWithPointers) sp = {<br/>
- (int *) x = 0x00000001001000b0<br/>
- (float *) y = 0x00000001001000c0<br/>
- (char *) z = 0x00000001001000d0 "X"<br/>
- }<br/>
- (Simple *) s = 0x00000001001000e0<br/>
-}<br/>
-<b>(lldb)</b> type summary add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = ${*var.s}" Couple<br/>
-<b>(lldb)</b> type summary add -c -p Simple<br/>
-<b>(lldb)</b> fr var c<br/>
-(Couple) c = int = 9, float = 9.99, char = 88, Simple = (x=9, y=9.99, z='X')<br/>
- </code>
- </p>
- <p>Option <code>-c</code> to <code>type summary
- add</code> tells LLDB not to look for a summary
- string, but instead to just print a listing of all
- the object's children on one line, lay out as in the
- previous example. The <code>-p</code> flag is used as
- a trick to show that aggregate types can be
- dereferenced as well as primitive ones. The above
- output would be shown even by typing <code>type
- summary add -f "int = ${*var.sp.x}, float =
- ${*var.sp.y}, char = ${*var.sp.z%u}, Simple =
- ${var.s}" Couple</code> if one took away the
- <code>-p</code> flag from the summary for type
- <code>Simple</code>. </p>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">More on summary strings</h1>
- <div class="postcontent">
-
- <p>What was described above are the main features
- that you can use in summary strings. However, there
- are three more features to them.</p> <p>Sometimes, a
- basic type's value actually represents several
- different values packed together in a bitfield. With
- the classical view, there is no way to look at them.
- Hexadecimal display can help, but if the bits
- actually span byte boundaries, the help is limited.
- Binary view would show it all without ambiguity, but
- is often too detailed and hard to read for real-life
- scenarios. To cope with the issue, LLDB supports
- native bitfield formatting in summary strings. If
- your expression paths leads to a so-called <i>scalar
- type</i> (the usual int, float, char, double, short,
- long, long long, double, long double and unsigned
- variants), you can ask LLDB to only grab some bits
- out of the value and display them in any format you
- like. The syntax is similar to that used for arrays,
- just you can also give a pair of indices separated by
- a <code>-</code>. <br/>
- e.g.
- <br/>
- <code>
- <b>(lldb)</b> fr var float_point<br/>
-(float) float_point = -3.14159<br/>
-<b>(lldb)</b> type summary add -f "Sign: ${var[31]%B} Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" float<br/>
-<b>(lldb)</b> fr var float_point<br/>
-(float) float_point = -3.14159 Sign: true Exponent: 0x00000080 Mantissa: 4788184<br/>
- </code>
- In this example, LLDB shows the internal
- representation of a <code>float</code> variable by
- extracting bitfields out of a float object. If you
- give a single index, only that one bit will be
- extracted. If you give a pair of indices, all the
- bits in the range (extremes included) will be
- extracted. Ranges can be specified either by giving
- the lower index first, or higher index first (as is
- often customary in describing packed data-type
- formats). </p>
- <p>The second additional feature allows you to
- display array members inside a summary string. For
- instance, you may want to display all arrays of a
- given type using a more compact notation than the
- default, and then just delve into individual array
- members that prove interesting to your debugging
- task. You can use a similar syntax to the one used
- for bitfields to tell LLDB to format arrays in
- special ways.
- <br/>
- e.g.
- <br/>
- <code>
- <b>(lldb)</b> fr var sarray<br/>
-(Simple [3]) sarray = {<br/>
- [0] = {<br/>
- x = 1<br/>
- y = 2<br/>
- z = '\x03'<br/>
- }<br/>
- [1] = {<br/>
- x = 4<br/>
- y = 5<br/>
- z = '\x06'<br/>
- }<br/>
- [2] = {<br/>
- x = 7<br/>
- y = 8<br/>
- z = '\t'<br/>
- }<br/>
-}<br/>
-<b>(lldb)</b> type summary add -f "${var[].x}" "Simple [3]"<br/>
-<b>(lldb)</b> fr var sarray<br/>
-(Simple [3]) sarray = [1,4,7]<br/>
- </code>
- The <code>[]</code> symbol amounts to: <i>if
- <code>var</code> is an array and I knows its size,
- apply this summary string to every element of the
- array</i>. Here, we are asking LLDB to display
- <code>.x</code> for every element of the array, and
- in fact this is what happens. If you find some of
- those integers anomalous, you can then inspect that
- one item in greater detail, without the array format
- getting in the way:
- <br/>
- <code>
- <b>(lldb)</b> fr var sarray[1]<br/>
-(Simple) sarray[1] = {<br/>
- x = 4<br/>
- y = 5<br/>
- z = '\x06'<br/>
-}<br/>
- </code>
- </p>
- <p>You can also ask LLDB to only print a subset of
- the array range by using the same syntax used to
- extract bit for bitfields.</p> <p>The same logic
- works if you are printing a pointer instead of an
- array, however in this latter case, <code>[]</code>
- cannot be used and you need to give exact range
- limits.</p> <p>The third, and last, additional
- feature does not directly apply to the summary
- strings themselves, but is an additional option to
- the <code>type summary add</code> command:
- <code>-x</code></p> <p>As you noticed, in order to
- associate the custom summary string to the array
- types, one must give the array size as part of the
- typename. This can long become tiresome when using
- arrays of different sizes, <code>Simple [3]</code>,
- <code>Simple [9]</code>, <code>Simple [12]</code>,
- ...</p> <p>If you use the <code>-x</code> option,
- type names are treated as regular expressions instead
- of type names. This would let you rephrase the above
- example as:
- <br/>
- <code>
-<b>(lldb)</b> type summary add -f "${var[].x}" -x "Simple \[[0-9]+\]"<br/>
-<b>(lldb)</b> fr var sarray<br/>
-(Simple [3]) sarray = [1,4,7]<br/>
- </code>
- The above scenario works for <code>Simple [3]</code>
- as well as for any other array of
- <code>Simple</code> objects. </p> <p>While this
- feature is mostly useful for arrays, you could also
- use regular expressions to catch other type sets
- grouped by name. However, as regular expression
- matching is slower than normal name matching, LLDB
- will first try to match by name in any way it can,
- and only when this fails, will it resort to regular
- expression matching. Thus, if your type has a base
- class with a cascading summary, this will be
- preferred over any regular expression match for your
- type itself.</p>
-
- </div> <div class="postfooter"></div> </div>
-
- <div class="post"> <h1 class ="postheader">Finding
- summaries 101</h1> <div class="postcontent">
-
- <p>While the rules for finding an appropriate
- format for a type are relatively simple (just go
- through typedef hierarchies), summaries follow a
- more complicated process in finding the right
- summary string for a variable. Namely, what
- happens is:</p> <ul> <li>If there is a summary for
- the type of the variable, use it</li> <li>If this
- object is a pointer, and there is a summary for
- the pointee type that does not skip pointers, use
- it</li> <li>If this object is a reference, and
- there is a summary for the pointee type that does
- not skip references, use it</li> <li>If this
- object is an Objective-C class with a parent
- class, look at the parent class (and parent of
- parent, ...)</li> <li>If this object is a C++
- class with base classes, look at base classes (and
- bases of bases, ...)</li> <li>If this object is a
- C++ class with virtual base classes, look at the
- virtual base classes (and bases of bases,
- ...)</li> <li>If this object's type is a typedef,
- go through typedef hierarchy</li> <li>If
- everything has failed, repeat the above search,
- looking for regular expressions instead of exact
- matches</li> </ul> </div> <div
- class="postfooter"></div> </div>
-
- <div class="post"> <h1 class ="postheader">TODOs</h1>
- <div class="postcontent">
-
- <ul> <li>There's no way to do multiple dereferencing,
- and you need to be careful what the dereferencing
- operation is binding to in complicated scenarios</li>
- <li>There is no way to call functions inside summary
- strings, not even <code>const</code> ones</li>
- <li><code>type format add</code> does not support the
- <code>-x</code> option</li> <li>Object location cannot
- be printed in the summary string</li> </ul>
- </div>
- <div class="postfooter"></div>
- </div>
-
- </div>
- </div>
-</div>
-</body>
-</html>
\ No newline at end of file
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;
+ charset=ISO-8859-1">
+ <link href="style.css" rel="stylesheet" type="text/css">
+ <title>LLDB Homepage</title>
+ </head>
+ <body>
+ <div class="www_title"> The <strong>LLDB</strong> Debugger </div>
+ <div id="container">
+ <div id="content">
+ <!--#include virtual="sidebar.incl"-->
+ <div id="middle">
+ <div class="post">
+ <h1 class="postheader">Variable display</h1>
+ <div class="postcontent">
+
+ <p>LLDB was recently modified to allow users to define custom
+ formatting options for the variables display.</p>
+
+ <p>Usually, when you type <code>frame variable</code> or
+ run some <code>expression</code> LLDB will
+ automatically choose a format to display your results on
+ a per-type basis, as in the following example:</p>
+
+ <p> <code> <b>(lldb)</b> frame variable -T sp<br>
+ (SimpleWithPointers) sp = {<br>
+ (int *) x = 0x0000000100100120<br>
+ (float *) y =
+ 0x0000000100100130<br>
+ (char *) z =
+ 0x0000000100100140 "6"<br>
+ }<br>
+ </code> </p>
+
+ <p>However, in certain cases, you may want to associate a
+ different format to the display for certain datatypes.
+ To do so, you need to give hints to the debugger as to
+ how datatypes should be displayed.<br>
+ A new <b>type</b> command has been introduced in LLDB
+ which allows to do just that.<br>
+ </p>
+
+ <p>Using it you can obtain a format like this one for <code>sp</code>,
+ instead of the default shown above: </p>
+
+ <p> <code> <b>(lldb)</b> frame variable sp<br>
+ (SimpleWithPointers) sp =
+ (x=0x0000000100100120 -> -1, y=0x0000000100100130
+ -> -2, z="3")<br>
+ </code> </p>
+
+ <p>There are two kinds of printing options: <span
+ style="font-style: italic;">summary</span> and <span
+ style="font-style: italic;">format</span>. While a
+ detailed description of both will be given below, one
+ can briefly say that a summary is mainly used for
+ aggregate types, while a format is attached to primitive
+ types.</p>
+
+ <p>To reflect this, the the <b>type</b> command has two
+ subcommands:<br>
+ </p>
+
+ <p><code>type format</code></p>
+ <p><code>type summary</code></p>
+
+ <p>These commands are meant to bind printing options to
+ types. When variables are printed, LLDB will first check
+ if custom printing options have been associated to a
+ variable's type and, if so, use them instead of picking
+ the default choices.<br>
+ </p>
+
+ <p>The two commands <code>type format</code> and <code>type
+ summary</code> each have four subcommands:<br>
+ </p>
+ <p><code>add</code>: associates a new printing option to one
+ or more types</p>
+ <p><code>delete</code>: deletes an existing association</p>
+ <p><code>list</code>: provides a listing of all
+ associations</p>
+ <p><code>clear</code>: deletes all associations</p>
+ </div>
+ </div>
+
+ <div class="post">
+ <h1 class="postheader">type format</h1>
+ <div class="postcontent">
+
+ <p>Type formats enable you to quickly override the default
+ format for displaying primitive types (the usual basic
+ C/C++/ObjC types: int, float, char, ...).</p>
+
+ <p>If for some reason you want all <code>int</code>
+ variables in your program to print out as hex, you can add
+ a format to the <code>int</code> type.<br></p>
+
+ <p>This is done by typing <code>type format add -f hex
+ int</code> at the LLDB command line.</p>
+
+ <p>The <code>-f</code> option accepts a <a
+ href="#formatstable">format name</a>, and a list of
+ types to which you want the new format applied.</p>
+
+ <p>A frequent scenario is that your program has a <code>typedef</code>
+ for a numeric type that you know represents something
+ that must be printed in a certain way. Again, you can
+ add a format just to that typedef by using <code>type
+ format add</code> with the name alias.</p>
+
+ <p>But things can quickly get hierarchical. Let's say you
+ have a situation like the following:</p>
+
+ <p><code>typedef int A;<br>
+ typedef A B;<br>
+ typedef B C;<br>
+ typedef C D;<br>
+ </code></p>
+
+ <p>and you want to show all <code>A</code>'s as hex, all
+ <code>C'</code>s as pointers and leave the defaults
+ untouched for other types.</p>
+
+ <p>If you simply type <br>
+ <code>type format add -f hex A<br>
+ type format add -f pointer C</code><br>
+ <br>
+ values of type <code>B</code> will be shown as hex
+ and values of type <code>D</code> as pointers.</p>
+
+ <p>This is because by default LLDB <i>cascades</i>
+ formats through typedef chains. In order to avoid that
+ you can use the option <code>-C no</code> to prevent
+ cascading, thus making the two commands required to
+ achieve your goal:<br>
+ <code> type format add -f hex -C no A<br>
+ type format add -f pointer -C no C </code></p>
+
+ <p>Two additional options that you will want to look at
+ are <code>-p</code> and <code>-r</code>. These two
+ options prevent LLDB from applying a format for type <code>T</code>
+ to values of type <code>T*</code> and <code>T&</code>
+ respectively.</p>
+
+ <p> <code> <b>(lldb)</b> type format add -f float32[]
+ int<br>
+ <b>(lldb)</b> fr var pointer *pointer -T<br>
+ (int *) pointer = {1.46991e-39 1.4013e-45}<br>
+ (int) *pointer = {1.53302e-42}<br>
+ <b>(lldb)</b> type format add -f float32[] int -p<br>
+ <b>(lldb)</b> fr var pointer *pointer -T<br>
+ (int *) pointer = 0x0000000100100180<br>
+ (int) *pointer = {1.53302e-42}<br>
+ </code> </p>
+
+ <p>As the previous example highlights, you will most
+ probably want to use <code>-p</code> for your formats.</p>
+
+ <p>If you need to delete a custom format simply type <code>type
+ format delete</code> followed by the name of the type
+ to which the format applies. To delete ALL formats, use
+ <code>type format clear</code>. To see all the formats
+ defined, type <code>type format list</code>.<br>
+ </p>
+
+ <p>If all you need to do, however, is display one variable
+ in a custom format, while leaving the others of the same
+ type untouched, you can simply type:<br>
+ <br>
+ <code>frame variable counter -f hex</code></p>
+
+ <p>This has the effect of displaying the value of <code>counter</code>
+ as an hexadecimal number, and will keep showing it this
+ way until you either pick a different format or till you
+ let your program run again.</p>
+
+ <p>Finally, this is a list of formatting options available
+ out of
+ which you can pick:</p><a name="formatstable"></a>
+ <table border="1">
+ <tbody>
+ <tr valign="top">
+ <td width="23%"><b>Format name</b></td>
+ <td><b>Abbreviation</b></td>
+ <td><b>Description</b></td>
+ </tr>
+ <tr valign="top">
+ <td><b>default</b></td>
+ <td><br>
+ </td>
+ <td>the default LLDB algorithm is used to pick a
+ format</td>
+ </tr>
+ <tr valign="top">
+ <td><b>boolean</b></td>
+ <td>B</td>
+ <td>show this as a true/false boolean, using the
+ customary rule that 0 is false and everything else
+ is true</td>
+ </tr>
+ <tr valign="top">
+ <td><b>binary</b></td>
+ <td>b</td>
+ <td>show this as a sequence of bits</td>
+ </tr>
+ <tr valign="top">
+ <td><b>bytes</b></td>
+ <td>y</td>
+ <td>show the bytes one after the other<br>
+ e.g. <code>(int) s.x = 07 00 00 00</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>bytes with ASCII</b></td>
+ <td>Y</td>
+ <td>show the bytes, but try to print them as ASCII
+ characters<br>
+ e.g. <code>(int *) c.sp.x = 50 f8 bf 5f ff 7f 00
+ 00 P.._....</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>character</b></td>
+ <td>c</td>
+ <td>show the bytes printed as ASCII characters<br>
+ e.g. <code>(int *) c.sp.x =
+ P\xf8\xbf_\xff\x7f\0\0</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>printable character</b></td>
+ <td>C</td>
+ <td>show the bytes printed as printable ASCII
+ characters<br>
+ e.g. <code>(int *) c.sp.x = P.._....</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>complex float</b></td>
+ <td>F</td>
+ <td>interpret this value as the real and imaginary
+ part of a complex floating-point number<br>
+ e.g. <code>(int *) c.sp.x = 2.76658e+19 +
+ 4.59163e-41i</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>c-string</b></td>
+ <td>s</td>
+ <td>show this as a 0-terminated C string</td>
+ </tr>
+ <tr valign="top">
+ <td><b>signed decimal</b></td>
+ <td>i</td>
+ <td>show this as a signed integer number (this does
+ not perform a cast, it simply shows the bytes as
+ signed integer)</td>
+ </tr>
+ <tr valign="top">
+ <td><b>enumeration</b></td>
+ <td>E</td>
+ <td>show this as an enumeration, printing the
+ value's name if available or the integer value
+ otherwise<br>
+ e.g. <code>(enum enumType) val_type = eValue2</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>hex</b></td>
+ <td>x</td>
+ <td>show this as in hexadecimal notation (this does
+ not perform a cast, it simply shows the bytes as
+ hex)</td>
+ </tr>
+ <tr valign="top">
+ <td><b>float</b></td>
+ <td>f</td>
+ <td>show this as a floating-point number (this does
+ not perform a cast, it simply interprets the bytes
+ as an IEEE754 floating-point value)</td>
+ </tr>
+ <tr valign="top">
+ <td><b>octal</b></td>
+ <td>o</td>
+ <td>show this in octal notation</td>
+ </tr>
+ <tr valign="top">
+ <td><b>OSType</b></td>
+ <td>O</td>
+ <td>show this as a MacOS OSType<br>
+ e.g. <code>(float) *c.sp.y = '\n\x1f\xd7\n'</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>unicode16</b></td>
+ <td>U</td>
+ <td>show this as UTF-16 characters<br>
+ e.g. <code>(float) *c.sp.y = 0xd70a 0x411f</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>unicode32</b></td>
+ <td><br>
+ </td>
+ <td>show this as UTF-32 characters<br>
+ e.g. <code>(float) *c.sp.y = 0x411fd70a</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>unsigned decimal</b></td>
+ <td>u</td>
+ <td>show this as an unsigned integer number (this
+ does not perform a cast, it simply shows the bytes
+ as unsigned integer)</td>
+ </tr>
+ <tr valign="top">
+ <td><b>pointer</b></td>
+ <td>p</td>
+ <td>show this as a native pointer (unless this is
+ really a pointer, the resulting address will
+ probably be invalid)</td>
+ </tr>
+ <tr valign="top">
+ <td><b>char[]</b></td>
+ <td><br>
+ </td>
+ <td>show this as an array of characters<br>
+ e.g. <code>(char) *c.sp.z = {X}</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>int8_t[], uint8_t[]<br>
+ int16_t[], uint16_t[]<br>
+ int32_t[], uint32_t[]<br>
+ int64_t[], uint64_t[]<br>
+ uint128_t[]</b></td>
+ <td><br>
+ </td>
+ <td>show this as an array of the corresponding
+ integer type<br>
+ e.g.<br>
+ <code>(int) sarray[0].x = {1 0 0 0}</code><br>
+ <code>(int) sarray[0].x = {0x00000001}</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>float32[], float64[]</b></td>
+ <td><br>
+ </td>
+ <td>show this as an array of the corresponding
+ floating-point type<br>
+ e.g. <code>(int *) pointer = {1.46991e-39
+ 1.4013e-45}</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>complex integer</b></td>
+ <td>I</td>
+ <td>interpret this value as the real and imaginary
+ part of a complex integer number<br>
+ e.g. <code>(int *) pointer = 1048960 + 1i</code></td>
+ </tr>
+ <tr valign="top">
+ <td><b>character array</b></td>
+ <td>a</td>
+ <td>show this as a character array<br>
+ e.g. <code>(int *) pointer =
+ \x80\x01\x10\0\x01\0\0\0</code></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="post">
+ <h1 class="postheader">type summary</h1>
+ <div class="postcontent">
+ <p>Type summaries enable you to add more information to
+ the default viewing format for a type, or to completely
+ replace it with your own display option. Unlike formats
+ which only apply to basic types, summaries can be used
+ on every type (basic types, classes (C++ and
+ Objective-C), arrays, ...).</p>
+ <p>The basic idea beneath type summaries is extracting
+ information from variables and arranging it in a format
+ that is suitable for display:</p>
+ <p> <i>before adding a summary...</i><br>
+ <code> <b>(lldb)</b> fr var -T one<br>
+ (i_am_cool) one = {<br>
+ (int) integer = 3<br>
+ (float) floating = 3.14159<br>
+ (char) character = 'E'<br>
+ }<br>
+ </code> <br>
+ <i>after adding a summary...</i><br>
+ <code> <b>(lldb)</b> fr var one<br>
+ (i_am_cool) one = int = 3, float = 3.14159, char = 69<br>
+ </code> </p>
+ <p>Evidently, somehow we managed to tell LLDB to grab the
+ three member variables of the <code>i_am_cool</code>
+ datatype, mix their values with some text, and even ask
+ it to display the <code>character</code> member using a
+ custom format.</p>
+ <p>The way to do this is add a <i>summary string</i> to
+ the datatype using the <code>type summary add</code>
+ command.</p>
+ <p>Its syntax is similar to <code>type format add</code>,
+ but some more options are supported that will be
+ described in the follow-up.</p>
+ <p>The main option to <code>type summary add</code> is <code>-f</code>
+ which accepts as parameter a summary string. After that,
+ you can type as many type names as you want to associate
+ the given summary string to them.</p>
+ </div>
+ </div>
+ <div class="post">
+ <h1 class="postheader">Summary Strings</h1>
+ <div class="postcontent">
+ <p>So what is the format of the summary strings? Summary
+ strings can contain plain text, control characters and
+ special symbols that have access to information about
+ the current object and the overall program state.</p>
+ <p>Normal characters are any text that doesn't contain a <code><b>'{'</b></code>,
+ <code><b>'}'</b></code>, <code><b>'$'</b></code>, or <code><b>'\'</b></code>
+ character.</p>
+ <p>Variable names are found in between a <code><b>"${"</b></code>
+ prefix, and end with a <code><b>"}"</b></code> suffix.
+ In other words, a variable looks like <code>"<b>${frame.pc}</b>"</code>.</p>
+ <p>Basically, all the variables described in <a
+ href="formats.html">Frame and Thread Formatting</a>
+ are accepted. Also acceptable are the control characters
+ and scoping features described in that page.
+ Additionally, <code>${var</code> and <code>${*var</code>
+ become acceptable symbols in this scenario.</p>
+ <p>The simplest thing you can do is grab a member variable
+ of a class or structure by typing its <i>expression
+ path</i>. In the previous example, the expression path
+ for the floating member is simply <code>.floating</code>,
+ because all you have to do to get at it given an object
+ of type <code>i_am_cool</code> is access it straight
+ away. Thus, to ask the summary string to display <code>floating</code>
+ you would type <code>${var.floating}</code> (<code>${var</code>
+ is a placeholder token replaced with whatever variable
+ is being displayed).</p>
+ <p>If you have code like the following: <br>
+ <code> struct A {<br>
+ int x;<br>
+ int y;<br>
+ };<br>
+ struct B {<br>
+ A x;<br>
+ A y;<br>
+ int z;<br>
+ };<br>
+ </code> the expression path for the <code>y</code>
+ member of the <code>x</code> member of an object of
+ type <code>B</code> would be <code>.x.y</code> and you
+ would type <code>${var.x.y}</code> to display it in a
+ summary string for type <code>B</code>. </p>
+ <p>As you could be using a summary string for both
+ displaying objects of type <code>T</code> or <code>T*</code>
+ (unless <code>-p</code> is used to prevent this), the
+ expression paths do not differentiate between <code>.</code>
+ and <code>-></code>, and the above expression path <code>.x.y</code>
+ would be just as good if you were displaying a <code>B*</code>,
+ or even if the actual definition of <code>B</code>
+ were: <code><br>
+ struct B {<br>
+ A *x;<br>
+ A y;<br>
+ int z;<br>
+ };<br>
+ </code> </p>
+ <p>This is unlike the behaviour of <code>frame variable</code>
+ which, on the contrary, will enforce the distinction. As
+ hinted above, the rationale for this choice is that
+ waiving this distinction enables one to write a summary
+ string once for type <code>T</code> and use it for both
+ <code>T</code> and <code>T*</code> instances. As a
+ summary string is mostly about extracting nested
+ members' information, a pointer to an object is just as
+ good as the object itself for the purpose.</p>
+ <p>Of course, you can have multiple entries in one summary
+ string. For instance, the command used to produce the
+ above summary string for i_am_cool was: <br>
+ <code>type summary add -f "int = ${var.integer}, float =
+ ${var.floating}, char = ${var.character%u}" i_am_cool
+ </code> </p>
+ <p>As you can see, the last expression path also contains
+ a <code>%u</code> symbol which is nowhere to be found
+ in the actual member variable name. The symbol is
+ reminding of a <code>printf()</code> format symbol, and
+ in fact it has a similar effect. If you add a % sign
+ followed by any one format name or abbreviation from the
+ above table after an expression path, the resulting
+ object will be displyed using exactly that format
+ instead of the LLDB default one. </p>
+ <p>There are two more special format symbols that you can
+ use only as part of a summary string: <code>%V</code>
+ and <code>%@</code>. The first one tells LLDB to ignore
+ summary strings for the type of the object referred by
+ the expression path and instead print the object's
+ value. The second is only applicable to Objective-C
+ classes, and tells LLDB to get the object's description
+ from the Objective-C runtime. By default, if no format
+ is provided, LLDB will try to get the object's summary,
+ and if empty the object's value. If neither can be
+ obtained, nothing will be displayed.</p>
+ <p>As previously said, pointers and values are treated the
+ same way when getting to their members in an expression
+ path. However, if your expression path leads to a
+ pointer, LLDB will not automatically dereference it. In
+ order to obtain The deferenced value for a pointer, your
+ expression path must start with <code>${*var</code>
+ instead of <code>${var</code>. Because there is no need
+ to dereference pointers along your way, the
+ dereferencing symbol only applies to the result of the
+ whole expression path traversing. <br>
+ e.g. <code> <br>
+ <b>(lldb)</b> fr var -T c<br>
+ (Couple) c = {<br>
+ (SimpleWithPointers) sp = {<br>
+ (int *) x = 0x00000001001000b0<br>
+ (float *) y = 0x00000001001000c0<br>
+ (char *) z = 0x00000001001000d0 "X"<br>
+ }<br>
+ (Simple *) s = 0x00000001001000e0<br>
+ }<br>
+ <b>(lldb)</b> type summary add -f "int = ${*var.sp.x},
+ float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple =
+ ${*var.s}" Couple<br>
+ <b>(lldb)</b> type summary add -c -p Simple<br>
+ <b>(lldb)</b> fr var c<br>
+ (Couple) c = int = 9, float = 9.99, char = 88, Simple
+ = (x=9, y=9.99, z='X')<br>
+ </code> </p>
+ <p>Option <code>-c</code> to <code>type summary add</code>
+ tells LLDB not to look for a summary string, but instead
+ to just print a listing of all the object's children on
+ one line, lay out as in the previous example. The <code>-p</code>
+ flag is used as a trick to show that aggregate types can
+ be dereferenced as well as primitive ones. The above
+ output would be shown even by typing <code>type summary
+ add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char
+ = ${*var.sp.z%u}, Simple = ${var.s}" Couple</code> if
+ one took away the <code>-p</code> flag from the summary
+ for type <code>Simple</code>. </p>
+ </div>
+ </div>
+ <div class="post">
+ <h1 class="postheader">More on summary strings</h1>
+ <div class="postcontent">
+ <p>What was described above are the main features that you
+ can use in summary strings. However, there are three
+ more features to them.</p>
+ <p>Sometimes, a basic type's value actually represents
+ several different values packed together in a bitfield.
+ With the classical view, there is no way to look at
+ them. Hexadecimal display can help, but if the bits
+ actually span byte boundaries, the help is limited.
+ Binary view would show it all without ambiguity, but is
+ often too detailed and hard to read for real-life
+ scenarios. To cope with the issue, LLDB supports native
+ bitfield formatting in summary strings. If your
+ expression paths leads to a so-called <i>scalar type</i>
+ (the usual int, float, char, double, short, long, long
+ long, double, long double and unsigned variants), you
+ can ask LLDB to only grab some bits out of the value and
+ display them in any format you like. The syntax is
+ similar to that used for arrays, just you can also give
+ a pair of indices separated by a <code>-</code>. <br>
+ e.g. <br>
+ <code> <b>(lldb)</b> fr var float_point<br>
+ (float) float_point = -3.14159<br>
+ <b>(lldb)</b> type summary add -f "Sign: ${var[31]%B}
+ Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}"
+ float<br>
+ <b>(lldb)</b> fr var float_point<br>
+ (float) float_point = -3.14159 Sign: true Exponent:
+ 0x00000080 Mantissa: 4788184<br>
+ </code> In this example, LLDB shows the internal
+ representation of a <code>float</code> variable by
+ extracting bitfields out of a float object. If you give
+ a single index, only that one bit will be extracted. If
+ you give a pair of indices, all the bits in the range
+ (extremes included) will be extracted. Ranges can be
+ specified either by giving the lower index first, or
+ higher index first (as is often customary in describing
+ packed data-type formats). </p>
+ <p>The second additional feature allows you to display
+ array members inside a summary string. For instance, you
+ may want to display all arrays of a given type using a
+ more compact notation than the default, and then just
+ delve into individual array members that prove
+ interesting to your debugging task. You can use a
+ similar syntax to the one used for bitfields to tell
+ LLDB to format arrays in special ways. <br>
+ e.g. <br>
+ <code> <b>(lldb)</b> fr var sarray<br>
+ (Simple [3]) sarray = {<br>
+ [0] = {<br>
+ x = 1<br>
+ y = 2<br>
+ z = '\x03'<br>
+ }<br>
+ [1] = {<br>
+ x = 4<br>
+ y = 5<br>
+ z = '\x06'<br>
+ }<br>
+ [2] = {<br>
+ x = 7<br>
+ y = 8<br>
+ z = '\t'<br>
+ }<br>
+ }<br>
+ <b>(lldb)</b> type summary add -f "${var[].x}" "Simple
+ [3]"<br>
+ <b>(lldb)</b> fr var sarray<br>
+ (Simple [3]) sarray = [1,4,7]<br>
+ </code> The <code>[]</code> symbol amounts to: <i>if <code>var</code>
+ is an array and I knows its size, apply this summary
+ string to every element of the array</i>. Here, we are
+ asking LLDB to display <code>.x</code> for every
+ element of the array, and in fact this is what happens.
+ If you find some of those integers anomalous, you can
+ then inspect that one item in greater detail, without
+ the array format getting in the way: <br>
+ <code> <b>(lldb)</b> fr var sarray[1]<br>
+ (Simple) sarray[1] = {<br>
+ x = 4<br>
+ y = 5<br>
+ z = '\x06'<br>
+ }<br>
+ </code> </p>
+ <p>You can also ask LLDB to only print a subset of the
+ array range by using the same syntax used to extract bit
+ for bitfields.</p>
+ <p>The same logic works if you are printing a pointer
+ instead of an array, however in this latter case, <code>[]</code>
+ cannot be used and you need to give exact range limits.</p>
+ <p>The third, and last, additional feature does not
+ directly apply to the summary strings themselves, but is
+ an additional option to the <code>type summary add</code>
+ command: <code>-x</code></p>
+ <p>As you noticed, in order to associate the custom
+ summary string to the array types, one must give the
+ array size as part of the typename. This can long become
+ tiresome when using arrays of different sizes, <code>Simple
+
+ [3]</code>, <code>Simple [9]</code>, <code>Simple
+ [12]</code>, ...</p>
+ <p>If you use the <code>-x</code> option, type names are
+ treated as regular expressions instead of type names.
+ This would let you rephrase the above example as: <br>
+ <code> <b>(lldb)</b> type summary add -f "${var[].x}"
+ -x "Simple \[[0-9]+\]"<br>
+ <b>(lldb)</b> fr var sarray<br>
+ (Simple [3]) sarray = [1,4,7]<br>
+ </code> The above scenario works for <code>Simple [3]</code>
+ as well as for any other array of <code>Simple</code>
+ objects. </p>
+ <p>While this feature is mostly useful for arrays, you
+ could also use regular expressions to catch other type
+ sets grouped by name. However, as regular expression
+ matching is slower than normal name matching, LLDB will
+ first try to match by name in any way it can, and only
+ when this fails, will it resort to regular expression
+ matching. Thus, if your type has a base class with a
+ cascading summary, this will be preferred over any
+ regular expression match for your type itself.</p>
+ </div>
+ </div>
+ <div class="post">
+ <h1 class="postheader">Finding summaries 101</h1>
+ <div class="postcontent">
+ <p>While the rules for finding an appropriate format for a
+ type are relatively simple (just go through typedef
+ hierarchies), summaries follow a more complicated
+ process in finding the right summary string for a
+ variable. Namely, what happens is:</p>
+ <ul>
+ <li>If there is a summary for the type of the variable,
+ use it</li>
+ <li>If this object is a pointer, and there is a summary
+ for the pointee type that does not skip pointers, use
+ it</li>
+ <li>If this object is a reference, and there is a
+ summary for the pointee type that does not skip
+ references, use it</li>
+ <li>If this object is an Objective-C class with a parent
+ class, look at the parent class (and parent of parent,
+ ...)</li>
+ <li>If this object is a C++ class with base classes,
+ look at base classes (and bases of bases, ...)</li>
+ <li>If this object is a C++ class with virtual base
+ classes, look at the virtual base classes (and bases
+ of bases, ...)</li>
+ <li>If this object's type is a typedef, go through
+ typedef hierarchy</li>
+ <li>If everything has failed, repeat the above search,
+ looking for regular expressions instead of exact
+ matches</li>
+ </ul>
+ </div>
+ </div>
+ <div class="post">
+ <h1 class="postheader">TODOs</h1>
+ <div class="postcontent">
+ <ul>
+ <li>There's no way to do multiple dereferencing, and you
+ need to be careful what the dereferencing operation is
+ binding to in complicated scenarios</li>
+ <li>There is no way to call functions inside summary
+ strings, not even <code>const</code> ones</li>
+ <li><code>type format add</code> does not support the <code>-x</code>
+ option</li>
+ <li>Object location cannot be printed in the summary
+ string</li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
More information about the lldb-commits
mailing list