#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto)
#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel)
#define elf_new_section_hook NAME(bfd_elf,new_section_hook)
-#define write_relocs NAME(bfd_elf,_write_relocs)
#define elf_find_section NAME(bfd_elf,find_section)
#define elf_bfd_link_add_symbols NAME(bfd_elf,bfd_link_add_symbols)
#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry)
static boolean elf_compute_section_file_positions
PARAMS ((bfd *, struct bfd_link_info *));
static boolean prep_headers PARAMS ((bfd *));
+static void write_relocs PARAMS ((bfd *, asection *, PTR));
static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
static boolean assign_section_numbers PARAMS ((bfd *));
static file_ptr align_file_position PARAMS ((file_ptr));
#ifdef DEBUG
static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *));
static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *));
+static char *elf_symbol_flags PARAMS ((flagword));
#endif
#define elf_string_from_elf_strtab(abfd,strindex) \
return (elf_symbol_type *) symbol;
}
-void
-write_relocs (abfd, sec, xxx)
+static void
+write_relocs (abfd, sec, data)
bfd *abfd;
asection *sec;
- PTR xxx;
+ PTR data;
{
+ boolean *failedp = (boolean *) data;
Elf_Internal_Shdr *rela_hdr;
Elf_External_Rela *outbound_relocas;
Elf_External_Rel *outbound_relocs;
asymbol *last_sym = 0;
int last_sym_idx = 9999999; /* should always be written before use */
+ /* If we have already failed, don't do anything. */
+ if (*failedp)
+ return;
+
if ((sec->flags & SEC_RELOC) == 0)
return;
rela_hdr = &elf_section_data (sec)->rel_hdr;
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
- rela_hdr->contents = (void *) bfd_alloc (abfd, rela_hdr->sh_size);
- if (!rela_hdr->contents)
+ rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
+ if (rela_hdr->contents == NULL)
{
bfd_set_error (bfd_error_no_memory);
- abort (); /* FIXME */
+ *failedp = true;
+ return;
}
/* orelocation has the data, reloc_count has the count... */
&& ((asect->flags & SEC_LOAD) == 0))
{
BFD_ASSERT (strcmp (asect->name, ".bss") == 0
- || strcmp (asect->name, ".sbss") == 0);
+ || strcmp (asect->name, ".sbss") == 0
+ || strcmp (asect->name, ".scommon") == 0
+ || strcmp (asect->name, "COMMON") == 0);
this_hdr->sh_type = SHT_NOBITS;
}
else
return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
(abfd, sym));
- if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
- {
- if (sym->flags & BSF_LOCAL)
- abort ();
- return 1;
- }
- if (sym->section == 0)
- {
- /* Is this valid? */
- abort ();
-
- return 1;
- }
- if (bfd_is_und_section (sym->section))
- return 1;
- if (bfd_is_com_section (sym->section))
- return 1;
- if (sym->flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE))
- return 0;
- return 0;
+ return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (sym))
+ || bfd_is_com_section (bfd_get_section (sym)));
}
static boolean
what we computed here. Actually, it's OK if we allocated too
much space in the program header. */
if (phdr_count > phdr_size / sizeof (Elf_External_Phdr))
- abort ();
+ {
+ ((*_bfd_error_handler)
+ ("%s: Not enough room for program headers (allocated %lu, need %u)",
+ bfd_get_filename (abfd),
+ (unsigned long) (phdr_size / sizeof (Elf_External_Phdr)),
+ phdr_count));
+ bfd_set_error (bfd_error_bad_value);
+ return (file_ptr) -1;
+ }
/* Set up program header information. */
i_ehdrp = elf_elfheader (abfd);
Elf_Internal_Sym sym;
bfd_vma value = syms[idx]->value;
elf_symbol_type *type_ptr;
+ flagword flags = syms[idx]->flags;
- if (syms[idx]->flags & BSF_SECTION_SYM)
+ if (flags & BSF_SECTION_SYM)
/* Section symbols have no names. */
sym.st_name = 0;
else
if (bfd_is_com_section (syms[idx]->section))
sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT);
else if (bfd_is_und_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (STB_GLOBAL,
- ((syms[idx]->flags & BSF_FUNCTION)
+ sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
+ ? STB_WEAK
+ : STB_GLOBAL),
+ ((flags & BSF_FUNCTION)
? STT_FUNC
: STT_NOTYPE));
- else if (syms[idx]->flags & BSF_SECTION_SYM)
+ else if (flags & BSF_SECTION_SYM)
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- else if (syms[idx]->flags & BSF_FILE)
+ else if (flags & BSF_FILE)
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
else
{
int bind = STB_LOCAL;
int type = STT_OBJECT;
- unsigned int flags = syms[idx]->flags;
if (flags & BSF_LOCAL)
bind = STB_LOCAL;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Shdr **i_shdrp;
+ boolean failed;
unsigned int count;
if (! abfd->output_has_begun
i_shdrp = elf_elfsections (abfd);
i_ehdrp = elf_elfheader (abfd);
- bfd_map_over_sections (abfd, write_relocs, (PTR) 0);
+ failed = false;
+ bfd_map_over_sections (abfd, write_relocs, &failed);
+ if (failed)
+ return false;
assign_file_positions_for_relocs (abfd);
/* After writing the headers, we need to write the sections too... */
}
idx = asym_ptr->udata.i;
- if (idx == 0)
- abort ();
+ BFD_ASSERT (idx != 0);
#if DEBUG & 4
{
fprintf (stderr,
- "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx %s\n",
+ "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n",
(long) asym_ptr, asym_ptr->name, idx, flags, elf_symbol_flags (flags));
fflush (stderr);
}
Elf_Internal_Shdr *hdr;
{
fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num,
- hdr->bfd_section != NULL ? hfd->bfd_section->name : "",
+ hdr->bfd_section != NULL ? hdr->bfd_section->name : "",
(long) hdr);
fprintf (stderr,
"sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
fprintf (stderr, "e_shnum = %ld\n", (long) ehdrp->e_shnum);
fprintf (stderr, "e_shentsize = %ld\n", (long) ehdrp->e_shentsize);
}
+
+static char *
+elf_symbol_flags (flags)
+ flagword flags;
+{
+ static char buffer[1024];
+
+ buffer[0] = '\0';
+ if (flags & BSF_LOCAL)
+ strcat (buffer, " local");
+
+ if (flags & BSF_GLOBAL)
+ strcat (buffer, " global");
+
+ if (flags & BSF_DEBUGGING)
+ strcat (buffer, " debug");
+
+ if (flags & BSF_FUNCTION)
+ strcat (buffer, " function");
+
+ if (flags & BSF_KEEP)
+ strcat (buffer, " keep");
+
+ if (flags & BSF_KEEP_G)
+ strcat (buffer, " keep_g");
+
+ if (flags & BSF_WEAK)
+ strcat (buffer, " weak");
+
+ if (flags & BSF_SECTION_SYM)
+ strcat (buffer, " section-sym");
+
+ if (flags & BSF_OLD_COMMON)
+ strcat (buffer, " old-common");
+
+ if (flags & BSF_NOT_AT_END)
+ strcat (buffer, " not-at-end");
+
+ if (flags & BSF_CONSTRUCTOR)
+ strcat (buffer, " constructor");
+
+ if (flags & BSF_WARNING)
+ strcat (buffer, " warning");
+
+ if (flags & BSF_INDIRECT)
+ strcat (buffer, " indirect");
+
+ if (flags & BSF_FILE)
+ strcat (buffer, " file");
+
+ if (flags & DYNAMIC)
+ strcat (buffer, " dynamic");
+
+ if (flags & ~(BSF_LOCAL
+ | BSF_GLOBAL
+ | BSF_DEBUGGING
+ | BSF_FUNCTION
+ | BSF_KEEP
+ | BSF_KEEP_G
+ | BSF_WEAK
+ | BSF_SECTION_SYM
+ | BSF_OLD_COMMON
+ | BSF_NOT_AT_END
+ | BSF_CONSTRUCTOR
+ | BSF_WARNING
+ | BSF_INDIRECT
+ | BSF_FILE
+ | BSF_DYNAMIC))
+ strcat (buffer, " unknown-bits");
+
+ return buffer;
+}
#endif
/* Canonicalize the relocs. */
if (core_prpsinfo (core_bfd))
{
- corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname);
+ corename = (((prpsinfo_t *) core_prpsinfo (core_bfd))->pr_fname);
}
else
{
static boolean elf_adjust_dynamic_symbol
PARAMS ((struct elf_link_hash_entry *, PTR));
+/* This struct is used to pass information to routines called via
+ elf_link_hash_traverse which must return failure. */
+
+struct elf_info_failed
+{
+ boolean failed;
+ struct bfd_link_info *info;
+};
+
/* Given an ELF BFD, add symbols to the global hash table as
appropriate. */
case bfd_archive:
first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
if (first == NULL)
- return false;
+ {
+ /* It's OK to have an empty archive. */
+ return true;
+ }
if (! bfd_check_format (first, bfd_object))
return false;
if (bfd_get_flavour (first) != bfd_target_elf_flavour)
{
asection *s;
const char *name;
+ bfd_size_type oldsize;
bfd_size_type strindex;
dynamic = true;
}
/* Add a DT_NEEDED entry for this dynamic object. */
+ oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
true, false);
if (strindex == (bfd_size_type) -1)
goto error_return;
+
+ if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+ {
+ asection *sdyn;
+ Elf_External_Dyn *dyncon, *dynconend;
+
+ /* The hash table size did not change, which means that the
+ dynamic object name was already entered. If we have
+ already included this dynamic object in the link, just
+ ignore it. There is no reason to include a particular
+ dynamic object more than once. */
+ sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ ".dynamic");
+ BFD_ASSERT (sdyn != NULL);
+
+ dyncon = (Elf_External_Dyn *) sdyn->contents;
+ dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+
+ elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn);
+ if (dyn.d_tag == DT_NEEDED
+ && dyn.d_un.d_val == strindex)
+ {
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+ }
+ }
+
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
goto error_return;
}
struct elf_link_hash_entry *h;
h = *hpp;
- if (h != hlook
+ if (h != NULL && h != hlook
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section == slook
asection **sinterpptr;
{
bfd *dynobj;
- asection *s;
- Elf_Internal_Sym isym;
- size_t i;
- size_t bucketcount;
struct elf_backend_data *bed;
*sinterpptr = NULL;
/* If we are supposed to export all symbols into the dynamic symbol
table (this is not the normal case), then do so. */
if (export_dynamic)
- elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
- (PTR) info);
+ {
+ struct elf_info_failed eif;
+
+ eif.failed = false;
+ eif.info = info;
+ elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
+ }
if (elf_hash_table (info)->dynamic_sections_created)
{
+ struct elf_info_failed eif;
bfd_size_type strsize;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
/* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */
+ eif.failed = false;
+ eif.info = info;
elf_link_hash_traverse (elf_hash_table (info),
elf_adjust_dynamic_symbol,
- (PTR) info);
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
/* Add some entries to the .dynamic section. We fill in some of the
values later, in elf_bfd_final_link, but we must add the entries
if (elf_hash_table (info)->dynamic_sections_created)
{
size_t dynsymcount;
+ asection *s;
+ size_t i;
+ size_t bucketcount;
+ Elf_Internal_Sym isym;
/* Set the size of the .dynsym and .hash sections. We counted
the number of dynamic symbols in elf_link_add_object_symbols.
struct elf_link_hash_entry *h;
PTR data;
{
- struct bfd_link_info *info = (struct bfd_link_info *) data;
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
if (h->dynindx == -1
&& (h->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
{
- if (! elf_link_record_dynamic_symbol (info, h))
+ if (! elf_link_record_dynamic_symbol (eif->info, h))
{
- /* FIXME: No way to report error. */
- abort ();
+ eif->failed = true;
+ return false;
}
}
struct elf_link_hash_entry *h;
PTR data;
{
- struct bfd_link_info *info = (struct bfd_link_info *) data;
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
bfd *dynobj;
struct elf_backend_data *bed;
/* There is an implicit reference by a regular object file
via the weak symbol. */
weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
- if (! elf_adjust_dynamic_symbol (weakdef, (PTR) info))
+ if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif))
return false;
}
}
- dynobj = elf_hash_table (info)->dynobj;
+ dynobj = elf_hash_table (eif->info)->dynobj;
bed = get_elf_backend_data (dynobj);
- if (! (*bed->elf_backend_adjust_dynamic_symbol) (info, h))
+ if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
{
- /* FIXME: No way to return error. */
- abort ();
+ eif->failed = true;
+ return false;
}
return true;
PARAMS ((bfd *, struct bfd_link_info *, asection *,
struct bfd_link_order *));
+/* This struct is used to pass information to routines called via
+ elf_link_hash_traverse which must return failure. */
+
+struct elf_finfo_failed
+{
+ boolean failed;
+ struct elf_final_link_info *finfo;
+};
+
/* Do the final step of an ELF link. */
boolean
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Shdr *symstrtab_hdr;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_finfo_failed eif;
if (info->shared)
abfd->flags |= DYNAMIC;
{
finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
- if (finfo.dynsym_sec == NULL
- || finfo.hash_sec == NULL)
- abort ();
+ BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
}
finfo.contents = NULL;
finfo.external_relocs = NULL;
elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
/* We get the global symbols from the hash table. */
+ eif.failed = false;
+ eif.finfo = &finfo;
elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
- (PTR) &finfo);
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
/* Flush all symbols to the file. */
if (! elf_link_flush_output_syms (&finfo))
dyn.d_un.d_val += (o->output_section->vma
+ o->output_offset);
else
- dyn.d_un.d_val += o->vma;
+ /* The symbol is imported from another shared
+ library and does not apply to this one. */
+ dyn.d_un.d_val = 0;
}
elf_swap_dyn_out (dynobj, &dyn, dyncon);
}
struct elf_link_hash_entry *h;
PTR data;
{
- struct elf_final_link_info *finfo = (struct elf_final_link_info *) data;
+ struct elf_finfo_failed *eif = (struct elf_finfo_failed *) data;
+ struct elf_final_link_info *finfo = eif->finfo;
boolean strip;
Elf_Internal_Sym sym;
asection *input_sec;
(finfo->info, h->root.root.string, h->root.u.undef.abfd,
(asection *) NULL, 0)))
{
- /* FIXME: No way to return error. */
- abort ();
+ eif->failed = true;
+ return false;
}
}
input_sec->output_section);
if (sym.st_shndx == (unsigned short) -1)
{
- /* FIXME: No way to handle errors. */
- abort ();
+ eif->failed = true;
+ return false;
}
/* ELF symbols in relocateable files are section relative,
if (! ((*bed->elf_backend_finish_dynamic_symbol)
(finfo->output_bfd, finfo->info, h, &sym)))
{
- /* FIXME: No way to return error. */
- abort ();
+ eif->failed = true;
+ return false;
}
elf_swap_symbol_out (finfo->output_bfd, &sym,
if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec))
{
- /* FIXME: No way to return error. */
- abort ();
+ eif->failed = true;
+ return false;
}
return true;
else
{
r_symndx = sec->output_section->target_index;
- if (r_symndx == 0)
- abort ();
+ BFD_ASSERT (r_symndx != 0);
}
}
else
if (link_order->type == bfd_section_reloc_link_order)
{
indx = link_order->u.reloc.p->u.section->target_index;
- if (indx == 0)
- abort ();
+ BFD_ASSERT (indx != 0);
*rel_hash_ptr = NULL;
}
else