From e7bab9df0f262a93918225d984cb48161922e854 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 12 Dec 1996 20:08:54 +0000 Subject: [PATCH] Support R_PPC_PLTREL24 --- bfd/ChangeLog | 5 ++ bfd/elf32-ppc.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 222 insertions(+), 27 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 371d94c..3dd932b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +Thu Dec 12 15:07:20 1996 Michael Meissner + + * elf32-ppc.c (ppc_elf_check_relocs): Move R_PPC_PLTREL24 into the + supported relocs. + Thu Dec 12 14:55:41 1996 Ian Lance Taylor * ppcboot.c (ppcboot_set_arch_mach): Don't define; it's a diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index d0a432a..bb4b8d4 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1113,10 +1113,8 @@ ppc_elf_copy_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd; { - /* This function is selected based on the input vector. We only - want to copy information over if the output BFD also uses Elf - format. */ - if (bfd_get_flavour (obfd) != bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return true; BFD_ASSERT (!elf_flags_init (obfd) @@ -1152,10 +1150,8 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd) return false; } - /* This function is selected based on the input vector. We only - want to copy information over if the output BFD also uses Elf - format. */ - if (bfd_get_flavour (obfd) != bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return true; new_flags = elf_elfheader (ibfd)->e_flags; @@ -1190,8 +1186,11 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd) ("%s: compiled normally and linked with modules compiled with -mrelocatable", bfd_get_filename (ibfd)); } - else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0) - elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE_LIB; + /* If -mrelocatable-lib is linked with an object without -mrelocatable-lib, turn off + the -mrelocatable-lib, since at least one module isn't relocatable. */ + else if ((old_flags & EF_PPC_RELOCATABLE_LIB) != 0 + && (new_flags & EF_PPC_RELOCATABLE_LIB) == 0) + elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */ @@ -1472,6 +1471,15 @@ ppc_elf_adjust_dynamic_symbol (info, h) /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; +#if 0 + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ + + s = bfd_get_section_by_name (dynobj, ".got.plt"); + BFD_ASSERT (s != NULL); + s->_raw_size += 4; +#endif + /* We also need to make an entry in the .rela.plt section. */ s = bfd_get_section_by_name (dynobj, ".rela.plt"); @@ -1610,17 +1618,11 @@ ppc_elf_size_dynamic_sections (output_bfd, info) s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } - - /* Make space for the trailing nop in .plt. */ - s = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (s != NULL); - if (s->_raw_size > 0) - s->_raw_size += 4; } else { /* We may have created entries in the .rela.got, .rela.sdata, and - .rela.sdata2 section2. However, if we are not creating the + .rela.sdata2 sections. However, if we are not creating the dynamic sections, we will not actually use these entries. Reset the size of .rela.got, et al, which will cause it to get stripped from the output file below. */ @@ -1820,6 +1822,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; + bfd_vma *local_got_offsets; elf_linker_section_t *got; elf_linker_section_t *plt; elf_linker_section_t *sdata; @@ -1871,6 +1874,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); + local_got_offsets = elf_local_got_offsets (abfd); sreloc = NULL; @@ -2007,6 +2011,10 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) case R_PPC_SECTOFF_HA: break; + /* This refers only to functions defined in the shared library */ + case R_PPC_LOCAL24PC: + break; + /* When creating a shared object, we must copy these relocs into the output file. We create a reloc section in dynobj and make room for the reloc. */ @@ -2027,6 +2035,10 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) if (info->shared && (sec->flags & SEC_ALLOC) != 0) { +#ifdef DEBUG + fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n", + (h && h->root.root.string) ? h->root.root.string : ""); +#endif if (sreloc == NULL) { const char *name; @@ -2096,8 +2108,28 @@ ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) elf_linker_section_t *sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); if (!sdata->bss_section) { - sdata->bss_section = bfd_make_section (elf_hash_table (info)->dynobj, sdata->bss_name); - sdata->bss_section->flags = (sdata->bss_section->flags & ~SEC_LOAD) | SEC_IS_COMMON; + /* We don't go through bfd_make_section, because we don't + want to attach this common section to DYNOBJ. The linker + will move the symbols to the appropriate output section + when it defines common symbols. */ + sdata->bss_section = ((asection *) + bfd_zalloc (abfd, sizeof (asection))); + if (sdata->bss_section == NULL) + return false; + sdata->bss_section->name = sdata->bss_name; + sdata->bss_section->flags = SEC_IS_COMMON; + sdata->bss_section->output_section = sdata->bss_section; + sdata->bss_section->symbol = + (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + sdata->bss_section->symbol_ptr_ptr = + (asymbol **) bfd_zalloc (abfd, sizeof (asymbol *)); + if (sdata->bss_section->symbol == NULL + || sdata->bss_section->symbol_ptr_ptr == NULL) + return false; + sdata->bss_section->symbol->name = sdata->bss_name; + sdata->bss_section->symbol->flags = BSF_SECTION_SYM; + sdata->bss_section->symbol->section = sdata->bss_section; + *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol; } *secp = sdata->bss_section; @@ -2384,6 +2416,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL; Elf_Internal_Rela *rel = relocs; Elf_Internal_Rela *relend = relocs + input_section->reloc_count; + asection *sreloc = NULL; boolean ret = true; long insn; @@ -2476,11 +2509,62 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; - if (!sec || !sec->output_section) + if ((r_type == R_PPC_PLT32 + && h->plt_offset != (bfd_vma) -1) + || ((r_type == R_PPC_GOT16 + || r_type == R_PPC_GOT16_LO + || r_type == R_PPC_GOT16_HI + || r_type == R_PPC_GOT16_HA) + && elf_hash_table (info)->dynamic_sections_created + && (! info->shared + || ! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) + || (info->shared + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0) + && (input_section->flags & SEC_ALLOC) != 0 + && (r_type == R_PPC_ADDR32 + || r_type == R_PPC_ADDR24 + || r_type == R_PPC_ADDR16 + || r_type == R_PPC_ADDR16_LO + || r_type == R_PPC_ADDR16_HI + || r_type == R_PPC_ADDR16_HA + || r_type == R_PPC_ADDR14 + || r_type == R_PPC_ADDR14_BRTAKEN + || r_type == R_PPC_ADDR14_BRNTAKEN + || r_type == R_PPC_PLTREL24 + || r_type == R_PPC_COPY + || r_type == R_PPC_GLOB_DAT + || r_type == R_PPC_JMP_SLOT + || r_type == R_PPC_UADDR32 + || r_type == R_PPC_UADDR16 + || r_type == R_PPC_REL32 + || r_type == R_PPC_SDAREL16 + || r_type == R_PPC_EMB_NADDR32 + || r_type == R_PPC_EMB_NADDR16 + || r_type == R_PPC_EMB_NADDR16_LO + || r_type == R_PPC_EMB_NADDR16_HI + || r_type == R_PPC_EMB_NADDR16_HA + || r_type == R_PPC_EMB_SDAI16 + || r_type == R_PPC_EMB_SDA2I16 + || r_type == R_PPC_EMB_SDA2REL + || r_type == R_PPC_EMB_SDA21 + || r_type == R_PPC_EMB_MRKREF + || r_type == R_PPC_EMB_BIT_FLD + || r_type == R_PPC_EMB_RELSDA + || ((r_type == R_PPC_REL24 + || r_type == R_PPC_REL14 + || r_type == R_PPC_REL14_BRTAKEN + || r_type == R_PPC_REL14_BRNTAKEN + || r_type == R_PPC_RELATIVE) + && strcmp (h->root.root.string, + "_GLOBAL_OFFSET_TABLE_") != 0)))) { - (*_bfd_error_handler) ("%s: Section in shared library for symbol %s\n", - bfd_get_filename (input_bfd), - sym_name); + /* In these cases, we don't need the relocation + value. We check specially because in some + obscure cases sec->output_section will be NULL. */ relocation = 0; } else @@ -2516,6 +2600,17 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, continue; /* relocations that need no special processing */ + case (int)R_PPC_LOCAL24PC: + break; + + case (int)R_PPC_REL24: + case (int)R_PPC_REL14: + if (h != NULL + && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + break; + /* fall through */ + + /* Relocations that need to be propigated if this is a shared object */ case (int)R_PPC_NONE: case (int)R_PPC_ADDR32: case (int)R_PPC_ADDR24: @@ -2523,11 +2618,108 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, case (int)R_PPC_ADDR16_LO: case (int)R_PPC_ADDR16_HI: case (int)R_PPC_ADDR14: - case (int)R_PPC_REL24: - case (int)R_PPC_REL14: case (int)R_PPC_UADDR32: case (int)R_PPC_UADDR16: case (int)R_PPC_REL32: + case (int)R_PPC_PLTREL24: + if (info->shared + && (input_section->flags & SEC_ALLOC) != 0) + { + Elf_Internal_Rela outrel; + +#ifdef DEBUG + fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n", + (h && h->root.root.string) ? h->root.root.string : ""); +#endif + + /* When generating a shared object, these relocations + are copied into the output file to be resolved at run + time. */ + + if (sreloc == NULL) + { + const char *name; + + name = (bfd_elf_string_from_elf_section + (input_bfd, + elf_elfheader (input_bfd)->e_shstrndx, + elf_section_data (input_section)->rel_hdr.sh_name)); + if (name == NULL) + return false; + + BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + && strcmp (bfd_get_section_name (input_bfd, + input_section), + name + 5) == 0); + + sreloc = bfd_get_section_by_name (dynobj, name); + BFD_ASSERT (sreloc != NULL); + } + + outrel.r_offset = (rel->r_offset + + input_section->output_section->vma + + input_section->output_offset); + if (h != NULL + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) + { + BFD_ASSERT (h->dynindx != -1); + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + outrel.r_addend = rel->r_addend; + } + else + { + if (r_type == R_PPC_ADDR32) + { + outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); + outrel.r_addend = relocation + rel->r_addend; + } + else + { + long indx; + + if (h == NULL) + sec = local_sections[r_symndx]; + else + { + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || (h->root.type + == bfd_link_hash_defweak)); + sec = h->root.u.def.section; + } + if (sec != NULL && bfd_is_abs_section (sec)) + indx = 0; + else if (sec == NULL || sec->owner == NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + else + { + asection *osec; + + osec = sec->output_section; + indx = elf_section_data (osec)->dynindx; + if (indx == 0) + abort (); + } + + outrel.r_info = ELF32_R_INFO (indx, r_type); + outrel.r_addend = relocation + rel->r_addend; + } + } + + bfd_elf32_swap_reloca_out (output_bfd, &outrel, + (((Elf32_External_Rela *) + sreloc->contents) + + sreloc->reloc_count)); + ++sreloc->reloc_count; + + /* This reloc will be computed at runtime, so there's no + need to do anything now. */ + continue; + } break; /* branch taken prediction relocations */ @@ -2724,12 +2916,10 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, case (int)R_PPC_EMB_MRKREF: continue; - case (int)R_PPC_PLTREL24: case (int)R_PPC_COPY: case (int)R_PPC_GLOB_DAT: case (int)R_PPC_JMP_SLOT: case (int)R_PPC_RELATIVE: - case (int)R_PPC_LOCAL24PC: case (int)R_PPC_PLT32: case (int)R_PPC_PLTREL32: case (int)R_PPC_PLT16_LO: -- 2.7.4