* elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when

copying relocs into a shared object, treat a defined global symbol
	as a local symbol.
	* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
	* elf32-mips.c (mips_elf_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
This commit is contained in:
Ian Lance Taylor 1996-01-29 20:01:29 +00:00
parent bdd2e7f179
commit 53787b2316
5 changed files with 428 additions and 312 deletions

View File

@ -7,6 +7,13 @@ Mon Jan 29 14:27:24 1996 Kim Knuttila <krk@cygnus.com>
Mon Jan 29 13:06:28 1996 Ian Lance Taylor <ian@cygnus.com>
* elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when
copying relocs into a shared object, treat a defined global symbol
as a local symbol.
* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
* elf32-mips.c (mips_elf_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
* elflink.h (elf_link_add_object_symbols): Only set weakdef to a
real defined symbol, not to a weak defined symbol.

View File

@ -1,5 +1,5 @@
/* Intel 80386/80486-specific support for 32-bit ELF
Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -916,6 +916,9 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|| (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)
&& (r_type == R_386_32
|| r_type == R_386_PC32)
&& (input_section->flags & SEC_ALLOC) != 0))
@ -1100,9 +1103,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
case R_386_PC32:
if (info->shared
&& (input_section->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32 || h != NULL))
&& (r_type != R_386_PC32
|| (h != NULL
&& (! info->symbolic
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
{
Elf_Internal_Rel outrel;
boolean relocate;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
@ -1134,15 +1142,23 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
if (r_type == R_386_PC32)
{
BFD_ASSERT (h != NULL && h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
}
else
{
if (h == NULL)
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
if (h == NULL
|| (info->symbolic
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) != 0))
{
relocate = true;
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
}
else
{
BFD_ASSERT (h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
}
}
@ -1157,7 +1173,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes
an addend for the dynamic reloc. */
if (h != NULL)
if (! relocate)
continue;
}

View File

@ -1,5 +1,5 @@
/* Motorola 68k series support for 32-bit ELF
Copyright 1993 Free Software Foundation, Inc.
Copyright 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -898,6 +898,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|| (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_68K_8
|| r_type == R_68K_16
@ -1142,7 +1145,10 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
outrel.r_offset = (rel->r_offset
+ input_section->output_section->vma
+ input_section->output_offset);
if (h != NULL)
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);
@ -1159,11 +1165,15 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
{
long indx;
sym = local_syms + r_symndx;
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
sec = local_sections[r_symndx];
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)

View File

@ -80,6 +80,10 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void mips_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
static void bfd_mips_elf32_swap_gptab_in
PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
static void bfd_mips_elf32_swap_gptab_out
PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
static boolean mips_elf_object_p PARAMS ((bfd *));
static boolean mips_elf_create_procedure_table
@ -89,6 +93,9 @@ static int mips_elf_additional_program_headers PARAMS ((bfd *));
static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
static void mips_elf_final_write_processing
PARAMS ((bfd *, boolean));
static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword));
static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
static boolean mips_elf_section_from_shdr
PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
static boolean mips_elf_fake_sections
@ -125,11 +132,32 @@ static boolean mips_elf_adjust_dynindx
static boolean mips_elf_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static boolean mips_elf_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean mips_elf_create_compact_rel_section
PARAMS ((bfd *, struct bfd_link_info *));
static boolean mips_elf_create_got_section
PARAMS ((bfd *, struct bfd_link_info *));
static boolean mips_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
static boolean mips_elf_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
static boolean mips_elf_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean mips_elf_finish_dynamic_symbol
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
Elf_Internal_Sym *));
static boolean mips_elf_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean mips_elf_add_symbol_hook
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
const char **, flagword *, asection **, bfd_vma *));
static bfd_reloc_status_type mips_elf_final_gp
PARAMS ((bfd *, asymbol *, boolean, char **));
static bfd_byte *elf32_mips_get_relocated_section_contents
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
bfd_byte *, boolean, asymbol **));
/* This is true for Irix 5 executables, false for normal MIPS ELF ABI
executables. FIXME: At the moment, we default to always generating
@ -289,6 +317,11 @@ typedef struct
#define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v))
#define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2)
static void bfd_elf32_swap_compact_rel_out
PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
static void bfd_elf32_swap_crinfo_out
PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
#define USE_REL 1 /* MIPS uses REL relocations instead of RELA */
enum reloc_type
@ -1327,7 +1360,7 @@ bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
static void
bfd_elf32_swap_compact_rel_out (abfd, in, ex)
bfd *abfd;
Elf32_compact_rel *in;
const Elf32_compact_rel *in;
Elf32_External_compact_rel *ex;
{
bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1);
@ -1341,7 +1374,7 @@ bfd_elf32_swap_compact_rel_out (abfd, in, ex)
static void
bfd_elf32_swap_crinfo_out (abfd, in, ex)
bfd *abfd;
Elf32_crinfo *in;
const Elf32_crinfo *in;
Elf32_External_crinfo *ex;
{
unsigned long l;
@ -1968,8 +2001,7 @@ mips_elf_additional_program_headers (abfd)
++ret;
}
if (bfd_get_section_by_name (abfd, ".interp") == NULL
&& bfd_get_section_by_name (abfd, ".dynamic") != NULL
if (bfd_get_section_by_name (abfd, ".dynamic") != NULL
&& bfd_get_section_by_name (abfd, ".mdebug") != NULL)
{
/* We need a PT_MIPS_RTPROC segment. */
@ -2409,6 +2441,8 @@ struct mips_elf_link_hash_table
bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
/* The number of .rtproc entries. */
bfd_size_type procedure_count;
/* The size of the .compact_rel section (if SGI_COMPAT). */
bfd_size_type compact_rel_size;
};
/* Look up an entry in a MIPS ELF linker hash table. */
@ -2494,6 +2528,7 @@ mips_elf_link_hash_table_create (abfd)
for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
ret->procedure_count = 0;
ret->compact_rel_size = 0;
return &ret->root.root;
}
@ -2512,6 +2547,15 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
asection **secp;
bfd_vma *valp;
{
if (SGI_COMPAT (abfd)
&& (abfd->flags & DYNAMIC) != 0
&& strcmp (*namep, "_rld_new_interface") == 0)
{
/* Skip Irix 5 rld entry name. */
*namep = NULL;
return true;
}
switch (sym->st_shndx)
{
case SHN_COMMON:
@ -2549,6 +2593,8 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
*secp = mips_elf_text_section_ptr;
break;
case SHN_MIPS_ACOMMON:
/* Fall through. XXX Can we treat this as allocated data? */
case SHN_MIPS_DATA:
/* This section is used in a shared object. */
if (mips_elf_data_section_ptr == NULL)
@ -3865,7 +3911,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
/* If this is HI16 or GOT16 with an associated LO16,
adjust the addend accordingly. Otherwise, just
relocate. */
if ((r_type != R_MIPS_HI16 || r_type == R_MIPS_GOT16)
if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
|| (rel + 1) >= relend
|| ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
r = _bfd_relocate_contents (howto, input_bfd,
@ -3953,6 +3999,19 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
relocation = 0;
else if (info->shared && ! info->symbolic)
relocation = 0;
else if (strcmp (h->root.root.string, "_DYNAMIC_LINK") == 0)
{
/* If this is a dynamic link, we should have created
a _DYNAMIC_LINK symbol in
mips_elf_create_dynamic_sections. Otherwise, we
should define the symbol with a value of 0.
FIXME: It should probably get into the symbol
table somehow as well. */
BFD_ASSERT (! info->shared);
BFD_ASSERT (bfd_get_section_by_name (output_bfd,
".dynamic") == NULL);
relocation = 0;
}
else
{
if (! ((*info->callbacks->undefined_symbol)
@ -4065,7 +4124,10 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
if (h != NULL)
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_MIPS_REL32);
@ -4075,11 +4137,15 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
{
long indx;
sym = local_syms + r_symndx;
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
sec = local_sections[r_symndx];
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)
@ -4122,6 +4188,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
else
mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
mips_elf_set_cr_dist2to (cptrel, 0);
cptrel.konst = addend;
cr = (scpt->contents
@ -4163,7 +4230,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
{
case R_MIPS_26:
mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD);
cptrel.konst = addend;
/* XXX How should we set dist2to in this case. */
mips_elf_set_cr_dist2to (cptrel, 8);
cptrel.konst = addend + relocation;
cr = scpt->contents + sizeof (Elf32_External_compact_rel);
bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
((Elf32_External_crinfo *) cr
@ -4176,6 +4245,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
case R_MIPS_GPREL32:
mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO);
cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr;
mips_elf_set_cr_dist2to (cptrel, 4);
cr = scpt->contents + sizeof (Elf32_External_compact_rel);
bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
((Elf32_External_crinfo *) cr
@ -4233,7 +4303,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
/* Create dynamic sections when linking against a dynamic object. */
static boolean mips_elf_create_got_section (bfd *, struct bfd_link_info *);
static boolean
mips_elf_create_dynamic_sections (abfd, info)
@ -4284,24 +4353,13 @@ mips_elf_create_dynamic_sections (abfd, info)
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_SECTION;
if (info->shared
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
/* Create .compact_rel section. */
if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
{
flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY;
s = bfd_make_section (abfd, ".compact_rel");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags)
|| ! bfd_set_section_alignment (abfd, s, 2))
return false;
}
s->_raw_size = sizeof (Elf32_compact_rel);
/* We need to create a .compact_rel section. */
if (! mips_elf_create_compact_rel_section (abfd, info))
return false;
/* Change aligments of some sections. */
s = bfd_get_section_by_name (abfd, ".hash");
@ -4321,9 +4379,51 @@ mips_elf_create_dynamic_sections (abfd, info)
bfd_set_section_alignment (abfd, s, 4);
}
if (!info->shared)
{
h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
(bfd_vma) 0, (const char *) NULL, false,
get_elf_backend_data (abfd)->collect,
(struct bfd_link_hash_entry **) &h)))
return false;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_SECTION;
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
return true;
}
/* Create the .compact_rel section. */
static boolean
mips_elf_create_compact_rel_section (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
flagword flags;
register asection *s;
if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
{
flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY;
s = bfd_make_section (abfd, ".compact_rel");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags)
|| ! bfd_set_section_alignment (abfd, s, 2))
return false;
s->_raw_size = sizeof (Elf32_External_compact_rel);
}
return true;
}
/* Create the .got section to hold the global offset table. */
static boolean
@ -4350,9 +4450,7 @@ mips_elf_create_got_section (abfd, info)
/* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
linker script because we don't want to define the symbol if we
are not creating a global offset table. XXX Should this be
defined at the start of the .got section, even if .got section is
accessed by using 16 bit signed offset? */
are not creating a global offset table. */
h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
@ -4407,7 +4505,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
const Elf_Internal_Rela *rel_end;
asection *sgot;
asection *sreloc;
asection *scpt;
if (info->relocateable)
return true;
@ -4419,10 +4516,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
sgot = NULL;
sreloc = NULL;
if (SGI_COMPAT (abfd) && dynobj != NULL)
scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
else
scpt = NULL;
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
@ -4577,19 +4670,21 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
}
sreloc->_raw_size += sizeof (Elf32_External_Rel);
if (scpt != NULL)
scpt->_raw_size += sizeof (Elf32_External_crinfo);
}
if (SGI_COMPAT (abfd))
mips_elf_hash_table (info)->compact_rel_size +=
sizeof (Elf32_External_crinfo);
break;
case R_MIPS_26:
case R_MIPS_GPREL16:
case R_MIPS_LITERAL:
case R_MIPS_GPREL32:
if (scpt != NULL)
scpt->_raw_size += sizeof (Elf32_External_crinfo);
if (SGI_COMPAT (abfd))
mips_elf_hash_table (info)->compact_rel_size +=
sizeof (Elf32_External_crinfo);
break;
default:
@ -4800,9 +4895,10 @@ mips_elf_size_dynamic_sections (output_bfd, info)
of .text section. So put a dummy. XXX */
s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
}
else if (strncmp (name, ".init", 5) != 0
&& (! SGI_COMPAT (output_bfd)
|| strncmp (name, ".compact_rel", 12) != 0))
else if (SGI_COMPAT (output_bfd)
&& strncmp (name, ".compact_rel", 12) == 0)
s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
else if (strncmp (name, ".init", 5) != 0)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@ -4872,7 +4968,7 @@ mips_elf_size_dynamic_sections (output_bfd, info)
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
return false;
if (bfd_get_section_by_name (dynobj, ".conflict"))
if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
{
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
return false;
@ -4890,8 +4986,11 @@ mips_elf_size_dynamic_sections (output_bfd, info)
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0))
return false;
#if 0
/* Time stamps in executable files are a bad idea. */
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0))
return false;
#endif
#if 0 /* FIXME */
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
@ -4932,74 +5031,76 @@ mips_elf_size_dynamic_sections (output_bfd, info)
#endif
}
/* If we are generating a shared library, we generate a section
symbol for each output section. These are local symbols, which
means that they must come first in the dynamic symbol table.
/* If we use dynamic linking, we generate a section symbol for each
output section. These are local symbols, which means that they
must come first in the dynamic symbol table.
That means we must increment the dynamic symbol index of every
other dynamic symbol. */
if (info->shared)
{
const char * const *namep;
int c, i;
bfd_size_type strindex;
struct bfd_strtab_hash *dynstr;
struct mips_got_info *g;
{
const char * const *namep;
unsigned int c, i;
bfd_size_type strindex;
struct bfd_strtab_hash *dynstr;
struct mips_got_info *g;
if (SGI_COMPAT (output_bfd))
{
c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1;
elf_link_hash_traverse (elf_hash_table (info),
mips_elf_adjust_dynindx,
(PTR) &c);
elf_hash_table (info)->dynsymcount += c;
if (elf_hash_table (info)->dynamic_sections_created)
{
if (SGI_COMPAT (output_bfd))
{
c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1;
elf_link_hash_traverse (elf_hash_table (info),
mips_elf_adjust_dynindx,
(PTR) &c);
elf_hash_table (info)->dynsymcount += c;
dynstr = elf_hash_table (info)->dynstr;
BFD_ASSERT (dynstr != NULL);
dynstr = elf_hash_table (info)->dynstr;
BFD_ASSERT (dynstr != NULL);
for (i = 1, namep = mips_elf_dynsym_sec_names;
*namep != NULL;
i++, namep++)
{
s = bfd_get_section_by_name (output_bfd, *namep);
if (s != NULL)
for (i = 1, namep = mips_elf_dynsym_sec_names;
*namep != NULL;
i++, namep++)
{
s = bfd_get_section_by_name (output_bfd, *namep);
if (s != NULL)
elf_section_data (s)->dynindx = i;
strindex = _bfd_stringtab_add (dynstr, *namep, true, false);
if (strindex == (bfd_size_type) -1)
return false;
mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
}
}
else
{
c = bfd_count_sections (output_bfd);
elf_link_hash_traverse (elf_hash_table (info),
mips_elf_adjust_dynindx,
(PTR) &c);
elf_hash_table (info)->dynsymcount += c;
for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
{
elf_section_data (s)->dynindx = i;
/* These symbols will have no names, so we don't need to
fiddle with dynstr_index. */
}
}
}
strindex = _bfd_stringtab_add (dynstr, *namep, true, false);
if (strindex == (bfd_size_type) -1)
return false;
s = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (s != NULL);
BFD_ASSERT (elf_section_data (s) != NULL);
g = (struct mips_got_info *) elf_section_data (s)->tdata;
BFD_ASSERT (g != NULL);
mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
}
}
else
{
c = bfd_count_sections (output_bfd);
elf_link_hash_traverse (elf_hash_table (info),
mips_elf_adjust_dynindx,
(PTR) &c);
elf_hash_table (info)->dynsymcount += c;
for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
{
elf_section_data (s)->dynindx = i;
/* These symbols will have no names, so we don't need to
fiddle with dynstr_index. */
}
}
s = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (s != NULL);
BFD_ASSERT (elf_section_data (s) != NULL);
g = (struct mips_got_info *) elf_section_data (s)->tdata;
BFD_ASSERT (g != NULL);
/* If there are no global got symbols, fake the last symbol so for
safety. */
if (g->global_gotsym)
g->global_gotsym += c;
else
g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
}
/* If there are no global got symbols, fake the last symbol so for
safety. */
if (g->global_gotsym)
g->global_gotsym += c;
else
g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
}
return true;
}
@ -5012,7 +5113,7 @@ mips_elf_adjust_dynindx (h, cparg)
struct elf_link_hash_entry *h;
PTR cparg;
{
int *cp = (int *) cparg;
unsigned int *cp = (unsigned int *) cparg;
if (h->dynindx != -1)
h->dynindx += *cp;
@ -5108,8 +5209,13 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
if (strcmp (name, "_DYNAMIC") == 0
|| strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
sym->st_shndx = SHN_ABS;
if (SGI_COMPAT (output_bfd))
else if (strcmp (name, "_DYNAMIC_LINK") == 0)
{
sym->st_shndx = SHN_ABS;
sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
sym->st_value = 1;
}
else if (SGI_COMPAT (output_bfd))
{
if (strcmp (name, "_gp_disp") == 0)
{
@ -5132,8 +5238,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
sym->st_value = mips_elf_hash_table (info)->procedure_count;
sym->st_shndx = SHN_ABS;
}
if (sym->st_shndx != SHN_UNDEF)
else if (sym->st_shndx != SHN_UNDEF)
{
if (h->type == STT_FUNC)
sym->st_shndx = SHN_MIPS_TEXT;
@ -5321,128 +5426,130 @@ mips_elf_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
if (info->shared)
{
asection *sdynsym;
asection *s;
unsigned int i;
bfd_vma last;
Elf_Internal_Sym sym;
long dindx;
const char *name;
const char * const * namep = mips_elf_dynsym_sec_names;
Elf32_compact_rel cpt;
{
asection *sdynsym;
asection *s;
unsigned int i;
bfd_vma last;
Elf_Internal_Sym sym;
long dindx;
const char *name;
const char * const * namep = mips_elf_dynsym_sec_names;
Elf32_compact_rel cpt;
/* Set up the section symbols for the output sections. SGI set
STT_NOTYPE attribute for these symbols. Should we do so? */
/* Set up the section symbols for the output sections. SGI sets
the STT_NOTYPE attribute for these symbols. Should we do so? */
sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
BFD_ASSERT (sdynsym != NULL);
sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
if (sdynsym != NULL)
{
if (SGI_COMPAT (output_bfd))
{
sym.st_size = 0;
sym.st_name = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
sym.st_other = 0;
if (SGI_COMPAT (output_bfd))
{
sym.st_size = 0;
sym.st_name = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
sym.st_other = 0;
i = 0;
while ((name = *namep++) != NULL)
{
s = bfd_get_section_by_name (output_bfd, name);
if (s != NULL)
{
sym.st_value = s->vma;
dindx = elf_section_data (s)->dynindx;
last = s->vma + s->_raw_size;
}
else
{
sym.st_value = last;
dindx++;
}
i = 0;
while ((name = *namep++) != NULL)
{
s = bfd_get_section_by_name (output_bfd, name);
if (s)
{
sym.st_value = s->vma;
dindx = elf_section_data (s)->dynindx;
last = s->vma + s->_raw_size;
}
else
{
sym.st_value = last;
dindx++;
}
sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO
? SHN_MIPS_TEXT
: SHN_MIPS_DATA);
++i;
sym.st_name =
mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO
? SHN_MIPS_TEXT
: SHN_MIPS_DATA);
++i;
sym.st_name =
mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
bfd_elf32_swap_symbol_out (output_bfd, &sym,
(((Elf32_External_Sym *)
sdynsym->contents)
+ dindx));
}
bfd_elf32_swap_symbol_out (output_bfd, &sym,
(((Elf32_External_Sym *)
sdynsym->contents)
+ dindx));
}
/* Set the sh_info field of the output .dynsym section to
the index of the first global symbol. */
elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
SIZEOF_MIPS_DYNSYM_SECNAMES;
}
else
{
sym.st_size = 0;
sym.st_name = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
sym.st_other = 0;
/* Set the sh_info field of the output .dynsym section to
the index of the first global symbol. */
elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
SIZEOF_MIPS_DYNSYM_SECNAMES;
}
else
{
sym.st_size = 0;
sym.st_name = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
sym.st_other = 0;
for (s = output_bfd->sections; s != NULL; s = s->next)
{
int indx;
for (s = output_bfd->sections; s != NULL; s = s->next)
{
int indx;
sym.st_value = s->vma;
sym.st_value = s->vma;
indx = elf_section_data (s)->this_idx;
BFD_ASSERT (indx > 0);
sym.st_shndx = indx;
indx = elf_section_data (s)->this_idx;
BFD_ASSERT (indx > 0);
sym.st_shndx = indx;
bfd_elf32_swap_symbol_out (output_bfd, &sym,
(((Elf32_External_Sym *)
sdynsym->contents)
+ elf_section_data (s)->dynindx));
}
bfd_elf32_swap_symbol_out (output_bfd, &sym,
(((Elf32_External_Sym *)
sdynsym->contents)
+ elf_section_data (s)->dynindx));
}
/* Set the sh_info field of the output .dynsym section to
the index of the first global symbol. */
elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
bfd_count_sections (output_bfd) + 1;
}
}
/* Set the sh_info field of the output .dynsym section to
the index of the first global symbol. */
elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
bfd_count_sections (output_bfd) + 1;
}
if (SGI_COMPAT (output_bfd))
{
/* Write .compact_rel section out. */
s = bfd_get_section_by_name (dynobj, ".compact_rel");
if (s != NULL)
{
cpt.id1 = 1;
cpt.num = s->reloc_count;
cpt.id2 = 2;
cpt.offset = (s->output_section->filepos
+ sizeof (Elf32_External_compact_rel));
cpt.reserved0 = 0;
cpt.reserved1 = 0;
bfd_elf32_swap_compact_rel_out (output_bfd, &cpt,
((Elf32_External_compact_rel *)
s->contents));
if (SGI_COMPAT (output_bfd))
{
/* Write .compact_rel section out. */
s = bfd_get_section_by_name (dynobj, ".compact_rel");
BFD_ASSERT (s != NULL);
/* Clean up a dummy stub function entry in .text. */
s = bfd_get_section_by_name (dynobj, ".stub");
if (s != NULL)
{
file_ptr dummy_offset;
cpt.id1 = 1;
cpt.num = s->reloc_count;
cpt.id2 = 2;
cpt.offset = (s->output_section->filepos
+ sizeof (Elf32_External_compact_rel));
cpt.reserved0 = 0;
cpt.reserved1 = 0;
bfd_elf32_swap_compact_rel_out (output_bfd, &cpt,
((Elf32_External_compact_rel *)
s->contents));
BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
memset (s->contents + dummy_offset, 0,
MIPS_FUNCTION_STUB_SIZE);
}
}
}
/* Clean up a dummy stub function entry in .text. */
s = bfd_get_section_by_name (dynobj, ".stub");
if (s != NULL)
{
file_ptr dummy_offset;
BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
memset (s->contents + dummy_offset, 0, MIPS_FUNCTION_STUB_SIZE);
}
}
/* Clean up a first relocation in .rel.dyn. */
s = bfd_get_section_by_name (dynobj, ".rel.dyn");
if (s)
memset (s->contents, 0, sizeof (Elf32_External_Rel));
}
/* Clean up a first relocation in .rel.dyn. */
s = bfd_get_section_by_name (dynobj, ".rel.dyn");
if (s != NULL)
memset (s->contents, 0, sizeof (Elf32_External_Rel));
}
return true;
}
@ -5712,7 +5819,6 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap =
#define bfd_elf32_bfd_merge_private_bfd_data \
mips_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags mips_elf_set_private_flags
#define elf_backend_relocate_section mips_elf_relocate_section
#define elf_backend_add_symbol_hook mips_elf_add_symbol_hook
#define elf_backend_create_dynamic_sections \
mips_elf_create_dynamic_sections

View File

@ -22,9 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
/* start-sanitize-v8plus */
#include "elf/sparc.h"
/* end-sanitize-v8plus */
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
@ -47,15 +45,11 @@ static boolean elf32_sparc_finish_dynamic_symbol
Elf_Internal_Sym *));
static boolean elf32_sparc_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
/* start-sanitize-v8plus */
static boolean elf32_sparc_set_private_flags PARAMS ((bfd *, flagword));
static boolean elf32_sparc_copy_private_bfd_data PARAMS ((bfd *, bfd *));
static boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *));
static boolean elf32_sparc_object_p
PARAMS ((bfd *));
static void elf32_sparc_final_write_processing
PARAMS ((bfd *, boolean));
/* end-sanitize-v8plus */
enum reloc_type
{
@ -914,6 +908,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|| (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_SPARC_8
|| r_type == R_SPARC_16
@ -1131,7 +1128,10 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
outrel.r_offset = (rel->r_offset
+ input_section->output_section->vma
+ input_section->output_offset);
if (h != NULL)
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);
@ -1148,8 +1148,15 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
{
long indx;
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
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)
@ -1491,45 +1498,13 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
return true;
}
/* start-sanitize-v8plus */
/* Function to set e_flags. */
/* Functions for dealing with the e_flags field.
static boolean
elf32_sparc_set_private_flags (abfd, flags)
bfd *abfd;
flagword flags;
{
/* Once the flags have been set, you (apparently) can't change them. */
BFD_ASSERT (!elf_flags_init (abfd)
|| elf_elfheader (abfd)->e_flags == flags);
elf_elfheader (abfd)->e_flags = flags;
elf_flags_init (abfd) = true;
return true;
}
/* Copy backend specific data from one object module to another. */
static boolean
elf32_sparc_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)
return true;
/* Once the flags have been set, you (apparently) can't change them. */
BFD_ASSERT (!elf_flags_init (obfd)
|| elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
elf_flags_init (obfd) = true;
return true;
}
We don't define set_private_flags or copy_private_bfd_data because
the only currently defined values are based on the bfd mach number,
so we use the latter instead and defer setting e_flags until the
file is written out. */
/* Merge backend specific data from an object file to the output
object file when linking. */
@ -1539,8 +1514,6 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
flagword old_flags;
flagword new_flags;
boolean error;
/* This function is selected based on the input vector. We only
@ -1551,6 +1524,13 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
error = false;
#if 0
/* ??? The native linker doesn't do this so we can't (otherwise gcc would
have to know which linker is being used). Instead, the native linker
bumps up the architecture level when it has to. However, I still think
warnings like these are good, so it would be nice to have them turned on
by some option. */
/* If the output machine is normal sparc, we can't allow v9 input files. */
if (bfd_get_mach (obfd) == bfd_mach_sparc
&& (bfd_get_mach (ibfd) == bfd_mach_sparc_v8plus
@ -1570,30 +1550,17 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
("%s: compiled for a v8plusa system and target is v8plus",
bfd_get_filename (ibfd));
}
new_flags = elf_elfheader (ibfd)->e_flags;
old_flags = elf_elfheader (obfd)->e_flags;
if (!elf_flags_init (obfd)) /* First call, no flags set */
#else
if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)
{
elf_flags_init (obfd) = true;
elf_elfheader (obfd)->e_flags = new_flags;
}
else if (new_flags == old_flags) /* Compatible flags are ok */
;
else /* Potentially incompatible flags */
{
new_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1);
old_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1);
/* Warn about any other mismatches */
if (new_flags != old_flags)
{
error = true;
(*_bfd_error_handler)
("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
bfd_get_filename (ibfd), (long) new_flags, (long) old_flags);
}
error = true;
(*_bfd_error_handler)
("%s: compiled for a 64 bit system and target is 32 bit",
bfd_get_filename (ibfd));
}
else if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));
#endif
if (error)
{
@ -1611,7 +1578,16 @@ elf32_sparc_object_p (abfd)
bfd *abfd;
{
if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v8plus);
{
if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
bfd_mach_sparc_v8plusa);
else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS)
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
bfd_mach_sparc_v8plus);
else
return false;
}
else
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
}
@ -1624,24 +1600,30 @@ elf32_sparc_final_write_processing (abfd, linker)
bfd *abfd;
boolean linker;
{
if (bfd_get_mach (abfd) == bfd_mach_sparc_v8plus)
switch (bfd_get_mach (abfd))
{
case bfd_mach_sparc :
break; /* nothing to do */
case bfd_mach_sparc_v8plus :
elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
#if 0 /* FIXME: Not sure how to handle EF_SPARC_32PLUS_US1 */
elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
#endif
elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS;
break;
case bfd_mach_sparc_v8plusa :
elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
break;
default :
abort ();
}
}
/* end-sanitize-v8plus */
#define TARGET_BIG_SYM bfd_elf32_sparc_vec
#define TARGET_BIG_NAME "elf32-sparc"
#define ELF_ARCH bfd_arch_sparc
#define ELF_MACHINE_CODE EM_SPARC
/* start-sanitize-v8plus */
#define ELF_MACHINE_ALT1 EM_SPARC32PLUS
/* end-sanitize-v8plus */
#define ELF_MAXPAGESIZE 0x10000
#define elf_backend_create_dynamic_sections \
_bfd_elf_create_dynamic_sections
@ -1655,16 +1637,11 @@ elf32_sparc_final_write_processing (abfd, linker)
elf32_sparc_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
elf32_sparc_finish_dynamic_sections
/* start-sanitize-v8plus */
#define bfd_elf32_bfd_set_private_flags elf32_sparc_set_private_flags
#define bfd_elf32_bfd_copy_private_bfd_data \
elf32_sparc_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data \
elf32_sparc_merge_private_bfd_data
#define elf_backend_object_p elf32_sparc_object_p
#define elf_backend_final_write_processing \
elf32_sparc_final_write_processing
/* end-sanitize-v8plus */
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1