11import gdb
22
33
4+ def deconstruct_dstring (val ):
5+ # ideally, we want to access the memory where the string
6+ # is stored directly instead of calling a function. However,
7+ # this is simpler.
8+ try :
9+ raw_address = str (val .address )
10+
11+ # If it's ::empty, we know it's empty without going further.
12+ if "::empty" in raw_address :
13+ return - 1 , ""
14+
15+ # Split the address on the first space, return that value
16+ # Addresses are usually {address} {optional type_name}
17+ typed_pointer = "((const {} *){})" .format (val .type , raw_address .split (None , 1 )[0 ])
18+
19+ string_no = val ["no" ]
20+
21+ # Check that the pointer is not null.
22+ null_ptr = gdb .parse_and_eval ("{} == 0" .format (typed_pointer ))
23+ if null_ptr .is_optimized_out :
24+ return - 1 , "{}: <Ptr optimized out>" .format (string_no )
25+ if null_ptr :
26+ return - 1 , ""
27+
28+ table_len = gdb .parse_and_eval ("get_string_container().string_vector.size()" )
29+ if table_len .is_optimized_out :
30+ return - 1 , "{}: <Table len optimized out>" .format (string_no )
31+ if string_no >= table_len :
32+ return - 1 , "{} index ({}) out of range" .format (val .type , string_no )
33+
34+ value = gdb .parse_and_eval ("{}->c_str()" .format (typed_pointer ))
35+ if value .is_optimized_out :
36+ return - 1 , "{}: <Optimized out>" .format (string_no )
37+ return string_no , value .string ().replace ("\0 " , "" )
38+ except :
39+ return - 1 , ""
40+
441# Class for pretty-printing dstringt
542class DStringPrettyPrinter :
643 "Print a dstringt"
@@ -9,44 +46,87 @@ def __init__(self, val):
946 self .val = val
1047
1148 def to_string (self ):
12- # ideally, we want to access the memory where the string
13- # is stored directly instead of calling a function. However,
14- # this is simpler.
49+ string_no , value = deconstruct_dstring (self .val )
50+ if string_no == - 1 :
51+ return value
52+ return "{}: \" {}\" " .format (string_no , value .replace ("\" " , "\\ \" " ))
53+
54+ def display_hint (self ):
55+ return None
56+
57+
58+ def find_type (type , name ):
59+ type = type .strip_typedefs ()
60+ while True :
61+ # Strip cv-qualifiers.
62+ search = "%s::%s" % (type .unqualified (), name )
1563 try :
16- raw_address = str (self .val .address )
64+ return gdb .lookup_type (search )
65+ except RuntimeError :
66+ pass
67+ # The type was not found, so try the superclass.
68+ # We only need to check the first superclass.
69+ type = type .fields ()[0 ].type
70+
1771
18- # If it's ::empty, we know it's empty without going further.
19- if "::empty" in raw_address :
20- return ""
21-
22- # Split the address on the first space, return that value
23- # Addresses are usually {address} {optional type_name}
24- typed_pointer = "((const {} *){})" .format (self .val .type , raw_address .split (None , 1 )[0 ])
25-
26- string_no = self .val ["no" ]
27-
28- # Check that the pointer is not null.
29- null_ptr = gdb .parse_and_eval ("{} == 0" .format (typed_pointer ))
30- if null_ptr .is_optimized_out :
31- return "{}: <Ptr optimized out>" .format (string_no )
32- if null_ptr :
33- return ""
34-
35- table_len = gdb .parse_and_eval ("get_string_container().string_vector.size()" )
36- if table_len .is_optimized_out :
37- return "{}: <Table len optimized out>" .format (string_no )
38- if string_no >= table_len :
39- return "{} index ({}) out of range" .format (self .val .type , string_no )
40-
41- value = gdb .parse_and_eval ("{}->c_str()" .format (typed_pointer ))
42- if value .is_optimized_out :
43- return "{}: <Optimized out>" .format (string_no )
44- return "{}: \" {}\" " .format (string_no , value .string ().replace ("\0 " , "" ).replace ("\" " , "\\ \" " ))
72+ class IrepPrettyPrinter :
73+ "Print an irept"
74+
75+ def __init__ (self , val ):
76+ self .val = val ["data" ].referenced_value ()
77+
78+ def to_string (self ):
79+ try :
80+ return "\" {}\" " .format (deconstruct_dstring (self .val ["data" ])[1 ].replace ("\" " , "\\ \" " ))
4581 except :
46- return ""
82+ return "Exception pretty printing irept"
83+
84+ def children (self ):
85+ sub = self .val ["sub" ]
86+ count = 0
87+ item = sub ["_M_impl" ]["_M_start" ]
88+ finish = sub ["_M_impl" ]["_M_finish" ]
89+ while item != finish :
90+ yield "sub %d key" % count , "sub[%d]" % count
91+ yield "sub %d value" % count , item .dereference ()
92+ count += 1
93+ item += 1
94+
95+ named_sub = self .val ["named_sub" ]
96+ size = named_sub ["_M_t" ]["_M_impl" ]["_M_node_count" ]
97+ node = named_sub ["_M_t" ]["_M_impl" ]["_M_header" ]["_M_left" ]
98+ count = 0
99+ while count != size :
100+ rep_type = find_type (named_sub .type , "_Rep_type" )
101+ link_type = find_type (rep_type , "_Link_type" )
102+ node_type = link_type .strip_typedefs ()
103+ current = node .cast (node_type ).dereference ()
104+ addr_type = current .type .template_argument (0 ).pointer ()
105+ result = current ["_M_storage" ]["_M_storage" ].address .cast (addr_type ).dereference ()
106+ yield "named_sub %d key" % count , "named_sub[\" %s\" ]" % deconstruct_dstring (result ["first" ])[1 ].replace ("\" " , "\\ \" " )
107+ yield "named_sub %d value" % count , result ["second" ]
108+ count += 1
109+ if count < size :
110+ # Get the next node
111+ right = node .dereference ()["_M_right" ]
112+ if right :
113+ node = right
114+ while True :
115+ left = node .dereference ()["_M_left" ]
116+ if not left :
117+ break
118+ node = left
119+ else :
120+ parent = node .dereference ()["_M_parent" ]
121+ while node == parent .dereference ()["_M_right" ]:
122+ node = parent
123+ parent = parent .dereference ()["_M_parent" ]
124+ # Not sure what this checks
125+ if node .dereference ()["_M_right" ] != parent :
126+ node = parent
47127
48128 def display_hint (self ):
49- return None
129+ return "map"
50130
51131
52132class InstructionPrettyPrinter :
0 commit comments