aboutsummaryrefslogtreecommitdiff
path: root/bfd/libecoff.h
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-03-25 22:37:55 +0000
committerIan Lance Taylor <ian@airs.com>1994-03-25 22:37:55 +0000
commita3a33af390c3a99e00b20847a102e307cfb538c7 (patch)
treeb262eb6f85a5b10fe60cdc47a0f753178e889283 /bfd/libecoff.h
parentf078dc7cf26a816ef0bb66be8b819ac549486e86 (diff)
downloadgdb-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.h211
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));