diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-10-16 11:58:02 +0200 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-11-30 13:28:26 +0000 |
commit | 42bcef4ad646732e0684557fe08b74dd0c5aa7e9 (patch) | |
tree | 2acf45f8515750719a487e904f25e08686c84572 /binutils | |
parent | bc301448c07afbf8aa70f2808be68dc8c50c9098 (diff) | |
download | gdb-42bcef4ad646732e0684557fe08b74dd0c5aa7e9.zip gdb-42bcef4ad646732e0684557fe08b74dd0c5aa7e9.tar.gz gdb-42bcef4ad646732e0684557fe08b74dd0c5aa7e9.tar.bz2 |
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.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 7 | ||||
-rw-r--r-- | binutils/dwarf.c | 25 | ||||
-rw-r--r-- | binutils/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/dw2-ranges.S | 140 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/dw2-ranges.W | 11 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/objdump.exp | 29 |
6 files changed, 207 insertions, 11 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index b058ead..73698d9 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2015-11-30 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-28 Cary Coutant <ccoutant@gmail.com> * MAINTAINERS: Update my email address. 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..57d9b89 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-11-30 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..4dfd248 --- /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 00000004 \(base address\) + 00000000 00000004 00000008 + 00000000 ffffffff 00000008 \(base address\) + 00000000 00000008 0000000c + 00000000 <End of list> diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp index c3cbb13..66b27e3 100644 --- a/binutils/testsuite/binutils-all/objdump.exp +++ b/binutils/testsuite/binutils-all/objdump.exp @@ -244,6 +244,35 @@ if { ![is_elf_format] } } +# Test objdump -W on a file containing debug_ranges information. + +if { ![is_elf_format] } 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 + } + + 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 |