Import fixes from GNU binutils mainline for handling DWARF-5 debug information.

This commit is contained in:
Nick Clifton 2020-08-25 16:57:53 +01:00
parent d62f898ae7
commit 2e0c2015a5
2 changed files with 434 additions and 1 deletions

View File

@ -0,0 +1,426 @@
diff -rup binutils.orig/bfd/dwarf2.c binutils-2.35/bfd/dwarf2.c
--- binutils.orig/bfd/dwarf2.c 2020-08-25 15:40:47.642219922 +0100
+++ binutils-2.35/bfd/dwarf2.c 2020-08-25 15:41:16.271039143 +0100
@@ -130,6 +130,12 @@ struct dwarf2_debug_file
/* Length of the loaded .debug_ranges section. */
bfd_size_type dwarf_ranges_size;
+ /* Pointer to the .debug_rnglists section loaded into memory. */
+ bfd_byte *dwarf_rnglists_buffer;
+
+ /* Length of the loaded .debug_rnglists section. */
+ bfd_size_type dwarf_rnglists_size;
+
/* A list of all previously read comp_units. */
struct comp_unit *all_comp_units;
@@ -327,6 +333,7 @@ const struct dwarf_debug_section dwarf_d
{ ".debug_pubnames", ".zdebug_pubnames" },
{ ".debug_pubtypes", ".zdebug_pubtypes" },
{ ".debug_ranges", ".zdebug_ranges" },
+ { ".debug_rnglists", ".zdebug_rnglist" },
{ ".debug_static_func", ".zdebug_static_func" },
{ ".debug_static_vars", ".zdebug_static_vars" },
{ ".debug_str", ".zdebug_str", },
@@ -360,6 +367,7 @@ enum dwarf_debug_section_enum
debug_pubnames,
debug_pubtypes,
debug_ranges,
+ debug_rnglists,
debug_static_func,
debug_static_vars,
debug_str,
@@ -1329,6 +1337,17 @@ read_attribute_value (struct attribute *
attr->form = DW_FORM_sdata;
attr->u.sval = implicit_const;
break;
+ case DW_FORM_data16:
+ /* This is really a "constant", but there is no way to store that
+ so pretend it is a 16 byte block instead. */
+ amt = sizeof (struct dwarf_block);
+ blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+ if (blk == NULL)
+ return NULL;
+ blk->size = 16;
+ info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
+ attr->u.blk = blk;
+ break;
default:
_bfd_error_handler (_("DWARF error: invalid or unhandled FORM value: %#x"),
form);
@@ -2069,11 +2088,17 @@ read_formatted_entries (struct comp_unit
case DW_FORM_udata:
*uintp = attr.u.val;
break;
+
+ case DW_FORM_data16:
+ /* MD5 data is in the attr.blk, but we are ignoring those. */
+ break;
}
}
- if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
- return FALSE;
+ /* Skip the first "zero entry", which is the compilation dir/file. */
+ if (datai != 0)
+ if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+ return FALSE;
}
*bufp = buf;
@@ -2617,6 +2642,19 @@ read_debug_ranges (struct comp_unit * un
&file->dwarf_ranges_buffer, &file->dwarf_ranges_size);
}
+/* Read in the .debug_rnglists section for future reference. */
+
+static bfd_boolean
+read_debug_rnglists (struct comp_unit * unit)
+{
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
+
+ return read_section (unit->abfd, &stash->debug_sections[debug_rnglists],
+ file->syms, 0,
+ &file->dwarf_rnglists_buffer, &file->dwarf_rnglists_size);
+}
+
/* Function table functions. */
static int
@@ -3107,8 +3145,8 @@ find_abstract_instance (struct comp_unit
}
static bfd_boolean
-read_rangelist (struct comp_unit *unit, struct arange *arange,
- bfd_uint64_t offset)
+read_ranges (struct comp_unit *unit, struct arange *arange,
+ bfd_uint64_t offset)
{
bfd_byte *ranges_ptr;
bfd_byte *ranges_end;
@@ -3153,6 +3191,107 @@ read_rangelist (struct comp_unit *unit,
return TRUE;
}
+static bfd_boolean
+read_rnglists (struct comp_unit *unit, struct arange *arange,
+ bfd_uint64_t offset)
+{
+ bfd_byte *rngs_ptr;
+ bfd_byte *rngs_end;
+ bfd_vma base_address = unit->base_address;
+ bfd_vma low_pc;
+ bfd_vma high_pc;
+ bfd *abfd = unit->abfd;
+
+ if (! unit->file->dwarf_rnglists_buffer)
+ {
+ if (! read_debug_rnglists (unit))
+ return FALSE;
+ }
+
+ rngs_ptr = unit->file->dwarf_rnglists_buffer + offset;
+ if (rngs_ptr < unit->file->dwarf_rnglists_buffer)
+ return FALSE;
+ rngs_end = unit->file->dwarf_rnglists_buffer;
+ rngs_end += unit->file->dwarf_rnglists_size;
+
+ for (;;)
+ {
+ enum dwarf_range_list_entry rlet;
+ unsigned int bytes_read;
+
+ if (rngs_ptr + 1 > rngs_end)
+ return FALSE;
+
+ rlet = read_1_byte (abfd, rngs_ptr, rngs_end);
+ rngs_ptr++;
+
+ switch (rlet)
+ {
+ case DW_RLE_end_of_list:
+ return TRUE;
+
+ case DW_RLE_base_address:
+ if (rngs_ptr + unit->addr_size > rngs_end)
+ return FALSE;
+ base_address = read_address (unit, rngs_ptr, rngs_end);
+ rngs_ptr += unit->addr_size;
+ continue;
+
+ case DW_RLE_start_length:
+ if (rngs_ptr + unit->addr_size > rngs_end)
+ return FALSE;
+ low_pc = read_address (unit, rngs_ptr, rngs_end);
+ rngs_ptr += unit->addr_size;
+ high_pc = low_pc;
+ high_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+ FALSE, rngs_end);
+ rngs_ptr += bytes_read;
+ break;
+
+ case DW_RLE_offset_pair:
+ low_pc = base_address;
+ low_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+ FALSE, rngs_end);
+ high_pc = base_address;
+ high_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+ FALSE, rngs_end);
+ break;
+
+ case DW_RLE_start_end:
+ if (rngs_ptr + 2 * unit->addr_size > rngs_end)
+ return FALSE;
+ low_pc = read_address (unit, rngs_ptr, rngs_end);
+ rngs_ptr += unit->addr_size;
+ high_pc = read_address (unit, rngs_ptr, rngs_end);
+ rngs_ptr += unit->addr_size;
+ break;
+
+ /* TODO x-variants need .debug_addr support used for split-dwarf. */
+ case DW_RLE_base_addressx:
+ case DW_RLE_startx_endx:
+ case DW_RLE_startx_length:
+ default:
+ return FALSE;
+ }
+
+ if ((low_pc == 0 && high_pc == 0) || low_pc == high_pc)
+ return FALSE;
+
+ if (!arange_add (unit, arange, low_pc, high_pc))
+ return FALSE;
+ }
+}
+
+static bfd_boolean
+read_rangelist (struct comp_unit *unit, struct arange *arange,
+ bfd_uint64_t offset)
+{
+ if (unit->version <= 4)
+ return read_ranges (unit, arange, offset);
+ else
+ return read_rnglists (unit, arange, offset);
+}
+
static struct varinfo *
lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
{
diff -rup binutils.orig/binutils/testsuite/binutils-all/readelf.exp binutils-2.35/binutils/testsuite/binutils-all/readelf.exp
--- binutils.orig/binutils/testsuite/binutils-all/readelf.exp 2020-08-25 15:40:46.998223989 +0100
+++ binutils-2.35/binutils/testsuite/binutils-all/readelf.exp 2020-08-25 15:41:08.408088795 +0100
@@ -188,7 +188,7 @@ proc readelf_wi_test {} {
".*DW_TAG_subprogram.*"
".*DW_TAG_base_type.*"
".*DW_AT_producer.*(GNU C|indirect string).*"
- ".*DW_AT_language.*ANSI C.*"
+ ".*DW_AT_language.*(ANSI C|C11).*"
".*DW_AT_name.*(testprog.c|indirect string).*"
".*DW_AT_name.*fn.*"
".*DW_AT_name.*(main|indirect string).*"
diff -rup binutils.orig/gas/dwarf2dbg.c binutils-2.35/gas/dwarf2dbg.c
--- binutils.orig/gas/dwarf2dbg.c 2020-08-25 15:40:47.251222391 +0100
+++ binutils-2.35/gas/dwarf2dbg.c 2020-08-25 15:41:44.775859148 +0100
@@ -1992,18 +1992,29 @@ out_dir_and_file_list (void)
the .debug_line_str section and reference them here. */
out_uleb128 (DW_FORM_string);
- /* Now state how many rows there are in the table. */
- out_uleb128 (dirs_in_use);
+ /* Now state how many rows there are in the table. We need at
+ least 1 if there is one or more file names to store the
+ "working directory". */
+ if (dirs_in_use == 0 && files_in_use > 0)
+ out_uleb128 (1);
+ else
+ out_uleb128 (dirs_in_use);
}
/* Emit directory list. */
- if (DWARF2_LINE_VERSION >= 5 && dirs_in_use > 0)
+ if (DWARF2_LINE_VERSION >= 5 && (dirs_in_use > 0 || files_in_use > 0))
{
- if (dirs == NULL || dirs[0] == NULL)
- dir = remap_debug_filename (".");
- else
+ /* DWARF5 uses slot zero, but that is only set explicitly
+ using a .file 0 directive. If that isn't used, but dir
+ one is used, then use that as main file directory.
+ Otherwise use pwd as main file directory. */
+ if (dirs_in_use > 0 && dirs != NULL && dirs[0] != NULL)
dir = remap_debug_filename (dirs[0]);
-
+ else if (dirs_in_use > 1 && dirs != NULL && dirs[1] != NULL)
+ dir = remap_debug_filename (dirs[1]);
+ else
+ dir = remap_debug_filename (getpwd ());
+
size = strlen (dir) + 1;
cp = frag_more (size);
memcpy (cp, dir, size);
@@ -2089,8 +2100,14 @@ out_dir_and_file_list (void)
if (files[i].filename == NULL)
{
- /* Prevent a crash later, particularly for file 1. */
- files[i].filename = "";
+ /* Prevent a crash later, particularly for file 1. DWARF5
+ uses slot zero, but that is only set explicitly using a
+ .file 0 directive. If that isn't used, but file 1 is,
+ then use that as main file name. */
+ if (DWARF2_LINE_VERSION >= 5 && i == 0 && files_in_use >= 1)
+ files[0].filename = files[1].filename;
+ else
+ files[i].filename = "";
if (DWARF2_LINE_VERSION < 5 || i != 0)
{
as_bad (_("unassigned file number %ld"), (long) i);
@@ -2427,8 +2444,7 @@ out_debug_abbrev (segT abbrev_seg,
if (DWARF2_VERSION < 4)
out_abbrev (DW_AT_high_pc, DW_FORM_addr);
else
- out_abbrev (DW_AT_high_pc, (sizeof_address == 4
- ? DW_FORM_data4 : DW_FORM_data8));
+ out_abbrev (DW_AT_high_pc, DW_FORM_udata);
}
else
{
@@ -2464,12 +2480,26 @@ out_debug_info (segT info_seg, segT abbr
/* DWARF version. */
out_two (DWARF2_VERSION);
- /* .debug_abbrev offset */
- TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);
+ if (DWARF2_VERSION < 5)
+ {
+ /* .debug_abbrev offset */
+ TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);
+ }
+ else
+ {
+ /* unit (header) type */
+ out_byte (DW_UT_compile);
+ }
/* Target address size. */
out_byte (sizeof_address);
+ if (DWARF2_VERSION >= 5)
+ {
+ /* .debug_abbrev offset */
+ TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);
+ }
+
/* DW_TAG_compile_unit DIE abbrev */
out_uleb128 (1);
@@ -2497,7 +2527,10 @@ out_debug_info (segT info_seg, segT abbr
}
exp.X_add_symbol = all_segs->text_end;
exp.X_add_number = 0;
- emit_expr (&exp, sizeof_address);
+ if (DWARF2_VERSION < 4)
+ emit_expr (&exp, sizeof_address);
+ else
+ emit_leb128_expr (&exp, 0);
}
else
{
diff -rup binutils.orig/gas/read.c binutils-2.35/gas/read.c
--- binutils.orig/gas/read.c 2020-08-25 15:40:47.251222391 +0100
+++ binutils-2.35/gas/read.c 2020-08-25 15:41:44.776859141 +0100
@@ -5138,7 +5138,7 @@ output_big_leb128 (char *p, LITTLENUM_TY
/* Generate the appropriate fragments for a given expression to emit a
leb128 value. SIGN is 1 for sleb, 0 for uleb. */
-static void
+void
emit_leb128_expr (expressionS *exp, int sign)
{
operatorT op = exp->X_op;
diff -rup binutils.orig/gas/read.h binutils-2.35/gas/read.h
--- binutils.orig/gas/read.h 2020-08-25 15:40:47.618220074 +0100
+++ binutils-2.35/gas/read.h 2020-08-25 15:41:44.776859141 +0100
@@ -132,6 +132,7 @@ extern void emit_expr_with_reloc (expres
TC_PARSE_CONS_RETURN_TYPE);
extern void emit_expr_fix (expressionS *, unsigned int, fragS *, char *,
TC_PARSE_CONS_RETURN_TYPE);
+extern void emit_leb128_expr (expressionS *, int);
extern void equals (char *, int);
extern void float_cons (int);
extern void ignore_rest_of_line (void);
diff -rup binutils.orig/gas/testsuite/gas/elf/elf.exp binutils-2.35/gas/testsuite/gas/elf/elf.exp
--- binutils.orig/gas/testsuite/gas/elf/elf.exp 2020-08-25 15:40:47.343221810 +0100
+++ binutils-2.35/gas/testsuite/gas/elf/elf.exp 2020-08-25 15:41:25.841978707 +0100
@@ -274,6 +274,8 @@ if { [is_elf_format] } then {
run_dump_test "dwarf2-18" $dump_opts
run_dump_test "dwarf2-19" $dump_opts
run_dump_test "dwarf-5-file0" $dump_opts
+ run_dump_test "dwarf-4-cu" $dump_opts
+ run_dump_test "dwarf-5-cu" $dump_opts
run_dump_test "pr25917"
run_dump_test "bss"
run_dump_test "bad-bss"
--- /dev/null 2020-08-25 08:24:40.895324651 +0100
+++ binutils-2.35/gas/testsuite/gas/elf/dwarf-4-cu.s 2020-08-25 15:41:25.841978707 +0100
@@ -0,0 +1,14 @@
+ .text
+ .file 1 "foo/bar.s"
+ .loc_mark_labels 1
+ .globl foobar
+ .type foobar, %function
+foobar:
+ .quad 0x1
+ .size foobar, .-foobar
+
+ .globl baz
+ .type baz, %function
+baz:
+ .quad 0x1
+ .size baz, .-baz
--- /dev/null 2020-08-25 08:24:40.895324651 +0100
+++ binutils-2.35/gas/testsuite/gas/elf/dwarf-4-cu.d 2020-08-25 15:41:25.841978707 +0100
@@ -0,0 +1,11 @@
+#as: --gdwarf-4
+#name: DWARF4 CU
+#readelf: -wi
+
+#...
+ Compilation Unit @ offset 0x0:
+ Length: 0x.*
+ Version: 4
+ Abbrev Offset: 0x0
+ Pointer Size: .
+#pass
--- /dev/null 2020-08-25 08:24:40.895324651 +0100
+++ binutils-2.35/gas/testsuite/gas/elf/dwarf-5-cu.d 2020-08-25 15:41:25.841978707 +0100
@@ -0,0 +1,11 @@
+#as: --gdwarf-5
+#name: DWARF5 CU
+#readelf: -wi
+
+#...
+ Compilation Unit @ offset 0x0:
+ Length: 0x.*
+ Version: 5
+ Abbrev Offset: 0x0
+ Pointer Size: .
+#pass
--- /dev/null 2020-08-25 08:24:40.895324651 +0100
+++ binutils-2.35/gas/testsuite/gas/elf/dwarf-5-cu.s 2020-08-25 15:41:25.841978707 +0100
@@ -0,0 +1,14 @@
+ .text
+ .file 1 "foo/bar.s"
+ .loc_mark_labels 1
+ .globl foobar
+ .type foobar, %function
+foobar:
+ .quad 0x1
+ .size foobar, .-foobar
+
+ .globl baz
+ .type baz, %function
+baz:
+ .quad 0x1
+ .size baz, .-baz

View File

@ -2,7 +2,7 @@
Summary: A GNU collection of binary utilities
Name: %{?cross}binutils%{?_with_debug:-debug}
Version: 2.35
Release: 11%{?dist}
Release: 12%{?dist}
License: GPLv3+
URL: https://sourceware.org/binutils
@ -241,6 +241,10 @@ Patch26: binutils-elf-add-objects.patch
# Lifetime: Fixed in 2.36
Patch27: binutils-ppc-rename-xvcvbf16sp-to-xvcvbf16spn.patch
# Purpose: Fixes for handling DWARF-5 debug information.
# Lifetime: Fixed in 2.36
Patch28: binutils-dwarf-5-fixes.patch
#----------------------------------------------------------------------------
Provides: bundled(libiberty)
@ -814,6 +818,9 @@ exit 0
#----------------------------------------------------------------------------
%changelog
* Tue Aug 25 2020 Nick Clifton <nickc@redhat.com> - 2.35-12
- Import fixes from GNU binutils mainline for handling DWARF-5 debug information.
* Mon Aug 24 2020 Nick Clifton <nickc@redhat.com> - 2.35-11
- Rename the PPC xvcvbf16sp instruction to xvcvbf16spn.