summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/ValueObject.cpp
diff options
context:
space:
mode:
authorEnrico Granata <granata.enrico@gmail.com>2011-07-12 22:56:10 +0000
committerEnrico Granata <granata.enrico@gmail.com>2011-07-12 22:56:10 +0000
commitf4efecd9587a54e331e14b90f53ef9f2bdfcfc93 (patch)
treedc88ed6dcb21a374f270d88684ca781e7cc49f46 /lldb/source/Core/ValueObject.cpp
parent5d11676eef4727474e6141e390c8fd20a54f1e1a (diff)
downloadbcm5719-llvm-f4efecd9587a54e331e14b90f53ef9f2bdfcfc93.tar.gz
bcm5719-llvm-f4efecd9587a54e331e14b90f53ef9f2bdfcfc93.zip
smarter summary strings:
- formats %s %char[] %c and %a now work to print 0-terminated c-strings if they are applied to a char* or char[] even without the [] operator (e.g. ${var%s}) - array formats (char[], intN[], ..) now work when applied to an array of a scalar type even without the [] operator (e.g. ${var%int32_t[]}) LLDB will not crash because of endless loop when trying to obtain a summary for an object that has no value and references itself in its summary string In many cases, a wrong summary string will now display an "<error>" message instead of giving out an empty string llvm-svn: 135007
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r--lldb/source/Core/ValueObject.cpp190
1 files changed, 154 insertions, 36 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index d39b836f021..d8e0e0f8ef8 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -40,8 +40,11 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RefCounter.h"
+
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_utility;
static lldb::user_id_t g_value_obj_uid = 0;
@@ -78,7 +81,8 @@ ValueObject::ValueObject (ValueObject &parent) :
m_last_format_mgr_revision(0),
m_last_summary_format(),
m_last_value_format(),
- m_forced_summary_format()
+ m_forced_summary_format(),
+ m_dump_printable_counter(0)
{
m_manager->ManageObject(this);
}
@@ -116,7 +120,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) :
m_last_format_mgr_revision(0),
m_last_summary_format(),
m_last_value_format(),
- m_forced_summary_format()
+ m_forced_summary_format(),
+ m_dump_printable_counter(0)
{
m_manager = new ValueObjectManager();
m_manager->ManageObject (this);
@@ -752,11 +757,13 @@ ValueObject::IsCStringContainer(bool check_pointer)
void
ValueObject::ReadPointedString(Stream& s,
Error& error,
- uint32_t max_length)
+ uint32_t max_length,
+ bool honor_array,
+ lldb::Format item_format)
{
if (max_length == 0)
- max_length = 128; // this should be a setting, or a formatting parameter
+ max_length = 128; // FIXME this should be a setting, or a formatting parameter
clang_type_t clang_type = GetClangType();
clang_type_t elem_or_pointee_clang_type;
@@ -781,14 +788,10 @@ ValueObject::ReadPointedString(Stream& s,
{
// We have an array
cstr_len = ClangASTContext::GetArraySize (clang_type);
- if (cstr_len > max_length) // TODO: make cap a setting
+ if (cstr_len > max_length)
{
- cstr_len = ClangASTContext::GetArraySize (clang_type);
- if (cstr_len > max_length) // TODO: make cap a setting
- {
- capped_data = true;
- cstr_len = max_length;
- }
+ capped_data = true;
+ cstr_len = max_length;
}
cstr_address = GetAddressOf (cstr_address_type, true);
}
@@ -803,9 +806,8 @@ ValueObject::ReadPointedString(Stream& s,
DataExtractor data;
size_t bytes_read = 0;
std::vector<char> data_buffer;
- Error error;
bool prefer_file_cache = false;
- if (cstr_len > 0)
+ if (cstr_len > 0 && honor_array)
{
data_buffer.resize(cstr_len);
data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder());
@@ -819,7 +821,7 @@ ValueObject::ReadPointedString(Stream& s,
s << '"';
data.Dump (&s,
0, // Start offset in "data"
- eFormatCharArray, // Print as characters
+ item_format,
1, // Size of item (1 byte for a char!)
bytes_read, // How many bytes to print?
UINT32_MAX, // num per line
@@ -833,7 +835,8 @@ ValueObject::ReadPointedString(Stream& s,
}
else
{
- const size_t k_max_buf_size = 256;
+ cstr_len = max_length;
+ const size_t k_max_buf_size = 64;
data_buffer.resize (k_max_buf_size + 1);
// NULL terminate in case we don't get the entire C string
data_buffer.back() = '\0';
@@ -852,10 +855,12 @@ ValueObject::ReadPointedString(Stream& s,
break;
if (len > bytes_read)
len = bytes_read;
+ if (len > cstr_len)
+ len = cstr_len;
data.Dump (&s,
0, // Start offset in "data"
- eFormatCharArray, // Print as characters
+ item_format,
1, // Size of item (1 byte for a char!)
len, // How many bytes to print?
UINT32_MAX, // num per line
@@ -865,6 +870,12 @@ ValueObject::ReadPointedString(Stream& s,
if (len < k_max_buf_size)
break;
+ if (len >= cstr_len)
+ {
+ s << "...";
+ break;
+ }
+ cstr_len -= len;
cstr_so_addr.Slide (k_max_buf_size);
}
s << '"';
@@ -1016,6 +1027,9 @@ const char *
ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,
lldb::Format custom_format)
{
+
+ RefCounter ref(&m_dump_printable_counter);
+
if(custom_format != lldb::eFormatInvalid)
SetFormat(custom_format);
@@ -1034,18 +1048,18 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_d
break;
}
- if (!return_value)
+ // this code snippet might lead to endless recursion, thus we use a RefCounter here to
+ // check that we are not looping endlessly
+ if (!return_value && (m_dump_printable_counter < 3))
{
// try to pick the other choice
if (val_obj_display == eDisplayValue)
return_value = GetSummaryAsCString();
else if (val_obj_display == eDisplaySummary)
return_value = GetValueAsCString();
- else
- return_value = "";
}
- return (return_value ? return_value : "");
+ return (return_value ? return_value : "<error>");
}
@@ -1054,25 +1068,129 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
ValueObjectRepresentationStyle val_obj_display,
lldb::Format custom_format)
{
+
+ clang_type_t elem_or_pointee_type;
+ Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type));
- if (IsCStringContainer(true) &&
- val_obj_display == ValueObject::eDisplayValue &&
- custom_format == lldb::eFormatCString)
+ if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer)
+ && val_obj_display == ValueObject::eDisplayValue)
{
- Error error;
- ReadPointedString(s, error);
- return error.Success();
- }
- else
- {
- const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format);
- if(targetvalue)
- s.PutCString(targetvalue);
- bool var_success = (targetvalue != NULL);
- if(custom_format != eFormatInvalid)
- SetFormat(eFormatDefault);
- return var_success;
+ // when being asked to get a printable display an array or pointer type directly,
+ // try to "do the right thing"
+
+ if (IsCStringContainer(true) &&
+ (custom_format == lldb::eFormatCString ||
+ custom_format == lldb::eFormatCharArray ||
+ custom_format == lldb::eFormatChar ||
+ custom_format == lldb::eFormatVectorOfChar)) // print char[] & char* directly
+ {
+ Error error;
+ ReadPointedString(s,
+ error,
+ 0,
+ (custom_format == lldb::eFormatVectorOfChar) ||
+ (custom_format == lldb::eFormatCharArray));
+ return !error.Fail();
+ }
+
+ if (custom_format == lldb::eFormatEnum)
+ return false;
+
+ // this only works for arrays, because I have no way to know when
+ // the pointed memory ends, and no special \0 end of data marker
+ if (flags.Test(ClangASTContext::eTypeIsArray))
+ {
+ if ((custom_format == lldb::eFormatBytes) ||
+ (custom_format == lldb::eFormatBytesWithASCII))
+ {
+ uint32_t count = GetNumChildren();
+
+ s << '[';
+ for (uint32_t low = 0; low < count; low++)
+ {
+
+ if (low)
+ s << ',';
+
+ ValueObjectSP child = GetChildAtIndex(low,true);
+ if (!child.get())
+ {
+ s << "<error>";
+ continue;
+ }
+ child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, custom_format);
+ }
+
+ s << ']';
+
+ return true;
+ }
+
+ if ((custom_format == lldb::eFormatVectorOfChar) ||
+ (custom_format == lldb::eFormatVectorOfFloat32) ||
+ (custom_format == lldb::eFormatVectorOfFloat64) ||
+ (custom_format == lldb::eFormatVectorOfSInt16) ||
+ (custom_format == lldb::eFormatVectorOfSInt32) ||
+ (custom_format == lldb::eFormatVectorOfSInt64) ||
+ (custom_format == lldb::eFormatVectorOfSInt8) ||
+ (custom_format == lldb::eFormatVectorOfUInt128) ||
+ (custom_format == lldb::eFormatVectorOfUInt16) ||
+ (custom_format == lldb::eFormatVectorOfUInt32) ||
+ (custom_format == lldb::eFormatVectorOfUInt64) ||
+ (custom_format == lldb::eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly
+ {
+ uint32_t count = GetNumChildren();
+
+ lldb::Format format = FormatManager::GetSingleItemFormat(custom_format);
+
+ s << '[';
+ for (uint32_t low = 0; low < count; low++)
+ {
+
+ if (low)
+ s << ',';
+
+ ValueObjectSP child = GetChildAtIndex(low,true);
+ if (!child.get())
+ {
+ s << "<error>";
+ continue;
+ }
+ child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, format);
+ }
+
+ s << ']';
+
+ return true;
+ }
+ }
+
+ if ((custom_format == lldb::eFormatBoolean) ||
+ (custom_format == lldb::eFormatBinary) ||
+ (custom_format == lldb::eFormatChar) ||
+ (custom_format == lldb::eFormatCharPrintable) ||
+ (custom_format == lldb::eFormatComplexFloat) ||
+ (custom_format == lldb::eFormatDecimal) ||
+ (custom_format == lldb::eFormatHex) ||
+ (custom_format == lldb::eFormatFloat) ||
+ (custom_format == lldb::eFormatOctal) ||
+ (custom_format == lldb::eFormatOSType) ||
+ (custom_format == lldb::eFormatUnicode16) ||
+ (custom_format == lldb::eFormatUnicode32) ||
+ (custom_format == lldb::eFormatUnsigned) ||
+ (custom_format == lldb::eFormatPointer) ||
+ (custom_format == lldb::eFormatComplexInteger) ||
+ (custom_format == lldb::eFormatComplex) ||
+ (custom_format == lldb::eFormatDefault)) // use the [] operator
+ return false;
}
+ const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format);
+ if(targetvalue)
+ s.PutCString(targetvalue);
+ bool var_success = (targetvalue != NULL);
+ if(custom_format != eFormatInvalid)
+ SetFormat(eFormatDefault);
+ return var_success;
}
addr_t
OpenPOWER on IntegriCloud