diff options
author | Daniel Jacobowitz <drow@false.org> | 2001-11-15 01:34:12 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2001-11-15 01:34:12 +0000 |
commit | 73d074b4e2c7e9a3954d0b08f048ebccd6c3e671 (patch) | |
tree | 8f33443a6ab464d2a979bf59dd24a98c71a9ba9b /bfd | |
parent | 86651999acf60eb76a233cc1445fe978885f2006 (diff) | |
download | gdb-73d074b4e2c7e9a3954d0b08f048ebccd6c3e671.zip gdb-73d074b4e2c7e9a3954d0b08f048ebccd6c3e671.tar.gz gdb-73d074b4e2c7e9a3954d0b08f048ebccd6c3e671.tar.bz2 |
2001-11-11 Daniel Jacobowitz <drow@mvista.com>
* bfd-in.h (bfd_elf32_discard_info): Add prototype.
(bfd_elf64_discard_info): Likewise.
* bfd-in2.h: Regenerate.
* elf-bfd.h (struct elf_reloc_cookie): New.
(struct elf_backend_data): Add elf_backend_discard_info,
elf_backend_ignore_discarded_relocs, and elf_backend_write_section.
(_bfd_elf32_reloc_symbol_deleted_p): Add prototype.
(_bfd_elf64_reloc_symbol_deleted_p): Likewise.
* elf32-mips.c (_bfd_elf32_mips_discard_info): New.
(_bfd_elf32_mips_ignore_discarded_relocs): New.
(_bfd_elf32_mips_write_section): New.
(elf_backend_discard_info): Define.
(elf_backend_ignore_discarded_relocs): Define.
(elf_backend_write_section): Define.
* elfcode.h (elf_bfd_discard_info): Define.
(elf_reloc_symbol_deleted_p): Define.
* elflink.h (elf_link_input_bfd): Check
elf_section_ignore_discarded_relocs. Call
bed->elf_backend_write_section if available.
(elf_reloc_symbol_deleted_p): New.
(elf_bfd_discard_info): New.
(elf_section_ignore_discarded_relocs): New.
* elfxx-target.h (elf_backend_discard_info): Define.
(elf_backend_ignore_discarded_relocs): Define.
(elf_backend_write_section): Define.
(elfNN_bed): Add elf_backend_discard_info,
elf_backend_ignore_discarded_relocs, and
elf_backend_write_section.
* libbfd-in.h (_bfd_discard_section_stabs): Add prototype.
* libbfd.h: Regenerate.
* stabs.c (_bfd_discard_section_stabs): New.
2001-11-11 Daniel Jacobowitz <drow@mvista.com>
* emultempl/elf32.em (gld${EMULATION_NAME}_finish): New.
(struct ld_emulation_xfer_struct): Use it.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 34 | ||||
-rw-r--r-- | bfd/bfd-in.h | 4 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 4 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 31 | ||||
-rw-r--r-- | bfd/elf32-mips.c | 119 | ||||
-rw-r--r-- | bfd/elfcode.h | 2 | ||||
-rw-r--r-- | bfd/elflink.h | 209 | ||||
-rw-r--r-- | bfd/elfxx-target.h | 12 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 5 | ||||
-rw-r--r-- | bfd/libbfd.h | 5 | ||||
-rw-r--r-- | bfd/stabs.c | 170 |
11 files changed, 593 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afd3dec..3c429ef 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,37 @@ +2001-11-14 Daniel Jacobowitz <drow@mvista.com> + + * bfd-in.h (bfd_elf32_discard_info): Add prototype. + (bfd_elf64_discard_info): Likewise. + * bfd-in2.h: Regenerate. + * elf-bfd.h (struct elf_reloc_cookie): New. + (struct elf_backend_data): Add elf_backend_discard_info, + elf_backend_ignore_discarded_relocs, and elf_backend_write_section. + (_bfd_elf32_reloc_symbol_deleted_p): Add prototype. + (_bfd_elf64_reloc_symbol_deleted_p): Likewise. + * elf32-mips.c (_bfd_elf32_mips_discard_info): New. + (_bfd_elf32_mips_ignore_discarded_relocs): New. + (_bfd_elf32_mips_write_section): New. + (elf_backend_discard_info): Define. + (elf_backend_ignore_discarded_relocs): Define. + (elf_backend_write_section): Define. + * elfcode.h (elf_bfd_discard_info): Define. + (elf_reloc_symbol_deleted_p): Define. + * elflink.h (elf_link_input_bfd): Check + elf_section_ignore_discarded_relocs. Call + bed->elf_backend_write_section if available. + (elf_reloc_symbol_deleted_p): New. + (elf_bfd_discard_info): New. + (elf_section_ignore_discarded_relocs): New. + * elfxx-target.h (elf_backend_discard_info): Define. + (elf_backend_ignore_discarded_relocs): Define. + (elf_backend_write_section): Define. + (elfNN_bed): Add elf_backend_discard_info, + elf_backend_ignore_discarded_relocs, and + elf_backend_write_section. + * libbfd-in.h (_bfd_discard_section_stabs): Add prototype. + * libbfd.h: Regenerate. + * stabs.c (_bfd_discard_section_stabs): New. + 2001-11-14 Martin Schwidefsky <schwidefsky@de.ibm.com> * elf32-s390.c (elf_s390_relocate_section): Use the "unresolved_reloc" diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 611f595..9eadbce 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -635,6 +635,10 @@ extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *)); extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *)); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf32_discard_info + PARAMS ((struct bfd_link_info *)); +extern boolean bfd_elf64_discard_info + PARAMS ((struct bfd_link_info *)); /* Return an upper bound on the number of bytes required to store a copy of ABFD's program header table entries. Return -1 if an error diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 1f3704b..b99a3d4 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -641,6 +641,10 @@ extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *)); extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *)); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf32_discard_info + PARAMS ((struct bfd_link_info *)); +extern boolean bfd_elf64_discard_info + PARAMS ((struct bfd_link_info *)); /* Return an upper bound on the number of bytes required to store a copy of ABFD's program header table entries. Return -1 if an error diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index cb79eea..b621327 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -381,6 +381,17 @@ enum elf_reloc_type_class { reloc_class_copy }; +struct elf_reloc_cookie +{ + Elf_Internal_Rela *rels, *rel, *relend; + void *locsyms; + bfd *abfd; + size_t locsymcount; + size_t extsymoff; + struct elf_link_hash_entry **sym_hashes; + boolean bad_symtab; +}; + struct elf_backend_data { /* The architecture for this backend. */ @@ -703,6 +714,21 @@ struct elf_backend_data enum elf_reloc_type_class (*elf_backend_reloc_type_class) PARAMS ((const Elf_Internal_Rela *)); + /* This function, if defined, removes information about discarded functions + from other sections which mention them. */ + boolean (*elf_backend_discard_info) + PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *)); + + /* This function, if defined, signals that the function above has removed + the discarded relocations for this section. */ + boolean (*elf_backend_ignore_discarded_relocs) + PARAMS ((asection *)); + + /* This function, if defined, may write out the given section. + Returns true if it did so and false if the caller should. */ + boolean (*elf_backend_write_section) + PARAMS ((bfd *, asection *, bfd_byte *)); + /* The swapping table to use when dealing with ECOFF information. Used for the MIPS ELF .mdebug section. */ const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; @@ -1437,6 +1463,11 @@ extern boolean _bfd_elf64_gc_record_vtinherit extern boolean _bfd_elf64_gc_record_vtentry PARAMS ((bfd *, asection *, struct elf_link_hash_entry *, bfd_vma)); +extern boolean _bfd_elf32_reloc_symbol_deleted_p + PARAMS ((bfd_vma, PTR)); +extern boolean _bfd_elf64_reloc_symbol_deleted_p + PARAMS ((bfd_vma, PTR)); + /* MIPS ELF specific routines. */ extern boolean _bfd_mips_elf_object_p diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index a530ee9..aa31108 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -219,6 +219,12 @@ static boolean _bfd_elf32_mips_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *)); static boolean _bfd_elf32_mips_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *)); +static boolean _bfd_elf32_mips_discard_info + PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *)); +static boolean _bfd_elf32_mips_ignore_discarded_relocs + PARAMS ((asection *)); +static boolean _bfd_elf32_mips_write_section + PARAMS ((bfd *, asection *, bfd_byte *)); extern const bfd_target bfd_elf32_tradbigmips_vec; extern const bfd_target bfd_elf32_tradlittlemips_vec; @@ -9226,6 +9232,114 @@ _bfd_elf32_mips_grok_psinfo (abfd, note) return true; } +#define PDR_SIZE 32 + +static boolean +_bfd_elf32_mips_discard_info (abfd, cookie, info) + bfd *abfd; + struct elf_reloc_cookie *cookie; + struct bfd_link_info *info; +{ + asection *o; + struct elf_backend_data *bed = get_elf_backend_data (abfd); + boolean ret = false; + unsigned char *tdata; + size_t i, skip; + + o = bfd_get_section_by_name (abfd, ".pdr"); + if (! o) + return false; + if (o->_raw_size == 0) + return false; + if (o->_raw_size % PDR_SIZE != 0) + return false; + if (o->output_section != NULL + && bfd_is_abs_section (o->output_section)) + return false; + + tdata = bfd_zmalloc (o->_raw_size / PDR_SIZE); + if (! tdata) + return false; + + cookie->rels = _bfd_elf32_link_read_relocs (abfd, o, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory); + if (!cookie->rels) + { + free (tdata); + return false; + } + + cookie->rel = cookie->rels; + cookie->relend = + cookie->rels + o->reloc_count * bed->s->int_rels_per_ext_rel; + + for (i = 0, skip = 0; i < o->_raw_size; i ++) + { + if (_bfd_elf32_reloc_symbol_deleted_p (i * PDR_SIZE, cookie)) + { + tdata[i] = 1; + skip ++; + } + } + + if (skip != 0) + { + elf_section_data (o)->tdata = tdata; + o->_cooked_size = o->_raw_size - skip * PDR_SIZE; + ret = true; + } + else + free (tdata); + + if (! info->keep_memory) + free (cookie->rels); + + return ret; +} + +static boolean +_bfd_elf32_mips_ignore_discarded_relocs (sec) + asection *sec; +{ + if (strcmp (sec->name, ".pdr") == 0) + return true; + return false; +} + +static boolean +_bfd_elf32_mips_write_section (output_bfd, sec, contents) + bfd *output_bfd; + asection *sec; + bfd_byte *contents; +{ + bfd_byte *to, *from, *end; + int i; + + if (strcmp (sec->name, ".pdr") != 0) + return false; + + if (elf_section_data (sec)->tdata == NULL) + return false; + + to = contents; + end = contents + sec->_raw_size; + for (from = contents, i = 0; + from < end; + from += PDR_SIZE, i++) + { + if (((unsigned char *)elf_section_data (sec)->tdata)[i] == 1) + continue; + if (to != from) + memcpy (to, from, PDR_SIZE); + to += PDR_SIZE; + } + bfd_set_section_contents (output_bfd, sec->output_section, contents, + (file_ptr) sec->output_offset, + sec->_cooked_size); + return true; +} + /* This is almost identical to bfd_generic_get_... except that some MIPS relocations need to be handled specially. Sigh. */ @@ -9516,6 +9630,11 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define elf_backend_grok_prstatus _bfd_elf32_mips_grok_prstatus #define elf_backend_grok_psinfo _bfd_elf32_mips_grok_psinfo +#define elf_backend_discard_info _bfd_elf32_mips_discard_info +#define elf_backend_ignore_discarded_relocs \ + _bfd_elf32_mips_ignore_discarded_relocs +#define elf_backend_write_section _bfd_elf32_mips_write_section + #define bfd_elf32_bfd_is_local_label_name \ mips_elf_is_local_label_name #define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line diff --git a/bfd/elfcode.h b/bfd/elfcode.h index b5da87f..becd8bf 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -123,6 +123,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table) #define elf_link_create_dynamic_sections \ NAME(bfd_elf,link_create_dynamic_sections) +#define elf_bfd_discard_info NAME(bfd_elf,discard_info) +#define elf_reloc_symbol_deleted_p NAME(_bfd_elf,reloc_symbol_deleted_p) #define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol #define elf_bfd_final_link NAME(bfd_elf,bfd_final_link) #define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section) diff --git a/bfd/elflink.h b/bfd/elflink.h index a4fb88d..4455f01 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -75,6 +75,8 @@ static int elf_link_sort_cmp2 PARAMS ((const void *, const void *)); static size_t elf_link_sort_relocs PARAMS ((bfd *, struct bfd_link_info *, asection **)); +static boolean elf_section_ignore_discarded_relocs + PARAMS ((asection *)); /* Given an ELF BFD, add symbols to the global hash table as appropriate. */ @@ -6287,7 +6289,8 @@ elf_link_input_bfd (finfo, input_bfd) .eh_frame to describe a routine in the linkonce section, and it turns out to be hard to remove the .eh_frame entry too. FIXME. */ - if (!finfo->info->relocateable) + if (!finfo->info->relocateable + && !elf_section_ignore_discarded_relocs (o)) { Elf_Internal_Rela *rel, *relend; @@ -6591,7 +6594,12 @@ elf_link_input_bfd (finfo, input_bfd) } /* Write out the modified section contents. */ - if (elf_section_data (o)->stab_info) + if (bed->elf_backend_write_section + && bed->elf_backend_write_section (output_bfd, o, contents)) + { + /* Section written out. */ + } + else if (elf_section_data (o)->stab_info) { if (! (_bfd_write_section_stabs (output_bfd, &elf_hash_table (finfo->info)->stab_info, @@ -7756,3 +7764,200 @@ elf_collect_hash_codes (h, data) return true; } + +boolean +elf_reloc_symbol_deleted_p (offset, cookie) + bfd_vma offset; + PTR cookie; +{ + struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *)cookie; + + if (rcookie->bad_symtab) + rcookie->rel = rcookie->rels; + + for (; rcookie->rel < rcookie->relend; rcookie->rel++) + { + unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info); + Elf_Internal_Sym isym; + + if (! rcookie->bad_symtab) + if (rcookie->rel->r_offset > offset) + return false; + if (rcookie->rel->r_offset != offset) + continue; + + if (rcookie->locsyms) + elf_swap_symbol_in (rcookie->abfd, + ((Elf_External_Sym *)rcookie->locsyms) + r_symndx, + &isym); + + if (r_symndx >= rcookie->locsymcount + || (rcookie->locsyms + && ELF_ST_BIND (isym.st_info) != STB_LOCAL)) + { + struct elf_link_hash_entry *h; + + h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff]; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && ! bfd_is_abs_section (h->root.u.def.section) + && bfd_is_abs_section (h->root.u.def.section + ->output_section)) + return true; + else + return false; + } + else if (rcookie->locsyms) + { + /* It's not a relocation against a global symbol, + but it could be a relocation against a section + symbol for a discarded section. */ + asection *isec; + + /* Need to: get the symbol; get the section. */ + if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) + { + isec = section_from_elf_index (rcookie->abfd, isym.st_shndx); + if (isec != NULL + && ELF_ST_TYPE (isym.st_info) == STT_SECTION + && ! bfd_is_abs_section (isec) + && bfd_is_abs_section (isec->output_section)) + return true; + } + } + return false; + } + return false; +} + +/* Discard unneeded references to discarded sections. + Returns true if any section's size was changed. */ +/* This function assumes that the relocations are in sorted order, + which is true for all known assemblers. */ + +boolean +elf_bfd_discard_info (info) + struct bfd_link_info *info; +{ + struct elf_reloc_cookie cookie; + asection *o; + Elf_Internal_Shdr *symtab_hdr; + Elf_External_Sym *freesyms; + struct elf_backend_data *bed; + bfd *abfd; + boolean ret = false; + + if (info->relocateable + || info->traditional_format + || info->hash->creator->flavour != bfd_target_elf_flavour + || ! is_elf_hash_table (info) + || info->strip == strip_all + || info->strip == strip_debugger) + return false; + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) + { + bed = get_elf_backend_data (abfd); + + if ((abfd->flags & DYNAMIC) != 0) + continue; + + o = bfd_get_section_by_name (abfd, ".stab"); + if (! o && ! bed->elf_backend_discard_info) + continue; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + cookie.abfd = abfd; + cookie.sym_hashes = elf_sym_hashes (abfd); + cookie.bad_symtab = elf_bad_symtab (abfd); + if (cookie.bad_symtab) + { + cookie.locsymcount = + symtab_hdr->sh_size / sizeof (Elf_External_Sym); + cookie.extsymoff = 0; + } + else + { + cookie.locsymcount = symtab_hdr->sh_info; + cookie.extsymoff = symtab_hdr->sh_info; + } + + freesyms = NULL; + if (symtab_hdr->contents) + cookie.locsyms = (void *) symtab_hdr->contents; + else if (cookie.locsymcount == 0) + cookie.locsyms = NULL; + else + { + bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym); + cookie.locsyms = bfd_malloc (amt); + if (cookie.locsyms == NULL + || bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 + || bfd_bread (cookie.locsyms, amt, abfd) != amt) + { + /* Something is very wrong - but we can still do our job for + global symbols, so don't give up. */ + if (cookie.locsyms) + free (cookie.locsyms); + cookie.locsyms = NULL; + } + else + { + freesyms = cookie.locsyms; + } + } + + if (o) + { + cookie.rels = (NAME(_bfd_elf,link_read_relocs) + (abfd, o, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory)); + if (cookie.rels) + { + cookie.rel = cookie.rels; + cookie.relend = + cookie.rels + o->reloc_count * bed->s->int_rels_per_ext_rel; + if (_bfd_discard_section_stabs (abfd, o, + elf_section_data (o)->stab_info, + elf_reloc_symbol_deleted_p, + &cookie)) + ret = true; + if (! info->keep_memory) + free (cookie.rels); + } + } + + if (bed->elf_backend_discard_info) + { + if (bed->elf_backend_discard_info (abfd, &cookie, info)) + ret = true; + } + + if (freesyms) + free (freesyms); + } + return ret; +} + +static boolean +elf_section_ignore_discarded_relocs (sec) + asection *sec; +{ + if (strcmp (sec->name, ".stab") == 0) + return true; + else if ((get_elf_backend_data (sec->owner) + ->elf_backend_ignore_discarded_relocs != NULL) + && (get_elf_backend_data (sec->owner) + ->elf_backend_ignore_discarded_relocs (sec))) + return true; + else + return false; +} + + diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index abbbee8..900926d 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -358,6 +358,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef elf_backend_reloc_type_class #define elf_backend_reloc_type_class _bfd_elf_reloc_type_class #endif +#ifndef elf_backend_discard_info +#define elf_backend_discard_info NULL +#endif +#ifndef elf_backend_ignore_discarded_relocs +#define elf_backend_ignore_discarded_relocs NULL +#endif +#ifndef elf_backend_write_section +#define elf_backend_write_section NULL +#endif /* Previously, backends could only use SHT_REL or SHT_RELA relocation sections, but not both. They defined USE_REL to indicate SHT_REL @@ -446,6 +455,9 @@ static const struct elf_backend_data elfNN_bed = elf_backend_sprintf_vma, elf_backend_fprintf_vma, elf_backend_reloc_type_class, + elf_backend_discard_info, + elf_backend_ignore_discarded_relocs, + elf_backend_write_section, elf_backend_ecoff_debug_swap, ELF_MACHINE_ALT1, ELF_MACHINE_ALT2, diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 23b7ad9..c739b4e 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -446,6 +446,11 @@ extern bfd_reloc_status_type _bfd_relocate_contents extern boolean _bfd_link_section_stabs PARAMS ((bfd *, PTR *, asection *, asection *, PTR *)); +/* Eliminate stabs for discarded functions and symbols. */ +extern boolean _bfd_discard_section_stabs + PARAMS ((bfd *, asection *, PTR, + boolean (*) (bfd_vma, PTR), PTR)); + /* Write out the .stab section when linking stabs in sections. */ extern boolean _bfd_write_section_stabs diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 408cc10..7c3bad7 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -451,6 +451,11 @@ extern bfd_reloc_status_type _bfd_relocate_contents extern boolean _bfd_link_section_stabs PARAMS ((bfd *, PTR *, asection *, asection *, PTR *)); +/* Eliminate stabs for discarded functions and symbols. */ +extern boolean _bfd_discard_section_stabs + PARAMS ((bfd *, asection *, PTR, + boolean (*) (bfd_vma, PTR), PTR)); + /* Write out the .stab section when linking stabs in sections. */ extern boolean _bfd_write_section_stabs diff --git a/bfd/stabs.c b/bfd/stabs.c index f54d658..635a702 100644 --- a/bfd/stabs.c +++ b/bfd/stabs.c @@ -502,6 +502,176 @@ _bfd_link_section_stabs (abfd, psinfo, stabsec, stabstrsec, psecinfo) return false; } + +/* This function is called for each input file before the stab + section is relocated. It discards stab entries for discarded + functions and variables. The function returns true iff + any entries have been deleted. +*/ + +boolean +_bfd_discard_section_stabs (abfd, stabsec, psecinfo, + reloc_symbol_deleted_p, cookie) + bfd *abfd; + asection *stabsec; + PTR psecinfo; + boolean (*reloc_symbol_deleted_p) (bfd_vma, PTR); + PTR cookie; +{ + bfd_size_type count, amt; + struct stab_section_info *secinfo; + bfd_byte *stabbuf = NULL; + bfd_byte *sym, *symend; + bfd_size_type skip; + bfd_size_type *pstridx; + int deleting; + + if (stabsec->_raw_size == 0) + { + /* This file does not contain stabs debugging information. */ + return false; + } + + if (stabsec->_raw_size % STABSIZE != 0) + { + /* Something is wrong with the format of these stab symbols. + Don't try to optimize them. */ + return false; + } + + if ((stabsec->output_section != NULL + && bfd_is_abs_section (stabsec->output_section))) + { + /* At least one of the sections is being discarded from the + link, so we should just ignore them. */ + return false; + } + + /* We should have initialized our data in _bfd_link_stab_sections. + If there was some bizarre error reading the string sections, though, + we might not have. Bail rather than asserting. */ + if (psecinfo == NULL) + return false; + + count = stabsec->_raw_size / STABSIZE; + secinfo = (struct stab_section_info *) psecinfo; + + /* Read the stabs information from abfd. */ + + stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size); + if (stabbuf == NULL) + goto error_return; + + if (! bfd_get_section_contents (abfd, stabsec, stabbuf, (bfd_vma) 0, + stabsec->_raw_size)) + goto error_return; + + /* Look through the stabs symbols and discard any information for + discarded functions. */ + + skip = 0; + deleting = -1; + + symend = stabbuf + stabsec->_raw_size; + for (sym = stabbuf, pstridx = secinfo->stridxs; + sym < symend; + sym += STABSIZE, ++pstridx) + { + int type; + + if (*pstridx == (bfd_size_type) -1) + { + /* This stab was deleted in a previous pass. */ + continue; + } + + type = sym[TYPEOFF]; + + if (type == N_FUN) + { + int strx = bfd_get_32 (abfd, sym + STRDXOFF); + + if (strx == 0) + { + if (deleting) + { + skip++; + *pstridx = -1; + } + deleting = -1; + continue; + } + deleting = 0; + if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) + deleting = 1; + } + + if (deleting == 1) + { + *pstridx = -1; + skip++; + } + else if (deleting == -1) + { + /* Outside of a function. Check for deleted variables. */ + if (type == N_STSYM || type == N_LCSYM) + if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie)) + { + *pstridx = -1; + skip ++; + } + /* We should also check for N_GSYM entries which reference a + deleted global, but those are less harmful to debuggers + and would require parsing the stab strings. */ + } + } + + free (stabbuf); + stabbuf = NULL; + + /* Shrink the stabsec as needed. */ + stabsec->_cooked_size -= skip * STABSIZE; + if (stabsec->_cooked_size == 0) + stabsec->flags |= SEC_EXCLUDE; + + /* Recalculate the `cumulative_skips' array now that stabs have been + deleted for this section. */ + + if (skip != 0) + { + bfd_size_type i, offset; + bfd_size_type *pskips; + + if (secinfo->cumulative_skips == NULL) + { + amt = count * sizeof (bfd_size_type); + secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt); + if (secinfo->cumulative_skips == NULL) + goto error_return; + } + + pskips = secinfo->cumulative_skips; + pstridx = secinfo->stridxs; + offset = 0; + + for (i = 0; i < count; i++, pskips++, pstridx++) + { + *pskips = offset; + if (*pstridx == (bfd_size_type) -1) + offset += STABSIZE; + } + + BFD_ASSERT (offset != 0); + } + + return (skip > 0); + + error_return: + if (stabbuf != NULL) + free (stabbuf); + return false; +} + /* Write out the stab section. This is called with the relocated contents. */ |