X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoffgen.c;h=a06ed663b3d264f3cfa359e100d97439749bac09;hb=661016bb24e303838a4d3821c2c85e042da085fa;hp=bb9882b7e60f8d8f113b022980e8c7aa04896828;hpb=1d8eda7ab48030197747490cb54b8123cc4cbddd;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coffgen.c b/bfd/coffgen.c index bb9882b7e6..a06ed663b3 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1,5 +1,6 @@ /* Support for the generic parts of COFF, for BFD. - Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998 + Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -56,6 +57,17 @@ static boolean coff_write_native_symbol static void coff_pointerize_aux PARAMS ((bfd *, combined_entry_type *, combined_entry_type *, unsigned int, combined_entry_type *)); +static boolean make_a_section_from_file + PARAMS ((bfd *, struct internal_scnhdr *, unsigned int)); +static const bfd_target *coff_real_object_p + PARAMS ((bfd *, unsigned, struct internal_filehdr *, + struct internal_aouthdr *)); +static void fixup_symbol_value + PARAMS ((bfd *, coff_symbol_type *, struct internal_syment *)); +static char *build_debug_section + PARAMS ((bfd *)); +static char *copy_name + PARAMS ((bfd *, char *, int)); #define STRING_SIZE_SIZE (4) @@ -70,12 +82,45 @@ make_a_section_from_file (abfd, hdr, target_index) asection *return_section; char *name; - /* Assorted wastage to null-terminate the name, thanks AT&T! */ - name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1); + name = NULL; + + /* Handle long section names as in PE. */ + if (bfd_coff_long_section_names (abfd) + && hdr->s_name[0] == '/') + { + char buf[SCNNMLEN]; + long strindex; + char *p; + const char *strings; + + memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1); + buf[SCNNMLEN - 1] = '\0'; + strindex = strtol (buf, &p, 10); + if (*p == '\0' && strindex >= 0) + { + strings = _bfd_coff_read_string_table (abfd); + if (strings == NULL) + return false; + /* FIXME: For extra safety, we should make sure that + strindex does not run us past the end, but right now we + don't know the length of the string table. */ + strings += strindex; + name = bfd_alloc (abfd, strlen (strings) + 1); + if (name == NULL) + return false; + strcpy (name, strings); + } + } + if (name == NULL) - return false; - strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); - name[sizeof (hdr->s_name)] = 0; + { + /* Assorted wastage to null-terminate the name, thanks AT&T! */ + name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1); + if (name == NULL) + return false; + strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); + name[sizeof (hdr->s_name)] = 0; + } return_section = bfd_make_section_anyway (abfd, name); if (return_section == NULL) @@ -176,7 +221,8 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a) bfd_coff_swap_scnhdr_in (abfd, (PTR) (external_sections + i * scnhsz), (PTR) & tmp); - make_a_section_from_file (abfd, &tmp, i + 1); + if (! make_a_section_from_file (abfd, &tmp, i + 1)) + goto fail; } } @@ -238,18 +284,14 @@ coff_object_p (abfd) opthdr = bfd_alloc (abfd, aoutsz); if (opthdr == NULL) return 0;; - if (bfd_read (opthdr, 1, aoutsz, abfd) != aoutsz) + if (bfd_read (opthdr, 1, internal_f.f_opthdr, abfd) + != internal_f.f_opthdr) { return 0; } - bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a); + bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) &internal_a); } - /* Seek past the opt hdr stuff */ - if (bfd_seek (abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET) - != 0) - return NULL; - return coff_real_object_p (abfd, nscns, &internal_f, (internal_f.f_opthdr != 0 ? &internal_a @@ -530,7 +572,8 @@ coff_symbol_from (ignore_abfd, symbol) } static void -fixup_symbol_value (coff_symbol_ptr, syment) +fixup_symbol_value (abfd, coff_symbol_ptr, syment) + bfd *abfd; coff_symbol_type *coff_symbol_ptr; struct internal_syment *syment; { @@ -558,10 +601,11 @@ fixup_symbol_value (coff_symbol_ptr, syment) syment->n_scnum = coff_symbol_ptr->symbol.section->output_section->target_index; - syment->n_value = - coff_symbol_ptr->symbol.value + - coff_symbol_ptr->symbol.section->output_offset + - coff_symbol_ptr->symbol.section->output_section->vma; + syment->n_value = (coff_symbol_ptr->symbol.value + + coff_symbol_ptr->symbol.section->output_offset); + if (! obj_pe (abfd)) + syment->n_value += + coff_symbol_ptr->symbol.section->output_section->vma; } else { @@ -605,9 +649,8 @@ coff_renumber_symbols (bfd_ptr, first_undef) asymbol **newsyms; unsigned int i; - newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr, - sizeof (asymbol *) - * (symbol_count + 1)); + newsyms = (asymbol **) bfd_alloc (bfd_ptr, + sizeof (asymbol *) * (symbol_count + 1)); if (!newsyms) return false; bfd_ptr->outsymbols = newsyms; @@ -615,17 +658,18 @@ coff_renumber_symbols (bfd_ptr, first_undef) if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0 || (!bfd_is_und_section (symbol_ptr_ptr[i]->section) && !bfd_is_com_section (symbol_ptr_ptr[i]->section) - && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_FUNCTION)) - != BSF_GLOBAL))) + && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0 + || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK)) + == 0)))) *newsyms++ = symbol_ptr_ptr[i]; for (i = 0; i < symbol_count; i++) - if (!bfd_is_und_section (symbol_ptr_ptr[i]->section) + if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0 + && !bfd_is_und_section (symbol_ptr_ptr[i]->section) && (bfd_is_com_section (symbol_ptr_ptr[i]->section) - || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL - | BSF_NOT_AT_END - | BSF_FUNCTION)) - == BSF_GLOBAL))) + || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0 + && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK)) + != 0)))) *newsyms++ = symbol_ptr_ptr[i]; *first_undef = newsyms - bfd_ptr->outsymbols; @@ -659,7 +703,7 @@ coff_renumber_symbols (bfd_ptr, first_undef) /* Modify the symbol values according to their section and type */ - fixup_symbol_value (coff_symbol_ptr, &(s->u.syment)); + fixup_symbol_value (bfd_ptr, coff_symbol_ptr, &(s->u.syment)); } for (i = 0; i < s->u.syment.n_numaux + 1; i++) s[i].offset = native_index++; @@ -974,8 +1018,9 @@ coff_write_alien_symbol (abfd, symbol, written, string_size_p, native->u.syment.n_scnum = symbol->section->output_section->target_index; native->u.syment.n_value = (symbol->value - + symbol->section->output_section->vma + symbol->section->output_offset); + if (! obj_pe (abfd)) + native->u.syment.n_value += symbol->section->output_section->vma; /* Copy the any flags from the the file header into the symbol. FIXME: Why? */ @@ -989,6 +1034,8 @@ coff_write_alien_symbol (abfd, symbol, written, string_size_p, native->u.syment.n_type = 0; if (symbol->flags & BSF_LOCAL) native->u.syment.n_sclass = C_STAT; + else if (symbol->flags & BSF_WEAK) + native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT; else native->u.syment.n_sclass = C_EXT; native->u.syment.n_numaux = 0; @@ -1084,6 +1131,24 @@ coff_write_symbols (abfd) debug_string_section = NULL; debug_string_size = 0; + /* If this target supports long section names, they must be put into + the string table. This is supported by PE. This code must + handle section names just as they are handled in + coff_write_object_contents. */ + if (bfd_coff_long_section_names (abfd)) + { + asection *o; + + for (o = abfd->sections; o != NULL; o = o->next) + { + size_t len; + + len = strlen (o->name); + if (len > SCNNMLEN) + string_size += len + 1; + } + } + /* Seek to the right place */ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) return false; @@ -1129,6 +1194,26 @@ coff_write_symbols (abfd) #endif if (bfd_write ((PTR) buffer, 1, sizeof (buffer), abfd) != sizeof (buffer)) return false; + + /* Handle long section names. This code must handle section + names just as they are handled in coff_write_object_contents. */ + if (bfd_coff_long_section_names (abfd)) + { + asection *o; + + for (o = abfd->sections; o != NULL; o = o->next) + { + size_t len; + + len = strlen (o->name); + if (len > SCNNMLEN) + { + if (bfd_write (o->name, 1, len + 1, abfd) != len + 1) + return false; + } + } + } + for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) @@ -1298,7 +1383,7 @@ coff_section_symbol (abfd, name) combined_entry_type e[10]; }; struct foo *f; - f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f)); + f = (struct foo *) bfd_alloc (abfd, sizeof (*f)); if (!f) { bfd_set_error (bfd_error_no_error); @@ -1336,8 +1421,8 @@ coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent) unsigned int indaux; combined_entry_type *auxent; { - int type = symbol->u.syment.n_type; - int class = symbol->u.syment.n_sclass; + unsigned int type = symbol->u.syment.n_type; + unsigned int class = symbol->u.syment.n_sclass; if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) { @@ -1355,7 +1440,7 @@ coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent) /* Otherwise patch up */ #define N_TMASK coff_data (abfd)->local_n_tmask #define N_BTSHFT coff_data (abfd)->local_n_btshft - if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK) + if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK || class == 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.p = @@ -1487,6 +1572,12 @@ _bfd_coff_read_string_table (abfd) if (obj_coff_strings (abfd) != NULL) return obj_coff_strings (abfd); + if (obj_sym_filepos (abfd) == 0) + { + bfd_set_error (bfd_error_no_symbols); + return NULL; + } + if (bfd_seek (abfd, (obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd)), @@ -1513,7 +1604,7 @@ _bfd_coff_read_string_table (abfd) if (strsize < STRING_SIZE_SIZE) { (*_bfd_error_handler) - ("%s: bad string table size %lu", bfd_get_filename (abfd), + (_("%s: bad string table size %lu"), bfd_get_filename (abfd), (unsigned long) strsize); bfd_set_error (bfd_error_bad_value); return NULL; @@ -1656,9 +1747,19 @@ coff_get_normalized_symtab (abfd) else { /* ordinary short filename, put into memory anyway */ - internal_ptr->u.syment._n._n_n._n_offset = (long) - copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, - FILNMLEN); + if (internal_ptr->u.syment.n_numaux > 1 + && coff_data (abfd)->pe) + { + internal_ptr->u.syment._n._n_n._n_offset = (long) + 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) + copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, + FILNMLEN); + } } } else @@ -1794,6 +1895,78 @@ coff_get_symbol_info (abfd, symbol, ret) } } +/* Return the COFF syment for a symbol. */ + +boolean +bfd_coff_get_syment (abfd, symbol, psyment) + 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 = ((combined_entry_type *) psyment->n_value + - obj_raw_syments (abfd)); + + /* FIXME: We should handle fix_line here. */ + + return true; +} + +/* Return the COFF auxent for a symbol. */ + +boolean +bfd_coff_get_auxent (abfd, symbol, indx, pauxent) + 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. */ void @@ -1877,7 +2050,7 @@ coff_print_symbol (abfd, filep, symbol, how) if (auxp->u.auxent.x_scn.x_checksum != 0 || auxp->u.auxent.x_scn.x_associated != 0 || auxp->u.auxent.x_scn.x_comdat != 0) - fprintf (file, "checksum 0x%lx assoc %d comdat %d", + fprintf (file, " checksum 0x%lx assoc %d comdat %d", auxp->u.auxent.x_scn.x_checksum, auxp->u.auxent.x_scn.x_associated, auxp->u.auxent.x_scn.x_comdat); @@ -1925,6 +2098,19 @@ coff_print_symbol (abfd, filep, symbol, how) } } +/* Return whether a symbol name implies a local symbol. In COFF, + local symbols generally start with ``.L''. Most targets use this + function for the is_local_label_name entry point, but some may + override it. */ + +boolean +_bfd_coff_is_local_label_name (abfd, name) + bfd *abfd; + const char *name; +{ + return name[0] == '.' && name[1] == 'L'; +} + /* Provided a BFD, a section and an offset into the section, calculate and return the name of the source file and the line nearest to the wanted location. */ @@ -1974,6 +2160,9 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr, /* Find the first C_FILE symbol. */ p = cof->raw_syments; + if (!p) + return false; + pend = p + cof->raw_syment_count; while (p < pend) { @@ -1984,9 +2173,11 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr, if (p < pend) { + bfd_vma sec_vma; bfd_vma maxdiff; /* Look through the C_FILE symbols to find the best one. */ + sec_vma = bfd_get_section_vma (abfd, section); *filename_ptr = (char *) p->u.syment._n._n_n._n_offset; maxdiff = (bfd_vma) 0 - (bfd_vma) 1; while (1) @@ -2010,11 +2201,11 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr, } if (p2 < pend - && offset >= (bfd_vma) p2->u.syment.n_value - && offset - (bfd_vma) p2->u.syment.n_value < maxdiff) + && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value + && offset + sec_vma - (bfd_vma) p2->u.syment.n_value < maxdiff) { *filename_ptr = (char *) p->u.syment._n._n_n._n_offset; - maxdiff = offset - p2->u.syment.n_value; + maxdiff = offset + sec_vma - p2->u.syment.n_value; } /* Avoid endless loops on erroneous files by ensuring that @@ -2081,7 +2272,7 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr, } else { - if (l->u.offset + bfd_get_section_vma (abfd, section) > offset) + if (l->u.offset > offset) break; *line_ptr = l->line_number + line_base - 1; } @@ -2127,3 +2318,71 @@ coff_sizeof_headers (abfd, reloc) size += abfd->section_count * bfd_coff_scnhsz (abfd); return size; } + +/* Change the class of a coff symbol held by BFD. */ +boolean +bfd_coff_set_symbol_class (abfd, symbol, class) + bfd * abfd; + asymbol * symbol; + unsigned int class; +{ + coff_symbol_type * csym; + + csym = coff_symbol_from (abfd, symbol); + if (csym == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + else if (csym->native == NULL) + { + /* This is an alien symbol which no native coff backend data. + We cheat here by creating a fake native entry for it and + then filling in the class. This code is based on that in + coff_write_alien_symbol(). */ + + combined_entry_type * native; + + native = (combined_entry_type *) bfd_alloc (abfd, sizeof (* native)); + if (native == NULL) + return false; + + memset (native, 0, sizeof (* native)); + + native->u.syment.n_type = T_NULL; + native->u.syment.n_sclass = class; + + if (bfd_is_und_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; + } + else if (bfd_is_com_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; + } + else + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + native->u.syment.n_value = (symbol->value + + symbol->section->output_offset); + if (! obj_pe (abfd)) + native->u.syment.n_value += symbol->section->output_section->vma; + + /* Copy the any flags from the the file header into the symbol. + FIXME: Why? */ + native->u.syment.n_flags = bfd_asymbol_bfd (& csym->symbol)->flags; + } + + csym->native = native; + } + else + { + csym->native->u.syment.n_sclass = class; + } + + return true; +} +