aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r--bfd/elf32-i386.c135
1 files changed, 94 insertions, 41 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 9ee5966..f8b1844 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -60,6 +60,13 @@ enum reloc_type
R_386_RELATIVE,
R_386_GOTOFF,
R_386_GOTPC,
+ FIRST_INVALID_RELOC,
+ LAST_INVALID_RELOC = 19,
+ /* The remaining relocs are a GNU extension. */
+ R_386_16 = 20,
+ R_386_PC16,
+ R_386_8,
+ R_386_PC8,
R_386_max
};
@@ -93,6 +100,20 @@ static reloc_howto_type elf_howto_table[]=
HOWTO(R_386_RELATIVE, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_RELATIVE", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_GOTOFF, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTOFF", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_GOTPC, 0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTPC", true,0xffffffff,0xffffffff,true),
+ { 11 },
+ { 12 },
+ { 13 },
+ { 14 },
+ { 15 },
+ { 16 },
+ { 17 },
+ { 18 },
+ { 19 },
+ /* The remaining relocs are a GNU extension. */
+ HOWTO(R_386_16, 0,1,16,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_16", true,0xffff,0xffff,false),
+ HOWTO(R_386_PC16, 0,1,16,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC16", true,0xffff,0xffff,true),
+ HOWTO(R_386_8, 0,0,8,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_8", true,0xff,0xff,false),
+ HOWTO(R_386_PC8, 0,0,8,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC8", true,0xff,0xff,true),
};
#ifdef DEBUG_GEN_RELOC
@@ -152,6 +173,23 @@ elf_i386_reloc_type_lookup (abfd, code)
TRACE ("BFD_RELOC_386_GOTPC");
return &elf_howto_table[ (int)R_386_GOTPC ];
+ /* The remaining relocs are a GNU extension. */
+ case BFD_RELOC_16:
+ TRACE ("BFD_RELOC_16");
+ return &elf_howto_table[(int) R_386_16];
+
+ case BFD_RELOC_16_PCREL:
+ TRACE ("BFD_RELOC_16_PCREL");
+ return &elf_howto_table[(int) R_386_PC16];
+
+ case BFD_RELOC_8:
+ TRACE ("BFD_RELOC_8");
+ return &elf_howto_table[(int) R_386_8];
+
+ case BFD_RELOC_8_PCREL:
+ TRACE ("BFD_RELOC_8_PCREL");
+ return &elf_howto_table[(int) R_386_PC8];
+
default:
break;
}
@@ -166,20 +204,22 @@ elf_i386_info_to_howto (abfd, cache_ptr, dst)
arelent *cache_ptr;
Elf32_Internal_Rela *dst;
{
- BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_386_max);
-
- cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+ abort ();
}
static void
elf_i386_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
+ bfd *abfd;
+ arelent *cache_ptr;
Elf32_Internal_Rel *dst;
{
- BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_386_max);
+ enum reloc_type type;
+
+ type = (enum reloc_type) ELF32_R_TYPE (dst->r_info);
+ BFD_ASSERT (type < R_386_max);
+ BFD_ASSERT (type < FIRST_INVALID_RELOC || type > LAST_INVALID_RELOC);
- cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+ cache_ptr->howto = &elf_howto_table[(int) type];
}
/* Functions for the i386 ELF linker. */
@@ -222,8 +262,8 @@ static const bfd_byte elf_i386_plt_entry[PLT_ENTRY_SIZE] =
static const bfd_byte elf_i386_pic_plt0_entry[PLT_ENTRY_SIZE] =
{
- 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */
- 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */
+ 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */
+ 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */
0, 0, 0, 0 /* pad out to 16 bytes. */
};
@@ -307,7 +347,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
{
case R_386_GOT32:
/* This symbol requires a global offset table entry. */
-
+
if (sgot == NULL)
{
sgot = bfd_get_section_by_name (dynobj, ".got");
@@ -327,6 +367,7 @@ elf_i386_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;
@@ -391,22 +432,16 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
case R_386_PLT32:
/* 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;
- /* 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;
- }
-
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
break;
@@ -414,7 +449,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
case R_386_32:
case R_386_PC32:
if (info->shared
- && (sec->flags & SEC_ALLOC) != 0
&& (ELF32_R_TYPE (rel->r_info) != R_386_PC32 || h != NULL))
{
/* When creating a shared object, we must copy these
@@ -438,14 +472,15 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
sreloc = bfd_get_section_by_name (dynobj, name);
if (sreloc == NULL)
{
+ flagword flags;
+
sreloc = bfd_make_section (dynobj, name);
+ flags = (SEC_HAS_CONTENTS | SEC_READONLY
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ if ((sec->flags & SEC_ALLOC) != 0)
+ flags |= SEC_ALLOC | SEC_LOAD;
if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY))
+ || ! bfd_set_section_flags (dynobj, sreloc, flags)
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
@@ -453,7 +488,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
sreloc->_raw_size += sizeof (Elf32_External_Rel);
}
-
+
break;
default:
@@ -498,17 +533,26 @@ elf_i386_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)
{
/* 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. */
+ 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 PC32
+ 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);
@@ -677,7 +721,7 @@ elf_i386_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
@@ -766,7 +810,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
if (s->contents == NULL && s->_raw_size != 0)
return false;
}
-
+
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -855,7 +899,10 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_reloc_status_type r;
r_type = ELF32_R_TYPE (rel->r_info);
- if (r_type < 0 || r_type >= (int) R_386_max)
+ if (r_type < 0
+ || r_type >= (int) R_386_max
+ || (r_type >= (int) FIRST_INVALID_RELOC
+ && r_type <= (int) LAST_INVALID_RELOC))
{
bfd_set_error (bfd_error_bad_value);
return false;
@@ -923,14 +970,21 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)
&& (r_type == R_386_32
- || r_type == R_386_PC32)
- && (input_section->flags & SEC_ALLOC) != 0))
+ || r_type == R_386_PC32)))
{
/* 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 if (sec->output_section == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: warning: unresolvable relocation against symbol `%s' from %s section",
+ bfd_get_filename (input_bfd), h->root.root.string,
+ bfd_get_section_name (input_bfd, input_section));
+ relocation = 0;
+ }
else
relocation = (h->root.u.def.value
+ sec->output_section->vma
@@ -1105,7 +1159,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
case R_386_32:
case R_386_PC32:
if (info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
&& (! info->symbolic
@@ -1327,7 +1380,7 @@ elf_i386_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");