Skip to content
Open
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions gdb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,12 @@ def __str__(self) -> str:
if type_flags & lldb.eTypeIsPointer:
return "0x%x" % self._as_number()

# Check for synthetic children.
if (t.GetTypeClass() == lldb.eTypeClassStruct):
valstr = str(self._sbvalue_object.GetSyntheticValue())
if (valstr != "No value" and
valstr.find("$1") == -1):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Would SBValue.IsValid() work here instead of checking the string against "No value"?

What is the check against "$1" supposed to do? If possible, we should replace this with some API call that tests some property of the SBValue rather than pattern-matching the stringified version. If this is not possible, is it always "$1" or is this the kind of convenience variable that depends on how many expressions you've evaluated before? Can it ever be "$2" or "$3"?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The problem comes from 'address.test'. There is a part of the text that specifically does not want to use a synthetic value (but there is a valid one). The Check line is
CHECK: Pretty s = pretty MyStruct

What my code returns, without the '$1' test is:
Pretty s = (MyStruct) $1 = pretty MyStruct

I don't really like the '$1' hack, but I'm not sure how to handle/fix this particular case?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Using IsValid does work, allowing me to not text for "No Value"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I've been trying some stuff and it looks like lldb is pretty inflexible about what str(sbvalue) does. It will always generate a string with the following format

(${val.GetType().GetName()}) ${val.GetName()} = ${val.GetSummary()} {
  children
  ...
}

In this case, the "$1" comes from SBValue.GetName(). If we want to match what gdb does, I'm afraid we'll need to implement the logic to generate the string ourselves without relying on str(val).

Or we could live with (MyStruct) $1 = pretty MyStruct and relax address.test to match that output.

return valstr
valstr = self._sbvalue_object.GetSummary()
if not valstr:
valstr = self._sbvalue_object.GetValue()
Expand Down
7 changes: 6 additions & 1 deletion test/lit/print_elements.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ RUN: %lldb -b -o 'command script import print_elements' %t | FileCheck %s
Check target.max-children-count values are correctly translated to "print
elements" values.

CHECK: gdb.parameter('print elements'): None
CHECK: gdb.parameter('print elements'): 256
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The behavior where a negative number means "no limit" was recently removed by llvm/llvm-project#105460. I think it would be better to just remove this CHECK, I don't see a need to check for a specific default value and it makes the test brittle in case lldb decides to change the default.

If you want, you could also simplify the parameter function around line 950 to

def parameter(s: str) -> Any:
    # gdb's 'print elements' is used for number of array elements to print and
    # also max number of chars in a string. lldb has 'target.max-children-count'
    # and 'target.max-string-summary-length', but max-children-count seems like
    # a closer match.
    if s == "print elements":
        return int(_GetSetting('target.max-children-count'))
    return None

but we can also do that as a follow-up if you prefer.

CHECK: gdb.parameter('print elements'): 0
CHECK: gdb.parameter('print elements'): 10

Expand All @@ -20,3 +20,8 @@ yield child 10. So check that we don't yield 11.

CHECK: yielding child 10
CHECK-NOT: yielding child 11


CHECK: yielding child 10
CHECK: A TestStruct of size 100
CHECK-NOT: yielding child 11
4 changes: 3 additions & 1 deletion test/lit/print_elements/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __lldb_init_module(debugger, internal_dict):
gdb.printing.register_pretty_printer(gdb.current_objfile(), printer)

# lldb treats all negative values here as 'unlimited'.
# gdb.parameter('print elements') returns None in this case.
# gdb.parameter('print elements') returns 256 in this case.
debugger.HandleCommand('settings set -- target.max-children-count -99')
print("gdb.parameter('print elements'):", gdb.parameter('print elements'))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here, please remove the negative number test case.


Expand All @@ -51,3 +51,5 @@ def __lldb_init_module(debugger, internal_dict):
print("gdb.parameter('print elements'):", gdb.parameter('print elements'))

debugger.HandleCommand('p s')

debugger.HandleCommand("script print(gdb.parse_and_eval('s'))")