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
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
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
#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
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);
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;
++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. */
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. */
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;
}
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:
*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)
/* 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,
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)
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);
{
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)
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
{
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
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
#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)
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))
- 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))
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
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");
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
/* 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,
const Elf_Internal_Rela *rel_end;
asection *sgot;
asection *sreloc;
- asection *scpt;
if (info->relocateable)
return true;
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++)
}
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:
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;
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;
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))
#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;
-
- 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);
-
- 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;
+ {
+ const char * const *namep;
+ unsigned int c, i;
+ bfd_size_type strindex;
+ struct bfd_strtab_hash *dynstr;
+ struct mips_got_info *g;
+
+ 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);
+
+ 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;
+ 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;
+ 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. */
- }
- }
+ 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);
+ 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;
}
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;
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)
{
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;
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;
-
- /* Set up the section symbols for the output sections. SGI set
- STT_NOTYPE attribute for these symbols. Should we do so? */
-
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (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;
-
- 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];
+ {
+ 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 sets
+ the STT_NOTYPE attribute for these symbols. Should we do so? */
+
+ 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;
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (((Elf32_External_Sym *)
- sdynsym->contents)
- + dindx));
- }
+ 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++;
+ }
- /* 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;
+ 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));
+ }
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
+ /* 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;
- sym.st_value = s->vma;
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
+ sym.st_value = s->vma;
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (((Elf32_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
- }
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
- /* 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;
- }
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ (((Elf32_External_Sym *)
+ sdynsym->contents)
+ + elf_section_data (s)->dynindx));
+ }
- if (SGI_COMPAT (output_bfd))
- {
- /* Write .compact_rel section out. */
- s = bfd_get_section_by_name (dynobj, ".compact_rel");
- BFD_ASSERT (s != NULL);
+ /* 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;
+ }
+ }
- 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));
-
- /* Clean up a dummy stub function entry in .text. */
- s = bfd_get_section_by_name (dynobj, ".stub");
- if (s != NULL)
- {
- file_ptr dummy_offset;
+ 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));
+
+ /* 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);
- }
- }
+ 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;
}
#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
#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));
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
{
|| (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
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);
{
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)
return true;
}
-/* start-sanitize-v8plus */
\f
-/* Function to set e_flags. */
-
-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;
+/* Functions for dealing with the e_flags field.
- /* 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. */
bfd *ibfd;
bfd *obfd;
{
- flagword old_flags;
- flagword new_flags;
boolean error;
/* This function is selected based on the input vector. We only
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
("%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)
{
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);
}
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 */
\f
#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
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