From: Ian Lance Taylor Date: Tue, 9 Jan 1996 20:40:39 +0000 (+0000) Subject: Tue Jan 9 15:22:53 1996 David Mosberger-Tang X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=64d5f5d061563094cce2f2edbe6447f9ac6adddd;p=binutils-gdb.git Tue Jan 9 15:22:53 1996 David Mosberger-Tang * coff-alpha.c (alpha_relocate_section): During final link, allow output .lita section to be bigger than 64k by adjusting gp value on a per-input section basis. * libecoff.h (struct ecoff_tdata): Add issued_multiple_gp_warning field. (struct ecoff_section_tdata): Add gp field. Tue Jan 9 12:00:36 1996 Ian Lance Taylor Handle Alpha ECOFF changes in OSF/1 3.2. * libecoff.h (struct ecoff_backend_data): Add get_elt_at_filepos field. * coff-alpha.c: Include "aout/ar.h". (alpha_ecoff_get_relocated_section_contents): Don't require an ALPHA_R_IGNORE reloc after an ALPHA_R_GPDISP reloc, since OSF/1 3.2 doesn't generate one. (alpha_relocate_section): Likewise. (alpha_ecoff_slurp_armap): Define. (alpha_ecoff_slurp_extended_name_table): Define. (alpha_ecoff_construct_extended_name_table): Define. (alpha_ecoff_truncate_arname): Define. (alpha_ecoff_write_armap): Define. (alpha_ecoff_generic_stat_arch_elt): Define. (alpha_ecoff_update_armap_timestamp): Define. (ARFZMAG): Define. (alpha_ecoff_read_ar_hdr): New static function. (alpha_ecoff_get_elt_at_filepos): New static function. (alpha_ecoff_openr_next_archived_file): New static function. (alpha_ecoff_get_elt_at_index): New static function. (alpha_ecoff_backend_data): Initialize get_elt_at_filepos field. (ecoffalpha_little_vec): Change BFD_JUMP_TABLE_ARCHIVE from _bfd_ecoff to alpha_ecoff. * ecoff.c (ecoff_link_add_archive_symbols): Use get_elt_at_filepos field from backend structure, rather than always calling _bfd_get_elt_at_filepos. * coff-mips.c (mips_ecoff_backend_data): Initialize get_elt_at_filepos field. * archive.c (_bfd_generic_read_ar_hdr_mag): New function, copied from _bfd_generic_read_ar_hdr with minor changes. (_bfd_generic_read_ar_hdr): Use _bfd_generic_read_ar_hdr_mag. * libbfd-in.h (_bfd_generic_read_ar_hdr_mag): Declare. * libbfd.h: Rebuild. * bfd-in.h (BFD_IN_MEMORY): Define. * libbfd-in.h (struct bfd_in_memory): Define. * libbfd.c (bfd_read): Handle BFD_IN_MEMORY flag. (bfd_get_file_window): Don't try to map a BFD_IN_MEMORY file. (bfd_write, bfd_stat): Abort if BFD_IN_MEMORY is set. (bfd_tell, bfd_flush, bfd_seek): Handle BFD_IN_MEMORY flag. * bfd.c (struct _bfd): Change iostream field from char * to PTR. (bfd_get_size): Handle BFD_IN_MEMORY flag. * cache.c (bfd_cache_close): Ignore BFD_IN_MEMORY files. (bfd_open_file): Cast to PTR, not char *, when setting iostream. (bfd_cache_lookup_worker): Abort if BFD_IN_MEMORY is set. * opncls.c (bfd_fdopenr): Cast to PTR, not char *, when setting iostream. (bfd_openstreamr): Likewise. * aoutx.h (NAME(aout,some_aout_object_p)): Only fstat iostream if BFD_IN_MEMORY is not set. * riscix.c (riscix_some_aout_object_p): Likewise. * bfd-in2.h, libbfd.h: Rebuild. * targets.c (bfd_target): Add _bfd_get_elt_at_index field. (BFD_JUMP_TABLE_ARCHIVE): Add _get_elt_at_index. (bfd_get_elt_at_index): Define. * archive.c (_bfd_generic_get_elt_at_index): Rename from bfd_get_elt_at_index. Change index parameter from int to symindex. * libbfd-in.h (_bfd_generic_get_elt_at_index): Declare. (_bfd_noarchive_get_elt_at_index): Define. (_bfd_archive_bsd_get_elt_at_index): Define. (_bfd_archive_coff_get_elt_at_index): Define. * bfd-in2.h, libbfd.h: Rebuild. * aout-target.h (MY_get_elt_at_index): Define if not defined. * coff-rs6000.c (xcoff_get_elt_at_index): Define. * ieee.c (ieee_get_elt_at_index): Define. * libecoff.h (_bfd_ecoff_get_elt_at_index): Define. * oasys.c (oasys_get_elt_at_index): Define. * som.c (som_get_elt_at_index): Define. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0f3acaccceb..cf31ee0f354 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,85 @@ +Tue Jan 9 15:22:53 1996 David Mosberger-Tang + + * coff-alpha.c (alpha_relocate_section): During final link, allow + output .lita section to be bigger than 64k by adjusting gp value + on a per-input section basis. + * libecoff.h (struct ecoff_tdata): Add issued_multiple_gp_warning + field. + (struct ecoff_section_tdata): Add gp field. + Tue Jan 9 12:00:36 1996 Ian Lance Taylor + Handle Alpha ECOFF changes in OSF/1 3.2. + * libecoff.h (struct ecoff_backend_data): Add get_elt_at_filepos + field. + * coff-alpha.c: Include "aout/ar.h". + (alpha_ecoff_get_relocated_section_contents): Don't require an + ALPHA_R_IGNORE reloc after an ALPHA_R_GPDISP reloc, since OSF/1 + 3.2 doesn't generate one. + (alpha_relocate_section): Likewise. + (alpha_ecoff_slurp_armap): Define. + (alpha_ecoff_slurp_extended_name_table): Define. + (alpha_ecoff_construct_extended_name_table): Define. + (alpha_ecoff_truncate_arname): Define. + (alpha_ecoff_write_armap): Define. + (alpha_ecoff_generic_stat_arch_elt): Define. + (alpha_ecoff_update_armap_timestamp): Define. + (ARFZMAG): Define. + (alpha_ecoff_read_ar_hdr): New static function. + (alpha_ecoff_get_elt_at_filepos): New static function. + (alpha_ecoff_openr_next_archived_file): New static function. + (alpha_ecoff_get_elt_at_index): New static function. + (alpha_ecoff_backend_data): Initialize get_elt_at_filepos field. + (ecoffalpha_little_vec): Change BFD_JUMP_TABLE_ARCHIVE from + _bfd_ecoff to alpha_ecoff. + * ecoff.c (ecoff_link_add_archive_symbols): Use get_elt_at_filepos + field from backend structure, rather than always calling + _bfd_get_elt_at_filepos. + * coff-mips.c (mips_ecoff_backend_data): Initialize + get_elt_at_filepos field. + * archive.c (_bfd_generic_read_ar_hdr_mag): New function, copied + from _bfd_generic_read_ar_hdr with minor changes. + (_bfd_generic_read_ar_hdr): Use _bfd_generic_read_ar_hdr_mag. + * libbfd-in.h (_bfd_generic_read_ar_hdr_mag): Declare. + * libbfd.h: Rebuild. + + * bfd-in.h (BFD_IN_MEMORY): Define. + * libbfd-in.h (struct bfd_in_memory): Define. + * libbfd.c (bfd_read): Handle BFD_IN_MEMORY flag. + (bfd_get_file_window): Don't try to map a BFD_IN_MEMORY file. + (bfd_write, bfd_stat): Abort if BFD_IN_MEMORY is set. + (bfd_tell, bfd_flush, bfd_seek): Handle BFD_IN_MEMORY flag. + * bfd.c (struct _bfd): Change iostream field from char * to PTR. + (bfd_get_size): Handle BFD_IN_MEMORY flag. + * cache.c (bfd_cache_close): Ignore BFD_IN_MEMORY files. + (bfd_open_file): Cast to PTR, not char *, when setting iostream. + (bfd_cache_lookup_worker): Abort if BFD_IN_MEMORY is set. + * opncls.c (bfd_fdopenr): Cast to PTR, not char *, when setting + iostream. + (bfd_openstreamr): Likewise. + * aoutx.h (NAME(aout,some_aout_object_p)): Only fstat iostream if + BFD_IN_MEMORY is not set. + * riscix.c (riscix_some_aout_object_p): Likewise. + * bfd-in2.h, libbfd.h: Rebuild. + + * targets.c (bfd_target): Add _bfd_get_elt_at_index field. + (BFD_JUMP_TABLE_ARCHIVE): Add _get_elt_at_index. + (bfd_get_elt_at_index): Define. + * archive.c (_bfd_generic_get_elt_at_index): Rename from + bfd_get_elt_at_index. Change index parameter from int to + symindex. + * libbfd-in.h (_bfd_generic_get_elt_at_index): Declare. + (_bfd_noarchive_get_elt_at_index): Define. + (_bfd_archive_bsd_get_elt_at_index): Define. + (_bfd_archive_coff_get_elt_at_index): Define. + * bfd-in2.h, libbfd.h: Rebuild. + * aout-target.h (MY_get_elt_at_index): Define if not defined. + * coff-rs6000.c (xcoff_get_elt_at_index): Define. + * ieee.c (ieee_get_elt_at_index): Define. + * libecoff.h (_bfd_ecoff_get_elt_at_index): Define. + * oasys.c (oasys_get_elt_at_index): Define. + * som.c (som_get_elt_at_index): Define. + * ecoff.c (_bfd_ecoff_find_nearest_line): Don't restrict line numbers to the .text section. diff --git a/bfd/aout-target.h b/bfd/aout-target.h index 3813826c7a8..c66e433cbba 100644 --- a/bfd/aout-target.h +++ b/bfd/aout-target.h @@ -43,6 +43,10 @@ MY(callback) (abfd) obj_datasec (abfd)->vma = N_DATADDR(*execp); obj_bsssec (abfd)->vma = N_BSSADDR(*execp); + obj_textsec (abfd)->lma = obj_textsec (abfd)->vma; + obj_datasec (abfd)->lma = obj_datasec (abfd)->vma; + obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma; + /* The file offsets of the sections */ obj_textsec (abfd)->filepos = N_TXTOFF (*execp); obj_datasec (abfd)->filepos = N_DATOFF (*execp); @@ -349,6 +353,9 @@ MY_bfd_final_link (abfd, info) #ifndef MY_openr_next_archived_file #define MY_openr_next_archived_file bfd_generic_openr_next_archived_file #endif +#ifndef MY_get_elt_at_index +#define MY_get_elt_at_index _bfd_generic_get_elt_at_index +#endif #ifndef MY_generic_stat_arch_elt #define MY_generic_stat_arch_elt bfd_generic_stat_arch_elt #endif @@ -416,6 +423,9 @@ MY_bfd_final_link (abfd, info) #ifndef MY_get_section_contents #define MY_get_section_contents NAME(aout,get_section_contents) #endif +#ifndef MY_get_section_contents_in_window +#define MY_get_section_contents_in_window _bfd_generic_get_section_contents_in_window +#endif #ifndef MY_new_section_hook #define MY_new_section_hook NAME(aout,new_section_hook) #endif @@ -547,11 +557,11 @@ const bfd_target MY(vec) = TARGETNAME, /* name */ bfd_target_aout_flavour, #ifdef TARGET_IS_BIG_ENDIAN_P - true, /* target byte order (big) */ - true, /* target headers byte order (big) */ + BFD_ENDIAN_BIG, /* target byte order (big) */ + BFD_ENDIAN_BIG, /* target headers byte order (big) */ #else - false, /* target byte order (little) */ - false, /* target headers byte order (little) */ + BFD_ENDIAN_LITTLE, /* target byte order (little) */ + BFD_ENDIAN_LITTLE, /* target headers byte order (little) */ #endif (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | diff --git a/bfd/aoutx.h b/bfd/aoutx.h index 8e30f54eae9..b8389feb069 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -598,7 +598,8 @@ NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p) the default text start (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size. This is not just a mach issue. Many kernels are loaded at non standard addresses. */ - if (abfd->iostream + if (abfd->iostream != NULL + && (abfd->flags & BFD_IN_MEMORY) == 0 && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) && ((stat_buf.st_mode & 0111) != 0)) abfd->flags |= EXEC_P; @@ -1986,7 +1987,7 @@ NAME(aout,swap_std_reloc_out) (abfd, g, natptr) } /* now the fun stuff */ - if (abfd->xvec->header_byteorder_big_p != false) { + if (bfd_header_big_endian (abfd)) { natptr->r_index[0] = r_index >> 16; natptr->r_index[1] = r_index >> 8; natptr->r_index[2] = r_index; @@ -2065,7 +2066,7 @@ NAME(aout,swap_ext_reloc_out) (abfd, g, natptr) } /* now the fun stuff */ - if (abfd->xvec->header_byteorder_big_p != false) { + if (bfd_header_big_endian (abfd)) { natptr->r_index[0] = r_index >> 16; natptr->r_index[1] = r_index >> 8; natptr->r_index[2] = r_index; @@ -2142,7 +2143,7 @@ NAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) cache_ptr->address = (GET_SWORD (abfd, bytes->r_address)); /* now the fun stuff */ - if (abfd->xvec->header_byteorder_big_p != false) { + if (bfd_header_big_endian (abfd)) { r_index = (bytes->r_index[0] << 16) | (bytes->r_index[1] << 8) | bytes->r_index[2]; @@ -2198,7 +2199,7 @@ NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address); /* now the fun stuff */ - if (abfd->xvec->header_byteorder_big_p != false) { + if (bfd_header_big_endian (abfd)) { r_index = (bytes->r_index[0] << 16) | (bytes->r_index[1] << 8) | bytes->r_index[2]; @@ -2495,6 +2496,7 @@ NAME(aout,get_symbol_info) (ignore_abfd, symbol, ret) stab_name = buf; } ret->type = '-'; + ret->stab_type = type_code; ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff); ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff); ret->stab_name = stab_name; @@ -4598,8 +4600,8 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs, check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); - BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p - == output_bfd->xvec->header_byteorder_big_p); + BFD_ASSERT (input_bfd->xvec->header_byteorder + == output_bfd->xvec->header_byteorder); relocateable = finfo->info->relocateable; syms = obj_aout_external_syms (input_bfd); @@ -4633,7 +4635,7 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs, int r_length; unsigned int howto_idx; - if (input_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (input_bfd)) { r_index = ((rel->r_index[0] << 16) | (rel->r_index[1] << 8) @@ -4687,7 +4689,7 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs, asection *output_section; /* Change the r_extern value. */ - if (output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (output_bfd)) rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; else rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; @@ -4752,7 +4754,7 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs, } /* Write out the new r_index value. */ - if (output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (output_bfd)) { rel->r_index[0] = r_index >> 16; rel->r_index[1] = r_index >> 8; @@ -4937,8 +4939,8 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); - BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p - == output_bfd->xvec->header_byteorder_big_p); + BFD_ASSERT (input_bfd->xvec->header_byteorder + == output_bfd->xvec->header_byteorder); relocateable = finfo->info->relocateable; syms = obj_aout_external_syms (input_bfd); @@ -4962,7 +4964,7 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, r_addr = GET_SWORD (input_bfd, rel->r_address); - if (input_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (input_bfd)) { r_index = ((rel->r_index[0] << 16) | (rel->r_index[1] << 8) @@ -5002,7 +5004,7 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, asection *output_section; /* Change the r_extern value. */ - if (output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (output_bfd)) rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; else rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; @@ -5080,7 +5082,7 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, } /* Write out the new r_index value. */ - if (output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (output_bfd)) { rel->r_index[0] = r_index >> 16; rel->r_index[1] = r_index >> 8; @@ -5389,7 +5391,7 @@ aout_link_reloc_link_order (finfo, o, p) r_length = howto->size; PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); - if (finfo->output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (finfo->output_bfd)) { srel.r_index[0] = r_index >> 16; srel.r_index[1] = r_index >> 8; @@ -5472,7 +5474,7 @@ aout_link_reloc_link_order (finfo, o, p) { PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); - if (finfo->output_bfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (finfo->output_bfd)) { erel.r_index[0] = r_index >> 16; erel.r_index[1] = r_index >> 8; diff --git a/bfd/archive.c b/bfd/archive.c index fba52a6985f..50f5be72aa9 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -355,10 +355,17 @@ PTR _bfd_generic_read_ar_hdr (abfd) bfd *abfd; { -#ifndef errno - extern int errno; -#endif + return _bfd_generic_read_ar_hdr_mag (abfd, (const char *) NULL); +} + +/* Alpha ECOFF uses an optional different ARFMAG value, so we have a + variant of _bfd_generic_read_ar_hdr which accepts a magic string. */ +PTR +_bfd_generic_read_ar_hdr_mag (abfd, mag) + bfd *abfd; + const char *mag; +{ struct ar_hdr hdr; char *hdrp = (char *) &hdr; unsigned int parsed_size; @@ -375,7 +382,9 @@ _bfd_generic_read_ar_hdr (abfd) bfd_set_error (bfd_error_no_more_archived_files); return NULL; } - if (strncmp (hdr.ar_fmag, ARFMAG, 2)) + if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0 + && (mag == NULL + || strncmp (hdr.ar_fmag, mag, 2) != 0)) { bfd_set_error (bfd_error_malformed_archive); return NULL; @@ -521,23 +530,13 @@ _bfd_get_elt_at_filepos (archive, filepos) return NULL; } -/* -FUNCTION - bfd_get_elt_at_index - -SYNOPSIS - bfd *bfd_get_elt_at_index(bfd *archive, int index); - -DESCRIPTION - Return the BFD which is referenced by the symbol in @var{archive} - indexed by @var{index}. @var{index} should have been returned by - <> (q.v.). +/* Return the BFD which is referenced by the symbol in ABFD indexed by + INDEX. INDEX should have been returned by bfd_get_next_mapent. */ -*/ bfd * -bfd_get_elt_at_index (abfd, index) +_bfd_generic_get_elt_at_index (abfd, index) bfd *abfd; - int index; + symindex index; { carsym *entry; @@ -1724,9 +1723,9 @@ _bfd_compute_and_write_armap (arch, elength) elength += sizeof (struct ar_hdr); elength += elength % 2; - map = (struct orl *) malloc (orl_max * sizeof (struct orl)); + map = (struct orl *) bfd_malloc (orl_max * sizeof (struct orl)); if (map == NULL) - goto no_memory_return; + goto error_return; /* We put the symbol names on the arch obstack, and then discard them when done. */ @@ -1763,9 +1762,9 @@ _bfd_compute_and_write_armap (arch, elength) if (syms_max > 0) free (syms); syms_max = storage; - syms = (asymbol **) malloc ((size_t) syms_max); + syms = (asymbol **) bfd_malloc ((size_t) syms_max); if (syms == NULL) - goto no_memory_return; + goto error_return; } symcount = bfd_canonicalize_symtab (current, syms); if (symcount < 0) @@ -1790,11 +1789,11 @@ _bfd_compute_and_write_armap (arch, elength) if (orl_count == orl_max) { orl_max *= 2; - new_map = ((struct orl *) - realloc ((PTR) map, - orl_max * sizeof (struct orl))); + new_map = + ((struct orl *) + bfd_realloc (map, orl_max * sizeof (struct orl))); if (new_map == (struct orl *) NULL) - goto no_memory_return; + goto error_return; map = new_map; } @@ -1838,9 +1837,6 @@ _bfd_compute_and_write_armap (arch, elength) return ret; - no_memory_return: - bfd_set_error (bfd_error_no_memory); - error_return: if (syms_max > 0) free (syms); diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 7713760b4e8..858daa8562a 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -235,6 +235,10 @@ typedef enum bfd_format { writing out an a.out object the symbols not be hashed to eliminate duplicates. */ #define BFD_TRADITIONAL_FORMAT 0x400 + +/* This flag indicates that the BFD contents are actually cached in + memory. If this is set, iostream points to a bfd_in_memory struct. */ +#define BFD_IN_MEMORY 0x800 /* symbols and relocation */ @@ -324,9 +328,10 @@ typedef struct _symbol_info symvalue value; char type; CONST char *name; /* Symbol name. */ - char stab_other; /* Unused. */ - short stab_desc; /* Info for N_TYPE. */ - CONST char *stab_name; + unsigned char stab_type; /* Stab type. */ + char stab_other; /* Stab other. */ + short stab_desc; /* Stab desc. */ + CONST char *stab_name; /* String for stab type. */ } symbol_info; /* Hash table routines. There is no way to free up a hash table. */ @@ -464,6 +469,12 @@ extern int bfd_stat PARAMS ((bfd *abfd, struct stat *)); #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) #define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) +#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG) +#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE) +#define bfd_header_big_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG) +#define bfd_header_little_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 4ff9c9d6bc1..d5821fc24bf 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -235,6 +235,10 @@ typedef enum bfd_format { writing out an a.out object the symbols not be hashed to eliminate duplicates. */ #define BFD_TRADITIONAL_FORMAT 0x400 + +/* This flag indicates that the BFD contents are actually cached in + memory. If this is set, iostream points to a bfd_in_memory struct. */ +#define BFD_IN_MEMORY 0x800 /* symbols and relocation */ @@ -324,9 +328,10 @@ typedef struct _symbol_info symvalue value; char type; CONST char *name; /* Symbol name. */ - char stab_other; /* Unused. */ - short stab_desc; /* Info for N_TYPE. */ - CONST char *stab_name; + unsigned char stab_type; /* Stab type. */ + char stab_other; /* Stab other. */ + short stab_desc; /* Stab desc. */ + CONST char *stab_name; /* String for stab type. */ } symbol_info; /* Hash table routines. There is no way to free up a hash table. */ @@ -464,6 +469,12 @@ extern int bfd_stat PARAMS ((bfd *abfd, struct stat *)); #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) #define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) +#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG) +#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE) +#define bfd_header_big_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG) +#define bfd_header_little_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) @@ -1814,8 +1825,10 @@ struct _bfd includes `<>', IOSTREAM has been declared as a "char *", and MTIME as a "long". Their correct types, to which they are cast when used, are "FILE *" and "time_t". The iostream - is the result of an fopen on the filename. */ - char *iostream; + is the result of an fopen on the filename. However, if the + BFD_IN_MEMORY flag is set, then iostream is actually a pointer + to a bfd_in_memory struct. */ + PTR iostream; /* Is the file descriptor being cached? That is, can it be closed as needed, and re-opened when accessed later? */ @@ -2118,9 +2131,6 @@ bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym)); boolean bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head)); -bfd * -bfd_get_elt_at_index PARAMS ((bfd *archive, int index)); - bfd * bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous)); @@ -2172,6 +2182,8 @@ enum bfd_flavour { bfd_target_msdos_flavour }; +enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; + /* Forward declaration. */ typedef struct bfd_link_info _bfd_link_info; @@ -2179,8 +2191,8 @@ typedef struct bfd_target { char *name; enum bfd_flavour flavour; - boolean byteorder_big_p; - boolean header_byteorder_big_p; + enum bfd_endian byteorder; + enum bfd_endian header_byteorder; flagword object_flags; flagword section_flags; char symbol_leading_char; @@ -2275,6 +2287,7 @@ CAT(NAME,_truncate_arname),\ CAT(NAME,_write_armap),\ CAT(NAME,_read_ar_hdr),\ CAT(NAME,_openr_next_archived_file),\ +CAT(NAME,_get_elt_at_index),\ CAT(NAME,_generic_stat_arch_elt),\ CAT(NAME,_update_armap_timestamp) boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); @@ -2289,6 +2302,8 @@ CAT(NAME,_update_armap_timestamp) int stridx)); PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *)); bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); +#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i)) + bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex)); int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *)); diff --git a/bfd/bfd.c b/bfd/bfd.c index 3fa0e081c86..c565bf81797 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -44,8 +44,10 @@ CODE_FRAGMENT . includes `<>', IOSTREAM has been declared as a "char . *", and MTIME as a "long". Their correct types, to which they . are cast when used, are "FILE *" and "time_t". The iostream -. is the result of an fopen on the filename. *} -. char *iostream; +. is the result of an fopen on the filename. However, if the +. BFD_IN_MEMORY flag is set, then iostream is actually a pointer +. to a bfd_in_memory struct. *} +. PTR iostream; . . {* Is the file descriptor being cached? That is, can it be closed as . needed, and re-opened when accessed later? *} @@ -158,6 +160,7 @@ CODE_FRAGMENT . struct ieee_data_struct *ieee_data; . struct ieee_ar_data_struct *ieee_ar_data; . struct srec_data_struct *srec_data; +. struct ihex_data_struct *ihex_data; . struct tekhex_data_struct *tekhex_data; . struct elf_obj_tdata *elf_obj_data; . struct nlm_obj_tdata *nlm_obj_data; @@ -747,6 +750,9 @@ bfd_get_size (abfd) FILE *fp; struct stat buf; + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return ((struct bfd_in_memory *) abfd->iostream)->size; + fp = bfd_cache_lookup (abfd); if (0 != fstat (fileno (fp), &buf)) return 0; diff --git a/bfd/cache.c b/bfd/cache.c index c6b968a733a..f965bdce8eb 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -1,5 +1,5 @@ /* BFD library -- caching of file descriptors. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1994 Free Software Foundation, Inc. Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of BFD, the Binary File Descriptor library. @@ -16,7 +16,7 @@ GNU General Public License for more details. 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SECTION @@ -39,6 +39,11 @@ SECTION #include "sysdep.h" #include "libbfd.h" +static void insert PARAMS ((bfd *)); +static void snip PARAMS ((bfd *)); +static boolean close_one PARAMS ((void)); +static boolean bfd_cache_delete PARAMS ((bfd *)); + /* INTERNAL_FUNCTION BFD_CACHE_MAX_OPEN macro @@ -51,18 +56,10 @@ DESCRIPTION */ - -static boolean -bfd_cache_delete PARAMS ((bfd *)); - -/* Number of bfds on the chain. All such bfds have their file open; - if it closed, they get snipd()d from the chain. */ +/* The number of BFD files we have open. */ static int open_files; -static bfd *cache_sentinel = 0; /* Chain of BFDs with active fds we've - opened */ - /* INTERNAL_FUNCTION bfd_last_cache @@ -96,87 +93,128 @@ bfd *bfd_last_cache; */ -static void -DEFUN_VOID(close_one) +/* Insert a BFD into the cache. */ + +static INLINE void +insert (abfd) + bfd *abfd; { - bfd *kill = cache_sentinel; - if (kill == 0) /* Nothing in the cache */ - return ; - - /* We can only close files that want to play this game. */ - while (!kill->cacheable) { - kill = kill->lru_prev; - if (kill == cache_sentinel) /* Nobody wants to play */ - return ; + if (bfd_last_cache == NULL) + { + abfd->lru_next = abfd; + abfd->lru_prev = abfd; } - - kill->where = ftell((FILE *)(kill->iostream)); - (void) bfd_cache_delete(kill); + else + { + abfd->lru_next = bfd_last_cache; + abfd->lru_prev = bfd_last_cache->lru_prev; + abfd->lru_prev->lru_next = abfd; + abfd->lru_next->lru_prev = abfd; + } + bfd_last_cache = abfd; } -/* Cuts the BFD abfd out of the chain in the cache */ -static void -DEFUN(snip,(abfd), - bfd *abfd) +/* Remove a BFD from the cache. */ + +static INLINE void +snip (abfd) + bfd *abfd; { abfd->lru_prev->lru_next = abfd->lru_next; - abfd->lru_next->lru_prev = abfd->lru_prev; - if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL; + abfd->lru_next->lru_prev = abfd->lru_prev; + if (abfd == bfd_last_cache) + { + bfd_last_cache = abfd->lru_next; + if (abfd == bfd_last_cache) + bfd_last_cache = NULL; + } } +/* We need to open a new file, and the cache is full. Find the least + recently used cacheable BFD and close it. */ + static boolean -DEFUN(bfd_cache_delete,(abfd), - bfd *abfd) +close_one () +{ + register bfd *kill; + + if (bfd_last_cache == NULL) + kill = NULL; + else + { + for (kill = bfd_last_cache->lru_prev; + ! kill->cacheable; + kill = kill->lru_prev) + { + if (kill == bfd_last_cache) + { + kill = NULL; + break; + } + } + } + + if (kill == NULL) + { + /* There are no open cacheable BFD's. */ + return true; + } + + kill->where = ftell ((FILE *) kill->iostream); + + return bfd_cache_delete (kill); +} + +/* Close a BFD and remove it from the cache. */ + +static boolean +bfd_cache_delete (abfd) + bfd *abfd; { boolean ret; - if (fclose ((FILE *)(abfd->iostream)) == 0) + if (fclose ((FILE *) abfd->iostream) == 0) ret = true; else { ret = false; bfd_set_error (bfd_error_system_call); } + snip (abfd); + abfd->iostream = NULL; - open_files--; - bfd_last_cache = 0; + --open_files; + return ret; } - -static bfd * -DEFUN(insert,(x,y), - bfd *x AND - bfd *y) -{ - if (y) { - x->lru_next = y; - x->lru_prev = y->lru_prev; - y->lru_prev->lru_next = x; - y->lru_prev = x; - - } - else { - x->lru_prev = x; - x->lru_next = x; - } - return x; -} - -/* Initialize a BFD by putting it on the cache LRU. */ +/* +INTERNAL_FUNCTION + bfd_cache_init + +SYNOPSIS + boolean bfd_cache_init (bfd *abfd); + +DESCRIPTION + Add a newly opened BFD to the cache. +*/ -void -DEFUN(bfd_cache_init,(abfd), - bfd *abfd) +boolean +bfd_cache_init (abfd) + bfd *abfd; { + BFD_ASSERT (abfd->iostream != NULL); if (open_files >= BFD_CACHE_MAX_OPEN) - close_one (); - cache_sentinel = insert(abfd, cache_sentinel); + { + if (! close_one ()) + return false; + } + insert (abfd); ++open_files; + return true; } - /* INTERNAL_FUNCTION bfd_cache_close @@ -192,19 +230,16 @@ RETURNS <> is returned if closing the file fails, <> is returned if all is well. */ + boolean -DEFUN(bfd_cache_close,(abfd), - bfd *abfd) +bfd_cache_close (abfd) + bfd *abfd; { - /* If this file is open then remove from the chain */ - if (abfd->iostream) - { - return bfd_cache_delete(abfd); - } - else - { - return true; - } + if (abfd->iostream == NULL + || (abfd->flags & BFD_IN_MEMORY) != 0) + return true; + + return bfd_cache_delete (abfd); } /* @@ -223,40 +258,47 @@ DESCRIPTION */ FILE * -DEFUN(bfd_open_file, (abfd), - bfd *abfd) +bfd_open_file (abfd) + bfd *abfd; { abfd->cacheable = true; /* Allow it to be closed later. */ - if(open_files >= BFD_CACHE_MAX_OPEN) { - close_one(); - } - - switch (abfd->direction) { - case read_direction: - case no_direction: - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB); - break; - case both_direction: - case write_direction: - if (abfd->opened_once == true) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB); - if (!abfd->iostream) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB); - } - } else { - /*open for creat */ - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB); - abfd->opened_once = true; + if (open_files >= BFD_CACHE_MAX_OPEN) + { + if (! close_one ()) + return NULL; + } + + switch (abfd->direction) + { + case read_direction: + case no_direction: + abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB); + break; + case both_direction: + case write_direction: + if (abfd->opened_once == true) + { + abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB); + if (abfd->iostream == NULL) + abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB); + } + else + { + /*open for creat */ + abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WB); + abfd->opened_once = true; + } + break; } - break; - } - if (abfd->iostream) { - bfd_cache_init (abfd); - } + if (abfd->iostream != NULL) + { + if (! bfd_cache_init (abfd)) + return NULL; + } - return (FILE *)(abfd->iostream); + return (FILE *) abfd->iostream; } /* @@ -272,40 +314,34 @@ DESCRIPTION necessary, it open it. If there are already more than <> files open, it tries to close one first, to avoid running out of file descriptors. - */ FILE * -DEFUN(bfd_cache_lookup_worker,(abfd), - bfd *abfd) +bfd_cache_lookup_worker (abfd) + bfd *abfd; { + if ((abfd->flags & BFD_IN_MEMORY) != 0) + abort (); + if (abfd->my_archive) - { - abfd = abfd->my_archive; - } - /* Is this file already open .. if so then quick exit */ - if (abfd->iostream) - { - if (abfd != cache_sentinel) { - /* Place onto head of lru chain */ + abfd = abfd->my_archive; + + if (abfd->iostream != NULL) + { + /* Move the file to the start of the cache. */ + if (abfd != bfd_last_cache) + { snip (abfd); - cache_sentinel = insert(abfd, cache_sentinel); + insert (abfd); } - } - /* This is a BFD without a stream - - so it must have been closed or never opened. - find an empty cache entry and use it. */ - else - { - - if (open_files >= BFD_CACHE_MAX_OPEN) - { - close_one(); - } + } + else + { + if (bfd_open_file (abfd) == NULL) + return NULL; + if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0) + return NULL; + } - BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ; - fseek((FILE *)(abfd->iostream), abfd->where, false); - } - bfd_last_cache = abfd; - return (FILE *)(abfd->iostream); + return (FILE *) abfd->iostream; } diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 4ad7077fa62..1bbec4c0194 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "coff/symconst.h" #include "coff/ecoff.h" #include "coff/alpha.h" +#include "aout/ar.h" #include "libcoff.h" #include "libecoff.h" @@ -57,6 +58,10 @@ static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd_byte *, PTR)); static boolean alpha_adjust_headers PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *)); +static PTR alpha_ecoff_read_ar_hdr PARAMS ((bfd *)); +static bfd *alpha_ecoff_get_elt_at_filepos PARAMS ((bfd *, file_ptr)); +static bfd *alpha_ecoff_openr_next_archived_file PARAMS ((bfd *, bfd *)); +static bfd *alpha_ecoff_get_elt_at_index PARAMS ((bfd *, symindex)); /* ECOFF has COFF sections, but the debugging information is stored in a completely different format. ECOFF targets use some of the @@ -525,7 +530,7 @@ alpha_ecoff_swap_reloc_in (abfd, ext_ptr, intern) intern->r_vaddr = bfd_h_get_64 (abfd, (bfd_byte *) ext->r_vaddr); intern->r_symndx = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_symndx); - BFD_ASSERT (abfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (bfd_header_little_endian (abfd)); intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) >> RELOC_BITS0_TYPE_SH_LITTLE); @@ -598,7 +603,7 @@ alpha_ecoff_swap_reloc_out (abfd, intern, dst) bfd_h_put_64 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr); bfd_h_put_32 (abfd, symndx, (bfd_byte *) ext->r_symndx); - BFD_ASSERT (abfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (bfd_header_little_endian (abfd)); ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE) & RELOC_BITS0_TYPE_LITTLE); @@ -914,16 +919,12 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, /* This marks the ldah of an ldah/lda pair which loads the gp register with the difference of the gp value and the current location. The second of the pair is r_size bytes - ahead, and is marked with an ALPHA_R_IGNORE reloc. */ + ahead; it used to be marked with an ALPHA_R_IGNORE reloc, + but that no longer happens in OSF/1 3.2. */ { unsigned long insn1, insn2; bfd_vma addend; - BFD_ASSERT (reloc_vector[1] != NULL - && reloc_vector[1]->howto->type == ALPHA_R_IGNORE - && (rel->address + rel->addend - == reloc_vector[1]->address)); - /* Get the two instructions. */ insn1 = bfd_get_32 (input_bfd, data + rel->address); insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); @@ -945,7 +946,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, /* The existing addend includes the different between the gp of the input BFD and the address in the input BFD. Subtract this out. */ - addend -= (reloc_vector[1]->addend + addend -= (ecoff_data (input_bfd)->gp - (input_section->vma + rel->address)); /* Now add in the final gp value, and subtract out the @@ -1364,7 +1365,7 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, bfd_byte *contents; PTR external_relocs; { - asection **symndx_to_section; + asection **symndx_to_section, *lita_sec; struct ecoff_link_hash_entry **sym_hashes; bfd_vma gp; boolean gp_undefined; @@ -1422,14 +1423,79 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, sym_hashes = ecoff_data (input_bfd)->sym_hashes; + /* On the Alpha, the .lita section must be addressable by the global + pointer. To support large programs, we need to allow multiple + global pointers. This works as long as each input .lita section + is <64KB big. This implies that when producing relocatable + output, the .lita section is limited to 64KB. . */ + + lita_sec = symndx_to_section[RELOC_SECTION_LITA]; gp = ecoff_data (output_bfd)->gp; - if (gp == 0) - gp_undefined = true; - else - gp_undefined = false; + if (! info->relocateable && lita_sec != NULL) + { + struct ecoff_section_tdata *lita_sec_data; + + /* Make sure we have a section data structure to which we can + hang on to the gp value we pick for the section. */ + lita_sec_data = ecoff_section_data (input_bfd, lita_sec); + if (lita_sec_data == NULL) + { + lita_sec_data = ((struct ecoff_section_tdata *) + bfd_zalloc (input_bfd, + sizeof (struct ecoff_section_tdata))); + ecoff_section_data (input_bfd, lita_sec) = lita_sec_data; + } + + if (lita_sec_data->gp != 0) + { + /* If we already assigned a gp to this section, we better + stick with that value. */ + gp = lita_sec_data->gp; + } + else + { + bfd_vma lita_vma; + bfd_size_type lita_size; + + lita_vma = lita_sec->output_offset + lita_sec->output_section->vma; + lita_size = lita_sec->_cooked_size; + if (lita_size == 0) + lita_size = lita_sec->_raw_size; + + if (gp == 0 + || lita_vma < gp - 0x8000 + || lita_vma + lita_size >= gp + 0x8000) + { + /* Either gp hasn't been set at all or the current gp + cannot address this .lita section. In both cases we + reset the gp to point into the "middle" of the + current input .lita section. For now, we issue a + warning when redefining the gp value (probably should + be made optional). */ + if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning) + { + (*_bfd_error_handler) + ("%s: warning: using multiple gp values", + bfd_get_filename (output_bfd)); + ecoff_data (output_bfd)->issued_multiple_gp_warning = true; + } + if (lita_vma < gp - 0x8000) + gp = lita_vma + lita_size - 0x8000; + else + gp = lita_vma + 0x8000; + + } + + lita_sec_data->gp = gp; + } + + ecoff_data (output_bfd)->gp = gp; + } + + gp_undefined = (gp == 0); - BFD_ASSERT (output_bfd->xvec->header_byteorder_big_p == false); - BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (bfd_header_little_endian (output_bfd)); + BFD_ASSERT (bfd_header_little_endian (input_bfd)); ext_rel = (struct external_reloc *) external_relocs; ext_rel_end = ext_rel + input_section->reloc_count; @@ -1469,12 +1535,12 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, abort (); case ALPHA_R_IGNORE: - /* This reloc appears after a GPDISP reloc. It marks the - position of the second instruction to be altered by the - GPDISP reloc, but is not otherwise used for anything. - For some reason, the address of the relocation does not - appear to include the section VMA, unlike the other - relocation types. */ + /* This reloc appears after a GPDISP reloc. On earlier + versions of OSF/1, It marked the position of the second + instruction to be altered by the GPDISP reloc, but it is + not otherwise used for anything. For some reason, the + address of the relocation does not appear to include the + section VMA, unlike the other relocation types. */ if (info->relocateable) bfd_h_put_64 (input_bfd, input_section->output_offset + r_vaddr, @@ -1544,19 +1610,11 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, /* This marks the ldah of an ldah/lda pair which loads the gp register with the difference of the gp value and the current location. The second of the pair is r_symndx - bytes ahead, and is also marked with an ALPHA_R_IGNORE - reloc. */ + bytes ahead. It used to be marked with an ALPHA_R_IGNORE + reloc, but OSF/1 3.2 no longer does that. */ { unsigned long insn1, insn2; - BFD_ASSERT (ext_rel + 1 < ext_rel_end - && (((ext_rel + 1)->r_bits[0] - & RELOC_BITS0_TYPE_LITTLE) - >> RELOC_BITS0_TYPE_SH_LITTLE) == ALPHA_R_IGNORE - && (bfd_h_get_64 (input_bfd, - (bfd_byte *) (ext_rel + 1)->r_vaddr) - == r_vaddr - input_section->vma + r_symndx)); - /* Get the two instructions. */ insn1 = bfd_get_32 (input_bfd, contents + r_vaddr - input_section->vma); @@ -1949,6 +2007,234 @@ alpha_adjust_headers (abfd, fhdr, ahdr) return true; } +/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital + introduced archive packing, in which the elements in an archive are + optionally compressed using a simple dictionary scheme. We know + how to read such archives, but we don't write them. */ + +#define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap +#define alpha_ecoff_slurp_extended_name_table \ + _bfd_ecoff_slurp_extended_name_table +#define alpha_ecoff_construct_extended_name_table \ + _bfd_ecoff_construct_extended_name_table +#define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname +#define alpha_ecoff_write_armap _bfd_ecoff_write_armap +#define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt +#define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp + +/* A compressed file uses this instead of ARFMAG. */ + +#define ARFZMAG "Z\012" + +/* Read an archive header. This is like the standard routine, but it + also accepts ARFZMAG. */ + +static PTR +alpha_ecoff_read_ar_hdr (abfd) + bfd *abfd; +{ + struct areltdata *ret; + struct ar_hdr *h; + + ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG); + if (ret == NULL) + return NULL; + + h = (struct ar_hdr *) ret->arch_header; + if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0) + { + bfd_byte ab[8]; + + /* This is a compressed file. We must set the size correctly. + The size is the eight bytes after the dummy file header. */ + if (bfd_seek (abfd, FILHSZ, SEEK_CUR) != 0 + || bfd_read (ab, 1, 8, abfd) != 8 + || bfd_seek (abfd, - (FILHSZ + 8), SEEK_CUR) != 0) + return NULL; + + ret->parsed_size = bfd_h_get_64 (abfd, ab); + } + + return (PTR) ret; +} + +/* Get an archive element at a specified file position. This is where + we uncompress the archive element if necessary. */ + +static bfd * +alpha_ecoff_get_elt_at_filepos (archive, filepos) + bfd *archive; + file_ptr filepos; +{ + bfd *nbfd = NULL; + struct areltdata *tdata; + struct ar_hdr *hdr; + bfd_byte ab[8]; + bfd_size_type size; + bfd_byte *buf, *p; + struct bfd_in_memory *bim; + + nbfd = _bfd_get_elt_at_filepos (archive, filepos); + if (nbfd == NULL) + goto error_return; + + if ((nbfd->flags & BFD_IN_MEMORY) != 0) + { + /* We have already expanded this BFD. */ + return nbfd; + } + + tdata = (struct areltdata *) nbfd->arelt_data; + hdr = (struct ar_hdr *) tdata->arch_header; + if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0) + return nbfd; + + /* We must uncompress this element. We do this by copying it into a + memory buffer, and making bfd_read and bfd_seek use that buffer. + This can use a lot of memory, but it's simpler than getting a + temporary file, making that work with the file descriptor caching + code, and making sure that it is deleted at all appropriate + times. It can be changed if it ever becomes important. */ + + /* The compressed file starts with a dummy ECOFF file header. */ + if (bfd_seek (nbfd, FILHSZ, SEEK_SET) != 0) + goto error_return; + + /* The next eight bytes are the real file size. */ + if (bfd_read (ab, 1, 8, nbfd) != 8) + goto error_return; + size = bfd_h_get_64 (nbfd, ab); + + if (size == 0) + buf = NULL; + else + { + bfd_size_type left; + bfd_byte dict[4096]; + unsigned int h; + bfd_byte b; + + buf = (bfd_byte *) bfd_alloc (nbfd, size); + if (buf == NULL) + goto error_return; + p = buf; + + left = size; + + /* I don't know what the next eight bytes are for. */ + if (bfd_read (ab, 1, 8, nbfd) != 8) + goto error_return; + + /* This is the uncompression algorithm. It's a simple + dictionary based scheme in which each character is predicted + by a hash of the previous three characters. A control byte + indicates whether the character is predicted or whether it + appears in the input stream; each control byte manages the + next eight bytes in the output stream. */ + memset (dict, 0, sizeof dict); + h = 0; + while (bfd_read (&b, 1, 1, nbfd) == 1) + { + unsigned int i; + + for (i = 0; i < 8; i++, b >>= 1) + { + bfd_byte n; + + if ((b & 1) == 0) + n = dict[h]; + else + { + if (! bfd_read (&n, 1, 1, nbfd)) + goto error_return; + dict[h] = n; + } + + *p++ = n; + + --left; + if (left == 0) + break; + + h <<= 4; + h ^= n; + h &= sizeof dict - 1; + } + + if (left == 0) + break; + } + } + + /* Now the uncompressed file contents are in buf. */ + bim = ((struct bfd_in_memory *) + bfd_alloc (nbfd, sizeof (struct bfd_in_memory))); + if (bim == NULL) + goto error_return; + bim->size = size; + bim->buffer = buf; + + nbfd->mtime_set = true; + nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10); + + nbfd->flags |= BFD_IN_MEMORY; + nbfd->iostream = (PTR) bim; + BFD_ASSERT (! nbfd->cacheable); + + return nbfd; + + error_return: + if (nbfd != NULL) + bfd_close (nbfd); + return NULL; +} + +/* Open the next archived file. */ + +static bfd * +alpha_ecoff_openr_next_archived_file (archive, last_file) + bfd *archive; + bfd *last_file; +{ + file_ptr filestart; + + if (last_file == NULL) + filestart = bfd_ardata (archive)->first_file_filepos; + else + { + struct areltdata *t; + struct ar_hdr *h; + bfd_size_type size; + + /* We can't use arelt_size here, because that uses parsed_size, + which is the uncompressed size. We need the compressed size. */ + t = (struct areltdata *) last_file->arelt_data; + h = (struct ar_hdr *) t->arch_header; + size = strtol (h->ar_size, (char **) NULL, 10); + + /* Pad to an even boundary... + Note that last_file->origin can be odd in the case of + BSD-4.4-style element with a long odd size. */ + filestart = last_file->origin + size; + filestart += filestart % 2; + } + + return alpha_ecoff_get_elt_at_filepos (archive, filestart); +} + +/* Open the archive file given an index into the armap. */ + +static bfd * +alpha_ecoff_get_elt_at_index (abfd, index) + bfd *abfd; + symindex index; +{ + carsym *entry; + + entry = bfd_ardata (abfd)->symdefs + index; + return alpha_ecoff_get_elt_at_filepos (abfd, entry->file_offset); +} + /* This is the ECOFF backend structure. The backend field of the target vector points to this. */ @@ -2038,7 +2324,9 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = /* Relocate section contents while linking. */ alpha_relocate_section, /* Do final adjustments to filehdr and aouthdr. */ - alpha_adjust_headers + alpha_adjust_headers, + /* Read an element from an archive at a given file position. */ + alpha_ecoff_get_elt_at_filepos }; /* Looking up a reloc type is Alpha specific. */ @@ -2059,8 +2347,8 @@ const bfd_target ecoffalpha_little_vec = { "ecoff-littlealpha", /* name */ bfd_target_ecoff_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | @@ -2087,7 +2375,7 @@ const bfd_target ecoffalpha_little_vec = BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), BFD_JUMP_TABLE_COPY (_bfd_ecoff), BFD_JUMP_TABLE_CORE (_bfd_nocore), - BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), + BFD_JUMP_TABLE_ARCHIVE (alpha_ecoff), BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), BFD_JUMP_TABLE_WRITE (_bfd_ecoff), diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c index 51a5ecd8a31..bab8beba271 100644 --- a/bfd/coff-mips.c +++ b/bfd/coff-mips.c @@ -396,12 +396,12 @@ mips_ecoff_bad_format_hook (abfd, filehdr) case MIPS_MAGIC_BIG: case MIPS_MAGIC_BIG2: case MIPS_MAGIC_BIG3: - return abfd->xvec->byteorder_big_p; + return bfd_big_endian (abfd); case MIPS_MAGIC_LITTLE: case MIPS_MAGIC_LITTLE2: case MIPS_MAGIC_LITTLE3: - return abfd->xvec->byteorder_big_p == false; + return bfd_little_endian (abfd); default: return false; @@ -423,7 +423,7 @@ mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern) const RELOC *ext = (RELOC *) ext_ptr; intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr); - if (abfd->xvec->header_byteorder_big_p != false) + if (bfd_header_big_endian (abfd)) { intern->r_symndx = (((int) ext->r_bits[0] << RELOC_BITS0_SYMNDX_SH_LEFT_BIG) @@ -500,7 +500,7 @@ mips_ecoff_swap_reloc_out (abfd, intern, dst) } bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr); - if (abfd->xvec->header_byteorder_big_p != false) + if (bfd_header_big_endian (abfd)) { ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG; ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG; @@ -1190,8 +1190,8 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section, boolean got_lo; struct internal_reloc lo_int_rel; - BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p - == output_bfd->xvec->header_byteorder_big_p); + BFD_ASSERT (input_bfd->xvec->header_byteorder + == output_bfd->xvec->header_byteorder); /* We keep a table mapping the symndx found in an internal reloc to the appropriate section. This is faster than looking up the @@ -1927,7 +1927,7 @@ mips_relax_section (abfd, sec, info, again) continue; /* Quickly check that this reloc is external PCREL16. */ - if (abfd->xvec->header_byteorder_big_p) + if (bfd_header_big_endian (abfd)) { if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0 || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG) @@ -2488,7 +2488,9 @@ static const struct ecoff_backend_data mips_ecoff_backend_data = /* Relocate section contents while linking. */ mips_relocate_section, /* Do final adjustments to filehdr and aouthdr. */ - NULL + NULL, + /* Read an element from an archive at a given file position. */ + _bfd_get_elt_at_filepos }; /* Looking up a reloc type is MIPS specific. */ @@ -2509,8 +2511,8 @@ const bfd_target ecoff_little_vec = { "ecoff-littlemips", /* name */ bfd_target_ecoff_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | @@ -2551,8 +2553,8 @@ const bfd_target ecoff_big_vec = { "ecoff-bigmips", /* name */ bfd_target_ecoff_flavour, - true, /* data byte order is big */ - true, /* header byte order is big */ + BFD_ENDIAN_BIG, /* data byte order is big */ + BFD_ENDIAN_BIG, /* header byte order is big */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index ba27ebe10ae..c07981bfee3 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -658,6 +658,10 @@ struct xcoff_ar_hdr bfd_false) #define xcoff_truncate_arname bfd_dont_truncate_arname +/* We can use the standard get_elt_at_index routine. */ + +#define xcoff_get_elt_at_index _bfd_generic_get_elt_at_index + /* XCOFF archives do not have a timestamp. */ #define xcoff_update_armap_timestamp bfd_true @@ -1346,8 +1350,8 @@ const bfd_target "aixcoff-rs6000", /* name */ #endif bfd_target_coff_flavour, - true, /* data byte order is big */ - true, /* header byte order is big */ + BFD_ENDIAN_BIG, /* data byte order is big */ + BFD_ENDIAN_BIG, /* header byte order is big */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | DYNAMIC | diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index dd68b8ac3a2..2a35b5be659 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -36,6 +36,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ do casts, and casting to the left of assignment isn't portable. */ #define set_tdata(bfd, v) ((bfd)->tdata.any = (PTR) (v)) +/* If BFD_IN_MEMORY is set for a BFD, then the iostream fields points + to an instance of this structure. */ + +struct bfd_in_memory +{ + /* Size of buffer. */ + bfd_size_type size; + /* Buffer holding contents of BFD. */ + bfd_byte *buffer; +}; + /* tdata for an archive. For an input archive, cache needs to be free()'d. For an output archive, symdefs do. */ @@ -70,16 +81,16 @@ struct areltdata { #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) -char *bfd_zmalloc PARAMS ((bfd_size_type size)); +extern PTR bfd_malloc PARAMS ((size_t)); +extern PTR bfd_realloc PARAMS ((PTR, size_t)); +extern PTR bfd_zmalloc PARAMS ((size_t)); extern bfd_error_handler_type _bfd_error_handler; -/* These routines allocate and free things on the BFD's obstack. Note - that realloc can never occur in place. */ +/* These routines allocate and free things on the BFD's obstack. */ PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); -PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t size)); void bfd_alloc_grow PARAMS ((bfd *abfd, PTR thing, size_t size)); PTR bfd_alloc_finish PARAMS ((bfd *abfd)); PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t wanted)); @@ -101,6 +112,7 @@ extern boolean _bfd_construct_extended_name_table boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); boolean _bfd_compute_and_write_armap PARAMS ((bfd *, unsigned int elength)); bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos)); +extern bfd *_bfd_generic_get_elt_at_index PARAMS ((bfd *, symindex)); bfd * _bfd_new_bfd PARAMS ((void)); boolean bfd_false PARAMS ((bfd *ignore)); @@ -130,13 +142,15 @@ boolean coff_write_armap PARAMS ((bfd *arch, unsigned int elength, extern PTR _bfd_generic_read_ar_hdr PARAMS ((bfd *)); +extern PTR _bfd_generic_read_ar_hdr_mag PARAMS ((bfd *, const char *)); + bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive, bfd *last_file)); int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); #define _bfd_read_ar_hdr(abfd) \ - BFD_SEND (abfd, _bfd_read_ar_hdr, (abfd)) + BFD_SEND (abfd, _bfd_read_ar_hdr_fn, (abfd)) /* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ @@ -148,6 +162,8 @@ int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); extern boolean _bfd_generic_get_section_contents PARAMS ((bfd *, asection *, PTR location, file_ptr offset, bfd_size_type count)); +extern boolean _bfd_generic_get_section_contents_in_window + PARAMS ((bfd *, asection *, bfd_window *, file_ptr, bfd_size_type)); /* Generic routines to use for BFD_JUMP_TABLE_COPY. Use BFD_JUMP_TABLE_COPY (_bfd_generic). */ @@ -163,7 +179,7 @@ extern boolean _bfd_generic_get_section_contents #define _bfd_generic_bfd_copy_private_symbol_data \ ((boolean (*) PARAMS ((bfd *, asymbol *, bfd *, asymbol *))) bfd_true) #define _bfd_generic_bfd_print_private_bfd_data \ - ((boolean (*) PARAMS ((bfd *, void *))) bfd_true) + ((boolean (*) PARAMS ((bfd *, PTR))) bfd_true) /* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */ @@ -190,6 +206,8 @@ extern boolean _bfd_nocore_core_file_matches_executable_p #define _bfd_noarchive_read_ar_hdr bfd_nullvoidptr #define _bfd_noarchive_openr_next_archived_file \ ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr) +#define _bfd_noarchive_get_elt_at_index \ + ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr) #define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt #define _bfd_noarchive_update_armap_timestamp bfd_false @@ -206,6 +224,7 @@ extern boolean _bfd_archive_bsd_construct_extended_name_table #define _bfd_archive_bsd_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_bsd_openr_next_archived_file \ bfd_generic_openr_next_archived_file +#define _bfd_archive_bsd_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_bsd_generic_stat_arch_elt \ bfd_generic_stat_arch_elt extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *)); @@ -223,6 +242,7 @@ extern boolean _bfd_archive_coff_construct_extended_name_table #define _bfd_archive_coff_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_coff_openr_next_archived_file \ bfd_generic_openr_next_archived_file +#define _bfd_archive_coff_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_coff_generic_stat_arch_elt \ bfd_generic_stat_arch_elt #define _bfd_archive_coff_update_armap_timestamp bfd_true @@ -401,6 +421,9 @@ extern bfd_reloc_status_type _bfd_relocate_contents /* Create a string table. */ extern struct bfd_strtab_hash *_bfd_stringtab_init PARAMS ((void)); +/* Create an XCOFF .debug section style string table. */ +extern struct bfd_strtab_hash *_bfd_xcoff_stringtab_init PARAMS ((void)); + /* Free a string table. */ extern void _bfd_stringtab_free PARAMS ((struct bfd_strtab_hash *)); diff --git a/bfd/libbfd.c b/bfd/libbfd.c index 4bd8f5824ea..cd8f896cb71 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -155,27 +155,60 @@ _bfd_dummy_target (ignore_abfd) return 0; } +/* Allocate memory using malloc. */ -#ifndef bfd_zmalloc -/* allocate and clear storage */ +PTR +bfd_malloc (size) + size_t size; +{ + PTR ptr; -char * + ptr = (PTR) malloc (size); + if (ptr == NULL && size != 0) + bfd_set_error (bfd_error_no_memory); + return ptr; +} + +/* Reallocate memory using realloc. */ + +PTR +bfd_realloc (ptr, size) + PTR ptr; + size_t size; +{ + PTR ret; + + if (ptr == NULL) + ret = malloc (size); + else + ret = realloc (ptr, size); + + if (ret == NULL) + bfd_set_error (bfd_error_no_memory); + + return ret; +} + +/* Allocate memory using malloc and clear it. */ + +PTR bfd_zmalloc (size) - bfd_size_type size; + size_t size; { - char *ptr = (char *) malloc ((size_t) size); + PTR ptr; + + ptr = (PTR) malloc (size); if (size != 0) { if (ptr == NULL) bfd_set_error (bfd_error_no_memory); else - memset (ptr, 0, (size_t) size); + memset (ptr, 0, size); } return ptr; } -#endif /* bfd_zmalloc */ /* Some IO code */ @@ -208,6 +241,24 @@ bfd_read (ptr, size, nitems, abfd) bfd *abfd; { int nread; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + { + struct bfd_in_memory *bim; + bfd_size_type get; + + bim = (struct bfd_in_memory *) abfd->iostream; + get = size * nitems; + if (abfd->where + get > bim->size) + { + get = bim->size - abfd->where; + bfd_set_error (bfd_error_file_truncated); + } + memcpy (ptr, bim->buffer + abfd->where, get); + abfd->where += get; + return get; + } + nread = real_read (ptr, 1, (size_t)(size*nitems), bfd_cache_lookup(abfd)); #ifdef FILE_OFFSET_IS_CHAR_INDEX if (nread > 0) @@ -350,7 +401,9 @@ bfd_get_file_window (abfd, offset, size, windowp, writable) i->data = 0; } #ifdef HAVE_MMAP - if (ok_to_map && (i->data == 0 || i->mapped == 1)) + if (ok_to_map + && (i->data == 0 || i->mapped == 1) + && (abfd->flags & BFD_IN_MEMORY) == 0) { file_ptr file_offset, offset2; size_t real_size; @@ -429,10 +482,7 @@ bfd_get_file_window (abfd, offset, size, windowp, writable) if (debug_windows) fprintf (stderr, "\n\t%s(%6ld)", i->data ? "realloc" : " malloc", (long) size_to_alloc); - if (i->data) - i->data = (PTR) realloc (i->data, size_to_alloc); - else - i->data = (PTR) malloc (size_to_alloc); + i->data = (PTR) bfd_realloc (i->data, size_to_alloc); if (debug_windows) fprintf (stderr, "\t-> %p\n", i->data); i->refcount = 1; @@ -470,8 +520,13 @@ bfd_write (ptr, size, nitems, abfd) bfd_size_type nitems; bfd *abfd; { - long nwrote = fwrite (ptr, 1, (size_t) (size * nitems), - bfd_cache_lookup (abfd)); + long nwrote; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + abort (); + + nwrote = fwrite (ptr, 1, (size_t) (size * nitems), + bfd_cache_lookup (abfd)); #ifdef FILE_OFFSET_IS_CHAR_INDEX if (nwrote > 0) abfd->where += nwrote; @@ -517,6 +572,9 @@ bfd_tell (abfd) { file_ptr ptr; + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return abfd->where; + ptr = ftell (bfd_cache_lookup(abfd)); if (abfd->my_archive) @@ -529,6 +587,8 @@ int bfd_flush (abfd) bfd *abfd; { + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return 0; return fflush (bfd_cache_lookup(abfd)); } @@ -541,6 +601,10 @@ bfd_stat (abfd, statbuf) { FILE *f; int result; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + abort (); + f = bfd_cache_lookup (abfd); if (f == NULL) { @@ -573,6 +637,16 @@ bfd_seek (abfd, position, direction) if (direction == SEEK_CUR && position == 0) return 0; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + { + if (direction == SEEK_SET) + abfd->where = position; + else + abfd->where += position; + return 0; + } + #ifdef FILE_OFFSET_IS_CHAR_INDEX if (abfd->format != bfd_archive && abfd->my_archive == 0) { @@ -1044,7 +1118,7 @@ _bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count) w->i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal)); if (w->i == NULL) return false; - w->i->data = (PTR) malloc ((size_t) count); + w->i->data = (PTR) bfd_malloc ((size_t) count); if (w->i->data == NULL) { free (w->i); diff --git a/bfd/libbfd.h b/bfd/libbfd.h index e86f355c735..dc22c649423 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -36,6 +36,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ do casts, and casting to the left of assignment isn't portable. */ #define set_tdata(bfd, v) ((bfd)->tdata.any = (PTR) (v)) +/* If BFD_IN_MEMORY is set for a BFD, then the iostream fields points + to an instance of this structure. */ + +struct bfd_in_memory +{ + /* Size of buffer. */ + bfd_size_type size; + /* Buffer holding contents of BFD. */ + bfd_byte *buffer; +}; + /* tdata for an archive. For an input archive, cache needs to be free()'d. For an output archive, symdefs do. */ @@ -70,16 +81,16 @@ struct areltdata { #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) -char *bfd_zmalloc PARAMS ((bfd_size_type size)); +extern PTR bfd_malloc PARAMS ((size_t)); +extern PTR bfd_realloc PARAMS ((PTR, size_t)); +extern PTR bfd_zmalloc PARAMS ((size_t)); extern bfd_error_handler_type _bfd_error_handler; -/* These routines allocate and free things on the BFD's obstack. Note - that realloc can never occur in place. */ +/* These routines allocate and free things on the BFD's obstack. */ PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); -PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t size)); void bfd_alloc_grow PARAMS ((bfd *abfd, PTR thing, size_t size)); PTR bfd_alloc_finish PARAMS ((bfd *abfd)); PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t wanted)); @@ -101,6 +112,7 @@ extern boolean _bfd_construct_extended_name_table boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); boolean _bfd_compute_and_write_armap PARAMS ((bfd *, unsigned int elength)); bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos)); +extern bfd *_bfd_generic_get_elt_at_index PARAMS ((bfd *, symindex)); bfd * _bfd_new_bfd PARAMS ((void)); boolean bfd_false PARAMS ((bfd *ignore)); @@ -130,13 +142,15 @@ boolean coff_write_armap PARAMS ((bfd *arch, unsigned int elength, extern PTR _bfd_generic_read_ar_hdr PARAMS ((bfd *)); +extern PTR _bfd_generic_read_ar_hdr_mag PARAMS ((bfd *, const char *)); + bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive, bfd *last_file)); int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); #define _bfd_read_ar_hdr(abfd) \ - BFD_SEND (abfd, _bfd_read_ar_hdr, (abfd)) + BFD_SEND (abfd, _bfd_read_ar_hdr_fn, (abfd)) /* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ @@ -148,6 +162,8 @@ int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); extern boolean _bfd_generic_get_section_contents PARAMS ((bfd *, asection *, PTR location, file_ptr offset, bfd_size_type count)); +extern boolean _bfd_generic_get_section_contents_in_window + PARAMS ((bfd *, asection *, bfd_window *, file_ptr, bfd_size_type)); /* Generic routines to use for BFD_JUMP_TABLE_COPY. Use BFD_JUMP_TABLE_COPY (_bfd_generic). */ @@ -163,7 +179,7 @@ extern boolean _bfd_generic_get_section_contents #define _bfd_generic_bfd_copy_private_symbol_data \ ((boolean (*) PARAMS ((bfd *, asymbol *, bfd *, asymbol *))) bfd_true) #define _bfd_generic_bfd_print_private_bfd_data \ - ((boolean (*) PARAMS ((bfd *, void *))) bfd_true) + ((boolean (*) PARAMS ((bfd *, PTR))) bfd_true) /* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */ @@ -190,6 +206,8 @@ extern boolean _bfd_nocore_core_file_matches_executable_p #define _bfd_noarchive_read_ar_hdr bfd_nullvoidptr #define _bfd_noarchive_openr_next_archived_file \ ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr) +#define _bfd_noarchive_get_elt_at_index \ + ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr) #define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt #define _bfd_noarchive_update_armap_timestamp bfd_false @@ -206,6 +224,7 @@ extern boolean _bfd_archive_bsd_construct_extended_name_table #define _bfd_archive_bsd_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_bsd_openr_next_archived_file \ bfd_generic_openr_next_archived_file +#define _bfd_archive_bsd_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_bsd_generic_stat_arch_elt \ bfd_generic_stat_arch_elt extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *)); @@ -223,6 +242,7 @@ extern boolean _bfd_archive_coff_construct_extended_name_table #define _bfd_archive_coff_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_coff_openr_next_archived_file \ bfd_generic_openr_next_archived_file +#define _bfd_archive_coff_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_coff_generic_stat_arch_elt \ bfd_generic_stat_arch_elt #define _bfd_archive_coff_update_armap_timestamp bfd_true @@ -401,6 +421,9 @@ extern bfd_reloc_status_type _bfd_relocate_contents /* Create a string table. */ extern struct bfd_strtab_hash *_bfd_stringtab_init PARAMS ((void)); +/* Create an XCOFF .debug section style string table. */ +extern struct bfd_strtab_hash *_bfd_xcoff_stringtab_init PARAMS ((void)); + /* Free a string table. */ extern void _bfd_stringtab_free PARAMS ((struct bfd_strtab_hash *)); diff --git a/bfd/libecoff.h b/bfd/libecoff.h index e8af957d03f..939e8134341 100644 --- a/bfd/libecoff.h +++ b/bfd/libecoff.h @@ -71,6 +71,9 @@ struct ecoff_backend_data /* Do final adjustments to filehdr and aouthdr. */ boolean (*adjust_headers) PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *)); + /* Read an element from an archive at a given file position. This + is needed because OSF/1 3.2 uses a weird archive format. */ + bfd *(*get_elt_at_filepos) PARAMS ((bfd *, file_ptr)); }; /* This is the target specific information kept for ECOFF files. */ @@ -127,6 +130,10 @@ typedef struct ecoff_tdata /* True if this BFD was written by the backend linker. */ boolean linker; + /* True if a warning that multiple global pointer values are + needed in the output binary was issued already. */ + boolean issued_multiple_gp_warning; + /* Used by find_nearest_line entry point. The structure could be included directly in this one, but there's no point to wasting the memory just for the infrequently called find_nearest_line. */ @@ -197,6 +204,14 @@ struct ecoff_section_tdata section, and the entry for any reloc that is not PC relative is zero. */ long *offsets; + + /* When producing an executable (i.e., final, non-relocatable link) + on the Alpha, we may need to use multiple global pointer values + to span the entire .lita section. In essence, we allow each + input .lita section to have its own gp value. To support this, + we need to keep track of the gp values that we picked for each + input .lita section . */ + bfd_vma gp; }; /* An accessor macro for the ecoff_section_tdata structure. */ @@ -269,8 +284,10 @@ extern boolean _bfd_ecoff_slurp_armap PARAMS ((bfd *abfd)); #define _bfd_ecoff_truncate_arname bfd_dont_truncate_arname extern boolean _bfd_ecoff_write_armap PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); +#define _bfd_ecoff_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_ecoff_openr_next_archived_file \ bfd_generic_openr_next_archived_file +#define _bfd_ecoff_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt #define _bfd_ecoff_update_armap_timestamp bfd_true diff --git a/bfd/oasys.c b/bfd/oasys.c index 71dee970abe..b72b5ef3c9c 100644 --- a/bfd/oasys.c +++ b/bfd/oasys.c @@ -1455,6 +1455,7 @@ oasys_sizeof_headers (abfd, exec) PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \ bfd_true) #define oasys_read_ar_hdr bfd_nullvoidptr +#define oasys_get_elt_at_index _bfd_generic_get_elt_at_index #define oasys_update_armap_timestamp bfd_true #define oasys_bfd_is_local_label bfd_generic_is_local_label @@ -1483,8 +1484,8 @@ const bfd_target oasys_vec = { "oasys", /* name */ bfd_target_oasys_flavour, - true, /* target byte order */ - true, /* target headers byte order */ + BFD_ENDIAN_BIG, /* target byte order */ + BFD_ENDIAN_BIG, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), diff --git a/bfd/opncls.c b/bfd/opncls.c index bfb341527c1..6117d875cd7 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -40,6 +40,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define obstack_chunk_alloc malloc #define obstack_chunk_free free +#ifndef HAVE_GETPAGESIZE +#define getpagesize() 2048 +#endif + +long _bfd_chunksize = -1; + /* Return a new BFD. All BFD's are allocated through this routine. */ bfd * @@ -49,12 +55,20 @@ _bfd_new_bfd () nbfd = (bfd *)bfd_zmalloc (sizeof (bfd)); if (!nbfd) + return 0; + + if (_bfd_chunksize <= 0) { - bfd_set_error (bfd_error_no_memory); - return 0; + _bfd_chunksize = getpagesize (); + if (_bfd_chunksize <= 0) + _bfd_chunksize = 2048; + /* Leave some slush space, since many malloc implementations + prepend a header, and may wind up wasting another page + because of it. */ + _bfd_chunksize -= 32; } - if (!obstack_begin(&nbfd->memory, 128)) + if (!obstack_begin(&nbfd->memory, _bfd_chunksize)) { bfd_set_error (bfd_error_no_memory); return 0; @@ -129,10 +143,8 @@ bfd_openr (filename, target) const bfd_target *target_vec; nbfd = _bfd_new_bfd(); - if (nbfd == NULL) { - bfd_set_error (bfd_error_no_memory); + if (nbfd == NULL) return NULL; - } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { @@ -197,7 +209,6 @@ bfd_fdopenr (filename, target, fd) int fdflags; bfd_set_error (bfd_error_system_call); - #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL) fdflags = O_RDWR; /* Assume full access */ #else @@ -207,24 +218,22 @@ bfd_fdopenr (filename, target, fd) nbfd = _bfd_new_bfd(); - if (nbfd == NULL) { - bfd_set_error (bfd_error_no_memory); + if (nbfd == NULL) return NULL; - } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { bfd_set_error (bfd_error_invalid_target); return NULL; } -#if defined(VMS) || defined(__GO32__) || defined (WIN32) - nbfd->iostream = (char *)fopen(filename, FOPEN_RB); +#if defined(VMS) || defined(__GO32__) || defined (WINGDB) + nbfd->iostream = (PTR)fopen(filename, FOPEN_RB); #else /* (O_ACCMODE) parens are to avoid Ultrix header file bug */ switch (fdflags & (O_ACCMODE)) { - case O_RDONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RB); break; - case O_WRONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB); break; - case O_RDWR: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB); break; + case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break; + case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; + case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; default: abort (); } #endif @@ -278,10 +287,7 @@ bfd_openstreamr (filename, target, stream) nbfd = _bfd_new_bfd (); if (nbfd == NULL) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } + return NULL; target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) @@ -290,7 +296,7 @@ bfd_openstreamr (filename, target, stream) return NULL; } - nbfd->iostream = (char *) stream; + nbfd->iostream = (PTR) stream; nbfd->filename = filename; nbfd->direction = read_direction; @@ -334,10 +340,8 @@ bfd_openw (filename, target) reclaim it correctly. */ nbfd = _bfd_new_bfd(); - if (nbfd == NULL) { - bfd_set_error (bfd_error_no_memory); + if (nbfd == NULL) return NULL; - } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) return NULL; @@ -521,10 +525,8 @@ bfd_create (filename, templ) bfd *templ; { bfd *nbfd = _bfd_new_bfd(); - if (nbfd == (bfd *)NULL) { - bfd_set_error (bfd_error_no_memory); + if (nbfd == (bfd *)NULL) return (bfd *)NULL; - } nbfd->filename = filename; if(templ) { nbfd->xvec = templ->xvec; @@ -552,7 +554,12 @@ bfd_alloc_by_size_t (abfd, size) bfd *abfd; size_t size; { - return obstack_alloc(&(abfd->memory), size); + PTR ret; + + ret = obstack_alloc (&(abfd->memory), size); + if (ret == NULL) + bfd_set_error (bfd_error_no_memory); + return ret; } void @@ -568,7 +575,12 @@ PTR bfd_alloc_finish (abfd) bfd *abfd; { - return obstack_finish(&(abfd->memory)); + PTR ret; + + ret = obstack_finish (&(abfd->memory)); + if (ret == NULL) + bfd_set_error (bfd_error_no_memory); + return ret; } PTR diff --git a/bfd/riscix.c b/bfd/riscix.c index 84898594ae4..192ebff9a14 100644 --- a/bfd/riscix.c +++ b/bfd/riscix.c @@ -349,7 +349,7 @@ riscix_swap_std_reloc_out (abfd, g, natptr) } /* now the fun stuff */ - if (abfd->xvec->header_byteorder_big_p != false) + if (bfd_header_big_endian (abfd)) { natptr->r_index[0] = r_index >> 16; natptr->r_index[1] = r_index >> 8; @@ -580,7 +580,8 @@ riscix_some_aout_object_p (abfd, execp, callback_to_real_object_p) */ { struct stat stat_buf; - if (abfd->iostream + if (abfd->iostream != NULL + && (abfd->flags & BFD_IN_MEMORY) == 0 && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) && ((stat_buf.st_mode & 0111) != 0)) abfd->flags |= EXEC_P; diff --git a/bfd/som.c b/bfd/som.c index 3cc39799dd6..59d07fcc00e 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -5846,6 +5846,7 @@ som_bfd_link_split_section (abfd, sec) #define som_read_ar_hdr _bfd_generic_read_ar_hdr #define som_openr_next_archived_file bfd_generic_openr_next_archived_file +#define som_get_elt_at_index _bfd_generic_get_elt_at_index #define som_generic_stat_arch_elt bfd_generic_stat_arch_elt #define som_truncate_arname bfd_bsd_truncate_arname #define som_slurp_extended_name_table _bfd_slurp_extended_name_table @@ -5871,8 +5872,8 @@ const bfd_target som_vec = { "som", /* name */ bfd_target_som_flavour, - true, /* target byte order */ - true, /* target headers byte order */ + BFD_ENDIAN_BIG, /* target byte order */ + BFD_ENDIAN_BIG, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC), diff --git a/bfd/targets.c b/bfd/targets.c index 32f27f3420a..24a09631628 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -311,6 +311,7 @@ The general target vector. .CAT(NAME,_write_armap),\ .CAT(NAME,_read_ar_hdr),\ .CAT(NAME,_openr_next_archived_file),\ +.CAT(NAME,_get_elt_at_index),\ .CAT(NAME,_generic_stat_arch_elt),\ .CAT(NAME,_update_armap_timestamp) . boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); @@ -325,6 +326,8 @@ The general target vector. . int stridx)); . PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *)); . bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); +.#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i)) +. bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex)); . int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); . boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *)); .