This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] objdump: Handle 32-bit base address in debug_ranges / debug_loc.


When the DWARF address size is 32-bit, but the host machine is 64-bit,
objdump fails to spot base addresses specified in the .debug_ranges and
.debug_loc lists.

As an example, here is the output when dumping an example .debug_ranges
section with the pre-patched objdump:

    Contents of the .debug_ranges section:

        Offset   Begin    End
        00000000 ffffffff 00000004 (start > end)
        00000000 00000000 00000004
        00000000 ffffffff 00000008 (start > end)
        00000000 00000000 00000004
        00000000 <End of list>

And this is what the same section looks like when dumped with the
patched version of objdump:

    Contents of the .debug_ranges section:

        Offset   Begin    End
        00000000 ffffffff 00000004 (base address)
        00000000 00000004 00000008
        00000000 ffffffff 00000008 (base address)
        00000000 00000008 0000000c
        00000000 <End of list>

binutils/ChangeLog:

	* dwarf.c (is_max_address): New function.
	(display_loc_list): Remove out of date comment, use
	is_max_address.
	(display_debug_ranges): Likewise.

binutils/testsuite/ChangeLog:

	* binutils-all/objdump.exp: Add test for .debug_ranges decode.
	* binutils-all/dw2-ranges.S: New file.
	* binutils-all/dw2-ranges.W: New file.
---
 binutils/ChangeLog                           |   7 ++
 binutils/dwarf.c                             |  25 ++---
 binutils/testsuite/ChangeLog                 |   6 ++
 binutils/testsuite/binutils-all/dw2-ranges.S | 140 +++++++++++++++++++++++++++
 binutils/testsuite/binutils-all/dw2-ranges.W |  11 +++
 binutils/testsuite/binutils-all/objdump.exp  |  31 ++++++
 6 files changed, 209 insertions(+), 11 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/dw2-ranges.S
 create mode 100644 binutils/testsuite/binutils-all/dw2-ranges.W

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index e1d8ea3..f947f08 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,10 @@
+2015-11-26  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* dwarf.c (is_max_address): New function.
+	(display_loc_list): Remove out of date comment, use
+	is_max_address.
+	(display_debug_ranges): Likewise.
+
 2015-11-20  Ronald Hoogenboom  <hoogenboom30@zonnet.nl>
 
 	* objcopy.c (parse_symflags): Use xstrndup in place of strndup.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 9f1baea..03e0117 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -4326,6 +4326,16 @@ display_debug_abbrev (struct dwarf_section *section,
   return 1;
 }
 
+/* Return true when ADDR is the maximum address, when addresses are
+   POINTER_SIZE bytes long.  */
+
+static bfd_boolean
+is_max_address (dwarf_vma addr, unsigned int pointer_size)
+{
+  dwarf_vma mask = ~(~(dwarf_vma) 1 << (pointer_size * 8 - 1));
+  return ((addr & mask) == mask);
+}
+
 /* Display a location list from a normal (ie, non-dwo) .debug_loc section.  */
 
 static void
@@ -4380,10 +4390,6 @@ display_loc_list (struct dwarf_section *section,
 
       printf ("    %8.8lx ", off);
 
-      /* Note: we use sign extension here in order to be sure that we can detect
-	 the -1 escape value.  Sign extension into the top 32 bits of a 32-bit
-	 address will not affect the values that we display since we always show
-	 hex values, and always the bottom 32-bits.  */
       SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end);
       SAFE_BYTE_GET_AND_INC (end, start, pointer_size, section_end);
 
@@ -4404,7 +4410,8 @@ display_loc_list (struct dwarf_section *section,
 	}
 
       /* Check base address specifiers.  */
-      if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
+      if (is_max_address (begin, pointer_size)
+          && !is_max_address (end, pointer_size))
 	{
 	  base_address = end;
 	  print_dwarf_vma (begin, pointer_size);
@@ -5202,11 +5209,6 @@ display_debug_ranges (struct dwarf_section *section,
 	  dwarf_vma begin;
 	  dwarf_vma end;
 
-	  /* Note: we use sign extension here in order to be sure that
-	     we can detect the -1 escape value.  Sign extension into the
-	     top 32 bits of a 32-bit address will not affect the values
-	     that we display since we always show hex values, and always
-	     the bottom 32-bits.  */
 	  SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
 	  if (start >= finish)
 	    break;
@@ -5221,7 +5223,8 @@ display_debug_ranges (struct dwarf_section *section,
 	    }
 
 	  /* Check base address specifiers.  */
-	  if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
+          if (is_max_address (begin, pointer_size)
+              && !is_max_address (end, pointer_size))
 	    {
 	      base_address = end;
 	      print_dwarf_vma (begin, pointer_size);
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index 64348e6..bc447d8 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-26  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* binutils-all/objdump.exp: Add test for .debug_ranges decode.
+	* binutils-all/dw2-ranges.S: New file.
+	* binutils-all/dw2-ranges.W: New file.
+
 2015-10-22  Alan Modra  <amodra@gmail.com>
 
 	* binutils-all/add-symbol.d: Run test on mips.  Support either
diff --git a/binutils/testsuite/binutils-all/dw2-ranges.S b/binutils/testsuite/binutils-all/dw2-ranges.S
new file mode 100644
index 0000000..74d7287
--- /dev/null
+++ b/binutils/testsuite/binutils-all/dw2-ranges.S
@@ -0,0 +1,140 @@
+/* Copyright (C) 2015 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 tests makes use of the .debug_ranges section, especially,
+   making sure that the base address encoding scheme is used.  */
+
+/* Dummy function to provide debug information for.  */
+
+	.text
+	.globl _start
+_start:
+	.4byte 0
+.Lbegin_text1:
+	.globl func_cu1
+	.type func_cu1, %function
+func_cu1:
+.Lbegin_func_cu1:
+	.4byte 0
+.Lend_func_cu1:
+	.size func_cu1, .-func_cu1
+.Lend_text1:
+
+.Lbegin_text2:
+	.globl func_cu2
+	.type func_cu2, %function
+func_cu2:
+.Lbegin_func_cu2:
+	.4byte 0
+.Lend_func_cu2:
+	.size func_cu2, .-func_cu2
+.Lend_text2:
+
+/* Debug information */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+        .4byte  .Lrange1_begin
+	.ascii	"file1.c\0"			/* DW_AT_name */
+	.byte	1				/* DW_AT_language (C) */
+
+	/* func_cu1 */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.ascii		"func_cu1\0"		/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.4byte		.Lbegin_func_cu1	/* DW_AT_low_pc */
+	.4byte		.Lend_func_cu1		/* DW_AT_high_pc */
+
+	/* func_cu1 */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.ascii		"func_cu2\0"		/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.4byte		.Lbegin_func_cu2	/* DW_AT_low_pc */
+	.4byte		.Lend_func_cu2		/* DW_AT_high_pc */
+
+.Ltype_int:
+	.uleb128	3			/* Abbrev: DW_TAG_base_type */
+	.ascii		"int\0"			/* DW_AT_name */
+	.byte		4			/* DW_AT_byte_size */
+	.byte		5			/* DW_AT_encoding */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+        .section .debug_ranges
+.Lrange1_begin:
+        .4byte  0xffffffff                      /* base address marker */
+	.4byte	.Lbegin_text1                   /* base address */
+        .4byte  0                               /* start offset */
+	.4byte	.Lend_text1 - .Lbegin_text1     /* end offset */
+        .4byte  0xffffffff                      /* base address marker */
+	.4byte	.Lbegin_text2                   /* base address */
+        .4byte  0                               /* start offset */
+	.4byte	.Lend_text2 - .Lbegin_text2     /* end offset */
+        .4byte  0                               /* End marker (Part 1) */
+        .4byte  0                               /* End marker (Part 2) */
+
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+        .uleb128	0x55			/* DW_AT_ranges */
+	.uleb128	0x17			/* DW_FORM_sec_offset */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
diff --git a/binutils/testsuite/binutils-all/dw2-ranges.W b/binutils/testsuite/binutils-all/dw2-ranges.W
new file mode 100644
index 0000000..098009b
--- /dev/null
+++ b/binutils/testsuite/binutils-all/dw2-ranges.W
@@ -0,0 +1,11 @@
+
+.*:     file format .*
+
+Contents of the \.debug_ranges section:
+
+    Offset   Begin    End
+    00000000 ffffffff 0000000(0|4) \(base address\)
+    00000000 0000000(0|4) 0000000(4|8) 
+    00000000 ffffffff 0000000(0|8) \(base address\)
+    00000000 0000000(0|8) 0000000(4|c) 
+    00000000 <End of list>
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index c3cbb13..dc1f779 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -244,6 +244,37 @@ if { ![is_elf_format]
     }
 }
 
+# Test objdump -s on a file that contains a compressed .debug section
+
+if { ![is_elf_format] || [istarget "msp430-*-elf"] } then {
+    unsupported "objdump debug_ranges test"
+} elseif { ![binutils_assemble $srcdir/$subdir/dw2-ranges.S tmpdir/dw2-ranges.o] } then {
+    fail "objdump debug_ranges test"
+} else {
+    if [is_remote host] {
+	set ranges_testfile [remote_download host tmpdir/dw2-ranges.o]
+    } else {
+	set ranges_testfile tmpdir/dw2-ranges.o
+    }
+
+    # Test objdump -W on a file containing debug_ranges information.
+
+    set got [remote_exec host "$OBJDUMP $OBJDUMPFLAGS --dwarf=Ranges $ranges_testfile" "" "/dev/null" "objdump.out"]
+
+    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+	fail "objdump -W for debug_ranges (reason: unexpected output)"
+	send_log $got
+	send_log "\n"
+    }
+
+    if { [regexp_diff objdump.out $srcdir/$subdir/dw2-ranges.W] } then {
+	fail "objdump -W for debug_ranges"
+    } else {
+	pass "objdump -W for debug_ranges"
+    }
+}
+
+
 # Options which are not tested: -a -d -D -R -T -x -l --stabs
 # I don't see any generic way to test any of these other than -a.
 # Tests could be written for specific targets, and that should be done
-- 
2.5.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]