static int ecoff_get_magic PARAMS ((bfd *abfd));
static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd));
-static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
+static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
asymbol *asym, int ext,
asymbol **indirect_ptr_ptr));
-static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
+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, union aux_ext *aux_ptr,
- unsigned int indx, int bigendian));
+ 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 void ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
bfd_zalloc (abfd, sizeof (ecoff_data_type)));
if (abfd->tdata.ecoff_obj_data == NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
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->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;
else if (strcmp (section->name, _BSS) == 0
|| strcmp (section->name, _SBSS) == 0)
section->flags |= SEC_ALLOC;
- else if (strcmp (section->name, REGINFO) == 0)
+ else if (strcmp (section->name, _LIB) == 0)
{
- /* Setting SEC_SHARED_LIBRARY should make the linker leave the
- section completely alone. */
- section->flags |= (SEC_SHARED_LIBRARY
- | SEC_HAS_CONTENTS
- | SEC_NEVER_LOAD);
- section->_raw_size = sizeof (struct ecoff_reginfo);
+ /* An Irix 4 shared libary. */
+ section->flags |= SEC_COFF_SHARED_LIBRARY;
}
/* Probably any other section name is SEC_NEVER_LOAD, but I'm
styp = STYP_PDATA;
else if (strcmp (name, _XDATA) == 0)
styp = STYP_XDATA;
+ else if (strcmp (name, _LIB) == 0)
+ styp = STYP_ECOFF_LIB;
else if (flags & SEC_CODE)
styp = STYP_TEXT;
else if (flags & SEC_DATA)
|| (styp_flags & STYP_ECOFF_FINI))
{
if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
+ sec_flags |= SEC_CODE | SEC_COFF_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))
+ || (styp_flags & STYP_SDATA)
+ || styp_flags == STYP_PDATA
+ || styp_flags == STYP_XDATA)
{
if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
+ sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
else
sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
- if (styp_flags & STYP_RDATA)
+ if ((styp_flags & STYP_RDATA)
+ || styp_flags == STYP_PDATA)
sec_flags |= SEC_READONLY;
}
else if ((styp_flags & STYP_BSS)
{
sec_flags |= SEC_ALLOC;
}
- else if (styp_flags & STYP_INFO)
+ else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT)
{
sec_flags |= SEC_NEVER_LOAD;
}
{
sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
}
+ else if (styp_flags & STYP_ECOFF_LIB)
+ {
+ sec_flags |= SEC_COFF_SHARED_LIBRARY;
+ }
else
{
sec_flags |= SEC_ALLOC | SEC_LOAD;
intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE)
>> RNDX_BITS1_INDEX_SH_LITTLE)
| (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE)
- | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
+ | ((unsigned int) ext->r_bits[3]
+ << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
}
#ifdef TEST
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
bfd_size_type external_hdr_size;
- PTR raw;
+ PTR raw = NULL;
HDRR *internal_symhdr;
/* See if we've already read it in. */
external_hdr_size = backend->debug_swap.external_hdr_size;
if (bfd_get_symcount (abfd) != external_hdr_size)
{
- bfd_error = bad_value;
+ bfd_set_error (bfd_error_bad_value);
return false;
}
/* Read the symbolic information header. */
- raw = (PTR) alloca ((size_t) external_hdr_size);
+ raw = (PTR) malloc ((size_t) external_hdr_size);
+ if (raw == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1
|| (bfd_read (raw, external_hdr_size, 1, abfd)
!= external_hdr_size))
- {
- bfd_error = system_call_error;
- return false;
- }
+ goto error_return;
internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
(*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr);
if (internal_symhdr->magic != backend->debug_swap.sym_magic)
{
- bfd_error = bad_value;
- return false;
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
}
/* Now we can get the correct number of symbols. */
bfd_get_symcount (abfd) = (internal_symhdr->isymMax
+ internal_symhdr->iextMax);
+ if (raw != NULL)
+ free (raw);
return true;
+ error_return:
+ if (raw != NULL)
+ free (raw);
+ return false;
}
/* Read in and swap the important symbolic information for an ECOFF
raw = (PTR) bfd_alloc (abfd, raw_size);
if (raw == NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
if (bfd_seek (abfd,
SEEK_SET) != 0
|| bfd_read (raw, raw_size, 1, abfd) != raw_size)
{
- bfd_error = system_call_error;
bfd_release (abfd, raw);
return false;
}
sizeof (struct fdr)));
if (ecoff_data (abfd)->debug_info.fdr == NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
external_fdr_size = backend->debug_swap.external_fdr_size;
new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));
if (new == (ecoff_symbol_type *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return (asymbol *) NULL;
}
- memset (new, 0, sizeof *new);
+ memset ((PTR) new, 0, sizeof *new);
new->symbol.section = (asection *) NULL;
new->fdr = (FDR *) NULL;
new->local = false;
/* Set the BFD flags and section for an ECOFF symbol. */
-static void
+static boolean
ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
bfd *abfd;
SYMR *ecoff_sym;
asym->flags = BSF_DEBUGGING;
asym->section = &bfd_und_section;
*indirect_ptr_ptr = NULL;
- return;
+ return true;
}
if (ECOFF_IS_STAB (ecoff_sym)
asym->section = &bfd_ind_section;
/* Pass this symbol on to the next call to this function. */
*indirect_ptr_ptr = asym;
- return;
+ return true;
}
/* Most symbol types are just for debugging. */
if (ECOFF_IS_STAB (ecoff_sym))
{
asym->flags = BSF_DEBUGGING;
- return;
+ return true;
}
break;
default:
asym->flags = BSF_DEBUGGING;
- return;
+ return true;
}
if (ext)
char *copy;
copy = (char *) bfd_alloc (abfd, strlen (name) + 1);
+ if (!copy)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
strcpy (copy, name);
section = bfd_make_section (abfd, copy);
}
/* Build a reloc pointing to this constructor. */
reloc_chain =
(arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+ if (!reloc_chain)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
reloc_chain->relent.sym_ptr_ptr =
bfd_get_section (asym)->symbol_ptr_ptr;
reloc_chain->relent.address = section->_raw_size;
break;
}
}
+ return true;
}
/* Read an ECOFF symbol table. */
internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
if (internal == NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
(*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym);
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext
+ internal_esym.asym.iss);
- ecoff_set_symbol_info (abfd, &internal_esym.asym,
- &internal_ptr->symbol, 1, &indirect_ptr);
+ if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
+ &internal_ptr->symbol, 1, &indirect_ptr))
+ return false;
/* The alpha uses a negative ifd field for section symbols. */
if (internal_esym.ifd >= 0)
internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss
+ fdr_ptr->issBase
+ internal_sym.iss);
- ecoff_set_symbol_info (abfd, &internal_sym,
- &internal_ptr->symbol, 0, &indirect_ptr);
+ if (!ecoff_set_symbol_info (abfd, &internal_sym,
+ &internal_ptr->symbol, 0, &indirect_ptr))
+ return false;
internal_ptr->fdr = fdr_ptr;
internal_ptr->local = true;
internal_ptr->native = (PTR) lraw_src;
/* Return the amount of space needed for the canonical symbols. */
-unsigned int
+long
ecoff_get_symtab_upper_bound (abfd)
bfd *abfd;
{
- if (ecoff_slurp_symbolic_info (abfd) == false
- || bfd_get_symcount (abfd) == 0)
+ if (! ecoff_slurp_symbolic_info (abfd))
+ return -1;
+
+ if (bfd_get_symcount (abfd) == 0)
return 0;
return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
/* Get the canonical symbols. */
-unsigned int
+long
ecoff_get_symtab (abfd, alocation)
bfd *abfd;
asymbol **alocation;
ecoff_symbol_type *symbase;
ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
- if (ecoff_slurp_symbol_table (abfd) == false
- || bfd_get_symcount (abfd) == 0)
+ if (ecoff_slurp_symbol_table (abfd) == false)
+ return -1;
+ if (bfd_get_symcount (abfd) == 0)
return 0;
symbase = ecoff_data (abfd)->canonical_symbols;
/* Write aggregate information to a string. */
static void
-ecoff_emit_aggregate (abfd, string, rndx, isym, which)
+ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
bfd *abfd;
+ FDR *fdr;
char *string;
RNDXR *rndx;
long isym;
- CONST char *which;
+ const char *which;
{
- int ifd = rndx->rfd;
- int indx = rndx->index;
- int sym_base, ss_base;
- CONST char *name;
+ const struct ecoff_debug_swap * const debug_swap =
+ &ecoff_backend (abfd)->debug_swap;
+ struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
+ unsigned int ifd = rndx->rfd;
+ unsigned int indx = rndx->index;
+ const char *name;
if (ifd == 0xfff)
ifd = isym;
- sym_base = ecoff_data (abfd)->debug_info.fdr[ifd].isymBase;
- ss_base = ecoff_data (abfd)->debug_info.fdr[ifd].issBase;
-
- if (indx == indexNil)
- name = "/* no name */";
+ /* An ifd of -1 is an opaque type. An escaped index of 0 is a
+ struct return type of a procedure compiled without -g. */
+ if (ifd == 0xffffffff
+ || (rndx->rfd == 0xfff && indx == 0))
+ name = "<undefined>";
+ else if (indx == indexNil)
+ name = "<no name>";
else
{
- const struct ecoff_debug_swap * const debug_swap
- = &ecoff_backend (abfd)->debug_swap;
SYMR sym;
- indx += sym_base;
- (*debug_swap->swap_sym_in)
- (abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_sym
- + indx * debug_swap->external_sym_size),
- &sym);
- name = ecoff_data (abfd)->debug_info.ss + ss_base + sym.iss;
+ if (debug_info->external_rfd == NULL)
+ fdr = debug_info->fdr + ifd;
+ else
+ {
+ RFDT rfd;
+
+ (*debug_swap->swap_rfd_in) (abfd,
+ ((char *) debug_info->external_rfd
+ + ((fdr->rfdBase + ifd)
+ * debug_swap->external_rfd_size)),
+ &rfd);
+ fdr = debug_info->fdr + rfd;
+ }
+
+ indx += fdr->isymBase;
+
+ (*debug_swap->swap_sym_in) (abfd,
+ ((char *) debug_info->external_sym
+ + indx * debug_swap->external_sym_size),
+ &sym);
+
+ name = debug_info->ss + fdr->issBase + sym.iss;
}
sprintf (string,
- "%s %s { ifd = %d, index = %ld }",
+ "%s %s { ifd = %u, index = %lu }",
which, name, ifd,
((long) indx
- + ecoff_data (abfd)->debug_info.symbolic_header.iextMax));
+ + debug_info->symbolic_header.iextMax));
}
/* Convert the type information to string format. */
static char *
-ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
+ecoff_type_to_string (abfd, fdr, indx)
bfd *abfd;
- union aux_ext *aux_ptr;
+ FDR *fdr;
unsigned int indx;
- int bigendian;
{
+ union aux_ext *aux_ptr;
+ int bigendian;
AUXU u;
struct qual {
unsigned int type;
int high_bound;
int stride;
} qualifiers[7];
-
unsigned int basic_type;
int i;
static char buffer1[1024];
char *p2 = buffer2;
RNDXR rndx;
+ aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase;
+ bigendian = fdr->fBigendian;
+
for (i = 0; i < 7; i++)
{
qualifiers[i].low_bound = 0;
case btStruct: /* Structure (Record) */
ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"struct");
indx++; /* skip aux words */
case btUnion: /* Union */
ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"union");
indx++; /* skip aux words */
case btEnum: /* Enumeration */
ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"enum");
indx++; /* skip aux words */
if (ecoffsymbol (symbol)->fdr != NULL
&& ecoff_ext.asym.index != indexNil)
{
+ FDR *fdr;
unsigned int indx;
int bigendian;
bfd_size_type sym_base;
union aux_ext *aux_base;
+ fdr = ecoffsymbol (symbol)->fdr;
indx = ecoff_ext.asym.index;
/* sym_base is used to map the fdr relative indices which
appear in the file to the position number which we are
using. */
- sym_base = ecoffsymbol (symbol)->fdr->isymBase;
+ sym_base = fdr->isymBase;
if (ecoffsymbol (symbol)->local)
sym_base +=
ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
/* aux_base is the start of the aux entries for this file;
asym.index is an offset from this. */
aux_base = (ecoff_data (abfd)->debug_info.external_aux
- + ecoffsymbol (symbol)->fdr->iauxBase);
+ + fdr->iauxBase);
/* The aux entries are stored in host byte order; the
order is indicated by a bit in the fdr. */
- bigendian = ecoffsymbol (symbol)->fdr->fBigendian;
+ bigendian = fdr->fBigendian;
/* This switch is basically from gcc/mips-tdump.c */
switch (ecoff_ext.asym.st)
(long) (indx + sym_base));
else
fprintf (file, "\n First symbol: %ld",
- (long) (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base));
+ ((long)
+ (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base)));
break;
case stProc:
;
else if (ecoffsymbol (symbol)->local)
fprintf (file, "\n End+1 symbol: %-7ld Type: %s",
- (long) (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base),
- ecoff_type_to_string (abfd, aux_base, indx + 1,
- bigendian));
+ ((long)
+ (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base)),
+ ecoff_type_to_string (abfd, fdr, indx + 1));
else
fprintf (file, "\n Local symbol: %ld",
((long) indx
->debug_info.symbolic_header.iextMax)));
break;
+ case stStruct:
+ fprintf (file, "\n struct; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stUnion:
+ fprintf (file, "\n union; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stEnum:
+ fprintf (file, "\n enum; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
default:
if (! ECOFF_IS_STAB (&ecoff_ext.asym))
fprintf (file, "\n Type: %s",
- ecoff_type_to_string (abfd, aux_base, indx,
- bigendian));
+ ecoff_type_to_string (abfd, fdr, indx));
break;
}
}
if (internal_relocs == (arelent *) NULL
|| external_relocs == (char *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
return false;
if (bfd_read (external_relocs, 1, external_relocs_size, abfd)
!= external_relocs_size)
- {
- bfd_error = system_call_error;
- return false;
- }
+ return false;
for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
{
/* Get a canonical list of relocs. */
-unsigned int
+long
ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
bfd *abfd;
asection *section;
arelent *tblptr;
if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
- return 0;
+ return -1;
tblptr = section->relocation;
- if (tblptr == (arelent *) NULL)
- return 0;
for (count = 0; count < section->reloc_count; count++)
*relptr++ = tblptr++;
char *pdr_ptr;
char *pdr_end;
PDR pdr;
+ bfd_vma first_off;
unsigned char *line_ptr;
unsigned char *line_end;
int lineno;
+ fdr_ptr->ipdFirst * external_pdr_size);
pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ if (offset < pdr.adr)
+ return false;
/* The address of the first PDR is an offset which applies to the
addresses of all the PDR's. */
- offset += pdr.adr;
+ first_off = pdr.adr;
for (pdr_ptr += external_pdr_size;
pdr_ptr < pdr_end;
pdr_ptr -= external_pdr_size;
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
- offset -= pdr.adr;
+ offset -= pdr.adr - first_off;
lineno = pdr.lnLow;
line_ptr = (ecoff_data (abfd)->debug_info.line
+ fdr_ptr->cbLineOffset
return true;
}
\f
+/* Copy private BFD data. This is called by objcopy and strip. We
+ use it to copy the ECOFF debugging information from one BFD to the
+ other. It would be theoretically possible to represent the ECOFF
+ debugging information in the symbol table. However, it would be a
+ lot of work, and there would be little gain (gas, gdb, and ld
+ already access the ECOFF debugging information via the
+ ecoff_debug_info structure, and that structure would have to be
+ retained in order to support ECOFF debugging in MIPS ELF).
+
+ The debugging information for the ECOFF external symbols comes from
+ the symbol table, so this function only handles the other debugging
+ information. */
+
+boolean
+ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
+ struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
+ register int i;
+ asymbol **sym_ptr_ptr;
+ size_t c;
+ boolean local;
+
+ BFD_ASSERT (ibfd->xvec == obfd->xvec);
+
+ /* Copy the GP value and the register masks. */
+ ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
+ ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
+ ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
+ for (i = 0; i < 3; i++)
+ ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
+
+ /* Copy the version stamp. */
+ oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
+
+ /* If there are no symbols, don't copy any debugging information. */
+ c = bfd_get_symcount (obfd);
+ sym_ptr_ptr = bfd_get_outsymbols (obfd);
+ if (c == 0 || sym_ptr_ptr == (asymbol **) NULL)
+ return true;
+
+ /* See if there are any local symbols. */
+ local = false;
+ for (; c > 0; c--, sym_ptr_ptr++)
+ {
+ if (ecoffsymbol (*sym_ptr_ptr)->local)
+ {
+ local = true;
+ break;
+ }
+ }
+
+ if (local)
+ {
+ /* There are some local symbols. We just bring over all the
+ debugging information. FIXME: This is not quite the right
+ thing to do. If the user has asked us to discard all
+ debugging information, then we are probably going to wind up
+ keeping it because there will probably be some local symbol
+ which objcopy did not discard. We should actually break
+ apart the debugging information and only keep that which
+ applies to the symbols we want to keep. */
+ oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax;
+ oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine;
+ oinfo->line = iinfo->line;
+
+ oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax;
+ oinfo->external_dnr = iinfo->external_dnr;
+
+ oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax;
+ oinfo->external_pdr = iinfo->external_pdr;
+
+ oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax;
+ oinfo->external_sym = iinfo->external_sym;
+
+ oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax;
+ oinfo->external_opt = iinfo->external_opt;
+
+ oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax;
+ oinfo->external_aux = iinfo->external_aux;
+
+ oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax;
+ oinfo->ss = iinfo->ss;
+
+ oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax;
+ oinfo->external_fdr = iinfo->external_fdr;
+
+ oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd;
+ oinfo->external_rfd = iinfo->external_rfd;
+ }
+ else
+ {
+ /* We are discarding all the local symbol information. Look
+ through the external symbols and remove all references to FDR
+ or aux information. */
+ c = bfd_get_symcount (obfd);
+ sym_ptr_ptr = bfd_get_outsymbols (obfd);
+ for (; c > 0; c--, sym_ptr_ptr++)
+ {
+ EXTR esym;
+
+ (*(ecoff_backend (obfd)->debug_swap.swap_ext_in))
+ (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym);
+ esym.ifd = ifdNil;
+ esym.asym.index = indexNil;
+ (*(ecoff_backend (obfd)->debug_swap.swap_ext_out))
+ (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native);
+ }
+ }
+
+ return true;
+}
+\f
/* Set the architecture. The supported architecture is stored in the
backend pointer. We always set the architecture anyhow, since many
callers ignore the return value. */
return arch == ecoff_backend (abfd)->arch;
}
-/* Get the size of the section headers. We do not output the .reginfo
- section. */
+/* Get the size of the section headers. */
/*ARGSUSED*/
int
{
asection *current;
int c;
+ int ret;
c = 0;
for (current = abfd->sections;
current != (asection *)NULL;
current = current->next)
- if (strcmp (current->name, REGINFO) != 0)
- ++c;
+ ++c;
- return (bfd_coff_filhsz (abfd)
- + bfd_coff_aoutsz (abfd)
- + c * bfd_coff_scnhsz (abfd));
+ ret = (bfd_coff_filhsz (abfd)
+ + bfd_coff_aoutsz (abfd)
+ + c * bfd_coff_scnhsz (abfd));
+ return BFD_ALIGN (ret, 16);
}
-/* 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. */
+/* Get the contents of a section. */
boolean
ecoff_get_section_contents (abfd, section, location, offset, count)
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, (size_t) count);
- return true;
+ return _bfd_generic_get_section_contents (abfd, section, location,
+ offset, count);
}
/* Calculate the file position for each section, and set
unsigned int alignment_power;
/* Only deal with sections which have contents */
- if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
- || strcmp (current->name, REGINFO) == 0)
+ if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
continue;
/* For the Alpha ECOFF .pdata section the lnnoptr field is
sofar = (sofar + round - 1) &~ (round - 1);
first_data = false;
}
+ else if (strcmp (current->name, _LIB) == 0)
+ {
+ const bfd_vma round = ecoff_backend (abfd)->round;
+ /* On Irix 4, the location of contents of the .lib section
+ from a shared library section is also rounded up to a
+ page boundary. */
+
+ sofar = (sofar + round - 1) &~ (round - 1);
+ }
/* Align the sections in the file to the same boundary on
which they are aligned in virtual memory. */
current != (asection *)NULL;
current = current->next)
{
- if (strcmp (current->name, REGINFO) == 0)
- continue;
if (current->reloc_count == 0)
current->rel_filepos = 0;
else
return reloc_size;
}
-/* 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. */
+/* Set the contents of a section. */
boolean
ecoff_set_section_contents (abfd, section, location, offset, count)
if (abfd->output_has_begun == false)
ecoff_compute_section_file_positions (abfd);
+ /* If this is a .lib section, bump the vma address so that it winds
+ up being the number of .lib sections output. This is right for
+ Irix 4. Ian Taylor <ian@cygnus.com>. */
+ if (strcmp (section->name, _LIB) == 0)
+ ++section->vma;
+
if (count == 0)
return true;
- if (strcmp (section->name, REGINFO) == 0)
+ if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+ || bfd_write (location, 1, count, abfd) != count)
+ return false;
+
+ return true;
+}
+
+/* Get the GP value for an ECOFF file. This is a hook used by
+ nlmconv. */
+
+bfd_vma
+bfd_ecoff_get_gp_value (abfd)
+ bfd *abfd;
+{
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
{
- ecoff_data_type *tdata = ecoff_data (abfd);
- struct ecoff_reginfo s;
- int i;
+ bfd_set_error (bfd_error_invalid_operation);
+ return 0;
+ }
+
+ return ecoff_data (abfd)->gp;
+}
- /* 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;
- }
+/* Set the GP value for an ECOFF file. This is a hook used by the
+ assembler. */
- /* 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, (size_t) count);
+boolean
+bfd_ecoff_set_gp_value (abfd, gp_value)
+ bfd *abfd;
+ bfd_vma gp_value;
+{
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
- 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;
+ ecoff_data (abfd)->gp = gp_value;
- return true;
+ return true;
+}
+
+/* Set the register masks for an ECOFF file. This is a hook used by
+ the assembler. */
+
+boolean
+bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
+ bfd *abfd;
+ unsigned long gprmask;
+ unsigned long fprmask;
+ unsigned long *cprmask;
+{
+ ecoff_data_type *tdata;
+
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
}
- if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
- || bfd_write (location, 1, count, abfd) != count)
- return false;
+ tdata = ecoff_data (abfd);
+ tdata->gprmask = gprmask;
+ tdata->fprmask = fprmask;
+ if (cprmask != (unsigned long *) NULL)
+ {
+ register int i;
+
+ for (i = 0; i < 3; i++)
+ tdata->cprmask[i] = cprmask[i];
+ }
return true;
}
ecoff_symbol_type *ecoff_sym_ptr;
bfd *input_bfd;
- /* Don't include debugging, local or section symbols. */
- if ((sym->flags & BSF_DEBUGGING) != 0
- || (sym->flags & BSF_LOCAL) != 0
- || (sym->flags & BSF_SECTION_SYM) != 0)
- return false;
-
if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour
|| ecoffsymbol (sym)->native == NULL)
{
+ /* Don't include debugging, local, or section symbols. */
+ if ((sym->flags & BSF_DEBUGGING) != 0
+ || (sym->flags & BSF_LOCAL) != 0
+ || (sym->flags & BSF_SECTION_SYM) != 0)
+ return false;
+
esym->jmptbl = 0;
esym->cobol_main = 0;
esym->weakext = 0;
ecoff_sym_ptr = ecoffsymbol (sym);
if (ecoff_sym_ptr->local)
- abort ();
+ return false;
input_bfd = bfd_asymbol_bfd (sym);
(*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in))
asection *current;
unsigned int count;
bfd_size_type reloc_size;
- unsigned long text_size;
- unsigned long text_start;
- unsigned long data_size;
- unsigned long data_start;
- unsigned long bss_size;
- PTR buff;
+ bfd_size_type text_size;
+ bfd_vma text_start;
+ boolean set_text_start;
+ bfd_size_type data_size;
+ bfd_vma data_start;
+ boolean set_data_start;
+ bfd_size_type bss_size;
+ PTR buff = NULL;
+ PTR reloc_buff = NULL;
struct internal_filehdr internal_f;
struct internal_aouthdr internal_a;
int i;
- bfd_error = system_call_error;
-
/* Determine where the sections and relocs will go in the output
file. */
reloc_size = ecoff_compute_reloc_file_positions (abfd);
current != (asection *)NULL;
current = current->next)
{
- if (strcmp (current->name, REGINFO) == 0)
- continue;
current->target_index = count;
++count;
}
else
text_size = 0;
text_start = 0;
+ set_text_start = false;
data_size = 0;
data_start = 0;
+ set_data_start = false;
bss_size = 0;
/* Write section headers to the file. */
- buff = (PTR) alloca (scnhsz);
+ /* Allocate buff big enough to hold a section header,
+ file header, or a.out header. */
+ {
+ bfd_size_type siz;
+ siz = scnhsz;
+ if (siz < filhsz)
+ siz = filhsz;
+ if (siz < aoutsz)
+ siz = aoutsz;
+ buff = (PTR) malloc (siz);
+ if (buff == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+ }
+
internal_f.f_nscns = 0;
if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0)
- return false;
+ goto error_return;
for (current = abfd->sections;
current != (asection *) NULL;
current = current->next)
struct internal_scnhdr section;
bfd_vma vma;
- if (strcmp (current->name, REGINFO) == 0)
- {
- BFD_ASSERT (current->reloc_count == 0);
- continue;
- }
-
++internal_f.f_nscns;
strncpy (section.s_name, current->name, sizeof section.s_name);
- /* FIXME: is this correct for shared libraries? I think it is
- but I have no platform to check. Ian Lance Taylor. */
+ /* This seems to be correct for Irix 4 shared libraries. */
vma = bfd_get_section_vma (abfd, current);
if (strcmp (current->name, _LIB) == 0)
section.s_vaddr = 0;
bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff);
if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
- return false;
+ goto error_return;
if ((section.s_flags & STYP_TEXT) != 0
|| ((section.s_flags & STYP_RDATA) != 0
|| strcmp (current->name, _PDATA) == 0)
{
text_size += bfd_get_section_size_before_reloc (current);
- if (text_start == 0 || text_start > vma)
- text_start = vma;
+ if (! set_text_start || text_start > vma)
+ {
+ text_start = vma;
+ set_text_start = true;
+ }
}
else if ((section.s_flags & STYP_RDATA) != 0
|| (section.s_flags & STYP_DATA) != 0
|| strcmp (current->name, _XDATA) == 0)
{
data_size += bfd_get_section_size_before_reloc (current);
- if (data_start == 0 || data_start > vma)
- data_start = vma;
+ if (! set_data_start || data_start > vma)
+ {
+ data_start = vma;
+ set_data_start = true;
+ }
}
else if ((section.s_flags & STYP_BSS) != 0
|| (section.s_flags & STYP_SBSS) != 0)
bss_size += bfd_get_section_size_before_reloc (current);
+ else if ((section.s_flags & STYP_ECOFF_LIB) != 0)
+ /* Do nothing */ ;
else
abort ();
}
/* Write out the file header and the optional header. */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- return false;
+ goto error_return;
- buff = (PTR) alloca (filhsz);
bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff);
if (bfd_write (buff, 1, filhsz, abfd) != filhsz)
- return false;
+ goto error_return;
- buff = (PTR) alloca (aoutsz);
bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff);
if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz)
- return false;
+ goto error_return;
/* Build the external symbol information. This must be done before
writing out the relocs so that we know the symbol indices. The
? true : false),
ecoff_get_extr, ecoff_set_index)
== false)
- return false;
+ goto error_return;
/* Write out the relocs. */
for (current = abfd->sections;
if (current->reloc_count == 0)
continue;
- buff = bfd_alloc (abfd, current->reloc_count * external_reloc_size);
- if (buff == NULL)
+ reloc_buff =
+ bfd_alloc (abfd, current->reloc_count * external_reloc_size);
+ if (reloc_buff == NULL)
{
- bfd_error = no_memory;
- return false;
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
}
reloc_ptr_ptr = current->orelocation;
reloc_end = reloc_ptr_ptr + current->reloc_count;
- out_ptr = (char *) buff;
+ out_ptr = (char *) reloc_buff;
for (;
reloc_ptr_ptr < reloc_end;
reloc_ptr_ptr++, out_ptr += external_reloc_size)
asymbol *sym;
struct internal_reloc in;
- memset (&in, 0, sizeof in);
+ memset ((PTR) &in, 0, sizeof in);
reloc = *reloc_ptr_ptr;
sym = *reloc->sym_ptr_ptr;
}
if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0)
- return false;
- if (bfd_write (buff, external_reloc_size, current->reloc_count, abfd)
+ goto error_return;
+ if (bfd_write (reloc_buff,
+ external_reloc_size, current->reloc_count, abfd)
!= external_reloc_size * current->reloc_count)
- return false;
- bfd_release (abfd, buff);
+ goto error_return;
+ bfd_release (abfd, reloc_buff);
+ reloc_buff = NULL;
}
/* Write out the symbolic debugging information. */
if (bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap,
ecoff_data (abfd)->sym_filepos)
== false)
- return false;
+ goto error_return;
}
- else if ((abfd->flags & EXEC_P) != 0
- && (abfd->flags & D_PAGED) != 0)
- {
- char c;
+ }
- /* A demand paged executable must occupy an even number of
- pages. */
- if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
- SEEK_SET) != 0)
- return false;
- if (bfd_read (&c, 1, 1, abfd) == 0)
- c = 0;
- if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
- SEEK_SET) != 0)
- return false;
- if (bfd_write (&c, 1, 1, abfd) != 1)
- return false;
- }
+ /* The .bss section of a demand paged executable must receive an
+ entire page. If there are symbols, the symbols will start on the
+ next page. If there are no symbols, we must fill out the page by
+ hand. */
+ if (bfd_get_symcount (abfd) == 0
+ && (abfd->flags & EXEC_P) != 0
+ && (abfd->flags & D_PAGED) != 0)
+ {
+ char c;
+
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
+ SEEK_SET) != 0)
+ goto error_return;
+ if (bfd_read (&c, 1, 1, abfd) == 0)
+ c = 0;
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
+ SEEK_SET) != 0)
+ goto error_return;
+ if (bfd_write (&c, 1, 1, abfd) != 1)
+ goto error_return;
}
+ if (reloc_buff != NULL)
+ bfd_release (abfd, reloc_buff);
+ if (buff != NULL)
+ free (buff);
return true;
+ error_return:
+ if (reloc_buff != NULL)
+ bfd_release (abfd, reloc_buff);
+ if (buff != NULL)
+ free (buff);
+ return false;
}
\f
/* Archive handling. ECOFF uses what appears to be a unique type of
if (i != 16)
return false;
- bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+ if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
+ return false;
/* Irix 4.0.5F apparently can use either an ECOFF armap or a
standard COFF armap. We could move the ECOFF armap stuff into
|| ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
^ (abfd->xvec->byteorder_big_p != false)))
{
- bfd_error = wrong_format;
+ bfd_set_error (bfd_error_wrong_format);
return false;
}
raw_armap = (char *) bfd_alloc (abfd, parsed_size);
if (raw_armap == (char *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
{
- bfd_error = malformed_archive;
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_malformed_archive);
bfd_release (abfd, (PTR) raw_armap);
return false;
}
symdef_ptr = ((struct symdef *)
bfd_alloc (abfd,
ardata->symdef_count * sizeof (struct symdef)));
+ if (!symdef_ptr)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
ardata->symdefs = (carsym *) symdef_ptr;
raw_ptr = raw_armap + 4;
return false;
hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
+ if (!hashtable)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
current = abfd->archive_head;
last_elt = current;
if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
|| strncmp (armag, ARMAG, SARMAG) != 0)
{
- bfd_error = wrong_format;
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
return (bfd_target *) NULL;
}
if (bfd_ardata (abfd) == (struct artdata *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return (bfd_target *) NULL;
}
if (ret == (struct ecoff_link_hash_entry *) NULL)
ret = ((struct ecoff_link_hash_entry *)
bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry)));
+ if (ret == (struct ecoff_link_hash_entry *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
/* Call the allocation method of the superclass. */
ret = ((struct ecoff_link_hash_entry *)
_bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
- /* Set local fields. */
- ret->indx = -1;
- ret->abfd = NULL;
- memset (&ret->esym, 0, sizeof ret->esym);
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->indx = -1;
+ ret->abfd = NULL;
+ }
+ memset ((PTR) &ret->esym, 0, sizeof ret->esym);
return (struct bfd_hash_entry *) ret;
}
malloc (sizeof (struct ecoff_link_hash_table)));
if (!ret)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return NULL;
}
if (! _bfd_link_hash_table_init (&ret->root, abfd,
case bfd_archive:
return ecoff_link_add_archive_symbols (abfd, info);
default:
- bfd_error = wrong_format;
+ bfd_set_error (bfd_error_wrong_format);
return false;
}
}
if (! bfd_has_map (abfd))
{
- bfd_error = no_symbols;
+ bfd_set_error (bfd_error_no_symbols);
return false;
}
= backend->debug_swap.swap_ext_in;
HDRR *symhdr;
bfd_size_type external_ext_size;
- PTR external_ext;
+ PTR external_ext = NULL;
size_t esize;
- char *ssext;
+ char *ssext = NULL;
char *ext_ptr;
char *ext_end;
*pneeded = false;
if (! ecoff_slurp_symbolic_header (abfd))
- return false;
+ goto error_return;
/* If there are no symbols, we don't want it. */
if (bfd_get_symcount (abfd) == 0)
- return true;
+ goto successful_return;
symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
/* Read in the external symbols and external strings. */
external_ext_size = backend->debug_swap.external_ext_size;
esize = symhdr->iextMax * external_ext_size;
- external_ext = (PTR) alloca (esize);
+ external_ext = (PTR) malloc (esize);
+ if (external_ext == NULL && esize != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0
|| bfd_read (external_ext, 1, esize, abfd) != esize)
- return false;
+ goto error_return;
+
+ ssext = (char *) malloc (symhdr->issExtMax);
+ if (ssext == NULL && symhdr->issExtMax != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
- ssext = (char *) alloca (symhdr->issExtMax);
if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
|| bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax)
- return false;
+ goto error_return;
/* Look through the external symbols to see if they define some
symbol that is currently undefined. */
/* Include this element. */
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
- return false;
+ goto error_return;
if (! ecoff_link_add_externals (abfd, info, external_ext, ssext))
- return false;
+ goto error_return;
*pneeded = true;
- return true;
+ goto successful_return;
}
+ successful_return:
+ if (external_ext != NULL)
+ free (external_ext);
+ if (ssext != NULL)
+ free (ssext);
return true;
+ error_return:
+ if (external_ext != NULL)
+ free (external_ext);
+ if (ssext != NULL)
+ free (ssext);
+ return false;
}
/* Add symbols from an ECOFF object file to the global linker hash
{
HDRR *symhdr;
bfd_size_type external_ext_size;
- PTR external_ext;
+ PTR external_ext = NULL;
size_t esize;
- char *ssext;
+ char *ssext = NULL;
+ boolean result;
if (! ecoff_slurp_symbolic_header (abfd))
return false;
/* Read in the external symbols and external strings. */
external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size;
esize = symhdr->iextMax * external_ext_size;
- external_ext = (PTR) alloca (esize);
+ external_ext = (PTR) malloc (esize);
+ if (external_ext == NULL && esize != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0
|| bfd_read (external_ext, 1, esize, abfd) != esize)
- return false;
+ goto error_return;
+
+ ssext = (char *) malloc (symhdr->issExtMax);
+ if (ssext == NULL && symhdr->issExtMax != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
- ssext = (char *) alloca (symhdr->issExtMax);
if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
|| bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax)
- return false;
-
- return ecoff_link_add_externals (abfd, info, external_ext, ssext);
+ goto error_return;
+
+ result = ecoff_link_add_externals (abfd, info, external_ext, ssext);
+
+ if (ssext != NULL)
+ free (ssext);
+ if (external_ext != NULL)
+ free (external_ext);
+ return result;
+
+ error_return:
+ if (ssext != NULL)
+ free (ssext);
+ if (external_ext != NULL)
+ free (external_ext);
+ return false;
}
/* Add the external symbols of an object file to the global linker
sym_hash = ((struct ecoff_link_hash_entry **)
bfd_alloc (abfd,
ext_count * sizeof (struct bfd_link_hash_entry *)));
+ if (!sym_hash)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
ecoff_data (abfd)->sym_hashes = sym_hash;
ext_ptr = (char *) external_ext;
name = ssext + esym.asym.iss;
+ h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_GLOBAL, section, value,
- (const char *) NULL, true, true, backend->constructor_bitsize,
+ (const char *) NULL, true, true,
(struct bfd_link_hash_entry **) &h)))
return false;
static boolean ecoff_indirect_link_order
PARAMS ((bfd *, struct bfd_link_info *, asection *,
struct bfd_link_order *));
+static boolean ecoff_reloc_link_order
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ struct bfd_link_order *));
/* ECOFF final link routine. This looks through all the input BFDs
and gathers together all the debugging information, and then
/* We accumulate the debugging information counts in the symbolic
header. */
symhdr = &debug->symbolic_header;
- symhdr->magic = backend->debug_swap.sym_magic;
symhdr->vstamp = 0;
symhdr->ilineMax = 0;
symhdr->cbLine = 0;
{
boolean ret;
- /* If we might be using the C based alloca function, dump memory
- allocated by ecoff_final_link_debug_accumulate. */
-#ifndef __GNUC__
-#ifndef alloca
- (void) alloca (0);
-#endif
-#endif
-
if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour)
{
/* Abitrarily set the symbolic header vstamp to the vstamp
p = p->next)
if (p->type == bfd_indirect_link_order)
o->reloc_count += p->u.indirect.section->reloc_count;
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
}
}
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
- /* Ignore any link_orders for the .reginfo section, which does
- not really exist. */
- if (strcmp (o->name, REGINFO) == 0)
- continue;
-
for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL;
p = p->next)
{
- /* If we might be using the C based alloca function, we need
- to dump the memory allocated by the function
- ecoff_indirect_link_order. */
-#ifndef __GNUC__
-#ifndef alloca
- (void) alloca (0);
-#endif
-#endif
if (p->type == bfd_indirect_link_order
&& (bfd_get_flavour (p->u.indirect.section->owner)
== bfd_target_ecoff_flavour))
if (! ecoff_indirect_link_order (abfd, info, o, p))
return false;
}
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! ecoff_reloc_link_order (abfd, info, o, p))
+ return false;
+ }
else
{
if (! _bfd_default_link_order (abfd, info, o, p))
debug->ptr = NULL; \
else \
{ \
- debug->ptr = (type) alloca (size * symhdr->count); \
+ debug->ptr = (type) malloc (size * symhdr->count); \
+ if (debug->ptr == NULL) \
+ { \
+ bfd_set_error (bfd_error_no_memory); \
+ ret = false; \
+ goto return_something; \
+ } \
if ((bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) \
!= 0) \
|| (bfd_read (debug->ptr, size, symhdr->count, \
input_bfd) != size * symhdr->count)) \
- return false; \
+ { \
+ ret = false; \
+ goto return_something; \
+ } \
}
- READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
- READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
- READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
- READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
- READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
- READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
- union aux_ext *);
- READ (ss, cbSsOffset, issMax, sizeof (char), char *);
- READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
- READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
+ /* If raw_syments is not NULL, then the data was already by read by
+ ecoff_slurp_symbolic_info. */
+ if (ecoff_data (input_bfd)->raw_syments == NULL)
+ {
+ READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
+ unsigned char *);
+ READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
+ READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
+ READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
+ READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
+ READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
+ union aux_ext *);
+ READ (ss, cbSsOffset, issMax, sizeof (char), char *);
+ READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
+ READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
+ }
#undef READ
/* We do not read the external strings or the external symbols. */
&ecoff_backend (output_bfd)->debug_swap,
input_bfd, debug, swap, info));
- /* Make sure we don't accidentally follow one of these pointers on
- to the stack. */
- debug->line = NULL;
- debug->external_dnr = NULL;
- debug->external_pdr = NULL;
- debug->external_sym = NULL;
- debug->external_opt = NULL;
- debug->external_aux = NULL;
- debug->ss = NULL;
- debug->external_fdr = NULL;
- debug->external_rfd = NULL;
+ return_something:
+ if (ecoff_data (input_bfd)->raw_syments == NULL)
+ {
+ if (debug->line != NULL)
+ free (debug->line);
+ if (debug->external_dnr != NULL)
+ free (debug->external_dnr);
+ if (debug->external_pdr != NULL)
+ free (debug->external_pdr);
+ if (debug->external_sym != NULL)
+ free (debug->external_sym);
+ if (debug->external_opt != NULL)
+ free (debug->external_opt);
+ if (debug->external_aux != NULL)
+ free (debug->external_aux);
+ if (debug->ss != NULL)
+ free (debug->ss);
+ if (debug->external_fdr != NULL)
+ free (debug->external_fdr);
+ if (debug->external_rfd != NULL)
+ free (debug->external_rfd);
+
+ /* Make sure we don't accidentally follow one of these pointers
+ into freed memory. */
+ debug->line = NULL;
+ debug->external_dnr = NULL;
+ debug->external_pdr = NULL;
+ debug->external_sym = NULL;
+ debug->external_opt = NULL;
+ debug->external_aux = NULL;
+ debug->ss = NULL;
+ debug->external_fdr = NULL;
+ debug->external_rfd = NULL;
+ }
return ret;
}
h->esym.reserved = 0;
h->esym.ifd = ifdNil;
h->esym.asym.value = 0;
- /* FIXME: we can do better than this for st and sc. */
h->esym.asym.st = stGlobal;
- h->esym.asym.sc = scAbs;
+
+ if (h->root.type != bfd_link_hash_defined)
+ h->esym.asym.sc = scAbs;
+ else
+ {
+ asection *output_section;
+ const char *name;
+
+ output_section = h->root.u.def.section->output_section;
+ name = bfd_section_name (output_section->owner, output_section);
+
+ if (strcmp (name, _TEXT) == 0)
+ h->esym.asym.sc = scText;
+ else if (strcmp (name, _DATA) == 0)
+ h->esym.asym.sc = scData;
+ else if (strcmp (name, _SDATA) == 0)
+ h->esym.asym.sc = scSData;
+ else if (strcmp (name, _RDATA) == 0)
+ h->esym.asym.sc = scRData;
+ else if (strcmp (name, _BSS) == 0)
+ h->esym.asym.sc = scBss;
+ else if (strcmp (name, _SBSS) == 0)
+ h->esym.asym.sc = scSBss;
+ else if (strcmp (name, _INIT) == 0)
+ h->esym.asym.sc = scInit;
+ else if (strcmp (name, _FINI) == 0)
+ h->esym.asym.sc = scFini;
+ else if (strcmp (name, _PDATA) == 0)
+ h->esym.asym.sc = scPData;
+ else if (strcmp (name, _XDATA) == 0)
+ h->esym.asym.sc = scXData;
+ else
+ h->esym.asym.sc = scAbs;
+ }
+
h->esym.asym.reserved = 0;
h->esym.asym.index = indexNil;
}
abort ();
case bfd_link_hash_undefined:
case bfd_link_hash_weak:
- if (h->esym.asym.st != scUndefined
- && h->esym.asym.st != scSUndefined)
- h->esym.asym.st = scUndefined;
+ if (h->esym.asym.sc != scUndefined
+ && h->esym.asym.sc != scSUndefined)
+ h->esym.asym.sc = scUndefined;
break;
case bfd_link_hash_defined:
if (h->esym.asym.sc == scUndefined
{
asection *input_section;
bfd *input_bfd;
- bfd_size_type input_size;
- bfd_byte *contents;
+ struct ecoff_section_tdata *section_tdata;
+ bfd_size_type raw_size;
+ bfd_size_type cooked_size;
+ bfd_byte *contents = NULL;
bfd_size_type external_reloc_size;
bfd_size_type external_relocs_size;
- PTR external_relocs;
+ PTR external_relocs = NULL;
BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
input_section = link_order->u.indirect.section;
input_bfd = input_section->owner;
+ section_tdata = ecoff_section_data (input_bfd, input_section);
+
+ raw_size = input_section->_raw_size;
+ cooked_size = input_section->_cooked_size;
+ if (cooked_size == 0)
+ cooked_size = raw_size;
BFD_ASSERT (input_section->output_section == output_section);
BFD_ASSERT (input_section->output_offset == link_order->offset);
- BFD_ASSERT (bfd_section_size (input_bfd, input_section) == link_order->size);
+ BFD_ASSERT (cooked_size == link_order->size);
+
+ /* Get the section contents. We allocate memory for the larger of
+ the size before relocating and the size after relocating. */
+ contents = (bfd_byte *) malloc (raw_size >= cooked_size
+ ? raw_size
+ : cooked_size);
+ if (contents == NULL && raw_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
- /* Get the section contents. */
- input_size = bfd_section_size (input_bfd, input_section);
- contents = (bfd_byte *) alloca (input_size);
- if (! bfd_get_section_contents (input_bfd, input_section, (PTR) contents,
- (file_ptr) 0, input_size))
- return false;
+ /* If we are relaxing, the contents may have already been read into
+ memory, in which case we copy them into our new buffer. We don't
+ simply reuse the old buffer in case cooked_size > raw_size. */
+ if (section_tdata != (struct ecoff_section_tdata *) NULL
+ && section_tdata->contents != (bfd_byte *) NULL)
+ memcpy (contents, section_tdata->contents, raw_size);
+ else
+ {
+ if (! bfd_get_section_contents (input_bfd, input_section,
+ (PTR) contents,
+ (file_ptr) 0, raw_size))
+ goto error_return;
+ }
- /* Get the relocs. */
+ /* Get the relocs. If we are relaxing MIPS code, they will already
+ have been read in. Otherwise, we read them in now. */
external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size;
external_relocs_size = external_reloc_size * input_section->reloc_count;
- external_relocs = (PTR) alloca (external_relocs_size);
- if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
- || (bfd_read (external_relocs, 1, external_relocs_size, input_bfd)
- != external_relocs_size))
- return false;
+
+ if (section_tdata != (struct ecoff_section_tdata *) NULL)
+ external_relocs = section_tdata->external_relocs;
+ else
+ {
+ external_relocs = (PTR) malloc (external_relocs_size);
+ if (external_relocs == NULL && external_relocs_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
+ if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (external_relocs, 1, external_relocs_size, input_bfd)
+ != external_relocs_size))
+ goto error_return;
+ }
/* Relocate the section contents. */
if (! ((*ecoff_backend (input_bfd)->relocate_section)
(output_bfd, info, input_bfd, input_section, contents,
external_relocs)))
- return false;
+ goto error_return;
/* Write out the relocated section. */
if (! bfd_set_section_contents (output_bfd,
output_section,
(PTR) contents,
input_section->output_offset,
- input_size))
- return false;
+ cooked_size))
+ goto error_return;
/* If we are producing relocateable output, the relocs were
modified, and we write them out now. We use the reloc_count
SEEK_SET) != 0
|| (bfd_write (external_relocs, 1, external_relocs_size, output_bfd)
!= external_relocs_size))
- return false;
+ goto error_return;
output_section->reloc_count += input_section->reloc_count;
}
+ if (contents != NULL)
+ free (contents);
+ if (external_relocs != NULL && section_tdata == NULL)
+ free (external_relocs);
return true;
+
+ error_return:
+ if (contents != NULL)
+ free (contents);
+ if (external_relocs != NULL && section_tdata == NULL)
+ free (external_relocs);
+ return false;
+}
+
+/* Generate a reloc when linking an ECOFF file. This is a reloc
+ requested by the linker, and does come from any input file. This
+ is used to build constructor and destructor tables when linking
+ with -Ur. */
+
+static boolean
+ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ asection *output_section;
+ struct bfd_link_order *link_order;
+{
+ arelent rel;
+ struct internal_reloc in;
+ bfd_size_type external_reloc_size;
+ bfd_byte *rbuf;
+ boolean ok;
+
+ /* We set up an arelent to pass to the backend adjust_reloc_out
+ routine. */
+ rel.address = link_order->offset;
+
+ rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (rel.howto == (const reloc_howto_type *) NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (link_order->type == bfd_section_reloc_link_order)
+ rel.sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr;
+ else
+ {
+ /* We can't set up a reloc against a symbol correctly, because
+ we have no asymbol structure. Currently no adjust_reloc_out
+ routine cases. */
+ rel.sym_ptr_ptr = (asymbol **) NULL;
+ }
+
+ /* All ECOFF relocs are in-place. Put the addend into the object
+ file. */
+
+ BFD_ASSERT (rel.howto->partial_inplace);
+ if (link_order->u.reloc.p->addend != 0)
+ {
+ bfd_size_type size;
+ bfd_reloc_status_type rstat;
+ bfd_byte *buf;
+ boolean ok;
+
+ size = bfd_get_reloc_size (rel.howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
+ if (buf == (bfd_byte *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ rstat = _bfd_relocate_contents (rel.howto, output_bfd,
+ link_order->u.reloc.p->addend, buf);
+ switch (rstat)
+ {
+ case bfd_reloc_ok:
+ break;
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ if (! ((*info->callbacks->reloc_overflow)
+ (info,
+ (link_order->type == bfd_section_reloc_link_order
+ ? bfd_section_name (output_bfd,
+ link_order->u.reloc.p->u.section)
+ : link_order->u.reloc.p->u.name),
+ rel.howto->name, link_order->u.reloc.p->addend,
+ (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
+ {
+ free (buf);
+ return false;
+ }
+ break;
+ }
+ ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
+ (file_ptr) link_order->offset, size);
+ free (buf);
+ if (! ok)
+ return false;
+ }
+
+ rel.addend = 0;
+
+ /* Move the information into a internal_reloc structure. */
+ in.r_vaddr = (rel.address
+ + bfd_get_section_vma (output_bfd, output_section));
+ in.r_type = rel.howto->type;
+
+ if (link_order->type == bfd_symbol_reloc_link_order)
+ {
+ struct ecoff_link_hash_entry *h;
+
+ h = ecoff_link_hash_lookup (ecoff_hash_table (info),
+ link_order->u.reloc.p->u.name,
+ false, false, true);
+ if (h != (struct ecoff_link_hash_entry *) NULL
+ && h->indx != -1)
+ in.r_symndx = h->indx;
+ else
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+ (asection *) NULL, (bfd_vma) 0)))
+ return false;
+ in.r_symndx = 0;
+ }
+ in.r_extern = 1;
+ }
+ else
+ {
+ CONST char *name;
+
+ name = bfd_get_section_name (output_bfd,
+ link_order->u.reloc.p->u.section);
+ if (strcmp (name, ".text") == 0)
+ in.r_symndx = RELOC_SECTION_TEXT;
+ else if (strcmp (name, ".rdata") == 0)
+ in.r_symndx = RELOC_SECTION_RDATA;
+ else if (strcmp (name, ".data") == 0)
+ in.r_symndx = RELOC_SECTION_DATA;
+ else if (strcmp (name, ".sdata") == 0)
+ in.r_symndx = RELOC_SECTION_SDATA;
+ else if (strcmp (name, ".sbss") == 0)
+ in.r_symndx = RELOC_SECTION_SBSS;
+ else if (strcmp (name, ".bss") == 0)
+ in.r_symndx = RELOC_SECTION_BSS;
+ else if (strcmp (name, ".init") == 0)
+ in.r_symndx = RELOC_SECTION_INIT;
+ else if (strcmp (name, ".lit8") == 0)
+ in.r_symndx = RELOC_SECTION_LIT8;
+ else if (strcmp (name, ".lit4") == 0)
+ in.r_symndx = RELOC_SECTION_LIT4;
+ else if (strcmp (name, ".xdata") == 0)
+ in.r_symndx = RELOC_SECTION_XDATA;
+ else if (strcmp (name, ".pdata") == 0)
+ in.r_symndx = RELOC_SECTION_PDATA;
+ else if (strcmp (name, ".fini") == 0)
+ in.r_symndx = RELOC_SECTION_FINI;
+ else if (strcmp (name, ".lita") == 0)
+ in.r_symndx = RELOC_SECTION_LITA;
+ else if (strcmp (name, "*ABS*") == 0)
+ in.r_symndx = RELOC_SECTION_ABS;
+ else
+ abort ();
+ in.r_extern = 0;
+ }
+
+ /* Let the BFD backend adjust the reloc. */
+ (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in);
+
+ /* Get some memory and swap out the reloc. */
+ external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
+ rbuf = (bfd_byte *) malloc (external_reloc_size);
+ if (rbuf == (bfd_byte *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
+ (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (PTR) rbuf);
+
+ ok = (bfd_seek (output_bfd,
+ (output_section->rel_filepos +
+ output_section->reloc_count * external_reloc_size),
+ SEEK_SET) == 0
+ && (bfd_write ((PTR) rbuf, 1, external_reloc_size, output_bfd)
+ == external_reloc_size));
+
+ if (ok)
+ ++output_section->reloc_count;
+
+ free (rbuf);
+
+ return ok;
}