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.
This commit is contained in:
parent
bc301448c0
commit
42bcef4ad6
6 changed files with 207 additions and 11 deletions
|
@ -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>
|
2015-11-28 Cary Coutant <ccoutant@gmail.com>
|
||||||
|
|
||||||
* MAINTAINERS: Update my email address.
|
* MAINTAINERS: Update my email address.
|
||||||
|
|
|
@ -4326,6 +4326,16 @@ display_debug_abbrev (struct dwarf_section *section,
|
||||||
return 1;
|
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. */
|
/* Display a location list from a normal (ie, non-dwo) .debug_loc section. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -4380,10 +4390,6 @@ display_loc_list (struct dwarf_section *section,
|
||||||
|
|
||||||
printf (" %8.8lx ", off);
|
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 (begin, start, pointer_size, section_end);
|
||||||
SAFE_BYTE_GET_AND_INC (end, 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. */
|
/* 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;
|
base_address = end;
|
||||||
print_dwarf_vma (begin, pointer_size);
|
print_dwarf_vma (begin, pointer_size);
|
||||||
|
@ -5202,11 +5209,6 @@ display_debug_ranges (struct dwarf_section *section,
|
||||||
dwarf_vma begin;
|
dwarf_vma begin;
|
||||||
dwarf_vma end;
|
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);
|
SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
|
||||||
if (start >= finish)
|
if (start >= finish)
|
||||||
break;
|
break;
|
||||||
|
@ -5221,7 +5223,8 @@ display_debug_ranges (struct dwarf_section *section,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check base address specifiers. */
|
/* 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;
|
base_address = end;
|
||||||
print_dwarf_vma (begin, pointer_size);
|
print_dwarf_vma (begin, pointer_size);
|
||||||
|
|
|
@ -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>
|
2015-10-22 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* binutils-all/add-symbol.d: Run test on mips. Support either
|
* binutils-all/add-symbol.d: Run test on mips. Support either
|
||||||
|
|
140
binutils/testsuite/binutils-all/dw2-ranges.S
Normal file
140
binutils/testsuite/binutils-all/dw2-ranges.S
Normal file
|
@ -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 */
|
11
binutils/testsuite/binutils-all/dw2-ranges.W
Normal file
11
binutils/testsuite/binutils-all/dw2-ranges.W
Normal file
|
@ -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>
|
|
@ -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
|
# 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.
|
# 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
|
# Tests could be written for specific targets, and that should be done
|
||||||
|
|
Loading…
Reference in a new issue