X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fcoffgen.c;h=0faaede68fd7a27c10433c04046f44bcc9a04f6d;hb=c7c7219d3a06a714e04e73ebd029811e6bd5bd37;hp=c541e6a590eb2d9abb7e367edd568192ff95c9d5;hpb=4ab527b0538fcb65673a93dc775c39a2e7ccb6d7;p=binutils-gdb.git diff --git a/bfd/coffgen.c b/bfd/coffgen.c index c541e6a590e..0faaede68fd 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1,6 +1,6 @@ /* Support for the generic parts of COFF, for BFD. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005 + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Cygnus Support. @@ -8,7 +8,7 @@ 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, @@ -18,7 +18,8 @@ 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. */ /* Most of this hacked by Steve Chamberlain, sac@cygnus.com. Split out of coffcode.h by Ian Taylor, ian@cygnus.com. */ @@ -37,8 +38,8 @@ Those functions may not use any COFF specific information, such as coff_data (abfd). */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "coff/internal.h" #include "libcoff.h" @@ -58,8 +59,13 @@ make_a_section_from_file (bfd *abfd, name = NULL; - /* Handle long section names as in PE. */ - if (bfd_coff_long_section_names (abfd) + /* Handle long section names as in PE. On reading, we want to + accept long names if the format permits them at all, regardless + of the current state of the flag that dictates if we would generate + them in outputs; this construct checks if that is the case by + attempting to set the flag, without changing its state; the call + will fail for formats that do not support long names at all. */ + if (bfd_coff_set_long_section_names (abfd, bfd_coff_long_section_names (abfd)) && hdr->s_name[0] == '/') { char buf[SCNNMLEN]; @@ -408,6 +414,9 @@ _bfd_coff_read_internal_relocs (bfd *abfd, struct internal_reloc *irel; bfd_size_type amt; + if (sec->reloc_count == 0) + return internal_relocs; /* Nothing to do. */ + if (coff_section_data (abfd, sec) != NULL && coff_section_data (abfd, sec)->relocs != NULL) { @@ -424,7 +433,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd, if (external_relocs == NULL) { free_external = bfd_malloc (amt); - if (free_external == NULL && sec->reloc_count > 0) + if (free_external == NULL) goto error_return; external_relocs = free_external; } @@ -438,7 +447,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd, amt = sec->reloc_count; amt *= sizeof (struct internal_reloc); free_internal = bfd_malloc (amt); - if (free_internal == NULL && sec->reloc_count > 0) + if (free_internal == NULL) goto error_return; internal_relocs = free_internal; } @@ -561,7 +570,8 @@ fixup_symbol_value (bfd *abfd, struct internal_syment *syment) { /* Normalize the symbol flags. */ - if (bfd_is_com_section (coff_symbol_ptr->symbol.section)) + if (coff_symbol_ptr->symbol.section + && bfd_is_com_section (coff_symbol_ptr->symbol.section)) { /* A common symbol is undefined with a value. */ syment->n_scnum = N_UNDEF; @@ -725,8 +735,8 @@ coff_mangle_symbols (bfd *bfd_ptr) { /* FIXME: We should use a union here. */ s->u.syment.n_value = - (bfd_vma)((combined_entry_type *) - ((unsigned long) s->u.syment.n_value))->offset; + (bfd_hostptr_t) ((combined_entry_type *) + ((bfd_hostptr_t) s->u.syment.n_value))->offset; s->fix_value = 0; } if (s->fix_line) @@ -1077,6 +1087,11 @@ coff_write_native_symbol (bfd *abfd, debug_string_size_p); } +static void +null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...) +{ +} + /* Write out the COFF symbols. */ bfd_boolean @@ -1133,6 +1148,42 @@ coff_write_symbols (bfd *abfd) } else { + if (coff_backend_info (abfd)->_bfd_coff_classify_symbol != NULL) + { + bfd_error_handler_type current_error_handler; + enum coff_symbol_classification class; + unsigned char *n_sclass; + + /* Suppress error reporting by bfd_coff_classify_symbol. + Error messages can be generated when we are processing a local + 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. */ + current_error_handler = bfd_set_error_handler (null_error_handler); + class = bfd_coff_classify_symbol (abfd, &c_symbol->native->u.syment); + (void) bfd_set_error_handler (current_error_handler); + + n_sclass = &c_symbol->native->u.syment.n_sclass; + + /* If the symbol class has been changed (eg objcopy/ld script/etc) + we cannot retain the existing sclass from the original symbol. + Weak symbols only have one valid sclass, so just set it always. + If it is not local class and should be, set it C_STAT. + If it is global and not classified as global, or if it is + weak (which is also classified as global), set it C_EXT. */ + + if (symbol->flags & BSF_WEAK) + *n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT; + else if (symbol->flags & BSF_LOCAL && class != COFF_SYMBOL_LOCAL) + *n_sclass = C_STAT; + else if (symbol->flags & BSF_GLOBAL + && (class != COFF_SYMBOL_GLOBAL +#ifdef COFF_WITH_PE + || *n_sclass == C_NT_WEAK +#endif + || *n_sclass == C_WEAKEXT)) + c_symbol->native->u.syment.n_sclass = C_EXT; + } + if (!coff_write_native_symbol (abfd, c_symbol, &written, &string_size, &debug_string_section, &debug_string_size)) @@ -1443,9 +1494,11 @@ _bfd_coff_get_external_symbols (bfd *abfd) symesz = bfd_coff_symesz (abfd); size = obj_raw_syment_count (abfd) * symesz; + if (size == 0) + return TRUE; syms = bfd_malloc (size); - if (syms == NULL && size != 0) + if (syms == NULL) return FALSE; if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 @@ -1640,7 +1693,7 @@ coff_get_normalized_symtab (bfd *abfd) } internal_ptr->u.syment._n._n_n._n_offset = - ((long) + ((bfd_hostptr_t) (string_table + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset)); } @@ -1652,13 +1705,13 @@ coff_get_normalized_symtab (bfd *abfd) if (internal_ptr->u.syment.n_numaux > 1 && coff_data (abfd)->pe) internal_ptr->u.syment._n._n_n._n_offset = - ((long) + ((bfd_hostptr_t) copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, internal_ptr->u.syment.n_numaux * symesz)); else internal_ptr->u.syment._n._n_n._n_offset = - ((long) + ((bfd_hostptr_t) copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, (size_t) bfd_coff_filnmlen (abfd))); @@ -1682,11 +1735,11 @@ coff_get_normalized_symtab (bfd *abfd) if (newstring == NULL) return NULL; strncpy (newstring, internal_ptr->u.syment._n._n_name, i); - internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring; + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) newstring; internal_ptr->u.syment._n._n_n._n_zeroes = 0; } else if (internal_ptr->u.syment._n._n_n._n_offset == 0) - internal_ptr->u.syment._n._n_n._n_offset = (long int) ""; + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) ""; else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment)) { /* Long name already. Point symbol at the string in the @@ -1698,7 +1751,7 @@ coff_get_normalized_symtab (bfd *abfd) return NULL; } internal_ptr->u.syment._n._n_n._n_offset = - ((long int) + ((bfd_hostptr_t) (string_table + internal_ptr->u.syment._n._n_n._n_offset)); } @@ -1707,7 +1760,7 @@ coff_get_normalized_symtab (bfd *abfd) /* Long name in debug section. Very similar. */ if (debug_section == NULL) debug_section = build_debug_section (abfd); - internal_ptr->u.syment._n._n_n._n_offset = (long int) + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) (debug_section + internal_ptr->u.syment._n._n_n._n_offset); } } @@ -1784,7 +1837,7 @@ coff_get_symbol_info (bfd *abfd, asymbol *symbol, symbol_info *ret) if (coffsymbol (symbol)->native != NULL && coffsymbol (symbol)->native->fix_value) ret->value = coffsymbol (symbol)->native->u.syment.n_value - - (unsigned long) obj_raw_syments (abfd); + (bfd_hostptr_t) obj_raw_syments (abfd); } /* Return the COFF syment for a symbol. */ @@ -1807,7 +1860,7 @@ bfd_coff_get_syment (bfd *abfd, if (csym->native->fix_value) psyment->n_value = psyment->n_value - - (unsigned long) obj_raw_syments (abfd); + (bfd_hostptr_t) obj_raw_syments (abfd); /* FIXME: We should handle fix_line here. */ @@ -1893,7 +1946,7 @@ coff_print_symbol (bfd *abfd, if (! combined->fix_value) val = (bfd_vma) combined->u.syment.n_value; else - val = combined->u.syment.n_value - (unsigned long) root; + val = combined->u.syment.n_value - (bfd_hostptr_t) root; fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x", combined->u.syment.n_scnum, @@ -1901,7 +1954,16 @@ coff_print_symbol (bfd *abfd, combined->u.syment.n_type, combined->u.syment.n_sclass, combined->u.syment.n_numaux); - fprintf_vma (file, val); +#ifdef BFD64 + /* fprintf_vma() on a 64-bit enabled host will always print a 64-bit + value, but really we want to display the address in the target's + address size. Since we do not have a field in the bfd structure + to tell us this, we take a guess, based on the target's name. */ + if (strstr (bfd_get_target (abfd), "64") == NULL) + fprintf (file, "%08lx", (unsigned long) (val & 0xffffffff)); + else +#endif + fprintf_vma (file, val); fprintf (file, " %s", symbol->name); for (aux = 0; aux < combined->u.syment.n_numaux; aux++) @@ -1930,7 +1992,7 @@ coff_print_symbol (bfd *abfd, /* Probably a section symbol ? */ { fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d", - (long) auxp->u.auxent.x_scn.x_scnlen, + (unsigned long) auxp->u.auxent.x_scn.x_scnlen, auxp->u.auxent.x_scn.x_nreloc, auxp->u.auxent.x_scn.x_nlinno); if (auxp->u.auxent.x_scn.x_checksum != 0 @@ -1944,6 +2006,7 @@ coff_print_symbol (bfd *abfd, } /* Otherwise fall through. */ case C_EXT: + case C_AIX_WEAKEXT: if (ISFCN (combined->u.syment.n_type)) { long next, llnos; @@ -1956,7 +2019,8 @@ coff_print_symbol (bfd *abfd, llnos = auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_lnnoptr; fprintf (file, "AUX tagndx %ld ttlsiz 0x%lx lnnos %ld next %ld", - tagndx, auxp->u.auxent.x_sym.x_misc.x_fsize, + tagndx, + (unsigned long) auxp->u.auxent.x_sym.x_misc.x_fsize, llnos, next); break; } @@ -2128,7 +2192,7 @@ coff_find_nearest_line (bfd *abfd, } /* Now wander though the raw linenumbers of the section. */ - /* If we have been called on this section before, and th. e offset we + /* If we have been called on this section before, and the offset we want is further down then we can prime the lookup loop. */ sec_data = coff_section_data (abfd, section); if (sec_data != NULL @@ -2215,7 +2279,7 @@ coff_find_nearest_line (bfd *abfd, if (sec_data != NULL) { sec_data->offset = offset; - sec_data->i = i; + sec_data->i = i - 1; sec_data->function = *functionname_ptr; sec_data->line_base = line_base; } @@ -2238,11 +2302,11 @@ coff_find_inliner_info (bfd *abfd, } int -coff_sizeof_headers (bfd *abfd, bfd_boolean reloc) +coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info) { size_t size; - if (! reloc) + if (!info->relocatable) size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); else size = bfd_coff_filhsz (abfd);