diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 4d133d1fe1..44df6db545 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -319,6 +319,21 @@ archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw)
   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);
+
+  return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>",
+                               Py_TYPE (self)->tp_name,
+                               gdbarch_bfd_arch_info (gdbarch)->arch_name,
+                               gdbarch_bfd_arch_info (gdbarch)->printable_name);
+}
+
 /* Implementation of gdb.architecture_names().  Return a list of all the
    BFD architecture names that GDB understands.  */
 
@@ -395,7 +410,7 @@ PyTypeObject arch_object_type = {
   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 */
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index 09fa74d862..6bca88d2fb 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -418,6 +418,51 @@ blpy_iter_is_valid (PyObject *self, PyObject *args)
   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 ());
+  for (struct symbol *symbol : block_iterator_range (block))
+    {
+      if(++written_symbols >= 6)
+        {
+          const int remaining = len - 5;
+          if (remaining == 1)
+            {
+              str = (str + "\n    ") + 
+                string_printf("... (%d more symbol)", len - 5);
+            }
+          else
+            {
+              str = (str + "\n    ") + 
+                string_printf("... (%d more symbols)", len - 5);
+            }
+
+          break;
+        }
+      str = (str + "\n    ") + symbol->print_name ();
+      if (written_symbols < len)
+        str = str + ",";
+    }
+  if(!str.empty ())
+    str += "\n";
+
+  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)
 {
@@ -482,7 +527,7 @@ PyTypeObject block_object_type = {
   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*/
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index becb04c91c..1dd746ba94 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -33,6 +33,7 @@
 #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");
@@ -981,6 +982,32 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
   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 number=%d hits=%d%s>",
+                               Py_TYPE (self)->tp_name,
+                               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
@@ -1406,7 +1433,7 @@ PyTypeObject breakpoint_object_type =
   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*/
@@ -1624,6 +1651,50 @@ bplocpy_dealloc (PyObject *py_self)
   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 += " address=0x";
+  str += string_printf 
+    ("%s", core_addr_to_string_nz (self->bp_loc->address));
+
+  if (self->bp_loc->requested_address != self->bp_loc->address)
+    {
+      str += " requested_address=0x";
+      str += string_printf 
+        ("%s", core_addr_to_string_nz (self->bp_loc->requested_address));
+    }
+  if (self->bp_loc->symtab != nullptr)
+    {
+      str += " source=";
+      str += self->bp_loc->symtab->filename;
+      str += ":";
+      str += string_printf ("%d", 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[] = {
@@ -1655,7 +1726,7 @@ PyTypeObject breakpoint_location_object_type =
   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*/
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index ff3d18504e..6cf9825d7f 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -378,6 +378,21 @@ sympy_dealloc (PyObject *obj)
   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
@@ -741,7 +756,7 @@ PyTypeObject symbol_object_type = {
   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*/
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index b9fa741177..283d595546 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1028,6 +1028,36 @@ typy_template_argument (PyObject *self, PyObject *args)
   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)
 {
@@ -1617,7 +1647,7 @@ PyTypeObject type_object_type =
   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*/
diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp
index 4f4b4aa766..597943ff68 100644
--- a/gdb/testsuite/gdb.python/py-arch.exp
+++ b/gdb/testsuite/gdb.python/py-arch.exp
@@ -27,6 +27,8 @@ if ![runto_main] {
 # 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.*" \
@@ -44,6 +46,10 @@ gdb_py_test_silent_cmd "python insn_list3 = arch.disassemble(pc, count=1)" \
 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"
diff --git a/gdb/testsuite/gdb.python/py-block.c b/gdb/testsuite/gdb.python/py-block.c
index a0c6e16560..7e26f2d1fe 100644
--- a/gdb/testsuite/gdb.python/py-block.c
+++ b/gdb/testsuite/gdb.python/py-block.c
@@ -30,9 +30,37 @@ int block_func (void)
   }
 }
 
+int no_locals_func (void)
+{
+  return block_func ();
+}
+
+int few_locals_func (void)
+{
+  int i = 0;
+  int j = 0;
+  int k = 0;
+  int x = 0;
+  int y = 0; 
+  return block_func ();
+}
+
+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. */
 }
diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp
index 3bdf97294a..dc2f2f53af 100644
--- a/gdb/testsuite/gdb.python/py-block.exp
+++ b/gdb/testsuite/gdb.python/py-block.exp
@@ -38,7 +38,7 @@ gdb_continue_to_breakpoint "Block break here."
 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> \{.*\}>" "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"
@@ -68,15 +68,46 @@ gdb_test_no_output "python block = block.superblock" "get superblock 2"
 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
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index 76094c95d1..77e44f6e3c 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -51,11 +51,13 @@ proc_with_prefix test_bkpt_basic { } {
 	return 0
     }
 
+    set repr_pattern "<gdb.Breakpoint number=-?$decimal hits=-?$decimal\( thread=$decimal\)?\( task=$decimal\)?\( enable_count=$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\]))" \
+	"$repr_pattern" "Check obj exists @main"
     gdb_test "python print (blist\[0\].location)" \
 	"main" "Check breakpoint location @main"
     gdb_test "python print (blist\[0\].pending)" "False" \
@@ -72,12 +74,12 @@ proc_with_prefix test_bkpt_basic { } {
 	"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\]))" \
+	"$repr_pattern" "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\]))" \
+	"$repr_pattern" "Check obj exists @mult_line"
 
     gdb_test "python print (blist\[1\].location)" \
 	"py-breakpoint\.c:${mult_line}*" \
@@ -225,14 +227,16 @@ proc_with_prefix test_bkpt_invisible { } {
 	return 0
     }
 
+    set repr_pattern "<gdb.Breakpoint number=-?$decimal hits=-?$decimal\( thread=$decimal\)?\( task=$decimal\)?\( enable_count=$decimal\)?>"
+
     delete_breakpoints
     set ibp_location [gdb_get_line_number "Break at multiply."]
     gdb_py_test_silent_cmd  "python ibp = gdb.Breakpoint(\"$ibp_location\", internal=False)" \
 	"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\]))" \
+	"$repr_pattern" "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)" \
@@ -244,8 +248,8 @@ proc_with_prefix test_bkpt_invisible { } {
 	"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\]))" \
+	"$repr_pattern" "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)" \
diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp
index 9ec2f44e9c..9bd5a35ed1 100644
--- a/gdb/testsuite/gdb.python/py-symbol.exp
+++ b/gdb/testsuite/gdb.python/py-symbol.exp
@@ -43,6 +43,8 @@ clean_restart ${binfile}
 # 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\")"
 
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index c245d41a1a..918216ddd6 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -388,3 +388,7 @@ if { [build_inferior "${binfile}-cxx" "c++"] == 0 } {
       test_type_equality
   }
 }
+
+# Test __repr__().
+gdb_test "python print (repr (gdb.lookup_type ('char')))" \
+      "<gdb.Type code=TYPE_CODE_INT name=char>" "test __repr__()"
