mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-30 09:09:16 +08:00
gdb: avoid dereferencing empty str_offsets_base optional in dwarf_decode_macros
Since 4d7188abfdf2 ("gdbsupport: add debug assertions in gdb::optional::get"), some macro-related tests fail on Ubuntu 20.04 with the system gcc 9.3.0 compiler when building with _GLIBCXX_DEBUG. For example, gdb.base/info-macros.exp results in: (gdb) break -qualified main /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/gdb_optional.h:206: internal-error: T& gdb::optional<T>::get() [with T = long unsigned int]: Assertion `this->has_value ()' failed. The binary contains DWARF 4 debug info and includes a pre-standard (pre-DWARF 5) .debug_macro section. The CU doesn't have a DW_AT_str_offsets_base attribute (which doesn't exist in DWARF 4). The field dwarf2_cu::str_offsets_base is therefore empty. At dwarf2/read.c:24138, we unconditionally read the value in the optional, which triggers the assertion shown above. The same thing happens when building the test program with DWARF 5 with the same gcc compiler, as that version of gcc doesn't use indirect string forms, even with DWARF 5. So it still doesn't add a DW_AT_str_offsets_base attribute on the CU. Fix that by propagating down a gdb::optional<ULONGEST> for the str offsets base instead of ULONGEST. That value is only used in dwarf_decode_macro_bytes, when encountering an "strx" macro operation (DW_MACRO_define_strx or DW_MACRO_undef_strx). Add a check there that we indeed have a value in the optional before reading it. This is unlikely to happen, but could happen in theory with an erroneous file that uses DW_MACRO_define_strx but does not provide a DW_AT_str_offsets_base (in practice, some things would probably have failed before and stopped processing of debug info). I tested the complaint by inverting the condition and using a clang-compiled binary, which uses the strx operators. This is the result: During symbol reading: use of DW_MACRO_define_strx with unknown string offsets base [in module /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/info-macros/info-macros] The test now passes cleanly with the setup mentioned above, and the testsuite looks on par with how it was before 4d7188abfdf2. Change-Id: I7ebd2724beb7b9b4178872374c2a177aea696e77
This commit is contained in:
@ -429,7 +429,7 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
|
|||||||
unsigned int offset_size,
|
unsigned int offset_size,
|
||||||
struct dwarf2_section_info *str_section,
|
struct dwarf2_section_info *str_section,
|
||||||
struct dwarf2_section_info *str_offsets_section,
|
struct dwarf2_section_info *str_offsets_section,
|
||||||
ULONGEST str_offsets_base,
|
gdb::optional<ULONGEST> str_offsets_base,
|
||||||
htab_t include_hash)
|
htab_t include_hash)
|
||||||
{
|
{
|
||||||
struct objfile *objfile = per_objfile->objfile;
|
struct objfile *objfile = per_objfile->objfile;
|
||||||
@ -575,15 +575,27 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
|
|||||||
int offset_index = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
int offset_index = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
||||||
mac_ptr += bytes_read;
|
mac_ptr += bytes_read;
|
||||||
|
|
||||||
|
/* Use of the strx operators requires a DW_AT_str_offsets_base. */
|
||||||
|
if (!str_offsets_base.has_value ())
|
||||||
|
{
|
||||||
|
complaint (_("use of %s with unknown string offsets base "
|
||||||
|
"[in module %s]"),
|
||||||
|
(macinfo_type == DW_MACRO_define_strx
|
||||||
|
? "DW_MACRO_define_strx"
|
||||||
|
: "DW_MACRO_undef_strx"),
|
||||||
|
objfile_name (objfile));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
str_offsets_section->read (objfile);
|
str_offsets_section->read (objfile);
|
||||||
const gdb_byte *info_ptr = (str_offsets_section->buffer
|
const gdb_byte *info_ptr = (str_offsets_section->buffer
|
||||||
+ str_offsets_base
|
+ *str_offsets_base
|
||||||
+ offset_index * offset_size);
|
+ offset_index * offset_size);
|
||||||
|
|
||||||
const char *macinfo_str = (macinfo_type == DW_MACRO_define_strx ?
|
const char *macinfo_str = (macinfo_type == DW_MACRO_define_strx ?
|
||||||
"DW_MACRO_define_strx" : "DW_MACRO_undef_strx");
|
"DW_MACRO_define_strx" : "DW_MACRO_undef_strx");
|
||||||
|
|
||||||
if (str_offsets_base + offset_index * offset_size
|
if (*str_offsets_base + offset_index * offset_size
|
||||||
>= str_offsets_section->size)
|
>= str_offsets_section->size)
|
||||||
{
|
{
|
||||||
complaint (_("%s pointing outside of .debug_str_offsets section "
|
complaint (_("%s pointing outside of .debug_str_offsets section "
|
||||||
@ -767,7 +779,8 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
|
|||||||
const struct line_header *lh, unsigned int offset_size,
|
const struct line_header *lh, unsigned int offset_size,
|
||||||
unsigned int offset, struct dwarf2_section_info *str_section,
|
unsigned int offset, struct dwarf2_section_info *str_section,
|
||||||
struct dwarf2_section_info *str_offsets_section,
|
struct dwarf2_section_info *str_offsets_section,
|
||||||
ULONGEST str_offsets_base, int section_is_gnu)
|
gdb::optional<ULONGEST> str_offsets_base,
|
||||||
|
int section_is_gnu)
|
||||||
{
|
{
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
const gdb_byte *mac_ptr, *mac_end;
|
const gdb_byte *mac_ptr, *mac_end;
|
||||||
|
@ -30,7 +30,7 @@ extern void dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
|
|||||||
unsigned int offset,
|
unsigned int offset,
|
||||||
dwarf2_section_info *str_section,
|
dwarf2_section_info *str_section,
|
||||||
dwarf2_section_info *str_offsets_section,
|
dwarf2_section_info *str_offsets_section,
|
||||||
ULONGEST str_offsets_base,
|
gdb::optional<ULONGEST> str_offsets_base,
|
||||||
int section_is_gnu);
|
int section_is_gnu);
|
||||||
|
|
||||||
#endif /* GDB_DWARF2_MACRO_H */
|
#endif /* GDB_DWARF2_MACRO_H */
|
||||||
|
@ -24122,7 +24122,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
|||||||
|
|
||||||
struct dwarf2_section_info *str_offsets_section;
|
struct dwarf2_section_info *str_offsets_section;
|
||||||
struct dwarf2_section_info *str_section;
|
struct dwarf2_section_info *str_section;
|
||||||
ULONGEST str_offsets_base;
|
gdb::optional<ULONGEST> str_offsets_base;
|
||||||
|
|
||||||
if (cu->dwo_unit != nullptr)
|
if (cu->dwo_unit != nullptr)
|
||||||
{
|
{
|
||||||
@ -24135,7 +24135,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
|||||||
{
|
{
|
||||||
str_offsets_section = &per_objfile->per_bfd->str_offsets;
|
str_offsets_section = &per_objfile->per_bfd->str_offsets;
|
||||||
str_section = &per_objfile->per_bfd->str;
|
str_section = &per_objfile->per_bfd->str;
|
||||||
str_offsets_base = *cu->str_offsets_base;
|
str_offsets_base = cu->str_offsets_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwarf_decode_macros (per_objfile, builder, section, lh,
|
dwarf_decode_macros (per_objfile, builder, section, lh,
|
||||||
|
Reference in New Issue
Block a user