Support R_PPC_PLTREL24

This commit is contained in:
Michael Meissner 1996-12-12 20:08:54 +00:00
parent a5147005bb
commit e7bab9df0f
2 changed files with 222 additions and 27 deletions

View File

@ -1,3 +1,8 @@
Thu Dec 12 15:07:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
* 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 <ian@cygnus.com>
* ppcboot.c (ppcboot_set_arch_mach): Don't define; it's a

View File

@ -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 : "<unknown>");
#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 : "<unknown>");
#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: