From aca736871c2567ee38bd285afdff62d6339790e4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 5 Oct 1995 17:48:32 +0000 Subject: [PATCH] * libecoff.h (struct ecoff_backend_data): Add adjust_headers field. * ecoff.c (ecoff_sec_to_styp_flags): Check for various Alpha sections, and set styp correctly for them: .got, .hash, .dynamic, .liblist, .rel.dyn, .conflic, .dynstr, .dynsym, .comment. (_bfd_ecoff_styp_to_sec_flags): Check for various Alpha section types. (ecoff_sort_hdrs): New static function. (ecoff_compute_section_file_positions): Return boolean, not void. Sort the sections by VMA before looking through them. Put the first non SEC_ALLOC section on a new page. Put every SEC_ALLOC section on an appropriate boundary within the page. (ecoff_compute_reloc_file_positions): Check return value of ecoff_compute_section_file_positions. (_bfd_ecoff_set_section_contents): Likewise. (_bfd_ecoff_write_object_contents): Check for various Alpha section types when incrementing text_size and data_size. Call adjust_headers backend function if it exists. * coff-alpha.c (alpha_adjust_headers): New static function. (alpha_ecoff_backend_data): Initialize adjust_headers field. * coff-mips.c (mips_ecoff_backend_data): Likewise. PR 8141. --- bfd/ChangeLog | 22 +++++++ bfd/coff-alpha.c | 26 +++++++- bfd/coff-mips.c | 7 +- bfd/ecoff.c | 164 +++++++++++++++++++++++++++++++++++++++-------- bfd/libecoff.h | 4 +- 5 files changed, 188 insertions(+), 35 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ffede825476..d04ff1cc6d6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,27 @@ Thu Oct 5 11:45:02 1995 Ian Lance Taylor + * libecoff.h (struct ecoff_backend_data): Add adjust_headers + field. + * ecoff.c (ecoff_sec_to_styp_flags): Check for various Alpha + sections, and set styp correctly for them: .got, .hash, .dynamic, + .liblist, .rel.dyn, .conflic, .dynstr, .dynsym, .comment. + (_bfd_ecoff_styp_to_sec_flags): Check for various Alpha section + types. + (ecoff_sort_hdrs): New static function. + (ecoff_compute_section_file_positions): Return boolean, not void. + Sort the sections by VMA before looking through them. Put the + first non SEC_ALLOC section on a new page. Put every SEC_ALLOC + section on an appropriate boundary within the page. + (ecoff_compute_reloc_file_positions): Check return value of + ecoff_compute_section_file_positions. + (_bfd_ecoff_set_section_contents): Likewise. + (_bfd_ecoff_write_object_contents): Check for various Alpha + section types when incrementing text_size and data_size. Call + adjust_headers backend function if it exists. + * coff-alpha.c (alpha_adjust_headers): New static function. + (alpha_ecoff_backend_data): Initialize adjust_headers field. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + * hosts/i386bsd.h: Restore file incorrectly deleted on Sep 6. Wed Oct 4 18:15:02 1995 Jeff Law (law@hurl.cygnus.com) diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 8d0b3a50008..d914d4de589 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -55,6 +55,8 @@ static bfd_vma alpha_convert_external_reloc static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR)); +static boolean alpha_adjust_headers + PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *)); /* ECOFF has COFF sections, but the debugging information is stored in a completely different format. ECOFF targets use some of the @@ -1935,6 +1937,23 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, return true; } +/* Do final adjustments to the filehdr and the aouthdr. This routine + sets the dynamic bits in the file header. */ + +/*ARGSUSED*/ +static boolean +alpha_adjust_headers (abfd, fhdr, ahdr) + bfd *abfd; + struct internal_filehdr *fhdr; + struct internal_aouthdr *ahdr; +{ + if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P)) + fhdr->f_flags |= F_ALPHA_CALL_SHARED; + else if ((abfd->flags & DYNAMIC) != 0) + fhdr->f_flags |= F_ALPHA_SHARABLE; + return true; +} + /* This is the ECOFF backend structure. The backend field of the target vector points to this. */ @@ -1956,8 +1975,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = alpha_ecoff_swap_scnhdr_in, NULL, alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, - _bfd_ecoff_make_section_hook, _bfd_ecoff_set_alignment_hook, - _bfd_ecoff_slurp_symbol_table, + _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, /* Supported architecture. */ @@ -2023,7 +2041,9 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = alpha_adjust_reloc_in, alpha_adjust_reloc_out, /* Relocate section contents while linking. */ - alpha_relocate_section + alpha_relocate_section, + /* Do final adjustments to filehdr and aouthdr. */ + alpha_adjust_headers }; /* Looking up a reloc type is Alpha specific. */ diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c index c8cb7447e25..e1a269f91cb 100644 --- a/bfd/coff-mips.c +++ b/bfd/coff-mips.c @@ -2441,8 +2441,7 @@ static const struct ecoff_backend_data mips_ecoff_backend_data = mips_ecoff_swap_scnhdr_in, NULL, mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, - _bfd_ecoff_make_section_hook, _bfd_ecoff_set_alignment_hook, - _bfd_ecoff_slurp_symbol_table, + _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, /* Supported architecture. */ @@ -2508,7 +2507,9 @@ static const struct ecoff_backend_data mips_ecoff_backend_data = mips_adjust_reloc_in, mips_adjust_reloc_out, /* Relocate section contents while linking. */ - mips_relocate_section + mips_relocate_section, + /* Do final adjustments to filehdr and aouthdr. */ + NULL }; /* Looking up a reloc type is MIPS specific. */ diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 1fe4f750adf..8b40eb5c56b 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -59,7 +59,8 @@ static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr, unsigned int indx)); static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section, asymbol **symbols)); -static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd)); +static int ecoff_sort_hdrs PARAMS ((const PTR, const PTR)); +static boolean ecoff_compute_section_file_positions PARAMS ((bfd *abfd)); static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *abfd)); static boolean ecoff_get_extr PARAMS ((asymbol *, EXTR *)); static void ecoff_set_index PARAMS ((asymbol *, bfd_size_type)); @@ -135,17 +136,6 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) return (PTR) ecoff; } -/* This is a hook needed by SCO COFF, but we have nothing to do. */ - -/*ARGSUSED*/ -asection * -_bfd_ecoff_make_section_hook (abfd, name) - bfd *abfd; - char *name; -{ - return (asection *) NULL; -} - /* Initialize a new section. */ boolean @@ -324,6 +314,27 @@ ecoff_sec_to_styp_flags (name, flags) styp = STYP_XDATA; else if (strcmp (name, _LIB) == 0) styp = STYP_ECOFF_LIB; + else if (strcmp (name, _GOT) == 0) + styp = STYP_GOT; + else if (strcmp (name, _HASH) == 0) + styp = STYP_HASH; + else if (strcmp (name, _DYNAMIC) == 0) + styp = STYP_DYNAMIC; + else if (strcmp (name, _LIBLIST) == 0) + styp = STYP_LIBLIST; + else if (strcmp (name, _RELDYN) == 0) + styp = STYP_RELDYN; + else if (strcmp (name, _CONFLIC) == 0) + styp = STYP_CONFLIC; + else if (strcmp (name, _DYNSTR) == 0) + styp = STYP_DYNSTR; + else if (strcmp (name, _DYNSYM) == 0) + styp = STYP_DYNSYM; + else if (strcmp (name, _COMMENT) == 0) + { + styp = STYP_COMMENT; + flags &=~ SEC_NEVER_LOAD; + } else if (flags & SEC_CODE) styp = STYP_TEXT; else if (flags & SEC_DATA) @@ -361,7 +372,14 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name) actually a shared library section. */ if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_ECOFF_INIT) - || (styp_flags & STYP_ECOFF_FINI)) + || (styp_flags & STYP_ECOFF_FINI) + || (styp_flags & STYP_DYNAMIC) + || (styp_flags & STYP_LIBLIST) + || (styp_flags & STYP_RELDYN) + || styp_flags == STYP_CONFLIC + || (styp_flags & STYP_DYNSTR) + || (styp_flags & STYP_DYNSYM) + || (styp_flags & STYP_HASH)) { if (sec_flags & SEC_NEVER_LOAD) sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY; @@ -372,7 +390,8 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name) || (styp_flags & STYP_RDATA) || (styp_flags & STYP_SDATA) || styp_flags == STYP_PDATA - || styp_flags == STYP_XDATA) + || styp_flags == STYP_XDATA + || (styp_flags & STYP_GOT)) { if (sec_flags & SEC_NEVER_LOAD) sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY; @@ -2011,27 +2030,77 @@ _bfd_ecoff_get_section_contents (abfd, section, location, offset, count) offset, count); } +/* Sort sections by VMA, but put SEC_ALLOC sections first. This is + called via qsort. */ + +static int +ecoff_sort_hdrs (arg1, arg2) + const PTR arg1; + const PTR arg2; +{ + const asection *hdr1 = *(const asection **) arg1; + const asection *hdr2 = *(const asection **) arg2; + + if ((hdr1->flags & SEC_ALLOC) != 0) + { + if ((hdr2->flags & SEC_ALLOC) == 0) + return -1; + } + else + { + if ((hdr2->flags & SEC_ALLOC) != 0) + return 1; + } + if (hdr1->vma < hdr2->vma) + return -1; + else if (hdr1->vma > hdr2->vma) + return 1; + else + return 0; +} + /* Calculate the file position for each section, and set reloc_filepos. */ -static void +static boolean ecoff_compute_section_file_positions (abfd) bfd *abfd; { - asection *current; file_ptr sofar; + asection **sorted_hdrs; + asection *current; + unsigned int i; file_ptr old_sofar; - boolean first_data; + boolean first_data, first_nonalloc; + const bfd_vma round = ecoff_backend (abfd)->round; sofar = _bfd_ecoff_sizeof_headers (abfd, false); + /* Sort the sections by VMA. */ + sorted_hdrs = (asection **) malloc (abfd->section_count + * sizeof (asection *)); + if (sorted_hdrs == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + for (current = abfd->sections, i = 0; + current != NULL; + current = current->next, i++) + sorted_hdrs[i] = current; + BFD_ASSERT (i == abfd->section_count); + + qsort (sorted_hdrs, abfd->section_count, sizeof (asection *), + ecoff_sort_hdrs); + first_data = true; - for (current = abfd->sections; - current != (asection *) NULL; - current = current->next) + first_nonalloc = true; + for (i = 0; i < abfd->section_count; i++) { unsigned int alignment_power; + current = sorted_hdrs[i]; + /* Only deal with sections which have contents */ if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0) continue; @@ -2062,26 +2131,37 @@ ecoff_compute_section_file_positions (abfd) || strcmp (current->name, _RDATA) != 0) && strcmp (current->name, _PDATA) != 0) { - const bfd_vma round = ecoff_backend (abfd)->round; - sofar = (sofar + round - 1) &~ (round - 1); first_data = false; } else if (strcmp (current->name, _LIB) == 0) { - const bfd_vma round = ecoff_backend (abfd)->round; /* On Irix 4, the location of contents of the .lib section from a shared library section is also rounded up to a page boundary. */ sofar = (sofar + round - 1) &~ (round - 1); } + else if (first_nonalloc + && (current->flags & SEC_ALLOC) == 0 + && (abfd->flags & D_PAGED) != 0) + { + /* Skip up to the next page for an unallocated section, such + as the .comment section on the Alpha. This leaves room + for the .bss section. */ + first_nonalloc = false; + sofar = (sofar + round - 1) &~ (round - 1); + } /* Align the sections in the file to the same boundary on which they are aligned in virtual memory. */ old_sofar = sofar; sofar = BFD_ALIGN (sofar, 1 << alignment_power); + if ((abfd->flags & D_PAGED) != 0 + && (current->flags & SEC_ALLOC) != 0) + sofar += (current->vma - sofar) % round; + current->filepos = sofar; sofar += current->_raw_size; @@ -2092,7 +2172,12 @@ ecoff_compute_section_file_positions (abfd) current->_raw_size += sofar - old_sofar; } + free (sorted_hdrs); + sorted_hdrs = NULL; + ecoff_data (abfd)->reloc_filepos = sofar; + + return true; } /* Determine the location of the relocs for all the sections in the @@ -2112,7 +2197,8 @@ ecoff_compute_reloc_file_positions (abfd) if (! abfd->output_has_begun) { - ecoff_compute_section_file_positions (abfd); + if (! ecoff_compute_section_file_positions (abfd)) + abort (); abfd->output_has_begun = true; } @@ -2164,7 +2250,10 @@ _bfd_ecoff_set_section_contents (abfd, section, location, offset, count) /* This must be done first, because bfd_set_section_contents is going to set output_has_begun to true. */ if (abfd->output_has_begun == false) - ecoff_compute_section_file_positions (abfd); + { + if (! ecoff_compute_section_file_positions (abfd)) + return false; + } /* If this is a .lib section, bump the vma address so that it winds up being the number of .lib sections output. This is right for @@ -2472,7 +2561,16 @@ _bfd_ecoff_write_object_contents (abfd) if ((section.s_flags & STYP_TEXT) != 0 || ((section.s_flags & STYP_RDATA) != 0 && backend->rdata_in_text) - || strcmp (current->name, _PDATA) == 0) + || section.s_flags == STYP_PDATA + || (section.s_flags & STYP_DYNAMIC) != 0 + || (section.s_flags & STYP_LIBLIST) != 0 + || (section.s_flags & STYP_RELDYN) != 0 + || section.s_flags == STYP_CONFLIC + || (section.s_flags & STYP_DYNSTR) != 0 + || (section.s_flags & STYP_DYNSYM) != 0 + || (section.s_flags & STYP_HASH) != 0 + || (section.s_flags & STYP_ECOFF_INIT) != 0 + || (section.s_flags & STYP_ECOFF_FINI) != 0) { text_size += bfd_get_section_size_before_reloc (current); if (! set_text_start || text_start > vma) @@ -2487,7 +2585,8 @@ _bfd_ecoff_write_object_contents (abfd) || (section.s_flags & STYP_LIT8) != 0 || (section.s_flags & STYP_LIT4) != 0 || (section.s_flags & STYP_SDATA) != 0 - || strcmp (current->name, _XDATA) == 0) + || section.s_flags == STYP_XDATA + || (section.s_flags & STYP_GOT) != 0) { data_size += bfd_get_section_size_before_reloc (current); if (! set_data_start || data_start > vma) @@ -2499,7 +2598,9 @@ _bfd_ecoff_write_object_contents (abfd) else if ((section.s_flags & STYP_BSS) != 0 || (section.s_flags & STYP_SBSS) != 0) bss_size += bfd_get_section_size_before_reloc (current); - else if ((section.s_flags & STYP_ECOFF_LIB) != 0) + else if (section.s_flags == 0 + || (section.s_flags & STYP_ECOFF_LIB) != 0 + || section.s_flags == STYP_COMMENT) /* Do nothing */ ; else abort (); @@ -2591,6 +2692,13 @@ _bfd_ecoff_write_object_contents (abfd) for (i = 0; i < 4; i++) internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i]; + /* Let the backend adjust the headers if necessary. */ + if (backend->adjust_headers) + { + if (! (*backend->adjust_headers) (abfd, &internal_f, &internal_a)) + goto error_return; + } + /* Write out the file header and the optional header. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) diff --git a/bfd/libecoff.h b/bfd/libecoff.h index d16e3fa44bd..e8af957d03f 100644 --- a/bfd/libecoff.h +++ b/bfd/libecoff.h @@ -68,6 +68,9 @@ struct ecoff_backend_data bfd *input_bfd, asection *input_section, bfd_byte *contents, PTR external_relocs)); + /* Do final adjustments to filehdr and aouthdr. */ + boolean (*adjust_headers) PARAMS ((bfd *, struct internal_filehdr *, + struct internal_aouthdr *)); }; /* This is the target specific information kept for ECOFF files. */ @@ -312,7 +315,6 @@ extern boolean _bfd_ecoff_bfd_final_link /* Hook functions for the generic COFF section reading code. */ extern PTR _bfd_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); -extern asection *_bfd_ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); #define _bfd_ecoff_set_alignment_hook \ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void) extern boolean _bfd_ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr)); -- 2.30.2