/* Generic ECOFF (Extended-COFF) routines.
- Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1990-2014 Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "aout/ar.h"
-#include "aout/ranlib.h"
#include "aout/stab_gnu.h"
/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
{
/* name, id, index, next, prev, flags, user_set_vma, */
"*DEBUG*", 0, 0, NULL, NULL, 0, 0,
- /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */
+ /* linker_mark, linker_has_input, gc_mark, compress_status, */
0, 0, 1, 0,
- /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */
- 0, 0, 0, 0,
- /* has_gp_reloc, need_finalize_relax, reloc_done, */
- 0, 0, 0,
- /* vma, lma, size, rawsize, */
- 0, 0, 0, 0,
+ /* segment_mark, sec_info_type, use_rela_p, */
+ 0, 0, 0,
+ /* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */
+ 0, 0, 0, 0, 0, 0,
+ /* vma, lma, size, rawsize, compressed_size, relax, relax_count, */
+ 0, 0, 0, 0, 0, 0, 0,
/* output_offset, output_section, alignment_power, */
0, NULL, 0,
/* relocation, orelocation, reloc_count, filepos, rel_filepos, */
{
bfd_size_type amt = sizeof (ecoff_data_type);
- abfd->tdata.ecoff_obj_data = bfd_zalloc (abfd, amt);
+ abfd->tdata.ecoff_obj_data = (struct ecoff_tdata *) bfd_zalloc (abfd, amt);
if (abfd->tdata.ecoff_obj_data == NULL)
return FALSE;
/* Initialize a new section. */
bfd_boolean
-_bfd_ecoff_new_section_hook (bfd *abfd ATTRIBUTE_UNUSED,
- asection *section)
+_bfd_ecoff_new_section_hook (bfd *abfd, asection *section)
{
unsigned int i;
static struct
uncertain about .init on some systems and I don't know how shared
libraries work. */
- return TRUE;
+ return _bfd_generic_new_section_hook (abfd, section);
}
/* Determine the machine architecture and type. This is called from
bfd_boolean
_bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr)
{
- struct internal_filehdr *internal_f = filehdr;
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
enum bfd_architecture arch;
unsigned long mach;
return bfd_default_set_arch_mach (abfd, arch, mach);
}
+bfd_boolean
+_bfd_ecoff_no_long_sections (bfd *abfd, int enable)
+{
+ (void) abfd;
+ (void) enable;
+ return FALSE;
+}
+
/* Get the magic number to use based on the architecture and machine.
This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */
asection *section ATTRIBUTE_UNUSED,
flagword * flags_ptr)
{
- struct internal_scnhdr *internal_s = hdr;
+ struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
long styp_flags = internal_s->s_flags;
flagword sec_flags = 0;
the symbols, so we swap them here. */
amt = internal_symhdr->ifdMax;
amt *= sizeof (struct fdr);
- debug->fdr = bfd_alloc (abfd, amt);
+ debug->fdr = (FDR *) bfd_alloc (abfd, amt);
if (debug->fdr == NULL)
return FALSE;
external_fdr_size = backend->debug_swap.external_fdr_size;
asymbol *
_bfd_ecoff_make_empty_symbol (bfd *abfd)
{
- ecoff_symbol_type *new;
+ ecoff_symbol_type *new_symbol;
bfd_size_type amt = sizeof (ecoff_symbol_type);
- new = bfd_zalloc (abfd, amt);
- if (new == NULL)
+ new_symbol = (ecoff_symbol_type *) bfd_zalloc (abfd, amt);
+ if (new_symbol == NULL)
return NULL;
- new->symbol.section = NULL;
- new->fdr = NULL;
- new->local = FALSE;
- new->native = NULL;
- new->symbol.the_bfd = abfd;
- return &new->symbol;
+ new_symbol->symbol.section = NULL;
+ new_symbol->fdr = NULL;
+ new_symbol->local = FALSE;
+ new_symbol->native = NULL;
+ new_symbol->symbol.the_bfd = abfd;
+ return &new_symbol->symbol;
}
/* Set the BFD flags and section for an ECOFF symbol. */
internal_size = bfd_get_symcount (abfd);
internal_size *= sizeof (ecoff_symbol_type);
- internal = bfd_alloc (abfd, internal_size);
+ internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
if (internal == NULL)
return FALSE;
sprintf (string,
"%s %s { ifd = %u, index = %lu }",
which, name, ifd,
- ((long) indx
+ ((unsigned long) indx
+ debug_info->symbolic_header.iextMax));
}
amt = section->reloc_count;
amt *= sizeof (arelent);
- internal_relocs = bfd_alloc (abfd, amt);
+ internal_relocs = (arelent *) bfd_alloc (abfd, amt);
external_reloc_size = backend->external_reloc_size;
amt = external_reloc_size * section->reloc_count;
- external_relocs = bfd_alloc (abfd, amt);
+ external_relocs = (char *) bfd_alloc (abfd, amt);
if (internal_relocs == NULL || external_relocs == NULL)
return FALSE;
if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
bfd_boolean
_bfd_ecoff_find_nearest_line (bfd *abfd,
+ asymbol **symbols ATTRIBUTE_UNUSED,
asection *section,
- asymbol **ignore_symbols ATTRIBUTE_UNUSED,
bfd_vma offset,
const char **filename_ptr,
const char **functionname_ptr,
- unsigned int *retline_ptr)
+ unsigned int *retline_ptr,
+ unsigned int *discriminator_ptr)
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (abfd)->debug_swap;
{
bfd_size_type amt = sizeof (struct ecoff_find_line);
- ecoff_data (abfd)->find_line_info = bfd_zalloc (abfd, amt);
+ ecoff_data (abfd)->find_line_info =
+ (struct ecoff_find_line *) bfd_zalloc (abfd, amt);
if (ecoff_data (abfd)->find_line_info == NULL)
return FALSE;
}
- line_info = ecoff_data (abfd)->find_line_info;
+ if (discriminator_ptr)
+ *discriminator_ptr = 0;
+ line_info = ecoff_data (abfd)->find_line_info;
return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
debug_swap, line_info, filename_ptr,
functionname_ptr, retline_ptr);
/* Get the size of the section headers. */
int
-_bfd_ecoff_sizeof_headers (bfd *abfd, bfd_boolean reloc ATTRIBUTE_UNUSED)
+_bfd_ecoff_sizeof_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
asection *current;
int c;
ret = (bfd_coff_filhsz (abfd)
+ bfd_coff_aoutsz (abfd)
+ c * bfd_coff_scnhsz (abfd));
- return BFD_ALIGN (ret, 16);
+ return (int) BFD_ALIGN (ret, 16);
}
/* Get the contents of a section. */
const bfd_vma round = ecoff_backend (abfd)->round;
bfd_size_type amt;
- sofar = _bfd_ecoff_sizeof_headers (abfd, FALSE);
+ sofar = _bfd_ecoff_sizeof_headers (abfd, NULL);
file_sofar = sofar;
/* Sort the sections by VMA. */
amt = abfd->section_count;
amt *= sizeof (asection *);
- sorted_hdrs = bfd_malloc (amt);
+ sorted_hdrs = (asection **) bfd_malloc (amt);
if (sorted_hdrs == NULL)
return FALSE;
for (current = abfd->sections, i = 0;
}
if ((abfd->flags & D_PAGED) != 0)
- text_size = _bfd_ecoff_sizeof_headers (abfd, FALSE);
+ text_size = _bfd_ecoff_sizeof_headers (abfd, NULL);
else
text_size = 0;
text_start = 0;
else
{
const char *name;
- unsigned int i;
+ unsigned int j;
static struct
{
const char * name;
name = bfd_get_section_name (abfd, bfd_get_section (sym));
- for (i = 0; i < ARRAY_SIZE (section_symndx); i++)
- if (streq (name, section_symndx[i].name))
+ for (j = 0; j < ARRAY_SIZE (section_symndx); j++)
+ if (streq (name, section_symndx[j].name))
{
- in.r_symndx = section_symndx[i].r_symndx;
+ in.r_symndx = section_symndx[j].r_symndx;
break;
}
- if (i == ARRAY_SIZE (section_symndx))
+ if (j == ARRAY_SIZE (section_symndx))
abort ();
in.r_extern = 0;
}
struct artdata *ardata;
unsigned int count;
char *raw_ptr;
- struct symdef *symdef_ptr;
+ carsym *symdef_ptr;
char *stringbase;
bfd_size_type amt;
bfd_slurp_armap, but that seems inappropriate since no other
target uses this format. Instead, we check directly for a COFF
armap. */
- if (strneq (nextname, "/ ", 16))
+ if (CONST_STRNEQ (nextname, "/ "))
return bfd_slurp_armap (abfd);
/* See if the first element is an armap. */
if (mapdata == NULL)
return FALSE;
parsed_size = mapdata->parsed_size;
- bfd_release (abfd, (void *) mapdata);
+ free (mapdata);
- raw_armap = bfd_alloc (abfd, parsed_size);
+ raw_armap = (char *) bfd_alloc (abfd, parsed_size);
if (raw_armap == NULL)
return FALSE;
++ardata->symdef_count;
amt = ardata->symdef_count;
- amt *= sizeof (struct symdef);
- symdef_ptr = bfd_alloc (abfd, amt);
+ amt *= sizeof (carsym);
+ symdef_ptr = (carsym *) bfd_alloc (abfd, amt);
if (!symdef_ptr)
return FALSE;
- ardata->symdefs = (carsym *) symdef_ptr;
+ ardata->symdefs = symdef_ptr;
raw_ptr = raw_armap + 4;
for (i = 0; i < count; i++, raw_ptr += 8)
if (file_offset == 0)
continue;
name_offset = H_GET_32 (abfd, raw_ptr);
- symdef_ptr->s.name = stringbase + name_offset;
+ symdef_ptr->name = stringbase + name_offset;
symdef_ptr->file_offset = file_offset;
++symdef_ptr;
}
linker just checks the archive name; the GNU linker may check the
date. */
stat (abfd->filename, &statbuf);
- sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60));
+ _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
+ (long) (statbuf.st_mtime + 60));
/* The DECstation uses zeroes for the uid, gid and mode of the
armap. */
hdr.ar_mode[1] = '4';
hdr.ar_mode[2] = '4';
- sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+ _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
hdr.ar_fmag[0] = '`';
hdr.ar_fmag[1] = '\012';
if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4)
return FALSE;
- hashtable = bfd_zalloc (abfd, symdefsize);
+ hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
if (!hashtable)
return FALSE;
last_elt = current;
for (i = 0; i < orl_count; i++)
{
- unsigned int hash, rehash;
+ unsigned int hash, rehash = 0;
/* Advance firstreal to the file position of this archive
element. */
{
firstreal += arelt_size (current) + sizeof (struct ar_hdr);
firstreal += firstreal % 2;
- current = current->next;
+ current = current->archive_next;
}
while (current != map[i].u.abfd);
}
return TRUE;
}
-
-/* See whether this BFD is an archive. If it is, read in the armap
- and the extended name table. */
-
-const bfd_target *
-_bfd_ecoff_archive_p (bfd *abfd)
-{
- struct artdata *tdata_hold;
- char armag[SARMAG + 1];
- bfd_size_type amt;
-
- if (bfd_bread ((void *) armag, (bfd_size_type) SARMAG, abfd) != SARMAG)
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
- }
-
- if (! strneq (armag, ARMAG, SARMAG))
- {
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
- }
-
- tdata_hold = bfd_ardata (abfd);
-
- amt = sizeof (struct artdata);
- bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
- if (bfd_ardata (abfd) == NULL)
- {
- bfd_ardata (abfd) = tdata_hold;
- return NULL;
- }
-
- bfd_ardata (abfd)->first_file_filepos = SARMAG;
- /* Already cleared by bfd_zalloc above.
- bfd_ardata (abfd)->cache = NULL;
- bfd_ardata (abfd)->archive_head = NULL;
- bfd_ardata (abfd)->symdefs = NULL;
- bfd_ardata (abfd)->extended_names = NULL;
- bfd_ardata (abfd)->extended_names_size = 0;
- bfd_ardata (abfd)->tdata = NULL; */
-
- if (! _bfd_ecoff_slurp_armap (abfd)
- || ! _bfd_ecoff_slurp_extended_name_table (abfd))
- {
- bfd_release (abfd, bfd_ardata (abfd));
- bfd_ardata (abfd) = tdata_hold;
- return NULL;
- }
-
- if (bfd_has_map (abfd))
- {
- bfd *first;
-
- /* This archive has a map, so we may presume that the contents
- are object files. Make sure that if the first file in the
- archive can be recognized as an object file, it is for this
- target. If not, assume that this is the wrong format. If
- the first file is not an object file, somebody is doing
- something weird, and we permit it so that ar -t will work. */
-
- first = bfd_openr_next_archived_file (abfd, NULL);
- if (first != NULL)
- {
- first->target_defaulted = FALSE;
- if (bfd_check_format (first, bfd_object)
- && first->xvec != abfd->xvec)
- {
- /* We ought to close `first' here, but we can't, because
- we have no way to remove it from the archive cache.
- It's almost impossible to figure out when we can
- release bfd_ardata. FIXME. */
- bfd_set_error (bfd_error_wrong_object_format);
- bfd_ardata (abfd) = tdata_hold;
- return NULL;
- }
- /* And we ought to close `first' here too. */
- }
- }
-
- return abfd->xvec;
-}
\f
/* ECOFF linker code. */
struct ecoff_link_hash_table *ret;
bfd_size_type amt = sizeof (struct ecoff_link_hash_table);
- ret = bfd_malloc (amt);
+ ret = (struct ecoff_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
return NULL;
- if (! _bfd_link_hash_table_init (&ret->root, abfd,
- ecoff_link_hash_newfunc))
+ if (!_bfd_link_hash_table_init (&ret->root, abfd,
+ ecoff_link_hash_newfunc,
+ sizeof (struct ecoff_link_hash_entry)))
{
free (ret);
return NULL;
((struct ecoff_link_hash_entry *) \
bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
-/* Traverse an ECOFF link hash table. */
-
-#define ecoff_link_hash_traverse(table, func, info) \
- (bfd_link_hash_traverse \
- (&(table)->root, \
- (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
- (info)))
-
/* Get the ECOFF link hash table from the info structure. This is
just a cast. */
amt = ext_count;
amt *= sizeof (struct bfd_link_hash_entry *);
- sym_hash = bfd_alloc (abfd, amt);
+ sym_hash = (struct bfd_link_hash_entry **) bfd_alloc (abfd, amt);
if (!sym_hash)
return FALSE;
ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash;
/* If we are building an ECOFF hash table, save the external
symbol information. */
- if (info->hash->creator->flavour == bfd_get_flavour (abfd))
+ if (bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd))
{
if (h->abfd == NULL
|| (! bfd_is_und_section (section)
|| bfd_bread (external_ext, esize, abfd) != esize)
goto error_return;
- ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
+ ssext = (char *) bfd_malloc ((bfd_size_type) symhdr->issExtMax);
if (ssext == NULL && symhdr->issExtMax != 0)
goto error_return;
static bfd_boolean
ecoff_link_check_archive_element (bfd *abfd,
struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
+ const char *name,
bfd_boolean *pneeded)
{
- const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- void (* const swap_ext_in) (bfd *, void *, EXTR *)
- = backend->debug_swap.swap_ext_in;
- HDRR *symhdr;
- bfd_size_type external_ext_size;
- void * external_ext = NULL;
- bfd_size_type esize;
- char *ssext = NULL;
- char *ext_ptr;
- char *ext_end;
-
*pneeded = FALSE;
- if (! ecoff_slurp_symbolic_header (abfd))
- goto error_return;
-
- /* If there are no symbols, we don't want it. */
- if (bfd_get_symcount (abfd) == 0)
- goto successful_return;
-
- symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
-
- /* Read in the external symbols and external strings. */
- external_ext_size = backend->debug_swap.external_ext_size;
- esize = symhdr->iextMax * external_ext_size;
- external_ext = bfd_malloc (esize);
- if (external_ext == NULL && esize != 0)
- goto error_return;
-
- if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
- || bfd_bread (external_ext, esize, abfd) != esize)
- goto error_return;
-
- ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
- if (ssext == NULL && symhdr->issExtMax != 0)
- goto error_return;
-
- if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
- || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
- != (bfd_size_type) symhdr->issExtMax))
- goto error_return;
-
- /* Look through the external symbols to see if they define some
- symbol that is currently undefined. */
- ext_ptr = (char *) external_ext;
- ext_end = ext_ptr + esize;
- for (; ext_ptr < ext_end; ext_ptr += external_ext_size)
- {
- EXTR esym;
- bfd_boolean def;
- const char *name;
- struct bfd_link_hash_entry *h;
-
- (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
-
- /* See if this symbol defines something. */
- if (esym.asym.st != stGlobal
- && esym.asym.st != stLabel
- && esym.asym.st != stProc)
- continue;
-
- switch (esym.asym.sc)
- {
- case scText:
- case scData:
- case scBss:
- case scAbs:
- case scSData:
- case scSBss:
- case scRData:
- case scCommon:
- case scSCommon:
- case scInit:
- case scFini:
- case scRConst:
- def = TRUE;
- break;
- default:
- def = FALSE;
- break;
- }
-
- if (! def)
- continue;
-
- name = ssext + esym.asym.iss;
- h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
-
- /* Unlike the generic linker, we do not pull in elements because
- of common symbols. */
- if (h == NULL
- || h->type != bfd_link_hash_undefined)
- continue;
-
- /* Include this element. */
- if (! (*info->callbacks->add_archive_element) (info, abfd, name))
- goto error_return;
- if (! ecoff_link_add_externals (abfd, info, external_ext, ssext))
- goto error_return;
+ /* Unlike the generic linker, we do not pull in elements because
+ of common symbols. */
+ if (h->type != bfd_link_hash_undefined)
+ return TRUE;
- *pneeded = TRUE;
- goto successful_return;
- }
+ /* Include this element. */
+ if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd))
+ return FALSE;
+ *pneeded = TRUE;
- successful_return:
- if (external_ext != NULL)
- free (external_ext);
- if (ssext != NULL)
- free (ssext);
- return TRUE;
- error_return:
- if (external_ext != NULL)
- free (external_ext);
- if (ssext != NULL)
- free (ssext);
- return FALSE;
+ return ecoff_link_add_object_symbols (abfd, info);
}
/* Add the symbols from an archive file to the global hash table.
while (*pundef != NULL)
{
struct bfd_link_hash_entry *h;
- unsigned int hash, rehash;
+ unsigned int hash, rehash = 0;
unsigned int file_offset;
const char *name;
bfd *element;
/* Unlike the generic linker, we know that this element provides
a definition for an undefined symbol and we know that we want
to include it. We don't need to check anything. */
- if (! (*info->callbacks->add_archive_element) (info, element, name))
+ if (!(*info->callbacks
+ ->add_archive_element) (info, element, name, &element))
return FALSE;
if (! ecoff_link_add_object_symbols (element, info))
return FALSE;
else \
{ \
bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
- debug->ptr = bfd_malloc (amt); \
+ debug->ptr = (type) bfd_malloc (amt); \
if (debug->ptr == NULL) \
{ \
ret = FALSE; \
bfd_byte *buf;
size = bfd_get_reloc_size (rel.howto);
- buf = bfd_zmalloc (size);
+ buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL)
return FALSE;
rstat = _bfd_relocate_contents (rel.howto, output_bfd,
/* Get some memory and swap out the reloc. */
external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
- rbuf = bfd_malloc (external_reloc_size);
+ rbuf = (bfd_byte *) bfd_malloc (external_reloc_size);
if (rbuf == NULL)
return FALSE;
the hash table. */
static bfd_boolean
-ecoff_link_write_external (struct ecoff_link_hash_entry *h, void * data)
+ecoff_link_write_external (struct bfd_hash_entry *bh, void * data)
{
+ struct ecoff_link_hash_entry *h = (struct ecoff_link_hash_entry *) bh;
struct extsym_info *einfo = (struct extsym_info *) data;
bfd *output_bfd = einfo->abfd;
bfd_boolean strip;
/* Accumulate the debugging symbols from each input BFD. */
for (input_bfd = info->input_bfds;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
{
bfd_boolean ret;
/* Write out the external symbols. */
einfo.abfd = abfd;
einfo.info = info;
- ecoff_link_hash_traverse (ecoff_hash_table (info),
- ecoff_link_write_external,
- (void *) &einfo);
+ bfd_hash_traverse (&info->hash->table, ecoff_link_write_external, &einfo);
if (info->relocatable)
{