diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-03-25 22:37:55 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-03-25 22:37:55 +0000 |
commit | a3a33af390c3a99e00b20847a102e307cfb538c7 (patch) | |
tree | b262eb6f85a5b10fe60cdc47a0f753178e889283 /bfd/libecoff.h | |
parent | f078dc7cf26a816ef0bb66be8b819ac549486e86 (diff) | |
download | gdb-a3a33af390c3a99e00b20847a102e307cfb538c7.zip gdb-a3a33af390c3a99e00b20847a102e307cfb538c7.tar.gz gdb-a3a33af390c3a99e00b20847a102e307cfb538c7.tar.bz2 |
Changes to support linker relaxing of embedded MIPS PIC code to
use a five instruction sequence for funtion calls which are out of
range of the bal instruction.
* libecoff.h (struct ecoff_section_tdata): Define.
(ecoff_section_data): Define.
(ecoff_bfd_relax_section): Don't define.
* ecoff.c (ecoff_final_link_debug_accumulate): Don't read or free
the debugging information if it has already been read.
(ecoff_indirect_link_order): Handle _cooked_size being different
from _raw_size. Don't reread the contents or the relocs if they
have already been read in.
* coff-mips.c (mips_howto_table): Change bitsize of PCREL16 from
18 to 16.
(PCREL16_EXPANSION_ADJUSTMENT): Define.
(mips_relocate_refhi): Take adjust argument.
(mips_relocate_section): Handle reloc offsets stored in section
used_by_bfd field. Call mips_relax_pcrel16 to handle details of
expanding an out of range PCREL16. Keep trace of adjustments
required by expansions. Set s and unset h when converting a reloc
from undefined to section. Change handling of PC relative relocs:
if against a section, they are correct in the object file, if
against an external symbol they are pcrel_offset.
(mips_relax_section): New function.
(mips_relax_pcrel16): New function.
(ecoff_bfd_relax_section): Define.
* coff-alpha.c (ecoff_bfd_relax_section): Define.
* ecofflink.c (bfd_ecoff_debug_accumulate): Handle adjustments
built by mips_relax_section when writing out addresses.
* elf32-mips.c (mips_elf_read_ecoff_info): Clear adjust field.
Diffstat (limited to 'bfd/libecoff.h')
-rw-r--r-- | bfd/libecoff.h | 211 |
1 files changed, 130 insertions, 81 deletions
diff --git a/bfd/libecoff.h b/bfd/libecoff.h index 74361c5..f0f3a11 100644 --- a/bfd/libecoff.h +++ b/bfd/libecoff.h @@ -18,65 +18,56 @@ 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. */ +#include "bfdlink.h" + +#ifndef ECOFF_H +#include "coff/ecoff.h" +#endif + /* This is the backend information kept for ECOFF files. This - structure is constant for a particular backend. ECOFF already - keeps a bfd_coff_backend_data structure in the bfd_target - backend_data field, so a pointer to this backend structure is kept - in the tdata field. */ + structure is constant for a particular backend. The first element + is the COFF backend data structure, so that ECOFF targets can use + the generic COFF code. */ -#define ecoff_backend(abfd) (ecoff_data (abfd)->backend_data) +#define ecoff_backend(abfd) \ + ((struct ecoff_backend_data *) (abfd)->xvec->backend_data) struct ecoff_backend_data { + /* COFF backend information. This must be the first field. */ + bfd_coff_backend_data coff; /* Supported architecture. */ enum bfd_architecture arch; - /* Big endian magic number. */ - int big_magic; - /* Little endian magic number. */ - int little_magic; - /* Alignment of debugging information. E.g., 4. */ - bfd_size_type debug_align; + /* Initial portion of armap string. */ + const char *armap_start; /* The page boundary used to align sections in a demand-paged executable file. E.g., 0x1000. */ bfd_vma round; + /* True if the .rdata section is part of the text segment, as on the + Alpha. False if .rdata is part of the data segment, as on the + MIPS. */ + boolean rdata_in_text; /* Bitsize of constructor entries. */ unsigned int constructor_bitsize; - /* Sizes of external symbolic information. */ - bfd_size_type external_hdr_size; - bfd_size_type external_dnr_size; - bfd_size_type external_pdr_size; - bfd_size_type external_sym_size; - bfd_size_type external_opt_size; - bfd_size_type external_fdr_size; - bfd_size_type external_rfd_size; - bfd_size_type external_ext_size; - /* Functions to swap in external symbolic data. */ - void (*swap_hdr_in) PARAMS ((bfd *, PTR, HDRR *)); - void (*swap_dnr_in) PARAMS ((bfd *, PTR, DNR *)); - void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)); - void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)); - void (*swap_opt_in) PARAMS ((bfd *, PTR, OPTR *)); - void (*swap_fdr_in) PARAMS ((bfd *, PTR, FDR *)); - void (*swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)); - void (*swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)); - /* Functions to swap out external symbolic data. */ - void (*swap_hdr_out) PARAMS ((bfd *, const HDRR *, PTR)); - void (*swap_dnr_out) PARAMS ((bfd *, const DNR *, PTR)); - void (*swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR)); - void (*swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)); - void (*swap_opt_out) PARAMS ((bfd *, const OPTR *, PTR)); - void (*swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)); - void (*swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)); - void (*swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)); - /* It so happens that the auxiliary type information has the same - type and format for all known ECOFF targets. I don't see any - reason that that should change, so at least for now the auxiliary - swapping information is not in this table. */ + /* Reloc to use for constructor entries. */ + CONST struct reloc_howto_struct *constructor_reloc; + /* How to swap debugging information. */ + struct ecoff_debug_swap debug_swap; /* External reloc size. */ bfd_size_type external_reloc_size; /* Reloc swapping functions. */ void (*swap_reloc_in) PARAMS ((bfd *, PTR, struct internal_reloc *)); void (*swap_reloc_out) PARAMS ((bfd *, const struct internal_reloc *, PTR)); + /* Backend reloc tweaking. */ + void (*adjust_reloc_in) PARAMS ((bfd *, const struct internal_reloc *, + arelent *)); + void (*adjust_reloc_out) PARAMS ((bfd *, const arelent *, + struct internal_reloc *)); + /* Relocate section contents while linking. */ + boolean (*relocate_section) PARAMS ((bfd *output_bfd, struct bfd_link_info *, + bfd *input_bfd, asection *input_section, + bfd_byte *contents, + PTR external_relocs)); }; /* This is the target specific information kept for ECOFF files. */ @@ -85,9 +76,6 @@ struct ecoff_backend_data typedef struct ecoff_tdata { - /* Constant backend information. */ - const struct ecoff_backend_data *backend_data; - /* The reloc file position, set by ecoff_compute_section_file_positions. */ file_ptr reloc_filepos; @@ -109,42 +97,30 @@ typedef struct ecoff_tdata int gp_size; /* The register masks. When linking, all the masks found in the - input files are combined into the masks of the output file. */ + input files are combined into the masks of the output file. + These are not all used for all targets, but that's OK, because + the relevant ones are the only ones swapped in and out. */ unsigned long gprmask; + unsigned long fprmask; unsigned long cprmask[4]; - /* The size of the unswapped ECOFF symbolic information. */ - bfd_size_type raw_size; + /* The ECOFF symbolic debugging information. */ + struct ecoff_debug_info debug_info; /* The unswapped ECOFF symbolic information. */ PTR raw_syments; - /* The swapped ECOFF symbolic header. */ - HDRR symbolic_header; - - /* Pointers to the unswapped symbolic information. */ - unsigned char *line; - PTR external_dnr; /* struct dnr_ext */ - PTR external_pdr; /* struct pdr_ext */ - PTR external_sym; /* struct sym_ext */ - PTR external_opt; /* struct opt_ext */ - union aux_ext *external_aux; - char *ss; - char *ssext; - PTR external_fdr; /* struct fdr_ext */ - PTR external_rfd; /* struct rfd_ext */ - PTR external_ext; /* struct ext_ext */ - - /* The swapped FDR information. */ - FDR *fdr; - - /* The FDR index. This is set for an input BFD to a link so that - the external symbols can set their FDR index correctly. */ - unsigned int ifdbase; - /* The canonical BFD symbols. */ struct ecoff_symbol_struct *canonical_symbols; + /* A mapping from external symbol numbers to entries in the linker + hash table, used when linking. */ + struct ecoff_link_hash_entry **sym_hashes; + + /* A mapping from reloc symbol indices to sections, used when + linking. */ + asection **symndx_to_section; + } ecoff_data_type; /* Each canonical asymbol really looks like this. */ @@ -176,13 +152,71 @@ typedef struct ecoff_symbol_struct #define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata) #define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx)) -/* Make an empty ECOFF symbol. */ -extern asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd)); +/* When generating MIPS embedded PIC code, the linker relaxes the code + to turn PC relative branches into longer code sequences when the PC + relative branch is out of range. This involves reading the relocs + in bfd_relax_section as well as in bfd_final_link, and requires the + code to keep track of which relocs have been expanded. A pointer + to this structure is put in the used_by_bfd pointer of a section to + keep track of this information. The user_by_bfd pointer will be + NULL if the information was not needed. */ + +struct ecoff_section_tdata +{ + /* The unswapped relocs for this section. These are stored in + memory so the input file does not have to be read twice. */ + PTR external_relocs; + + /* The contents of the section. These bytes may or may not be saved + in memory, but if it is this is a pointer to them. */ + bfd_byte *contents; + + /* Offset adjustments for PC relative branches. A number other than + 1 is an addend for a PC relative branch; this addend arises because + it crosses one or more branches which were expanded into a larger + code sequence. A 1 means that this branch was itself expanded into + a larger code sequence. 1 is not a possible offset, since all + offsets must be multiples of the instruction size, which is 4; + also, the only relocs with non-zero offsets will be PC relative + branches within the same object file. If this field is NULL, no + branches were expanded and no offsets are required. Otherwise + there are as many entries as there are relocs in the section, and + the entry for any reloc that is not PC relative is zero. */ + long *offsets; +}; + +/* An accessor macro for the ecoff_section_tdata structure. */ +#define ecoff_section_data(abfd, sec) \ + ((struct ecoff_section_tdata *) (sec)->used_by_bfd) + +/* ECOFF linker hash table entries. */ + +struct ecoff_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Symbol index in output file. */ + long indx; + /* BFD that ext field value came from. */ + bfd *abfd; + /* ECOFF external symbol information. */ + EXTR esym; +}; + +/* ECOFF linker hash table. */ + +struct ecoff_link_hash_table +{ + struct bfd_link_hash_table root; +}; + +/* Make an ECOFF object. */ +extern boolean ecoff_mkobject PARAMS ((bfd *)); /* Read in the ECOFF symbolic debugging information. */ extern boolean ecoff_slurp_symbolic_info PARAMS ((bfd *)); /* Generic ECOFF BFD backend vectors. */ +extern asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd)); extern unsigned int ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd)); extern unsigned int ecoff_get_symtab PARAMS ((bfd *abfd, asymbol **alocation)); @@ -196,8 +230,6 @@ extern unsigned int ecoff_canonicalize_reloc PARAMS ((bfd *abfd, asection *section, arelent **relptr, asymbol **symbols)); -extern CONST struct reloc_howto_struct *ecoff_bfd_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); extern boolean ecoff_find_nearest_line PARAMS ((bfd *abfd, asection *section, asymbol **symbols, @@ -205,8 +237,6 @@ extern boolean ecoff_find_nearest_line PARAMS ((bfd *abfd, CONST char **filename_ptr, CONST char **fnname_ptr, unsigned int *retline_ptr)); -extern boolean ecoff_bfd_seclet_link PARAMS ((bfd *abfd, PTR data, - boolean relocateable)); extern boolean ecoff_set_arch_mach PARAMS ((bfd *abfd, enum bfd_architecture arch, unsigned long machine)); @@ -216,6 +246,11 @@ extern boolean ecoff_set_section_contents PARAMS ((bfd *abfd, PTR location, file_ptr offset, bfd_size_type count)); +extern boolean ecoff_get_section_contents PARAMS ((bfd *abfd, + asection *section, + PTR location, + file_ptr offset, + bfd_size_type count)); extern boolean ecoff_write_object_contents PARAMS ((bfd *abfd)); extern boolean ecoff_slurp_armap PARAMS ((bfd *abfd)); extern boolean ecoff_write_armap PARAMS ((bfd *abfd, unsigned int elength, @@ -229,20 +264,34 @@ extern bfd_target *ecoff_archive_p PARAMS ((bfd *abfd)); #define ecoff_truncate_arname bfd_dont_truncate_arname #define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file #define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt -#define ecoff_get_section_contents bfd_generic_get_section_contents #define ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound #define ecoff_close_and_cleanup bfd_generic_close_and_cleanup #define ecoff_bfd_debug_info_start bfd_void #define ecoff_bfd_debug_info_end bfd_void #define ecoff_bfd_debug_info_accumulate \ ((void (*) PARAMS ((bfd *, struct sec *))) bfd_void) -#define ecoff_bfd_get_relocated_section_contents \ - bfd_generic_get_relocated_section_contents -#define ecoff_bfd_relax_section bfd_generic_relax_section #define ecoff_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +extern struct bfd_link_hash_table *ecoff_bfd_link_hash_table_create + PARAMS ((bfd *)); +extern boolean ecoff_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean ecoff_bfd_final_link PARAMS ((bfd *, struct bfd_link_info *)); + +#ifndef ecoff_bfd_copy_private_section_data +#define ecoff_bfd_copy_private_section_data \ + ((boolean (*) PARAMS ((bfd *, asection *, bfd *, asection *))) bfd_true) +#endif +#ifndef ecoff_bfd_copy_private_bfd_data +#define ecoff_bfd_copy_private_bfd_data \ + ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true) +#endif +#ifndef ecoff_bfd_is_local_label +#define ecoff_bfd_is_local_label bfd_generic_is_local_label +#endif /* Hook functions for the generic COFF section reading code. */ +extern PTR ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); extern asection *ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); extern boolean ecoff_new_section_hook PARAMS ((bfd *abfd, asection *section)); |