// this function abstracts away the layout and mode details of a libc++ string // and returns the address of the data and the size ready for callers to consume static bool ExtractLibcxxStringInfo (ValueObject& valobj, ValueObjectSP &location_sp, uint64_t& size) { ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0})); if (!D) return false; ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0})); // this child should exist if (!layout_decider) return false; ConstString g_data_name("__data_"); ConstString g_size_name("__size_"); bool short_mode = false; // this means the string is in short-mode and the data is stored inline LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; uint64_t size_mode_value = 0; if (layout == eLibcxxStringLayoutModeDSC) { ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0})); if (!size_mode) return false; if (size_mode->GetName() != g_size_name) { // we are hitting the padding structure, move along size_mode = D->GetChildAtIndexPath({1,1,1}); if (!size_mode) return false; } size_mode_value = (size_mode->GetValueAsUnsigned(0)); short_mode = ((size_mode_value & 0x80) == 0); } else { ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0})); if (!size_mode) return false; size_mode_value = (size_mode->GetValueAsUnsigned(0)); short_mode = ((size_mode_value & 1) == 0); } if (short_mode) { ValueObjectSP s(D->GetChildAtIndex(1, true)); if (!s) return false; location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256); return (location_sp.get() != nullptr); } else {