From: Andrew Burgess Date: Mon, 1 Sep 2025 15:58:58 +0000 (+0100) Subject: gdb/python: add gdb.Value.is_unavailable attribute X-Git-Tag: gdb-17-branchpoint~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b652ce7b808cd81346da587e4b4f7c3754c9d98e;p=thirdparty%2Fbinutils-gdb.git 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 . 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 Reviewed-By: Christina Schimpe --- diff --git a/gdb/NEWS b/gdb/NEWS index 2d410a75265..97828478146 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -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 for dealing with colors. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 6fa22851f6a..3763eee9d63 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 8a2e26368d7..833ce26d5a3 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 a82234646e7..5052950ce0d 100644 --- a/gdb/testsuite/gdb.python/py-value.c +++ b/gdb/testsuite/gdb.python/py-value.c @@ -19,6 +19,14 @@ #include #include +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 4857937836a..ab49f2deb92 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\])" "^" \ + "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