version 1.1.1.1, 2016/01/26 17:25:59 |
version 1.1.1.1.2.1, 2016/11/04 14:43:49 |
|
|
/* Support for the generic parts of COFF, for BFD. |
/* Support for the generic parts of COFF, for BFD. |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
Copyright (C) 1990-2015 Free Software Foundation, Inc. |
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
|
Free Software Foundation, Inc. |
|
Written by Cygnus Support. |
Written by Cygnus Support. |
|
|
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
Line 86 make_a_section_from_file (bfd *abfd, |
|
Line 84 make_a_section_from_file (bfd *abfd, |
|
strings = _bfd_coff_read_string_table (abfd); |
strings = _bfd_coff_read_string_table (abfd); |
if (strings == NULL) |
if (strings == NULL) |
return FALSE; |
return FALSE; |
/* FIXME: For extra safety, we should make sure that |
if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd)) |
strindex does not run us past the end, but right now we |
return FALSE; |
don't know the length of the string table. */ |
|
strings += strindex; |
strings += strindex; |
name = (char *) bfd_alloc (abfd, |
name = (char *) bfd_alloc (abfd, |
(bfd_size_type) strlen (strings) + 1); |
(bfd_size_type) strlen (strings) + 1 + 1); |
if (name == NULL) |
if (name == NULL) |
return FALSE; |
return FALSE; |
strcpy (name, strings); |
strcpy (name, strings); |
Line 102 make_a_section_from_file (bfd *abfd, |
|
Line 99 make_a_section_from_file (bfd *abfd, |
|
{ |
{ |
/* Assorted wastage to null-terminate the name, thanks AT&T! */ |
/* Assorted wastage to null-terminate the name, thanks AT&T! */ |
name = (char *) bfd_alloc (abfd, |
name = (char *) bfd_alloc (abfd, |
(bfd_size_type) sizeof (hdr->s_name) + 1); |
(bfd_size_type) sizeof (hdr->s_name) + 1 + 1); |
if (name == NULL) |
if (name == NULL) |
return FALSE; |
return FALSE; |
strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); |
strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); |
Line 146 make_a_section_from_file (bfd *abfd, |
|
Line 143 make_a_section_from_file (bfd *abfd, |
|
if (hdr->s_scnptr != 0) |
if (hdr->s_scnptr != 0) |
return_section->flags |= SEC_HAS_CONTENTS; |
return_section->flags |= SEC_HAS_CONTENTS; |
|
|
|
/* Compress/decompress DWARF debug sections with names: .debug_* and |
|
.zdebug_*, after the section flags is set. */ |
|
if ((flags & SEC_DEBUGGING) |
|
&& strlen (name) > 7 |
|
&& ((name[1] == 'd' && name[6] == '_') |
|
|| (strlen (name) > 8 && name[1] == 'z' && name[7] == '_'))) |
|
{ |
|
enum { nothing, compress, decompress } action = nothing; |
|
char *new_name = NULL; |
|
|
|
if (bfd_is_section_compressed (abfd, return_section)) |
|
{ |
|
/* Compressed section. Check if we should decompress. */ |
|
if ((abfd->flags & BFD_DECOMPRESS)) |
|
action = decompress; |
|
} |
|
else if (!bfd_is_section_compressed (abfd, return_section)) |
|
{ |
|
/* Normal section. Check if we should compress. */ |
|
if ((abfd->flags & BFD_COMPRESS) && return_section->size != 0) |
|
action = compress; |
|
} |
|
|
|
switch (action) |
|
{ |
|
case nothing: |
|
break; |
|
case compress: |
|
if (!bfd_init_section_compress_status (abfd, return_section)) |
|
{ |
|
(*_bfd_error_handler) |
|
(_("%B: unable to initialize compress status for section %s"), |
|
abfd, name); |
|
return FALSE; |
|
} |
|
if (return_section->compress_status == COMPRESS_SECTION_DONE) |
|
{ |
|
if (name[1] != 'z') |
|
{ |
|
unsigned int len = strlen (name); |
|
|
|
new_name = bfd_alloc (abfd, len + 2); |
|
if (new_name == NULL) |
|
return FALSE; |
|
new_name[0] = '.'; |
|
new_name[1] = 'z'; |
|
memcpy (new_name + 2, name + 1, len); |
|
} |
|
} |
|
break; |
|
case decompress: |
|
if (!bfd_init_section_decompress_status (abfd, return_section)) |
|
{ |
|
(*_bfd_error_handler) |
|
(_("%B: unable to initialize decompress status for section %s"), |
|
abfd, name); |
|
return FALSE; |
|
} |
|
if (name[1] == 'z') |
|
{ |
|
unsigned int len = strlen (name); |
|
|
|
new_name = bfd_alloc (abfd, len); |
|
if (new_name == NULL) |
|
return FALSE; |
|
new_name[0] = '.'; |
|
memcpy (new_name + 1, name + 2, len - 1); |
|
} |
|
break; |
|
} |
|
if (new_name != NULL) |
|
bfd_rename_section (abfd, return_section, new_name); |
|
} |
|
|
return result; |
return result; |
} |
} |
|
|
/* Read in a COFF object and make it into a BFD. This is used by |
/* Read in a COFF object and make it into a BFD. This is used by |
ECOFF as well. */ |
ECOFF as well. */ |
|
const bfd_target * |
static const bfd_target * |
coff_real_object_p (bfd *, |
|
unsigned, |
|
struct internal_filehdr *, |
|
struct internal_aouthdr *); |
|
const bfd_target * |
coff_real_object_p (bfd *abfd, |
coff_real_object_p (bfd *abfd, |
unsigned nscns, |
unsigned nscns, |
struct internal_filehdr *internal_f, |
struct internal_filehdr *internal_f, |
Line 294 coff_object_p (bfd *abfd) |
|
Line 369 coff_object_p (bfd *abfd) |
|
bfd_release (abfd, opthdr); |
bfd_release (abfd, opthdr); |
return NULL; |
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); |
|
|
bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a); |
bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a); |
bfd_release (abfd, opthdr); |
bfd_release (abfd, opthdr); |
} |
} |
Line 392 _bfd_coff_internal_syment_name (bfd *abf |
|
Line 471 _bfd_coff_internal_syment_name (bfd *abf |
|
if (strings == NULL) |
if (strings == NULL) |
return NULL; |
return NULL; |
} |
} |
|
/* PR 17910: Only check for string overflow if the length has been set. |
|
Some DLLs, eg those produced by Visual Studio, may not set the length field. */ |
|
if (obj_coff_strings_len (abfd) > 0 |
|
&& sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd)) |
|
return NULL; |
return strings + sym->_n._n_n._n_offset; |
return strings + sym->_n._n_n._n_offset; |
} |
} |
} |
} |
Line 555 coff_count_linenumbers (bfd *abfd) |
|
Line 639 coff_count_linenumbers (bfd *abfd) |
|
return total; |
return total; |
} |
} |
|
|
/* Takes a bfd and a symbol, returns a pointer to the coff specific |
|
area of the symbol if there is one. */ |
|
|
|
coff_symbol_type * |
|
coff_symbol_from (bfd *ignore_abfd ATTRIBUTE_UNUSED, |
|
asymbol *symbol) |
|
{ |
|
if (!bfd_family_coff (bfd_asymbol_bfd (symbol))) |
|
return (coff_symbol_type *) NULL; |
|
|
|
if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL) |
|
return (coff_symbol_type *) NULL; |
|
|
|
return (coff_symbol_type *) symbol; |
|
} |
|
|
|
static void |
static void |
fixup_symbol_value (bfd *abfd, |
fixup_symbol_value (bfd *abfd, |
coff_symbol_type *coff_symbol_ptr, |
coff_symbol_type *coff_symbol_ptr, |
struct internal_syment *syment) |
struct internal_syment *syment) |
{ |
{ |
/* Normalize the symbol flags. */ |
/* Normalize the symbol flags. */ |
if (coff_symbol_ptr->symbol.section |
if (coff_symbol_ptr->symbol.section |
&& bfd_is_com_section (coff_symbol_ptr->symbol.section)) |
&& bfd_is_com_section (coff_symbol_ptr->symbol.section)) |
{ |
{ |
/* A common symbol is undefined with a value. */ |
/* A common symbol is undefined with a value. */ |
Line 687 coff_renumber_symbols (bfd *bfd_ptr, int |
|
Line 755 coff_renumber_symbols (bfd *bfd_ptr, int |
|
|
|
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) |
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) |
{ |
{ |
coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); |
coff_symbol_type *coff_symbol_ptr; |
|
|
|
coff_symbol_ptr = coff_symbol_from (symbol_ptr_ptr[symbol_index]); |
symbol_ptr_ptr[symbol_index]->udata.i = symbol_index; |
symbol_ptr_ptr[symbol_index]->udata.i = symbol_index; |
if (coff_symbol_ptr && coff_symbol_ptr->native) |
if (coff_symbol_ptr && coff_symbol_ptr->native) |
{ |
{ |
combined_entry_type *s = coff_symbol_ptr->native; |
combined_entry_type *s = coff_symbol_ptr->native; |
int i; |
int i; |
|
|
|
BFD_ASSERT (s->is_sym); |
if (s->u.syment.n_sclass == C_FILE) |
if (s->u.syment.n_sclass == C_FILE) |
{ |
{ |
if (last_file != NULL) |
if (last_file != NULL) |
Line 730 coff_mangle_symbols (bfd *bfd_ptr) |
|
Line 801 coff_mangle_symbols (bfd *bfd_ptr) |
|
|
|
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) |
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) |
{ |
{ |
coff_symbol_type *coff_symbol_ptr = |
coff_symbol_type *coff_symbol_ptr; |
coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); |
|
|
|
|
coff_symbol_ptr = coff_symbol_from (symbol_ptr_ptr[symbol_index]); |
if (coff_symbol_ptr && coff_symbol_ptr->native) |
if (coff_symbol_ptr && coff_symbol_ptr->native) |
{ |
{ |
int i; |
int i; |
combined_entry_type *s = coff_symbol_ptr->native; |
combined_entry_type *s = coff_symbol_ptr->native; |
|
|
|
BFD_ASSERT (s->is_sym); |
if (s->fix_value) |
if (s->fix_value) |
{ |
{ |
/* FIXME: We should use a union here. */ |
/* FIXME: We should use a union here. */ |
Line 761 coff_mangle_symbols (bfd *bfd_ptr) |
|
Line 833 coff_mangle_symbols (bfd *bfd_ptr) |
|
for (i = 0; i < s->u.syment.n_numaux; i++) |
for (i = 0; i < s->u.syment.n_numaux; i++) |
{ |
{ |
combined_entry_type *a = s + i + 1; |
combined_entry_type *a = s + i + 1; |
|
|
|
BFD_ASSERT (! a->is_sym); |
if (a->fix_tag) |
if (a->fix_tag) |
{ |
{ |
a->u.auxent.x_sym.x_tagndx.l = |
a->u.auxent.x_sym.x_tagndx.l = |
Line 804 coff_fix_symbol_name (bfd *abfd, |
|
Line 878 coff_fix_symbol_name (bfd *abfd, |
|
} |
} |
name_length = strlen (name); |
name_length = strlen (name); |
|
|
|
BFD_ASSERT (native->is_sym); |
if (native->u.syment.n_sclass == C_FILE |
if (native->u.syment.n_sclass == C_FILE |
&& native->u.syment.n_numaux > 0) |
&& native->u.syment.n_numaux > 0) |
{ |
{ |
Line 819 coff_fix_symbol_name (bfd *abfd, |
|
Line 894 coff_fix_symbol_name (bfd *abfd, |
|
else |
else |
strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); |
strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); |
|
|
|
BFD_ASSERT (! (native + 1)->is_sym); |
auxent = &(native + 1)->u.auxent; |
auxent = &(native + 1)->u.auxent; |
|
|
filnmlen = bfd_coff_filnmlen (abfd); |
filnmlen = bfd_coff_filnmlen (abfd); |
Line 921 coff_write_symbol (bfd *abfd, |
|
Line 997 coff_write_symbol (bfd *abfd, |
|
void * buf; |
void * buf; |
bfd_size_type symesz; |
bfd_size_type symesz; |
|
|
|
BFD_ASSERT (native->is_sym); |
|
|
if (native->u.syment.n_sclass == C_FILE) |
if (native->u.syment.n_sclass == C_FILE) |
symbol->flags |= BSF_DEBUGGING; |
symbol->flags |= BSF_DEBUGGING; |
|
|
Line 961 coff_write_symbol (bfd *abfd, |
|
Line 1039 coff_write_symbol (bfd *abfd, |
|
return FALSE; |
return FALSE; |
for (j = 0; j < native->u.syment.n_numaux; j++) |
for (j = 0; j < native->u.syment.n_numaux; j++) |
{ |
{ |
|
BFD_ASSERT (! (native + j + 1)->is_sym); |
bfd_coff_swap_aux_out (abfd, |
bfd_coff_swap_aux_out (abfd, |
&((native + j + 1)->u.auxent), |
&((native + j + 1)->u.auxent), |
type, n_sclass, (int) j, |
type, n_sclass, (int) j, |
Line 1006 coff_write_alien_symbol (bfd *abfd, |
|
Line 1085 coff_write_alien_symbol (bfd *abfd, |
|
{ |
{ |
symbol->name = ""; |
symbol->name = ""; |
if (isym != NULL) |
if (isym != NULL) |
memset (isym, 0, sizeof(*isym)); |
memset (isym, 0, sizeof (*isym)); |
return TRUE; |
return TRUE; |
} |
} |
native = dummy; |
native = dummy; |
|
native->is_sym = TRUE; |
|
native[1].is_sym = FALSE; |
native->u.syment.n_type = T_NULL; |
native->u.syment.n_type = T_NULL; |
native->u.syment.n_flags = 0; |
native->u.syment.n_flags = 0; |
native->u.syment.n_numaux = 0; |
native->u.syment.n_numaux = 0; |
Line 1036 coff_write_alien_symbol (bfd *abfd, |
|
Line 1117 coff_write_alien_symbol (bfd *abfd, |
|
name to keep it from being put in the string table. */ |
name to keep it from being put in the string table. */ |
symbol->name = ""; |
symbol->name = ""; |
if (isym != NULL) |
if (isym != NULL) |
memset (isym, 0, sizeof(*isym)); |
memset (isym, 0, sizeof (*isym)); |
return TRUE; |
return TRUE; |
} |
} |
else |
else |
Line 1050 coff_write_alien_symbol (bfd *abfd, |
|
Line 1131 coff_write_alien_symbol (bfd *abfd, |
|
/* Copy the any flags from the file header into the symbol. |
/* Copy the any flags from the file header into the symbol. |
FIXME: Why? */ |
FIXME: Why? */ |
{ |
{ |
coff_symbol_type *c = coff_symbol_from (abfd, symbol); |
coff_symbol_type *c = coff_symbol_from (symbol); |
if (c != (coff_symbol_type *) NULL) |
if (c != (coff_symbol_type *) NULL) |
native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags; |
native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags; |
} |
} |
Line 1095 coff_write_native_symbol (bfd *abfd, |
|
Line 1176 coff_write_native_symbol (bfd *abfd, |
|
return TRUE; |
return TRUE; |
} |
} |
|
|
|
BFD_ASSERT (native->is_sym); |
/* If this symbol has an associated line number, we must store the |
/* If this symbol has an associated line number, we must store the |
symbol index in the line number field. We also tag the auxent to |
symbol index in the line number field. We also tag the auxent to |
point to the right place in the lineno table. */ |
point to the right place in the lineno table. */ |
Line 1181 coff_write_symbols (bfd *abfd) |
|
Line 1263 coff_write_symbols (bfd *abfd) |
|
for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) |
for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) |
{ |
{ |
asymbol *symbol = *p; |
asymbol *symbol = *p; |
coff_symbol_type *c_symbol = coff_symbol_from (abfd, symbol); |
coff_symbol_type *c_symbol = coff_symbol_from (symbol); |
|
|
if (c_symbol == (coff_symbol_type *) NULL |
if (c_symbol == (coff_symbol_type *) NULL |
|| c_symbol->native == (combined_entry_type *) NULL) |
|| c_symbol->native == (combined_entry_type *) NULL) |
Line 1204 coff_write_symbols (bfd *abfd) |
|
Line 1286 coff_write_symbols (bfd *abfd) |
|
symbol which has no associated section and we do not have to |
symbol which has no associated section and we do not have to |
worry about this, all we need to know is that it is local. */ |
worry about this, all we need to know is that it is local. */ |
current_error_handler = bfd_set_error_handler (null_error_handler); |
current_error_handler = bfd_set_error_handler (null_error_handler); |
|
BFD_ASSERT (c_symbol->native->is_sym); |
sym_class = bfd_coff_classify_symbol (abfd, |
sym_class = bfd_coff_classify_symbol (abfd, |
&c_symbol->native->u.syment); |
&c_symbol->native->u.syment); |
(void) bfd_set_error_handler (current_error_handler); |
(void) bfd_set_error_handler (current_error_handler); |
|
|
n_sclass = &c_symbol->native->u.syment.n_sclass; |
n_sclass = &c_symbol->native->u.syment.n_sclass; |
Line 1280 coff_write_symbols (bfd *abfd) |
|
Line 1363 coff_write_symbols (bfd *abfd) |
|
{ |
{ |
asymbol *q = *p; |
asymbol *q = *p; |
size_t name_length = strlen (q->name); |
size_t name_length = strlen (q->name); |
coff_symbol_type *c_symbol = coff_symbol_from (abfd, q); |
coff_symbol_type *c_symbol = coff_symbol_from (q); |
size_t maxlen; |
size_t maxlen; |
|
|
/* Figure out whether the symbol name should go in the string |
/* Figure out whether the symbol name should go in the string |
Line 1296 coff_write_symbols (bfd *abfd) |
|
Line 1379 coff_write_symbols (bfd *abfd) |
|
file name, nor does it go in the .debug section. */ |
file name, nor does it go in the .debug section. */ |
maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN; |
maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN; |
|
|
|
else if (! c_symbol->native->is_sym) |
|
maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN; |
|
|
else if (bfd_coff_symname_in_debug (abfd, |
else if (bfd_coff_symname_in_debug (abfd, |
&c_symbol->native->u.syment)) |
&c_symbol->native->u.syment)) |
/* This symbol name is in the XCOFF .debug section. |
/* This symbol name is in the XCOFF .debug section. |
Line 1386 coff_write_linenumbers (bfd *abfd) |
|
Line 1472 coff_write_linenumbers (bfd *abfd) |
|
{ |
{ |
/* Found a linenumber entry, output. */ |
/* Found a linenumber entry, output. */ |
struct internal_lineno out; |
struct internal_lineno out; |
|
|
memset ((void *) & out, 0, sizeof (out)); |
memset ((void *) & out, 0, sizeof (out)); |
out.l_lnno = 0; |
out.l_lnno = 0; |
out.l_addr.l_symndx = l->u.offset; |
out.l_addr.l_symndx = l->u.offset; |
Line 1433 coff_pointerize_aux (bfd *abfd, |
|
Line 1520 coff_pointerize_aux (bfd *abfd, |
|
unsigned int type = symbol->u.syment.n_type; |
unsigned int type = symbol->u.syment.n_type; |
unsigned int n_sclass = symbol->u.syment.n_sclass; |
unsigned int n_sclass = symbol->u.syment.n_sclass; |
|
|
|
BFD_ASSERT (symbol->is_sym); |
if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) |
if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) |
{ |
{ |
if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) |
if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) |
Line 1446 coff_pointerize_aux (bfd *abfd, |
|
Line 1534 coff_pointerize_aux (bfd *abfd, |
|
if (n_sclass == C_FILE) |
if (n_sclass == C_FILE) |
return; |
return; |
|
|
|
BFD_ASSERT (! auxent->is_sym); |
/* Otherwise patch up. */ |
/* Otherwise patch up. */ |
#define N_TMASK coff_data (abfd)->local_n_tmask |
#define N_TMASK coff_data (abfd)->local_n_tmask |
#define N_BTSHFT coff_data (abfd)->local_n_btshft |
#define N_BTSHFT coff_data (abfd)->local_n_btshft |
|
|
if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK |
if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK |
|| n_sclass == C_FCN) |
|| 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 > 0) |
Line 1473 coff_pointerize_aux (bfd *abfd, |
|
Line 1562 coff_pointerize_aux (bfd *abfd, |
|
we didn't want to go to the trouble until someone needed it. */ |
we didn't want to go to the trouble until someone needed it. */ |
|
|
static char * |
static char * |
build_debug_section (bfd *abfd) |
build_debug_section (bfd *abfd, asection ** sect_return) |
{ |
{ |
char *debug_section; |
char *debug_section; |
file_ptr position; |
file_ptr position; |
Line 1501 build_debug_section (bfd *abfd) |
|
Line 1590 build_debug_section (bfd *abfd) |
|
|| bfd_bread (debug_section, sec_size, abfd) != sec_size |
|| bfd_bread (debug_section, sec_size, abfd) != sec_size |
|| bfd_seek (abfd, position, SEEK_SET) != 0) |
|| bfd_seek (abfd, position, SEEK_SET) != 0) |
return NULL; |
return NULL; |
|
|
|
* sect_return = sect; |
return debug_section; |
return debug_section; |
} |
} |
|
|
Line 1563 _bfd_coff_get_external_symbols (bfd *abf |
|
Line 1654 _bfd_coff_get_external_symbols (bfd *abf |
|
|
|
/* Read in the external strings. The strings are not loaded until |
/* Read in the external strings. The strings are not loaded until |
they are needed. This is because we have no simple way of |
they are needed. This is because we have no simple way of |
detecting a missing string table in an archive. */ |
detecting a missing string table in an archive. If the strings |
|
are loaded then the STRINGS and STRINGS_LEN fields in the |
|
coff_tdata structure will be set. */ |
|
|
const char * |
const char * |
_bfd_coff_read_string_table (bfd *abfd) |
_bfd_coff_read_string_table (bfd *abfd) |
Line 1613 _bfd_coff_read_string_table (bfd *abfd) |
|
Line 1706 _bfd_coff_read_string_table (bfd *abfd) |
|
return NULL; |
return NULL; |
} |
} |
|
|
strings = (char *) bfd_malloc (strsize); |
strings = (char *) bfd_malloc (strsize + 1); |
if (strings == NULL) |
if (strings == NULL) |
return NULL; |
return NULL; |
|
|
|
/* PR 17521 file: 079-54929-0.004. |
|
A corrupt file could contain an index that points into the first |
|
STRING_SIZE_SIZE bytes of the string table, so make sure that |
|
they are zero. */ |
|
memset (strings, 0, STRING_SIZE_SIZE); |
|
|
if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd) |
if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd) |
!= strsize - STRING_SIZE_SIZE) |
!= strsize - STRING_SIZE_SIZE) |
{ |
{ |
Line 1625 _bfd_coff_read_string_table (bfd *abfd) |
|
Line 1724 _bfd_coff_read_string_table (bfd *abfd) |
|
} |
} |
|
|
obj_coff_strings (abfd) = strings; |
obj_coff_strings (abfd) = strings; |
|
obj_coff_strings_len (abfd) = strsize; |
|
/* Terminate the string table, just in case. */ |
|
strings[strsize] = 0; |
return strings; |
return strings; |
} |
} |
|
|
Line 1645 _bfd_coff_free_symbols (bfd *abfd) |
|
Line 1746 _bfd_coff_free_symbols (bfd *abfd) |
|
{ |
{ |
free (obj_coff_strings (abfd)); |
free (obj_coff_strings (abfd)); |
obj_coff_strings (abfd) = NULL; |
obj_coff_strings (abfd) = NULL; |
|
obj_coff_strings_len (abfd) = 0; |
} |
} |
return TRUE; |
return TRUE; |
} |
} |
Line 1665 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1767 coff_get_normalized_symtab (bfd *abfd) |
|
char *raw_src; |
char *raw_src; |
char *raw_end; |
char *raw_end; |
const char *string_table = NULL; |
const char *string_table = NULL; |
char *debug_section = NULL; |
asection * debug_sec = NULL; |
|
char *debug_sec_data = NULL; |
bfd_size_type size; |
bfd_size_type size; |
|
|
if (obj_raw_syments (abfd) != NULL) |
if (obj_raw_syments (abfd) != NULL) |
return obj_raw_syments (abfd); |
return obj_raw_syments (abfd); |
|
|
|
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) * sizeof (combined_entry_type); |
internal = (combined_entry_type *) bfd_zalloc (abfd, size); |
internal = (combined_entry_type *) bfd_zalloc (abfd, size); |
if (internal == NULL && size != 0) |
if (internal == NULL && size != 0) |
return NULL; |
return NULL; |
internal_end = internal + obj_raw_syment_count (abfd); |
internal_end = internal + obj_raw_syment_count (abfd); |
|
|
if (! _bfd_coff_get_external_symbols (abfd)) |
|
return NULL; |
|
|
|
raw_src = (char *) obj_coff_external_syms (abfd); |
raw_src = (char *) obj_coff_external_syms (abfd); |
|
|
/* Mark the end of the symbols. */ |
/* Mark the end of the symbols. */ |
Line 1694 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1797 coff_get_normalized_symtab (bfd *abfd) |
|
raw_src < raw_end; |
raw_src < raw_end; |
raw_src += symesz, internal_ptr++) |
raw_src += symesz, internal_ptr++) |
{ |
{ |
|
|
unsigned int i; |
unsigned int i; |
|
|
bfd_coff_swap_sym_in (abfd, (void *) raw_src, |
bfd_coff_swap_sym_in (abfd, (void *) raw_src, |
(void *) & internal_ptr->u.syment); |
(void *) & internal_ptr->u.syment); |
symbol_ptr = internal_ptr; |
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; |
for (i = 0; |
i < symbol_ptr->u.syment.n_numaux; |
i < symbol_ptr->u.syment.n_numaux; |
i++) |
i++) |
{ |
{ |
internal_ptr++; |
internal_ptr++; |
|
/* PR 17512: Prevent buffer overrun. */ |
|
if (internal_ptr >= internal_end) |
|
{ |
|
bfd_release (abfd, internal); |
|
return NULL; |
|
} |
|
|
raw_src += symesz; |
raw_src += symesz; |
bfd_coff_swap_aux_in (abfd, (void *) raw_src, |
bfd_coff_swap_aux_in (abfd, (void *) raw_src, |
symbol_ptr->u.syment.n_type, |
symbol_ptr->u.syment.n_type, |
symbol_ptr->u.syment.n_sclass, |
symbol_ptr->u.syment.n_sclass, |
(int) i, symbol_ptr->u.syment.n_numaux, |
(int) i, symbol_ptr->u.syment.n_numaux, |
&(internal_ptr->u.auxent)); |
&(internal_ptr->u.auxent)); |
|
|
|
internal_ptr->is_sym = FALSE; |
coff_pointerize_aux (abfd, internal, symbol_ptr, i, |
coff_pointerize_aux (abfd, internal, symbol_ptr, i, |
internal_ptr); |
internal_ptr); |
} |
} |
Line 1724 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1847 coff_get_normalized_symtab (bfd *abfd) |
|
for (internal_ptr = internal; internal_ptr < internal_end; |
for (internal_ptr = internal; internal_ptr < internal_end; |
internal_ptr++) |
internal_ptr++) |
{ |
{ |
|
BFD_ASSERT (internal_ptr->is_sym); |
|
|
if (internal_ptr->u.syment.n_sclass == C_FILE |
if (internal_ptr->u.syment.n_sclass == C_FILE |
&& internal_ptr->u.syment.n_numaux > 0) |
&& internal_ptr->u.syment.n_numaux > 0) |
{ |
{ |
|
combined_entry_type * aux = internal_ptr + 1; |
|
|
/* Make a file symbol point to the name in the auxent, since |
/* Make a file symbol point to the name in the auxent, since |
the text ".file" is redundant. */ |
the text ".file" is redundant. */ |
if ((internal_ptr + 1)->u.auxent.x_file.x_n.x_zeroes == 0) |
BFD_ASSERT (! aux->is_sym); |
|
|
|
if (aux->u.auxent.x_file.x_n.x_zeroes == 0) |
{ |
{ |
/* The filename is a long one, point into the string table. */ |
/* The filename is a long one, point into the string table. */ |
if (string_table == NULL) |
if (string_table == NULL) |
Line 1739 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1868 coff_get_normalized_symtab (bfd *abfd) |
|
return NULL; |
return NULL; |
} |
} |
|
|
internal_ptr->u.syment._n._n_n._n_offset = |
if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_offset) |
((bfd_hostptr_t) |
>= obj_coff_strings_len (abfd)) |
(string_table |
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); |
+ (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset)); |
else |
|
internal_ptr->u.syment._n._n_n._n_offset = |
|
(bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_offset)); |
} |
} |
else |
else |
{ |
{ |
Line 1752 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1883 coff_get_normalized_symtab (bfd *abfd) |
|
if (internal_ptr->u.syment.n_numaux > 1 |
if (internal_ptr->u.syment.n_numaux > 1 |
&& coff_data (abfd)->pe) |
&& coff_data (abfd)->pe) |
internal_ptr->u.syment._n._n_n._n_offset = |
internal_ptr->u.syment._n._n_n._n_offset = |
((bfd_hostptr_t) |
(bfd_hostptr_t) |
copy_name (abfd, |
copy_name (abfd, |
(internal_ptr + 1)->u.auxent.x_file.x_fname, |
aux->u.auxent.x_file.x_fname, |
internal_ptr->u.syment.n_numaux * symesz)); |
internal_ptr->u.syment.n_numaux * symesz); |
else |
else |
internal_ptr->u.syment._n._n_n._n_offset = |
internal_ptr->u.syment._n._n_n._n_offset = |
((bfd_hostptr_t) |
((bfd_hostptr_t) |
copy_name (abfd, |
copy_name (abfd, |
(internal_ptr + 1)->u.auxent.x_file.x_fname, |
aux->u.auxent.x_file.x_fname, |
(size_t) bfd_coff_filnmlen (abfd))); |
(size_t) bfd_coff_filnmlen (abfd))); |
} |
} |
} |
} |
Line 1797 coff_get_normalized_symtab (bfd *abfd) |
|
Line 1928 coff_get_normalized_symtab (bfd *abfd) |
|
if (string_table == NULL) |
if (string_table == NULL) |
return NULL; |
return NULL; |
} |
} |
internal_ptr->u.syment._n._n_n._n_offset = |
if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd) |
((bfd_hostptr_t) |
|| string_table + internal_ptr->u.syment._n._n_n._n_offset < string_table) |
(string_table |
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); |
+ internal_ptr->u.syment._n._n_n._n_offset)); |
else |
|
internal_ptr->u.syment._n._n_n._n_offset = |
|
((bfd_hostptr_t) |
|
(string_table |
|
+ internal_ptr->u.syment._n._n_n._n_offset)); |
} |
} |
else |
else |
{ |
{ |
/* Long name in debug section. Very similar. */ |
/* Long name in debug section. Very similar. */ |
if (debug_section == NULL) |
if (debug_sec_data == NULL) |
debug_section = build_debug_section (abfd); |
debug_sec_data = build_debug_section (abfd, & debug_sec); |
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) |
if (debug_sec_data != NULL) |
(debug_section + internal_ptr->u.syment._n._n_n._n_offset); |
{ |
|
BFD_ASSERT (debug_sec != NULL); |
|
/* PR binutils/17512: Catch out of range offsets into the debug data. */ |
|
if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size |
|
|| debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset < debug_sec_data) |
|
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); |
|
else |
|
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) |
|
(debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset); |
|
} |
|
else |
|
internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) ""; |
} |
} |
} |
} |
internal_ptr += internal_ptr->u.syment.n_numaux; |
internal_ptr += internal_ptr->u.syment.n_numaux; |
Line 1841 coff_make_empty_symbol (bfd *abfd) |
|
Line 1987 coff_make_empty_symbol (bfd *abfd) |
|
if (new_symbol == NULL) |
if (new_symbol == NULL) |
return NULL; |
return NULL; |
new_symbol->symbol.section = 0; |
new_symbol->symbol.section = 0; |
new_symbol->native = 0; |
new_symbol->native = NULL; |
new_symbol->lineno = NULL; |
new_symbol->lineno = NULL; |
new_symbol->done_lineno = FALSE; |
new_symbol->done_lineno = FALSE; |
new_symbol->symbol.the_bfd = abfd; |
new_symbol->symbol.the_bfd = abfd; |
Line 1867 coff_bfd_make_debug_symbol (bfd *abfd, |
|
Line 2013 coff_bfd_make_debug_symbol (bfd *abfd, |
|
new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt); |
new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt); |
if (!new_symbol->native) |
if (!new_symbol->native) |
return NULL; |
return NULL; |
|
new_symbol->native->is_sym = TRUE; |
new_symbol->symbol.section = bfd_abs_section_ptr; |
new_symbol->symbol.section = bfd_abs_section_ptr; |
new_symbol->symbol.flags = BSF_DEBUGGING; |
new_symbol->symbol.flags = BSF_DEBUGGING; |
new_symbol->lineno = NULL; |
new_symbol->lineno = NULL; |
new_symbol->done_lineno = FALSE; |
new_symbol->done_lineno = FALSE; |
new_symbol->symbol.the_bfd = abfd; |
new_symbol->symbol.the_bfd = abfd; |
|
|
return & new_symbol->symbol; |
return & new_symbol->symbol; |
} |
} |
|
|
Line 1882 coff_get_symbol_info (bfd *abfd, asymbol |
|
Line 2029 coff_get_symbol_info (bfd *abfd, asymbol |
|
bfd_symbol_info (symbol, ret); |
bfd_symbol_info (symbol, ret); |
|
|
if (coffsymbol (symbol)->native != NULL |
if (coffsymbol (symbol)->native != NULL |
&& coffsymbol (symbol)->native->fix_value) |
&& coffsymbol (symbol)->native->fix_value |
|
&& coffsymbol (symbol)->native->is_sym) |
ret->value = coffsymbol (symbol)->native->u.syment.n_value - |
ret->value = coffsymbol (symbol)->native->u.syment.n_value - |
(bfd_hostptr_t) obj_raw_syments (abfd); |
(bfd_hostptr_t) obj_raw_syments (abfd); |
} |
} |
|
|
/* Return the COFF syment for a symbol. */ |
|
|
|
bfd_boolean |
|
bfd_coff_get_syment (bfd *abfd, |
|
asymbol *symbol, |
|
struct internal_syment *psyment) |
|
{ |
|
coff_symbol_type *csym; |
|
|
|
csym = coff_symbol_from (abfd, symbol); |
|
if (csym == NULL || csym->native == NULL) |
|
{ |
|
bfd_set_error (bfd_error_invalid_operation); |
|
return FALSE; |
|
} |
|
|
|
*psyment = csym->native->u.syment; |
|
|
|
if (csym->native->fix_value) |
|
psyment->n_value = psyment->n_value - |
|
(bfd_hostptr_t) obj_raw_syments (abfd); |
|
|
|
/* FIXME: We should handle fix_line here. */ |
|
|
|
return TRUE; |
|
} |
|
|
|
/* Return the COFF auxent for a symbol. */ |
|
|
|
bfd_boolean |
|
bfd_coff_get_auxent (bfd *abfd, |
|
asymbol *symbol, |
|
int indx, |
|
union internal_auxent *pauxent) |
|
{ |
|
coff_symbol_type *csym; |
|
combined_entry_type *ent; |
|
|
|
csym = coff_symbol_from (abfd, symbol); |
|
|
|
if (csym == NULL |
|
|| csym->native == NULL |
|
|| indx >= csym->native->u.syment.n_numaux) |
|
{ |
|
bfd_set_error (bfd_error_invalid_operation); |
|
return FALSE; |
|
} |
|
|
|
ent = csym->native + indx + 1; |
|
|
|
*pauxent = ent->u.auxent; |
|
|
|
if (ent->fix_tag) |
|
pauxent->x_sym.x_tagndx.l = |
|
((combined_entry_type *) pauxent->x_sym.x_tagndx.p |
|
- obj_raw_syments (abfd)); |
|
|
|
if (ent->fix_end) |
|
pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l = |
|
((combined_entry_type *) pauxent->x_sym.x_fcnary.x_fcn.x_endndx.p |
|
- obj_raw_syments (abfd)); |
|
|
|
if (ent->fix_scnlen) |
|
pauxent->x_csect.x_scnlen.l = |
|
((combined_entry_type *) pauxent->x_csect.x_scnlen.p |
|
- obj_raw_syments (abfd)); |
|
|
|
return TRUE; |
|
} |
|
|
|
/* Print out information about COFF symbol. */ |
/* Print out information about COFF symbol. */ |
|
|
void |
void |
Line 1990 coff_print_symbol (bfd *abfd, |
|
Line 2068 coff_print_symbol (bfd *abfd, |
|
|
|
fprintf (file, "[%3ld]", (long) (combined - root)); |
fprintf (file, "[%3ld]", (long) (combined - root)); |
|
|
|
/* PR 17512: file: 079-33786-0.001:0.1. */ |
|
if (combined < obj_raw_syments (abfd) |
|
|| combined >= obj_raw_syments (abfd) + obj_raw_syment_count (abfd)) |
|
{ |
|
fprintf (file, _("<corrupt info> %s"), symbol->name); |
|
break; |
|
} |
|
|
|
BFD_ASSERT (combined->is_sym); |
if (! combined->fix_value) |
if (! combined->fix_value) |
val = (bfd_vma) combined->u.syment.n_value; |
val = (bfd_vma) combined->u.syment.n_value; |
else |
else |
Line 2009 coff_print_symbol (bfd *abfd, |
|
Line 2096 coff_print_symbol (bfd *abfd, |
|
combined_entry_type *auxp = combined + aux + 1; |
combined_entry_type *auxp = combined + aux + 1; |
long tagndx; |
long tagndx; |
|
|
|
BFD_ASSERT (! auxp->is_sym); |
if (auxp->fix_tag) |
if (auxp->fix_tag) |
tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root; |
tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root; |
else |
else |
Line 2083 coff_print_symbol (bfd *abfd, |
|
Line 2171 coff_print_symbol (bfd *abfd, |
|
l++; |
l++; |
while (l->line_number) |
while (l->line_number) |
{ |
{ |
fprintf (file, "\n%4d : ", l->line_number); |
if (l->line_number > 0) |
bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma); |
{ |
|
fprintf (file, "\n%4d : ", l->line_number); |
|
bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma); |
|
} |
l++; |
l++; |
} |
} |
} |
} |
Line 2119 _bfd_coff_is_local_label_name (bfd *abfd |
|
Line 2210 _bfd_coff_is_local_label_name (bfd *abfd |
|
|
|
bfd_boolean |
bfd_boolean |
coff_find_nearest_line_with_names (bfd *abfd, |
coff_find_nearest_line_with_names (bfd *abfd, |
const struct dwarf_debug_section *debug_sections, |
|
asection *section, |
|
asymbol **symbols, |
asymbol **symbols, |
|
asection *section, |
bfd_vma offset, |
bfd_vma offset, |
const char **filename_ptr, |
const char **filename_ptr, |
const char **functionname_ptr, |
const char **functionname_ptr, |
unsigned int *line_ptr) |
unsigned int *line_ptr, |
|
const struct dwarf_debug_section *debug_sections) |
{ |
{ |
bfd_boolean found; |
bfd_boolean found; |
unsigned int i; |
unsigned int i; |
Line 2150 coff_find_nearest_line_with_names (bfd * |
|
Line 2241 coff_find_nearest_line_with_names (bfd * |
|
return TRUE; |
return TRUE; |
|
|
/* Also try examining DWARF2 debugging information. */ |
/* Also try examining DWARF2 debugging information. */ |
if (_bfd_dwarf2_find_nearest_line (abfd, debug_sections, |
if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, |
section, symbols, offset, |
|
filename_ptr, functionname_ptr, |
filename_ptr, functionname_ptr, |
line_ptr, NULL, 0, |
line_ptr, NULL, debug_sections, 0, |
&coff_data(abfd)->dwarf2_find_line_info)) |
&coff_data(abfd)->dwarf2_find_line_info)) |
return TRUE; |
return TRUE; |
|
|
|
/* If the DWARF lookup failed, but there is DWARF information available |
|
then the problem might be that the file has been rebased. This tool |
|
changes the VMAs of all the sections, but it does not update the DWARF |
|
information. So try again, using a bias against the address sought. */ |
|
if (coff_data (abfd)->dwarf2_find_line_info != NULL) |
|
{ |
|
bfd_signed_vma bias; |
|
|
|
bias = _bfd_dwarf2_find_symbol_bias (symbols, |
|
& coff_data (abfd)->dwarf2_find_line_info); |
|
|
|
if (bias |
|
&& _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, |
|
offset + bias, |
|
filename_ptr, functionname_ptr, |
|
line_ptr, NULL, debug_sections, 0, |
|
&coff_data(abfd)->dwarf2_find_line_info)) |
|
return TRUE; |
|
} |
|
|
*filename_ptr = 0; |
*filename_ptr = 0; |
*functionname_ptr = 0; |
*functionname_ptr = 0; |
*line_ptr = 0; |
*line_ptr = 0; |
Line 2176 coff_find_nearest_line_with_names (bfd * |
|
Line 2286 coff_find_nearest_line_with_names (bfd * |
|
pend = p + cof->raw_syment_count; |
pend = p + cof->raw_syment_count; |
while (p < pend) |
while (p < pend) |
{ |
{ |
|
BFD_ASSERT (p->is_sym); |
if (p->u.syment.n_sclass == C_FILE) |
if (p->u.syment.n_sclass == C_FILE) |
break; |
break; |
p += 1 + p->u.syment.n_numaux; |
p += 1 + p->u.syment.n_numaux; |
Line 2199 coff_find_nearest_line_with_names (bfd * |
|
Line 2310 coff_find_nearest_line_with_names (bfd * |
|
p2 < pend; |
p2 < pend; |
p2 += 1 + p2->u.syment.n_numaux) |
p2 += 1 + p2->u.syment.n_numaux) |
{ |
{ |
|
BFD_ASSERT (p2->is_sym); |
if (p2->u.syment.n_scnum > 0 |
if (p2->u.syment.n_scnum > 0 |
&& (section |
&& (section |
== coff_section_from_bfd_index (abfd, |
== coff_section_from_bfd_index (abfd, |
Line 2210 coff_find_nearest_line_with_names (bfd * |
|
Line 2322 coff_find_nearest_line_with_names (bfd * |
|
break; |
break; |
} |
} |
} |
} |
|
if (p2 >= pend) |
|
break; |
|
|
file_addr = (bfd_vma) p2->u.syment.n_value; |
file_addr = (bfd_vma) p2->u.syment.n_value; |
/* PR 11512: Include the section address of the function name symbol. */ |
/* PR 11512: Include the section address of the function name symbol. */ |
Line 2274 coff_find_nearest_line_with_names (bfd * |
|
Line 2388 coff_find_nearest_line_with_names (bfd * |
|
if (coff->native) |
if (coff->native) |
{ |
{ |
combined_entry_type *s = coff->native; |
combined_entry_type *s = coff->native; |
|
|
|
BFD_ASSERT (s->is_sym); |
s = s + 1 + s->u.syment.n_numaux; |
s = s + 1 + s->u.syment.n_numaux; |
|
|
/* In XCOFF a debugging symbol can follow the |
/* In XCOFF a debugging symbol can follow the |
Line 2286 coff_find_nearest_line_with_names (bfd * |
|
Line 2402 coff_find_nearest_line_with_names (bfd * |
|
{ |
{ |
/* The linenumber is stored in the auxent. */ |
/* The linenumber is stored in the auxent. */ |
union internal_auxent *a = &((s + 1)->u.auxent); |
union internal_auxent *a = &((s + 1)->u.auxent); |
|
|
line_base = a->x_sym.x_misc.x_lnsz.x_lnno; |
line_base = a->x_sym.x_misc.x_lnsz.x_lnno; |
*line_ptr = line_base; |
*line_ptr = line_base; |
} |
} |
Line 2335 coff_find_nearest_line_with_names (bfd * |
|
Line 2452 coff_find_nearest_line_with_names (bfd * |
|
|
|
bfd_boolean |
bfd_boolean |
coff_find_nearest_line (bfd *abfd, |
coff_find_nearest_line (bfd *abfd, |
asection *section, |
|
asymbol **symbols, |
asymbol **symbols, |
|
asection *section, |
bfd_vma offset, |
bfd_vma offset, |
const char **filename_ptr, |
const char **filename_ptr, |
const char **functionname_ptr, |
const char **functionname_ptr, |
unsigned int *line_ptr) |
unsigned int *line_ptr, |
|
unsigned int *discriminator_ptr) |
{ |
{ |
return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections, |
if (discriminator_ptr) |
section, symbols, offset, |
*discriminator_ptr = 0; |
|
return coff_find_nearest_line_with_names (abfd, symbols, section, offset, |
filename_ptr, functionname_ptr, |
filename_ptr, functionname_ptr, |
line_ptr); |
line_ptr, dwarf_debug_sections); |
} |
} |
|
|
bfd_boolean |
bfd_boolean |
Line 2367 coff_sizeof_headers (bfd *abfd, struct b |
|
Line 2486 coff_sizeof_headers (bfd *abfd, struct b |
|
{ |
{ |
size_t size; |
size_t size; |
|
|
if (!info->relocatable) |
if (!bfd_link_relocatable (info)) |
size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); |
size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); |
else |
else |
size = bfd_coff_filhsz (abfd); |
size = bfd_coff_filhsz (abfd); |
Line 2385 bfd_coff_set_symbol_class (bfd * |
|
Line 2504 bfd_coff_set_symbol_class (bfd * |
|
{ |
{ |
coff_symbol_type * csym; |
coff_symbol_type * csym; |
|
|
csym = coff_symbol_from (abfd, symbol); |
csym = coff_symbol_from (symbol); |
if (csym == NULL) |
if (csym == NULL) |
{ |
{ |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
Line 2405 bfd_coff_set_symbol_class (bfd * |
|
Line 2524 bfd_coff_set_symbol_class (bfd * |
|
if (native == NULL) |
if (native == NULL) |
return FALSE; |
return FALSE; |
|
|
|
native->is_sym = TRUE; |
native->u.syment.n_type = T_NULL; |
native->u.syment.n_type = T_NULL; |
native->u.syment.n_sclass = symbol_class; |
native->u.syment.n_sclass = symbol_class; |
|
|
Line 2440 bfd_coff_set_symbol_class (bfd * |
|
Line 2560 bfd_coff_set_symbol_class (bfd * |
|
return TRUE; |
return TRUE; |
} |
} |
|
|
struct coff_comdat_info * |
|
bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec) |
|
{ |
|
if (bfd_get_flavour (abfd) == bfd_target_coff_flavour |
|
&& coff_section_data (abfd, sec) != NULL) |
|
return coff_section_data (abfd, sec)->comdat; |
|
else |
|
return NULL; |
|
} |
|
|
|
bfd_boolean |
bfd_boolean |
_bfd_coff_section_already_linked (bfd *abfd, |
_bfd_coff_section_already_linked (bfd *abfd, |
asection *sec, |
asection *sec, |
Line 2516 _bfd_coff_section_already_linked (bfd *a |
|
Line 2626 _bfd_coff_section_already_linked (bfd *a |
|
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); |
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); |
return FALSE; |
return FALSE; |
} |
} |
|
|
|
/* Initialize COOKIE for input bfd ABFD. */ |
|
|
|
static bfd_boolean |
|
init_reloc_cookie (struct coff_reloc_cookie *cookie, |
|
struct bfd_link_info *info ATTRIBUTE_UNUSED, |
|
bfd *abfd) |
|
{ |
|
/* Sometimes the symbol table does not yet have been loaded here. */ |
|
bfd_coff_slurp_symbol_table (abfd); |
|
|
|
cookie->abfd = abfd; |
|
cookie->sym_hashes = obj_coff_sym_hashes (abfd); |
|
|
|
cookie->symbols = obj_symbols (abfd); |
|
|
|
return TRUE; |
|
} |
|
|
|
/* Free the memory allocated by init_reloc_cookie, if appropriate. */ |
|
|
|
static void |
|
fini_reloc_cookie (struct coff_reloc_cookie *cookie ATTRIBUTE_UNUSED, |
|
bfd *abfd ATTRIBUTE_UNUSED) |
|
{ |
|
/* Nothing to do. */ |
|
} |
|
|
|
/* Initialize the relocation information in COOKIE for input section SEC |
|
of input bfd ABFD. */ |
|
|
|
static bfd_boolean |
|
init_reloc_cookie_rels (struct coff_reloc_cookie *cookie, |
|
struct bfd_link_info *info ATTRIBUTE_UNUSED, |
|
bfd *abfd, |
|
asection *sec) |
|
{ |
|
if (sec->reloc_count == 0) |
|
{ |
|
cookie->rels = NULL; |
|
cookie->relend = NULL; |
|
cookie->rel = NULL; |
|
return TRUE; |
|
} |
|
|
|
cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, FALSE, NULL, 0, NULL); |
|
|
|
if (cookie->rels == NULL) |
|
return FALSE; |
|
|
|
cookie->rel = cookie->rels; |
|
cookie->relend = (cookie->rels + sec->reloc_count); |
|
return TRUE; |
|
} |
|
|
|
/* Free the memory allocated by init_reloc_cookie_rels, |
|
if appropriate. */ |
|
|
|
static void |
|
fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie, |
|
asection *sec) |
|
{ |
|
if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels) |
|
free (cookie->rels); |
|
} |
|
|
|
/* Initialize the whole of COOKIE for input section SEC. */ |
|
|
|
static bfd_boolean |
|
init_reloc_cookie_for_section (struct coff_reloc_cookie *cookie, |
|
struct bfd_link_info *info, |
|
asection *sec) |
|
{ |
|
if (!init_reloc_cookie (cookie, info, sec->owner)) |
|
return FALSE; |
|
|
|
if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec)) |
|
{ |
|
fini_reloc_cookie (cookie, sec->owner); |
|
return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
/* Free the memory allocated by init_reloc_cookie_for_section, |
|
if appropriate. */ |
|
|
|
static void |
|
fini_reloc_cookie_for_section (struct coff_reloc_cookie *cookie, |
|
asection *sec) |
|
{ |
|
fini_reloc_cookie_rels (cookie, sec); |
|
fini_reloc_cookie (cookie, sec->owner); |
|
} |
|
|
|
static asection * |
|
_bfd_coff_gc_mark_hook (asection *sec, |
|
struct bfd_link_info *info ATTRIBUTE_UNUSED, |
|
struct internal_reloc *rel ATTRIBUTE_UNUSED, |
|
struct coff_link_hash_entry *h, |
|
struct internal_syment *sym) |
|
{ |
|
if (h != NULL) |
|
{ |
|
switch (h->root.type) |
|
{ |
|
case bfd_link_hash_defined: |
|
case bfd_link_hash_defweak: |
|
return h->root.u.def.section; |
|
|
|
case bfd_link_hash_common: |
|
return h->root.u.c.p->section; |
|
|
|
case bfd_link_hash_undefined: |
|
case bfd_link_hash_undefweak: |
|
default: |
|
break; |
|
} |
|
return NULL; |
|
} |
|
|
|
return coff_section_from_bfd_index (sec->owner, sym->n_scnum); |
|
} |
|
|
|
/* COOKIE->rel describes a relocation against section SEC, which is |
|
a section we've decided to keep. Return the section that contains |
|
the relocation symbol, or NULL if no section contains it. */ |
|
|
|
static asection * |
|
_bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec, |
|
coff_gc_mark_hook_fn gc_mark_hook, |
|
struct coff_reloc_cookie *cookie) |
|
{ |
|
struct coff_link_hash_entry *h; |
|
|
|
h = cookie->sym_hashes[cookie->rel->r_symndx]; |
|
if (h != NULL) |
|
{ |
|
while (h->root.type == bfd_link_hash_indirect |
|
|| h->root.type == bfd_link_hash_warning) |
|
h = (struct coff_link_hash_entry *) h->root.u.i.link; |
|
|
|
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); |
|
} |
|
|
|
return (*gc_mark_hook) (sec, info, cookie->rel, NULL, |
|
&(cookie->symbols |
|
+ obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment); |
|
} |
|
|
|
static bfd_boolean _bfd_coff_gc_mark |
|
(struct bfd_link_info *, asection *, coff_gc_mark_hook_fn); |
|
|
|
/* COOKIE->rel describes a relocation against section SEC, which is |
|
a section we've decided to keep. Mark the section that contains |
|
the relocation symbol. */ |
|
|
|
static bfd_boolean |
|
_bfd_coff_gc_mark_reloc (struct bfd_link_info *info, |
|
asection *sec, |
|
coff_gc_mark_hook_fn gc_mark_hook, |
|
struct coff_reloc_cookie *cookie) |
|
{ |
|
asection *rsec; |
|
|
|
rsec = _bfd_coff_gc_mark_rsec (info, sec, gc_mark_hook, cookie); |
|
if (rsec && !rsec->gc_mark) |
|
{ |
|
if (bfd_get_flavour (rsec->owner) != bfd_target_coff_flavour) |
|
rsec->gc_mark = 1; |
|
else if (!_bfd_coff_gc_mark (info, rsec, gc_mark_hook)) |
|
return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
/* The mark phase of garbage collection. For a given section, mark |
|
it and any sections in this section's group, and all the sections |
|
which define symbols to which it refers. */ |
|
|
|
static bfd_boolean |
|
_bfd_coff_gc_mark (struct bfd_link_info *info, |
|
asection *sec, |
|
coff_gc_mark_hook_fn gc_mark_hook) |
|
{ |
|
bfd_boolean ret = TRUE; |
|
|
|
sec->gc_mark = 1; |
|
|
|
/* Look through the section relocs. */ |
|
if ((sec->flags & SEC_RELOC) != 0 |
|
&& sec->reloc_count > 0) |
|
{ |
|
struct coff_reloc_cookie cookie; |
|
|
|
if (!init_reloc_cookie_for_section (&cookie, info, sec)) |
|
ret = FALSE; |
|
else |
|
{ |
|
for (; cookie.rel < cookie.relend; cookie.rel++) |
|
{ |
|
if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie)) |
|
{ |
|
ret = FALSE; |
|
break; |
|
} |
|
} |
|
fini_reloc_cookie_for_section (&cookie, sec); |
|
} |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
static bfd_boolean |
|
_bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info, |
|
coff_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) |
|
{ |
|
bfd *ibfd; |
|
|
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) |
|
{ |
|
asection *isec; |
|
bfd_boolean some_kept; |
|
|
|
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) |
|
continue; |
|
|
|
/* Ensure all linker created sections are kept, and see whether |
|
any other section is already marked. */ |
|
some_kept = FALSE; |
|
for (isec = ibfd->sections; isec != NULL; isec = isec->next) |
|
{ |
|
if ((isec->flags & SEC_LINKER_CREATED) != 0) |
|
isec->gc_mark = 1; |
|
else if (isec->gc_mark) |
|
some_kept = TRUE; |
|
} |
|
|
|
/* If no section in this file will be kept, then we can |
|
toss out debug sections. */ |
|
if (!some_kept) |
|
continue; |
|
|
|
/* Keep debug and special sections like .comment when they are |
|
not part of a group, or when we have single-member groups. */ |
|
for (isec = ibfd->sections; isec != NULL; isec = isec->next) |
|
if ((isec->flags & SEC_DEBUGGING) != 0 |
|
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) |
|
isec->gc_mark = 1; |
|
} |
|
return TRUE; |
|
} |
|
|
|
/* Sweep symbols in swept sections. Called via coff_link_hash_traverse. */ |
|
|
|
static bfd_boolean |
|
coff_gc_sweep_symbol (struct coff_link_hash_entry *h, |
|
void *data ATTRIBUTE_UNUSED) |
|
{ |
|
if (h->root.type == bfd_link_hash_warning) |
|
h = (struct coff_link_hash_entry *) h->root.u.i.link; |
|
|
|
if ((h->root.type == bfd_link_hash_defined |
|
|| h->root.type == bfd_link_hash_defweak) |
|
&& !h->root.u.def.section->gc_mark |
|
&& !(h->root.u.def.section->owner->flags & DYNAMIC)) |
|
{ |
|
/* Do our best to hide the symbol. */ |
|
h->root.u.def.section = bfd_und_section_ptr; |
|
h->symbol_class = C_HIDDEN; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
/* The sweep phase of garbage collection. Remove all garbage sections. */ |
|
|
|
typedef bfd_boolean (*gc_sweep_hook_fn) |
|
(bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *); |
|
|
|
static bfd_boolean |
|
coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) |
|
{ |
|
bfd *sub; |
|
|
|
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
|
{ |
|
asection *o; |
|
|
|
if (bfd_get_flavour (sub) != bfd_target_coff_flavour) |
|
continue; |
|
|
|
for (o = sub->sections; o != NULL; o = o->next) |
|
{ |
|
/* Keep debug and special sections. */ |
|
if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 |
|
|| (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) |
|
o->gc_mark = 1; |
|
else if (CONST_STRNEQ (o->name, ".idata") |
|
|| CONST_STRNEQ (o->name, ".pdata") |
|
|| CONST_STRNEQ (o->name, ".xdata") |
|
|| CONST_STRNEQ (o->name, ".rsrc")) |
|
o->gc_mark = 1; |
|
|
|
if (o->gc_mark) |
|
continue; |
|
|
|
/* Skip sweeping sections already excluded. */ |
|
if (o->flags & SEC_EXCLUDE) |
|
continue; |
|
|
|
/* Since this is early in the link process, it is simple |
|
to remove a section from the output. */ |
|
o->flags |= SEC_EXCLUDE; |
|
|
|
if (info->print_gc_sections && o->size != 0) |
|
_bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name); |
|
|
|
#if 0 |
|
/* But we also have to update some of the relocation |
|
info we collected before. */ |
|
if (gc_sweep_hook |
|
&& (o->flags & SEC_RELOC) != 0 |
|
&& o->reloc_count > 0 |
|
&& !bfd_is_abs_section (o->output_section)) |
|
{ |
|
struct internal_reloc *internal_relocs; |
|
bfd_boolean r; |
|
|
|
internal_relocs |
|
= _bfd_coff_link_read_relocs (o->owner, o, NULL, NULL, |
|
info->keep_memory); |
|
if (internal_relocs == NULL) |
|
return FALSE; |
|
|
|
r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs); |
|
|
|
if (coff_section_data (o)->relocs != internal_relocs) |
|
free (internal_relocs); |
|
|
|
if (!r) |
|
return FALSE; |
|
} |
|
#endif |
|
} |
|
} |
|
|
|
/* Remove the symbols that were in the swept sections from the dynamic |
|
symbol table. */ |
|
coff_link_hash_traverse (coff_hash_table (info), coff_gc_sweep_symbol, |
|
NULL); |
|
|
|
return TRUE; |
|
} |
|
|
|
/* Keep all sections containing symbols undefined on the command-line, |
|
and the section containing the entry symbol. */ |
|
|
|
static void |
|
_bfd_coff_gc_keep (struct bfd_link_info *info) |
|
{ |
|
struct bfd_sym_chain *sym; |
|
|
|
for (sym = info->gc_sym_list; sym != NULL; sym = sym->next) |
|
{ |
|
struct coff_link_hash_entry *h; |
|
|
|
h = coff_link_hash_lookup (coff_hash_table (info), sym->name, |
|
FALSE, FALSE, FALSE); |
|
|
|
if (h != NULL |
|
&& (h->root.type == bfd_link_hash_defined |
|
|| h->root.type == bfd_link_hash_defweak) |
|
&& !bfd_is_abs_section (h->root.u.def.section)) |
|
h->root.u.def.section->flags |= SEC_KEEP; |
|
} |
|
} |
|
|
|
/* Do mark and sweep of unused sections. */ |
|
|
|
bfd_boolean |
|
bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) |
|
{ |
|
bfd *sub; |
|
|
|
/* FIXME: Should we implement this? */ |
|
#if 0 |
|
const bfd_coff_backend_data *bed = coff_backend_info (abfd); |
|
|
|
if (!bed->can_gc_sections |
|
|| !is_coff_hash_table (info->hash)) |
|
{ |
|
(*_bfd_error_handler)(_("Warning: gc-sections option ignored")); |
|
return TRUE; |
|
} |
|
#endif |
|
|
|
_bfd_coff_gc_keep (info); |
|
|
|
/* Grovel through relocs to find out who stays ... */ |
|
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) |
|
{ |
|
asection *o; |
|
|
|
if (bfd_get_flavour (sub) != bfd_target_coff_flavour) |
|
continue; |
|
|
|
for (o = sub->sections; o != NULL; o = o->next) |
|
{ |
|
if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP |
|
|| CONST_STRNEQ (o->name, ".vectors") |
|
|| CONST_STRNEQ (o->name, ".ctors") |
|
|| CONST_STRNEQ (o->name, ".dtors")) |
|
&& !o->gc_mark) |
|
{ |
|
if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook)) |
|
return FALSE; |
|
} |
|
} |
|
} |
|
|
|
/* Allow the backend to mark additional target specific sections. */ |
|
_bfd_coff_gc_mark_extra_sections (info, _bfd_coff_gc_mark_hook); |
|
|
|
/* ... and mark SEC_EXCLUDE for those that go. */ |
|
return coff_gc_sweep (abfd, info); |
|
} |