aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
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/dwarf2
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/dwarf2')
-rw-r--r--gdb/dwarf2/line-header.c15
-rw-r--r--gdb/dwarf2/read.c12
-rw-r--r--gdb/dwarf2/read.h5
3 files changed, 26 insertions, 6 deletions
diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c
index 1519576..852e285 100644
--- a/gdb/dwarf2/line-header.c
+++ b/gdb/dwarf2/line-header.c
@@ -137,7 +137,7 @@ read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
static void
read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd,
const gdb_byte **bufp, struct line_header *lh,
- const struct comp_unit_head *cu_header,
+ unsigned int offset_size,
void (*callback) (struct line_header *lh,
const char *name,
dir_index d_index,
@@ -187,9 +187,12 @@ read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd,
break;
case DW_FORM_line_strp:
- string.emplace
- (per_objfile->read_line_string (buf, cu_header, &bytes_read));
- buf += bytes_read;
+ {
+ const char *str
+ = per_objfile->read_line_string (buf, offset_size);
+ string.emplace (str);
+ buf += offset_size;
+ }
break;
case DW_FORM_data1:
@@ -372,7 +375,7 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz,
{
/* Read directory table. */
read_formatted_entries (per_objfile, abfd, &line_ptr, lh.get (),
- cu_header,
+ offset_size,
[] (struct line_header *header, const char *name,
dir_index d_index, unsigned int mod_time,
unsigned int length)
@@ -382,7 +385,7 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz,
/* Read file name table. */
read_formatted_entries (per_objfile, abfd, &line_ptr, lh.get (),
- cu_header,
+ offset_size,
[] (struct line_header *header, const char *name,
dir_index d_index, unsigned int mod_time,
unsigned int length)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 4a963e4..a513cc4 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -20306,6 +20306,18 @@ read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *abfd,
const char *
dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
+ unsigned int offset_size)
+{
+ bfd *abfd = objfile->obfd;
+ ULONGEST str_offset = read_offset (abfd, buf, offset_size);
+
+ return per_bfd->line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
+}
+
+/* See read.h. */
+
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 1638d85..fe34e3f 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -517,6 +517,11 @@ struct dwarf2_per_objfile
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr);
+ /* Return pointer to string at .debug_line_str offset as read from BUF.
+ The offset_size is OFFSET_SIZE. */
+ const char *read_line_string (const gdb_byte *buf,
+ unsigned int offset_size);
+
/* Return true if the symtab corresponding to PER_CU has been set,
false otherwise. */
bool symtab_set_p (const dwarf2_per_cu_data *per_cu) const;