mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 17:18:55 +00:00
Correct bounds check when working around GAS DWARF 5 directory table bug
Recent Go toolchains are causing GDB to crash on a relatively recent
workaround for a GAS bug:
commit a833790a62
Date: Wed Nov 1 00:33:12 2023 +0100
[gdb/symtab] Work around gas PR28629
In the original GAS bug, the first directory table entry did not contain
the current directory of the compilation. So the above commit added a
workaround fix to prepend the second directory table entry.
However recent Go toolchain compilations (specifically on aarch64)
only output a single directory table entry. Looking at the workaround:
if (lh->version == 5 && lh->is_valid_file_index (1))
{
std::string dir = lh->include_dir_at (1);
fnd.set_comp_dir (std::move (dir));
}
`lh->is_valid_file_index (1)' is true, but since the directory table only
has one entry, `include_dir_at (1)' returns nullptr. Consequently the
std::string ctor will segfault. Since there are no guarantees that the file
and directory tables are the same size, a better bounds check is to simply
rely on `include_dir_at' to ensure a valid directory table entry.
I have updated the workaround commit's test, gdb.dwarf2/dw2-gas-workaround.exp
and tested on x86_64 and aarch64 RHEL 9 and Fedora 41.
Approved-By: Andrew Burgess <aburgess@redhat.com>
This commit is contained in:
@@ -6124,7 +6124,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
sect_offset line_offset = (sect_offset) attr->as_unsigned ();
|
||||
line_header_up lh = dwarf_decode_line_header (line_offset, cu,
|
||||
fnd.get_comp_dir ());
|
||||
if (lh->version == 5 && lh->is_valid_file_index (1))
|
||||
if (lh->version == 5 && lh->include_dir_at (1) != nullptr)
|
||||
{
|
||||
std::string dir = lh->include_dir_at (1);
|
||||
fnd.set_comp_dir (std::move (dir));
|
||||
|
||||
@@ -20,7 +20,7 @@ load_lib dwarf.exp
|
||||
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
require dwarf2_support
|
||||
|
||||
standard_testfile dw2-lines.c -dw2.S
|
||||
standard_testfile dw2-lines.c -dw2.S -dw2-one-diridx.S
|
||||
|
||||
with_shared_gdb {
|
||||
set func_info_vars [get_func_info bar]
|
||||
@@ -33,49 +33,61 @@ proc line_for { l } {
|
||||
return [expr $line + 1]
|
||||
}
|
||||
|
||||
set asm_file [standard_output_file $srcfile2]
|
||||
Dwarf::assemble $asm_file {
|
||||
declare_labels Llines
|
||||
global srcdir subdir srcfile objdir
|
||||
global func_info_vars
|
||||
foreach var $func_info_vars {
|
||||
global $var
|
||||
}
|
||||
# A helper proc to create the DWARF assembly for the test.
|
||||
# If ONE_DIRIDX is true, then the directory table will be limited
|
||||
# to one entry.
|
||||
proc create_dwarf_assembly {source_file one_diridx} {
|
||||
set asm_file [standard_output_file $source_file]
|
||||
Dwarf::assemble $asm_file {
|
||||
declare_labels Llines
|
||||
global srcdir subdir srcfile objdir
|
||||
global func_info_vars
|
||||
upvar one_diridx one_diridx
|
||||
foreach var $func_info_vars {
|
||||
global $var
|
||||
}
|
||||
|
||||
cu { version 5 } {
|
||||
compile_unit {
|
||||
DW_AT_language @DW_LANG_Mips_Assembler
|
||||
DW_AT_name $srcfile
|
||||
DW_AT_comp_dir $objdir
|
||||
DW_AT_stmt_list $Llines DW_FORM_sec_offset
|
||||
DW_AT_producer "GNU AS 2.35.2"
|
||||
} {
|
||||
subprogram {
|
||||
DW_AT_external 1 flag
|
||||
DW_AT_name bar
|
||||
DW_AT_low_pc $bar_start addr
|
||||
DW_AT_high_pc "$bar_start + $bar_len" addr
|
||||
cu { version 5 } {
|
||||
compile_unit {
|
||||
DW_AT_language @DW_LANG_Mips_Assembler
|
||||
DW_AT_name $srcfile
|
||||
DW_AT_comp_dir $objdir
|
||||
DW_AT_stmt_list $Llines DW_FORM_sec_offset
|
||||
DW_AT_producer "GNU AS 2.35.2"
|
||||
} {
|
||||
subprogram {
|
||||
DW_AT_external 1 flag
|
||||
DW_AT_name bar
|
||||
DW_AT_low_pc $bar_start addr
|
||||
DW_AT_high_pc "$bar_start + $bar_len" addr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lines [list version 5] Llines {
|
||||
set diridx1 [include_dir "${srcdir}/${subdir}"]
|
||||
file_name "$srcfile" $diridx1
|
||||
if {!$one_diridx} {
|
||||
set diridx2 [include_dir "${srcdir}/${subdir}"]
|
||||
file_name "$srcfile" $diridx2
|
||||
} else {
|
||||
file_name "$srcfile" $diridx1
|
||||
}
|
||||
program {
|
||||
DW_LNE_set_address bar_label
|
||||
line [line_for bar_label]
|
||||
DW_LNS_copy
|
||||
|
||||
DW_LNE_set_address $bar_end
|
||||
DW_LNE_end_sequence
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lines [list version 5] Llines {
|
||||
set diridx1 [include_dir "${srcdir}/${subdir}"]
|
||||
set diridx2 [include_dir "${srcdir}/${subdir}"]
|
||||
file_name "$srcfile" $diridx1
|
||||
file_name "$srcfile" $diridx2
|
||||
|
||||
program {
|
||||
DW_LNE_set_address bar_label
|
||||
line [line_for bar_label]
|
||||
DW_LNS_copy
|
||||
|
||||
DW_LNE_set_address $bar_end
|
||||
DW_LNE_end_sequence
|
||||
}
|
||||
}
|
||||
return $asm_file
|
||||
}
|
||||
|
||||
set asm_file [create_dwarf_assembly $srcfile2 false]
|
||||
if { [prepare_for_testing "failed to prepare" ${testfile} \
|
||||
[list $srcfile $asm_file] {nodebug}] } {
|
||||
return -1
|
||||
@@ -90,3 +102,13 @@ gdb_test_multiple "ptype bar" "" {
|
||||
pass $gdb_test_name
|
||||
}
|
||||
}
|
||||
|
||||
# Test whether gdb crashes in the case where the number of
|
||||
# directory indexes is only one.
|
||||
set asm_file [create_dwarf_assembly $srcfile3 true]
|
||||
if {[prepare_for_testing "failed to prepare" ${testfile}-one-diridx \
|
||||
[list $srcfile $asm_file] {nodebug}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_test "ptype bar" ".*" "do not crash with only one directory table entry"
|
||||
|
||||
Reference in New Issue
Block a user