diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 053ccef..c283ec0 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -6153,24 +6153,73 @@ print_breakpoint_location (struct breakpoint *b,
     uiout->field_string ("what", event_location_to_string (b->location.get ()));
   else if (loc && loc->symtab)
     {
-      struct symbol *sym 
-	= find_pc_sect_function (loc->address, loc->section);
-      if (sym)
+      /* If a location is associated with an inlined symbol, print out
+	 information about its call site, too.  */
+      if (loc->symbol != NULL && SYMBOL_INLINED (loc->symbol))
 	{
+	  struct inlined_symbol *isym = (struct inlined_symbol *) (loc->symbol);
+	  struct symbol *sym
+	    = find_pc_sect_function (loc->address, loc->section);
+
+	  /* ISYM contains information about the inlined function, and
+	     LOC->SYMBOL describes the call site.  */
 	  uiout->text ("in ");
-	  uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+	  uiout->field_string ("func", SYMBOL_PRINT_NAME (loc->symbol));
 	  uiout->text (" ");
 	  uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
 	  uiout->text ("at ");
+
+	  const char *s = symtab_to_filename_for_display (isym->decl_file);
+          uiout->field_string ("file", s);
+
+	  uiout->text (":");
+	  if (uiout->is_mi_like_p ())
+	    {
+	      uiout->field_string ("fullname",
+				   symtab_to_fullname (isym->decl_file));
+	    }
+	  uiout->field_int ("line", isym->decl_line);
+	  uiout->text (" ");
+	  uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
+	  uiout->text ("inlined in ");
+	  if (sym != NULL)
+	    uiout->field_string ("call-site-func", SYMBOL_PRINT_NAME (sym));
+	  uiout->text (" ");
+	  uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
+	  uiout->text ("at ");
+	  s = symtab_to_filename_for_display (symbol_symtab (loc->symbol));
+	  uiout->field_string ("call-site-file", s);
+
+	  uiout->text (":");
+	  if (uiout->is_mi_like_p ())
+	    {
+	      s = symtab_to_fullname (symbol_symtab (loc->symbol));
+	      uiout->field_string ("call-site-fullname", s);
+	    }
+	  uiout->field_int ("call-site-line", SYMBOL_LINE (loc->symbol));
 	}
-      uiout->field_string ("file",
-			   symtab_to_filename_for_display (loc->symtab));
-      uiout->text (":");
+      else
+	{
+	  struct symbol *sym
+	    = find_pc_sect_function (loc->address, loc->section);
 
-      if (uiout->is_mi_like_p ())
-	uiout->field_string ("fullname", symtab_to_fullname (loc->symtab));
+	  if (sym)
+	    {
+	      uiout->text ("in ");
+	      uiout->field_string ("func", SYMBOL_PRINT_NAME (sym));
+	      uiout->text (" ");
+	      uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
+	      uiout->text ("at ");
+	    }
+	  uiout->field_string ("file",
+			       symtab_to_filename_for_display (loc->symtab));
+	  uiout->text (":");
+
+	  if (uiout->is_mi_like_p ())
+	    uiout->field_string ("fullname", symtab_to_fullname (loc->symtab));
       
-      uiout->field_int ("line", loc->line_number);
+	  uiout->field_int ("line", loc->line_number);
+	}
     }
   else if (loc)
     {
@@ -8986,6 +9035,7 @@ add_location_to_breakpoint (struct breakpoint *b,
   loc->gdbarch = loc_gdbarch;
   loc->line_number = sal->line;
   loc->symtab = sal->symtab;
+  loc->symbol = sal->symbol;
 
   set_breakpoint_location_function (loc,
 				    sal->explicit_pc || sal->explicit_line);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index d955184..2f10c3b 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -484,6 +484,11 @@ public:
      to find the corresponding source file name.  */
 
   struct symtab *symtab = NULL;
+
+  /* The symbol found by the location parser, if any.  This may be used to
+     ascertain when an event location was set at a different location than
+     the one originally selected by parsing, e.g., inlined symbols.  */
+  const struct symbol *symbol = NULL;
 };
 
 /* The possible return values for print_bpstat, print_it_normal,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c167a86..58cdc1a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -26755,6 +26755,14 @@ known.  If not known, this field is not present.
 The line number at which this breakpoint appears, if known.
 If not known, this field is not present.
 
+@item call-site-func
+@item call-site-file
+@item call-site-fullname
+@item call-site-line
+These fields describe the call site for a breakpoint set on an inlined function.
+The fields are analogous to those fields of the same name for normal breakpoint
+locations.
+
 @item at
 If the source file is not known, this field may be provided.  If
 provided, this holds the address of the breakpoint, possibly followed
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 0fdcd42..3b3193b 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -11470,6 +11470,35 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
   do_cleanups (cleanups);
 }
 
+/* Get the symtab representing the KIND of file of DIE in CU or NULL
+   if no such file exists.  KIND is any valid DWARF file attribute such as
+   DW_AT_decl_file or DW_AT_call_file.  */
+
+static struct symtab *
+dwarf2_file_symtab (unsigned int kind, struct die_info *die,
+		    struct dwarf2_cu *cu)
+{
+  struct attribute *attr = dwarf2_attr (die, kind, cu);
+
+  if (attr != NULL)
+    {
+      file_name_index file_index = (file_name_index) DW_UNSND (attr);
+      struct file_entry *fe;
+
+      if (cu->line_header != NULL)
+	fe = cu->line_header->file_name_at (file_index);
+      else
+	fe = NULL;
+
+      if (fe == NULL)
+	complaint (&symfile_complaints, _("file index out of range"));
+      else
+	return fe->symtab;
+    }
+
+  return NULL;
+}
+
 static void
 read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
@@ -11486,6 +11515,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
   VEC (symbolp) *template_args = NULL;
   struct template_symbol *templ_func = NULL;
+  struct inlined_symbol *isym = NULL;
+  struct symbol *symbol_storage = NULL;
 
   if (inlined_func)
     {
@@ -11540,13 +11571,28 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  templ_func = allocate_template_symbol (objfile);
 	  templ_func->base.is_cplus_template_function = 1;
+	  symbol_storage = (struct symbol *) templ_func;
 	  break;
 	}
     }
 
+  /* If we have an inlined symbol, we must also allocate a different
+     symbol.  */
+  if (inlined_func)
+    {
+      isym = allocate_inlined_symbol (objfile);
+      isym->decl_file = dwarf2_file_symtab (DW_AT_decl_file, die, cu);
+
+      attr = dwarf2_attr (die, DW_AT_decl_line, cu);
+      if (attr != NULL)
+	isym->decl_line = DW_UNSND (attr);
+
+      symbol_storage = (struct symbol *) isym;
+    }
+
   newobj = push_context (0, lowpc);
   newobj->name = new_symbol_full (die, read_type_die (die, cu), cu,
-			       (struct symbol *) templ_func);
+				  symbol_storage);
 
   /* If there is a location expression for DW_AT_frame_base, record
      it.  */
@@ -18948,25 +18994,11 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	  SYMBOL_LINE (sym) = DW_UNSND (attr);
 	}
 
-      attr = dwarf2_attr (die,
-			  inlined_func ? DW_AT_call_file : DW_AT_decl_file,
-			  cu);
-      if (attr)
-	{
-	  file_name_index file_index = (file_name_index) DW_UNSND (attr);
-	  struct file_entry *fe;
-
-	  if (cu->line_header != NULL)
-	    fe = cu->line_header->file_name_at (file_index);
-	  else
-	    fe = NULL;
-
-	  if (fe == NULL)
-	    complaint (&symfile_complaints,
-		       _("file index out of range"));
-	  else
-	    symbol_set_symtab (sym, fe->symtab);
-	}
+      struct symtab *symtab
+	= dwarf2_file_symtab (inlined_func ? DW_AT_call_file : DW_AT_decl_file,
+			      die, cu);
+      if (symtab != NULL)
+	symbol_set_symtab (sym, symtab);
 
       switch (die->tag)
 	{
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 497d520..55bfc93 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3472,6 +3472,7 @@ find_function_start_sal (struct symbol *sym, int funfirstline)
   fixup_symbol_section (sym, NULL);
   section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
   sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
+  sal.symbol = sym;
 
   if (funfirstline && sal.symtab != NULL
       && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
@@ -5998,6 +5999,19 @@ allocate_template_symbol (struct objfile *objfile)
   return result;
 }
 
+/* See description in symtab.h.  */
+
+struct inlined_symbol *
+allocate_inlined_symbol (struct objfile *objfile)
+{
+  struct inlined_symbol *result;
+
+  result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct inlined_symbol);
+  initialize_objfile_symbol_1 (&result->base);
+
+  return result;
+}
+
 /* See symtab.h.  */
 
 struct objfile *
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 341deca..a70ed54 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -910,6 +910,21 @@ struct template_symbol
   struct symbol **template_arguments;
 };
 
+/* A superclass of struct symbol used to represent an inlined symbol.
+   A symbol is really of this type if SYMBOL_INLINED is true.  */
+
+struct inlined_symbol
+{
+  /* The base class.  */
+  struct symbol base;
+
+  /* The inlined symbol's symtab.  */
+  struct symtab *decl_file;
+
+  /* Line number of the inlined symbol.  */
+  int decl_line;
+};
+
 
 /* Each item represents a line-->pc (or the reverse) mapping.  This is
    somewhat more wasteful of space than one might wish, but since only
@@ -1436,6 +1451,9 @@ struct symtab_and_line
   /* If PROBE is not NULL, then this is the objfile in which the probe
      originated.  */
   struct objfile *objfile;
+
+  /* The symbol for which this SaL was created.  */
+  struct symbol *symbol;
 };
 
 extern void init_sal (struct symtab_and_line *sal);
@@ -1676,4 +1694,6 @@ void initialize_objfile_symbol (struct symbol *);
 
 struct template_symbol *allocate_template_symbol (struct objfile *);
 
+extern struct inlined_symbol *allocate_inlined_symbol (struct objfile *);
+
 #endif /* !defined(SYMTAB_H) */
diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp
index 7be3a34..91766d4 100644
--- a/gdb/testsuite/gdb.opt/inline-break.exp
+++ b/gdb/testsuite/gdb.opt/inline-break.exp
@@ -24,6 +24,76 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
     return -1
 }
 
+# Return a string that may be used to match the output of "info break NUM".
+#
+# Optional arguments:
+#
+# source    - the name of the source file
+# func      - the name of the function
+# disp      - the event disposition
+# enabled   - enable state
+# locs      - number of locations
+# line      - source line number (ignored without -source)
+# inlined   - add inlined list, argument is a list of regexps to match
+#             *per location* (e.g., [list "" "foo at $source:$line"] will yield
+#             no inline for first location, and "inlined in foo at ..." for
+#             the second location)
+
+proc break_info_1 {num args} {
+    global decimal
+
+    # Column delimiter
+    set c {[\t ]+}
+
+    # Row delimiter
+    set end {[\r\n \t]+}
+
+    # Table header
+    set header "[join [list Num Type Disp Enb Address What] ${c}]"
+
+    # Get/configure any optional parameters.
+    parse_args [list {source ""} {func ".*"} {disp "keep"} \
+		    {enabled "y"} {locs 1} [list line $decimal] \
+		    {inlined {}} {type "breakpoint"}]
+
+    if {$source != ""} {
+	set source "/$source:$line"
+    }
+
+    # Result starts with the standard header.
+    set result "$header${end}"
+
+    # Set up for multi-location breakpoint marker.
+    if {$locs == 1} {
+	set multi ".*"
+    } else {
+	set multi "<MULTIPLE>${end}"
+    }
+    append result "[join [list $num $type $disp $enabled $multi] $c]"
+
+    # Add location info.
+    for {set i 1} {$i <= $locs} {incr i} {
+	if {$locs > 1} {
+	    append result "[join [list $num.$i $enabled] $c].*"
+	}
+
+	#  Add function/source file info.
+	append result "in $func at .*$source${end}"
+
+	# Add inline, if requested.
+	if {$i <= [llength $inlined]} {
+	    set inlined_regexp [lindex $inlined [expr $i - 1]]
+	} else {
+	    set inlined_regexp ""
+	}
+	if {$inlined_regexp != ""} {
+	    append result ".*inlined in $inlined_regexp${end}"
+	}
+    }
+
+    return $result
+}
+
 #
 # func1 is a static inlined function that is called once.
 # The result should be a single-location breakpoint.
@@ -111,3 +181,34 @@ gdb_test "print func1" \
 #
 gdb_test "print func2" \
     "\\\$.* = {int \\(int\\)} .* <func2>"
+
+# Test that "info break" reports the location of the breakpoints "inside"
+# the inlined functions
+
+set results(1) [break_info_1 1 -source $srcfile -func "func1" \
+		    -inlined [list "main at .*"]]
+set results(2) [break_info_1 2 -locs 2 -source $srcfile -func "func2" \
+		    -inlined [list "" "main at .*"]]
+set results(3) [break_info_1 3 -source $srcfile -func "func3b" \
+		    -inlined [list "main at .*"]]
+set results(4) [break_info_1 4 -locs 2 -source $srcfile -func "func4b" \
+		    -inlined [list "func4a at .*" "main at .*"]]
+set results(5) [break_info_1 5 -locs 2 -source $srcfile -func "func5b" \
+		    -inlined [list "" ".*"]]
+set results(6) [break_info_1 6 -locs 3 -source $srcfile -func "func6b" \
+		    -inlined [list "" ".*"]]
+set results(7) [break_info_1 7 -locs 2 -source $srcfile -func "func7b" \
+		    -inlined [list ".*" ".*"]]
+set results(8) [break_info_1 8 -locs 3 -source $srcfile -func "func8b"\
+		    -inlined [list "" ".*" ".*"]]
+
+for {set i 1} {$i <= [llength [array names results]]} {incr i} {
+    send_log "Expecting: $results($i)\n"
+    gdb_test "info break $i" $results($i)
+}
+
+# A quick check that MI is outputting new call-site parameters.
+gdb_test "interpreter-exec mi -break-info 1" \
+    ".*,call-site-func=\"main\",call-site-file=\".*\",call-site-fullname=\".*\",call-site-line=\".*\".*"
+
+unset -nocomplain results
