aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/lib/dwarf.exp
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2021-11-22 09:14:16 +0100
committerTom de Vries <tdevries@suse.de>2021-11-22 09:14:16 +0100
commitbab31d145160cd4dec7b9ad0e79346382ebf8385 (patch)
tree85261ec6bfe218eb40d187efe56da0d409e05ea9 /gdb/testsuite/lib/dwarf.exp
parent26bf28e29d7b3bddc6d2f8f34f07000f2b858588 (diff)
downloadgdb-bab31d145160cd4dec7b9ad0e79346382ebf8385.zip
gdb-bab31d145160cd4dec7b9ad0e79346382ebf8385.tar.gz
gdb-bab31d145160cd4dec7b9ad0e79346382ebf8385.tar.bz2
[gdb/symtab] Support .debug_line with DW_FORM_line_strp
I noticed a new gcc option -gdwarf64 and tried it out (using gcc 11.2.1). With a test-case hello.c: ... int main (void) { printf ("hello\n"); return 0; } ... compiled like this: ... $ gcc -g -gdwarf64 ~/hello.c ... I ran into: ... $ gdb -q -batch a.out DW_FORM_line_strp pointing outside of .debug_line_str section \ [in module a.out] ... Debugging gdb revealed that the string offset is: ... (gdb) up objfile=0x182ab70, str_offset=1378684502312, form_name=0xeae9b5 "DW_FORM_line_strp") at src/gdb/dwarf2/section.c:208 208 error (_("%s pointing outside of %s section [in module %s]"), (gdb) p /x str_offset $1 = 0x14100000128 (gdb) ... which is read when parsing a .debug_line entry at 0x1e0. Looking with readelf at the 0x1e0 entry, we have: ... The Directory Table (offset 0x202, lines 2, columns 1): Entry Name 0 (indirect line string, offset: 0x128): /data/gdb_versions/devel 1 (indirect line string, offset: 0x141): /home/vries ... which in a hexdump looks like: ... 0x00000200 1f022801 00004101 00000201 1f020f02 ... What happens is the following: - readelf interprets the DW_FORM_line_strp reference to .debug_line_str as a 4 byte value, and sees entries 0x00000128 and 0x00000141. - gdb instead interprets it as an 8 byte value, and sees as first entry 0x0000014100000128, which is too big so it bails out. AFAIU, gdb is wrong. It assumes DW_FORM_line_strp is 8 bytes on the basis that the corresponding CU is 64-bit DWARF. However, the .debug_line contribution has it's own initial_length field, and encodes there that it's 32-bit DWARF. Fix this by using the correct offset size for DW_FORM_line_strp references in .debug_line. Note: the described test-case does trigger this complaint (both with and without this patch): ... $ gdb -q -batch -iex "set complaints 10" a.out During symbol reading: intermixed 32-bit and 64-bit DWARF sections ... The reason that the CU has 64-bit dwarf is because -gdwarf64 was passed to gcc. The reason that the .debug_line entry has 32-bit dwarf is because that's what gas generates. Perhaps this is complaint-worthy, but I don't think it is wrong. Tested on x86_64-linux, using native and target board dwarf64.exp.
Diffstat (limited to 'gdb/testsuite/lib/dwarf.exp')
-rw-r--r--gdb/testsuite/lib/dwarf.exp75
1 files changed, 65 insertions, 10 deletions
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index b2a3372..cbb1bf6 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -2185,9 +2185,11 @@ namespace eval Dwarf {
variable _line_saw_program
variable _line_header_end_label
variable _line_unit_version
+ variable _line_is_64
+ variable _line_string_form
# Establish the defaults.
- set is_64 0
+ set _line_is_64 0
set _line_unit_version 4
set _unit_addr_size default
set _line_saw_program 0
@@ -2197,14 +2199,17 @@ namespace eval Dwarf {
set _line_header_finalized 0
set _default_is_stmt 1
set _seg_sel_size 0
+ #set _line_string_form string
+ set _line_string_form line_strp
foreach { name value } $options {
switch -exact -- $name {
- is_64 { set is_64 $value }
+ is_64 { set _line_is_64 $value }
version { set _line_unit_version $value }
addr_size { set _unit_addr_size $value }
seg_sel_size { set _seg_sel_size $value }
default_is_stmt { set _default_is_stmt $value }
+ string_form { set $_line_string_form $value }
default { error "unknown option $name" }
}
}
@@ -2231,7 +2236,7 @@ namespace eval Dwarf {
set header_len_label [_compute_label "line${_line_count}_header_start"]
set _line_header_end_label [_compute_label "line${_line_count}_header_end"]
- if {$is_64} {
+ if {$_line_is_64} {
_op .4byte 0xffffffff
_op .8byte "$unit_end_label - $unit_len_label" "unit_length"
} else {
@@ -2248,7 +2253,7 @@ namespace eval Dwarf {
_op .byte $_seg_sel_size "seg_sel_size"
}
- if {$is_64} {
+ if {$_line_is_64} {
_op .8byte "$_line_header_end_label - $header_len_label" "header_length"
} else {
_op .4byte "$_line_header_end_label - $header_len_label" "header_length"
@@ -2306,12 +2311,22 @@ namespace eval Dwarf {
variable _line_file_names
variable _line_unit_version
+ variable _line_is_64
+ variable _line_string_form
if { $_line_unit_version >= 5 } {
_op .byte 1 "directory_entry_format_count"
_op .uleb128 1 \
"directory_entry_format (content type code: DW_LNCT_path)"
- _op .uleb128 0x08 \
- "directory_entry_format (form: DW_FORM_string)"
+ switch $_line_string_form {
+ string {
+ _op .uleb128 0x08 \
+ "directory_entry_format (form: DW_FORM_string)"
+ }
+ line_strp {
+ _op .uleb128 0x1f \
+ "directory_entry_format (form: DW_FORM_line_strp)"
+ }
+ }
set nr_dirs [llength $_line_include_dirs]
# For entry 0.
@@ -2324,14 +2339,38 @@ namespace eval Dwarf {
[concat [list $dirname] $_line_include_dirs]
foreach dirname $_line_include_dirs {
- _op .ascii [_quote $dirname]
+ switch $_line_string_form {
+ string {
+ _op .ascii [_quote $dirname]
+ }
+ line_strp {
+ declare_labels string_ptr
+ _defer_output .debug_line_str {
+ string_ptr:
+ _op .ascii [_quote $dirname]
+ }
+ if { $_line_is_64 } {
+ _op .8byte $string_ptr
+ } else {
+ _op .4byte $string_ptr
+ }
+ }
+ }
}
_op .byte 2 "file_name_entry_format_count"
_op .uleb128 1 \
"file_name_entry_format (content type code: DW_LNCT_path)"
- _op .uleb128 0x08 \
- "file_name_entry_format (form: DW_FORM_string)"
+ switch $_line_string_form {
+ string {
+ _op .uleb128 0x08 \
+ "directory_entry_format (form: DW_FORM_string)"
+ }
+ line_strp {
+ _op .uleb128 0x1f \
+ "directory_entry_format (form: DW_FORM_line_strp)"
+ }
+ }
_op .uleb128 2 \
"file_name_entry_format (content type code: DW_LNCT_directory_index)"
_op .uleb128 0x0f \
@@ -2349,7 +2388,23 @@ namespace eval Dwarf {
[concat [list $filename $diridx] $_line_file_names]
foreach { filename diridx } $_line_file_names {
- _op .ascii [_quote $filename]
+ switch $_line_string_form {
+ string {
+ _op .ascii [_quote $filename]
+ }
+ line_strp {
+ declare_labels string_ptr
+ _defer_output .debug_line_str {
+ string_ptr:
+ _op .ascii [_quote $filename]
+ }
+ if { $_line_is_64 } {
+ _op .8byte $string_ptr
+ } else {
+ _op .4byte $string_ptr
+ }
+ }
+ }
_op .uleb128 $diridx
}
} else {