-#include "seclet.h"
-#include "aout/ar.h"
-#include "aout/ranlib.h"
-#include "coff/mips.h"
-#include "coff/internal.h"
-#include "coff/sym.h"
-#include "coff/symconst.h"
-#include "coff/ecoff-ext.h"
-#include "libcoff.h"
-#include "libecoff.h"
-
-/* Each canonical asymbol really looks like this. */
-
-typedef struct ecoff_symbol_struct
-{
- /* The actual symbol which the rest of BFD works with */
- asymbol symbol;
-
- /* The fdr for this symbol. */
- FDR *fdr;
-
- /* true if this is a local symbol rather than an external one. */
- boolean local;
-
- /* A pointer to the unswapped hidden information for this symbol */
- union
- {
- struct sym_ext *lnative;
- struct ext_ext *enative;
- }
- native;
-} ecoff_symbol_type;
-
-/* We take the address of the first element of a asymbol to ensure that the
- macro is only ever applied to an asymbol. */
-#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
-
-/* This is a hack borrowed from coffcode.h; we need to save the index
- of a symbol when we write it out so that can set the symbol index
- correctly when we write out the relocs. */
-#define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata)
-#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx))
-
-/* The page boundary used to align sections in the executable file. */
-#define PAGE_SIZE 0x2000
-
-/* The linker needs a section to hold small common variables while
- linking. There is no convenient way to create it when the linker
- needs it, so we always create one for each BFD. We then avoid
- writing it out. */
-#define SCOMMON ".scommon"
-
-/* MIPS ECOFF has COFF sections, but the debugging information is
- stored in a completely different format. This files uses the some
- of the swapping routines from coffswap.h, and some of the generic
- COFF routines in coffgen.c, but, unlike the real COFF targets, does
- not use coffcode.h itself. */
-\f
-/* Prototypes for static functions. */
-
-static boolean ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
-static asection *ecoff_make_section_hook PARAMS ((bfd *abfd, char *name));
-static boolean ecoff_new_section_hook PARAMS ((bfd *abfd, asection *section));
-static boolean ecoff_mkobject PARAMS ((bfd *abfd));
-static PTR ecoff_mkobject_hook PARAMS ((bfd *abfd, PTR filehdr, PTR aouthdr));
-static boolean ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr));
-static long ecoff_sec_to_styp_flags PARAMS ((CONST char *name,
- flagword flags));
-static flagword ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr));
-static asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd));
-static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
- asymbol *asym, int ext));
-static boolean ecoff_slurp_symbol_table PARAMS ((bfd *abfd));
-static unsigned int ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd));
-static unsigned int ecoff_get_symtab PARAMS ((bfd *abfd,
- asymbol **alocation));
-static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
- RNDXR *rndx, long isym,
- CONST char *which));
-static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr,
- int indx, int bigendian));
-static void ecoff_print_symbol PARAMS ((bfd *abfd, PTR filep,
- asymbol *symbol,
- bfd_print_symbol_type how));
-static void ecoff_swap_reloc_in PARAMS ((bfd *abfd, RELOC *ext,
- struct internal_reloc *intern));
-static unsigned int ecoff_swap_reloc_out PARAMS ((bfd *abfd, PTR src,
- PTR dst));
-static bfd_reloc_status_type ecoff_generic_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd));
-static bfd_reloc_status_type ecoff_refhi_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd));
-static bfd_reloc_status_type ecoff_gprel_reloc PARAMS ((bfd *abfd,
- arelent *reloc,
- asymbol *symbol,
- PTR data,
- asection *section,
- bfd *output_bfd));
-static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
- asymbol **symbols));
-static unsigned int ecoff_canonicalize_reloc PARAMS ((bfd *abfd,
- asection *section,
- arelent **relptr,
- asymbol **symbols));
-static boolean ecoff_find_nearest_line PARAMS ((bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- CONST char **filename_ptr,
- CONST char **fnname_ptr,
- unsigned int *retline_ptr));
-static void ecoff_clear_output_flags PARAMS ((bfd *abfd));
-static boolean ecoff_rel PARAMS ((bfd *output_bfd, bfd_seclet_type *seclet,
- asection *output_section, PTR data,
- boolean relocateable));
-static boolean ecoff_dump_seclet PARAMS ((bfd *abfd, bfd_seclet_type *seclet,
- asection *section, PTR data,
- boolean relocateable));
-static long ecoff_add_string PARAMS ((bfd *output_bfd, FDR *fdr,
- CONST char *string, boolean external));
-static boolean ecoff_get_debug PARAMS ((bfd *output_bfd,
- bfd_seclet_type *seclet,
- asection *section,
- boolean relocateable));
-static boolean ecoff_bfd_seclet_link PARAMS ((bfd *abfd, PTR data,
- boolean relocateable));
-static boolean ecoff_set_arch_mach PARAMS ((bfd *abfd,
- enum bfd_architecture arch,
- unsigned long machine));
-static int ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc));
-static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
-static boolean ecoff_set_section_contents PARAMS ((bfd *abfd,
- asection *section,
- PTR location,
- file_ptr offset,
- bfd_size_type count));
-static boolean ecoff_write_object_contents PARAMS ((bfd *abfd));
-static unsigned int ecoff_armap_hash PARAMS ((CONST char *s,
- unsigned int *rehash,
- unsigned int size,
- unsigned int hlog));
-static boolean ecoff_slurp_armap PARAMS ((bfd *abfd));
-static boolean ecoff_write_armap PARAMS ((bfd *abfd, unsigned int elength,
- struct orl *map,
- unsigned int orl_count,
- int stridx));
-static bfd_target *ecoff_archive_p PARAMS ((bfd *abfd));
-\f
-/* Get the generic COFF swapping routines, except for the reloc,
- symbol, and lineno ones. Give them ecoff names. */
-#define MIPSECOFF
-#define NO_COFF_RELOCS
-#define NO_COFF_SYMBOLS
-#define NO_COFF_LINENOS
-#define coff_swap_filehdr_in ecoff_swap_filehdr_in
-#define coff_swap_filehdr_out ecoff_swap_filehdr_out
-#define coff_swap_aouthdr_in ecoff_swap_aouthdr_in
-#define coff_swap_aouthdr_out ecoff_swap_aouthdr_out
-#define coff_swap_scnhdr_in ecoff_swap_scnhdr_in
-#define coff_swap_scnhdr_out ecoff_swap_scnhdr_out
-#include "coffswap.h"
-\f
-/* This stuff is somewhat copied from coffcode.h. */
-
-static asection bfd_debug_section = { "*DEBUG*" };
-
-/* See whether the magic number matches. */
-
-static boolean
-ecoff_bad_format_hook (abfd, filehdr)
- bfd *abfd;
- PTR filehdr;
-{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
-
- if (ECOFFBADMAG (*internal_f))
- return false;
-
- return true;
-}
-
-/* This is a hook needed by SCO COFF, but we have nothing to do. */
-
-static asection *
-ecoff_make_section_hook (abfd, name)
- bfd *abfd;
- char *name;
-{
- return (asection *) NULL;
-}
-
-/* Initialize a new section. */
-
-static boolean
-ecoff_new_section_hook (abfd, section)
- bfd *abfd;
- asection *section;
-{
- section->alignment_power = abfd->xvec->align_power_min;
-
- if (strcmp (section->name, _TEXT) == 0)
- section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
- else if (strcmp (section->name, _DATA) == 0
- || strcmp (section->name, _SDATA) == 0)
- section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
- else if (strcmp (section->name, _RDATA) == 0
- || strcmp (section->name, _LIT8) == 0
- || strcmp (section->name, _LIT4) == 0)
- section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
- else if (strcmp (section->name, _BSS) == 0
- || strcmp (section->name, _SBSS) == 0)
- section->flags |= SEC_ALLOC;
-
- /* Probably any other section name is SEC_NEVER_LOAD, but I'm
- uncertain about .init on some systems and I don't know how shared
- libraries work. */
-
- return true;
-}
-
-/* Set the alignment of a section; we have nothing to do. */
-
-#define ecoff_set_alignment_hook \
- ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
-
-/* Create an ECOFF object. */
-
-static boolean
-ecoff_mkobject (abfd)
- bfd *abfd;
-{
- abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
- bfd_zalloc (abfd, sizeof(ecoff_data_type)));
- if (abfd->tdata.ecoff_obj_data == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
-
- /* Always create a .scommon section for every BFD. This is a hack so
- that the linker has something to attach scSCommon symbols to. */
- bfd_make_section (abfd, SCOMMON);
-
- return true;
-}
-
-/* Create the ECOFF backend specific information. */
-
-static PTR
-ecoff_mkobject_hook (abfd, filehdr, aouthdr)
- bfd *abfd;
- PTR filehdr;
- PTR aouthdr;
-{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
- struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
- ecoff_data_type *ecoff;
-
- if (ecoff_mkobject (abfd) == false)
- return NULL;
-
- ecoff = ecoff_data (abfd);
- ecoff->sym_filepos = internal_f->f_symptr;
-
- if (internal_a != (struct internal_aouthdr *) NULL)
- {
- int i;
-
- ecoff->text_start = internal_a->text_start;
- ecoff->text_end = internal_a->text_start + internal_a->tsize;
- ecoff->gp = internal_a->gp_value;
- ecoff->gprmask = internal_a->gprmask;
- for (i = 0; i < 4; i++)
- ecoff->cprmask[i] = internal_a->cprmask[i];
- }
-
- return (PTR) ecoff;
-}
-
-/* Determine the machine architecture and type. */
-
-static boolean
-ecoff_set_arch_mach_hook (abfd, filehdr)
- bfd *abfd;
- PTR filehdr;
-{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
- enum bfd_architecture arch;
-
- switch (internal_f->f_magic)
- {
- case MIPS_MAGIC_1:
- case MIPS_MAGIC_LITTLE:
- case MIPS_MAGIC_BIG:
- arch = bfd_arch_mips;
- break;
-
- default:
- arch = bfd_arch_obscure;
- break;
- }
-
- bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
-
- return true;
-}
-
-/* Get the section s_flags to use for a section. */
-
-static long
-ecoff_sec_to_styp_flags (name, flags)
- CONST char *name;
- flagword flags;
-{
- long styp;
-
- styp = 0;
-
- if (strcmp (name, _TEXT) == 0)
- styp = STYP_TEXT;
- else if (strcmp (name, _DATA) == 0)
- styp = STYP_DATA;
- else if (strcmp (name, _SDATA) == 0)
- styp = STYP_SDATA;
- else if (strcmp (name, _RDATA) == 0)
- styp = STYP_RDATA;
- else if (strcmp (name, _LIT8) == 0)
- styp = STYP_LIT8;
- else if (strcmp (name, _LIT4) == 0)
- styp = STYP_LIT4;
- else if (strcmp (name, _BSS) == 0)
- styp = STYP_BSS;
- else if (strcmp (name, _SBSS) == 0)
- styp = STYP_SBSS;
- else if (flags & SEC_CODE)
- styp = STYP_TEXT;
- else if (flags & SEC_DATA)
- styp = STYP_DATA;
- else if (flags & SEC_READONLY)
- styp = STYP_RDATA;
- else if (flags & SEC_LOAD)
- styp = STYP_TEXT;
- else
- styp = STYP_BSS;
-
- if (flags & SEC_NEVER_LOAD)
- styp |= STYP_NOLOAD;
-
- return styp;
-}
-
-/* Get the BFD flags to use for a section. */
-
-static flagword
-ecoff_styp_to_sec_flags (abfd, hdr)
- bfd *abfd;
- PTR hdr;
-{
- struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
- long styp_flags = internal_s->s_flags;
- flagword sec_flags=0;
-
- if (styp_flags & STYP_NOLOAD)
- sec_flags |= SEC_NEVER_LOAD;
-
- /* For 386 COFF, at least, an unloadable text or data section is
- actually a shared library section. */
- if (styp_flags & STYP_TEXT)
- {
- if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
- else
- sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
- }
- else if ((styp_flags & STYP_DATA)
- || (styp_flags & STYP_RDATA)
- || (styp_flags & STYP_SDATA))
- {
- if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
- else
- sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
- if (styp_flags & STYP_RDATA)
- sec_flags |= SEC_READONLY;
- }
- else if ((styp_flags & STYP_BSS)
- || (styp_flags & STYP_SBSS))
- {
- sec_flags |= SEC_ALLOC;
- }
- else if (styp_flags & STYP_INFO)
- {
- sec_flags |= SEC_NEVER_LOAD;
- }
- else if ((styp_flags & STYP_LIT8)
- || (styp_flags & STYP_LIT4))
- {
- sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
- }
- else
- {
- sec_flags |= SEC_ALLOC | SEC_LOAD;
- }
-
- return sec_flags;
-}
-\f
-/* Read in and swap the important symbolic information for an ECOFF
- object file. FIXME: This is called by gdb. If there is ever
- another ECOFF target, it should be moved into some sort of target
- specific structure. */
-
-boolean
-ecoff_slurp_symbolic_info (abfd)
- bfd *abfd;
-{
- struct hdr_ext external_symhdr;
- HDRR *internal_symhdr;
- bfd_size_type raw_base;
- bfd_size_type raw_size;
- PTR raw;
- struct fdr_ext *fraw_src;
- struct fdr_ext *fraw_end;
- struct fdr *fdr_ptr;
-
- /* Check whether we've already gotten it, and whether there's any to
- get. */
- if (ecoff_data (abfd)->raw_syments != (PTR) NULL)
- return true;
- if (ecoff_data (abfd)->sym_filepos == 0)
- {
- bfd_get_symcount (abfd) = 0;
- return true;
- }
-
- /* At this point bfd_get_symcount (abfd) holds the number of symbols
- as read from the file header, but on ECOFF this is always the
- size of the symbolic information header. It would be cleaner to
- handle this when we first read the file in coffgen.c. */
- if (bfd_get_symcount (abfd) != sizeof (external_symhdr))
- {
- bfd_error = bad_value;
- return false;
- }
-
- /* Read the symbolic information header. */
- if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1
- || (bfd_read ((PTR) &external_symhdr, sizeof (external_symhdr), 1, abfd)
- != sizeof (external_symhdr)))
- {
- bfd_error = system_call_error;
- return false;
- }
- internal_symhdr = &ecoff_data (abfd)->symbolic_header;
- ecoff_swap_hdr_in (abfd, &external_symhdr, internal_symhdr);
-
- if (internal_symhdr->magic != magicSym)
- {
- bfd_error = bad_value;
- return false;
- }
-
- /* Now we can get the correct number of symbols. */
- bfd_get_symcount (abfd) = (internal_symhdr->isymMax
- + internal_symhdr->iextMax);
-
- /* Read all the symbolic information at once. */
- raw_base = ecoff_data (abfd)->sym_filepos + sizeof (struct hdr_ext);
-
- if (internal_symhdr->cbExtOffset != 0)
- raw_size = (internal_symhdr->cbExtOffset
- - raw_base
- + internal_symhdr->iextMax * sizeof (struct ext_ext));
- else
- {
- long cbline, issmax, issextmax;
-
- cbline = (internal_symhdr->cbLine + 3) &~ 3;
- issmax = (internal_symhdr->issMax + 3) &~ 3;
- issextmax = (internal_symhdr->issExtMax + 3) &~ 3;
- raw_size = (cbline * sizeof (unsigned char)
- + internal_symhdr->idnMax * sizeof (struct dnr_ext)
- + internal_symhdr->ipdMax * sizeof (struct pdr_ext)
- + internal_symhdr->isymMax * sizeof (struct sym_ext)
- + internal_symhdr->ioptMax * sizeof (struct opt_ext)
- + internal_symhdr->iauxMax * sizeof (union aux_ext)
- + issmax * sizeof (char)
- + issextmax * sizeof (char)
- + internal_symhdr->ifdMax * sizeof (struct fdr_ext)
- + internal_symhdr->crfd * sizeof (struct rfd_ext)
- + internal_symhdr->iextMax * sizeof (struct ext_ext));
- }
-
- if (raw_size == 0)
- {
- ecoff_data (abfd)->sym_filepos = 0;
- return true;
- }
- raw = (PTR) bfd_alloc (abfd, raw_size);
- if (raw == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
- if (bfd_read (raw, raw_size, 1, abfd) != raw_size)
- {
- bfd_error = system_call_error;
- bfd_release (abfd, raw);
- return false;
- }
-
- ecoff_data (abfd)->raw_size = raw_size;
- ecoff_data (abfd)->raw_syments = raw;
-
- /* Get pointers for the numeric offsets in the HDRR structure. */
-#define FIX(off1, off2, type) \
- if (internal_symhdr->off1 == 0) \
- ecoff_data (abfd)->off2 = (type *) NULL; \
- else \
- ecoff_data (abfd)->off2 = (type *) ((char *) raw \
- + internal_symhdr->off1 \
- - raw_base)
- FIX (cbLineOffset, line, unsigned char);
- FIX (cbDnOffset, external_dnr, struct dnr_ext);
- FIX (cbPdOffset, external_pdr, struct pdr_ext);
- FIX (cbSymOffset, external_sym, struct sym_ext);
- FIX (cbOptOffset, external_opt, struct opt_ext);
- FIX (cbAuxOffset, external_aux, union aux_ext);
- FIX (cbSsOffset, ss, char);
- FIX (cbSsExtOffset, ssext, char);
- FIX (cbFdOffset, external_fdr, struct fdr_ext);
- FIX (cbRfdOffset, external_rfd, struct rfd_ext);
- FIX (cbExtOffset, external_ext, struct ext_ext);
-#undef FIX
-
- /* I don't want to always swap all the data, because it will just
- waste time and most programs will never look at it. The only
- time the linker needs most of the debugging information swapped
- is when linking big-endian and little-endian MIPS object files
- together, which is not a common occurrence.
-
- We need to look at the fdr to deal with a lot of information in
- the symbols, so we swap them here. */
- ecoff_data (abfd)->fdr = (struct fdr *) bfd_alloc (abfd,
- (internal_symhdr->ifdMax *
- sizeof (struct fdr)));
- if (ecoff_data (abfd)->fdr == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
- fdr_ptr = ecoff_data (abfd)->fdr;
- fraw_src = ecoff_data (abfd)->external_fdr;
- fraw_end = fraw_src + internal_symhdr->ifdMax;
- for (; fraw_src < fraw_end; fraw_src++, fdr_ptr++)
- ecoff_swap_fdr_in (abfd, fraw_src, fdr_ptr);
-
- return true;
-}
-\f
-/* ECOFF symbol table routines. The ECOFF symbol table is described
- in gcc/mips-tfile.c. */
-
-/* ECOFF uses two common sections. One is the usual one, and the
- other is for small objects. All the small objects are kept
- together, and then referenced via the gp pointer, which yields
- faster assembler code. This is what we use for the small common
- section. */
-static asection ecoff_scom_section;
-static asymbol ecoff_scom_symbol;
-static asymbol *ecoff_scom_symbol_ptr;
-
-/* Create an empty symbol. */
-
-static asymbol *
-ecoff_make_empty_symbol (abfd)
- bfd *abfd;
-{
- ecoff_symbol_type *new;
-
- new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));
- if (new == (ecoff_symbol_type *) NULL)
- {
- bfd_error = no_memory;
- return (asymbol *) NULL;
- }
- new->symbol.section = (asection *) NULL;
- new->fdr = (FDR *) NULL;
- new->local = false;
- new->native.lnative = (struct sym_ext *) NULL;
- new->symbol.the_bfd = abfd;
- return &new->symbol;
-}
-
-/* Set the BFD flags and section for an ECOFF symbol. */
-
-static void
-ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
- bfd *abfd;
- SYMR *ecoff_sym;
- asymbol *asym;
- int ext;
-{
- asym->the_bfd = abfd;
- asym->value = ecoff_sym->value;
- asym->section = &bfd_debug_section;
- asym->udata = NULL;
-
- /* Most symbol types are just for debugging. */
- switch (ecoff_sym->st)
- {
- case stGlobal:
- case stStatic:
- case stLabel:
- case stProc:
- case stStaticProc:
- case stNil:
- break;
- default:
- asym->flags = BSF_DEBUGGING;
- return;
- }
-
- if (ext)
- asym->flags = BSF_EXPORT | BSF_GLOBAL;
- else
- asym->flags = BSF_LOCAL;
- switch (ecoff_sym->sc)
- {
- case scNil:
- /* Used for compiler generated labels. Leave them in the
- debugging section, and mark them as local. If BSF_DEBUGGING
- is set, then nm does not display them for some reason. If no
- flags are set then the linker whines about them. */
- asym->flags = BSF_LOCAL;
- break;
- case scText:
- asym->section = bfd_make_section_old_way (abfd, ".text");
- asym->value -= asym->section->vma;
- break;
- case scData:
- asym->section = bfd_make_section_old_way (abfd, ".data");
- asym->value -= asym->section->vma;
- break;
- case scBss:
- if (ext)
- {
- asym->section = &bfd_com_section;
- asym->flags = 0;
- }
- else
- {
- asym->section = bfd_make_section_old_way (abfd, ".bss");
- asym->value -= asym->section->vma;
- }
- break;
- case scRegister:
- asym->flags = BSF_DEBUGGING;
- break;
- case scAbs:
- asym->section = &bfd_abs_section;
- break;
- case scUndefined:
- asym->section = &bfd_und_section;
- asym->flags = 0;
- asym->value = 0;
- break;
- case scCdbLocal:
- case scBits:
- case scCdbSystem:
- case scRegImage:
- case scInfo:
- case scUserStruct:
- asym->flags = BSF_DEBUGGING;
- break;
- case scSData:
- asym->section = bfd_make_section_old_way (abfd, ".sdata");
- asym->value -= asym->section->vma;
- break;
- case scSBss:
- asym->section = bfd_make_section_old_way (abfd, ".sbss");
- if (! ext)
- asym->value -= asym->section->vma;
- break;
- case scRData:
- asym->section = bfd_make_section_old_way (abfd, ".rdata");
- asym->value -= asym->section->vma;
- break;
- case scVar:
- asym->flags = BSF_DEBUGGING;
- break;
- case scCommon:
- /* FIXME: We should take a -G argument, which gives the maximum
- size of objects to be put in the small common section. Until
- we do, we put objects of sizes up to 8 in the small common
- section. The assembler should do this for us, but the native
- assembler seems to get confused. */
- if (asym->value > 8)
- {
- asym->section = &bfd_com_section;
- break;
- }
- /* Fall through. */
- case scSCommon:
- if (ecoff_scom_section.name == NULL)
- {
- /* Initialize the small common section. */
- ecoff_scom_section.name = SCOMMON;
- ecoff_scom_section.flags = SEC_IS_COMMON;
- ecoff_scom_section.output_section = &ecoff_scom_section;
- ecoff_scom_section.symbol = &ecoff_scom_symbol;
- ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
- ecoff_scom_symbol.name = SCOMMON;
- ecoff_scom_symbol.flags = BSF_SECTION_SYM;
- ecoff_scom_symbol.section = &ecoff_scom_section;
- ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
- }
- asym->section = &ecoff_scom_section;
- asym->flags = 0;
- break;
- case scVarRegister:
- case scVariant:
- asym->flags = BSF_DEBUGGING;
- break;
- case scSUndefined:
- asym->section = &bfd_und_section;
- asym->flags = 0;
- asym->value = 0;
- break;
- case scInit:
- asym->section = bfd_make_section_old_way (abfd, ".init");
- asym->value -= asym->section->vma;
- break;
- case scBasedVar:
- case scXData:
- case scPData:
- asym->flags = BSF_DEBUGGING;
- break;
- case scFini:
- asym->section = bfd_make_section_old_way (abfd, ".fini");
- asym->value -= asym->section->vma;
- break;
- default:
- break;
- }
-}
-
-/* Read an ECOFF symbol table. */
-
-static boolean
-ecoff_slurp_symbol_table (abfd)
- bfd *abfd;
-{
- bfd_size_type internal_size;
- ecoff_symbol_type *internal;
- ecoff_symbol_type *internal_ptr;
- struct ext_ext *eraw_src;
- struct ext_ext *eraw_end;
- FDR *fdr_ptr;
- FDR *fdr_end;
-
- /* If we've already read in the symbol table, do nothing. */
- if (ecoff_data (abfd)->canonical_symbols != NULL)
- return true;
-
- /* Get the symbolic information. */
- if (ecoff_slurp_symbolic_info (abfd) == false)
- return false;
- if (bfd_get_symcount (abfd) == 0)
- return true;
-
- internal_size = bfd_get_symcount (abfd) * sizeof (ecoff_symbol_type);
- internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
- if (internal == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
-
- internal_ptr = internal;
- eraw_src = ecoff_data (abfd)->external_ext;
- eraw_end = eraw_src + ecoff_data (abfd)->symbolic_header.iextMax;
- for (; eraw_src < eraw_end; eraw_src++, internal_ptr++)
- {
- EXTR internal_esym;
-
- ecoff_swap_ext_in (abfd, eraw_src, &internal_esym);
- internal_ptr->symbol.name = (ecoff_data (abfd)->ssext
- + internal_esym.asym.iss);
- ecoff_set_symbol_info (abfd, &internal_esym.asym,
- &internal_ptr->symbol, 1);
- internal_ptr->fdr = ecoff_data (abfd)->fdr + internal_esym.ifd;
- internal_ptr->local = false;
- internal_ptr->native.enative = eraw_src;
- }
-
- /* The local symbols must be accessed via the fdr's, because the
- string and aux indices are relative to the fdr information. */
- fdr_ptr = ecoff_data (abfd)->fdr;
- fdr_end = fdr_ptr + ecoff_data (abfd)->symbolic_header.ifdMax;
- for (; fdr_ptr < fdr_end; fdr_ptr++)
- {
- struct sym_ext *lraw_src;
- struct sym_ext *lraw_end;
-
- lraw_src = ecoff_data (abfd)->external_sym + fdr_ptr->isymBase;
- lraw_end = lraw_src + fdr_ptr->csym;
- for (; lraw_src < lraw_end; lraw_src++, internal_ptr++)
- {
- SYMR internal_sym;
-
- ecoff_swap_sym_in (abfd, lraw_src, &internal_sym);
- internal_ptr->symbol.name = (ecoff_data (abfd)->ss
- + fdr_ptr->issBase
- + internal_sym.iss);
- ecoff_set_symbol_info (abfd, &internal_sym,
- &internal_ptr->symbol, 0);
- internal_ptr->fdr = fdr_ptr;
- internal_ptr->local = true;
- internal_ptr->native.lnative = lraw_src;
- }
- }
-
- ecoff_data (abfd)->canonical_symbols = internal;
-
- return true;
-}
-
-static unsigned int
-ecoff_get_symtab_upper_bound (abfd)
- bfd *abfd;
-{
- if (ecoff_slurp_symbolic_info (abfd) == false
- || bfd_get_symcount (abfd) == 0)
- return 0;
-
- return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
-}
-
-static unsigned int
-ecoff_get_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
-{
- unsigned int counter = 0;
- ecoff_symbol_type *symbase;
- ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
-
- if (ecoff_slurp_symbol_table (abfd) == false
- || bfd_get_symcount (abfd) == 0)
- return 0;
-
- symbase = ecoff_data (abfd)->canonical_symbols;
- while (counter < bfd_get_symcount (abfd))
- {
- *(location++) = symbase++;
- counter++;
- }
- *location++ = (ecoff_symbol_type *) NULL;
- return bfd_get_symcount (abfd);
-}
-
-/* Turn ECOFF type information into a printable string.
- ecoff_emit_aggregate and ecoff_type_to_string are from
- gcc/mips-tdump.c, with swapping added and used_ptr removed. */
-
-/* Write aggregate information to a string. */
-
-static void
-ecoff_emit_aggregate (abfd, string, rndx, isym, which)
- bfd *abfd;
- char *string;
- RNDXR *rndx;
- long isym;
- CONST char *which;
-{
- int ifd = rndx->rfd;
- int indx = rndx->index;
- int sym_base, ss_base;
- CONST char *name;
-
- if (ifd == 0xfff)
- ifd = isym;
-
- sym_base = ecoff_data (abfd)->fdr[ifd].isymBase;
- ss_base = ecoff_data (abfd)->fdr[ifd].issBase;
-
- if (indx == indexNil)
- name = "/* no name */";
- else
- {
- SYMR sym;
-
- indx += sym_base;
- ecoff_swap_sym_in (abfd,
- ecoff_data (abfd)->external_sym + indx,
- &sym);
- name = ecoff_data (abfd)->ss + ss_base + sym.iss;
- }
-
- sprintf (string,
- "%s %s { ifd = %d, index = %d }",
- which, name, ifd,
- indx + ecoff_data (abfd)->symbolic_header.iextMax);
-}
-
-/* Convert the type information to string format. */
-
-static char *
-ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
- bfd *abfd;
- union aux_ext *aux_ptr;
- int indx;
- int bigendian;
-{
- AUXU u;
- struct qual {
- unsigned int type;
- int low_bound;
- int high_bound;
- int stride;
- } qualifiers[7];
-
- unsigned int basic_type;
- int i;
- static char buffer1[1024];
- static char buffer2[1024];
- char *p1 = buffer1;
- char *p2 = buffer2;
- RNDXR rndx;
-
- for (i = 0; i < 7; i++)
- {
- qualifiers[i].low_bound = 0;
- qualifiers[i].high_bound = 0;
- qualifiers[i].stride = 0;
- }
-
- if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1)
- return "-1 (no type)";
- ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
-
- basic_type = u.ti.bt;
- qualifiers[0].type = u.ti.tq0;
- qualifiers[1].type = u.ti.tq1;
- qualifiers[2].type = u.ti.tq2;
- qualifiers[3].type = u.ti.tq3;
- qualifiers[4].type = u.ti.tq4;
- qualifiers[5].type = u.ti.tq5;
- qualifiers[6].type = tqNil;
-
- /*
- * Go get the basic type.
- */
- switch (basic_type)
- {
- case btNil: /* undefined */
- strcpy (p1, "nil");
- break;
-
- case btAdr: /* address - integer same size as pointer */
- strcpy (p1, "address");
- break;
-
- case btChar: /* character */
- strcpy (p1, "char");
- break;
-
- case btUChar: /* unsigned character */
- strcpy (p1, "unsigned char");
- break;
-
- case btShort: /* short */
- strcpy (p1, "short");
- break;
-
- case btUShort: /* unsigned short */
- strcpy (p1, "unsigned short");
- break;
-
- case btInt: /* int */
- strcpy (p1, "int");
- break;
-
- case btUInt: /* unsigned int */
- strcpy (p1, "unsigned int");
- break;
-
- case btLong: /* long */
- strcpy (p1, "long");
- break;
-
- case btULong: /* unsigned long */
- strcpy (p1, "unsigned long");
- break;
-
- case btFloat: /* float (real) */
- strcpy (p1, "float");
- break;
-
- case btDouble: /* Double (real) */
- strcpy (p1, "double");
- break;
-
- /* Structures add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
-
- case btStruct: /* Structure (Record) */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "struct");
- indx++; /* skip aux words */
- break;
-
- /* Unions add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to union def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
-
- case btUnion: /* Union */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "union");
- indx++; /* skip aux words */
- break;
-
- /* Enumerations add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
-
- case btEnum: /* Enumeration */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "enum");
- indx++; /* skip aux words */
- break;
-
- case btTypedef: /* defined via a typedef, isymRef points */
- strcpy (p1, "typedef");
- break;
-
- case btRange: /* subrange of int */
- strcpy (p1, "subrange");
- break;
-
- case btSet: /* pascal sets */
- strcpy (p1, "set");
- break;
-
- case btComplex: /* fortran complex */
- strcpy (p1, "complex");
- break;
-
- case btDComplex: /* fortran double complex */
- strcpy (p1, "double complex");
- break;
-
- case btIndirect: /* forward or unnamed typedef */
- strcpy (p1, "forward/unamed typedef");
- break;
-
- case btFixedDec: /* Fixed Decimal */
- strcpy (p1, "fixed decimal");
- break;
-
- case btFloatDec: /* Float Decimal */
- strcpy (p1, "float decimal");
- break;
-
- case btString: /* Varying Length Character String */
- strcpy (p1, "string");
- break;
-
- case btBit: /* Aligned Bit String */
- strcpy (p1, "bit");
- break;
-
- case btPicture: /* Picture */
- strcpy (p1, "picture");
- break;