]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/python: add gdb.Value.is_unavailable attribute
authorAndrew Burgess <aburgess@redhat.com>
Mon, 1 Sep 2025 15:58:58 +0000 (16:58 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Thu, 4 Sep 2025 21:18:59 +0000 (22:18 +0100)
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>
gdb/NEWS
gdb/doc/python.texi
gdb/python/py-value.c
gdb/testsuite/gdb.python/py-value.c
gdb/testsuite/gdb.python/py-value.exp

index 2d410a75265c64145ed59def5b9da61677e15657..97828478146276cd5c3b5858afc9eb13928dd3cb 100644 (file)
--- 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 <gdb:color> for dealing with colors.
index 6fa22851f6a7879a7e601c9ef2bd72d3d5006600..3763eee9d634d4b5682f2abd18b9f3e028e80a86 100644 (file)
@@ -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
index 8a2e26368d785ae4fb96a61963f0ad7cd9770ef8..833ce26d5a36d1536fb71ca3e186470ff354b0af 100644 (file)
@@ -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 },
index a82234646e7abc56a2d90a1b794ff05dd96465f4..5052950ce0ddbba13e56b1e29bc36eeb7e2c354d 100644 (file)
 #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;
index 4857937836a02576f213b541415ff8ab032b8916..ab49f2deb9201fa5cbd82486aadb9ba071538490 100644 (file)
@@ -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