aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2013-04-29 13:38:59 +0000
committerNick Clifton <nickc@redhat.com>2013-04-29 13:38:59 +0000
commitb40bf0a25574c43114b906ba151b7895b2348794 (patch)
tree7964a382ed4b6f081640dd260954b27a7c17625e /bfd
parent09526ec1c28f4f31b38c271c259b7dea0993d5b0 (diff)
downloadgdb-b40bf0a25574c43114b906ba151b7895b2348794.zip
gdb-b40bf0a25574c43114b906ba151b7895b2348794.tar.gz
gdb-b40bf0a25574c43114b906ba151b7895b2348794.tar.bz2
* elflink.c (_bfd_elf_gc_mark_extra_sections): Remove mark from
fragmented .debug_line sections associated with unmarked code sections. * dwarf.c (read_debug_line_header): New function. Reads in a header in a .debug_line section. (display_debug_lines_raw): Use new function. Handle fragmentary .debug_line sections. (display_debug_lines_decoded): Likewise. * readelf.c (process_section_headers): Handle fragmenatry .debug_line sections. (display_debug_section): Likewise. * as.c (Options): Add -gdwarf-sections. (parse_args): Likewise. * as.h (flag_dwarf_sections): Declare. * dwarf2dbg.c (emit_fixed_inc_line_addr): Skip section changes. (process_entries): When -gdwarf-sections is enabled generate fragmentary .debug_line sections. (out_debug_line): Set the section for the .debug_line section end symbol. * doc/as.texinfo: Document -gdwarf-sections. * NEWS: Mention -gdwarf-sections. * gas/elf/dwarf2-3.d: Fix expected readelf output. * scripttempl/DWARF.sc: Add support for .debug_line.* and .debug_line_end.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elflink.c54
2 files changed, 56 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6c5739a..06bdfe7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2013-04-29 Nick Clifton <nickc@redhat.com>
+
+ * elflink.c (_bfd_elf_gc_mark_extra_sections): Remove mark from
+ fragmented .debug_line sections associated with unmarked code
+ sections.
+
2013-04-29 Will Newton <will.newton@linaro.org>
* elf32-arm.c (elf32_arm_populate_plt_entry): Call
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 313d89e..84ac1f2 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11814,23 +11814,30 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
{
asection *isec;
bfd_boolean some_kept;
+ bfd_boolean debug_frag_seen;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
- /* Ensure all linker created sections are kept, and see whether
- any other section is already marked. */
- some_kept = FALSE;
+ /* Ensure all linker created sections are kept,
+ see if any other section is already marked,
+ and note if we have any fragmented debug sections. */
+ debug_frag_seen = some_kept = FALSE;
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
{
if ((isec->flags & SEC_LINKER_CREATED) != 0)
isec->gc_mark = 1;
else if (isec->gc_mark)
some_kept = TRUE;
+
+ if (debug_frag_seen == FALSE
+ && (isec->flags & SEC_DEBUGGING)
+ && CONST_STRNEQ (isec->name, ".debug_line."))
+ debug_frag_seen = TRUE;
}
/* If no section in this file will be kept, then we can
- toss out debug sections. */
+ toss out the debug and special sections. */
if (!some_kept)
continue;
@@ -11842,6 +11849,45 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
&& ((isec->flags & SEC_DEBUGGING) != 0
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
isec->gc_mark = 1;
+
+ if (! debug_frag_seen)
+ continue;
+
+ /* Look for CODE sections which are going to be discarded,
+ and find and discard any fragmented debug sections which
+ are associated with that code section. */
+ for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+ if ((isec->flags & SEC_CODE) != 0
+ && isec->gc_mark == 0)
+ {
+ unsigned int ilen;
+ asection *dsec;
+
+ ilen = strlen (isec->name);
+
+ /* Association is determined by the name of the debug section
+ containing the name of the code section as a suffix. For
+ example .debug_line.text.foo is a debug section associated
+ with .text.foo. */
+ for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+ {
+ unsigned int dlen;
+
+ if (dsec->gc_mark == 0
+ || (dsec->flags & SEC_DEBUGGING) == 0)
+ continue;
+
+ dlen = strlen (dsec->name);
+
+ if (dlen > ilen
+ && strncmp (dsec->name + (dlen - ilen),
+ isec->name, ilen) == 0)
+ {
+ dsec->gc_mark = 0;
+ break;
+ }
+ }
+ }
}
return TRUE;
}