/* Support for the generic parts of COFF, for BFD.
- Copyright (C) 1990-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2020 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
coff_data (abfd). */
#include "sysdep.h"
+#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
#include "coff/internal.h"
break;
}
if (new_name != NULL)
- bfd_rename_section (abfd, return_section, new_name);
+ bfd_rename_section (return_section, new_name);
}
return result;
/* Read in a COFF object and make it into a BFD. This is used by
ECOFF as well. */
-const bfd_target *
+bfd_cleanup
coff_real_object_p (bfd *,
unsigned,
struct internal_filehdr *,
struct internal_aouthdr *);
-const bfd_target *
+bfd_cleanup
coff_real_object_p (bfd *abfd,
unsigned nscns,
struct internal_filehdr *internal_f,
if ((internal_f->f_flags & F_EXEC) != 0)
abfd->flags |= D_PAGED;
- bfd_get_symcount (abfd) = internal_f->f_nsyms;
+ abfd->symcount = internal_f->f_nsyms;
if (internal_f->f_nsyms)
abfd->flags |= HAS_SYMS;
if (internal_a != (struct internal_aouthdr *) NULL)
- bfd_get_start_address (abfd) = internal_a->entry;
+ abfd->start_address = internal_a->entry;
else
- bfd_get_start_address (abfd) = 0;
+ abfd->start_address = 0;
/* Set up the tdata area. ECOFF uses its own routine, and overrides
abfd->flags. */
scnhsz = bfd_coff_scnhsz (abfd);
readsize = (bfd_size_type) nscns * scnhsz;
- external_sections = (char *) bfd_alloc (abfd, readsize);
+ external_sections = (char *) _bfd_alloc_and_read (abfd, readsize, readsize);
if (!external_sections)
goto fail;
- if (bfd_bread ((void *) external_sections, readsize, abfd) != readsize)
- goto fail;
-
/* Set the arch/mach *before* swapping in sections; section header swapping
may depend on arch/mach info. */
if (! bfd_coff_set_arch_mach_hook (abfd, (void *) internal_f))
}
}
- return abfd->xvec;
+ _bfd_coff_free_symbols (abfd);
+ return _bfd_no_cleanup;
fail:
+ _bfd_coff_free_symbols (abfd);
bfd_release (abfd, tdata);
fail2:
abfd->tdata.any = tdata_save;
abfd->flags = oflags;
- bfd_get_start_address (abfd) = ostart;
- return (const bfd_target *) NULL;
+ abfd->start_address = ostart;
+ return NULL;
}
/* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is
not a COFF file. This is also used by ECOFF. */
-const bfd_target *
+bfd_cleanup
coff_object_p (bfd *abfd)
{
bfd_size_type filhsz;
filhsz = bfd_coff_filhsz (abfd);
aoutsz = bfd_coff_aoutsz (abfd);
- filehdr = bfd_alloc (abfd, filhsz);
+ filehdr = _bfd_alloc_and_read (abfd, filhsz, filhsz);
if (filehdr == NULL)
- return NULL;
- if (bfd_bread (filehdr, filhsz, abfd) != filhsz)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_wrong_format);
- bfd_release (abfd, filehdr);
return NULL;
}
bfd_coff_swap_filehdr_in (abfd, filehdr, &internal_f);
{
void * opthdr;
- opthdr = bfd_alloc (abfd, aoutsz);
+ opthdr = _bfd_alloc_and_read (abfd, aoutsz, internal_f.f_opthdr);
if (opthdr == NULL)
return NULL;
- if (bfd_bread (opthdr, (bfd_size_type) internal_f.f_opthdr, abfd)
- != internal_f.f_opthdr)
- {
- bfd_release (abfd, opthdr);
- return NULL;
- }
/* PR 17512: file: 11056-1136-0.004. */
if (internal_f.f_opthdr < aoutsz)
- memset (((char *) opthdr) + internal_f.f_opthdr, 0, aoutsz - internal_f.f_opthdr);
+ memset (((char *) opthdr) + internal_f.f_opthdr, 0,
+ aoutsz - internal_f.f_opthdr);
bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);
bfd_release (abfd, opthdr);
for (i = 0; i < s->u.syment.n_numaux; i++)
{
combined_entry_type *a = s + i + 1;
-
+
BFD_ASSERT (! a->is_sym);
if (a->fix_tag)
{
combined_entry_type *table_base,
combined_entry_type *symbol,
unsigned int indaux,
- combined_entry_type *auxent)
+ combined_entry_type *auxent,
+ combined_entry_type *table_end)
{
unsigned int type = symbol->u.syment.n_type;
unsigned int n_sclass = symbol->u.syment.n_sclass;
|| n_sclass == C_FCN)
&& auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0
&& auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l
- < (long) obj_raw_syment_count (abfd))
+ < (long) obj_raw_syment_count (abfd)
+ && table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l
+ < table_end)
{
auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p =
table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
auxent->fix_end = 1;
}
+
/* A negative tagndx is meaningless, but the SCO 3.2v4 cc can
generate one, so we must be careful to ignore it. */
if ((unsigned long) auxent->u.auxent.x_sym.x_tagndx.l
- < obj_raw_syment_count (abfd))
+ < obj_raw_syment_count (abfd)
+ && table_base + auxent->u.auxent.x_sym.x_tagndx.l < table_end)
{
auxent->u.auxent.x_sym.x_tagndx.p =
table_base + auxent->u.auxent.x_sym.x_tagndx.l;
return NULL;
}
- sec_size = sect->size;
- debug_section = (char *) bfd_alloc (abfd, sec_size);
- if (debug_section == NULL)
- return NULL;
-
/* Seek to the beginning of the `.debug' section and read it.
Save the current position first; it is needed by our caller.
Then read debug section and reset the file pointer. */
position = bfd_tell (abfd);
- if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0
- || bfd_bread (debug_section, sec_size, abfd) != sec_size
- || bfd_seek (abfd, position, SEEK_SET) != 0)
+ if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0)
+ return NULL;
+
+ sec_size = sect->size;
+ debug_section = (char *) _bfd_alloc_and_read (abfd, sec_size, sec_size);
+ if (debug_section == NULL)
+ return NULL;
+
+ if (bfd_seek (abfd, position, SEEK_SET) != 0)
return NULL;
* sect_return = sect;
bfd_boolean
_bfd_coff_get_external_symbols (bfd *abfd)
{
- bfd_size_type symesz;
- bfd_size_type size;
+ size_t symesz;
+ size_t size;
void * syms;
if (obj_coff_external_syms (abfd) != NULL)
return TRUE;
symesz = bfd_coff_symesz (abfd);
-
- size = obj_raw_syment_count (abfd) * symesz;
- if (size == 0)
- return TRUE;
- /* Check for integer overflow and for unreasonable symbol counts. */
- if (size < obj_raw_syment_count (abfd)
- || (bfd_get_file_size (abfd) > 0
- && size > bfd_get_file_size (abfd)))
-
- {
- _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""),
- abfd, (uint64_t) obj_raw_syment_count (abfd));
- return FALSE;
- }
-
- syms = bfd_malloc (size);
- if (syms == NULL)
+ if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size))
{
- /* PR 21013: Provide an error message when the alloc fails. */
- _bfd_error_handler (_("%pB: not enough memory to allocate space "
- "for %#" PRIx64 " symbols of size %#" PRIx64),
- abfd, (uint64_t) obj_raw_syment_count (abfd),
- (uint64_t) symesz);
+ bfd_set_error (bfd_error_file_truncated);
return FALSE;
}
- if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
- || bfd_bread (syms, size, abfd) != size)
- {
- if (syms != NULL)
- free (syms);
- return FALSE;
- }
+ if (size == 0)
+ return TRUE;
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
+ return FALSE;
+ syms = _bfd_malloc_and_read (abfd, size, size);
obj_coff_external_syms (abfd) = syms;
- return TRUE;
+ return syms != NULL;
}
/* Read in the external strings. The strings are not loaded until
bfd_size_type strsize;
char *strings;
file_ptr pos;
+ ufile_ptr filesize;
if (obj_coff_strings (abfd) != NULL)
return obj_coff_strings (abfd);
#endif
}
- if (strsize < STRING_SIZE_SIZE || strsize > bfd_get_file_size (abfd))
+ filesize = bfd_get_file_size (abfd);
+ if (strsize < STRING_SIZE_SIZE
+ || (filesize != 0 && strsize > filesize))
{
_bfd_error_handler
/* xgettext: c-format */
if (! _bfd_coff_get_external_symbols (abfd))
return NULL;
- size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
+ size = obj_raw_syment_count (abfd);
/* Check for integer overflow. */
- if (size < obj_raw_syment_count (abfd))
+ if (size > (bfd_size_type) -1 / sizeof (combined_entry_type))
return NULL;
+ size *= sizeof (combined_entry_type);
internal = (combined_entry_type *) bfd_zalloc (abfd, size);
if (internal == NULL && size != 0)
return NULL;
symbol_ptr = internal_ptr;
internal_ptr->is_sym = TRUE;
- /* PR 17512: file: 1353-1166-0.004. */
- if (symbol_ptr->u.syment.n_sclass == C_FILE
- && symbol_ptr->u.syment.n_numaux > 0
- && raw_src + symesz + symbol_ptr->u.syment.n_numaux
- * symesz > raw_end)
- {
- bfd_release (abfd, internal);
- return NULL;
- }
-
for (i = 0;
i < symbol_ptr->u.syment.n_numaux;
i++)
{
internal_ptr++;
+ raw_src += symesz;
+
/* PR 17512: Prevent buffer overrun. */
- if (internal_ptr >= internal_end)
+ if (raw_src >= raw_end || internal_ptr >= internal_end)
{
bfd_release (abfd, internal);
return NULL;
}
- raw_src += symesz;
bfd_coff_swap_aux_in (abfd, (void *) raw_src,
symbol_ptr->u.syment.n_type,
symbol_ptr->u.syment.n_sclass,
internal_ptr->is_sym = FALSE;
coff_pointerize_aux (abfd, internal, symbol_ptr, i,
- internal_ptr);
+ internal_ptr, internal_end);
}
}
- /* Free the raw symbols, but not the strings (if we have them). */
- obj_coff_keep_strings (abfd) = TRUE;
- if (! _bfd_coff_free_symbols (abfd))
- return NULL;
+ /* Free the raw symbols. */
+ if (obj_coff_external_syms (abfd) != NULL
+ && ! obj_coff_keep_syms (abfd))
+ {
+ free (obj_coff_external_syms (abfd));
+ obj_coff_external_syms (abfd) = NULL;
+ }
for (internal_ptr = internal; internal_ptr < internal_end;
internal_ptr++)
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
+#if SIZEOF_LONG == SIZEOF_INT
+ if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return -1;
+ }
+#endif
return (asect->reloc_count + 1) * sizeof (arelent *);
}
asymbol *
coff_make_empty_symbol (bfd *abfd)
{
- bfd_size_type amt = sizeof (coff_symbol_type);
+ size_t amt = sizeof (coff_symbol_type);
coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_zalloc (abfd, amt);
if (new_symbol == NULL)
void * ptr ATTRIBUTE_UNUSED,
unsigned long sz ATTRIBUTE_UNUSED)
{
- bfd_size_type amt = sizeof (coff_symbol_type);
+ size_t amt = sizeof (coff_symbol_type);
coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_alloc (abfd, amt);
if (new_symbol == NULL)
combined_entry_type *pend;
alent *l;
struct coff_section_tdata *sec_data;
- bfd_size_type amt;
+ size_t amt;
/* Before looking through the symbol table, try to use a .stab
section to find the information. */
/* Also try examining DWARF2 debugging information. */
if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
filename_ptr, functionname_ptr,
- line_ptr, NULL, debug_sections, 0,
+ line_ptr, NULL, debug_sections,
&coff_data(abfd)->dwarf2_find_line_info))
return TRUE;
information. So try again, using a bias against the address sought. */
if (coff_data (abfd)->dwarf2_find_line_info != NULL)
{
- bfd_signed_vma bias;
+ bfd_signed_vma bias = 0;
/* Create a cache of the result for the next call. */
if (sec_data == NULL && section->owner == abfd)
if (sec_data != NULL && sec_data->saved_bias)
bias = sec_data->saved_bias;
- else
+ else if (symbols)
{
bias = _bfd_dwarf2_find_symbol_bias (symbols,
& coff_data (abfd)->dwarf2_find_line_info);
+
if (sec_data)
{
sec_data->saved_bias = TRUE;
&& _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section,
offset + bias,
filename_ptr, functionname_ptr,
- line_ptr, NULL, debug_sections, 0,
+ line_ptr, NULL, debug_sections,
&coff_data(abfd)->dwarf2_find_line_info))
return TRUE;
}
bfd_vma maxdiff;
/* Look through the C_FILE symbols to find the best one. */
- sec_vma = bfd_get_section_vma (abfd, section);
+ sec_vma = bfd_section_vma (section);
*filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
while (1)
maxdiff = offset + sec_vma - p2->u.syment.n_value;
}
+ if (p->u.syment.n_value >= cof->raw_syment_count)
+ break;
+
/* Avoid endless loops on erroneous files by ensuring that
we always move forward in the file. */
if (p >= cof->raw_syments + p->u.syment.n_value)
break;
p = cof->raw_syments + p->u.syment.n_value;
- if (p > pend || p->u.syment.n_sclass != C_FILE)
+ if (!p->is_sym || p->u.syment.n_sclass != C_FILE)
break;
}
}
coff_write_alien_symbol(). */
combined_entry_type * native;
- bfd_size_type amt = sizeof (* native);
+ size_t amt = sizeof (* native);
native = (combined_entry_type *) bfd_zalloc (abfd, amt);
if (native == NULL)
struct bfd_section_already_linked_hash_entry *already_linked_list;
struct coff_comdat_info *s_comdat;
+ if (sec->output_section == bfd_abs_section_ptr)
+ return FALSE;
+
flags = sec->flags;
if ((flags & SEC_LINK_ONCE) == 0)
return FALSE;
if ((flags & SEC_GROUP) != 0)
return FALSE;
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_section_name (sec);
s_comdat = bfd_coff_get_comdat_section (abfd, sec);
if (s_comdat != NULL)
/* ... and mark SEC_EXCLUDE for those that go. */
return coff_gc_sweep (abfd, info);
}
+
+/* Return name used to identify a comdat group. */
+
+const char *
+bfd_coff_group_name (bfd *abfd, const asection *sec)
+{
+ struct coff_comdat_info *ci = bfd_coff_get_comdat_section (abfd, sec);
+ if (ci != NULL)
+ return ci->name;
+ return NULL;
+}
+
+bfd_boolean
+_bfd_coff_close_and_cleanup (bfd *abfd)
+{
+ if (abfd->format == bfd_object
+ && bfd_family_coff (abfd)
+ && coff_data (abfd) != NULL)
+ {
+ /* PR 25447:
+ Do not clear the keep_syms and keep_strings flags.
+ These may have been set by pe_ILF_build_a_bfd() indicating
+ that the syms and strings pointers are not to be freed. */
+ if (!_bfd_coff_free_symbols (abfd))
+ return FALSE;
+ }
+ return _bfd_generic_close_and_cleanup (abfd);
+}