libdw/
2005-08-15  Roland McGrath  <roland@redhat.com>

	* dwarf_func_inline.c: New file.
	* Makefile.am (libdw_a_SOURCES): Add it.
	* libdw.h: Declare dwarf_func_inline, dwarf_func_inline_instances.
	* libdw.map: Add them.

	* dwarf_func_die.c: New file.
	* Makefile.am (libdw_a_SOURCES): Add it.
	* libdw.h: Declare dwarf_func_die.
	* libdw.map: Add it.  Bump version to ELFUTILS_0.114.

tests/
2005-08-15  Roland McGrath  <roland@redhat.com>

	* dwflmodtest.c (print_instance, print_inline): New functions.
	(print_func): Call print_inline.
	(options, parse_opt): Grok -i/--inlines.

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index c5d1503..17b8b3e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,15 @@
+2005-08-15  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_func_inline.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_func_inline, dwarf_func_inline_instances.
+	* libdw.map: Add them.
+
+	* dwarf_func_die.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_func_die.
+	* libdw.map: Add it.  Bump version to ELFUTILS_0.114.
+
 2005-08-10  Ulrich Drepper  <drepper@redhat.com>
 
 	* dwarf_getsrclines.c (dwarf_getsrclines): Correct fallout of renaming
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 097ec3a..ad6b28a 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -62,8 +62,10 @@
 		  dwarf_macro_param2.c dwarf_addrdie.c \
 		  dwarf_getfuncs.c dwarf_func_name.c dwarf_func_lowpc.c \
 		  dwarf_func_highpc.c dwarf_func_entrypc.c dwarf_func_file.c \
-		  dwarf_func_line.c dwarf_func_col.c dwarf_getsrc_file.c \
-		  libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c
+		  dwarf_func_line.c dwarf_func_col.c dwarf_func_die.c \
+		  dwarf_func_inline.c dwarf_getsrc_file.c \
+		  libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \
+		  libdw_visit_scopes.c
 
 
 if !MUDFLAP
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 786be22..e6b3059 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -508,6 +508,19 @@
 extern int dwarf_func_col (Dwarf_Func *func, int *colp)
      __nonnull_attribute__ (2);
 
+/* Get definition DIE of given function.  */
+extern Dwarf_Die *dwarf_func_die (Dwarf_Func *func, Dwarf_Die *die_mem)
+    __nonnull_attribute__ (2);
+
+/* Return nonzero if given function is an abstract inline definition.  */
+extern int dwarf_func_inline (Dwarf_Func *func);
+
+/* Find each concrete inlined instance of the abstract inline definition.  */
+extern int dwarf_func_inline_instances (Dwarf_Func *func,
+					int (*callback) (Dwarf_Die *, void *),
+					void *arg);
+
+
 
 /* Call callback function for each of the macro information entry for
    the CU.  */
diff --git a/libdw/libdw.map b/libdw/libdw.map
index fb4a62d..b54dea3 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -1,5 +1,5 @@
 ELFUTILS_0 { };
-ELFUTILS_0.111 {
+ELFUTILS_0.114 {
   global:
     dwarf_abbrevhaschildren;
     dwarf_addrdie;
@@ -29,9 +29,12 @@
     dwarf_formstring;
     dwarf_formudata;
     dwarf_func_col;
+    dwarf_func_die;
     dwarf_func_entrypc;
     dwarf_func_file;
     dwarf_func_highpc;
+    dwarf_func_inline;
+    dwarf_func_inline_instances;
     dwarf_func_line;
     dwarf_func_lowpc;
     dwarf_func_name;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 062b3dc..5f15cf9 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -342,6 +342,13 @@
 extern int __libdw_func_intval (Dwarf_Func *func, int *linep, int attval)
      __nonnull_attribute__ (1, 2) internal_function;
 
+/* Helper function to walk scopes.  */
+extern int __libdw_visit_scopes (unsigned int depth, Dwarf_Die *root,
+				 int (*visit) (unsigned int depth,
+					       Dwarf_Die *die, void *arg),
+				 void *arg)
+  __nonnull_attribute__ (2, 3) internal_function;
+
 /* Return error code of last failing function call.  This value is kept
    separately for each thread.  */
 extern int __dwarf_errno_internal (void);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index ee83376..ec7a22c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2005-08-15  Roland McGrath  <roland@redhat.com>
+
+	* dwflmodtest.c (print_instance, print_inline): New functions.
+	(print_func): Call print_inline.
+	(options, parse_opt): Grok -i/--inlines.
+
 2005-08-07  Roland McGrath  <roland@redhat.com>
 
 	* dwflmodtest.c: Print function details only if -f flag is given.
diff --git a/tests/dwflmodtest.c b/tests/dwflmodtest.c
index e2b7d3c..5155f6c 100644
--- a/tests/dwflmodtest.c
+++ b/tests/dwflmodtest.c
@@ -23,12 +23,93 @@
 #include <locale.h>
 #include <argp.h>
 #include <libdwfl.h>
+#include <dwarf.h>
 
+static bool show_inlines;
+
+struct info
+{
+  Dwarf_Die *cudie;
+  Dwarf_Addr dwbias;
+};
+
+static int
+print_instance (Dwarf_Die *instance, void *arg)
+{
+  const struct info *info = arg;
+
+  printf ("    inlined");
+
+  Dwarf_Files *files;
+  if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
+    {
+      Dwarf_Attribute attr_mem;
+      Dwarf_Word val;
+      if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
+				       &attr_mem), &val) == 0)
+	{
+	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
+	  int lineno = 0, colno = 0;
+	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
+					   &attr_mem), &val) == 0)
+	    lineno = val;
+	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
+					   &attr_mem), &val) == 0)
+	    colno = val;
+	  if (lineno == 0)
+	    {
+	      if (file != NULL)
+		printf (" from %s", file);
+	    }
+	  else if (colno == 0)
+	    printf (" at %s:%u", file, lineno);
+	  else
+	    printf (" at %s:%u:%u", file, lineno, colno);
+	}
+    }
+
+  Dwarf_Addr lo = -1, hi = -1, entry = -1;
+  if (dwarf_lowpc (instance, &lo) == 0)
+    lo += info->dwbias;
+  else
+    printf (" (lowpc => %s)", dwarf_errmsg (-1));
+  if (dwarf_highpc (instance, &hi) == 0)
+    hi += info->dwbias;
+  else
+    printf (" (highpc => %s)", dwarf_errmsg (-1));
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = INTUSE(dwarf_attr) (instance, DW_AT_entry_pc,
+					      &attr_mem);
+  if (attr != NULL)
+    {
+      if (INTUSE(dwarf_formaddr) (attr, &entry) == 0)
+	entry += info->dwbias;
+      else
+	printf (" (entrypc => %s)", dwarf_errmsg (-1));
+    }
+
+  if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
+    printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
+  if (entry != (Dwarf_Addr) -1)
+    printf (" => %#" PRIx64 "\n", entry);
+  else
+    puts ("");
+
+  return DWARF_CB_OK;
+}
+
+static void
+print_inline (Dwarf_Func *func, void *arg)
+{
+  if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
+    printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
+}
 
 static int
 print_func (Dwarf_Func *func, void *arg)
 {
-  const Dwarf_Addr dwbias = *(Dwarf_Addr *) arg;
+  const struct info *info = arg;
 
   const char *file = dwarf_func_file (func);
   int line = -1;
@@ -37,26 +118,35 @@
 
   printf ("  %s:%d: %s:", file, line, fct);
 
-  Dwarf_Addr lo = -1, hi = -1, entry = -1;
-  if (dwarf_func_lowpc (func, &lo) == 0)
-    lo += dwbias;
+  if (dwarf_func_inline (func))
+    {
+      puts (" inline function");
+      if (show_inlines)
+	print_inline (func, arg);
+    }
   else
-    printf (" (lowpc => %s)", dwarf_errmsg (-1));
-  if (dwarf_func_highpc (func, &hi) == 0)
-    hi += dwbias;
-  else
-    printf (" (highpc => %s)", dwarf_errmsg (-1));
-  if (dwarf_func_entrypc (func, &entry) == 0)
-    entry += dwbias;
-  else
-    printf (" (entrypc => %s)", dwarf_errmsg (-1));
+    {
+      Dwarf_Addr lo = -1, hi = -1, entry = -1;
+      if (dwarf_func_lowpc (func, &lo) == 0)
+	lo += info->dwbias;
+      else
+	printf (" (lowpc => %s)", dwarf_errmsg (-1));
+      if (dwarf_func_highpc (func, &hi) == 0)
+	hi += info->dwbias;
+      else
+	printf (" (highpc => %s)", dwarf_errmsg (-1));
+      if (dwarf_func_entrypc (func, &entry) == 0)
+	entry += info->dwbias;
+      else
+	printf (" (entrypc => %s)", dwarf_errmsg (-1));
 
-  if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
-      || entry != (Dwarf_Addr) -1)
-    printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
-	    lo, hi, entry);
-  else
-    puts ("");
+      if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
+	  || entry != (Dwarf_Addr) -1)
+	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
+		lo, hi, entry);
+      else
+	puts ("");
+    }
 
   return DWARF_CB_OK;
 }
@@ -80,9 +170,8 @@
       while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
 	{
 	  Dwarf_Die die_mem;
-	  Dwarf_Die *die = dwarf_offdie (dw, off + cuhl, &die_mem);
-
-	  (void) dwarf_getfuncs (die, print_func, &bias, 0);
+	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
+	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
 
 	  off = noff;
 	}
@@ -95,7 +184,8 @@
 
 static const struct argp_option options[] =
   {
-    { "functions", 'f', NULL, 0, N_("Additional show function names"), 0 },
+    { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
+    { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
     { NULL, 0, NULL, 0, NULL, 0 }
   };
 
@@ -113,6 +203,10 @@
       show_functions = true;
       break;
 
+    case 'i':
+      show_inlines = show_functions = true;
+      break;
+
     default:
       return ARGP_ERR_UNKNOWN;
     }