aboutsummaryrefslogtreecommitdiff
path: root/gdb/python/lib
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2024-11-15 09:29:27 -0700
committerTom Tromey <tromey@adacore.com>2024-12-09 14:26:23 -0700
commit4c2d19e3cd80e23acb555e25b7725592173cbd0d (patch)
tree979f6955c741a120731fd47f5954c60804883318 /gdb/python/lib
parentc286bfe1e5c252689126cb2f45677bd36a2fdd56 (diff)
downloadbinutils-4c2d19e3cd80e23acb555e25b7725592173cbd0d.zip
binutils-4c2d19e3cd80e23acb555e25b7725592173cbd0d.tar.gz
binutils-4c2d19e3cd80e23acb555e25b7725592173cbd0d.tar.bz2
Introduce NoOpStringPrinter
We discovered that attempting to print a very large string-like array would succeed on the CLI, but in DAP would cause the "variables" request to fail with: value requires 67038491 bytes, which is more than max-value-size This turns out to be a limitation in Value.format_string, which de-lazy-ifies the value. This patch fixes this problem by introducing a new NoOpStringPrinter class, and then using it for string-like values. This printer returns a lazy string, which solves the problem. Note there are some special cases where we do not want to return a lazy string. I've documented these in the code. I considered making gdb.Value.lazy_string handle these cases -- for example it could return 'self' rather than a lazy string in some situations -- but this approach was simpler.
Diffstat (limited to 'gdb/python/lib')
-rw-r--r--gdb/python/lib/gdb/printing.py40
1 files changed, 39 insertions, 1 deletions
diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index 55ba435..0635993 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -281,6 +281,44 @@ class NoOpScalarPrinter(gdb.ValuePrinter):
return self.__value.format_string(raw=True)
+class NoOpStringPrinter(gdb.ValuePrinter):
+ """A no-op pretty printer that wraps a string value."""
+
+ def __init__(self, ty, value):
+ self.__ty = ty
+ self.__value = value
+
+ def to_string(self):
+ # We need some special cases here.
+ #
+ # * If the gdb.Value was created from a Python string, it will
+ # be a non-lazy array -- but will have address 0 and so the
+ # contents will be lost on conversion to lazy string.
+ # (Weirdly, the .address attribute will not be 0 though.)
+ # Since conversion to lazy string is to avoid fetching too
+ # much data, and since the array is already non-lazy, just
+ # return it.
+ #
+ # * To avoid weird printing for a C "string" that is just a
+ # NULL pointer, special case this as well.
+ #
+ # * Lazy strings only understand arrays and pointers; other
+ # string-like objects (like a Rust &str) should simply be
+ # returned.
+ code = self.__ty.code
+ if code == gdb.TYPE_CODE_ARRAY and not self.__value.is_lazy:
+ return self.__value
+ elif code == gdb.TYPE_CODE_PTR and self.__value == 0:
+ return self.__value
+ elif code != gdb.TYPE_CODE_PTR and code != gdb.TYPE_CODE_ARRAY:
+ return self.__value
+ else:
+ return self.__value.lazy_string()
+
+ def display_hint(self):
+ return "string"
+
+
class NoOpPointerReferencePrinter(gdb.ValuePrinter):
"""A no-op pretty printer that wraps a pointer or reference."""
@@ -368,7 +406,7 @@ def make_visualizer(value):
else:
ty = value.type.strip_typedefs()
if ty.is_string_like:
- result = NoOpScalarPrinter(value)
+ result = NoOpStringPrinter(ty, value)
elif ty.code == gdb.TYPE_CODE_ARRAY:
result = NoOpArrayPrinter(ty, value)
elif ty.is_array_like: