diff options
author | Ian Lance Taylor <ian@airs.com> | 1997-01-03 22:09:40 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1997-01-03 22:09:40 +0000 |
commit | ff12f303355b20de1260bc1d007f973bd02615dc (patch) | |
tree | 405f3b582a787fe20c609cda43409e3105cb6b38 /bfd/elf32-m68k.c | |
parent | 98141a3cc1a9e2a5c11abc9d9f6c34e30f7e2b64 (diff) | |
download | gdb-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.c | 329 |
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) { |