forked from qt-creator/qt-creator
Debugger: libc++ 16 dumper for string
Change-Id: Ic3eed66d7af54a0251ec58886b68dda611682bef Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -5,6 +5,7 @@ from stdtypes import qdump__std__array, qdump__std__complex, qdump__std__once_fl
|
|||||||
from utils import DisplayFormat
|
from utils import DisplayFormat
|
||||||
from dumper import Children, DumperBase
|
from dumper import Children, DumperBase
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
def qform__std____1__array():
|
def qform__std____1__array():
|
||||||
return [DisplayFormat.ArrayPlot]
|
return [DisplayFormat.ArrayPlot]
|
||||||
@@ -163,231 +164,114 @@ def qdump__std____1__stack(d, value):
|
|||||||
d.putBetterType(value.type)
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
def GetChildMemberWithName(value, name):
|
|
||||||
members = value.members(True)
|
|
||||||
|
|
||||||
for member in members:
|
# Examples for std::__1::string layouts for libcxx version 16
|
||||||
if member.name == name:
|
#
|
||||||
return member
|
# std::string b = "asd"
|
||||||
return None
|
#
|
||||||
|
# b = {
|
||||||
|
# static __endian_factor = 2,
|
||||||
def GetIndexOfChildWithName(value, name):
|
# __r_ = {
|
||||||
members = value.members(True)
|
# <std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {
|
||||||
|
# __value_ = {{
|
||||||
for i, member in enumerate(members):
|
# __l = {
|
||||||
if member.name == name:
|
# {__is_long_ = 0, __cap_ = 842641539},
|
||||||
return i
|
# __size_ = 140737353746888,
|
||||||
return None
|
# __data_ = 0x7ffff7fa0a20 <std::__1::codecvt<wchar_t, char, __mbstate_t>::id> \"\\377\\377\\377\\377\\377\\377\\377\\377\\006\"
|
||||||
|
# },
|
||||||
|
# __s = {
|
||||||
class StringLayout:
|
# {__is_long_ = 0 '\\000', __size_ = 3 '\\003'},
|
||||||
CSD = 0
|
# __padding_ = 0x7fffffffd859 \"asd\",
|
||||||
DSC = 1
|
# __data_ = \"asd\\000\\000\\000\\000\\310\\t\\372\\367\\377\\177\\000\\000 \\n\\372\\367\\377\\177\\000\"
|
||||||
|
# },
|
||||||
|
# __r = {
|
||||||
def std_1_string_dumper_v2(d, value):
|
# __words = {1685283078, 140737353746888, 140737353746976}
|
||||||
charType = value['__l']['__data_'].dereference().type
|
# }
|
||||||
|
# }}
|
||||||
R = GetChildMemberWithName(value, "__r_")
|
# },
|
||||||
if not R:
|
# <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {
|
||||||
raise Exception("Could not find __r_")
|
# <std::__1::allocator<char>> = {
|
||||||
|
# <std::__1::__non_trivial_if<true, std::__1::allocator<char> >> = {
|
||||||
# __r_ is a compressed_pair of the actual data and the allocator. The data we
|
# <No data fields>
|
||||||
# want is in the first base class.
|
# },
|
||||||
R_Base_SP = R[0]
|
# <No data fields>
|
||||||
|
# },
|
||||||
if not R_Base_SP:
|
# <No data fields>
|
||||||
raise Exception("Could not find R_Base_SP")
|
# },
|
||||||
|
# <No data fields>
|
||||||
Rep_Sp = GetChildMemberWithName(R_Base_SP, "__value_")
|
# },
|
||||||
|
# static npos = 18446744073709551615
|
||||||
if not Rep_Sp:
|
# }
|
||||||
raise Exception("Could not find __value_")
|
#
|
||||||
|
#
|
||||||
# Our layout seems a little different
|
# std::string c = "asdlonasdlongstringasdlongstringasdlongstringasdlongstringgstring"
|
||||||
Rep_Sp = Rep_Sp[0]
|
#
|
||||||
|
# c = {
|
||||||
if not Rep_Sp:
|
# static __endian_factor = 2,
|
||||||
raise Exception("Could not find Rep_Sp")
|
# __r_ = {
|
||||||
|
# <std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {
|
||||||
L = GetChildMemberWithName(Rep_Sp, "__l")
|
# __value_ = {{
|
||||||
|
# __l = {
|
||||||
if not L:
|
# {__is_long_ = 1, __cap_ = 40}, # size_type: __cap_
|
||||||
raise Exception("Could not find __l")
|
# __size_ = 65,
|
||||||
|
# __data_ = 0x5555555592a0 \"asdlonasdlongstringasdlongstringasdlongstringasdlongstringgstring\"
|
||||||
layout = StringLayout.CSD
|
# },
|
||||||
if GetIndexOfChildWithName(L, "__data_") == 0:
|
# __s = {
|
||||||
layout = StringLayout.DSC
|
# {__is_long_ = 1 '\\001', __size_ = 40 '('},
|
||||||
|
# __padding_ = 0x7fffffffd831 \"\", __data_ = \"\\000\\000\\000\\000\\000\\000\\000A\\000\\000\\000\\000\\000\\000\\000\\240\\222UUUU\\000\"
|
||||||
short_mode = False
|
# },
|
||||||
using_bitmasks = True
|
# __r = {
|
||||||
size = 0
|
# __words = {81, 65, 93824992252576}
|
||||||
size_mode_value = 0
|
# }
|
||||||
|
# }}
|
||||||
Short_Sp = GetChildMemberWithName(Rep_Sp, "__s")
|
# },
|
||||||
if not Short_Sp:
|
# <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {
|
||||||
raise Exception("Could not find __s")
|
# <std::__1::allocator<char>> = {
|
||||||
|
# <std::__1::__non_trivial_if<true, std::__1::allocator<char> >> = {
|
||||||
Is_Long = GetChildMemberWithName(Short_Sp, "__is_long_")
|
# <No data fields>
|
||||||
Size_Sp = GetChildMemberWithName(Short_Sp, "__size_")
|
# },
|
||||||
if not Size_Sp:
|
# <No data fields>
|
||||||
raise Exception("Could not find __size_")
|
# },
|
||||||
|
# <No data fields
|
||||||
if Is_Long:
|
# >},
|
||||||
using_bitmasks = False
|
# <No data fields>
|
||||||
short_mode = Is_Long.integer() == 0
|
# },
|
||||||
size = Size_Sp.integer()
|
# static npos = 18446744073709551615
|
||||||
else:
|
# }"
|
||||||
size_mode_value = Size_Sp.integer()
|
|
||||||
mode_mask = 1
|
|
||||||
if layout == StringLayout.DSC:
|
|
||||||
mode_mask = 0x80
|
|
||||||
short_mode = (size_mode_value & mode_mask) == 0
|
|
||||||
|
|
||||||
if short_mode:
|
|
||||||
Location_Sp = GetChildMemberWithName(Short_Sp, "__data_")
|
|
||||||
|
|
||||||
if using_bitmasks:
|
|
||||||
size = ((size_mode_value >> 1) % 256)
|
|
||||||
if layout == StringLayout.DSC:
|
|
||||||
size = size_mode_value
|
|
||||||
|
|
||||||
# The string is most likely not initialized yet
|
|
||||||
if size > 100 or not Location_Sp:
|
|
||||||
raise Exception("Probably not initialized yet")
|
|
||||||
|
|
||||||
d.putCharArrayHelper(d.extractPointer(Location_Sp), size,
|
|
||||||
charType, d.currentItemFormat())
|
|
||||||
return
|
|
||||||
|
|
||||||
Location_Sp = GetChildMemberWithName(L, "__data_")
|
|
||||||
Size_Vo = GetChildMemberWithName(L, "__size_")
|
|
||||||
Capacity_Vo = GetChildMemberWithName(L, "__cap_")
|
|
||||||
|
|
||||||
if not Location_Sp or not Size_Vo or not Capacity_Vo:
|
|
||||||
raise Exception("Could not find Location_Sp, Size_Vo or Capacity_Vo")
|
|
||||||
|
|
||||||
size = Size_Vo.integer()
|
|
||||||
capacity = Capacity_Vo.integer()
|
|
||||||
if not using_bitmasks and layout == StringLayout.CSD:
|
|
||||||
capacity *= 2
|
|
||||||
if capacity < size:
|
|
||||||
raise Exception("Capacity is less than size")
|
|
||||||
|
|
||||||
d.putCharArrayHelper(d.extractPointer(Location_Sp), size,
|
|
||||||
charType, d.currentItemFormat())
|
|
||||||
|
|
||||||
|
|
||||||
def std_1_string_dumper_v1(d, value):
|
|
||||||
charType = value['__l']['__data_'].dereference().type
|
|
||||||
D = None
|
|
||||||
|
|
||||||
if d.isLldb:
|
|
||||||
D = value[0][0][0][0]
|
|
||||||
elif d.isGdb:
|
|
||||||
D = value["__r_"].members(True)[0][0][0]
|
|
||||||
else:
|
|
||||||
raise Exception("Unknown debugger (neither gdb nor lldb)")
|
|
||||||
|
|
||||||
layoutDecider = D[0][0]
|
|
||||||
if not layoutDecider:
|
|
||||||
raise Exception("Could not find layoutDecider")
|
|
||||||
|
|
||||||
size = 0
|
|
||||||
size_mode_value = 0
|
|
||||||
short_mode = False
|
|
||||||
libcxx_version = 14
|
|
||||||
|
|
||||||
layoutModeIsDSC = layoutDecider.name == '__data_'
|
|
||||||
if (layoutModeIsDSC):
|
|
||||||
size_mode = D[1][1][0]
|
|
||||||
if not size_mode:
|
|
||||||
raise Exception("Could not find size_mode")
|
|
||||||
if not size_mode.name == '__size_':
|
|
||||||
size_mode = D[1][1][1]
|
|
||||||
if not size_mode:
|
|
||||||
raise Exception("Could not find size_mode")
|
|
||||||
|
|
||||||
size_mode_value = size_mode.integer()
|
|
||||||
short_mode = ((size_mode_value & 0x80) == 0)
|
|
||||||
else:
|
|
||||||
size_mode = D[1][0][0]
|
|
||||||
if not size_mode:
|
|
||||||
raise Exception("Could not find size_mode")
|
|
||||||
|
|
||||||
if size_mode.name == '__is_long_':
|
|
||||||
libcxx_version = 15
|
|
||||||
short_mode = (size_mode.integer() == 0)
|
|
||||||
|
|
||||||
size_mode = D[1][0][1]
|
|
||||||
size_mode_value = size_mode.integer()
|
|
||||||
else:
|
|
||||||
size_mode_value = size_mode.integer()
|
|
||||||
short_mode = ((size_mode_value & 1) == 0)
|
|
||||||
|
|
||||||
if short_mode:
|
|
||||||
s = D[1]
|
|
||||||
|
|
||||||
if not s:
|
|
||||||
raise Exception("Could not find s")
|
|
||||||
|
|
||||||
if libcxx_version == 14:
|
|
||||||
location_sp = s[0] if layoutModeIsDSC else s[1]
|
|
||||||
size = size_mode_value if layoutModeIsDSC else ((size_mode_value >> 1) % 256)
|
|
||||||
elif libcxx_version == 15:
|
|
||||||
location_sp = s[0] if layoutModeIsDSC else s[2]
|
|
||||||
size = size_mode_value
|
|
||||||
|
|
||||||
else:
|
|
||||||
l = D[0]
|
|
||||||
if not l:
|
|
||||||
raise Exception("Could not find l")
|
|
||||||
|
|
||||||
# we can use the layout_decider object as the data pointer
|
|
||||||
location_sp = layoutDecider if layoutModeIsDSC else l[2]
|
|
||||||
size_vo = l[1]
|
|
||||||
if not size_vo or not location_sp:
|
|
||||||
raise Exception("Could not find size_vo or location_sp")
|
|
||||||
size = size_vo.integer()
|
|
||||||
|
|
||||||
if short_mode and location_sp:
|
|
||||||
d.putCharArrayHelper(d.extractPointer(location_sp), size,
|
|
||||||
charType, d.currentItemFormat())
|
|
||||||
else:
|
|
||||||
d.putCharArrayHelper(location_sp.integer(),
|
|
||||||
size, charType, d.currentItemFormat())
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def qdump__std____1__string(d, value):
|
def qdump__std____1__string(d, value):
|
||||||
try:
|
charType = value.type[0]
|
||||||
std_1_string_dumper_v2(d, value)
|
blob = bytes(value.data())
|
||||||
except Exception as eV2:
|
r0, r1, r2 = struct.unpack(d.packCode + 'QQQ', blob)
|
||||||
try:
|
if d.isLldb and d.isArmMac:
|
||||||
std_1_string_dumper_v1(d, value)
|
is_long = r2 >> 63
|
||||||
except Exception as eV1:
|
if is_long:
|
||||||
d.putValue("Could not parse: %s, %s" % (eV1, eV2))
|
# [---------------- data ptr ---------------] 63:0
|
||||||
|
# [------------------ size ----------------]
|
||||||
|
# [?---------------- alloc ----------------]
|
||||||
def qdump__std____1__wstring(d, value):
|
data = r0
|
||||||
try:
|
size = r1
|
||||||
std_1_string_dumper_v2(d, value)
|
else:
|
||||||
except Exception as eV2:
|
# [------------------- data ----------------] 63:0
|
||||||
try:
|
# [------------------- data ----------------]
|
||||||
std_1_string_dumper_v1(d, value)
|
# [?ssss-------------- data ----------------]
|
||||||
except Exception as eV1:
|
data = value.laddress
|
||||||
d.putValue("Could not parse: %s, %s" % (eV1, eV2))
|
size = (r2 >> 56) & 255
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__basic_string(d, value):
|
|
||||||
innerType = value.type[0].name
|
|
||||||
if innerType in ("char", "char8_t", "char16_t"):
|
|
||||||
qdump__std____1__string(d, value)
|
|
||||||
elif innerType in ("wchar_t", "char32_t"):
|
|
||||||
qdump__std____1__wstring(d, value)
|
|
||||||
else:
|
else:
|
||||||
d.warn("UNKNOWN INNER TYPE %s" % innerType)
|
is_long = r0 & 1
|
||||||
|
if is_long:
|
||||||
|
# [------------------ alloc ---------------?] 63:0
|
||||||
|
# [------------------- size ----------------]
|
||||||
|
# [----------------- data ptr --------------]
|
||||||
|
data = r2
|
||||||
|
size = r1
|
||||||
|
else:
|
||||||
|
# [------------------- data ----------sssss?] 63:0
|
||||||
|
# [------------------- data ----------------]
|
||||||
|
# [------------------- data ----------------]
|
||||||
|
data = value.laddress + charType.size()
|
||||||
|
size = (r0 & 255) // 2
|
||||||
|
d.putCharArrayHelper(data, size, charType)
|
||||||
|
|
||||||
|
|
||||||
def qdump__std____1__shared_ptr(d, value):
|
def qdump__std____1__shared_ptr(d, value):
|
||||||
|
@@ -1312,6 +1312,8 @@ class Dumper(DumperBase):
|
|||||||
self.reportResult('error="No frame"', args)
|
self.reportResult('error="No frame"', args)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.isArmMac = frame.module.triple.startswith('arm64-apple')
|
||||||
|
|
||||||
self.output = []
|
self.output = []
|
||||||
isPartial = len(self.partialVariable) > 0
|
isPartial = len(self.partialVariable) > 0
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user