diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -555,6 +555,7 @@ /// Determine the size in bytes of \p valobj (a libc++ std::string object) and /// extract its data payload. Return the size + payload pair. +// TODO: Support big-endian architectures. static llvm::Optional> ExtractLibcxxStringInfo(ValueObject &valobj) { ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0})); @@ -572,14 +573,27 @@ ConstString g_size_name("__size_"); bool short_mode = false; // this means the string is in short-mode and the // data is stored inline + bool using_bitmasks = true; // Whether the class uses bitmasks for the mode + // flag (pre-D123580). + uint64_t size; LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; uint64_t size_mode_value = 0; - if (layout == eLibcxxStringLayoutModeDSC) { + if (ValueObjectSP is_long = D->GetChildAtNamePath( + {ConstString("__s"), ConstString("__is_long_")})) { + using_bitmasks = false; + short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0); + if (ValueObjectSP size_member = + D->GetChildAtNamePath({ConstString("__s"), ConstString("__size_")})) + size = size_member->GetValueAsUnsigned(/*fail_value=*/0); + else + return {}; + } else if (layout == eLibcxxStringLayoutModeDSC) { llvm::SmallVector size_mode_locations[] = { - {1, 2}, // Post-c3d0205ee771 layout + {1, 2}, // Post-c3d0205ee771 layout. This was in use for only a brief + // period, so we can delete it if it becomes a burden. {1, 1, 0}, {1, 1, 1}, }; @@ -610,9 +624,10 @@ return {}; ValueObjectSP location_sp = s->GetChildAtIndex( (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); - const uint64_t size = (layout == eLibcxxStringLayoutModeDSC) - ? size_mode_value - : ((size_mode_value >> 1) % 256); + if (using_bitmasks) + size = (layout == eLibcxxStringLayoutModeDSC) + ? size_mode_value + : ((size_mode_value >> 1) % 256); // When the small-string optimization takes place, the data must fit in the // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's @@ -631,18 +646,18 @@ if (!l) return {}; // we can use the layout_decider object as the data pointer - ValueObjectSP location_sp = (layout == eLibcxxStringLayoutModeDSC) - ? layout_decider - : l->GetChildAtIndex(2, true); - ValueObjectSP size_vo(l->GetChildAtIndex(1, true)); - const unsigned capacity_index = - (layout == eLibcxxStringLayoutModeDSC) ? 2 : 0; - ValueObjectSP capacity_vo(l->GetChildAtIndex(capacity_index, true)); + ValueObjectSP location_sp = + l->GetChildMemberWithName(ConstString("__data_"), /*can_create=*/true); + ValueObjectSP size_vo = + l->GetChildMemberWithName(ConstString("__size_"), /*can_create=*/true); + ValueObjectSP capacity_vo = + l->GetChildMemberWithName(ConstString("__cap_"), /*can_create=*/true); if (!size_vo || !location_sp || !capacity_vo) return {}; - const uint64_t size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET); - const uint64_t capacity = - capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET); + size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET); + uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET); + if (!using_bitmasks && layout == eLibcxxStringLayoutModeCSD) + capacity *= 2; if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET || capacity < size) return {};