return type_to_type_object (type);
}
+/* __repr__ implementation for gdb.Architecture. */
+
+static PyObject *
+archpy_repr (PyObject *self)
+{
+ const auto gdbarch = arch_object_to_gdbarch (self);
+ if (gdbarch == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ auto arch_info = gdbarch_bfd_arch_info (gdbarch);
+ return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>",
+ Py_TYPE (self)->tp_name, arch_info->arch_name,
+ arch_info->printable_name);
+}
+
/* Implementation of gdb.architecture_names(). Return a list of all the
BFD architecture names that GDB understands. */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
- 0, /* tp_repr */
+ archpy_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
Py_RETURN_TRUE;
}
+/* __repr__ implementation for gdb.Block. */
+
+static PyObject *
+blpy_repr (PyObject *self)
+{
+ const auto block = block_object_to_block (self);
+ if (block == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ const auto name = block->function () ?
+ block->function ()->print_name () : "<anonymous>";
+
+ std::string str;
+ unsigned int written_symbols = 0;
+ const int len = mdict_size (block->multidict ());
+ static constexpr int SYMBOLS_TO_SHOW = 5;
+ for (struct symbol *symbol : block_iterator_range (block))
+ {
+ if (written_symbols == SYMBOLS_TO_SHOW)
+ {
+ const int remaining = len - SYMBOLS_TO_SHOW;
+ if (remaining == 1)
+ str += string_printf ("... (%d more symbol)", remaining);
+ else
+ str += string_printf ("... (%d more symbols)", remaining);
+ break;
+ }
+ str += symbol->print_name ();
+ if (++written_symbols < len)
+ str += ", ";
+ }
+ return PyUnicode_FromFormat ("<%s %s {%s}>", Py_TYPE (self)->tp_name,
+ name, str.c_str ());
+}
+
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_blocks (void)
{
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ blpy_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
&block_object_as_mapping, /*tp_as_mapping*/
#include "location.h"
#include "py-event.h"
#include "linespec.h"
+#include "gdbsupport/common-utils.h"
extern PyTypeObject breakpoint_location_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("breakpoint_location_object");
return 0;
}
+/* __repr__ implementation for gdb.Breakpoint. */
+
+static PyObject *
+bppy_repr (PyObject *self)
+{
+ const auto bp = (struct gdbpy_breakpoint_object*) self;
+ if (bp->bp == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ std::string str = " ";
+ if (bp->bp->thread != -1)
+ str += string_printf ("thread=%d ", bp->bp->thread);
+ if (bp->bp->task > 0)
+ str += string_printf ("task=%d ", bp->bp->task);
+ if (bp->bp->enable_count > 0)
+ str += string_printf ("enable_count=%d ", bp->bp->enable_count);
+ str.pop_back ();
+
+ return PyUnicode_FromFormat ("<%s%s number=%d hits=%d%s>",
+ Py_TYPE (self)->tp_name,
+ (bp->bp->enable_state == bp_enabled
+ ? "" : " disabled"), bp->bp->number,
+ bp->bp->hit_count, str.c_str ());
+}
+
/* Append to LIST the breakpoint Python object associated to B.
Return true on success. Return false on failure, with the Python error
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ bppy_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
Py_TYPE (py_self)->tp_free (py_self);
}
+/* __repr__ implementation for gdb.BreakpointLocation. */
+
+static PyObject *
+bplocpy_repr (PyObject *py_self)
+{
+ const auto self = (gdbpy_breakpoint_location_object *) py_self;
+ if (self->owner == nullptr || self->owner->bp == nullptr
+ || self->owner->bp != self->bp_loc->owner)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ const auto enabled = self->bp_loc->enabled ? "enabled" : "disabled";
+
+ std::string str (enabled);
+
+ str += string_printf (" address=%s",
+ paddress (self->bp_loc->owner->gdbarch,
+ self->bp_loc->address));
+
+ if (self->bp_loc->requested_address != self->bp_loc->address)
+ str += string_printf (" requested_address=%s",
+ paddress (self->bp_loc->owner->gdbarch,
+ self->bp_loc->requested_address));
+ if (self->bp_loc->symtab != nullptr)
+ str += string_printf (" source=%s:%d", self->bp_loc->symtab->filename,
+ self->bp_loc->line_number);
+
+ const auto fn_name = self->bp_loc->function_name.get ();
+ if (fn_name != nullptr)
+ {
+ str += " in ";
+ str += fn_name;
+ }
+
+ return PyUnicode_FromFormat ("<%s %s>", Py_TYPE (self)->tp_name,
+ str.c_str ());
+}
+
/* Attribute get/set Python definitions. */
static gdb_PyGetSetDef bp_location_object_getset[] = {
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ bplocpy_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
Py_TYPE (obj)->tp_free (obj);
}
+/* __repr__ implementation for gdb.Symbol. */
+
+static PyObject *
+sympy_repr (PyObject *self)
+{
+ const auto symbol = symbol_object_to_symbol (self);
+ if (symbol == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+
+ return PyUnicode_FromFormat ("<%s print_name=%s>", Py_TYPE (self)->tp_name,
+ symbol->print_name ());
+}
+
/* Implementation of
gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)
A tuple with 2 elements is always returned. The first is the symbol
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ sympy_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
return result;
}
+/* __repr__ implementation for gdb.Type. */
+
+static PyObject *
+typy_repr (PyObject *self)
+{
+ const auto type = type_object_to_type (self);
+ if (type == nullptr)
+ return PyUnicode_FromFormat ("<%s (invalid)>",
+ Py_TYPE (self)->tp_name);
+
+ const char *code = pyty_codes[type->code ()].name;
+ string_file type_name;
+ try
+ {
+ current_language->print_type (type, "", &type_name, -1, 0,
+ &type_print_raw_options);
+ }
+ catch (const gdb_exception &except)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ auto py_typename = PyUnicode_Decode (type_name.c_str (), type_name.size (),
+ host_charset (), NULL);
+
+ return PyUnicode_FromFormat ("<%s code=%s name=%U>", Py_TYPE (self)->tp_name,
+ code, py_typename);
+}
+
static PyObject *
typy_str (PyObject *self)
{
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ typy_repr, /*tp_repr*/
&type_object_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
&typy_mapping, /*tp_as_mapping*/
# Test python/15461. Invalid architectures should not trigger an
# internal GDB assert.
gdb_py_test_silent_cmd "python empty = gdb.Architecture()" "get empty arch" 0
+gdb_test "python print(repr (empty))" "<gdb\\.Architecture \\(invalid\\)>" \
+ "Test empty achitecture __repr__ does not trigger an assert"
gdb_test "python print(empty.name())" ".*Architecture is invalid.*" \
"Test empty architecture.name does not trigger an assert"
gdb_test "python print(empty.disassemble())" ".*Architecture is invalid.*" \
gdb_py_test_silent_cmd "python insn_list4 = arch.disassemble(gdb.Value(pc))" \
"disassemble no end no count" 0
+gdb_test "python print (repr (arch))" \
+ "<gdb.Architecture arch_name=.* printable_name=.*>" \
+ "test __repr__ for architecture"
+
gdb_test "python print (len(insn_list1))" "1" "test number of instructions 1"
gdb_test "python print (len(insn_list2))" "1" "test number of instructions 2"
gdb_test "python print (len(insn_list3))" "1" "test number of instructions 3"
}
}
+/* A function with no locals. Used for testing gdb.Block.__repr__(). */
+int no_locals_func (void)
+{
+ return block_func ();
+}
+
+/* A function with 5 locals. Used for testing gdb.Block.__repr__(). */
+int few_locals_func (void)
+{
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ int x = 0;
+ int y = 0;
+ return block_func ();
+}
+
+/* A function with 6 locals. Used for testing gdb.Block.__repr__(). */
+int many_locals_func (void)
+{
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ int x = 0;
+ int y = 0;
+ int z = 0;
+ return block_func ();
+}
int main (int argc, char *argv[])
{
block_func ();
+ no_locals_func ();
+ few_locals_func ();
+ many_locals_func ();
return 0; /* Break at end. */
}
gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
gdb_py_test_silent_cmd "python block = frame.block()" \
"Get block, initial innermost block" 0
-gdb_test "python print (block)" "<gdb.Block object at $hex>" "check block not None"
+gdb_test "python print (block)" "<gdb.Block <anonymous> \{i, f, b\}>" \
+ "check block not None"
gdb_test "python print (block.function)" "None" "first anonymous block"
gdb_test "python print (block.start)" "${decimal}" "check start not None"
gdb_test "python print (block.end)" "${decimal}" "check end not None"
gdb_test "python print (block.function)" "block_func" \
"Print superblock 2 function"
+# Switch frames, then test block for no_locals_func.
+gdb_test "continue" ".*" "continue to no_locals_func breakpoint"
+gdb_test "up" ".*" "up to no_locals_func"
+gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0
+gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0
+gdb_test "python print (repr (block))" "<gdb.Block no_locals_func \{\}>" \
+ "Check block in no_locals_func"
+gdb_test "python print (block.function)" "no_locals_func" \
+ "no_locals_func block"
+
+# Switch frames, then test block for few_locals_func.
+gdb_test "continue" ".*" "continue to few_locals_func breakpoint"
+gdb_test "up" ".*" "up to few_locals_func"
+gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0
+gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0
+gdb_test "python print (repr (block))" \
+ "<gdb.Block few_locals_func \{i, j, k, x, y\}>" \
+ "Check block in few_locals_func"
+gdb_test "python print (block.function)" "few_locals_func" \
+ "few_locals_func block"
+
+# Switch frames, then test block for many_locals_func.
+gdb_test "continue" ".*" "continue to many_locals_func breakpoint"
+gdb_test "up" ".*" "up to many_locals_func"
+gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0
+gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0
+gdb_test "python print (repr (block))" \
+ "<gdb.Block many_locals_func \{i, j, k, x, y, \\.\\.\\. \\(1 more symbol\\)\}>" \
+ "Check block in many_locals_func"
+gdb_test "python print (block.function)" "many_locals_func" \
+ "many_locals_func block"
+
# Switch frames, then test for main block.
gdb_test "up" ".*"
gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0
gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0
-gdb_test "python print (block)" "<gdb.Block object at $hex>" \
+gdb_test "python print (repr (block))" "<gdb.Block main \{.*\}>" \
"Check Frame 2's block not None"
gdb_test "python print (block.function)" "main" "main block"
-
# Test Block is_valid. This must always be the last test in this
# testcase as it unloads the object file.
delete_breakpoints
return -1
}
+# Build a regexp string that represents the __repr__ of a
+# gdb.BreakpointLocation object. Accepts arguments -enabled, -address,
+# -source, -line, and -func.
+proc build_bpl_regexp { args } {
+ parse_args [list {enabled True} [list address "$::hex"] {source ".*"} \
+ [list line "$::decimal"] {func ""}]
+
+ set pattern "<gdb.BreakpointLocation"
+
+ if {$enabled} {
+ set pattern "$pattern enabled"
+ } else {
+ set pattern "$pattern disabled"
+ }
+
+ set pattern "$pattern address=${address}(?: requested_address=$::hex)?"
+ set pattern "$pattern source=${source}:${line}"
+ if {$func ne ""} {
+ set pattern "$pattern in ${func}"
+ }
+ set pattern "$pattern>"
+ return $pattern
+}
+
# Set breakpoint with 2 locations.
gdb_breakpoint "add"
".*('.*py-bp-locations.c', $expected_line_a).*"
gdb_test "python print(gdb.breakpoints()\[1\].locations\[1\].source)" \
".*('.*py-bp-locations.c', $expected_line_b).*"
+gdb_test "python print(gdb.breakpoints()\[1\].locations\[1\])" \
+ [build_bpl_regexp -enabled True -source ".*py-bp-locations.c" \
+ -line "$expected_line_b" -func ".*"] \
+ "check repr of enabled breakpoint location"
# Disable first location and make sure we don't hit it.
gdb_test "python gdb.breakpoints()\[1\].locations\[0\].enabled = False" ""
+gdb_test "python print(gdb.breakpoints()\[1\].locations\[0\])" \
+ [build_bpl_regexp -enabled False -source ".*py-bp-locations.c" \
+ -line "$expected_line_a" -func ".*"] \
+ "check repr of disabled breakpoint location"
gdb_continue_to_breakpoint "" ".*25.*"
if ![runto_main] {
set past_throw_catch_line [gdb_get_line_number "Past throw-catch."]
+# Build a regexp string that can match against the repr of a gdb.Breakpoint
+# object. Accepts arguments -enabled, -number, -hits, -thread, -task, and
+# -enable_count. The -enabled argument is a boolean, while all of the others
+# take a regexp string.
+proc build_bp_repr { args } {
+ parse_args [list {enabled True} [list number "-?$::decimal"] \
+ [list hits $::decimal] {thread ""} {task ""} \
+ {enable_count ""}]
+
+ set pattern "<gdb\\.Breakpoint"
+
+ if {!$enabled} {
+ set pattern "$pattern disabled"
+ }
+
+ set pattern "$pattern number=$number hits=$hits"
+
+ if {$thread ne ""} {
+ set pattern "$pattern thread=$thread"
+ }
+ if {$task ne ""} {
+ set pattern "$pattern task=$task"
+ }
+ if {$enable_count ne ""} {
+ set pattern "$pattern enable_count=$enable_count"
+ }
+ set pattern "${pattern}>"
+ return $pattern
+}
+
proc_with_prefix test_bkpt_basic { } {
global srcfile testfile hex decimal
# Now there should be one breakpoint: main.
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" \
"Get Breakpoint List" 0
- gdb_test "python print (blist\[0\])" \
- "<gdb.Breakpoint object at $hex>" "Check obj exists @main"
+ gdb_test "python print (repr (blist\[0\]))" \
+ [build_bp_repr -number 1 -hits 1] "Check obj exists @main"
gdb_test "python print (blist\[0\].location)" \
"main" "Check breakpoint location @main"
gdb_test "python print (blist\[0\].pending)" "False" \
"Get Breakpoint List" 0
gdb_test "python print (len(blist))" \
"2" "Check for two breakpoints"
- gdb_test "python print (blist\[0\])" \
- "<gdb.Breakpoint object at $hex>" "Check obj exists @main 2"
+ gdb_test "python print (repr (blist\[0\]))" \
+ [build_bp_repr -number 1 -hits 1] "Check obj exists @main 2"
gdb_test "python print (blist\[0\].location)" \
"main" "Check breakpoint location @main 2"
- gdb_test "python print (blist\[1\])" \
- "<gdb.Breakpoint object at $hex>" "Check obj exists @mult_line"
+ gdb_test "python print (repr (blist\[1\]))" \
+ [build_bp_repr -number 2 -hits 1] "Check obj exists @mult_line"
gdb_test "python print (blist\[1\].location)" \
"py-breakpoint\.c:${mult_line}*" \
"True" "Check breakpoint enabled."
gdb_py_test_silent_cmd "python blist\[1\].enabled = False" \
"Set breakpoint disabled." 0
+ gdb_test "python print (repr (blist\[1\]))" \
+ [build_bp_repr -enabled False -number 2 -hits 6] \
+ "Check repr for a disabled breakpoint"
gdb_continue_to_breakpoint "Break at add 2" ".*Break at add.*"
gdb_py_test_silent_cmd "python blist\[1\].enabled = True" \
"Set breakpoint enabled." 0
"Get Breakpoint List" 0
gdb_test "python print (blist\[1\].thread)" \
"None" "Check breakpoint thread"
+ gdb_py_test_silent_cmd "python blist\[1\].thread = 1" \
+ "set breakpoint thread" 0
+ gdb_test "python print (repr (blist\[1\]))" \
+ [build_bp_repr -number 2 -hits 7 -thread 1] \
+ "Check repr for a thread breakpoint"
+ gdb_py_test_silent_cmd "python blist\[1\].thread = None" \
+ "clear breakpoint thread" 0
gdb_test "python print (blist\[1\].type == gdb.BP_BREAKPOINT)" \
"True" "Check breakpoint type"
gdb_test "python print (blist\[0\].number)" \
"Set invisible breakpoint" 0
gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" \
"Get Breakpoint List" 0
- gdb_test "python print (ilist\[0\])" \
- "<gdb.Breakpoint object at $hex>" "Check invisible bp obj exists 1"
+ gdb_test "python print (repr (ilist\[0\]))" \
+ [build_bp_repr -number 2 -hits 0] "Check invisible bp obj exists 1"
gdb_test "python print (ilist\[0\].location)" \
"py-breakpoint\.c:$ibp_location*" "Check breakpoint location 1"
gdb_test "python print (ilist\[0\].visible)" \
"Set invisible breakpoint" 0
gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" \
"Get Breakpoint List" 0
- gdb_test "python print (ilist\[0\])" \
- "<gdb.Breakpoint object at $hex>" "Check invisible bp obj exists 2"
+ gdb_test "python print (repr (ilist\[0\]))" \
+ [build_bp_repr -number "-$decimal" -hits 0] \
+ "Check invisible bp obj exists 2"
gdb_test "python print (ilist\[0\].location)" \
"py-breakpoint\.c:$ibp_location*" "Check breakpoint location 2"
gdb_test "python print (ilist\[0\].visible)" \
set mult_line [gdb_get_line_number "Break at multiply."]
gdb_breakpoint ${mult_line}
gdb_test_no_output "enable count 1 2" "one shot enable"
+
+ # Find the Python gdb.Breakpoint object for breakpoint #2.
+ gdb_py_test_silent_cmd \
+ "python bp = \[b for b in gdb.breakpoints() if b.number == 2\]\[0\]" \
+ "Get breakpoint number 2" 0
+ gdb_test "python print (repr (bp))" \
+ [build_bp_repr -number 2 -hits 0 -enable_count 1]
+
# Python 2 doesn't support print in lambda function, so use a named
# function instead.
gdb_test_multiline "Define print_bp_enabled" \
# point where we don't have a current frame, and we don't want to
# require one.
gdb_py_test_silent_cmd "python main_func = gdb.lookup_global_symbol(\"main\")" "Lookup main" 1
+gdb_test "python print (repr (main_func))" "<gdb.Symbol print_name=main>" \
+ "test main_func.__repr__"
gdb_test "python print (main_func.is_function)" "True" "test main_func.is_function"
gdb_test "python print (gdb.lookup_global_symbol(\"junk\"))" "None" "test lookup_global_symbol(\"junk\")"
test_type_equality
}
}
+
+# Test __repr__().
+gdb_test "python print (repr (gdb.lookup_type ('char')))" \
+ "<gdb.Type code=TYPE_CODE_INT name=char>" "test __repr__()"