diff options
author | Andrew Burgess <aburgess@redhat.com> | 2025-09-01 16:58:58 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2025-09-04 22:18:59 +0100 |
commit | b652ce7b808cd81346da587e4b4f7c3754c9d98e (patch) | |
tree | b40a208552403eba435fc04bd7e233d2b3b3c6c4 | |
parent | 95f21c0d25a8241251a1dfcf6e5d80701cd80a06 (diff) | |
download | binutils-b652ce7b808cd81346da587e4b4f7c3754c9d98e.zip binutils-b652ce7b808cd81346da587e4b4f7c3754c9d98e.tar.gz binutils-b652ce7b808cd81346da587e4b4f7c3754c9d98e.tar.bz2 |
gdb/python: add gdb.Value.is_unavailable attribute
Add a new gdb.Value.is_unavailable attribute. This is similar to the
existing Value.is_optimized_out attribute, but returns True if any
part of the value is <unavailable>.
The existing Value.is_optimized_out attribute returns true if any part
of the value is optimized out, so I thought that Value.is_unavailable
should work the same way.
There's also a test.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33345
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Christina Schimpe <christina.schimpe@intel.com>
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/doc/python.texi | 21 | ||||
-rw-r--r-- | gdb/python/py-value.c | 27 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-value.c | 8 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-value.exp | 34 |
5 files changed, 93 insertions, 1 deletions
@@ -174,6 +174,10 @@ info threads [-gid] [-stopped] [-running] [ID]... ** New gdb.warning() function that takes a string and prints it as a warning, with GDB's standard 'warning' prefix. + ** New attribute gdb.Value.is_unavailable, this checks for + unavailability like gdb.Value.is_optimized_out checks for + optimized out values. + * Guile API ** New type <gdb:color> for dealing with colors. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 6fa2285..3763eee 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -910,7 +910,26 @@ this attribute holds @code{None}. @cindex optimized out value in Python @defvar Value.is_optimized_out This read-only boolean attribute is true if the compiler optimized out -this value, thus it is not available for fetching from the inferior. +this value, or any part of this value, and thus it is not available +for fetching from the inferior. +@end defvar + +@cindex unavailable values in Python +@defvar Value.is_unavailable +This read-only boolean attribute is true if this value, or any part of +this value, is not available to @value{GDBN}. Where an optimized out +value has been removed from the program by the compiler, an +unavailable value does exist in the program, but @value{GDBN} is +unable to fetch it. + +Some reasons why this might occur include, but are not limited to: a +core file format that @value{GDBN} doesn't fully understand; during +live debugging if the debug API has no mechanism to access the +required state, e.g.@: the kernel gives an error when trying to read a +particular register set; or reading a value from @value{GDBN}'s +history, when only a partial value was stored, e.g.@: due to the +@kbd{max-value-size} setting (@pxref{set +max-value-size,,max-value-size}). @end defvar @defvar Value.type diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 8a2e263..833ce26 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -1288,6 +1288,30 @@ valpy_get_is_optimized_out (PyObject *self, void *closure) Py_RETURN_FALSE; } +/* Implements gdb.Value.is_unavailable. Return true if any part of the + value is unavailable. */ + +static PyObject * +valpy_get_is_unavailable (PyObject *self, void *closure) +{ + struct value *value = ((value_object *) self)->value; + bool entirely_available = false; + + try + { + entirely_available = value->entirely_available (); + } + catch (const gdb_exception &except) + { + return gdbpy_handle_gdb_exception (nullptr, except); + } + + if (!entirely_available) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + /* Implements gdb.Value.is_lazy. */ static PyObject * valpy_get_is_lazy (PyObject *self, void *closure) @@ -2194,6 +2218,9 @@ static gdb_PyGetSetDef value_object_getset[] = { "Boolean telling whether the value is optimized " "out (i.e., not available).", NULL }, + { "is_unavailable", valpy_get_is_unavailable, nullptr, + "Boolean telling whether the value is unavailable.", + nullptr }, { "type", valpy_get_type, NULL, "Type of the value.", NULL }, { "dynamic_type", valpy_get_dynamic_type, NULL, "Dynamic type of the value.", NULL }, diff --git a/gdb/testsuite/gdb.python/py-value.c b/gdb/testsuite/gdb.python/py-value.c index a822346..5052950 100644 --- a/gdb/testsuite/gdb.python/py-value.c +++ b/gdb/testsuite/gdb.python/py-value.c @@ -19,6 +19,14 @@ #include <stdlib.h> #include <string.h> +int long_array[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 +}; + struct s { int a; diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp index 4857937..ab49f2d 100644 --- a/gdb/testsuite/gdb.python/py-value.exp +++ b/gdb/testsuite/gdb.python/py-value.exp @@ -681,6 +681,7 @@ proc_with_prefix test_value_bytes { } { "python" "" \ "def check_value_bytes(var_name):" "" \ " val = gdb.parse_and_eval(var_name)" "" \ + " assert not val.is_unavailable" "" \ " addr = val.address" "" \ " len = val.type.sizeof" "" \ " mem = gdb.selected_inferior().read_memory(addr, len)" "" \ @@ -763,6 +764,38 @@ proc test_assign {} { "cannot assign to integer" } +# Test Value.is_unavailable +proc test_unavailable {} { + set elem_size [get_valueof "/d" "sizeof(long_array\[0\])" "UNKNOWN" \ + "get size of long_array element"] + set max [expr $elem_size * 10] + + with_set "print elements" 5 { + with_max_value_size $max { + gdb_test "p long_array" + + gdb_test_no_output "set print elements 15" + + gdb_test_no_output "python v = gdb.history(0)" + + gdb_test "python print(v.is_unavailable)" "^True" \ + "overall object shows as unavailable" + for { set i 0 } { $i < 10 } { incr i } { + gdb_test "python print(v\[$i\].is_unavailable)" "^False" \ + "array element $i is available" + gdb_test "python print(v\[$i\])" "^$i" \ + "array element $i has correct value" + } + for { set i 10 } { $i < 15 } { incr i } { + gdb_test "python print(v\[$i\].is_unavailable)" "^True" \ + "array element $i is unavailable" + gdb_test "python print(v\[$i\])" "^<unavailable>" \ + "array element $i shows as unavailable" + } + } + } +} + # Build C version of executable. C++ is built later. if { [build_inferior "${binfile}" "c"] < 0 } { return -1 @@ -789,6 +822,7 @@ if {![runto_main]} { return 0 } +test_unavailable test_value_in_inferior test_value_from_buffer test_value_sub_classes |