]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/python/py-frame.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / python / py-frame.c
index 4b025dbabb7faca7e895e1e286f4e0125825b9eb..5c027547825a3ae0b385ee34efa37ca813825af9 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to stack frames
 
-   Copyright (C) 2008-2013 Free Software Foundation, Inc.
+   Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,7 +21,6 @@
 #include "charset.h"
 #include "block.h"
 #include "frame.h"
-#include "exceptions.h"
 #include "symtab.h"
 #include "stack.h"
 #include "value.h"
@@ -29,7 +28,7 @@
 #include "symfile.h"
 #include "objfiles.h"
 
-typedef struct {
+struct frame_object {
   PyObject_HEAD
   struct frame_id frame_id;
   struct gdbarch *gdbarch;
@@ -43,7 +42,7 @@ typedef struct {
      ID as the  previous frame).  Whenever get_prev_frame returns NULL, we
      record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1.  */
   int frame_id_is_next;
-} frame_object;
+};
 
 /* Require a valid frame.  This must be called inside a TRY_CATCH, or
    another context in which a gdb exception is allowed.  */
@@ -61,7 +60,7 @@ typedef struct {
 struct frame_info *
 frame_object_to_frame_info (PyObject *obj)
 {
-  frame_object *frame_obj = (frame_object *) obj;  
+  frame_object *frame_obj = (frame_object *) obj;
   struct frame_info *frame;
 
   frame = frame_find_by_id (frame_obj->frame_id);
@@ -80,17 +79,10 @@ frame_object_to_frame_info (PyObject *obj)
 static PyObject *
 frapy_str (PyObject *self)
 {
-  char *s;
-  PyObject *result;
-  struct ui_file *strfile;
+  string_file strfile;
 
-  strfile = mem_fileopen ();
-  fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
-  s = ui_file_xstrdup (strfile, NULL);
-  result = PyString_FromString (s);
-  xfree (s);
-
-  return result;
+  fprint_frame_id (&strfile, ((frame_object *) self)->frame_id);
+  return PyString_FromString (strfile.c_str ());
 }
 
 /* Implementation of gdb.Frame.is_valid (self) -> Boolean.
@@ -101,13 +93,15 @@ static PyObject *
 frapy_is_valid (PyObject *self, PyObject *args)
 {
   struct frame_info *frame = NULL;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       frame = frame_object_to_frame_info (self);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   if (frame == NULL)
     Py_RETURN_FALSE;
@@ -122,21 +116,26 @@ static PyObject *
 frapy_name (PyObject *self, PyObject *args)
 {
   struct frame_info *frame;
-  const char *name;
+  gdb::unique_xmalloc_ptr<char> name;
   enum language lang;
   PyObject *result;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
-      find_frame_funname (frame, &name, &lang, NULL);
+      name = find_frame_funname (frame, &lang, NULL);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
 
   if (name)
-    result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
+    {
+      result = PyUnicode_Decode (name.get (), strlen (name.get ()),
+                                host_charset (), NULL);
+    }
   else
     {
       result = Py_None;
@@ -154,17 +153,40 @@ frapy_type (PyObject *self, PyObject *args)
 {
   struct frame_info *frame;
   enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning.  */
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
       type = get_frame_type (frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
-  return PyInt_FromLong (type);
+  return gdb_py_object_from_longest (type).release ();
+}
+
+/* Implementation of gdb.Frame.architecture (self) -> gdb.Architecture.
+   Returns the frame's architecture as a gdb.Architecture object.  */
+
+static PyObject *
+frapy_arch (PyObject *self, PyObject *args)
+{
+  struct frame_info *frame = NULL;    /* Initialize to appease gcc warning.  */
+  frame_object *obj = (frame_object *) self;
+
+  try
+    {
+      FRAPY_REQUIRE_VALID (self, frame);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  return gdbarch_to_arch_object (obj->gdbarch);
 }
 
 /* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
@@ -174,18 +196,20 @@ static PyObject *
 frapy_unwind_stop_reason (PyObject *self, PyObject *args)
 {
   struct frame_info *frame = NULL;    /* Initialize to appease gcc warning.  */
-  volatile struct gdb_exception except;
   enum unwind_stop_reason stop_reason;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   stop_reason = get_frame_unwind_stop_reason (frame);
 
-  return PyInt_FromLong (stop_reason);
+  return gdb_py_object_from_longest (stop_reason).release ();
 }
 
 /* Implementation of gdb.Frame.pc (self) -> Long.
@@ -196,17 +220,58 @@ frapy_pc (PyObject *self, PyObject *args)
 {
   CORE_ADDR pc = 0;          /* Initialize to appease gcc warning.  */
   struct frame_info *frame;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
       pc = get_frame_pc (frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  return gdb_py_object_from_ulongest (pc).release ();
+}
+
+/* Implementation of gdb.Frame.read_register (self, register) -> gdb.Value.
+   Returns the value of a register in this frame.  */
+
+static PyObject *
+frapy_read_register (PyObject *self, PyObject *args)
+{
+  PyObject *pyo_reg_id;
+  struct value *val = NULL;
+
+  if (!PyArg_UnpackTuple (args, "read_register", 1, 1, &pyo_reg_id))
+    return NULL;
+  try
+    {
+      struct frame_info *frame;
+      int regnum;
+
+      FRAPY_REQUIRE_VALID (self, frame);
+
+      if (!gdbpy_parse_register_id (get_frame_arch (frame), pyo_reg_id,
+                                   &regnum))
+       {
+         PyErr_SetString (PyExc_ValueError, "Bad register");
+         return NULL;
+       }
+
+      gdb_assert (regnum >= 0);
+      val = value_of_register (regnum, frame);
+
+      if (val == NULL)
+       PyErr_SetString (PyExc_ValueError, _("Can't read register."));
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
-  return gdb_py_long_from_ulongest (pc);
+  return val == NULL ? NULL : value_to_value_object (val);
 }
 
 /* Implementation of gdb.Frame.block (self) -> gdb.Block.
@@ -216,15 +281,17 @@ static PyObject *
 frapy_block (PyObject *self, PyObject *args)
 {
   struct frame_info *frame;
-  struct block *block = NULL, *fn_block;
-  volatile struct gdb_exception except;
+  const struct block *block = NULL, *fn_block;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
       block = get_frame_block (frame, NULL);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   for (fn_block = block;
        fn_block != NULL && BLOCK_FUNCTION (fn_block) == NULL;
@@ -234,16 +301,14 @@ frapy_block (PyObject *self, PyObject *args)
   if (block == NULL || fn_block == NULL || BLOCK_FUNCTION (fn_block) == NULL)
     {
       PyErr_SetString (PyExc_RuntimeError,
-                      _("Cannot locate object file for block."));
+                      _("Cannot locate block for frame."));
       return NULL;
     }
 
   if (block)
     {
-      struct symtab *symt;
-
-      symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block));
-      return block_to_block_object (block, symt->objfile);
+      return block_to_block_object
+       (block, symbol_objfile (BLOCK_FUNCTION (fn_block)));
     }
 
   Py_RETURN_NONE;
@@ -258,15 +323,20 @@ frapy_function (PyObject *self, PyObject *args)
 {
   struct symbol *sym = NULL;
   struct frame_info *frame;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
+      enum language funlang;
+
       FRAPY_REQUIRE_VALID (self, frame);
 
-      sym = find_pc_function (get_frame_address_in_block (frame));
+      gdb::unique_xmalloc_ptr<char> funname
+       = find_frame_funname (frame, &funlang, &sym);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
 
   if (sym)
     return symbol_to_symbol_object (sym);
@@ -280,18 +350,12 @@ frapy_function (PyObject *self, PyObject *args)
 PyObject *
 frame_info_to_frame_object (struct frame_info *frame)
 {
-  frame_object *frame_obj;
-  volatile struct gdb_exception except;
-
-  frame_obj = PyObject_New (frame_object, &frame_object_type);
+  gdbpy_ref<frame_object> frame_obj (PyObject_New (frame_object,
+                                                  &frame_object_type));
   if (frame_obj == NULL)
-    {
-      PyErr_SetString (PyExc_MemoryError, 
-                      _("Could not allocate frame object."));
-      return NULL;
-    }
+    return NULL;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
 
       /* Try to get the previous frame, to determine if this is the last frame
@@ -311,9 +375,13 @@ frame_info_to_frame_object (struct frame_info *frame)
        }
       frame_obj->gdbarch = get_frame_arch (frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      gdbpy_convert_exception (except);
+      return NULL;
+    }
 
-  return (PyObject *) frame_obj;
+  return (PyObject *) frame_obj.release ();
 }
 
 /* Implementation of gdb.Frame.older (self) -> gdb.Frame.
@@ -323,24 +391,27 @@ frame_info_to_frame_object (struct frame_info *frame)
 static PyObject *
 frapy_older (PyObject *self, PyObject *args)
 {
-  struct frame_info *frame, *prev;
-  volatile struct gdb_exception except;
+  struct frame_info *frame, *prev = NULL;
   PyObject *prev_obj = NULL;   /* Initialize to appease gcc warning.  */
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
       prev = get_prev_frame (frame);
-      if (prev)
-       prev_obj = (PyObject *) frame_info_to_frame_object (prev);
-      else
-       {
-         Py_INCREF (Py_None);
-         prev_obj = Py_None;
-       }
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  if (prev)
+    prev_obj = frame_info_to_frame_object (prev);
+  else
+    {
+      Py_INCREF (Py_None);
+      prev_obj = Py_None;
+    }
 
   return prev_obj;
 }
@@ -352,24 +423,27 @@ frapy_older (PyObject *self, PyObject *args)
 static PyObject *
 frapy_newer (PyObject *self, PyObject *args)
 {
-  struct frame_info *frame, *next;
-  volatile struct gdb_exception except;
+  struct frame_info *frame, *next = NULL;
   PyObject *next_obj = NULL;   /* Initialize to appease gcc warning.  */
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
       next = get_next_frame (frame);
-      if (next)
-       next_obj = (PyObject *) frame_info_to_frame_object (next);
-      else
-       {
-         Py_INCREF (Py_None);
-         next_obj = Py_None;
-       }
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  if (next)
+    next_obj = frame_info_to_frame_object (next);
+  else
+    {
+      Py_INCREF (Py_None);
+      next_obj = Py_None;
+    }
 
   return next_obj;
 }
@@ -381,18 +455,19 @@ static PyObject *
 frapy_find_sal (PyObject *self, PyObject *args)
 {
   struct frame_info *frame;
-  struct symtab_and_line sal;
-  volatile struct gdb_exception except;
   PyObject *sal_obj = NULL;   /* Initialize to appease gcc warning.  */
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
-      find_frame_sal (frame, &sal);
+      symtab_and_line sal = find_frame_sal (frame);
       sal_obj = symtab_and_line_to_sal_object (sal);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return sal_obj;
 }
@@ -410,8 +485,8 @@ frapy_read_var (PyObject *self, PyObject *args)
   struct frame_info *frame;
   PyObject *sym_obj, *block_obj = NULL;
   struct symbol *var = NULL;   /* gcc-4.3.2 false warning.  */
+  const struct block *block = NULL;
   struct value *val = NULL;
-  volatile struct gdb_exception except;
 
   if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj))
     return NULL;
@@ -420,15 +495,11 @@ frapy_read_var (PyObject *self, PyObject *args)
     var = symbol_object_to_symbol (sym_obj);
   else if (gdbpy_is_string (sym_obj))
     {
-      char *var_name;
-      const struct block *block = NULL;
-      struct cleanup *cleanup;
-      volatile struct gdb_exception except;
+      gdb::unique_xmalloc_ptr<char>
+       var_name (python_string_to_target_string (sym_obj));
 
-      var_name = python_string_to_target_string (sym_obj);
       if (!var_name)
        return NULL;
-      cleanup = make_cleanup (xfree, var_name);
 
       if (block_obj)
        {
@@ -441,26 +512,30 @@ frapy_read_var (PyObject *self, PyObject *args)
            }
        }
 
-      TRY_CATCH (except, RETURN_MASK_ALL)
+      try
        {
+         struct block_symbol lookup_sym;
          FRAPY_REQUIRE_VALID (self, frame);
 
          if (!block)
            block = get_frame_block (frame, NULL);
-         var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
+         lookup_sym = lookup_symbol (var_name.get (), block, VAR_DOMAIN, NULL);
+         var = lookup_sym.symbol;
+         block = lookup_sym.block;
+       }
+      catch (const gdb_exception &except)
+       {
+         gdbpy_convert_exception (except);
+         return NULL;
        }
-      GDB_PY_HANDLE_EXCEPTION (except);
 
       if (!var)
        {
          PyErr_Format (PyExc_ValueError,
-                       _("Variable '%s' not found."), var_name);
-         do_cleanups (cleanup);
+                       _("Variable '%s' not found."), var_name.get ());
 
          return NULL;
        }
-
-      do_cleanups (cleanup);
     }
   else
     {
@@ -469,13 +544,16 @@ frapy_read_var (PyObject *self, PyObject *args)
       return NULL;
     }
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
-      val = read_var_value (var, frame);
+      val = read_var_value (var, block, frame);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
 
   return value_to_value_object (val);
 }
@@ -486,15 +564,17 @@ static PyObject *
 frapy_select (PyObject *self, PyObject *args)
 {
   struct frame_info *fi;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       FRAPY_REQUIRE_VALID (self, fi);
 
       select_frame (fi);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   Py_RETURN_NONE;
 }
@@ -505,18 +585,18 @@ frapy_select (PyObject *self, PyObject *args)
 PyObject *
 gdbpy_newest_frame (PyObject *self, PyObject *args)
 {
-  struct frame_info *frame;
-  PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
-  volatile struct gdb_exception except;
+  struct frame_info *frame = NULL;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       frame = get_current_frame ();
-      frame_obj = frame_info_to_frame_object (frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
-  return frame_obj;
+  return frame_info_to_frame_object (frame);
 }
 
 /* Implementation of gdb.selected_frame () -> gdb.Frame.
@@ -525,18 +605,18 @@ gdbpy_newest_frame (PyObject *self, PyObject *args)
 PyObject *
 gdbpy_selected_frame (PyObject *self, PyObject *args)
 {
-  struct frame_info *frame;
-  PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
-  volatile struct gdb_exception except;
+  struct frame_info *frame = NULL;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       frame = get_selected_frame ("No frame is currently selected.");
-      frame_obj = frame_info_to_frame_object (frame);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
-  return frame_obj;
+  return frame_info_to_frame_object (frame);
 }
 
 /* Implementation of gdb.stop_reason_string (Integer) -> String.
@@ -553,12 +633,12 @@ gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
 
   if (reason < UNWIND_FIRST || reason > UNWIND_LAST)
     {
-      PyErr_SetString (PyExc_ValueError, 
+      PyErr_SetString (PyExc_ValueError,
                       _("Invalid frame stop reason."));
       return NULL;
     }
 
-  str = frame_stop_reason_string (reason);
+  str = unwind_stop_reason_to_string ((enum unwind_stop_reason) reason);
   return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
 }
 
@@ -591,33 +671,36 @@ frapy_richcompare (PyObject *self, PyObject *other, int op)
 
 /* Sets up the Frame API in the gdb module.  */
 
-void
+int
 gdbpy_initialize_frames (void)
 {
   frame_object_type.tp_new = PyType_GenericNew;
   if (PyType_Ready (&frame_object_type) < 0)
-    return;
+    return -1;
 
   /* Note: These would probably be best exposed as class attributes of
      Frame, but I don't know how to do it except by messing with the
      type's dictionary.  That seems too messy.  */
-  PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
-  PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
-  PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME);
-  PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME);
-  PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
-  PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
-  PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
+  if (PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME",
+                                 TAILCALL_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME",
+                                 SIGTRAMP_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME) < 0
+      || PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME",
+                                 SENTINEL_FRAME) < 0)
+    return -1;
 
 #define SET(name, description) \
-  PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
-#define FIRST_ERROR(name) \
-  PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
+  if (PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name) < 0) \
+    return -1;
 #include "unwind_stop_reasons.def"
 #undef SET
 
-  Py_INCREF (&frame_object_type);
-  PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
+  return gdb_pymodule_addobject (gdb_module, "Frame",
+                                (PyObject *) &frame_object_type);
 }
 
 \f
@@ -632,12 +715,18 @@ Return the function name of the frame, or None if it can't be determined." },
   { "type", frapy_type, METH_NOARGS,
     "type () -> Integer.\n\
 Return the type of the frame." },
+  { "architecture", frapy_arch, METH_NOARGS,
+    "architecture () -> gdb.Architecture.\n\
+Return the architecture of the frame." },
   { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
     "unwind_stop_reason () -> Integer.\n\
 Return the reason why it's not possible to find frames older than this." },
   { "pc", frapy_pc, METH_NOARGS,
     "pc () -> Long.\n\
 Return the frame's resume address." },
+  { "read_register", frapy_read_register, METH_VARARGS,
+    "read_register (register_name) -> gdb.Value\n\
+Return the value of the register in the frame." },
   { "block", frapy_block, METH_NOARGS,
     "block () -> gdb.Block.\n\
 Return the frame's code block." },