Miscellaneous fixes for big-endian systems

This patch fixes a bunch of issues that show up on big-endian systems:

- The gnu_libstdcpp.py script doesn't follow the way libstdc++ encodes
  bit vectors: it should identify the enclosing *word* and then access
  the appropriate bit within that word.  Instead, the script simply
  operates on bytes.  This gives the same result on little-endian
  systems, but not on big-endian.

- lldb_private::formatters::WCharSummaryProvider always assumes wchar_t
  is UTF16, even though it could also be UTF8 or UTF32.  This is mostly
  not an issue on little-endian systems, but immediately fails on BE.
  Fixed by checking the size of wchar_t like WCharStringSummaryProvider
  already does.

- ClangASTContext::GetChildCompilerTypeAtIndex uses uint32_t to access
  the virtual base offset stored in the vtable, even though the size
  of this field matches the target pointer size according to the C++
  ABI.  Again, this is mostly not visible on LE, but fails on BE.

- Process::ReadStringFromMemory uses strncmp to search for a terminator
  consisting of multiple zero bytes.  This doesn't work since strncmp
  will stop already at the first zero byte.  Use memcmp instead.

Differential Revision: http://reviews.llvm.org/D18983

llvm-svn: 266313
This commit is contained in:
Ulrich Weigand 2016-04-14 14:33:47 +00:00
parent 461bd680c3
commit 0501eebda6
4 changed files with 31 additions and 9 deletions

View File

@ -237,11 +237,12 @@ class StdVectorSynthProvider:
def get_child_at_index(self, index):
if index >= self.num_children():
return None
byte_offset = index / 8
bit_offset = index % 8
element_size = self.start_p.GetType().GetPointeeType().GetByteSize()
data = self.start_p.GetPointeeData(byte_offset / element_size)
bit = data.GetUnsignedInt8(lldb.SBError(), byte_offset % element_size) & (1 << bit_offset)
element_type = self.start_p.GetType().GetPointeeType()
element_bits = 8 * element_type.GetByteSize()
element_offset = index / element_bits
bit_offset = index % element_bits
element = self.start_p.CreateChildAtOffset('['+str(index)+']',element_offset,element_type)
bit = element.GetValueAsUnsigned(0) & (1 << bit_offset)
if bit != 0:
value_expr = "(bool)true"
else:

View File

@ -192,6 +192,14 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str
if (error.Fail())
return false;
// Get a wchar_t basic type from the current type system
CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
if (!wchar_compiler_type)
return false;
const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
options.SetData(data);
options.SetStream(&stream);
@ -200,5 +208,17 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str
options.SetSourceSize(1);
options.SetBinaryZeroIsTerminator(false);
return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
switch (wchar_size)
{
case 8:
return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
case 16:
return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
case 32:
return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
default:
stream.Printf("size for wchar_t is not valid");
return true;
}
return true;
}

View File

@ -6075,8 +6075,9 @@ ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type,
{
clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl);
const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity();
const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
if (base_offset != UINT32_MAX)
const uint32_t base_offset_size = process->GetAddressByteSize();
const uint64_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, base_offset_size, UINT32_MAX, err);
if (base_offset < UINT32_MAX)
{
handled = true;
bit_offset = base_offset * 8;

View File

@ -2437,7 +2437,7 @@ Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error &
// Search for a null terminator of correct size and alignment in bytes_read
size_t aligned_start = total_bytes_read - total_bytes_read % type_width;
for (size_t i = aligned_start; i + type_width <= total_bytes_read + bytes_read; i += type_width)
if (::strncmp(&dst[i], terminator, type_width) == 0)
if (::memcmp(&dst[i], terminator, type_width) == 0)
{
error.Clear();
return i;