From 6a5bb8757e503d29dd2b0cc656a8747bca71362e Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Thu, 22 Feb 2007 17:03:59 +0000 Subject: [PATCH] 2007-02-22 Paul Brook bfd/ * elflink.c (gc_mark_hook_fn): Remove. (_bfd_elf_gc_mark): Rename gc_mark_hook_fn to elf_gc_mark_hook_fn. (bfd_elf_gc_sections): Ditto. Call gc_mark_extra_sections. * elf-bfd.h (elf_gc_mark_hook_fn): Define. (elf_backend_data): Add gc_mark_extra_sections. * elfxx-target.h (elf_backend_gc_mark_extra_sections): Provide default definition. (elfNN_bed): Add elf_backend_gc_mark_extra_sections. * elf32-arm.c (elf32_arm_gc_mark_extra_sections): New function. (elf_backend_gc_mark_extra_sections): Define. ld/testsuite/ * ld-arm/arm-elf.exp (armelftests): Add gc-unwind.h. * ld-arm/gc-unwind.s: New file. * ld-arm/gc-unwind.d: New file. --- bfd/ChangeLog | 13 ++++++++++ bfd/elf-bfd.h | 13 +++++++--- bfd/elf32-arm.c | 45 +++++++++++++++++++++++++++++++++ bfd/elflink.c | 14 +++++----- bfd/elfxx-target.h | 4 +++ ld/testsuite/ChangeLog | 6 +++++ ld/testsuite/ld-arm/arm-elf.exp | 3 +++ ld/testsuite/ld-arm/gc-unwind.d | 5 ++++ ld/testsuite/ld-arm/gc-unwind.s | 38 ++++++++++++++++++++++++++++ 9 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 ld/testsuite/ld-arm/gc-unwind.d create mode 100644 ld/testsuite/ld-arm/gc-unwind.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0bd67952294..0156a9c88ea 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2007-02-22 Paul Brook + + * elflink.c (gc_mark_hook_fn): Remove. + (_bfd_elf_gc_mark): Rename gc_mark_hook_fn to elf_gc_mark_hook_fn. + (bfd_elf_gc_sections): Ditto. Call gc_mark_extra_sections. + * elf-bfd.h (elf_gc_mark_hook_fn): Define. + (elf_backend_data): Add gc_mark_extra_sections. + * elfxx-target.h (elf_backend_gc_mark_extra_sections): Provide default + definition. + (elfNN_bed): Add elf_backend_gc_mark_extra_sections. + * elf32-arm.c (elf32_arm_gc_mark_extra_sections): New function. + (elf_backend_gc_mark_extra_sections): Define. + 2007-02-21 Nick Clifton * elf.c (_bfd_elf_map_sections_to_segments): If the diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index a0e6391a4f7..303b823a77c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -538,6 +538,10 @@ enum action_discarded PRETEND = 2 }; +typedef asection * (*elf_gc_mark_hook_fn) + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); + struct elf_backend_data { /* The architecture for this backend. */ @@ -843,9 +847,12 @@ struct elf_backend_data /* This function is called during section gc to discover the section a particular relocation refers to. */ - asection * (*gc_mark_hook) - (asection *sec, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *h, Elf_Internal_Sym *); + elf_gc_mark_hook_fn gc_mark_hook; + + /* This function, if defined, is called after the first gc marking pass + to allow the backend to mark additional sections. */ + bfd_boolean (*gc_mark_extra_sections) + (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook); /* This function, if defined, is called during the sweep phase of gc in order that a backend might update any data structures it might diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 87d617f7e45..78aa2a0aad8 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -8150,6 +8150,50 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, return TRUE; } +/* Unwinding tables are not referenced directly. This pass marks them as + required if the corresponding code section is marked. */ + +static bfd_boolean +elf32_arm_gc_mark_extra_sections(struct bfd_link_info *info, + elf_gc_mark_hook_fn gc_mark_hook) +{ + bfd *sub; + Elf_Internal_Shdr **elf_shdrp; + bfd_boolean again; + + /* Marking EH data may cause additional code sections to be marked, + requiring multiple passes. */ + again = TRUE; + while (again) + { + again = FALSE; + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + { + asection *o; + + if (bfd_get_flavour (sub) != bfd_target_elf_flavour) + continue; + + elf_shdrp = elf_elfsections (sub); + for (o = sub->sections; o != NULL; o = o->next) + { + Elf_Internal_Shdr *hdr; + hdr = &elf_section_data (o)->this_hdr; + if (hdr->sh_type == SHT_ARM_EXIDX && hdr->sh_link + && !o->gc_mark + && elf_shdrp[hdr->sh_link]->bfd_section->gc_mark) + { + again = TRUE; + if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) + return FALSE; + } + } + } + } + + return TRUE; +} + /* Treat mapping symbols as special target symbols. */ static bfd_boolean @@ -10532,6 +10576,7 @@ const struct elf_size_info elf32_arm_size_info = { #define elf_backend_get_symbol_type elf32_arm_get_symbol_type #define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook +#define elf_backend_gc_mark_extra_sections elf32_arm_gc_mark_extra_sections #define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook #define elf_backend_check_relocs elf32_arm_check_relocs #define elf_backend_relocate_section elf32_arm_relocate_section diff --git a/bfd/elflink.c b/bfd/elflink.c index 00dd2aafe7c..f7de165e2f6 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10088,10 +10088,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Garbage collect unused sections. */ -typedef asection * (*gc_mark_hook_fn) - (asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *); - /* Default gc_mark_hook. */ asection * @@ -10129,7 +10125,7 @@ _bfd_elf_gc_mark_hook (asection *sec, bfd_boolean _bfd_elf_gc_mark (struct bfd_link_info *info, asection *sec, - gc_mark_hook_fn gc_mark_hook) + elf_gc_mark_hook_fn gc_mark_hook) { bfd_boolean ret; bfd_boolean is_eh; @@ -10498,9 +10494,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) { bfd_boolean ok = TRUE; bfd *sub; - asection * (*gc_mark_hook) - (asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *h, Elf_Internal_Sym *); + elf_gc_mark_hook_fn gc_mark_hook; const struct elf_backend_data *bed = get_elf_backend_data (abfd); if (!bed->can_gc_sections @@ -10547,6 +10541,10 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) return FALSE; } + /* Allow the backend to mark additional target specific sections. */ + if (bed->gc_mark_extra_sections) + bed->gc_mark_extra_sections(info, gc_mark_hook); + /* ... again for sections marked from eh_frame. */ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) { diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index c7be5771c0b..661584115b7 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -136,6 +136,9 @@ #ifndef elf_backend_gc_mark_hook #define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook #endif +#ifndef elf_backend_gc_mark_extra_sections +#define elf_backend_gc_mark_extra_sections NULL +#endif #ifndef elf_backend_gc_sweep_hook #define elf_backend_gc_sweep_hook NULL #endif @@ -627,6 +630,7 @@ static struct elf_backend_data elfNN_bed = elf_backend_modify_program_headers, elf_backend_gc_mark_dynamic_ref, elf_backend_gc_mark_hook, + elf_backend_gc_mark_extra_sections, elf_backend_gc_sweep_hook, elf_backend_post_process_headers, elf_backend_print_symbol_all, diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 2f75a9e54f5..17be55150e3 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-02-22 Paul Brook + + * ld-arm/arm-elf.exp (armelftests): Add gc-unwind.h. + * ld-arm/gc-unwind.s: New file. + * ld-arm/gc-unwind.d: New file. + 2007-02-14 H.J. Lu PR ld/3953 diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 71d817a71de..9b7b3696587 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -156,6 +156,9 @@ set armelftests { "-EL --vfp11-denorm-fix=scalar" "-EL" {vfp11-fix-none.s} {{objdump -dr vfp11-fix-none.d}} "vfp11-fix-none"} + {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s} + {{objdump -sj.data gc-unwind.d}} + "gc-unwind"} } diff --git a/ld/testsuite/ld-arm/gc-unwind.d b/ld/testsuite/ld-arm/gc-unwind.d new file mode 100644 index 00000000000..fbb79115b8f --- /dev/null +++ b/ld/testsuite/ld-arm/gc-unwind.d @@ -0,0 +1,5 @@ + +.*: file format.* + +Contents of section .data: + [^ ]* 22222222 .* diff --git a/ld/testsuite/ld-arm/gc-unwind.s b/ld/testsuite/ld-arm/gc-unwind.s new file mode 100644 index 00000000000..c5326c28651 --- /dev/null +++ b/ld/testsuite/ld-arm/gc-unwind.s @@ -0,0 +1,38 @@ +@ Test -gc-sections and unwinding tables. .data.eh should be pulled in +@ via the EH tables, .data.foo should not. +.text +.global _start +.fnstart +_start: +bx lr +.personality my_pr +.handlerdata +.word 0 +.fnend + +.section .data.foo +my_foo: +.word 0x11111111 + +.section .text.foo +.fnstart +foo: +bx lr +.personality my_pr +.handlerdata +.word my_foo +.fnend + +.section .data.eh +my_eh: +.word 0x22222222 + +.section .text.eh +.fnstart +my_pr: +bx lr +.personality my_pr +.handlerdata +.word my_eh +.fnend + -- 2.30.2