* 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> 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 * elflink.h (elf_link_add_object_symbols): Only set weakdef to a
real defined symbol, not to a weak defined symbol. real defined symbol, not to a weak defined symbol.

View File

@ -1,5 +1,5 @@
/* Intel 80386/80486-specific support for 32-bit ELF /* 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. 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 || (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)) & ELF_LINK_HASH_DEF_REGULAR) == 0))
|| (info->shared || (info->shared
&& (! info->symbolic
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)
&& (r_type == R_386_32 && (r_type == R_386_32
|| r_type == R_386_PC32) || r_type == R_386_PC32)
&& (input_section->flags & SEC_ALLOC) != 0)) && (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: case R_386_PC32:
if (info->shared if (info->shared
&& (input_section->flags & SEC_ALLOC) != 0 && (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; Elf_Internal_Rel outrel;
boolean relocate;
/* When generating a shared object, these relocations /* When generating a shared object, these relocations
are copied into the output file to be resolved at run 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) if (r_type == R_386_PC32)
{ {
BFD_ASSERT (h != NULL && h->dynindx != -1); BFD_ASSERT (h != NULL && h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32); outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
} }
else else
{ {
if (h == NULL) if (h == NULL
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); || (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 else
{ {
BFD_ASSERT (h->dynindx != -1); BFD_ASSERT (h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32); 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 not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes need to include the symbol value so that it becomes
an addend for the dynamic reloc. */ an addend for the dynamic reloc. */
if (h != NULL) if (! relocate)
continue; continue;
} }

View File

@ -1,5 +1,5 @@
/* Motorola 68k series support for 32-bit ELF /* 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. 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 || (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)) & ELF_LINK_HASH_DEF_REGULAR) == 0))
|| (info->shared || (info->shared
&& (! info->symbolic
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)
&& (input_section->flags & SEC_ALLOC) != 0 && (input_section->flags & SEC_ALLOC) != 0
&& (r_type == R_68K_8 && (r_type == R_68K_8
|| r_type == R_68K_16 || 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 outrel.r_offset = (rel->r_offset
+ input_section->output_section->vma + input_section->output_section->vma
+ input_section->output_offset); + 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); BFD_ASSERT (h->dynindx != -1);
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 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; long indx;
sym = local_syms + r_symndx; if (h == NULL)
sec = local_sections[r_symndx];
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); else
{
sec = local_sections[r_symndx]; 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)) if (sec != NULL && bfd_is_abs_section (sec))
indx = 0; indx = 0;
else if (sec == NULL || sec->owner == NULL) 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)); PARAMS ((bfd *, bfd_reloc_code_real_type));
static void mips_info_to_howto_rel static void mips_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_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_sym_is_global PARAMS ((bfd *, asymbol *));
static boolean mips_elf_object_p PARAMS ((bfd *)); static boolean mips_elf_object_p PARAMS ((bfd *));
static boolean mips_elf_create_procedure_table 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 boolean mips_elf_modify_segment_map PARAMS ((bfd *));
static void mips_elf_final_write_processing static void mips_elf_final_write_processing
PARAMS ((bfd *, boolean)); 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 static boolean mips_elf_section_from_shdr
PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
static boolean mips_elf_fake_sections static boolean mips_elf_fake_sections
@ -125,11 +132,32 @@ static boolean mips_elf_adjust_dynindx
static boolean mips_elf_relocate_section static boolean mips_elf_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 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 static boolean mips_elf_add_symbol_hook
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
const char **, flagword *, asection **, bfd_vma *)); const char **, flagword *, asection **, bfd_vma *));
static bfd_reloc_status_type mips_elf_final_gp static bfd_reloc_status_type mips_elf_final_gp
PARAMS ((bfd *, asymbol *, boolean, char **)); 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 /* This is true for Irix 5 executables, false for normal MIPS ELF ABI
executables. FIXME: At the moment, we default to always generating 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_dist2to(x,v) ((x).dist2to = (v))
#define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2) #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 */ #define USE_REL 1 /* MIPS uses REL relocations instead of RELA */
enum reloc_type enum reloc_type
@ -1327,7 +1360,7 @@ bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
static void static void
bfd_elf32_swap_compact_rel_out (abfd, in, ex) bfd_elf32_swap_compact_rel_out (abfd, in, ex)
bfd *abfd; bfd *abfd;
Elf32_compact_rel *in; const Elf32_compact_rel *in;
Elf32_External_compact_rel *ex; Elf32_External_compact_rel *ex;
{ {
bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1); 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 static void
bfd_elf32_swap_crinfo_out (abfd, in, ex) bfd_elf32_swap_crinfo_out (abfd, in, ex)
bfd *abfd; bfd *abfd;
Elf32_crinfo *in; const Elf32_crinfo *in;
Elf32_External_crinfo *ex; Elf32_External_crinfo *ex;
{ {
unsigned long l; unsigned long l;
@ -1968,8 +2001,7 @@ mips_elf_additional_program_headers (abfd)
++ret; ++ret;
} }
if (bfd_get_section_by_name (abfd, ".interp") == NULL if (bfd_get_section_by_name (abfd, ".dynamic") != NULL
&& bfd_get_section_by_name (abfd, ".dynamic") != NULL
&& bfd_get_section_by_name (abfd, ".mdebug") != NULL) && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
{ {
/* We need a PT_MIPS_RTPROC segment. */ /* 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]; bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
/* The number of .rtproc entries. */ /* The number of .rtproc entries. */
bfd_size_type procedure_count; 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. */ /* 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++) for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
ret->dynsym_sec_strindex[i] = (bfd_size_type) -1; ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
ret->procedure_count = 0; ret->procedure_count = 0;
ret->compact_rel_size = 0;
return &ret->root.root; return &ret->root.root;
} }
@ -2512,6 +2547,15 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
asection **secp; asection **secp;
bfd_vma *valp; 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) switch (sym->st_shndx)
{ {
case SHN_COMMON: 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; *secp = mips_elf_text_section_ptr;
break; break;
case SHN_MIPS_ACOMMON:
/* Fall through. XXX Can we treat this as allocated data? */
case SHN_MIPS_DATA: case SHN_MIPS_DATA:
/* This section is used in a shared object. */ /* This section is used in a shared object. */
if (mips_elf_data_section_ptr == NULL) 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, /* If this is HI16 or GOT16 with an associated LO16,
adjust the addend accordingly. Otherwise, just adjust the addend accordingly. Otherwise, just
relocate. */ 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 || (rel + 1) >= relend
|| ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16) || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
r = _bfd_relocate_contents (howto, input_bfd, r = _bfd_relocate_contents (howto, input_bfd,
@ -3953,6 +3999,19 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
relocation = 0; relocation = 0;
else if (info->shared && ! info->symbolic) else if (info->shared && ! info->symbolic)
relocation = 0; 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 else
{ {
if (! ((*info->callbacks->undefined_symbol) 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); 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); BFD_ASSERT (h->dynindx != -1);
outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_REL32); 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; long indx;
sym = local_syms + r_symndx; if (h == NULL)
sec = local_sections[r_symndx];
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); else
{
sec = local_sections[r_symndx]; 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)) if (sec != NULL && bfd_is_abs_section (sec))
indx = 0; indx = 0;
else if (sec == NULL || sec->owner == NULL) 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); mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
else else
mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
mips_elf_set_cr_dist2to (cptrel, 0);
cptrel.konst = addend; cptrel.konst = addend;
cr = (scpt->contents cr = (scpt->contents
@ -4163,7 +4230,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
{ {
case R_MIPS_26: case R_MIPS_26:
mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD); 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); cr = scpt->contents + sizeof (Elf32_External_compact_rel);
bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
((Elf32_External_crinfo *) cr ((Elf32_External_crinfo *) cr
@ -4176,6 +4245,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
case R_MIPS_GPREL32: case R_MIPS_GPREL32:
mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO); mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO);
cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr; cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr;
mips_elf_set_cr_dist2to (cptrel, 4);
cr = scpt->contents + sizeof (Elf32_External_compact_rel); cr = scpt->contents + sizeof (Elf32_External_compact_rel);
bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
((Elf32_External_crinfo *) cr ((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" #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
/* Create dynamic sections when linking against a dynamic object. */ /* Create dynamic sections when linking against a dynamic object. */
static boolean mips_elf_create_got_section (bfd *, struct bfd_link_info *);
static boolean static boolean
mips_elf_create_dynamic_sections (abfd, info) 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->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_SECTION; h->type = STT_SECTION;
if (info->shared if (! bfd_elf32_link_record_dynamic_symbol (info, h))
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
return false; return false;
} }
/* Create .compact_rel section. */ /* We need to create a .compact_rel section. */
if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) if (! mips_elf_create_compact_rel_section (abfd, info))
{ return false;
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);
/* Change aligments of some sections. */ /* Change aligments of some sections. */
s = bfd_get_section_by_name (abfd, ".hash"); 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); 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; 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. */ /* Create the .got section to hold the global offset table. */
static boolean 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 /* 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 linker script because we don't want to define the symbol if we
are not creating a global offset table. XXX Should this be are not creating a global offset table. */
defined at the start of the .got section, even if .got section is
accessed by using 16 bit signed offset? */
h = NULL; h = NULL;
if (! (_bfd_generic_link_add_one_symbol if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (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; const Elf_Internal_Rela *rel_end;
asection *sgot; asection *sgot;
asection *sreloc; asection *sreloc;
asection *scpt;
if (info->relocateable) if (info->relocateable)
return true; return true;
@ -4419,10 +4516,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
sgot = NULL; sgot = NULL;
sreloc = 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; rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++) 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); 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; break;
case R_MIPS_26: case R_MIPS_26:
case R_MIPS_GPREL16: case R_MIPS_GPREL16:
case R_MIPS_LITERAL: case R_MIPS_LITERAL:
case R_MIPS_GPREL32: case R_MIPS_GPREL32:
if (scpt != NULL) if (SGI_COMPAT (abfd))
scpt->_raw_size += sizeof (Elf32_External_crinfo); mips_elf_hash_table (info)->compact_rel_size +=
sizeof (Elf32_External_crinfo);
break; break;
default: default:
@ -4800,9 +4895,10 @@ mips_elf_size_dynamic_sections (output_bfd, info)
of .text section. So put a dummy. XXX */ of .text section. So put a dummy. XXX */
s->_raw_size += MIPS_FUNCTION_STUB_SIZE; s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
} }
else if (strncmp (name, ".init", 5) != 0 else if (SGI_COMPAT (output_bfd)
&& (! SGI_COMPAT (output_bfd) && strncmp (name, ".compact_rel", 12) == 0)
|| 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. */ /* It's not one of our sections, so don't allocate space. */
continue; continue;
@ -4872,7 +4968,7 @@ mips_elf_size_dynamic_sections (output_bfd, info)
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0)) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
return false; 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)) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
return false; 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)) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0))
return false; 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)) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0))
return false; return false;
#endif
#if 0 /* FIXME */ #if 0 /* FIXME */
if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0)) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
@ -4932,74 +5031,76 @@ mips_elf_size_dynamic_sections (output_bfd, info)
#endif #endif
} }
/* If we are generating a shared library, we generate a section /* If we use dynamic linking, we generate a section symbol for each
symbol for each output section. These are local symbols, which output section. These are local symbols, which means that they
means that they must come first in the dynamic symbol table. must come first in the dynamic symbol table.
That means we must increment the dynamic symbol index of every That means we must increment the dynamic symbol index of every
other dynamic symbol. */ other dynamic symbol. */
if (info->shared) {
{ const char * const *namep;
const char * const *namep; unsigned int c, i;
int c, i; bfd_size_type strindex;
bfd_size_type strindex; struct bfd_strtab_hash *dynstr;
struct bfd_strtab_hash *dynstr; struct mips_got_info *g;
struct mips_got_info *g;
if (SGI_COMPAT (output_bfd)) if (elf_hash_table (info)->dynamic_sections_created)
{ {
c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1; if (SGI_COMPAT (output_bfd))
elf_link_hash_traverse (elf_hash_table (info), {
mips_elf_adjust_dynindx, c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1;
(PTR) &c); elf_link_hash_traverse (elf_hash_table (info),
elf_hash_table (info)->dynsymcount += c; mips_elf_adjust_dynindx,
(PTR) &c);
elf_hash_table (info)->dynsymcount += c;
dynstr = elf_hash_table (info)->dynstr; dynstr = elf_hash_table (info)->dynstr;
BFD_ASSERT (dynstr != NULL); BFD_ASSERT (dynstr != NULL);
for (i = 1, namep = mips_elf_dynsym_sec_names; for (i = 1, namep = mips_elf_dynsym_sec_names;
*namep != NULL; *namep != NULL;
i++, namep++) i++, namep++)
{ {
s = bfd_get_section_by_name (output_bfd, *namep); s = bfd_get_section_by_name (output_bfd, *namep);
if (s != NULL) 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; 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); s = bfd_get_section_by_name (dynobj, ".got");
if (strindex == (bfd_size_type) -1) BFD_ASSERT (s != NULL);
return false; 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; /* If there are no global got symbols, fake the last symbol so for
} safety. */
} if (g->global_gotsym)
else g->global_gotsym += c;
{ else
c = bfd_count_sections (output_bfd); g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
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;
}
return true; return true;
} }
@ -5012,7 +5113,7 @@ mips_elf_adjust_dynindx (h, cparg)
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
PTR cparg; PTR cparg;
{ {
int *cp = (int *) cparg; unsigned int *cp = (unsigned int *) cparg;
if (h->dynindx != -1) if (h->dynindx != -1)
h->dynindx += *cp; h->dynindx += *cp;
@ -5108,8 +5209,13 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
if (strcmp (name, "_DYNAMIC") == 0 if (strcmp (name, "_DYNAMIC") == 0
|| strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
sym->st_shndx = SHN_ABS; sym->st_shndx = SHN_ABS;
else if (strcmp (name, "_DYNAMIC_LINK") == 0)
if (SGI_COMPAT (output_bfd)) {
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) 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_value = mips_elf_hash_table (info)->procedure_count;
sym->st_shndx = SHN_ABS; sym->st_shndx = SHN_ABS;
} }
else if (sym->st_shndx != SHN_UNDEF)
if (sym->st_shndx != SHN_UNDEF)
{ {
if (h->type == STT_FUNC) if (h->type == STT_FUNC)
sym->st_shndx = SHN_MIPS_TEXT; 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; elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
if (info->shared) {
{ asection *sdynsym;
asection *sdynsym; asection *s;
asection *s; unsigned int i;
unsigned int i; bfd_vma last;
bfd_vma last; Elf_Internal_Sym sym;
Elf_Internal_Sym sym; long dindx;
long dindx; const char *name;
const char *name; const char * const * namep = mips_elf_dynsym_sec_names;
const char * const * namep = mips_elf_dynsym_sec_names; Elf32_compact_rel cpt;
Elf32_compact_rel cpt;
/* Set up the section symbols for the output sections. SGI set /* Set up the section symbols for the output sections. SGI sets
STT_NOTYPE attribute for these symbols. Should we do so? */ the STT_NOTYPE attribute for these symbols. Should we do so? */
sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
BFD_ASSERT (sdynsym != NULL); 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)) i = 0;
{ while ((name = *namep++) != NULL)
sym.st_size = 0; {
sym.st_name = 0; s = bfd_get_section_by_name (output_bfd, name);
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); if (s != NULL)
sym.st_other = 0; {
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; sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO
while ((name = *namep++) != NULL) ? SHN_MIPS_TEXT
{ : SHN_MIPS_DATA);
s = bfd_get_section_by_name (output_bfd, name); ++i;
if (s) sym.st_name =
{ mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
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 bfd_elf32_swap_symbol_out (output_bfd, &sym,
? SHN_MIPS_TEXT (((Elf32_External_Sym *)
: SHN_MIPS_DATA); sdynsym->contents)
++i; + dindx));
sym.st_name = }
mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
bfd_elf32_swap_symbol_out (output_bfd, &sym, /* Set the sh_info field of the output .dynsym section to
(((Elf32_External_Sym *) the index of the first global symbol. */
sdynsym->contents) elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ dindx)); 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 for (s = output_bfd->sections; s != NULL; s = s->next)
the index of the first global symbol. */ {
elf_section_data (sdynsym->output_section)->this_hdr.sh_info = int indx;
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) sym.st_value = s->vma;
{
int indx;
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_elf32_swap_symbol_out (output_bfd, &sym,
BFD_ASSERT (indx > 0); (((Elf32_External_Sym *)
sym.st_shndx = indx; sdynsym->contents)
+ elf_section_data (s)->dynindx));
}
bfd_elf32_swap_symbol_out (output_bfd, &sym, /* Set the sh_info field of the output .dynsym section to
(((Elf32_External_Sym *) the index of the first global symbol. */
sdynsym->contents) elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ elf_section_data (s)->dynindx)); bfd_count_sections (output_bfd) + 1;
} }
}
/* Set the sh_info field of the output .dynsym section to if (SGI_COMPAT (output_bfd))
the index of the first global symbol. */ {
elf_section_data (sdynsym->output_section)->this_hdr.sh_info = /* Write .compact_rel section out. */
bfd_count_sections (output_bfd) + 1; 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)) /* Clean up a dummy stub function entry in .text. */
{ s = bfd_get_section_by_name (dynobj, ".stub");
/* Write .compact_rel section out. */ if (s != NULL)
s = bfd_get_section_by_name (dynobj, ".compact_rel"); {
BFD_ASSERT (s != NULL); file_ptr dummy_offset;
cpt.id1 = 1; BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
cpt.num = s->reloc_count; dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
cpt.id2 = 2; memset (s->contents + dummy_offset, 0,
cpt.offset = (s->output_section->filepos MIPS_FUNCTION_STUB_SIZE);
+ 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));
/* Clean up a dummy stub function entry in .text. */ /* Clean up a first relocation in .rel.dyn. */
s = bfd_get_section_by_name (dynobj, ".stub"); s = bfd_get_section_by_name (dynobj, ".rel.dyn");
if (s != NULL) if (s != NULL)
{ memset (s->contents, 0, sizeof (Elf32_External_Rel));
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));
}
return true; 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 \ #define bfd_elf32_bfd_merge_private_bfd_data \
mips_elf_merge_private_bfd_data mips_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags mips_elf_set_private_flags #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_add_symbol_hook mips_elf_add_symbol_hook
#define elf_backend_create_dynamic_sections \ #define elf_backend_create_dynamic_sections \
mips_elf_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 "bfdlink.h"
#include "libbfd.h" #include "libbfd.h"
#include "elf-bfd.h" #include "elf-bfd.h"
/* start-sanitize-v8plus */
#include "elf/sparc.h" #include "elf/sparc.h"
/* end-sanitize-v8plus */
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type)); PARAMS ((bfd *, bfd_reloc_code_real_type));
@ -47,15 +45,11 @@ static boolean elf32_sparc_finish_dynamic_symbol
Elf_Internal_Sym *)); Elf_Internal_Sym *));
static boolean elf32_sparc_finish_dynamic_sections static boolean elf32_sparc_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *)); 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_merge_private_bfd_data PARAMS ((bfd *, bfd *));
static boolean elf32_sparc_object_p static boolean elf32_sparc_object_p
PARAMS ((bfd *)); PARAMS ((bfd *));
static void elf32_sparc_final_write_processing static void elf32_sparc_final_write_processing
PARAMS ((bfd *, boolean)); PARAMS ((bfd *, boolean));
/* end-sanitize-v8plus */
enum reloc_type enum reloc_type
{ {
@ -914,6 +908,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|| (h->elf_link_hash_flags || (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)) & ELF_LINK_HASH_DEF_REGULAR) == 0))
|| (info->shared || (info->shared
&& (! info->symbolic
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)
&& (input_section->flags & SEC_ALLOC) != 0 && (input_section->flags & SEC_ALLOC) != 0
&& (r_type == R_SPARC_8 && (r_type == R_SPARC_8
|| r_type == R_SPARC_16 || 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 outrel.r_offset = (rel->r_offset
+ input_section->output_section->vma + input_section->output_section->vma
+ input_section->output_offset); + 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); BFD_ASSERT (h->dynindx != -1);
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 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; long indx;
sym = local_syms + r_symndx; if (h == NULL)
sec = local_sections[r_symndx]; 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)) if (sec != NULL && bfd_is_abs_section (sec))
indx = 0; indx = 0;
else if (sec == NULL || sec->owner == NULL) else if (sec == NULL || sec->owner == NULL)
@ -1491,45 +1498,13 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
return true; return true;
} }
/* start-sanitize-v8plus */
/* Function to set e_flags. */ /* Functions for dealing with the e_flags field.
static boolean We don't define set_private_flags or copy_private_bfd_data because
elf32_sparc_set_private_flags (abfd, flags) the only currently defined values are based on the bfd mach number,
bfd *abfd; so we use the latter instead and defer setting e_flags until the
flagword flags; file is written out. */
{
/* 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;
}
/* Merge backend specific data from an object file to the output /* Merge backend specific data from an object file to the output
object file when linking. */ object file when linking. */
@ -1539,8 +1514,6 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd; bfd *ibfd;
bfd *obfd; bfd *obfd;
{ {
flagword old_flags;
flagword new_flags;
boolean error; boolean error;
/* This function is selected based on the input vector. We only /* 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; 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 the output machine is normal sparc, we can't allow v9 input files. */
if (bfd_get_mach (obfd) == bfd_mach_sparc if (bfd_get_mach (obfd) == bfd_mach_sparc
&& (bfd_get_mach (ibfd) == bfd_mach_sparc_v8plus && (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", ("%s: compiled for a v8plusa system and target is v8plus",
bfd_get_filename (ibfd)); bfd_get_filename (ibfd));
} }
#else
new_flags = elf_elfheader (ibfd)->e_flags; if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)
old_flags = elf_elfheader (obfd)->e_flags;
if (!elf_flags_init (obfd)) /* First call, no flags set */
{ {
elf_flags_init (obfd) = true; error = true;
elf_elfheader (obfd)->e_flags = new_flags; (*_bfd_error_handler)
} ("%s: compiled for a 64 bit system and target is 32 bit",
else if (new_flags == old_flags) /* Compatible flags are ok */ bfd_get_filename (ibfd));
;
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);
}
} }
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) if (error)
{ {
@ -1611,7 +1578,16 @@ elf32_sparc_object_p (abfd)
bfd *abfd; bfd *abfd;
{ {
if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) 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 else
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); 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; bfd *abfd;
boolean linker; 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; 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; elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
#endif
elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS; 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_SYM bfd_elf32_sparc_vec
#define TARGET_BIG_NAME "elf32-sparc" #define TARGET_BIG_NAME "elf32-sparc"
#define ELF_ARCH bfd_arch_sparc #define ELF_ARCH bfd_arch_sparc
#define ELF_MACHINE_CODE EM_SPARC #define ELF_MACHINE_CODE EM_SPARC
/* start-sanitize-v8plus */
#define ELF_MACHINE_ALT1 EM_SPARC32PLUS #define ELF_MACHINE_ALT1 EM_SPARC32PLUS
/* end-sanitize-v8plus */
#define ELF_MAXPAGESIZE 0x10000 #define ELF_MAXPAGESIZE 0x10000
#define elf_backend_create_dynamic_sections \ #define elf_backend_create_dynamic_sections \
_bfd_elf_create_dynamic_sections _bfd_elf_create_dynamic_sections
@ -1655,16 +1637,11 @@ elf32_sparc_final_write_processing (abfd, linker)
elf32_sparc_finish_dynamic_symbol elf32_sparc_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \ #define elf_backend_finish_dynamic_sections \
elf32_sparc_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 \ #define bfd_elf32_bfd_merge_private_bfd_data \
elf32_sparc_merge_private_bfd_data elf32_sparc_merge_private_bfd_data
#define elf_backend_object_p elf32_sparc_object_p #define elf_backend_object_p elf32_sparc_object_p
#define elf_backend_final_write_processing \ #define elf_backend_final_write_processing \
elf32_sparc_final_write_processing elf32_sparc_final_write_processing
/* end-sanitize-v8plus */
#define elf_backend_want_got_plt 0 #define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 0 #define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1 #define elf_backend_want_plt_sym 1