* ecoff.c (ecoff_mkobject): Check bfd_make_section return value.
(ecoff_mkobject_hook): New function. (ecoff_new_section_hook, ecoff_sizeof_headers, ecoff_compute_section_file_positions, ecoff_set_section_contents, ecoff_write_object_contents): Handle dummy REGINFO section. (ecoff_get_section_contents): New function to handle reading REGINFO section. * libecoff.h (ecoff_get_section_contents): Change from macro definition to function prototype. (ecoff_mkobject_hook): New prototype. * coff-alpha.c (alpha_ecoff_mkobject_hook): Removed. (alpha_ecoff_backend_data): Use ecoff_mkobject_hook. * coff-mips.c (mips_ecoff_mkobject_hook): Removed. (mips_ecoff_backend_data): Use ecoff_mkobject_hook.
This commit is contained in:
parent
f3863d3ab1
commit
a785321604
2 changed files with 272 additions and 36 deletions
|
@ -1,3 +1,20 @@
|
|||
Mon Oct 11 17:25:18 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
||||
|
||||
* ecoff.c (ecoff_mkobject): Check bfd_make_section return value.
|
||||
(ecoff_mkobject_hook): New function.
|
||||
(ecoff_new_section_hook, ecoff_sizeof_headers,
|
||||
ecoff_compute_section_file_positions, ecoff_set_section_contents,
|
||||
ecoff_write_object_contents): Handle dummy REGINFO section.
|
||||
(ecoff_get_section_contents): New function to handle reading
|
||||
REGINFO section.
|
||||
* libecoff.h (ecoff_get_section_contents): Change from macro
|
||||
definition to function prototype.
|
||||
(ecoff_mkobject_hook): New prototype.
|
||||
* coff-alpha.c (alpha_ecoff_mkobject_hook): Removed.
|
||||
(alpha_ecoff_backend_data): Use ecoff_mkobject_hook.
|
||||
* coff-mips.c (mips_ecoff_mkobject_hook): Removed.
|
||||
(mips_ecoff_backend_data): Use ecoff_mkobject_hook.
|
||||
|
||||
Fri Oct 8 15:25:33 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
|
||||
* libbfd.c (bfd_get*32, bfd_get*64): Prevent ANSI sign extension
|
||||
|
|
291
bfd/ecoff.c
291
bfd/ecoff.c
|
@ -44,6 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
/* Prototypes for static functions. */
|
||||
|
||||
static int ecoff_get_magic PARAMS ((bfd *abfd));
|
||||
static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
|
||||
asymbol *asym, int ext,
|
||||
asymbol **indirect_ptr_ptr));
|
||||
|
@ -93,11 +94,64 @@ ecoff_mkobject (abfd)
|
|||
|
||||
/* 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);
|
||||
if (bfd_make_section (abfd, SCOMMON) == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This is a hook called by coff_real_object_p to create any backend
|
||||
specific information. */
|
||||
|
||||
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;
|
||||
asection *regsec;
|
||||
|
||||
if (ecoff_mkobject (abfd) == false)
|
||||
return NULL;
|
||||
|
||||
ecoff = ecoff_data (abfd);
|
||||
ecoff->gp_size = 8;
|
||||
ecoff->sym_filepos = internal_f->f_symptr;
|
||||
|
||||
/* Create the .reginfo section to give programs outside BFD a way to
|
||||
see the information stored in the a.out header. See the comment
|
||||
in coff/ecoff.h. */
|
||||
regsec = bfd_make_section (abfd, REGINFO);
|
||||
if (regsec == NULL)
|
||||
return NULL;
|
||||
|
||||
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];
|
||||
ecoff->fprmask = internal_a->fprmask;
|
||||
if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
|
||||
abfd->flags |= D_PAGED;
|
||||
}
|
||||
|
||||
/* It turns out that no special action is required by the MIPS or
|
||||
Alpha ECOFF backends. They have different information in the
|
||||
a.out header, but we just copy it all (e.g., gprmask, cprmask and
|
||||
fprmask) and let the swapping routines ensure that only relevant
|
||||
information is written out. */
|
||||
|
||||
return (PTR) ecoff;
|
||||
}
|
||||
|
||||
/* This is a hook needed by SCO COFF, but we have nothing to do. */
|
||||
|
||||
asection *
|
||||
|
@ -129,6 +183,11 @@ ecoff_new_section_hook (abfd, section)
|
|||
else if (strcmp (section->name, _BSS) == 0
|
||||
|| strcmp (section->name, _SBSS) == 0)
|
||||
section->flags |= SEC_ALLOC;
|
||||
else if (strcmp (section->name, REGINFO) == 0)
|
||||
{
|
||||
section->flags |= SEC_HAS_CONTENTS | SEC_NEVER_LOAD;
|
||||
section->_raw_size = sizeof (struct ecoff_reginfo);
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -137,7 +196,10 @@ ecoff_new_section_hook (abfd, section)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Determine the machine architecture and type. */
|
||||
/* Determine the machine architecture and type. This is called from
|
||||
the generic COFF routines. It is the inverse of ecoff_get_magic,
|
||||
below. This could be an ECOFF backend routine, with one version
|
||||
for each target, but there aren't all that many ECOFF targets. */
|
||||
|
||||
boolean
|
||||
ecoff_set_arch_mach_hook (abfd, filehdr)
|
||||
|
@ -146,6 +208,7 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
|
|||
{
|
||||
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
|
||||
enum bfd_architecture arch;
|
||||
unsigned long mach;
|
||||
|
||||
switch (internal_f->f_magic)
|
||||
{
|
||||
|
@ -153,20 +216,78 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
|
|||
case MIPS_MAGIC_LITTLE:
|
||||
case MIPS_MAGIC_BIG:
|
||||
arch = bfd_arch_mips;
|
||||
mach = 3000;
|
||||
break;
|
||||
|
||||
case MIPS_MAGIC_LITTLE2:
|
||||
case MIPS_MAGIC_BIG2:
|
||||
/* 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 */
|
||||
arch = bfd_arch_mips;
|
||||
mach = 4000;
|
||||
break;
|
||||
|
||||
case ALPHA_MAGIC:
|
||||
arch = bfd_arch_alpha;
|
||||
mach = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
arch = bfd_arch_obscure;
|
||||
mach = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
|
||||
return bfd_default_set_arch_mach (abfd, arch, mach);
|
||||
}
|
||||
|
||||
return true;
|
||||
/* Get the magic number to use based on the architecture and machine.
|
||||
This is the inverse of ecoff_set_arch_mach_hook, above. */
|
||||
|
||||
static int
|
||||
ecoff_get_magic (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
int big, little;
|
||||
|
||||
switch (bfd_get_arch (abfd))
|
||||
{
|
||||
case bfd_arch_mips:
|
||||
switch (bfd_get_mach (abfd))
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
case 3000:
|
||||
big = MIPS_MAGIC_BIG;
|
||||
little = MIPS_MAGIC_LITTLE;
|
||||
break;
|
||||
|
||||
case 6000:
|
||||
big = MIPS_MAGIC_BIG2;
|
||||
little = MIPS_MAGIC_LITTLE2;
|
||||
break;
|
||||
|
||||
case 4000:
|
||||
big = MIPS_MAGIC_BIG3;
|
||||
little = MIPS_MAGIC_LITTLE3;
|
||||
break;
|
||||
}
|
||||
|
||||
return abfd->xvec->byteorder_big_p ? big : little;
|
||||
|
||||
case bfd_arch_alpha:
|
||||
return ALPHA_MAGIC;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the section s_flags to use for a section. */
|
||||
|
@ -198,6 +319,8 @@ ecoff_sec_to_styp_flags (name, flags)
|
|||
styp = STYP_SBSS;
|
||||
else if (strcmp (name, _INIT) == 0)
|
||||
styp = STYP_ECOFF_INIT;
|
||||
else if (strcmp (name, _FINI) == 0)
|
||||
styp = STYP_ECOFF_FINI;
|
||||
else if (flags & SEC_CODE)
|
||||
styp = STYP_TEXT;
|
||||
else if (flags & SEC_DATA)
|
||||
|
@ -232,7 +355,8 @@ ecoff_styp_to_sec_flags (abfd, hdr)
|
|||
/* For 386 COFF, at least, an unloadable text or data section is
|
||||
actually a shared library section. */
|
||||
if ((styp_flags & STYP_TEXT)
|
||||
|| (styp_flags & STYP_ECOFF_INIT))
|
||||
|| (styp_flags & STYP_ECOFF_INIT)
|
||||
|| (styp_flags & STYP_ECOFF_FINI))
|
||||
{
|
||||
if (sec_flags & SEC_NEVER_LOAD)
|
||||
sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
|
||||
|
@ -483,6 +607,8 @@ ecoff_slurp_symbolic_info (abfd)
|
|||
char *fraw_src;
|
||||
char *fraw_end;
|
||||
struct fdr *fdr_ptr;
|
||||
bfd_size_type raw_end;
|
||||
bfd_size_type cb_end;
|
||||
|
||||
/* Check whether we've already gotten it, and whether there's any to
|
||||
get. */
|
||||
|
@ -530,30 +656,34 @@ ecoff_slurp_symbolic_info (abfd)
|
|||
/* Read all the symbolic information at once. */
|
||||
raw_base = ecoff_data (abfd)->sym_filepos + external_hdr_size;
|
||||
|
||||
if (internal_symhdr->cbExtOffset != 0)
|
||||
raw_size = (internal_symhdr->cbExtOffset
|
||||
- raw_base
|
||||
+ internal_symhdr->iextMax * backend->external_ext_size);
|
||||
else
|
||||
{
|
||||
long cbline, issmax, issextmax;
|
||||
/* Alpha ecoff makes the determination of raw_size difficult. It has
|
||||
an undocumented debug data section between the symhdr and the first
|
||||
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. */
|
||||
|
||||
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 * backend->external_dnr_size
|
||||
+ internal_symhdr->ipdMax * backend->external_pdr_size
|
||||
+ internal_symhdr->isymMax * backend->external_sym_size
|
||||
+ internal_symhdr->ioptMax * backend->external_opt_size
|
||||
+ internal_symhdr->iauxMax * sizeof (union aux_ext)
|
||||
+ issmax * sizeof (char)
|
||||
+ issextmax * sizeof (char)
|
||||
+ internal_symhdr->ifdMax * backend->external_fdr_size
|
||||
+ internal_symhdr->crfd * backend->external_rfd_size
|
||||
+ internal_symhdr->iextMax * backend->external_ext_size);
|
||||
}
|
||||
raw_end = 0;
|
||||
|
||||
#define UPDATE_RAW_END(start, count, size) \
|
||||
cb_end = internal_symhdr->start + internal_symhdr->count * (size); \
|
||||
if (cb_end > raw_end) \
|
||||
raw_end = cb_end
|
||||
|
||||
UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));
|
||||
UPDATE_RAW_END (cbDnOffset, idnMax, backend->external_dnr_size);
|
||||
UPDATE_RAW_END (cbPdOffset, ipdMax, backend->external_pdr_size);
|
||||
UPDATE_RAW_END (cbSymOffset, isymMax, backend->external_sym_size);
|
||||
UPDATE_RAW_END (cbOptOffset, ioptMax, backend->external_opt_size);
|
||||
UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));
|
||||
UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));
|
||||
UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char));
|
||||
UPDATE_RAW_END (cbFdOffset, ifdMax, backend->external_fdr_size);
|
||||
UPDATE_RAW_END (cbRfdOffset, crfd, backend->external_rfd_size);
|
||||
UPDATE_RAW_END (cbExtOffset, iextMax, backend->external_ext_size);
|
||||
|
||||
#undef UPDATE_RAW_END
|
||||
|
||||
raw_size = raw_end - raw_base;
|
||||
if (raw_size == 0)
|
||||
{
|
||||
ecoff_data (abfd)->sym_filepos = 0;
|
||||
|
@ -2821,16 +2951,63 @@ ecoff_set_arch_mach (abfd, arch, machine)
|
|||
}
|
||||
|
||||
/* Get the size of the section headers. We do not output the .scommon
|
||||
section which we created in ecoff_mkobject. */
|
||||
section which we created in ecoff_mkobject, nor do we output any
|
||||
.reginfo section. */
|
||||
|
||||
int
|
||||
ecoff_sizeof_headers (abfd, reloc)
|
||||
bfd *abfd;
|
||||
boolean reloc;
|
||||
{
|
||||
asection *current;
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
for (current = abfd->sections;
|
||||
current != (asection *)NULL;
|
||||
current = current->next)
|
||||
if (strcmp (current->name, SCOMMON) != 0
|
||||
&& strcmp (current->name, REGINFO) != 0)
|
||||
++c;
|
||||
|
||||
return (bfd_coff_filhsz (abfd)
|
||||
+ bfd_coff_aoutsz (abfd)
|
||||
+ (abfd->section_count - 1) * bfd_coff_scnhsz (abfd));
|
||||
+ c * bfd_coff_scnhsz (abfd));
|
||||
}
|
||||
|
||||
|
||||
/* Get the contents of a section. This is where we handle reading the
|
||||
.reginfo section, which implicitly holds the contents of an
|
||||
ecoff_reginfo structure. */
|
||||
|
||||
boolean
|
||||
ecoff_get_section_contents (abfd, section, location, offset, count)
|
||||
bfd *abfd;
|
||||
asection *section;
|
||||
PTR location;
|
||||
file_ptr offset;
|
||||
bfd_size_type count;
|
||||
{
|
||||
ecoff_data_type *tdata = ecoff_data (abfd);
|
||||
struct ecoff_reginfo s;
|
||||
int i;
|
||||
|
||||
if (strcmp (section->name, REGINFO) != 0)
|
||||
return bfd_generic_get_section_contents (abfd, section, location,
|
||||
offset, count);
|
||||
|
||||
s.gp_value = tdata->gp;
|
||||
s.gprmask = tdata->gprmask;
|
||||
for (i = 0; i < 4; i++)
|
||||
s.cprmask[i] = tdata->cprmask[i];
|
||||
s.fprmask = tdata->fprmask;
|
||||
|
||||
/* bfd_get_section_contents has already checked that the offset and
|
||||
size is reasonable. We don't have to worry about swapping or any
|
||||
such thing; the .reginfo section is defined such that the
|
||||
contents are an ecoff_reginfo structure as seen on the host. */
|
||||
memcpy (location, ((char *) &s) + offset, count);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Calculate the file position for each section, and set
|
||||
|
@ -2857,7 +3034,8 @@ ecoff_compute_section_file_positions (abfd)
|
|||
{
|
||||
/* Only deal with sections which have contents */
|
||||
if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
|
||||
|| strcmp (current->name, SCOMMON) == 0)
|
||||
|| strcmp (current->name, SCOMMON) == 0
|
||||
|| strcmp (current->name, REGINFO) == 0)
|
||||
continue;
|
||||
|
||||
/* On Ultrix, the data sections in an executable file must be
|
||||
|
@ -2893,7 +3071,9 @@ ecoff_compute_section_file_positions (abfd)
|
|||
ecoff_data (abfd)->reloc_filepos = sofar;
|
||||
}
|
||||
|
||||
/* Set the contents of a section. */
|
||||
/* Set the contents of a section. This is where we handle setting the
|
||||
contents of the .reginfo section, which implicitly holds a
|
||||
ecoff_reginfo structure. */
|
||||
|
||||
boolean
|
||||
ecoff_set_section_contents (abfd, section, location, offset, count)
|
||||
|
@ -2906,6 +3086,40 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
|
|||
if (abfd->output_has_begun == false)
|
||||
ecoff_compute_section_file_positions (abfd);
|
||||
|
||||
if (strcmp (section->name, REGINFO) == 0)
|
||||
{
|
||||
ecoff_data_type *tdata = ecoff_data (abfd);
|
||||
struct ecoff_reginfo s;
|
||||
int i;
|
||||
|
||||
/* If the caller is only changing part of the structure, we must
|
||||
retrieve the current information before the memcpy. */
|
||||
if (offset != 0 || count != sizeof (struct ecoff_reginfo))
|
||||
{
|
||||
s.gp_value = tdata->gp;
|
||||
s.gprmask = tdata->gprmask;
|
||||
for (i = 0; i < 4; i++)
|
||||
s.cprmask[i] = tdata->cprmask[i];
|
||||
s.fprmask = tdata->fprmask;
|
||||
}
|
||||
|
||||
/* bfd_set_section_contents has already checked that the offset
|
||||
and size is reasonable. We don't have to worry about
|
||||
swapping or any such thing; the .reginfo section is defined
|
||||
such that the contents are an ecoff_reginfo structure as seen
|
||||
on the host. */
|
||||
memcpy (((char *) &s) + offset, location, count);
|
||||
|
||||
tdata->gp = s.gp_value;
|
||||
tdata->gprmask = s.gprmask;
|
||||
for (i = 0; i < 4; i++)
|
||||
tdata->cprmask[i] = s.cprmask[i];
|
||||
tdata->fprmask = s.fprmask;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET);
|
||||
|
||||
if (count != 0)
|
||||
|
@ -2964,7 +3178,8 @@ ecoff_write_object_contents (abfd)
|
|||
current != (asection *)NULL;
|
||||
current = current->next)
|
||||
{
|
||||
if (strcmp (current->name, SCOMMON) == 0)
|
||||
if (strcmp (current->name, SCOMMON) == 0
|
||||
|| strcmp (current->name, REGINFO) == 0)
|
||||
continue;
|
||||
current->target_index = count;
|
||||
++count;
|
||||
|
@ -3020,6 +3235,13 @@ ecoff_write_object_contents (abfd)
|
|||
&& current->reloc_count == 0);
|
||||
continue;
|
||||
}
|
||||
if (strcmp (current->name, REGINFO) == 0)
|
||||
{
|
||||
BFD_ASSERT ((bfd_get_section_size_before_reloc (current)
|
||||
== sizeof (struct ecoff_reginfo))
|
||||
&& current->reloc_count == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
++internal_f.f_nscns;
|
||||
|
||||
|
@ -3084,10 +3306,7 @@ ecoff_write_object_contents (abfd)
|
|||
|
||||
/* Set up the file header. */
|
||||
|
||||
if (abfd->xvec->header_byteorder_big_p != false)
|
||||
internal_f.f_magic = backend->big_magic;
|
||||
else
|
||||
internal_f.f_magic = backend->little_magic;
|
||||
internal_f.f_magic = ecoff_get_magic (abfd);
|
||||
|
||||
/* We will NOT put a fucking timestamp in the header here. Every
|
||||
time you put it back, I will come in and take it out again. I'm
|
||||
|
|
Loading…
Reference in a new issue