/* Intel 80386/80486-specific support for 32-bit ELF
- Copyright 1993, 94-98, 1999 Free Software Foundation, Inc.
+ Copyright 1993, 94, 95, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
bfd_elf_generic_reloc, "R_386_GOTPC",
true, 0xffffffff, 0xffffffff, true),
+ /* We have a gap in the reloc numbers here.
+ R_386_standard counts the number up to this point, and
+ R_386_ext_offset is the value to subtract from a reloc type of
+ R_386_16 thru R_386_PC8 to form an index into this table. */
#define R_386_standard ((unsigned int) R_386_GOTPC + 1)
#define R_386_ext_offset ((unsigned int) R_386_16 - R_386_standard)
true, 0xff, 0xff, false),
HOWTO(R_386_PC8, 0, 0, 8, true, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_386_PC8",
- true, 0xff, 0xff, true)
-};
+ true, 0xff, 0xff, true),
+
+ /* Another gap. */
+#define R_386_ext ((unsigned int) R_386_PC8 + 1 - R_386_ext_offset)
+#define R_386_vt_offset ((unsigned int) R_386_GNU_VTINHERIT - R_386_ext)
/* GNU extension to record C++ vtable hierarchy. */
-static reloc_howto_type elf32_i386_vtinherit_howto =
HOWTO (R_386_GNU_VTINHERIT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false);
+ false),
/* GNU extension to record C++ vtable member usage. */
-static reloc_howto_type elf32_i386_vtentry_howto =
HOWTO (R_386_GNU_VTENTRY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
- false);
+ false)
+
+#define R_386_vt ((unsigned int) R_386_GNU_VTENTRY + 1 - R_386_vt_offset)
+
+};
+
#ifdef DEBUG_GEN_RELOC
#define TRACE(str) fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str)
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
- return &elf32_i386_vtinherit_howto;
+ return &elf_howto_table[(unsigned int) R_386_GNU_VTINHERIT
+ - R_386_vt_offset];
case BFD_RELOC_VTABLE_ENTRY:
TRACE ("BFD_RELOC_VTABLE_ENTRY");
- return &elf32_i386_vtentry_howto;
+ return &elf_howto_table[(unsigned int) R_386_GNU_VTENTRY
+ - R_386_vt_offset];
default:
break;
arelent *cache_ptr;
Elf32_Internal_Rel *dst;
{
- enum elf_i386_reloc_type type;
-
- type = (enum elf_i386_reloc_type) ELF32_R_TYPE (dst->r_info);
- if (type == R_386_GNU_VTINHERIT)
- cache_ptr->howto = &elf32_i386_vtinherit_howto;
- else if (type == R_386_GNU_VTENTRY)
- cache_ptr->howto = &elf32_i386_vtentry_howto;
- else
+ unsigned int r_type = ELF32_R_TYPE (dst->r_info);
+ unsigned int indx;
+
+ if ((indx = r_type) >= R_386_standard
+ && ((indx = r_type - R_386_ext_offset) - R_386_standard
+ >= R_386_ext - R_386_standard)
+ && ((indx = r_type - R_386_vt_offset) - R_386_ext
+ >= R_386_vt - R_386_ext))
{
- unsigned int indx;
-
- if ((indx = (unsigned int) type) >= R_386_standard
- && ((indx = (unsigned int) type - R_386_ext_offset)
- >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0])))
- {
- (*_bfd_error_handler) (_("%s: invalid relocation type %d"),
- bfd_get_filename (abfd), (int) type);
- indx = (unsigned int) R_386_NONE;
- }
- cache_ptr->howto = &elf_howto_table[indx];
+ (*_bfd_error_handler) (_("%s: invalid relocation type %d"),
+ bfd_get_filename (abfd), (int) r_type);
+ indx = (unsigned int) R_386_NONE;
}
+ cache_ptr->howto = &elf_howto_table[indx];
}
/* Return whether a symbol name implies a local label. The UnixWare
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
/* If we are creating a shared library, and this is a reloc
- against a global symbol, or a non PC relative reloc
- against a local symbol, then we need to copy the reloc
- into the shared library. However, if we are linking with
- -Bsymbolic, we do not need to copy a reloc against a
- global symbol which is defined in an object we are
- including in the link (i.e., DEF_REGULAR is set). At
- this point we have not seen all the input files, so it is
- possible that DEF_REGULAR is not set now but will be set
- later (it is never cleared). We account for that
- possibility below by storing information in the
- pcrel_relocs_copied field of the hash table entry. */
+ against a global symbol, or a non PC relative reloc
+ against a local symbol, then we need to copy the reloc
+ into the shared library. However, if we are linking with
+ -Bsymbolic, we do not need to copy a reloc against a
+ global symbol which is defined in an object we are
+ including in the link (i.e., DEF_REGULAR is set). At
+ this point we have not seen all the input files, so it is
+ possible that DEF_REGULAR is not set now but will be set
+ later (it is never cleared). We account for that
+ possibility below by storing information in the
+ pcrel_relocs_copied field of the hash table entry.
+ A similar situation occurs when creating shared libraries
+ and symbol visibility changes render the symbol local. */
if (info->shared
&& (sec->flags & SEC_ALLOC) != 0
&& (ELF32_R_TYPE (rel->r_info) != R_386_PC32
& 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
- section in dynobj and make room for this reloc. */
+ reloc types into the output file. We create a reloc
+ section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
const char *name;
sreloc->_raw_size += sizeof (Elf32_External_Rel);
- /* If we are linking with -Bsymbolic, and this is a
- global symbol, we count the number of PC relative
- relocations we have entered for this symbol, so that
- we can discard them again if the symbol is later
- defined by a regular object. Note that this function
- is only called if we are using an elf_i386 linker
- hash table, which means that h is really a pointer to
- an elf_i386_link_hash_entry. */
- if (h != NULL && info->symbolic
+ /* If this is a global symbol, we count the number of PC
+ relative relocations we have entered for this symbol,
+ so that we can discard them later as necessary. Note
+ that this function is only called if we are using an
+ elf_i386 linker hash table, which means that h is
+ really a pointer to an elf_i386_link_hash_entry. */
+ if (h != NULL
&& ELF32_R_TYPE (rel->r_info) == R_386_PC32)
{
struct elf_i386_link_hash_entry *eh;
PC relative relocs against symbols defined in a regular object.
We allocated space for them in the check_relocs routine, but we
will not fill them in in the relocate_section routine. */
- if (info->shared && info->symbolic)
+ if (info->shared)
elf_i386_link_hash_traverse (elf_i386_hash_table (info),
elf_i386_discard_copies,
- (PTR) NULL);
+ (PTR) info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
continue;
}
- /* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ /* Allocate memory for the section contents. We use bfd_zalloc
+ here in case unused entries are not reclaimed before the
+ section's contents are written out. This should not happen,
+ but this way if it does, we get a R_386_NONE reloc instead
+ of garbage. */
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
return false;
}
{
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
+ info->flags |= DF_TEXTREL;
}
}
}
/* This function is called via elf_i386_link_hash_traverse if we are
- creating a shared object with -Bsymbolic. It discards the space
- allocated to copy PC relative relocs against symbols which are
- defined in regular objects. We allocated space for them in the
+ creating a shared object. In the -Bsymbolic case, it discards the
+ space allocated to copy PC relative relocs against symbols which
+ are defined in regular objects. For the normal non-symbolic case,
+ we also discard space for relocs that have become local due to
+ symbol visibility changes. We allocated space for them in the
check_relocs routine, but we won't fill them in in the
relocate_section routine. */
/*ARGSUSED*/
static boolean
-elf_i386_discard_copies (h, ignore)
+elf_i386_discard_copies (h, inf)
struct elf_i386_link_hash_entry *h;
- PTR ignore ATTRIBUTE_UNUSED;
+ PTR inf;
{
struct elf_i386_pcrel_relocs_copied *s;
-
- /* We only discard relocs for symbols defined in a regular object. */
- if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- return true;
-
- for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
- s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+ /* If a symbol has been forced local or we have found a regular
+ definition for the symbolic link case, then we won't be needing
+ any relocs. */
+ if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+ || info->symbolic))
+ {
+ for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
+ s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
+ }
return true;
}
unsigned int indx;
r_type = ELF32_R_TYPE (rel->r_info);
- if (r_type == R_386_GNU_VTINHERIT
- || r_type == R_386_GNU_VTENTRY)
+ if (r_type == (int) R_386_GNU_VTINHERIT
+ || r_type == (int) R_386_GNU_VTENTRY)
continue;
+
if ((indx = (unsigned) r_type) >= R_386_standard
- && ((indx = (unsigned) r_type - R_386_ext_offset)
- >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0])))
+ && ((indx = (unsigned) r_type - R_386_ext_offset) - R_386_standard
+ >= R_386_ext - R_386_standard))
{
bfd_set_error (bfd_error_bad_value);
return false;