/* Generic ECOFF (Extended-COFF) routines.
- Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1990-2016 Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
{
/* name, id, index, next, prev, flags, user_set_vma, */
"*DEBUG*", 0, 0, NULL, NULL, 0, 0,
- /* linker_mark, linker_has_input, gc_mark, segment_mark, */
+ /* linker_mark, linker_has_input, gc_mark, compress_status, */
0, 0, 1, 0,
- /* sec_info_type, use_rela_p, */
- 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, relax, relax_count, */
- 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_boolean
-_bfd_ecoff_no_long_sections (abfd, enable)
- bfd *abfd;
- int enable;
+_bfd_ecoff_no_long_sections (bfd *abfd, int enable)
{
(void) abfd;
(void) enable;
struct fdr *fdr_ptr;
bfd_size_type raw_end;
bfd_size_type cb_end;
- bfd_size_type amt;
file_ptr pos;
BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);
We need to look at the fdr to deal with a lot of information in
the symbols, so we swap them here. */
- amt = internal_symhdr->ifdMax;
- amt *= sizeof (struct fdr);
- debug->fdr = (FDR *) bfd_alloc (abfd, amt);
+ debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax,
+ sizeof (struct fdr));
if (debug->fdr == NULL)
return FALSE;
external_fdr_size = backend->debug_swap.external_fdr_size;
fdr_ptr = debug->fdr;
fraw_src = (char *) debug->external_fdr;
+ /* PR 17512: file: 3372-1243-0.004. */
+ if (fraw_src == NULL && internal_symhdr->ifdMax > 0)
+ return FALSE;
fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
(*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr);
= backend->debug_swap.swap_ext_in;
void (* const swap_sym_in) (bfd *, void *, SYMR *)
= backend->debug_swap.swap_sym_in;
- bfd_size_type internal_size;
ecoff_symbol_type *internal;
ecoff_symbol_type *internal_ptr;
char *eraw_src;
if (bfd_get_symcount (abfd) == 0)
return TRUE;
- internal_size = bfd_get_symcount (abfd);
- internal_size *= sizeof (ecoff_symbol_type);
- internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
+ internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd),
+ sizeof (ecoff_symbol_type));
if (internal == NULL)
return FALSE;
EXTR internal_esym;
(*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym);
+
+ /* PR 17512: file: 3372-1000-0.004. */
+ if (internal_esym.asym.iss >= ecoff_data (abfd)->debug_info.symbolic_header.issExtMax
+ || internal_esym.asym.iss < 0)
+ return FALSE;
+
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext
+ internal_esym.asym.iss);
+
if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
&internal_ptr->symbol, 1,
internal_esym.weakext))
return FALSE;
+
/* The alpha uses a negative ifd field for section symbols. */
if (internal_esym.ifd >= 0)
- internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr
- + internal_esym.ifd);
+ {
+ /* PR 17512: file: 3372-1983-0.004. */
+ if (internal_esym.ifd >= ecoff_data (abfd)->debug_info.symbolic_header.ifdMax)
+ internal_ptr->fdr = NULL;
+ else
+ internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr
+ + internal_esym.ifd);
+ }
else
internal_ptr->fdr = NULL;
internal_ptr->local = FALSE;
}
}
+ /* PR 17512: file: 3372-3080-0.004.
+ A discrepancy between ecoff_data (abfd)->debug_info.symbolic_header.isymMax
+ and ecoff_data (abfd)->debug_info.symbolic_header.ifdMax can mean that
+ we have fewer symbols than we were expecting. Allow for this by updating
+ the symbol count and warning the user. */
+ if (internal_ptr - internal < (ptrdiff_t) bfd_get_symcount (abfd))
+ {
+ bfd_get_symcount (abfd) = internal_ptr - internal;
+ (*_bfd_error_handler)
+ (_("%B: warning: isymMax (%ld) is greater than ifdMax (%d)\n"),
+ abfd, ecoff_data (abfd)->debug_info.symbolic_header.isymMax,
+ ecoff_data (abfd)->debug_info.symbolic_header.ifdMax);
+ }
+
ecoff_data (abfd)->canonical_symbols = internal;
return TRUE;
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;
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);
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. */
if (mapdata == NULL)
return FALSE;
parsed_size = mapdata->parsed_size;
- bfd_release (abfd, (void *) mapdata);
+ free (mapdata);
raw_armap = (char *) bfd_alloc (abfd, parsed_size);
if (raw_armap == 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. */
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 = (char *) 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.
/* 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;
modified, and we write them out now. We use the reloc_count
field of output_section to keep track of the number of relocs we
have output so far. */
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
file_ptr pos = (output_section->rel_filepos
+ output_section->reloc_count * external_reloc_size);
size = bfd_get_reloc_size (rel.howto);
buf = (bfd_byte *) bfd_zmalloc (size);
- if (buf == NULL)
+ if (buf == NULL && size != 0)
return FALSE;
rstat = _bfd_relocate_contents (rel.howto, output_bfd,
(bfd_vma) addend, buf);
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)
+ if (bfd_link_relocatable (info))
{
/* We need to make a pass over the link_orders to count up the
number of relocations we will need to output, so that we know
bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
/* Now reset the reloc_count field of the sections in the output
BFD to 0, so that we can use them to keep track of how many
ecoff_data (abfd)->gp = (h->u.def.value
+ h->u.def.section->output_section->vma
+ h->u.def.section->output_offset);
- else if (info->relocatable)
+ else if (bfd_link_relocatable (info))
{
bfd_vma lo;