diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-10-16 10:08:19 +0200 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-12-10 09:53:46 +0000 |
commit | 28d2bfb9c3e519a3b7619bbe5d061ebe520750ef (patch) | |
tree | 6d5d3817360c2c2ae738248ea453e7b1d8b68031 /gdb/testsuite/lib | |
parent | c74088593761f7e839aa9a97728df146f3dfb3d6 (diff) | |
download | gdb-28d2bfb9c3e519a3b7619bbe5d061ebe520750ef.zip gdb-28d2bfb9c3e519a3b7619bbe5d061ebe520750ef.tar.gz gdb-28d2bfb9c3e519a3b7619bbe5d061ebe520750ef.tar.bz2 |
gdb: Handle multiple base address in debug_ranges data.
It is possible to use multiple base addresses within a single address
range series, within the .debug_ranges section. The following is a
simplified example for 32-bit addresses:
.section ".debug_ranges"
.4byte 0xffffffff
.4byte BASE_1
.4byte START_OFFSET_1
.4byte END_OFFSET_1
.4byte START_OFFSET_2
.4byte END_OFFSET_2
.4byte 0xffffffff
.4byte BASE_2
.4byte START_OFFSET_3
.4byte END_OFFSET_3
.4byte 0
.4byte 0
In this example START/END 1 and 2 are relative to BASE_1, while
START/END 3 are relative to BASE_2.
Currently gdb does not correctly parse this DWARF, resulting in
corrupted address range information. This commit fixes this issue, and
adds a new test to cover this case.
In order to support testing of this feature extensions were made to the
testsuite dwarf assembler, additional functionality was added to the
.debug_line generation function, and a new function for generating the
.debug_ranges section was added.
gdb/ChangeLog:
* dwarf2read.c (dwarf2_ranges_read): Unify and fix base address
reading code.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-ranges-base.c: New file.
* gdb.dwarf2/dw2-ranges-base.exp: New file.
* lib/dwarf.exp (namespace eval Dwarf): Add new variables to
support additional line table, and debug ranges generation.
(Dwarf::ranges): New function, generate .debug_ranges.
(Dwarf::lines): Support generating simple line table programs.
(Dwarf::assemble): Initialise new namespace variables.
Diffstat (limited to 'gdb/testsuite/lib')
-rw-r--r-- | gdb/testsuite/lib/dwarf.exp | 175 |
1 files changed, 165 insertions, 10 deletions
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index c87da87..44200a1 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -303,6 +303,15 @@ namespace eval Dwarf { # Whether a file_name entry was seen. variable _line_saw_file + # Whether a line table program has been seen. + variable _line_saw_program + + # A Label for line table header generation. + variable _line_header_end_label + + # The address size for debug ranges section. + variable _debug_ranges_64_bit + proc _process_one_constant {name value} { variable _constants variable _AT @@ -992,7 +1001,7 @@ namespace eval Dwarf { set _cu_label [_compute_label "cu${cu_num}_begin"] set start_label [_compute_label "cu${cu_num}_start"] set end_label [_compute_label "cu${cu_num}_end"] - + define_label $_cu_label if {$is_64} { _op .4byte 0xffffffff @@ -1129,6 +1138,78 @@ namespace eval Dwarf { define_label $end_label } + # Emit a DWARF .debug_ranges unit. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if you want to emit 64-bit DWARF + # default = 0 (32-bit) + # + # BODY is Tcl code that emits the content of the .debug_ranges + # unit, it is evaluated in the caller's context. + proc ranges {options body} { + variable _debug_ranges_64_bit + + foreach { name value } $options { + switch -exact -- $name { + is_64 { set _debug_ranges_64_bit [subst $value] } + default { error "unknown option $name" } + } + } + + set section ".debug_ranges" + _section $section + + proc sequence {{ranges {}}} { + variable _debug_ranges_64_bit + + # Emit the sequence of addresses. + set base "" + foreach range $ranges { + set range [uplevel 1 "subst \"$range\""] + set type [lindex $range 0] + switch -exact -- $type { + base { + set base [lrange $range 1 end] + + if { $_debug_ranges_64_bit } then { + _op .8byte 0xffffffffffffffff "Base Marker" + _op .8byte $base "Base Address" + } else { + _op .4byte 0xffffffff "Base Marker" + _op .4byte $base "Base Address" + } + } + range { + set start [lindex $range 1] + set end [lrange $range 2 end] + + if { $_debug_ranges_64_bit } then { + _op .8byte $start "Start Address" + _op .8byte $end "End Address" + } else { + _op .4byte $start "Start Address" + _op .4byte $end "End Address" + } + } + default { error "unknown range type: $type " } + } + } + + # End of the sequence. + if { $_debug_ranges_64_bit } then { + _op .8byte 0x0 "End of Sequence Marker (Part 1)" + _op .8byte 0x0 "End of Sequence Marker (Part 2)" + } else { + _op .4byte 0x0 "End of Sequence Marker (Part 1)" + _op .4byte 0x0 "End of Sequence Marker (Part 2)" + } + } + + uplevel $body + } + + # Emit a DWARF .debug_line unit. # OPTIONS is a list with an even number of elements containing # option-name and option-value pairs. @@ -1157,6 +1238,8 @@ namespace eval Dwarf { proc lines {options label body} { variable _line_count variable _line_saw_file + variable _line_saw_program + variable _line_header_end_label # Establish the defaults. set is_64 0 @@ -1192,7 +1275,7 @@ namespace eval Dwarf { set unit_len_label [_compute_label "line${_line_count}_start"] set unit_end_label [_compute_label "line${_line_count}_end"] set header_len_label [_compute_label "line${_line_count}_header_start"] - set header_end_label [_compute_label "line${_line_count}_header_end"] + set _line_header_end_label [_compute_label "line${_line_count}_header_end"] if {$is_64} { _op .4byte 0xffffffff @@ -1206,20 +1289,34 @@ namespace eval Dwarf { _op .2byte $_unit_version version if {$is_64} { - _op .8byte "$header_end_label - $header_len_label" "header_length" + _op .8byte "$_line_header_end_label - $header_len_label" "header_length" } else { - _op .4byte "$header_end_label - $header_len_label" "header_length" + _op .4byte "$_line_header_end_label - $header_len_label" "header_length" } define_label $header_len_label _op .byte 1 "minimum_instruction_length" - _op .byte 0 "default_is_stmt" + _op .byte 1 "default_is_stmt" _op .byte 1 "line_base" _op .byte 1 "line_range" - _op .byte 1 "opcode_base" - # Since we emit opcode_base==1, we skip - # standard_opcode_length table altogether. + _op .byte 10 "opcode_base" + + # The standard_opcode_lengths table. The number of arguments + # for each of the standard opcodes. Generating 9 entries here + # matches the use of 10 in the opcode_base above. These 9 + # entries match the 9 standard opcodes for DWARF2, making use + # of only 9 should be fine, even if we are generating DWARF3 + # or DWARF4. + _op .byte 0 "standard opcode 1" + _op .byte 1 "standard opcode 2" + _op .byte 1 "standard opcode 3" + _op .byte 1 "standard opcode 4" + _op .byte 1 "standard opcode 5" + _op .byte 0 "standard opcode 6" + _op .byte 0 "standard opcode 7" + _op .byte 0 "standard opcode 8" + _op .byte 1 "standard opcode 9" proc include_dir {dirname} { _op .ascii [_quote $dirname] @@ -1239,6 +1336,57 @@ namespace eval Dwarf { _op .sleb128 0 "length" } + proc program {statements} { + variable _line_saw_program + variable _line_header_end_label + + if "! $_line_saw_program" { + # Terminate the file list. + _op .byte 0 "Terminator." + define_label $_line_header_end_label + set _line_saw_program 1 + } + + proc DW_LNE_set_address {addr} { + _op .byte 0 + set start [new_label "set_address_start"] + set end [new_label "set_address_end"] + _op .uleb128 "${end} - ${start}" + define_label ${start} + _op .byte 2 + if {[is_64_target]} { + _op .8byte ${addr} + } else { + _op .4byte ${addr} + } + define_label ${end} + } + + proc DW_LNE_end_sequence {} { + _op .byte 0 + _op .uleb128 1 + _op .byte 1 + } + + proc DW_LNS_copy {} { + _op .byte 1 + } + + proc DW_LNS_advance_pc {offset} { + _op .byte 2 + _op .uleb128 ${offset} + } + + proc DW_LNS_advance_line {offset} { + _op .byte 3 + _op .sleb128 ${offset} + } + + foreach statement $statements { + uplevel 1 $statement + } + } + uplevel $body rename include_dir "" @@ -1250,9 +1398,11 @@ namespace eval Dwarf { } # Terminate the file list. - _op .byte 0 "Terminator." + if "! $_line_saw_program" { + _op .byte 0 "Terminator." + define_label $_line_header_end_label + } - define_label $header_end_label define_label $unit_end_label } @@ -1337,6 +1487,9 @@ namespace eval Dwarf { variable _cu_count variable _line_count variable _line_saw_file + variable _line_saw_program + variable _line_header_end_label + variable _debug_ranges_64_bit if {!$_initialized} { _read_constants @@ -1352,6 +1505,8 @@ namespace eval Dwarf { set _line_count 0 set _line_saw_file 0 + set _line_saw_program 0 + set _debug_ranges_64_bit [is_64_target] # Not "uplevel" here, because we want to evaluate in this # namespace. This is somewhat bad because it means we can't |