|
|
|
@ -4,21 +4,21 @@ |
|
|
|
Original version by Per Bothner. |
|
|
|
Full support added by Ian Lance Taylor, ian@cygnus.com. |
|
|
|
|
|
|
|
This file is part of BFD, the Binary File Descriptor library. |
|
|
|
This file is part of BFD, the Binary File Descriptor library. |
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
|
|
|
it under the terms of the GNU General Public License as published by |
|
|
|
the Free Software Foundation; either version 2 of the License, or |
|
|
|
(at your option) any later version. |
|
|
|
This program is free software; you can redistribute it and/or modify |
|
|
|
it under the terms of the GNU General Public License as published by |
|
|
|
the Free Software Foundation; either version 2 of the License, or |
|
|
|
(at your option) any later version. |
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
GNU General Public License for more details. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
|
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
|
|
|
|
|
|
#include "bfd.h" |
|
|
|
#include "sysdep.h" |
|
|
|
@ -46,29 +46,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
|
|
|
|
|
|
/* Prototypes for static functions. */ |
|
|
|
|
|
|
|
static int ecoff_get_magic PARAMS ((bfd *abfd)); |
|
|
|
static long ecoff_sec_to_styp_flags PARAMS ((const char *name, |
|
|
|
flagword flags)); |
|
|
|
static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd)); |
|
|
|
static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym, |
|
|
|
asymbol *asym, int ext, int weak)); |
|
|
|
static void ecoff_emit_aggregate PARAMS ((bfd *abfd, FDR *fdr, |
|
|
|
char *string, |
|
|
|
RNDXR *rndx, long isym, |
|
|
|
const char *which)); |
|
|
|
static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr, |
|
|
|
unsigned int indx)); |
|
|
|
static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section, |
|
|
|
asymbol **symbols)); |
|
|
|
static int ecoff_get_magic PARAMS ((bfd *)); |
|
|
|
static long ecoff_sec_to_styp_flags PARAMS ((const char *, flagword)); |
|
|
|
static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *)); |
|
|
|
static boolean ecoff_set_symbol_info PARAMS ((bfd *, SYMR *, asymbol *, int, int)); |
|
|
|
static void ecoff_emit_aggregate PARAMS ((bfd *, FDR *, char *, RNDXR *, long, const char *)); |
|
|
|
static char *ecoff_type_to_string PARAMS ((bfd *, FDR *, unsigned int)); |
|
|
|
static boolean ecoff_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **)); |
|
|
|
static int ecoff_sort_hdrs PARAMS ((const PTR, const PTR)); |
|
|
|
static boolean ecoff_compute_section_file_positions PARAMS ((bfd *abfd)); |
|
|
|
static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *abfd)); |
|
|
|
static boolean ecoff_compute_section_file_positions PARAMS ((bfd *)); |
|
|
|
static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *)); |
|
|
|
static boolean ecoff_get_extr PARAMS ((asymbol *, EXTR *)); |
|
|
|
static void ecoff_set_index PARAMS ((asymbol *, bfd_size_type)); |
|
|
|
static unsigned int ecoff_armap_hash PARAMS ((const char *s, |
|
|
|
unsigned int *rehash, |
|
|
|
unsigned int size, |
|
|
|
unsigned int hlog)); |
|
|
|
static unsigned int ecoff_armap_hash PARAMS ((const char *, unsigned int *, unsigned int, unsigned int)); |
|
|
|
|
|
|
|
/* This stuff is somewhat copied from coffcode.h. */ |
|
|
|
|
|
|
|
@ -105,6 +95,7 @@ _bfd_ecoff_mkobject (abfd) |
|
|
|
bfd *abfd; |
|
|
|
{ |
|
|
|
bfd_size_type amt = sizeof (ecoff_data_type); |
|
|
|
|
|
|
|
abfd->tdata.ecoff_obj_data = (struct ecoff_tdata *) bfd_zalloc (abfd, amt); |
|
|
|
if (abfd->tdata.ecoff_obj_data == NULL) |
|
|
|
return false; |
|
|
|
@ -184,10 +175,8 @@ _bfd_ecoff_new_section_hook (abfd, section) |
|
|
|
|| strcmp (section->name, _SBSS) == 0) |
|
|
|
section->flags |= SEC_ALLOC; |
|
|
|
else if (strcmp (section->name, _LIB) == 0) |
|
|
|
{ |
|
|
|
/* An Irix 4 shared libary. */ |
|
|
|
section->flags |= SEC_COFF_SHARED_LIBRARY; |
|
|
|
} |
|
|
|
/* An Irix 4 shared libary. */ |
|
|
|
section->flags |= SEC_COFF_SHARED_LIBRARY; |
|
|
|
|
|
|
|
/* 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 |
|
|
|
@ -221,14 +210,14 @@ _bfd_ecoff_set_arch_mach_hook (abfd, filehdr) |
|
|
|
|
|
|
|
case MIPS_MAGIC_LITTLE2: |
|
|
|
case MIPS_MAGIC_BIG2: |
|
|
|
/* MIPS ISA level 2: the r6000 */ |
|
|
|
/* MIPS ISA level 2: the r6000. */ |
|
|
|
arch = bfd_arch_mips; |
|
|
|
mach = 6000; |
|
|
|
break; |
|
|
|
|
|
|
|
case MIPS_MAGIC_LITTLE3: |
|
|
|
case MIPS_MAGIC_BIG3: |
|
|
|
/* MIPS ISA level 3: the r4000 */ |
|
|
|
/* MIPS ISA level 3: the r4000. */ |
|
|
|
arch = bfd_arch_mips; |
|
|
|
mach = 4000; |
|
|
|
break; |
|
|
|
@ -553,7 +542,6 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) |
|
|
|
documented section. And the ordering of the sections varies between |
|
|
|
statically and dynamically linked executables. |
|
|
|
If bfd supports SEEK_END someday, this code could be simplified. */ |
|
|
|
|
|
|
|
raw_end = 0; |
|
|
|
|
|
|
|
#define UPDATE_RAW_END(start, count, size) \ |
|
|
|
@ -604,6 +592,7 @@ _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) |
|
|
|
debug->off2 = (type) ((char *) raw \ |
|
|
|
+ (internal_symhdr->off1 \ |
|
|
|
- raw_base)) |
|
|
|
|
|
|
|
FIX (cbLineOffset, line, unsigned char *); |
|
|
|
FIX (cbDnOffset, external_dnr, PTR); |
|
|
|
FIX (cbPdOffset, external_pdr, PTR); |
|
|
|
@ -726,6 +715,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak) |
|
|
|
|| ECOFF_IS_STAB (ecoff_sym)) |
|
|
|
asym->flags |= BSF_DEBUGGING; |
|
|
|
} |
|
|
|
|
|
|
|
if (ecoff_sym->st == stProc || ecoff_sym->st == stStaticProc) |
|
|
|
asym->flags |= BSF_FUNCTION; |
|
|
|
|
|
|
|
switch (ecoff_sym->sc) |
|
|
|
{ |
|
|
|
case scNil: |
|
|
|
@ -1186,56 +1179,54 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
qualifiers[5].type = u.ti.tq5; |
|
|
|
qualifiers[6].type = tqNil; |
|
|
|
|
|
|
|
/*
|
|
|
|
* Go get the basic type. |
|
|
|
*/ |
|
|
|
/* Go get the basic type. */ |
|
|
|
switch (basic_type) |
|
|
|
{ |
|
|
|
case btNil: /* undefined */ |
|
|
|
case btNil: /* Undefined. */ |
|
|
|
strcpy (p1, "nil"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btAdr: /* address - integer same size as pointer */ |
|
|
|
case btAdr: /* Address - integer same size as pointer. */ |
|
|
|
strcpy (p1, "address"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btChar: /* character */ |
|
|
|
case btChar: /* Character. */ |
|
|
|
strcpy (p1, "char"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btUChar: /* unsigned character */ |
|
|
|
case btUChar: /* Unsigned character. */ |
|
|
|
strcpy (p1, "unsigned char"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btShort: /* short */ |
|
|
|
case btShort: /* Short. */ |
|
|
|
strcpy (p1, "short"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btUShort: /* unsigned short */ |
|
|
|
case btUShort: /* Unsigned short. */ |
|
|
|
strcpy (p1, "unsigned short"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btInt: /* int */ |
|
|
|
case btInt: /* Int. */ |
|
|
|
strcpy (p1, "int"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btUInt: /* unsigned int */ |
|
|
|
case btUInt: /* Unsigned int. */ |
|
|
|
strcpy (p1, "unsigned int"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btLong: /* long */ |
|
|
|
case btLong: /* Long. */ |
|
|
|
strcpy (p1, "long"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btULong: /* unsigned long */ |
|
|
|
case btULong: /* Unsigned long. */ |
|
|
|
strcpy (p1, "unsigned long"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btFloat: /* float (real) */ |
|
|
|
case btFloat: /* Float (real). */ |
|
|
|
strcpy (p1, "float"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btDouble: /* Double (real) */ |
|
|
|
case btDouble: /* Double (real). */ |
|
|
|
strcpy (p1, "double"); |
|
|
|
break; |
|
|
|
|
|
|
|
@ -1243,83 +1234,83 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
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) */ |
|
|
|
case btStruct: /* Structure (Record). */ |
|
|
|
_bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); |
|
|
|
ecoff_emit_aggregate (abfd, fdr, p1, &rndx, |
|
|
|
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), |
|
|
|
"struct"); |
|
|
|
indx++; /* skip aux words */ |
|
|
|
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 */ |
|
|
|
case btUnion: /* Union. */ |
|
|
|
_bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); |
|
|
|
ecoff_emit_aggregate (abfd, fdr, p1, &rndx, |
|
|
|
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), |
|
|
|
"union"); |
|
|
|
indx++; /* skip aux words */ |
|
|
|
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 */ |
|
|
|
case btEnum: /* Enumeration. */ |
|
|
|
_bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); |
|
|
|
ecoff_emit_aggregate (abfd, fdr, p1, &rndx, |
|
|
|
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), |
|
|
|
"enum"); |
|
|
|
indx++; /* skip aux words */ |
|
|
|
indx++; /* Skip aux words. */ |
|
|
|
break; |
|
|
|
|
|
|
|
case btTypedef: /* defined via a typedef, isymRef points */ |
|
|
|
case btTypedef: /* Defined via a typedef, isymRef points. */ |
|
|
|
strcpy (p1, "typedef"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btRange: /* subrange of int */ |
|
|
|
case btRange: /* Subrange of int. */ |
|
|
|
strcpy (p1, "subrange"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btSet: /* pascal sets */ |
|
|
|
case btSet: /* Pascal sets. */ |
|
|
|
strcpy (p1, "set"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btComplex: /* fortran complex */ |
|
|
|
case btComplex: /* Fortran complex. */ |
|
|
|
strcpy (p1, "complex"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btDComplex: /* fortran double complex */ |
|
|
|
case btDComplex: /* Fortran double complex. */ |
|
|
|
strcpy (p1, "double complex"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btIndirect: /* forward or unnamed typedef */ |
|
|
|
case btIndirect: /* Forward or unnamed typedef. */ |
|
|
|
strcpy (p1, "forward/unamed typedef"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btFixedDec: /* Fixed Decimal */ |
|
|
|
case btFixedDec: /* Fixed Decimal. */ |
|
|
|
strcpy (p1, "fixed decimal"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btFloatDec: /* Float Decimal */ |
|
|
|
case btFloatDec: /* Float Decimal. */ |
|
|
|
strcpy (p1, "float decimal"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btString: /* Varying Length Character String */ |
|
|
|
case btString: /* Varying Length Character String. */ |
|
|
|
strcpy (p1, "string"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btBit: /* Aligned Bit String */ |
|
|
|
case btBit: /* Aligned Bit String. */ |
|
|
|
strcpy (p1, "bit"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btPicture: /* Picture */ |
|
|
|
case btPicture: /* Picture. */ |
|
|
|
strcpy (p1, "picture"); |
|
|
|
break; |
|
|
|
|
|
|
|
case btVoid: /* Void */ |
|
|
|
case btVoid: /* Void. */ |
|
|
|
strcpy (p1, "void"); |
|
|
|
break; |
|
|
|
|
|
|
|
@ -1330,9 +1321,7 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
|
|
|
|
p1 += strlen (buffer1); |
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is a bitfield, get the bitsize. |
|
|
|
*/ |
|
|
|
/* If this is a bitfield, get the bitsize. */ |
|
|
|
if (u.ti.fBitfield) |
|
|
|
{ |
|
|
|
int bitsize; |
|
|
|
@ -1342,20 +1331,16 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
p1 += strlen (buffer1); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Deal with any qualifiers. |
|
|
|
*/ |
|
|
|
/* Deal with any qualifiers. */ |
|
|
|
if (qualifiers[0].type != tqNil) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Snarf up any array bounds in the correct order. Arrays |
|
|
|
* store 5 successive words in the aux. table: |
|
|
|
* word 0 RNDXR to type of the bounds (ie, int) |
|
|
|
* word 1 Current file descriptor index |
|
|
|
* word 2 low bound |
|
|
|
* word 3 high bound (or -1 if []) |
|
|
|
* word 4 stride size in bits |
|
|
|
*/ |
|
|
|
/* Snarf up any array bounds in the correct order. Arrays
|
|
|
|
store 5 successive words in the aux. table: |
|
|
|
word 0 RNDXR to type of the bounds (ie, int) |
|
|
|
word 1 Current file descriptor index |
|
|
|
word 2 low bound |
|
|
|
word 3 high bound (or -1 if []) |
|
|
|
word 4 stride size in bits. */ |
|
|
|
for (i = 0; i < 7; i++) |
|
|
|
{ |
|
|
|
if (qualifiers[i].type == tqArray) |
|
|
|
@ -1370,9 +1355,7 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Now print out the qualifiers. |
|
|
|
*/ |
|
|
|
/* Now print out the qualifiers. */ |
|
|
|
for (i = 0; i < 6; i++) |
|
|
|
{ |
|
|
|
switch (qualifiers[i].type) |
|
|
|
@ -1408,7 +1391,6 @@ ecoff_type_to_string (abfd, fdr, indx) |
|
|
|
|
|
|
|
/* Print array bounds reversed (ie, in the order the C
|
|
|
|
programmer writes them). C is such a fun language.... */ |
|
|
|
|
|
|
|
while (i < 5 && qualifiers[i+1].type == tqArray) |
|
|
|
i++; |
|
|
|
|
|
|
|
@ -1510,7 +1492,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) |
|
|
|
} |
|
|
|
break; |
|
|
|
case bfd_print_symbol_all: |
|
|
|
/* Print out the symbols in a reasonable way */ |
|
|
|
/* Print out the symbols in a reasonable way. */ |
|
|
|
{ |
|
|
|
char type; |
|
|
|
int pos; |
|
|
|
@ -1584,7 +1566,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how) |
|
|
|
order is indicated by a bit in the fdr. */ |
|
|
|
bigendian = fdr->fBigendian; |
|
|
|
|
|
|
|
/* This switch is basically from gcc/mips-tdump.c */ |
|
|
|
/* This switch is basically from gcc/mips-tdump.c. */ |
|
|
|
switch (ecoff_ext.asym.st) |
|
|
|
{ |
|
|
|
case stNil: |
|
|
|
@ -2180,7 +2162,7 @@ ecoff_compute_section_file_positions (abfd) |
|
|
|
if ((current->flags & SEC_HAS_CONTENTS) != 0) |
|
|
|
file_sofar += current->_raw_size; |
|
|
|
|
|
|
|
/* make sure that this section is of the right size too */ |
|
|
|
/* Make sure that this section is of the right size too. */ |
|
|
|
old_sofar = sofar; |
|
|
|
sofar = BFD_ALIGN (sofar, 1 << alignment_power); |
|
|
|
if ((current->flags & SEC_HAS_CONTENTS) != 0) |
|
|
|
@ -2362,7 +2344,7 @@ bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask) |
|
|
|
tdata->fprmask = fprmask; |
|
|
|
if (cprmask != (unsigned long *) NULL) |
|
|
|
{ |
|
|
|
register int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) |
|
|
|
tdata->cprmask[i] = cprmask[i]; |
|
|
|
@ -2629,13 +2611,12 @@ _bfd_ecoff_write_object_contents (abfd) |
|
|
|
else if (section.s_flags == 0 |
|
|
|
|| (section.s_flags & STYP_ECOFF_LIB) != 0 |
|
|
|
|| section.s_flags == STYP_COMMENT) |
|
|
|
/* Do nothing */ ; |
|
|
|
/* Do nothing. */ ; |
|
|
|
else |
|
|
|
abort (); |
|
|
|
} |
|
|
|
|
|
|
|
/* Set up the file header. */ |
|
|
|
|
|
|
|
internal_f.f_magic = ecoff_get_magic (abfd); |
|
|
|
|
|
|
|
/* We will NOT put a fucking timestamp in the header here. Every
|
|
|
|
@ -2728,7 +2709,6 @@ _bfd_ecoff_write_object_contents (abfd) |
|
|
|
} |
|
|
|
|
|
|
|
/* Write out the file header and the optional header. */ |
|
|
|
|
|
|
|
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
@ -3056,7 +3036,6 @@ _bfd_ecoff_slurp_armap (abfd) |
|
|
|
|
|
|
|
/* This code used to overlay the symdefs over the raw archive data,
|
|
|
|
but that doesn't work on a 64 bit host. */ |
|
|
|
|
|
|
|
stringbase = raw_armap + count * 8 + 8; |
|
|
|
|
|
|
|
#ifdef CHECK_ARMAP_HASH |
|
|
|
|