diff options
Diffstat (limited to 'bfd/elf32-mips.c')
-rw-r--r-- | bfd/elf32-mips.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index a530ee97aa..aa3110870f 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 |