gdb.UnwindInfo.add_saved_register (REG, VALUE) -> None. */
static PyObject *
-unwind_infopy_add_saved_register (PyObject *self, PyObject *args)
+unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
{
unwind_info_object *unwind_info = (unwind_info_object *) self;
pending_frame_object *pending_frame
{
PyErr_SetString (PyExc_ValueError,
"UnwindInfo instance refers to a stale PendingFrame");
- return NULL;
+ return nullptr;
}
- if (!PyArg_UnpackTuple (args, "previous_frame_register", 2, 2,
- &pyo_reg_id, &pyo_reg_value))
- return NULL;
+
+ static const char *keywords[] = { "register", "value", nullptr };
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO!", keywords,
+ &pyo_reg_id, &value_object_type,
+ &pyo_reg_value))
+ return nullptr;
+
if (!gdbpy_parse_register_id (pending_frame->gdbarch, pyo_reg_id, ®num))
return nullptr;
}
}
- {
- struct value *value;
- size_t data_size;
+ /* The argument parsing above guarantees that PYO_REG_VALUE will be a
+ gdb.Value object, as a result the value_object_to_value call should
+ succeed. */
+ gdb_assert (pyo_reg_value != nullptr);
+ struct value *value = value_object_to_value (pyo_reg_value);
+ gdb_assert (value != nullptr);
+
+ ULONGEST reg_size = register_size (pending_frame->gdbarch, regnum);
+ if (reg_size != value->type ()->length ())
+ {
+ PyErr_Format (PyExc_ValueError,
+ "The value of the register returned by the Python "
+ "sniffer has unexpected size: %s instead of %s.",
+ pulongest (value->type ()->length ()),
+ pulongest (reg_size));
+ return nullptr;
+ }
+
+ gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
+ bool found = false;
+ for (saved_reg ® : *unwind_info->saved_regs)
+ {
+ if (regnum == reg.number)
+ {
+ found = true;
+ reg.value = std::move (new_value);
+ break;
+ }
+ }
+ if (!found)
+ unwind_info->saved_regs->emplace_back (regnum, std::move (new_value));
- if (pyo_reg_value == NULL
- || (value = value_object_to_value (pyo_reg_value)) == NULL)
- {
- PyErr_SetString (PyExc_ValueError, "Bad register value");
- return NULL;
- }
- data_size = register_size (pending_frame->gdbarch, regnum);
- if (data_size != value->type ()->length ())
- {
- PyErr_Format (
- PyExc_ValueError,
- "The value of the register returned by the Python "
- "sniffer has unexpected size: %u instead of %u.",
- (unsigned) value->type ()->length (),
- (unsigned) data_size);
- return NULL;
- }
- }
- {
- gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
- bool found = false;
- for (saved_reg ® : *unwind_info->saved_regs)
- {
- if (regnum == reg.number)
- {
- found = true;
- reg.value = std::move (new_value);
- break;
- }
- }
- if (!found)
- unwind_info->saved_regs->emplace_back (regnum, std::move (new_value));
- }
Py_RETURN_NONE;
}
static PyMethodDef unwind_info_object_methods[] =
{
{ "add_saved_register",
- unwind_infopy_add_saved_register, METH_VARARGS,
+ (PyCFunction) unwind_infopy_add_saved_register,
+ METH_VARARGS | METH_KEYWORDS,
"add_saved_register (REG, VALUE) -> None\n"
"Set the value of the REG in the previous frame to VALUE." },
{ NULL } /* Sentinel */
check_for_broken_backtrace "stack is broken after command disabling"
check_info_unwinder "info unwinder after command disabling" off
-# Check that invalid register names cause errors.
-gdb_test "python print(add_saved_register_error)" "True" \
- "add_saved_register error"
-gdb_test "python print(read_register_error)" "True" \
+# Check that invalid register names and values cause errors.
+gdb_test "python print(add_saved_register_errors\[\"unknown_name\"\])" \
+ "Bad register" \
+ "add_saved_register error when an unknown register name is used"
+gdb_test "python print(add_saved_register_errors\[\"unknown_number\"\])" \
+ "Bad register" \
+ "add_saved_register error when an unknown register number is used"
+gdb_test "python print(add_saved_register_errors\[\"bad_value\"\])" \
+ "argument 2 must be gdb.Value, not int" \
+ "add_saved_register error when invalid register value is used"
+gdb_test "python print(read_register_error)" "Bad register" \
"read_register error"
# Try to create an unwinder object with a non-string name.
# These are set to test whether invalid register names cause an error.
-add_saved_register_error = False
+add_saved_register_errors = {}
read_register_error = False
try:
pending_frame.read_register("nosuchregister")
- except ValueError:
+ except ValueError as ve:
global read_register_error
- read_register_error = True
+ read_register_error = str(ve)
frame_id = FrameId(
pending_frame.read_register(TestUnwinder.AMD64_RSP),
)
unwind_info = pending_frame.create_unwind_info(frame_id)
unwind_info.add_saved_register(TestUnwinder.AMD64_RBP, previous_bp)
- unwind_info.add_saved_register("rip", previous_ip)
- unwind_info.add_saved_register("rsp", previous_sp)
+ unwind_info.add_saved_register(value=previous_ip, register="rip")
+ unwind_info.add_saved_register(register="rsp", value=previous_sp)
+
+ global add_saved_register_errors
try:
unwind_info.add_saved_register("nosuchregister", previous_sp)
- except ValueError:
- global add_saved_register_error
- add_saved_register_error = True
+ except ValueError as ve:
+ add_saved_register_errors["unknown_name"] = str(ve)
+
+ try:
+ unwind_info.add_saved_register(999, previous_sp)
+ except ValueError as ve:
+ add_saved_register_errors["unknown_number"] = str(ve)
+
+ try:
+ unwind_info.add_saved_register("rsp", 1234)
+ except TypeError as ve:
+ add_saved_register_errors["bad_value"] = str(ve)
+
return unwind_info
except (gdb.error, RuntimeError):
return None