public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Patch: DWARF browser
@ 2011-04-26 20:09 Tom Tromey
  2011-04-26 20:22 ` David Miller
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Tom Tromey @ 2011-04-26 20:09 UTC (permalink / raw)
  To: Binutils Development

I have been wanting a nicer way to browse DWARF, so I came up with the
appended.  It is an Emacs mode for DWARF browsing, plus a couple of new
supporting readelf features.

The simplest way to browse is just M-x dwarf-browse, then enter a file
name.  This will show a high-level view of the debug info (just the CU
DIEs).  If you want to see more details, you can click or RET on the
`...' fields, and the mode will expand more DIEs.

The mode has a bit of font-lock support and it also has support for
following DIE references (pushing the mark while doing so).

I needed 2 readelf features to make this work nicely.  One, a way to
elide DIEs at a certain depth.  Two, a way to then print sibling DIEs
starting with a certain DIE.

I don't know if you'd want the .el code in binutils or not.  It is no
problem if not, I will just put it in ELPA.  I'll probably add features
to it as I need them.

It would be handy if the readelf changes could go in regardless of what
happens to the lisp code.

Let me know what you think.

Tom

2011-04-26  Tom Tromey  <tromey@redhat.com>

	* dwarf-mode.el: New file.
	* dwarf.c (dwarf_cutoff_level, dwarf_start_die): New globals.
	(read_and_display_attr_value): Also check debug_info_p.
	(process_debug_info): Handle dwarf_start_die and
	dwarf_cutoff_level.
	* dwarf.h (dwarf_cutoff_level, dwarf_start_die): Declare.
	* readelf.c (usage): Update.
	(OPTION_DWARF_DEPTH): New macro.
	(OPTION_DWARF_START): Likewise.
	(options): Add dwarf-depth and dwarf-start entries.
	(parse_args): Handle OPTION_DWARF_START and OPTION_DWARF_DEPTH.

From a913cbeb77711c1d3d2c7332b003c2899df447b8 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Mon, 25 Apr 2011 07:07:04 -0600
Subject: [PATCH] add dwarf-depth and dwarf-start

---
 binutils/ChangeLog         |   14 ++++
 binutils/doc/binutils.texi |   24 ++++++
 binutils/dwarf-mode.el     |  167 ++++++++++++++++++++++++++++++++++++++++++++
 binutils/dwarf.c           |   56 ++++++++++++---
 binutils/dwarf.h           |    3 +
 binutils/readelf.c         |   23 ++++++
 6 files changed, 275 insertions(+), 12 deletions(-)
 create mode 100644 binutils/dwarf-mode.el

diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 45a7ff7..0499021 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -3957,6 +3957,8 @@ readelf [@option{-a}|@option{--all}]
         [@option{-c}|@option{--archive-index}]
         [@option{-w[lLiaprmfFsoRt]}|
          @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index]]
+        [@option{--dwarf-depth=@var{n}}]
+        [@option{--dwarf-start=@var{n}}]
         [@option{-I}|@option{--histogram}]
         [@option{-v}|@option{--version}]
         [@option{-W}|@option{--wide}]
@@ -4124,6 +4126,28 @@ Note: the @option{=frames-interp} option will display the interpreted
 contents of a .debug_frame section whereas the @option{=frames} option
 dumps the contents in a raw format.
 
+Note: the output from the @option{=info} option can also be affected
+by the options @option{--dwarf-depth} and @option{--dwarf-start}.
+
+@item --dwarf-depth=@var{n}
+Limit the dump of the @code{.debug_info} section to @var{n} children.
+This is only useful with @option{--debug-dump=info}.  The default is
+to print all DIEs; the special value 0 for @var{n} will also have this
+effect.
+
+With a non-zero value for @var{n}, DIEs at or deeper than @var{n}
+levels will not be printed.  The range for @var{n} is zero-based.
+
+@item --dwarf-start=@var{n}
+Print only DIEs beginning with the DIE numbered @var{n}.  This is only
+useful with @option{--debug-dump=info}.
+
+If specified, this option will suppress printing of any header
+information and all DIEs before the DIE numbered @var{n}.  Only
+siblings and children of the specified DIE will be printed.
+
+This can be used in conjunction with @option{--dwarf-depth}.
+
 @item -I
 @itemx --histogram
 Display a histogram of bucket list lengths when displaying the contents
diff --git a/binutils/dwarf-mode.el b/binutils/dwarf-mode.el
new file mode 100644
index 0000000..a1d6856
--- /dev/null
+++ b/binutils/dwarf-mode.el
@@ -0,0 +1,167 @@
+;;; dwarf-mode.el --- Browser for DWARF information.
+
+;; Version: 1.0
+
+;; This file is not part of GNU Emacs, but is distributed under the
+;; same terms:
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(defvar dwarf-readelf-program "readelf")
+
+(defconst dwarf-font-lock-keywords
+  '(
+    ;; Name and linkage name.
+    ("DW_AT_[a-z_]*name\\s *: .*:\\(.*\\)\\s *$"
+     (1 font-lock-function-name-face))
+
+    ("Compilation Unit @ offset 0x[0-9a-f]+"
+     (0 font-lock-string-face))
+    ))
+
+(defvar dwarf-file nil
+  "Buffer-local variable holding the file name passed to readelf.")
+
+;; Expand a "..." to show all the child DIES.  NEW-DEPTH controls how
+;; deep to display the new dies; `nil' means display all of them.
+(defun dwarf-do-insert-substructure (new-depth die)
+  (let ((inhibit-read-only t))
+    (beginning-of-line)
+    (delete-region (point) (progn
+			     (end-of-line)
+			     (forward-char)
+			     (point)))
+    (save-excursion
+      (apply #'call-process dwarf-readelf-program nil (current-buffer) nil
+	     "-wi" (concat "--dwarf-start=0x" die)
+	     dwarf-file
+	     (if new-depth (list (concat "--dwarf-depth="
+					 (int-to-string new-depth))))))
+    (set-buffer-modified-p nil)))
+
+(defun dwarf-insert-substructure-button (die)
+  (beginning-of-line)
+  (unless (looking-at "^ <\\([0-9]+\\)>")
+    (error "Unrecognized line."))
+  (let ((new-depth (1+ (string-to-int (match-string 1)))))
+    (dwarf-do-insert-substructure new-depth die)))
+
+(defun dwarf-insert-substructure (arg)
+  "Expand a `...' to show children of the current DIE.
+By default, expands just one level of children.
+A prefix argument means expand all children."
+  (interactive "P")
+  (beginning-of-line)
+  (unless (looking-at "^ <\\([0-9]+\\)><\\([0-9a-f]+\\)>")
+    (error "Unrecognized line."))
+  (let ((die (match-string 2)))
+    (if arg
+	(dwarf-do-insert-substructure nil die)
+      (dwarf-insert-substructure-button die))))
+
+;; Called when a button is pressed.
+;; Either follows a DIE reference, or expands a "...".
+(defun dwarf-die-button-action (button)
+  (let* ((die (button-get button 'die))
+	 ;; Note that the first number can only be decimal.
+	 (die-rx (concat "^\\s *\\(<[0-9]+>\\)?<"
+			 die ">[^<]"))
+	 (old (point))
+	 (is-ref (button-get button 'die-ref)))
+    (if is-ref
+	(progn
+	  (goto-char (point-min))
+	  (if (re-search-forward die-rx nil 'move)
+	      (push-mark old)
+	    (goto-char old)
+	    (error "Could not find DIE <0x%s>" die)))
+      (dwarf-insert-substructure-button die))))
+
+;; Button definition.
+(define-button-type 'dwarf-die-button
+  'follow-link t
+  'action #'dwarf-die-button-action)
+
+;; Helper regexp to match a DIE reference.
+(defconst dwarf-die-reference ": \\(<0x\\([0-9a-f]+\\)>\\)\\s *$")
+
+;; Helper regexp to match a `...' indicating that there are hidden
+;; children.
+(defconst dwarf-die-more "^ <[0-9]+><\\([0-9a-z]+\\)>: \\([.][.][.]\\)")
+
+;; jit-lock callback function to fontify a region.  This applies the
+;; buttons, since AFAICT there is no good way to apply buttons via
+;; font-lock.
+(defun dwarf-fontify-region (start end)
+  (save-excursion
+    (let ((beg-line (progn (goto-char start) (line-beginning-position)))
+	  (end-line (progn (goto-char end) (line-end-position))))
+      (goto-char beg-line)
+      (while (re-search-forward dwarf-die-reference end-line 'move)
+	(let ((b-start (match-beginning 1))
+	      (b-end (match-end 1))
+	      (hex (match-string-no-properties 2)))
+	  (make-text-button b-start b-end :type 'dwarf-die-button
+			    'die hex 'die-ref t)))
+      ;; This is a bogus approach.  Why can't we make buttons from the
+      ;; font-lock defaults?
+      (goto-char beg-line)
+      (while (re-search-forward dwarf-die-more end-line 'move)
+	(let ((hex (match-string-no-properties 1))
+	      (b-start (match-beginning 2))
+	      (b-end (match-end 2)))
+	  (make-text-button b-start b-end :type 'dwarf-die-button
+			    'die hex 'die-ref nil))))))
+
+;; Run readelf and insert the contents into the buffer.  The arguments
+;; are the way they are because this is also called as a
+;; revert-buffer-function.
+(defun dwarf-do-refresh (&rest ignore)
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (save-excursion
+      (call-process dwarf-readelf-program
+		    nil (current-buffer) nil
+		    "-wi" "--dwarf-depth=1"
+		    dwarf-file))
+    (set-buffer-modified-p nil)))
+
+;;;###autoload
+(define-derived-mode dwarf-mode special-mode "DWARF"
+  "Major mode for browsing DWARF output.
+
+\\{dwarf-mode-map}"
+
+  (set (make-local-variable 'font-lock-defaults) '(dwarf-font-lock-keywords))
+  ;; FIXME: we could be smarter and check the file time.
+  (set (make-local-variable 'revert-buffer-function) #'dwarf-do-refresh)
+  (jit-lock-register #'dwarf-fontify-region))
+
+(define-key dwarf-mode-map [(control ?m)] #'dwarf-insert-substructure)
+
+;;:###autoload
+(defun dwarf-browse (file)
+  "Invoke `readelf' and put output into a `dwarf-mode' buffer.
+This is the main interface to `dwarf-mode'."
+  (interactive "fFile name: ")
+  (let* ((base-name (file-name-nondirectory file))
+	 (buffer (generate-new-buffer (concat "*DWARF for " base-name "*"))))
+    (pop-to-buffer buffer)
+    (dwarf-mode)
+    (set (make-local-variable 'dwarf-file) file)
+    (dwarf-do-refresh)))
+
+(provide 'dwarf-mode)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 8846e87..3086d33 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -63,6 +63,9 @@ int do_trace_abbrevs;
 int do_trace_aranges;
 int do_wide;
 
+int dwarf_cutoff_level = -1;
+unsigned long dwarf_start_die;
+
 /* Values for do_debug_lines.  */
 #define FLAG_DEBUG_LINES_RAW	 1
 #define FLAG_DEBUG_LINES_DECODED 2
@@ -1367,7 +1370,8 @@ read_and_display_attr_value (unsigned long attribute,
     }
 
   if ((do_loc || do_debug_loc || do_debug_ranges)
-      && num_debug_info_entries == 0)
+      && num_debug_info_entries == 0
+      && debug_info_p != NULL)
     {
       switch (attribute)
 	{
@@ -1981,7 +1985,8 @@ process_debug_info (struct dwarf_section *section,
 
   if (!do_loc)
     {
-      printf (_("Contents of the %s section:\n\n"), section->name);
+      if (dwarf_start_die == 0)
+	printf (_("Contents of the %s section:\n\n"), section->name);
 
       load_debug_section (str, file);
     }
@@ -1999,7 +2004,7 @@ process_debug_info (struct dwarf_section *section,
       DWARF2_Internal_CompUnit compunit;
       unsigned char *hdrptr;
       unsigned char *tags;
-      int level;
+      int level, last_level, saved_level;
       dwarf_vma cu_offset;
       int offset_size;
       int initial_length_size;
@@ -2068,7 +2073,7 @@ process_debug_info (struct dwarf_section *section,
 	  debug_information [unit].num_range_lists = 0;
 	}
 
-      if (!do_loc)
+      if (!do_loc && dwarf_start_die == 0)
 	{
 	  printf (_("  Compilation Unit @ offset 0x%s:\n"),
 		  dwarf_vmatoa ("x", cu_offset));
@@ -2129,6 +2134,8 @@ process_debug_info (struct dwarf_section *section,
 	   + debug_displays [abbrev_sec].section.size);
 
       level = 0;
+      last_level = level;
+      saved_level = -1;
       while (tags < start)
 	{
 	  unsigned int bytes_read;
@@ -2136,6 +2143,7 @@ process_debug_info (struct dwarf_section *section,
 	  unsigned long die_offset;
 	  abbrev_entry *entry;
 	  abbrev_attr *attr;
+	  int do_printing = 1;
 
 	  die_offset = tags - section_begin;
 
@@ -2172,12 +2180,30 @@ process_debug_info (struct dwarf_section *section,
 			warn (_("Further warnings about bogus end-of-sibling markers suppressed\n"));
 		    }
 		}
+	      if (dwarf_start_die != 0 && level < saved_level)
+		return 1;
 	      continue;
 	    }
 
 	  if (!do_loc)
-	    printf (_(" <%d><%lx>: Abbrev Number: %lu"),
-		    level, die_offset, abbrev_number);
+	    {
+	      if (dwarf_start_die != 0 && die_offset < dwarf_start_die)
+		do_printing = 0;
+	      else
+		{
+		  if (dwarf_start_die != 0 && die_offset == dwarf_start_die)
+		    saved_level = level;
+		  do_printing = (dwarf_cutoff_level == -1
+				 || level < dwarf_cutoff_level);
+		  if (do_printing)
+		    printf (_(" <%d><%lx>: Abbrev Number: %lu"),
+			    level, die_offset, abbrev_number);
+		  else if (dwarf_cutoff_level == -1
+			   || last_level < dwarf_cutoff_level)
+		    printf (_(" <%d><%lx>: ...\n"), level, die_offset);
+		  last_level = level;
+		}
+	    }
 
 	  /* Scan through the abbreviation list until we reach the
 	     correct entry.  */
@@ -2188,7 +2214,7 @@ process_debug_info (struct dwarf_section *section,
 
 	  if (entry == NULL)
 	    {
-	      if (!do_loc)
+	      if (!do_loc && do_printing)
 		{
 		  printf ("\n");
 		  fflush (stdout);
@@ -2198,7 +2224,7 @@ process_debug_info (struct dwarf_section *section,
 	      return 0;
 	    }
 
-	  if (!do_loc)
+	  if (!do_loc && do_printing)
 	    printf (" (%s)\n", get_TAG_name (entry->tag));
 
 	  switch (entry->tag)
@@ -2219,9 +2245,15 @@ process_debug_info (struct dwarf_section *section,
 
 	  for (attr = entry->first_attr; attr; attr = attr->next)
 	    {
-	      if (! do_loc)
+	      debug_info *arg;
+
+	      if (! do_loc && do_printing)
 		/* Show the offset from where the tag was extracted.  */
-		printf ("    <%2lx>", (unsigned long)(tags - section_begin));
+		printf ("    <%lx>", (unsigned long)(tags - section_begin));
+
+	      arg = debug_information;
+	      if (debug_information)
+		arg += unit;
 
 	      tags = read_and_display_attr (attr->attribute,
 					    attr->form,
@@ -2229,8 +2261,8 @@ process_debug_info (struct dwarf_section *section,
 					    compunit.cu_pointer_size,
 					    offset_size,
 					    compunit.cu_version,
-					    debug_information + unit,
-					    do_loc, section);
+					    arg,
+					    do_loc || ! do_printing, section);
 	    }
 
  	  if (entry->children)
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 62b57a6..07b95b0 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -200,6 +200,9 @@ extern int do_trace_abbrevs;
 extern int do_trace_aranges;
 extern int do_wide;
 
+extern int dwarf_cutoff_level;
+extern unsigned long dwarf_start_die;
+
 extern void init_dwarf_regnames (unsigned int);
 extern void init_dwarf_regnames_i386 (void);
 extern void init_dwarf_regnames_x86_64 (void);
diff --git a/binutils/readelf.c b/binutils/readelf.c
index c4df8d9..6c8b966 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -3073,6 +3073,8 @@ get_section_type_name (unsigned int sh_type)
 
 #define OPTION_DEBUG_DUMP	512
 #define OPTION_DYN_SYMS		513
+#define OPTION_DWARF_DEPTH	514
+#define OPTION_DWARF_START	515
 
 static struct option options[] =
 {
@@ -3106,6 +3108,9 @@ static struct option options[] =
 #endif
   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
 
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
+
   {"version",	       no_argument, 0, 'v'},
   {"wide",	       no_argument, 0, 'W'},
   {"help",	       no_argument, 0, 'H'},
@@ -3149,6 +3154,10 @@ usage (FILE * stream)
                =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
                =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
+  fprintf (stream, _("\
+  --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+  --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                         or deeper\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -3355,6 +3364,20 @@ parse_args (int argc, char ** argv)
 	      dwarf_select_sections_by_names (optarg);
 	    }
 	  break;
+	case OPTION_DWARF_DEPTH:
+	  {
+	    char *cp;
+
+	    dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+	  }
+	  break;
+	case OPTION_DWARF_START:
+	  {
+	    char *cp;
+
+	    dwarf_start_die = strtoul (optarg, & cp, 0);
+	  }
+	  break;
 	case OPTION_DYN_SYMS:
 	  do_dyn_syms++;
 	  break;
-- 
1.7.3.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-26 20:09 Patch: DWARF browser Tom Tromey
@ 2011-04-26 20:22 ` David Miller
  2011-04-26 21:14 ` Cary Coutant
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2011-04-26 20:22 UTC (permalink / raw)
  To: tromey; +Cc: binutils

From: Tom Tromey <tromey@redhat.com>
Date: Tue, 26 Apr 2011 14:09:15 -0600

> Let me know what you think.

Thank you for writing this, it is really nice.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-26 20:09 Patch: DWARF browser Tom Tromey
  2011-04-26 20:22 ` David Miller
@ 2011-04-26 21:14 ` Cary Coutant
  2011-04-27  7:13 ` Tristan Gingold
  2011-04-27  9:48 ` Nick Clifton
  3 siblings, 0 replies; 8+ messages in thread
From: Cary Coutant @ 2011-04-26 21:14 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Binutils Development

> I have been wanting a nicer way to browse DWARF, so I came up with the
> appended.  It is an Emacs mode for DWARF browsing, plus a couple of new
> supporting readelf features.

Nice!

For the emacs-challenged, I'll offer this Perl script that I wrote a
while back. It takes readelf -wi output, and converts it to an HTML
file with disclosure triangles to collapse subtrees, and DIE
references as hotlinks:

http://www.bayarea.net/~cary/dwarf/witohtml.pl

-cary

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-26 20:09 Patch: DWARF browser Tom Tromey
  2011-04-26 20:22 ` David Miller
  2011-04-26 21:14 ` Cary Coutant
@ 2011-04-27  7:13 ` Tristan Gingold
  2011-04-27  9:48 ` Nick Clifton
  3 siblings, 0 replies; 8+ messages in thread
From: Tristan Gingold @ 2011-04-27  7:13 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Binutils Development


On Apr 26, 2011, at 10:09 PM, Tom Tromey wrote:

> I have been wanting a nicer way to browse DWARF, so I came up with the
> appended.  It is an Emacs mode for DWARF browsing, plus a couple of new
> supporting readelf features.
> 
> The simplest way to browse is just M-x dwarf-browse, then enter a file
> name.  This will show a high-level view of the debug info (just the CU
> DIEs).  If you want to see more details, you can click or RET on the
> `...' fields, and the mode will expand more DIEs.
> 
> The mode has a bit of font-lock support and it also has support for
> following DIE references (pushing the mark while doing so).
> 
> I needed 2 readelf features to make this work nicely.  One, a way to
> elide DIEs at a certain depth.  Two, a way to then print sibling DIEs
> starting with a certain DIE.
> 
> I don't know if you'd want the .el code in binutils or not.  It is no
> problem if not, I will just put it in ELPA.  I'll probably add features
> to it as I need them.
> 
> It would be handy if the readelf changes could go in regardless of what
> happens to the lisp code.
> 
> Let me know what you think.

Comment from a non-elf dwarf user:

* thank you for working on that.

* You'd better to base on objdump instead of readelf.  objdump provides the same functionalities as readelf (for the dwarf part), but it support more file formats.

Tristan.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-26 20:09 Patch: DWARF browser Tom Tromey
                   ` (2 preceding siblings ...)
  2011-04-27  7:13 ` Tristan Gingold
@ 2011-04-27  9:48 ` Nick Clifton
  2011-04-28 17:23   ` Tom Tromey
  3 siblings, 1 reply; 8+ messages in thread
From: Nick Clifton @ 2011-04-27  9:48 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Binutils Development

Hi Tom,

> I have been wanting a nicer way to browse DWARF, so I came up with the
> appended.  It is an Emacs mode for DWARF browsing, plus a couple of new
> supporting readelf features.

Nice - the patch is approved, although please also add a line to 
binutils/NEWS mentioning the new feature.

A patch to add this functionality to objdump is pre-approved.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-27  9:48 ` Nick Clifton
@ 2011-04-28 17:23   ` Tom Tromey
  2011-04-29  1:51     ` Hans-Peter Nilsson
  0 siblings, 1 reply; 8+ messages in thread
From: Tom Tromey @ 2011-04-28 17:23 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Binutils Development

Tom> I have been wanting a nicer way to browse DWARF, so I came up with the
Tom> appended.  It is an Emacs mode for DWARF browsing, plus a couple of new
Tom> supporting readelf features.

Nick> Nice - the patch is approved, although please also add a line to
Nick> binutils/NEWS mentioning the new feature.

Nick> A patch to add this functionality to objdump is pre-approved.

Here is the combined patch I am checking in.

It includes a similar change to objdump, and per Tristan's request I
changed dwarf-mode.el to use objdump.

The test case change is because I had changed a format from "%2lx" to
just "%lx".  I didn't notice the test failure the first time around.  I
hope this is ok; but if not let me know and I will revert that bit and
fix dwarf-mode to follow.

Tom

2011-04-28  Tom Tromey  <tromey@redhat.com>

	* NEWS: Add note about --dwarf-depth, --dwarf-start, and
	dwarf-mode.el.
	* objdump.c (suppress_bfd_header): New global.
	(usage): Update.
	(OPTION_DWARF_DEPTH, OPTION_DWARF_START): New constants.
	(options): Add dwarf-depth and dwarf-start entries.
	(dump_bfd): Use suppress_bfd_header.
	(main): Handle OPTION_DWARF_START, OPTION_DWARF_DEPTH.
	* doc/binutils.texi (objcopy): Document --dwarf-depth and
	--dwarf-start.
	(readelf): Likewise.
	* dwarf-mode.el: New file.
	* dwarf.c (dwarf_cutoff_level, dwarf_start_die): New globals.
	(read_and_display_attr_value): Also check debug_info_p.
	(process_debug_info): Handle dwarf_start_die and
	dwarf_cutoff_level.
	* dwarf.h (dwarf_cutoff_level, dwarf_start_die): Declare.
	* readelf.c (usage): Update.
	(OPTION_DWARF_DEPTH): New macro.
	(OPTION_DWARF_START): Likewise.
	(options): Add dwarf-depth and dwarf-start entries.
	(parse_args): Handle OPTION_DWARF_START and OPTION_DWARF_DEPTH.

2011-04-28  Tom Tromey  <tromey@redhat.com>

	* binutils-all/objdump.W: Correct output.

diff --git a/binutils/NEWS b/binutils/NEWS
index d1b2a51..e069a25 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -3,6 +3,9 @@
 * Add --preprocessor-arg option to windres to specify additional options
   passed to preprocessor.
 
+* Add --dwarf-start and --dwarf-end to readelf and objdump.  These are used by
+  the new Emacs mode, see dwarf-mode.el.
+
 Changes in 2.21:
 
 * Add --interleave-width option to objcopy to allowing copying a range of
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 45a7ff7..08e1c4e 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1076,6 +1076,8 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
         [@option{--subsystem=}@var{which}:@var{major}.@var{minor}]
         [@option{--compress-debug-sections}]
         [@option{--decompress-debug-sections}]
+        [@option{--dwarf-depth=@var{n}}]
+        [@option{--dwarf-start=@var{n}}]
         [@option{-v}|@option{--verbose}]
         [@option{-V}|@option{--version}]
         [@option{--help}] [@option{--info}]
@@ -2129,6 +2131,28 @@ then only data found in those specific sections will be dumped.
 Note that there is no single letter option to display the content of
 trace sections or .gdb_index.
 
+Note: the output from the @option{=info} option can also be affected
+by the options @option{--dwarf-depth} and @option{--dwarf-start}.
+
+@item --dwarf-depth=@var{n}
+Limit the dump of the @code{.debug_info} section to @var{n} children.
+This is only useful with @option{--dwarf=info}.  The default is
+to print all DIEs; the special value 0 for @var{n} will also have this
+effect.
+
+With a non-zero value for @var{n}, DIEs at or deeper than @var{n}
+levels will not be printed.  The range for @var{n} is zero-based.
+
+@item --dwarf-start=@var{n}
+Print only DIEs beginning with the DIE numbered @var{n}.  This is only
+useful with @option{--dwarf=info}.
+
+If specified, this option will suppress printing of any header
+information and all DIEs before the DIE numbered @var{n}.  Only
+siblings and children of the specified DIE will be printed.
+
+This can be used in conjunction with @option{--dwarf-depth}.
+
 @item -G
 @itemx --stabs
 @cindex stab
@@ -3957,6 +3981,8 @@ readelf [@option{-a}|@option{--all}]
         [@option{-c}|@option{--archive-index}]
         [@option{-w[lLiaprmfFsoRt]}|
          @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index]]
+        [@option{--dwarf-depth=@var{n}}]
+        [@option{--dwarf-start=@var{n}}]
         [@option{-I}|@option{--histogram}]
         [@option{-v}|@option{--version}]
         [@option{-W}|@option{--wide}]
@@ -4124,6 +4150,28 @@ Note: the @option{=frames-interp} option will display the interpreted
 contents of a .debug_frame section whereas the @option{=frames} option
 dumps the contents in a raw format.
 
+Note: the output from the @option{=info} option can also be affected
+by the options @option{--dwarf-depth} and @option{--dwarf-start}.
+
+@item --dwarf-depth=@var{n}
+Limit the dump of the @code{.debug_info} section to @var{n} children.
+This is only useful with @option{--debug-dump=info}.  The default is
+to print all DIEs; the special value 0 for @var{n} will also have this
+effect.
+
+With a non-zero value for @var{n}, DIEs at or deeper than @var{n}
+levels will not be printed.  The range for @var{n} is zero-based.
+
+@item --dwarf-start=@var{n}
+Print only DIEs beginning with the DIE numbered @var{n}.  This is only
+useful with @option{--debug-dump=info}.
+
+If specified, this option will suppress printing of any header
+information and all DIEs before the DIE numbered @var{n}.  Only
+siblings and children of the specified DIE will be printed.
+
+This can be used in conjunction with @option{--dwarf-depth}.
+
 @item -I
 @itemx --histogram
 Display a histogram of bucket list lengths when displaying the contents
diff --git a/binutils/dwarf-mode.el b/binutils/dwarf-mode.el
new file mode 100644
index 0000000..3362bc4
--- /dev/null
+++ b/binutils/dwarf-mode.el
@@ -0,0 +1,167 @@
+;;; dwarf-mode.el --- Browser for DWARF information.
+
+;; Version: 1.0
+
+;; This file is not part of GNU Emacs, but is distributed under the
+;; same terms:
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(defvar dwarf-objdump-program "objdump")
+
+(defconst dwarf-font-lock-keywords
+  '(
+    ;; Name and linkage name.
+    ("DW_AT_[a-z_]*name\\s *: .*:\\(.*\\)\\s *$"
+     (1 font-lock-function-name-face))
+
+    ("Compilation Unit @ offset 0x[0-9a-f]+"
+     (0 font-lock-string-face))
+    ))
+
+(defvar dwarf-file nil
+  "Buffer-local variable holding the file name passed to objdump.")
+
+;; Expand a "..." to show all the child DIES.  NEW-DEPTH controls how
+;; deep to display the new dies; `nil' means display all of them.
+(defun dwarf-do-insert-substructure (new-depth die)
+  (let ((inhibit-read-only t))
+    (beginning-of-line)
+    (delete-region (point) (progn
+			     (end-of-line)
+			     (forward-char)
+			     (point)))
+    (save-excursion
+      (apply #'call-process dwarf-objdump-program nil (current-buffer) nil
+	     "-Wi" (concat "--dwarf-start=0x" die)
+	     dwarf-file
+	     (if new-depth (list (concat "--dwarf-depth="
+					 (int-to-string new-depth))))))
+    (set-buffer-modified-p nil)))
+
+(defun dwarf-insert-substructure-button (die)
+  (beginning-of-line)
+  (unless (looking-at "^ <\\([0-9]+\\)>")
+    (error "Unrecognized line."))
+  (let ((new-depth (1+ (string-to-int (match-string 1)))))
+    (dwarf-do-insert-substructure new-depth die)))
+
+(defun dwarf-insert-substructure (arg)
+  "Expand a `...' to show children of the current DIE.
+By default, expands just one level of children.
+A prefix argument means expand all children."
+  (interactive "P")
+  (beginning-of-line)
+  (unless (looking-at "^ <\\([0-9]+\\)><\\([0-9a-f]+\\)>")
+    (error "Unrecognized line."))
+  (let ((die (match-string 2)))
+    (if arg
+	(dwarf-do-insert-substructure nil die)
+      (dwarf-insert-substructure-button die))))
+
+;; Called when a button is pressed.
+;; Either follows a DIE reference, or expands a "...".
+(defun dwarf-die-button-action (button)
+  (let* ((die (button-get button 'die))
+	 ;; Note that the first number can only be decimal.
+	 (die-rx (concat "^\\s *\\(<[0-9]+>\\)?<"
+			 die ">[^<]"))
+	 (old (point))
+	 (is-ref (button-get button 'die-ref)))
+    (if is-ref
+	(progn
+	  (goto-char (point-min))
+	  (if (re-search-forward die-rx nil 'move)
+	      (push-mark old)
+	    (goto-char old)
+	    (error "Could not find DIE <0x%s>" die)))
+      (dwarf-insert-substructure-button die))))
+
+;; Button definition.
+(define-button-type 'dwarf-die-button
+  'follow-link t
+  'action #'dwarf-die-button-action)
+
+;; Helper regexp to match a DIE reference.
+(defconst dwarf-die-reference ": \\(<0x\\([0-9a-f]+\\)>\\)\\s *$")
+
+;; Helper regexp to match a `...' indicating that there are hidden
+;; children.
+(defconst dwarf-die-more "^ <[0-9]+><\\([0-9a-z]+\\)>: \\([.][.][.]\\)")
+
+;; jit-lock callback function to fontify a region.  This applies the
+;; buttons, since AFAICT there is no good way to apply buttons via
+;; font-lock.
+(defun dwarf-fontify-region (start end)
+  (save-excursion
+    (let ((beg-line (progn (goto-char start) (line-beginning-position)))
+	  (end-line (progn (goto-char end) (line-end-position))))
+      (goto-char beg-line)
+      (while (re-search-forward dwarf-die-reference end-line 'move)
+	(let ((b-start (match-beginning 1))
+	      (b-end (match-end 1))
+	      (hex (match-string-no-properties 2)))
+	  (make-text-button b-start b-end :type 'dwarf-die-button
+			    'die hex 'die-ref t)))
+      ;; This is a bogus approach.  Why can't we make buttons from the
+      ;; font-lock defaults?
+      (goto-char beg-line)
+      (while (re-search-forward dwarf-die-more end-line 'move)
+	(let ((hex (match-string-no-properties 1))
+	      (b-start (match-beginning 2))
+	      (b-end (match-end 2)))
+	  (make-text-button b-start b-end :type 'dwarf-die-button
+			    'die hex 'die-ref nil))))))
+
+;; Run objdump and insert the contents into the buffer.  The arguments
+;; are the way they are because this is also called as a
+;; revert-buffer-function.
+(defun dwarf-do-refresh (&rest ignore)
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (save-excursion
+      (call-process dwarf-objdump-program
+		    nil (current-buffer) nil
+		    "-Wi" "--dwarf-depth=1"
+		    dwarf-file))
+    (set-buffer-modified-p nil)))
+
+;;;###autoload
+(define-derived-mode dwarf-mode special-mode "DWARF"
+  "Major mode for browsing DWARF output.
+
+\\{dwarf-mode-map}"
+
+  (set (make-local-variable 'font-lock-defaults) '(dwarf-font-lock-keywords))
+  ;; FIXME: we could be smarter and check the file time.
+  (set (make-local-variable 'revert-buffer-function) #'dwarf-do-refresh)
+  (jit-lock-register #'dwarf-fontify-region))
+
+(define-key dwarf-mode-map [(control ?m)] #'dwarf-insert-substructure)
+
+;;:###autoload
+(defun dwarf-browse (file)
+  "Invoke `objdump' and put output into a `dwarf-mode' buffer.
+This is the main interface to `dwarf-mode'."
+  (interactive "fFile name: ")
+  (let* ((base-name (file-name-nondirectory file))
+	 (buffer (generate-new-buffer (concat "*DWARF for " base-name "*"))))
+    (pop-to-buffer buffer)
+    (dwarf-mode)
+    (set (make-local-variable 'dwarf-file) file)
+    (dwarf-do-refresh)))
+
+(provide 'dwarf-mode)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 8846e87..3086d33 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -63,6 +63,9 @@ int do_trace_abbrevs;
 int do_trace_aranges;
 int do_wide;
 
+int dwarf_cutoff_level = -1;
+unsigned long dwarf_start_die;
+
 /* Values for do_debug_lines.  */
 #define FLAG_DEBUG_LINES_RAW	 1
 #define FLAG_DEBUG_LINES_DECODED 2
@@ -1367,7 +1370,8 @@ read_and_display_attr_value (unsigned long attribute,
     }
 
   if ((do_loc || do_debug_loc || do_debug_ranges)
-      && num_debug_info_entries == 0)
+      && num_debug_info_entries == 0
+      && debug_info_p != NULL)
     {
       switch (attribute)
 	{
@@ -1981,7 +1985,8 @@ process_debug_info (struct dwarf_section *section,
 
   if (!do_loc)
     {
-      printf (_("Contents of the %s section:\n\n"), section->name);
+      if (dwarf_start_die == 0)
+	printf (_("Contents of the %s section:\n\n"), section->name);
 
       load_debug_section (str, file);
     }
@@ -1999,7 +2004,7 @@ process_debug_info (struct dwarf_section *section,
       DWARF2_Internal_CompUnit compunit;
       unsigned char *hdrptr;
       unsigned char *tags;
-      int level;
+      int level, last_level, saved_level;
       dwarf_vma cu_offset;
       int offset_size;
       int initial_length_size;
@@ -2068,7 +2073,7 @@ process_debug_info (struct dwarf_section *section,
 	  debug_information [unit].num_range_lists = 0;
 	}
 
-      if (!do_loc)
+      if (!do_loc && dwarf_start_die == 0)
 	{
 	  printf (_("  Compilation Unit @ offset 0x%s:\n"),
 		  dwarf_vmatoa ("x", cu_offset));
@@ -2129,6 +2134,8 @@ process_debug_info (struct dwarf_section *section,
 	   + debug_displays [abbrev_sec].section.size);
 
       level = 0;
+      last_level = level;
+      saved_level = -1;
       while (tags < start)
 	{
 	  unsigned int bytes_read;
@@ -2136,6 +2143,7 @@ process_debug_info (struct dwarf_section *section,
 	  unsigned long die_offset;
 	  abbrev_entry *entry;
 	  abbrev_attr *attr;
+	  int do_printing = 1;
 
 	  die_offset = tags - section_begin;
 
@@ -2172,12 +2180,30 @@ process_debug_info (struct dwarf_section *section,
 			warn (_("Further warnings about bogus end-of-sibling markers suppressed\n"));
 		    }
 		}
+	      if (dwarf_start_die != 0 && level < saved_level)
+		return 1;
 	      continue;
 	    }
 
 	  if (!do_loc)
-	    printf (_(" <%d><%lx>: Abbrev Number: %lu"),
-		    level, die_offset, abbrev_number);
+	    {
+	      if (dwarf_start_die != 0 && die_offset < dwarf_start_die)
+		do_printing = 0;
+	      else
+		{
+		  if (dwarf_start_die != 0 && die_offset == dwarf_start_die)
+		    saved_level = level;
+		  do_printing = (dwarf_cutoff_level == -1
+				 || level < dwarf_cutoff_level);
+		  if (do_printing)
+		    printf (_(" <%d><%lx>: Abbrev Number: %lu"),
+			    level, die_offset, abbrev_number);
+		  else if (dwarf_cutoff_level == -1
+			   || last_level < dwarf_cutoff_level)
+		    printf (_(" <%d><%lx>: ...\n"), level, die_offset);
+		  last_level = level;
+		}
+	    }
 
 	  /* Scan through the abbreviation list until we reach the
 	     correct entry.  */
@@ -2188,7 +2214,7 @@ process_debug_info (struct dwarf_section *section,
 
 	  if (entry == NULL)
 	    {
-	      if (!do_loc)
+	      if (!do_loc && do_printing)
 		{
 		  printf ("\n");
 		  fflush (stdout);
@@ -2198,7 +2224,7 @@ process_debug_info (struct dwarf_section *section,
 	      return 0;
 	    }
 
-	  if (!do_loc)
+	  if (!do_loc && do_printing)
 	    printf (" (%s)\n", get_TAG_name (entry->tag));
 
 	  switch (entry->tag)
@@ -2219,9 +2245,15 @@ process_debug_info (struct dwarf_section *section,
 
 	  for (attr = entry->first_attr; attr; attr = attr->next)
 	    {
-	      if (! do_loc)
+	      debug_info *arg;
+
+	      if (! do_loc && do_printing)
 		/* Show the offset from where the tag was extracted.  */
-		printf ("    <%2lx>", (unsigned long)(tags - section_begin));
+		printf ("    <%lx>", (unsigned long)(tags - section_begin));
+
+	      arg = debug_information;
+	      if (debug_information)
+		arg += unit;
 
 	      tags = read_and_display_attr (attr->attribute,
 					    attr->form,
@@ -2229,8 +2261,8 @@ process_debug_info (struct dwarf_section *section,
 					    compunit.cu_pointer_size,
 					    offset_size,
 					    compunit.cu_version,
-					    debug_information + unit,
-					    do_loc, section);
+					    arg,
+					    do_loc || ! do_printing, section);
 	    }
 
  	  if (entry->children)
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 62b57a6..07b95b0 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -200,6 +200,9 @@ extern int do_trace_abbrevs;
 extern int do_trace_aranges;
 extern int do_wide;
 
+extern int dwarf_cutoff_level;
+extern unsigned long dwarf_start_die;
+
 extern void init_dwarf_regnames (unsigned int);
 extern void init_dwarf_regnames_i386 (void);
 extern void init_dwarf_regnames_x86_64 (void);
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 8b6bc28..231a668 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -110,6 +110,7 @@ static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
 static bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
 static int dump_debugging;		/* --debugging */
 static int dump_debugging_tags;		/* --debugging-tags */
+static int suppress_bfd_header;
 static int dump_special_syms = 0;	/* --special-syms */
 static bfd_vma adjust_section_vma = 0;	/* --adjust-vma */
 static int file_start_context = 0;      /* --file-start-context */
@@ -246,8 +247,11 @@ usage (FILE *stream, int status)
       --adjust-vma=OFFSET        Add OFFSET to all displayed section addresses\n\
       --special-syms             Include special symbols in symbol dumps\n\
       --prefix=PREFIX            Add PREFIX to absolute paths for -S\n\
-      --prefix-strip=LEVEL       Strip initial directory names for -S\n\
-\n"));
+      --prefix-strip=LEVEL       Strip initial directory names for -S\n"));
+      fprintf (stream, _("\
+      --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+      --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                             or deeper\n\n"));
       list_supported_targets (program_name, stream);
       list_supported_architectures (program_name, stream);
 
@@ -268,7 +272,9 @@ enum option_values
     OPTION_PREFIX,
     OPTION_PREFIX_STRIP,
     OPTION_INSN_WIDTH,
-    OPTION_ADJUST_VMA
+    OPTION_ADJUST_VMA,
+    OPTION_DWARF_DEPTH,
+    OPTION_DWARF_START
   };
 
 static struct option long_options[]=
@@ -316,6 +322,8 @@ static struct option long_options[]=
   {"prefix", required_argument, NULL, OPTION_PREFIX},
   {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
   {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
   {0, no_argument, 0, 0}
 };
 \f
@@ -3079,7 +3087,7 @@ dump_bfd (bfd *abfd)
       bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
     }
 
-  if (! dump_debugging_tags)
+  if (! dump_debugging_tags && ! suppress_bfd_header)
     printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
 	    abfd->xvec->name);
   if (dump_ar_hdrs)
@@ -3088,7 +3096,7 @@ dump_bfd (bfd *abfd)
     dump_bfd_header (abfd);
   if (dump_private_headers)
     dump_bfd_private_header (abfd);
-  if (! dump_debugging_tags)
+  if (! dump_debugging_tags && ! suppress_bfd_header)
     putchar ('\n');
   if (dump_section_headers)
     dump_headers (abfd);
@@ -3476,6 +3484,19 @@ main (int argc, char **argv)
 	  else
 	    dwarf_select_sections_all ();
 	  break;
+	case OPTION_DWARF_DEPTH:
+	  {
+	    char *cp;
+	    dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+	  }
+	  break;
+	case OPTION_DWARF_START:
+	  {
+	    char *cp;
+	    dwarf_start_die = strtoul (optarg, & cp, 0);
+	    suppress_bfd_header = 1;
+	  }
+	  break;
 	case 'G':
 	  dump_stab_section_info = TRUE;
 	  seenflag = TRUE;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index c4df8d9..6c8b966 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -3073,6 +3073,8 @@ get_section_type_name (unsigned int sh_type)
 
 #define OPTION_DEBUG_DUMP	512
 #define OPTION_DYN_SYMS		513
+#define OPTION_DWARF_DEPTH	514
+#define OPTION_DWARF_START	515
 
 static struct option options[] =
 {
@@ -3106,6 +3108,9 @@ static struct option options[] =
 #endif
   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
 
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
+
   {"version",	       no_argument, 0, 'v'},
   {"wide",	       no_argument, 0, 'W'},
   {"help",	       no_argument, 0, 'H'},
@@ -3149,6 +3154,10 @@ usage (FILE * stream)
                =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
                =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
+  fprintf (stream, _("\
+  --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+  --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                         or deeper\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -3355,6 +3364,20 @@ parse_args (int argc, char ** argv)
 	      dwarf_select_sections_by_names (optarg);
 	    }
 	  break;
+	case OPTION_DWARF_DEPTH:
+	  {
+	    char *cp;
+
+	    dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+	  }
+	  break;
+	case OPTION_DWARF_START:
+	  {
+	    char *cp;
+
+	    dwarf_start_die = strtoul (optarg, & cp, 0);
+	  }
+	  break;
 	case OPTION_DYN_SYMS:
 	  do_dyn_syms++;
 	  break;
diff --git a/binutils/testsuite/binutils-all/objdump.W b/binutils/testsuite/binutils-all/objdump.W
index 0197647..5b58fb4 100644
--- a/binutils/testsuite/binutils-all/objdump.W
+++ b/binutils/testsuite/binutils-all/objdump.W
@@ -9,7 +9,7 @@ Contents of the .debug_info section:
    Abbrev Offset: 0
    Pointer Size:  4
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_stmt_list   : 0x0	
+    <c>   DW_AT_stmt_list   : 0x0	
     <10>   DW_AT_high_pc     : 0x.	
     <14>   DW_AT_low_pc      : 0x.	
     <18>   DW_AT_name        : file1.txt	

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-28 17:23   ` Tom Tromey
@ 2011-04-29  1:51     ` Hans-Peter Nilsson
  2011-04-30 13:18       ` H.J. Lu
  0 siblings, 1 reply; 8+ messages in thread
From: Hans-Peter Nilsson @ 2011-04-29  1:51 UTC (permalink / raw)
  To: tromey; +Cc: nickc, binutils

> From: Tom Tromey <tromey@redhat.com>
> Date: Thu, 28 Apr 2011 11:22:56 -0600

> The test case change is because I had changed a format from "%2lx" to
> just "%lx".  I didn't notice the test failure the first time around.  I
> hope this is ok; but if not let me know and I will revert that bit and
> fix dwarf-mode to follow.

There was something wrong with that testing too.  I committed
the following as obvious, but haven't checked other targets than
cross to cris-elf and native i686-pc-linux-gnu.

binutils/testsuite:
	* binutils-all/i386/compressed-1a.d: Adjust for change in output
	format.

gas/testsuite:
	* gas/elf/dwarf2-1.d, gas/elf/dwarf2-2.d: Adjust for change in
	output format.
	* gas/i386/dw2-compress-1.d: Ditto.

Index: binutils-all/i386/compressed-1a.d
===================================================================
RCS file: /cvs/src/src/binutils/testsuite/binutils-all/i386/compressed-1a.d,v
retrieving revision 1.2
diff -p -u -r1.2 compressed-1a.d
--- binutils-all/i386/compressed-1a.d	15 Jul 2010 00:37:12 -0000	1.2
+++ binutils-all/i386/compressed-1a.d	29 Apr 2011 01:38:04 -0000
@@ -33,7 +33,7 @@ Contents of the .[z]?debug_info section:
    Abbrev Offset: 0
    Pointer Size:  4
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_producer    : \(indirect string, offset: 0x0\): GNU C 4.4.4	
+    <c>   DW_AT_producer    : \(indirect string, offset: 0x0\): GNU C 4.4.4	
     <10>   DW_AT_language    : 1	\(ANSI C\)
     <11>   DW_AT_name        : \(indirect string, offset: 0x18\): compressed-1.c	
     <15>   DW_AT_comp_dir    : \(indirect string, offset: 0x16\): .	

Index: gas/elf/dwarf2-1.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/elf/dwarf2-1.d,v
retrieving revision 1.3
diff -p -u -r1.3 dwarf2-1.d
--- gas/elf/dwarf2-1.d	29 Oct 2010 12:10:35 -0000	1.3
+++ gas/elf/dwarf2-1.d	29 Apr 2011 01:41:24 -0000
@@ -11,7 +11,7 @@ Contents of the .[z]?debug_info section:
    Abbrev Offset: 0
    Pointer Size:  4
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_stmt_list   : 0x0	
+    <c>   DW_AT_stmt_list   : 0x0	
     <10>   DW_AT_high_pc     : 0x.	
     <14>   DW_AT_low_pc      : 0x.	
     <18>   DW_AT_name        : file1.txt	
Index: gas/elf/dwarf2-2.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/elf/dwarf2-2.d,v
retrieving revision 1.3
diff -p -u -r1.3 dwarf2-2.d
--- gas/elf/dwarf2-2.d	29 Oct 2010 12:10:35 -0000	1.3
+++ gas/elf/dwarf2-2.d	29 Apr 2011 01:41:24 -0000
@@ -11,7 +11,7 @@ Contents of the .[z]?debug_info section:
    Abbrev Offset: 0
    Pointer Size:  4
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_stmt_list   : 0x0	
+    <c>   DW_AT_stmt_list   : 0x0	
     <10>   DW_AT_high_pc     : 0x.	
     <14>   DW_AT_low_pc      : 0x.	
     <18>   DW_AT_name        : file1.txt	
Index: gas/i386/dw2-compress-1.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/i386/dw2-compress-1.d,v
retrieving revision 1.3
diff -p -u -r1.3 dw2-compress-1.d
--- gas/i386/dw2-compress-1.d	3 Sep 2010 15:54:32 -0000	1.3
+++ gas/i386/dw2-compress-1.d	29 Apr 2011 01:41:24 -0000
@@ -10,7 +10,7 @@ Contents of the .zdebug_info section:
    Abbrev Offset: 0
    Pointer Size:  4
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_stmt_list   : 0x0	
+    <c>   DW_AT_stmt_list   : 0x0	
     <10>   DW_AT_high_pc     : 0x4	
     <14>   DW_AT_low_pc      : 0x0	
     <18>   DW_AT_name        : file1.txt	

brgds, H-P

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: DWARF browser
  2011-04-29  1:51     ` Hans-Peter Nilsson
@ 2011-04-30 13:18       ` H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2011-04-30 13:18 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: tromey, nickc, binutils

On Thu, Apr 28, 2011 at 6:50 PM, Hans-Peter Nilsson
<hans-peter.nilsson@axis.com> wrote:
>> From: Tom Tromey <tromey@redhat.com>
>> Date: Thu, 28 Apr 2011 11:22:56 -0600
>
>> The test case change is because I had changed a format from "%2lx" to
>> just "%lx".  I didn't notice the test failure the first time around.  I
>> hope this is ok; but if not let me know and I will revert that bit and
>> fix dwarf-mode to follow.
>
> There was something wrong with that testing too.  I committed
> the following as obvious, but haven't checked other targets than
> cross to cris-elf and native i686-pc-linux-gnu.
>
> binutils/testsuite:
>        * binutils-all/i386/compressed-1a.d: Adjust for change in output
>        format.
>
> gas/testsuite:
>        * gas/elf/dwarf2-1.d, gas/elf/dwarf2-2.d: Adjust for change in
>        output format.
>        * gas/i386/dw2-compress-1.d: Ditto.
>

I checked in this patch for x86-64.


-- 
H.J.
---
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index d5703ff..178b3eb 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-04-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* binutils-all/x86-64/compressed-1a.d: Adjust for change in output
+	format.
+
 2011-04-29  Hans-Peter Nilsson  <hp@axis.com>

 	* binutils-all/i386/compressed-1a.d: Adjust for change in output
diff --git a/binutils/testsuite/binutils-all/x86-64/compressed-1a.d b/binutils/t
estsuite/binutils-all/x86-64/compressed-1a.d
index 4b1b354..4176f6d 100644
--- a/binutils/testsuite/binutils-all/x86-64/compressed-1a.d
+++ b/binutils/testsuite/binutils-all/x86-64/compressed-1a.d
@@ -33,7 +33,7 @@ Contents of the .[z]?debug_info section:
    Abbrev Offset: 0
    Pointer Size:  8
  <0><b>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
-    < c>   DW_AT_producer    : \(indirect string, offset: 0x0\): GNU C 4.4.4	
+    <c>   DW_AT_producer    : \(indirect string, offset: 0x0\): GNU C 4.4.4	
     <10>   DW_AT_language    : 1	\(ANSI C\)
     <11>   DW_AT_name        : \(indirect string, offset: 0x18\): compressed-1.
c	
     <15>   DW_AT_comp_dir    : \(indirect string, offset: 0x16\): .

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-04-30 13:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-26 20:09 Patch: DWARF browser Tom Tromey
2011-04-26 20:22 ` David Miller
2011-04-26 21:14 ` Cary Coutant
2011-04-27  7:13 ` Tristan Gingold
2011-04-27  9:48 ` Nick Clifton
2011-04-28 17:23   ` Tom Tromey
2011-04-29  1:51     ` Hans-Peter Nilsson
2011-04-30 13:18       ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).