diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8d780ac758..489dab5ca1 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -377,6 +377,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-instruction.c \
 	python/py-lazy-string.c \
 	python/py-linetable.c \
+	python/py-minsymbol.c \
 	python/py-newobjfileevent.c \
 	python/py-objfile.c \
 	python/py-param.c \
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 1035be33f0..d91f6e35c5 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -158,6 +158,7 @@ optional arguments while skipping others.  Example:
 * Frames In Python::            Accessing inferior stack frames from Python.
 * Blocks In Python::            Accessing blocks from Python.
 * Symbols In Python::           Python representation of symbols.
+* Minimal Symbols In Python::   Python representation of minimal symbols.
 * Symbol Tables In Python::     Python representation of symbol tables.
 * Line Tables In Python::       Python representation of line tables.
 * Breakpoints In Python::       Manipulating breakpoints using Python.
@@ -4878,6 +4879,145 @@ The value does not actually exist in the program.
 The value's address is a computed location.
 @end vtable
 
+@node Minimal Symbols In Python
+@subsubsection Python representation of Minimal Symbols.
+
+@cindex minsymbols in python
+@tindex gdb.MinSymbol
+
+@value{GDBN} represents every variable, function and type as an
+entry in a symbol table.  @xref{Symbols, ,Examining the Symbol Table}.
+Typical symbols like functions, variables, etc are represented by
+gdb.Symbol objects in Python.  Some symbols are defined with less
+information associated with them, like linker script variables
+or assembly labels.  Python represents these minimal symbols in @value{GDBN}
+with the @code{gdb.MinSymbol} object.
+
+The following minimal symbol-related functions are available in the @code{gdb}
+module:
+
+@findex gdb.lookup_minimal_symbol
+@defun gdb.lookup_minimal_symbol (name @r{[}, sfile@r{]}, objfile@r{[})
+This function searches for a minimal symbol by name.
+The search scope can be restricted by the sfile and objfile arguments.
+
+@var{name} is the name of the minimal symbol.  It must be a string.
+The optional @var{sfile} argument restricts the search to the source file
+in which the minimal symbol was defined.
+The @var{sfile} argument must be a string.  The optional @var{objfile}
+restricts the search to the objfile that contains the minimal symbol.
+The @var{objfile} argument must be a @code{gdb.Objfile} object.
+
+The result is a @code{gdb.MinSymbol} object or @code{None} if the symbol
+is not found.
+@end defun
+
+A @code{gdb.MinSymbol} object has the following attributes:
+
+@defvar MinSymbol.name
+The name of the symbol as a string.  This attribute is not writable.
+@end defvar
+
+@defvar MinSymbol.linkage_name
+The name of the symbol, as used by the linker (i.e., may be mangled).
+This attribute is not writable.
+@end defvar
+
+@defvar MinSymbol.print_name
+The name of the symbol in a form suitable for output.  This is either
+@code{name} or @code{linkage_name}, depending on whether the user
+asked @value{GDBN} to display demangled or mangled names.
+@end defvar
+
+@defvar MinSymbol.filename
+The file name of the source file where the minimal symbol is defined.  This
+value may represent filenames used internally by the compiler rather
+than a viewable/editable source file.
+@end defvar
+
+@defvar MinSymbol.section
+The name of the binary section containing this minimal symbol.
+@end defvar
+
+@defvar MinSymbol.is_code
+@code{True} if the minimal symbol is a function or a method.
+@end defvar
+
+@defvar MinSymbol.is_data
+@code{True} if the symbol is a variable or other data.
+@end defvar
+
+A @code{gdb.MinSymbol} object has the following methods:
+
+@defun MinSymbol.is_valid ()
+Returns @code{True} if the @code{gdb.MinSymbol} object is valid,
+@code{False} if not.  A @code{gdb.MinSymbol} object can become invalid if
+the symbol it refers to does not exist in @value{GDBN} any longer.
+All other @code{gdb.MinSymbol} methods will throw an exception if it is
+invalid at the time the method is called.
+@end defun
+
+@defun MinSymbol.value ()
+Compute the value of the minimal symbol, as a @code{gdb.Value}.  The value
+returned represents the address of the minimal symbol.  Since minimal symbols
+represent objects without rich type information, the @code{gdb.Type}
+associated with the @code{gdb.Value} objects will be limited to whether
+the minimal symbol describes executable code or data.
+@end defun
+
+The available types for @code{gdb.MinSymbol} are represented
+as constants in the @code{gdb} module.  They are distinctly separate from the
+types represented by the @code{gdb.Type} object.
+
+@vtable @code
+@vindex MINSYMBOL_TYPE_UNKNOWN
+@item gdb.MINSYMBOL_TYPE_UNKNOWN
+This is used when the type has not been discovered or none of the
+following types apply.  This usually indicates an error either
+in the symbol information or in @value{GDBN}'s handling of symbols.
+
+@vindex MINSYMBOL_TYPE_TEXT
+@item gdb.MINSYMBOL_TYPE_TEXT
+This type represents executable code.
+
+@vindex MINSYMBOL_TYPE_TEXT_GNU_IFUNC
+@item gdb.MINSYMBOL_TYPE_TEXT_GNU_IFUNC
+This type represents executable code that returns the address
+of executable code.
+
+@vindex MINSYMBOL_TYPE_SLOT_GOT_PLT
+@item gdb.MINSYMBOL_TYPE_SLOT_GOT_PLT
+This type represents GOT for .plt sections.
+
+@vindex MINSYMBOL_TYPE_DATA
+@item gdb.MINSYMBOL_TYPE_DATA
+This type represents generally initialized (nonzero) data.
+
+@vindex MINSYMBOL_TYPE_BSS
+@item gdb.MINSYMBOL_TYPE_BSS
+This type represents generally uninitialized (zeroed) data.
+
+@vindex MINSYMBOL_TYPE_ABS
+@item gdb.MINSYMBOL_TYPE_ABS
+This type represents generally absolute (non-relocatable) data.
+
+@vindex MINSYMBOL_TYPE_SOLIB_TRAMPOLINE
+@item gdb.MINSYMBOL_TYPE_SOLIB_TRAMPOLINE
+This type represents the start address of a shared library trampoline entry.
+
+@vindex MINSYMBOL_TYPE_FILE_TEXT
+@item gdb.MINSYMBOL_TYPE_FILE_TEXT
+This type represents the static version of gdb.MINSYMBOL_TYPE_TEXT.
+
+@vindex MINSYMBOL_TYPE_FILE_DATA
+@item gdb.MINSYMBOL_TYPE_FILE_DATA
+This type represents the static version of gdb.MINSYMBOL_TYPE_DATA.
+
+@vindex MINSYMBOL_TYPE_FILE_BSS
+@item gdb.MINSYMBOL_TYPE_FILE_BSS
+This type represents the static version of gdb.MINSYMBOL_TYPE_BSS.
+@end vtable
+
 @node Symbol Tables In Python
 @subsubsection Symbol table representation in Python
 
diff --git a/gdb/python/py-minsymbol.c b/gdb/python/py-minsymbol.c
new file mode 100644
index 0000000000..44e19ddf2f
--- /dev/null
+++ b/gdb/python/py-minsymbol.c
@@ -0,0 +1,492 @@
+/* Python interface to minsymbols.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "block.h"
+#include "exceptions.h"
+#include "frame.h"
+#include "symtab.h"
+#include "python-internal.h"
+#include "objfiles.h"
+#include "value.h"
+#include "py-ref.h"
+
+typedef struct msympy_symbol_object {
+  PyObject_HEAD
+
+  /* The GDB bound_minimal_symbol structure this object is wrapping.  */
+  struct bound_minimal_symbol bound;
+
+  /* A minsym object is associated with an objfile, so keep track with
+     doubly-linked list, rooted in the objfile.  This lets us
+     invalidate the underlying struct minimal_symbol when the objfile is
+     deleted.  */
+  struct msympy_symbol_object *prev;
+  struct msympy_symbol_object *next;
+} minsym_object;
+
+/* Return the symbol that is wrapped by this symbol object.  */
+static struct minimal_symbol *
+minsym_object_to_minsym (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &minsym_object_type))
+    return NULL;
+  return ((minsym_object *) obj)->bound.minsym;
+}
+
+static struct objfile *
+minsym_object_to_objfile (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &minsym_object_type))
+    return NULL;
+  return ((minsym_object *) obj)->bound.objfile;
+}
+
+/* Require a valid symbol.  All access to minsym_object->symbol should be
+   gated by this call.  */
+#define MSYMPY_REQUIRE_VALID(minsym_obj, minsym)	\
+  do {							\
+    minsym = minsym_object_to_minsym (minsym_obj);	\
+    if (minsym == NULL)					\
+      {							\
+	PyErr_SetString (PyExc_RuntimeError,		\
+			 _("MinSymbol is invalid."));	\
+	return NULL;					\
+      }							\
+  } while (0)
+
+#define MSYMPY_REQUIRE_VALID_BOUND(minsym_obj, minsym, objfile)	\
+  do {								\
+    minsym = minsym_object_to_minsym (minsym_obj);		\
+    objfile = minsym_object_to_objfile (minsym_obj);		\
+    if (minsym == NULL || objfile == NULL)			\
+      {								\
+	PyErr_SetString (PyExc_RuntimeError,			\
+			 _("MinSymbol is invalid."));		\
+	return NULL;						\
+      }								\
+  } while (0)
+
+static const struct objfile_data *msympy_objfile_data_key;
+
+static PyObject *
+msympy_str (PyObject *self)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return PyString_FromString (MSYMBOL_PRINT_NAME (minsym));
+}
+
+static PyObject *
+msympy_get_name (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return PyString_FromString (MSYMBOL_NATURAL_NAME (minsym));
+}
+
+static PyObject *
+msympy_get_file_name (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return PyString_FromString (minsym->filename);
+}
+
+static PyObject *
+msympy_get_linkage_name (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return PyString_FromString (MSYMBOL_LINKAGE_NAME (minsym));
+}
+
+static PyObject *
+msympy_get_print_name (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return msympy_str (self);
+}
+
+static PyObject *
+msympy_get_section (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+  struct objfile *objfile = NULL;
+  struct obj_section *section;
+  const char *name;
+
+  MSYMPY_REQUIRE_VALID_BOUND (self, minsym, objfile);
+
+  section = MSYMBOL_OBJ_SECTION (objfile, minsym);
+  if (section)
+    {
+      name = bfd_section_name (objfile->obfd, section->the_bfd_section);
+      if (name)
+	return PyString_FromString (name);
+    }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+msympy_get_type (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+  return PyInt_FromLong (MSYMBOL_TYPE (minsym));
+}
+
+static PyObject *
+msympy_is_valid (PyObject *self, PyObject *args)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  minsym = minsym_object_to_minsym (self);
+  if (minsym == NULL)
+    Py_RETURN_FALSE;
+
+  Py_RETURN_TRUE;
+}
+
+static struct gdbarch *
+minsym_gdbarch (PyObject *minsym_obj)
+{
+  return get_objfile_arch (minsym_object_to_objfile (minsym_obj));
+}
+
+static struct type *
+minsym_type (PyObject *minsym_obj)
+{
+  struct type *type;
+
+  switch (minsym_object_to_minsym (minsym_obj)->type)
+    {
+    case mst_text:
+    case mst_solib_trampoline:
+    case mst_file_text:
+    case mst_text_gnu_ifunc:
+    case mst_slot_got_plt:
+      type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_func_ptr;
+      break;
+
+    case mst_data:
+    case mst_abs:
+    case mst_bss:
+    case mst_file_data:
+    case mst_file_bss:
+      type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_data_ptr;
+      break;
+
+    case mst_unknown:
+    default:
+      type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_void;
+      break;
+    }
+
+  return type;
+}
+
+static PyObject *
+msympy_is_code (PyObject *self, PyObject *args)
+{
+  struct minimal_symbol *minsym = NULL;
+  struct type *type;
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  type = builtin_type (minsym_gdbarch (self))->builtin_func_ptr;
+
+  if (minsym_type (self) == type)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+static PyObject *
+msympy_is_data (PyObject *self, PyObject *args)
+{
+  struct minimal_symbol *minsym = NULL;
+  struct type *type;
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  type = builtin_type (minsym_gdbarch (self))->builtin_data_ptr;
+
+  if (minsym_type (self) == type)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+/* Implementation of gdb.MinSymbol.value (self) -> gdb.Value.  Returns
+   the value of the symbol, or an error in various circumstances.  */
+
+static PyObject *
+msympy_value (PyObject *self, PyObject *args)
+{
+  minsym_object *minsym_obj = (minsym_object *)self;
+  struct minimal_symbol *minsym = NULL;
+  struct value *value = NULL;
+
+  if (!PyArg_ParseTuple (args, ""))
+    return NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+  TRY
+    {
+      value = value_at_lazy (minsym_type (self),
+			     BMSYMBOL_VALUE_ADDRESS (minsym_obj->bound));
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+  END_CATCH
+
+  return value_to_value_object (value);
+}
+
+static void
+set_symbol (minsym_object *obj, struct bound_minimal_symbol *bound)
+{
+  obj->bound = *bound;
+  obj->prev = NULL;
+  if (bound->objfile)
+    {
+      obj->next = (minsym_object *) objfile_data (bound->objfile,
+						  msympy_objfile_data_key);
+      if (obj->next)
+	obj->next->prev = obj;
+      set_objfile_data (bound->objfile, msympy_objfile_data_key, obj);
+    }
+  else
+    obj->next = NULL;
+}
+
+static PyObject *
+bound_minsym_to_minsym_object (struct bound_minimal_symbol *bound)
+{
+  minsym_object *msym_obj;
+
+  msym_obj = PyObject_New (minsym_object, &minsym_object_type);
+  if (msym_obj)
+    set_symbol (msym_obj, bound);
+
+  return (PyObject *) msym_obj;
+}
+
+static void
+msympy_dealloc (PyObject *obj)
+{
+  minsym_object *msym_obj = (minsym_object *) obj;
+
+  if (msym_obj->prev)
+    msym_obj->prev->next = msym_obj->next;
+  else if (msym_obj->bound.objfile)
+    set_objfile_data (msym_obj->bound.objfile,
+		      msympy_objfile_data_key, msym_obj->next);
+  if (msym_obj->next)
+    msym_obj->next->prev = msym_obj->prev;
+  msym_obj->bound.minsym = NULL;
+  msym_obj->bound.objfile = NULL;
+}
+
+/* Implementation of
+   gdb.lookup_minimal_symbol (name, [sfile, [objfile]]) -> symbol or None.  */
+
+PyObject *
+gdbpy_lookup_minimal_symbol (PyObject *self, PyObject *args, PyObject *kw)
+{
+  const char *name, *sfile = NULL;
+  struct objfile *objfile = NULL;
+  static const char *keywords[] = { "name", "sfile", "objfile", NULL };
+  struct bound_minimal_symbol bound_minsym = {};
+  PyObject *msym_obj = NULL, *sfile_obj = NULL, *objfile_obj = NULL;
+  gdb::unique_xmalloc_ptr<char> sfile_tmp;
+
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|OO", keywords, &name,
+					&sfile_obj, &objfile_obj))
+    return NULL;
+
+  if (sfile_obj && sfile_obj != Py_None)
+    {
+      sfile_tmp = gdbpy_obj_to_string (sfile_obj);
+      sfile = sfile_tmp.get ();
+    }
+
+  if (objfile_obj && objfile_obj != Py_None)
+    {
+      objfile = objfpy_object_to_objfile (objfile_obj);
+      if (!objfile)
+	return NULL;
+    }
+
+  TRY
+    {
+      bound_minsym = lookup_minimal_symbol (name, sfile, objfile);
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+  END_CATCH
+
+  if (bound_minsym.minsym)
+    msym_obj = bound_minsym_to_minsym_object (&bound_minsym);
+
+  if (msym_obj)
+    return msym_obj;
+
+  Py_RETURN_NONE;
+}
+
+static void
+del_objfile_msymbols (struct objfile *objfile, void *datum)
+{
+  minsym_object *obj = (minsym_object *) datum;
+  while (obj)
+    {
+      minsym_object *next = obj->next;
+
+      obj->bound.minsym = NULL;
+      obj->bound.objfile = NULL;
+      obj->next = NULL;
+      obj->prev = NULL;
+
+      obj = next;
+    }
+}
+
+int
+gdbpy_initialize_minsymbols (void)
+{
+  if (PyType_Ready (&minsym_object_type) < 0)
+    return -1;
+
+  msympy_objfile_data_key
+    = register_objfile_data_with_cleanup (NULL, del_objfile_msymbols);
+
+  if (PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_UNKNOWN",
+			       mst_unknown) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT",
+				  mst_text) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT_GNU_IFUNC",
+				  mst_text_gnu_ifunc) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SLOT_GOT_PLT",
+				  mst_slot_got_plt) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_DATA",
+				  mst_data) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_BSS", mst_bss) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_ABS", mst_abs) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SOLIB_TRAMPOLINE",
+				  mst_solib_trampoline) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_TEXT",
+				  mst_file_text) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_DATA",
+				  mst_file_data) < 0
+      || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_BSS",
+				  mst_file_bss) < 0)
+    return -1;
+
+  return gdb_pymodule_addobject (gdb_module, "MinSymbol",
+				 (PyObject *) &minsym_object_type);
+}
+
+
+
+static gdb_PyGetSetDef minsym_object_getset[] = {
+  { "name", msympy_get_name, NULL,
+    "Name of the minimal symbol, as it appears in the source code.", NULL },
+  { "linkage_name", msympy_get_linkage_name, NULL,
+    "Name of the minimal symbol, as used by the linker (i.e., may be mangled).",
+    NULL },
+  { "filename", msympy_get_file_name, NULL,
+    "Name of source file that contains this minimal symbol. Only applies for"
+    " mst_file_*.",
+    NULL },
+  { "print_name", msympy_get_print_name, NULL,
+    "Name of the minimal symbol in a form suitable for output.\n\
+This is either name or linkage_name, depending on whether the user asked GDB\n\
+to display demangled or mangled names.", NULL },
+  { "section", msympy_get_section, NULL,
+    "Section that contains this minimal symbol, if any", NULL, },
+  { "type", msympy_get_type, NULL,
+    "Type that this minimal symbol represents." },
+  { NULL }  /* Sentinel */
+};
+
+static PyMethodDef minsym_object_methods[] = {
+  { "is_valid", msympy_is_valid, METH_NOARGS,
+    "is_valid () -> Boolean.\n\
+Return true if this minimal symbol is valid, false if not." },
+  { "is_code", msympy_is_code, METH_NOARGS,
+    "is_code () -> Boolean.\n\
+Return true if this minimal symbol represents code." },
+  { "is_data", msympy_is_data, METH_NOARGS,
+    "is_data () -> Boolean.\n\
+Return true if this minimal symbol represents data." },
+  { "value", msympy_value, METH_VARARGS,
+    "value ([frame]) -> gdb.Value\n\
+Return the value of the minimal symbol." },
+  {NULL}  /* Sentinel */
+};
+
+PyTypeObject minsym_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "gdb.MinSymbol",		  /*tp_name*/
+  sizeof (minsym_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  msympy_dealloc,		  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  msympy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB minimal symbol object",	  /*tp_doc */
+  0,				  /*tp_traverse */
+  0,				  /*tp_clear */
+  0,				  /*tp_richcompare */
+  0,				  /*tp_weaklistoffset */
+  0,				  /*tp_iter */
+  0,				  /*tp_iternext */
+  minsym_object_methods,	  /*tp_methods */
+  0,				  /*tp_members */
+  minsym_object_getset		  /*tp_getset */
+};
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 2e24d0f3ff..736027a7a7 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -417,6 +417,15 @@ objfpy_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+struct objfile *
+objfpy_object_to_objfile (PyObject *self)
+{
+  objfile_object *obj = (objfile_object *) self;
+  OBJFPY_REQUIRE_VALID (obj);
+
+  return obj->objfile;
+}
+
 /* Implementation of gdb.Objfile.add_separate_debug_file (self) -> Boolean.  */
 
 static PyObject *
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 1812abb5b7..35368f205d 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -366,6 +366,8 @@ extern PyTypeObject block_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("block_object");
 extern PyTypeObject symbol_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symbol_object");
+extern PyTypeObject minsym_object_type
+     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("minsym_object");
 extern PyTypeObject event_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
 extern PyTypeObject breakpoint_object_type
@@ -475,6 +477,8 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
 PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args,
 				      PyObject *kw);
+PyObject *gdbpy_lookup_minimal_symbol (PyObject *self, PyObject *args,
+				       PyObject *kw);
 PyObject *gdbpy_start_recording (PyObject *self, PyObject *args);
 PyObject *gdbpy_current_recording (PyObject *self, PyObject *args);
 PyObject *gdbpy_stop_recording (PyObject *self, PyObject *args);
@@ -516,6 +520,7 @@ PyObject *objfpy_get_frame_filters (PyObject *, void *);
 PyObject *objfpy_get_frame_unwinders (PyObject *, void *);
 PyObject *objfpy_get_xmethods (PyObject *, void *);
 PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw);
+struct objfile *objfpy_object_to_objfile (PyObject *self);
 
 PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
 
@@ -552,6 +557,8 @@ int gdbpy_initialize_commands (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_symbols (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_minsymbols (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_symtabs (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_blocks (void)
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8fbce78469..2fc57ae2bb 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1684,6 +1684,7 @@ do_start_initialization ()
       || gdbpy_initialize_record () < 0
       || gdbpy_initialize_btrace () < 0
       || gdbpy_initialize_symbols () < 0
+      || gdbpy_initialize_minsymbols () < 0
       || gdbpy_initialize_symtabs () < 0
       || gdbpy_initialize_blocks () < 0
       || gdbpy_initialize_functions () < 0
@@ -1984,6 +1985,10 @@ a boolean indicating if name is a field of the current implied argument\n\
     METH_VARARGS | METH_KEYWORDS,
     "lookup_global_symbol (name [, domain]) -> symbol\n\
 Return the symbol corresponding to the given name (or None)." },
+{ "lookup_minimal_symbol", (PyCFunction) gdbpy_lookup_minimal_symbol,
+    METH_VARARGS | METH_KEYWORDS,
+    "lookup_minimal_symbol (name, [sfile, [objfile]]) -> minsym\n\
+Return the symbol corresponding to the given name (or None)." },
 
   { "lookup_objfile", (PyCFunction) gdbpy_lookup_objfile,
     METH_VARARGS | METH_KEYWORDS,
diff --git a/gdb/testsuite/gdb.python/py-minsymbol.c b/gdb/testsuite/gdb.python/py-minsymbol.c
new file mode 100644
index 0000000000..4ce111d306
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-minsymbol.c
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2018 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see  <http://www.gnu.org/licenses/>.  */
+
+/* So we have a data section */
+const char foo[] = "somestring";
+
+asm("\
+.section .text\n\
+.global text_msym\n\
+text_msym:\n\
+	.byte 0\n\
+.section .data\n\
+.globl data_msym\n\
+data_msym:\n\
+	.asciz \"minsym text\"\n\
+data_msym2:\n\
+	.asciz \"minsym2 text\"\n\
+");
+
+int
+main(void)
+{
+	return 0;
+}
diff --git a/gdb/testsuite/gdb.python/py-minsymbol.exp b/gdb/testsuite/gdb.python/py-minsymbol.exp
new file mode 100644
index 0000000000..16bbaf64e1
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-minsymbol.exp
@@ -0,0 +1,67 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing values to Python.
+
+load_lib gdb-python.exp
+
+standard_testfile
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+    return -1
+}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+# Test looking up missing value
+gdb_test "python print (gdb.lookup_minimal_symbol('xyz'))" "None" "lookup missing symbol"
+
+# Test handling of invalid arguments
+gdb_test "python print (gdb.lookup_minimal_symbol(None))" ".*TypeError: argument 1 must be str(ing)?, not None.*" "lookup_minimal_symbol name arg None"
+gdb_test "python print (gdb.lookup_minimal_symbol('text_msym', None))" "text_msym" "lookup_minimal_symbol sfile arg None"
+gdb_test "python print (gdb.lookup_minimal_symbol('text_msym', objfile=None))" "text_msym" "lookup_minimal_symbol objfile arg None"
+
+# Test looking up a minimal symbol of text type
+gdb_test "print text_msym" " = \{<text variable, no debug info>\} 0x\[0-9a-f\]* <text_msym>" "locate text_msym with print"
+gdb_py_test_silent_cmd "python x = gdb.lookup_minimal_symbol('text_msym')" "Lookup text_msym" 1
+gdb_test "python print (x)" "text_msym" "lookup text min sym"
+gdb_test "python print (x.name)" "text_msym" "get text minsym name"
+gdb_test "python print (x.linkage_name)" "text_msym" "get text minsym linkage_name"
+# Using asm() ends up inventing a compiler-dependent filename
+gdb_test "python print (x.filename)" ".*" "get text minsym filename"
+gdb_test "python print (x.print_name)" "text_msym" "get text minsym print_name"
+gdb_test "python print (x.section)" ".text" "get text minsym section"
+gdb_test "python print (x.value())" "0x\[0-9a-f\]*.*" "get text minsym value"
+gdb_test "python print (x.value().type)" "void \\(\\*\\)\\(\\)" "get text minsym value type"
+
+# Test looking up a minimal symbol of data type
+gdb_test "print (void *)data_msym" "0x\[0-9a-f\]*.*" "locate data_msym with print"
+gdb_py_test_silent_cmd "python x = gdb.lookup_minimal_symbol('data_msym')" "Lookup data_msym" 1
+gdb_test "python print (x.name)" "data_msym" "get data minsym name"
+gdb_test "python print (x.linkage_name)" "data_msym" "get data minsym linkage_name"
+# Using asm() ends up inventing a compiler-dependent filename
+gdb_test "python print (x.filename)" ".*" "get data minsym filename"
+gdb_test "python print (x.print_name)" "data_msym" "get data minsym print_name"
+gdb_test "python print (x.section)" ".data" "get data minsym section"
+gdb_test "python print (x.value())" "0x\[0-9a-f\]*.*" "get data minsym value"
+
+gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'foobar.c'))" "None" "Lookup data_msym2 in foobar.c src"
+gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'py-minsymbol.c'))" "data_msym2" "Lookup data_msym2 in py-minsymbol.c src"
+
+gdb_unload
+gdb_test "python print (x.is_valid())" "False" "Test symbol non-validity"
+gdb_test_no_output "python a = None" "Test symbol destructor"
