aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-m68k.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1997-01-03 22:09:40 +0000
committerIan Lance Taylor <ian@airs.com>1997-01-03 22:09:40 +0000
commitff12f303355b20de1260bc1d007f973bd02615dc (patch)
tree405f3b582a787fe20c609cda43409e3105cb6b38 /bfd/elf32-m68k.c
parent98141a3cc1a9e2a5c11abc9d9f6c34e30f7e2b64 (diff)
downloadgdb-ff12f303355b20de1260bc1d007f973bd02615dc.zip
gdb-ff12f303355b20de1260bc1d007f973bd02615dc.tar.gz
gdb-ff12f303355b20de1260bc1d007f973bd02615dc.tar.bz2
Fri Jan 3 16:58:31 1997 Richard Henderson <rth@tamu.edu>
elf64-alpha multiple .got rewrite: * elf-bfd.h (struct elf_backend_data): Add always_size_sections entry. (bfd_elf*_mkobject): Don't define here ... * elfxx-target.h: ... but rather here. Default always_size_sections hook to NULL. * elf.c (elf_mkobject): Rename to bfd_elf_mkobject, since that was what the #defines in elf-bfd.h transmuted it to anyway. * section.c: Add SEC_LINKER_CREATED flag. * bfd-in2.h: Rebuild. * elf32-i386.c (elf_i386_check_relocs): Add SEC_LINKER_CREATED to relocation section flags. (elf_i386_size_dynamic_sections): Use SEC_LINKER_CREATED instead of SEC_IN_MEMORY to recognize generated bits. * elf32-m68k.c (elf_m68k_check_relocs, elf_m68k_size_dynamic_sections): Likewise. * elf32-mips.c (mips_elf_final_link, mips_elf_create_dynamic_sections, mips_elf_create_compact_rel_section, mips_elf_create_got_section, mips_elf_check_relocs, mips_elf_size_dynamic_sections): Likewise. * elf32-ppc.c (ppc_elf_create_linker_section, ppc_elf_size_dynamic_sections): Likewise. * elf32-sparc.c (elf32_sparc_check_relocs, elf32_sparc_size_dynamic_sections): Likewise. * elflink.c (_bfd_elf_create_got_section): Add SEC_LINKER_CREATED to section flags. (_bfd_elf_create_dynamic_sections): Likewise. (_bfd_elf_make_linker_section_rela): Likewise. * elflink.h (elf_link_create_dynamic_sections): Likewise. (bfd_elf,size_dynamic_sections): Call the always_size_sections hook. (elf_bfd_final_link): Use SEC_LINKER_CREATED instead of SEC_IN_MEMORY to identify generated bits. (elf_link_input_bfd): Likewise. * elf64-alpha.c: Rewrite everything touching relocations.
Diffstat (limited to 'bfd/elf32-m68k.c')
-rw-r--r--bfd/elf32-m68k.c329
1 files changed, 183 insertions, 146 deletions
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 2303f62..b64f735 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -187,9 +187,9 @@ reloc_type_lookup (abfd, code)
static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] =
{
0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
- 0, 0, 0, 0, /* replaced with address of .got + 4. */
+ 0, 0, 0, 0, /* replaced with offset to .got + 4. */
0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,addr]) */
- 0, 0, 0, 0, /* replaced with address of .got + 8. */
+ 0, 0, 0, 0, /* replaced with offset to .got + 8. */
0, 0, 0, 0 /* pad out to 20 bytes. */
};
@@ -197,8 +197,8 @@ static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] =
static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] =
{
- 0x4e, 0xfb, 0x01, 0x71, /* jmp ([addr]) */
- 0, 0, 0, 0, /* replaced with address of this symbol in .got. */
+ 0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,symbol@GOTPC]) */
+ 0, 0, 0, 0, /* replaced with offset to symbol's .got entry. */
0x2f, 0x3c, /* move.l #offset,-(%sp) */
0, 0, 0, 0, /* replaced with offset into relocation table. */
0x60, 0xff, /* bra.l .plt */
@@ -256,15 +256,15 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
case R_68K_GOT8:
case R_68K_GOT16:
case R_68K_GOT32:
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
case R_68K_GOT8O:
case R_68K_GOT16O:
case R_68K_GOT32O:
/* This symbol requires a global offset table entry. */
- if (h != NULL
- && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
- break;
-
if (dynobj == NULL)
{
/* Create the .got section. */
@@ -292,6 +292,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
| SEC_READONLY))
|| !bfd_set_section_alignment (dynobj, srelgot, 2))
return false;
@@ -355,20 +356,35 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
case R_68K_PLT8:
case R_68K_PLT16:
case R_68K_PLT32:
- case R_68K_PLT8O:
- case R_68K_PLT16O:
- case R_68K_PLT32O:
/* This symbol requires a procedure linkage table entry. We
actually build the entry in adjust_dynamic_symbol,
- because this might be a case of linking PIC code without
- linking in any dynamic objects, in which case we don't
- need to generate a procedure linkage table after all. */
-
+ because this might be a case of linking PIC code which is
+ never referenced by a dynamic object, in which case we
+ don't need to generate a procedure linkage table entry
+ after all. */
+
/* If this is a local symbol, we resolve it directly without
creating a procedure linkage table entry. */
if (h == NULL)
continue;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ break;
+
+ case R_68K_PLT8O:
+ case R_68K_PLT16O:
+ case R_68K_PLT32O:
+ /* This symbol requires a procedure linkage table entry. */
+
+ if (h == NULL)
+ {
+ /* It does not make sense to have this relocation for a
+ local symbol. FIXME: does it? How to handle it if
+ it does make sense? */
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
@@ -389,7 +405,13 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
case R_68K_16:
case R_68K_32:
if (info->shared
- && (sec->flags & SEC_ALLOC) != 0)
+ && (sec->flags & SEC_ALLOC) != 0
+ && ((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
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
@@ -419,6 +441,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
| SEC_READONLY))
|| !bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
@@ -472,17 +495,30 @@ elf_m68k_adjust_dynamic_symbol (info, h)
if (h->type == STT_FUNC
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
{
- if (!elf_hash_table (info)->dynamic_sections_created)
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
+ /* We must always create the plt entry if it was referenced
+ by a PLTxxO relocation. In this case we already recorded
+ it as a dynamic symbol. */
+ && h->dynindx == -1)
{
- /* This case can occur if we saw a PLT32 reloc in an input
- file, but none of the input files were dynamic objects.
- In such a case, we don't actually need to build a
- procedure linkage table, and we can just do a PC32 reloc
- instead. */
+ /* This case can occur if we saw a PLTxx reloc in an input
+ file, but the symbol was never referred to by a dynamic
+ object. In such a case, we don't actually need to build
+ a procedure linkage table, and we can just do a PCxx
+ reloc instead. */
BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
return true;
}
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
s = bfd_get_section_by_name (dynobj, ".plt");
BFD_ASSERT (s != NULL);
@@ -651,7 +687,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
const char *name;
boolean strip;
- if ((s->flags & SEC_IN_MEMORY) == 0)
+ if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
/* It's OK to base decisions on the section name, because none
@@ -800,7 +836,6 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
struct elf_link_hash_entry **sym_hashes;
bfd_vma *local_got_offsets;
asection *sgot;
- asection *sgotplt;
asection *splt;
asection *sreloc;
Elf_Internal_Rela *rel;
@@ -812,7 +847,6 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
local_got_offsets = elf_local_got_offsets (input_bfd);
sgot = NULL;
- sgotplt = NULL;
splt = NULL;
sreloc = NULL;
@@ -941,8 +975,8 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
case R_68K_GOT8:
case R_68K_GOT16:
case R_68K_GOT32:
- /* Relocation is to the entry for this symbol in the global
- offset table. */
+ /* Relocation is to the address of the entry for this symbol
+ in the global offset table. */
if (h != NULL
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
break;
@@ -953,105 +987,97 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
/* Relocation is the offset of the entry for this symbol in
the global offset table. */
- if (sgot == NULL)
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
- }
-
- if (sgotplt == NULL)
- {
- sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- BFD_ASSERT (sgotplt != NULL);
- }
-
- if (h != NULL)
- {
- bfd_vma off;
+ {
+ bfd_vma off;
- off = h->got_offset;
- BFD_ASSERT (off != (bfd_vma) -1);
-
- if (!elf_hash_table (info)->dynamic_sections_created
- || (info->shared
- && info->symbolic
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
- {
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally. We must initialize this entry in the
- global offset table. Since the offset must
- always be a multiple of 4, we use the least
- significant bit to record whether we have
- initialized it already.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation,
- sgot->contents + off);
- h->got_offset |= 1;
- }
- }
-
- relocation = sgot->output_offset + off;
- if (r_type == R_68K_GOT8O
- || r_type == R_68K_GOT16O
- || r_type == R_68K_GOT32O)
- relocation -= sgotplt->output_offset;
- }
- else
- {
- bfd_vma off;
-
- BFD_ASSERT (local_got_offsets != NULL
- && local_got_offsets[r_symndx] != (bfd_vma) -1);
-
- off = local_got_offsets[r_symndx];
-
- /* The offset must always be a multiple of 4. We use
- the least significant bit to record whether we have
- already generated the necessary reloc. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
- if (info->shared)
- {
- asection *srelgot;
- Elf_Internal_Rela outrel;
+ if (h != NULL)
+ {
+ off = h->got_offset;
+ BFD_ASSERT (off != (bfd_vma) -1);
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- BFD_ASSERT (srelgot != NULL);
+ if (!elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global offset table. Since the offset must
+ always be a multiple of 4, we use the least
+ significant bit to record whether we have
+ initialized it already.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation,
+ sgot->contents + off);
+ h->got_offset |= 1;
+ }
+ }
+ }
+ else
+ {
+ BFD_ASSERT (local_got_offsets != NULL
+ && local_got_offsets[r_symndx] != (bfd_vma) -1);
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + off);
- outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
- outrel.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- (((Elf32_External_Rela *)
- srelgot->contents)
- + srelgot->reloc_count));
- ++srelgot->reloc_count;
- }
+ off = local_got_offsets[r_symndx];
- local_got_offsets[r_symndx] |= 1;
- }
-
- relocation = sgot->output_offset + off;
- if (r_type == R_68K_GOT8O
- || r_type == R_68K_GOT16O
- || r_type == R_68K_GOT32O)
- relocation -= sgotplt->output_offset;
- }
+ /* The offset must always be a multiple of 4. We use
+ the least significant bit to record whether we have
+ already generated the necessary reloc. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+
+ if (info->shared)
+ {
+ asection *srelgot;
+ Elf_Internal_Rela outrel;
+
+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (srelgot != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + off);
+ outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ outrel.r_addend = relocation;
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+ (((Elf32_External_Rela *)
+ srelgot->contents)
+ + srelgot->reloc_count));
+ ++srelgot->reloc_count;
+ }
+
+ local_got_offsets[r_symndx] |= 1;
+ }
+ }
+ relocation = sgot->output_offset + off;
+ if (r_type == R_68K_GOT8O
+ || r_type == R_68K_GOT16O
+ || r_type == R_68K_GOT32O)
+ {
+ /* This relocation does not use the addend. */
+ rel->r_addend = 0;
+ }
+ else
+ relocation += sgot->output_section->vma;
+ }
break;
case R_68K_PLT8:
@@ -1060,7 +1086,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
/* Relocation is to the entry for this symbol in the
procedure linkage table. */
- /* Resolve a PLT32 reloc against a local symbol directly,
+ /* Resolve a PLTxx reloc against a local symbol directly,
without using the procedure linkage table. */
if (h == NULL)
break;
@@ -1089,14 +1115,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
case R_68K_PLT32O:
/* Relocation is the offset of the entry for this symbol in
the procedure linkage table. */
- BFD_ASSERT (h != NULL);
-
- if (h->plt_offset == (bfd_vma) -1)
- {
- /* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code. */
- break;
- }
+ BFD_ASSERT (h != NULL && h->plt_offset == (bfd_vma) -1);
if (splt == NULL)
{
@@ -1105,6 +1124,10 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
}
relocation = h->plt_offset;
+
+ /* This relocation does not use the addend. */
+ rel->r_addend = 0;
+
break;
case R_68K_PC8:
@@ -1117,9 +1140,16 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
case R_68K_16:
case R_68K_32:
if (info->shared
- && (input_section->flags & SEC_ALLOC) != 0)
+ && (input_section->flags & SEC_ALLOC) != 0
+ && ((r_type != R_68K_PC8
+ && r_type != R_68K_PC16
+ && r_type != R_68K_PC32)
+ || (!info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
Elf_Internal_Rela outrel;
+ int relocate;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
@@ -1154,13 +1184,15 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
& ELF_LINK_HASH_DEF_REGULAR) == 0))
{
BFD_ASSERT (h->dynindx != -1);
+ relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
- outrel.r_addend = rel->r_addend;
+ outrel.r_addend = relocation + rel->r_addend;
}
else
{
if (r_type == R_68K_32)
{
+ relocate = true;
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
outrel.r_addend = relocation + rel->r_addend;
}
@@ -1194,6 +1226,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
abort ();
}
+ relocate = false;
outrel.r_info = ELF32_R_INFO (indx, r_type);
outrel.r_addend = relocation + rel->r_addend;
}
@@ -1206,8 +1239,11 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
++sreloc->reloc_count;
/* This reloc will be computed at runtime, so there's no
- need to do anything now. */
- continue;
+ need to do anything now, except for R_68K_32
+ relocations that have been turned into
+ R_68K_RELATIVE. */
+ if (!relocate)
+ continue;
}
break;
@@ -1351,7 +1387,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
/* This symbol has an entry in the global offset table. Set it
up. */
-
+
BFD_ASSERT (h->dynindx != -1);
sgot = bfd_get_section_by_name (dynobj, ".got");
@@ -1369,14 +1405,19 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
if (info->shared
&& info->symbolic
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
- rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ {
+ rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ rela.r_addend = bfd_get_32 (output_bfd,
+ sgot->contents + (h->got_offset & ~1));
+ }
else
{
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0,
+ sgot->contents + (h->got_offset & ~1));
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT);
+ rela.r_addend = 0;
}
- rela.r_addend = 0;
bfd_elf32_swap_reloca_out (output_bfd, &rela,
((Elf32_External_Rela *) srela->contents
+ srela->reloc_count));
@@ -1480,17 +1521,13 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
break;
case DT_RELASZ:
- /* My reading of the SVR4 ABI indicates that the
- procedure linkage table relocs (DT_JMPREL) should be
- included in the overall relocs (DT_RELA). This is
- what Solaris does. However, UnixWare can not handle
- that case. Therefore, we override the DT_RELASZ entry
- here to make it not include the JMPREL relocs. Since
- the linker script arranges for .rela.plt to follow all
+ /* The procedure linkage table relocs (DT_JMPREL) should
+ not be included in the overall relocs (DT_RELA).
+ Therefore, we override the DT_RELASZ entry here to
+ make it not include the JMPREL relocs. Since the
+ linker script arranges for .rela.plt to follow all
other relocation sections, we don't have to worry
about changing the DT_RELA entry. */
- /* FIXME: This comment is from elf32-i386.c, what about
- the SVR4/m68k implementations? */
s = bfd_get_section_by_name (output_bfd, ".rela.plt");
if (s != NULL)
{