diff options
Diffstat (limited to 'bfd/elf32-m68k.c')
-rw-r--r-- | bfd/elf32-m68k.c | 101 |
1 files changed, 68 insertions, 33 deletions
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index a40f09e..0875d88 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -277,6 +277,9 @@ struct elf_m68k_link_hash_entry struct elf_m68k_link_hash_table { struct elf_link_hash_table root; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; }; /* Declare this now that the above structures are defined. */ @@ -349,6 +352,8 @@ elf_m68k_link_hash_table_create (abfd) return NULL; } + ret->sym_sec.abfd = NULL; + return &ret->root.root; } @@ -516,7 +521,8 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) if (h->got.refcount == 0) { /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { if (!bfd_elf32_link_record_dynamic_symbol (info, h)) return FALSE; @@ -593,7 +599,8 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) } /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { if (!bfd_elf32_link_record_dynamic_symbol (info, h)) return FALSE; @@ -620,6 +627,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (!info->symbolic + || h->root.type == bfd_link_hash_defweak || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { @@ -687,24 +695,41 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) sreloc->_raw_size += sizeof (Elf32_External_Rela); - /* If we are linking with -Bsymbolic, we count the number of - PC relative relocations we have entered for this symbol, - so that we can discard them again if the symbol is later - defined by a regular object. Note that this function is - only called if we are using an m68kelf linker hash table, - which means that h is really a pointer to an + /* We count the number of PC relative relocations we have + entered for this symbol, so that we can discard them + again if, in the -Bsymbolic case, the symbol is later + defined by a regular object, or, in the normal shared + case, the symbol is forced to be local. Note that this + function is only called if we are using an m68kelf linker + hash table, which means that h is really a pointer to an elf_m68k_link_hash_entry. */ - if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8 - || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 - || ELF32_R_TYPE (rel->r_info) == R_68K_PC32) - && info->symbolic) + if (ELF32_R_TYPE (rel->r_info) == R_68K_PC8 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC32) { - struct elf_m68k_link_hash_entry *eh; struct elf_m68k_pcrel_relocs_copied *p; + struct elf_m68k_pcrel_relocs_copied **head; - eh = (struct elf_m68k_link_hash_entry *) h; + if (h != NULL) + { + struct elf_m68k_link_hash_entry *eh + = (struct elf_m68k_link_hash_entry *) h; + head = &eh->pcrel_relocs_copied; + } + else + { + asection *s; + s = (bfd_section_from_r_symndx + (abfd, &elf_m68k_hash_table (info)->sym_sec, + sec, r_symndx)); + if (s == NULL) + return FALSE; + + head = ((struct elf_m68k_pcrel_relocs_copied **) + &elf_section_data (s)->local_dynrel); + } - for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) + for (p = *head; p != NULL; p = p->next) if (p->section == sreloc) break; @@ -714,8 +739,8 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); if (p == NULL) return FALSE; - p->next = eh->pcrel_relocs_copied; - eh->pcrel_relocs_copied = p; + p->next = *head; + *head = p; p->section = sreloc; p->count = 0; } @@ -950,7 +975,8 @@ elf_m68k_adjust_dynamic_symbol (info, h) } /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return FALSE; @@ -1121,14 +1147,16 @@ elf_m68k_size_dynamic_sections (output_bfd, info) s->_raw_size = 0; } - /* If this is a -Bsymbolic shared link, then we need to discard all PC - relative relocs against symbols defined in a regular object. We - allocated space for them in the check_relocs routine, but we will not - fill them in in the relocate_section routine. */ - if (info->shared && info->symbolic) + /* If this is a -Bsymbolic shared link, then we need to discard all + PC relative relocs against symbols defined in a regular object. + For the normal shared case we discard the PC relative relocs + against symbols that have become local due to visibility changes. + We allocated space for them in the check_relocs routine, but we + will not fill them in in the relocate_section routine. */ + if (info->shared) elf_m68k_link_hash_traverse (elf_m68k_hash_table (info), elf_m68k_discard_copies, - (PTR) NULL); + (PTR) info); /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate @@ -1255,23 +1283,28 @@ elf_m68k_size_dynamic_sections (output_bfd, info) } /* This function is called via elf_m68k_link_hash_traverse if we are - creating a shared object with -Bsymbolic. It discards the space - allocated to copy PC relative relocs against symbols which are defined - in regular objects. We allocated space for them in the check_relocs - routine, but we won't fill them in in the relocate_section routine. */ + creating a shared object. In the -Bsymbolic case it discards the + space allocated to copy PC relative relocs against symbols which + are defined in regular objects. For the normal shared case, if + discards space for pc-relative relocs that have become local due to + symbol visibility changes. We allocated space for them in the + check_relocs routine, but we won't fill them in in the + relocate_section routine. */ static bfd_boolean -elf_m68k_discard_copies (h, ignore) +elf_m68k_discard_copies (h, inf) struct elf_m68k_link_hash_entry *h; - PTR ignore ATTRIBUTE_UNUSED; + PTR inf; { + struct bfd_link_info *info = (struct bfd_link_info *) inf; struct elf_m68k_pcrel_relocs_copied *s; if (h->root.root.type == bfd_link_hash_warning) h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link; - /* We only discard relocs for symbols defined in a regular object. */ - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 + || (!info->symbolic + && (h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)) return TRUE; for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) @@ -1591,7 +1624,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, case R_68K_PC8: case R_68K_PC16: case R_68K_PC32: - if (h == NULL) + if (h == NULL + || (info->shared + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) break; /* Fall through. */ case R_68K_8: |