Skip to content

Add a pretty printer for irept #4960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 113 additions & 33 deletions scripts/pretty-printers/gdb/pretty_printers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
import gdb


def deconstruct_dstring(val):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ Probably would have been easier to review if the refactoring of printing dstring was separate to the introduction of irep printing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be slightly overkill - the changes can be read top-to-bottom - only the last hunk is not related to this refactoring.

# ideally, we want to access the memory where the string
# is stored directly instead of calling a function. However,
# this is simpler.
try:
raw_address = str(val.address)

# If it's ::empty, we know it's empty without going further.
if "::empty" in raw_address:
return -1, ""

# Split the address on the first space, return that value
# Addresses are usually {address} {optional type_name}
typed_pointer = "((const {} *){})".format(val.type, raw_address.split(None, 1)[0])

string_no = val["no"]

# Check that the pointer is not null.
null_ptr = gdb.parse_and_eval("{} == 0".format(typed_pointer))
if null_ptr.is_optimized_out:
return -1, "{}: <Ptr optimized out>".format(string_no)
if null_ptr:
return -1, ""

table_len = gdb.parse_and_eval("get_string_container().string_vector.size()")
if table_len.is_optimized_out:
return -1, "{}: <Table len optimized out>".format(string_no)
if string_no >= table_len:
return -1, "{} index ({}) out of range".format(val.type, string_no)

value = gdb.parse_and_eval("{}->c_str()".format(typed_pointer))
if value.is_optimized_out:
return -1, "{}: <Optimized out>".format(string_no)
return string_no, value.string().replace("\0", "")
except:
return -1, ""

# Class for pretty-printing dstringt
class DStringPrettyPrinter:
"Print a dstringt"
Expand All @@ -9,44 +46,87 @@ def __init__(self, val):
self.val = val

def to_string(self):
# ideally, we want to access the memory where the string
# is stored directly instead of calling a function. However,
# this is simpler.
string_no, value = deconstruct_dstring(self.val)
if string_no == -1:
return value
return "{}: \"{}\"".format(string_no, value.replace("\"", "\\\""))

def display_hint(self):
return None


def find_type(type, name):
type = type.strip_typedefs()
while True:
# Strip cv-qualifiers.
search = "%s::%s" % (type.unqualified(), name)
try:
raw_address = str(self.val.address)
return gdb.lookup_type(search)
except RuntimeError:
pass
# The type was not found, so try the superclass.
# We only need to check the first superclass.
type = type.fields()[0].type


# If it's ::empty, we know it's empty without going further.
if "::empty" in raw_address:
return ""

# Split the address on the first space, return that value
# Addresses are usually {address} {optional type_name}
typed_pointer = "((const {} *){})".format(self.val.type, raw_address.split(None, 1)[0])

string_no = self.val["no"]

# Check that the pointer is not null.
null_ptr = gdb.parse_and_eval("{} == 0".format(typed_pointer))
if null_ptr.is_optimized_out:
return "{}: <Ptr optimized out>".format(string_no)
if null_ptr:
return ""

table_len = gdb.parse_and_eval("get_string_container().string_vector.size()")
if table_len.is_optimized_out:
return "{}: <Table len optimized out>".format(string_no)
if string_no >= table_len:
return "{} index ({}) out of range".format(self.val.type, string_no)

value = gdb.parse_and_eval("{}->c_str()".format(typed_pointer))
if value.is_optimized_out:
return "{}: <Optimized out>".format(string_no)
return "{}: \"{}\"".format(string_no, value.string().replace("\0", "").replace("\"", "\\\""))
class IrepPrettyPrinter:
"Print an irept"

def __init__(self, val):
self.val = val["data"].referenced_value()

def to_string(self):
try:
return "\"{}\"".format(deconstruct_dstring(self.val["data"])[1].replace("\"", "\\\""))
except:
return ""
return "Exception pretty printing irept"

def children(self):
sub = self.val["sub"]
count = 0
item = sub["_M_impl"]["_M_start"]
finish = sub["_M_impl"]["_M_finish"]
while item != finish:
yield "sub %d key" % count, "sub[%d]" % count
yield "sub %d value" % count, item.dereference()
count += 1
item += 1

named_sub = self.val["named_sub"]
size = named_sub["_M_t"]["_M_impl"]["_M_node_count"]
node = named_sub["_M_t"]["_M_impl"]["_M_header"]["_M_left"]
count = 0
while count != size:
rep_type = find_type(named_sub.type, "_Rep_type")
link_type = find_type(rep_type, "_Link_type")
node_type = link_type.strip_typedefs()
current = node.cast(node_type).dereference()
addr_type = current.type.template_argument(0).pointer()
result = current["_M_storage"]["_M_storage"].address.cast(addr_type).dereference()
yield "named_sub %d key" % count, "named_sub[\"%s\"]" % deconstruct_dstring(result["first"])[1].replace("\"", "\\\"")
yield "named_sub %d value" % count, result["second"]
count += 1
if count < size:
# Get the next node
right = node.dereference()["_M_right"]
if right:
node = right
while True:
left = node.dereference()["_M_left"]
if not left:
break
node = left
else:
parent = node.dereference()["_M_parent"]
while node == parent.dereference()["_M_right"]:
node = parent
parent = parent.dereference()["_M_parent"]
# Not sure what this checks
if node.dereference()["_M_right"] != parent:
node = parent

def display_hint(self):
return None
return "map"


class InstructionPrettyPrinter:
Expand Down