/* Generic ECOFF (Extended-COFF) routines.
- Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
\f
/* This stuff is somewhat copied from coffcode.h. */
-static asection bfd_debug_section = { "*DEBUG*" };
+static asection bfd_debug_section =
+{
+ /* name, id, index, next, flags, user_set_vma, reloc_done, */
+ "*DEBUG*", 0, 0, NULL, 0, 0, 0,
+ /* linker_mark, linker_has_input, gc_mark, segment_mark, */
+ 0, 0, 0, 0,
+ /* vma, lma, _cooked_size, _raw_size, */
+ 0, 0, 0, 0,
+ /* output_offset, output_section, alignment_power, */
+ 0, NULL, 0,
+ /* relocation, orelocation, reloc_count, filepos, rel_filepos, */
+ NULL, NULL, 0, 0, 0,
+ /* line_filepos, userdata, contents, lineno, lineno_count, */
+ 0, NULL, NULL, NULL, 0,
+ /* entsize, comdat, kept_section, moving_line_filepos, */
+ 0, NULL, NULL, 0,
+ /* target_index, used_by_bfd, constructor_chain, owner, */
+ 0, NULL, NULL, NULL,
+ /* symbol, */
+ (struct symbol_cache_entry *) NULL,
+ /* symbol_ptr_ptr, */
+ (struct symbol_cache_entry **) NULL,
+ /* link_order_head, link_order_tail */
+ NULL, NULL
+};
/* Create an ECOFF object. */
boolean
_bfd_ecoff_new_section_hook (abfd, section)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *section;
{
- /* For the .pdata section, which has a special meaning on the Alpha,
- we set the alignment power to 3. We correct this later in
- ecoff_compute_section_file_positions. We do this hackery because
- we need to know the exact unaligned size of the .pdata section in
- order to set the lnnoptr field correctly. For every other
- section we use an alignment power of 4; this could be made target
- dependent by adding a field to ecoff_backend_data, but 4 appears
- to be correct for both the MIPS and the Alpha. */
- if (strcmp (section->name, _PDATA) == 0)
- section->alignment_power = 3;
- else
- section->alignment_power = 4;
+ section->alignment_power = 4;
- if (strcmp (section->name, _TEXT) == 0)
+ if (strcmp (section->name, _TEXT) == 0
+ || strcmp (section->name, _INIT) == 0
+ || strcmp (section->name, _FINI) == 0)
section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
else if (strcmp (section->name, _DATA) == 0
|| strcmp (section->name, _SDATA) == 0)
else if (strcmp (section->name, _RDATA) == 0
|| strcmp (section->name, _LIT8) == 0
|| strcmp (section->name, _LIT4) == 0
- || strcmp (section->name, _RCONST) == 0)
+ || strcmp (section->name, _RCONST) == 0
+ || strcmp (section->name, _PDATA) == 0)
section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
else if (strcmp (section->name, _BSS) == 0
|| strcmp (section->name, _SBSS) == 0)
}
else if (strcmp (name, _RCONST) == 0)
styp = STYP_RCONST;
- else if (flags & SEC_CODE)
+ else if (flags & SEC_CODE)
styp = STYP_TEXT;
- else if (flags & SEC_DATA)
+ else if (flags & SEC_DATA)
styp = STYP_DATA;
else if (flags & SEC_READONLY)
styp = STYP_RDATA;
/* Get the BFD flags to use for a section. */
-/*ARGSUSED*/
-flagword
-_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
- bfd *abfd;
+boolean
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name, section, flags_ptr)
+ bfd *abfd ATTRIBUTE_UNUSED;
PTR hdr;
- const char *name;
+ const char *name ATTRIBUTE_UNUSED;
+ asection *section ATTRIBUTE_UNUSED;
+ flagword * flags_ptr;
{
struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
long styp_flags = internal_s->s_flags;
- flagword sec_flags=0;
+ flagword sec_flags = 0;
if (styp_flags & STYP_NOLOAD)
sec_flags |= SEC_NEVER_LOAD;
}
else if ((styp_flags & STYP_BSS)
|| (styp_flags & STYP_SBSS))
- {
- sec_flags |= SEC_ALLOC;
- }
+ sec_flags |= SEC_ALLOC;
else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT)
- {
- sec_flags |= SEC_NEVER_LOAD;
- }
+ sec_flags |= SEC_NEVER_LOAD;
else if ((styp_flags & STYP_LITA)
|| (styp_flags & STYP_LIT8)
|| (styp_flags & STYP_LIT4))
- {
- sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
- }
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
else if (styp_flags & STYP_ECOFF_LIB)
- {
- sec_flags |= SEC_COFF_SHARED_LIBRARY;
- }
+ sec_flags |= SEC_COFF_SHARED_LIBRARY;
else
- {
- sec_flags |= SEC_ALLOC | SEC_LOAD;
- }
+ sec_flags |= SEC_ALLOC | SEC_LOAD;
- return sec_flags;
+ * flags_ptr = sec_flags;
+ return true;
}
\f
/* Read in the symbolic header for an ECOFF object file. */
HDRR *internal_symhdr;
/* See if we've already read it in. */
- if (ecoff_data (abfd)->debug_info.symbolic_header.magic ==
+ if (ecoff_data (abfd)->debug_info.symbolic_header.magic ==
backend->debug_swap.sym_magic)
return true;
object file. This is called by gdb via the read_debug_info entry
point in the backend structure. */
-/*ARGSUSED*/
boolean
_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)
bfd *abfd;
- asection *ignore;
+ asection *ignore ATTRIBUTE_UNUSED;
struct ecoff_debug_info *debug;
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
case N_SETD:
case N_SETB:
{
+ /* This code is no longer needed. It used to be used to
+ make the linker handle set symbols, but they are now
+ handled in the add_symbols routine instead. */
+#if 0
const char *name;
asection *section;
arelent_chain *reloc_chain;
section->constructor_chain = reloc_chain;
section->_raw_size += bitsize / 8;
+#endif /* 0 */
+
/* Mark the symbol as a constructor. */
asym->flags |= BSF_CONSTRUCTOR;
}
unsigned int ifd = rndx->rfd;
unsigned int indx = rndx->index;
const char *name;
-
+
if (ifd == 0xfff)
ifd = isym;
break;
default:
- sprintf (p1, "Unknown basic type %d", (int) basic_type);
+ sprintf (p1, _("Unknown basic type %d"), (int) basic_type);
break;
}
p1 += strlen (buffer1);
}
-
/*
* Deal with any qualifiers.
*/
int j;
/* Print array bounds reversed (ie, in the order the C
- programmer writes them). C is such a fun language.... */
+ programmer writes them). C is such a fun language.... */
while (i < 5 && qualifiers[i+1].type == tqArray)
i++;
/* Return information about ECOFF symbol SYMBOL in RET. */
-/*ARGSUSED*/
void
_bfd_ecoff_get_symbol_info (abfd, symbol, ret)
- bfd *abfd; /* Ignored. */
+ bfd *abfd ATTRIBUTE_UNUSED;
asymbol *symbol;
symbol_info *ret;
{
/* Return whether this is a local label. */
-/*ARGSUSED*/
boolean
-_bfd_ecoff_bfd_is_local_label (abfd, symbol)
- bfd *abfd;
- asymbol *symbol;
+_bfd_ecoff_bfd_is_local_label_name (abfd, name)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ const char *name;
{
- return symbol->name[0] == '$';
+ return name[0] == '$';
}
/* Print information about an ECOFF symbol. */
if (ecoffsymbol (symbol)->local)
{
SYMR ecoff_sym;
-
+
(*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
&ecoff_sym);
fprintf (file, "ecoff local ");
case stFile:
case stBlock:
- fprintf (file, "\n End+1 symbol: %ld",
+ fprintf (file, _("\n End+1 symbol: %ld"),
(long) (indx + sym_base));
break;
case stEnd:
if (ecoff_ext.asym.sc == scText
|| ecoff_ext.asym.sc == scInfo)
- fprintf (file, "\n First symbol: %ld",
+ fprintf (file, _("\n First symbol: %ld"),
(long) (indx + sym_base));
else
- fprintf (file, "\n First symbol: %ld",
+ fprintf (file, _("\n First symbol: %ld"),
((long)
(AUX_GET_ISYM (bigendian,
&aux_base[ecoff_ext.asym.index])
if (ECOFF_IS_STAB (&ecoff_ext.asym))
;
else if (ecoffsymbol (symbol)->local)
- fprintf (file, "\n End+1 symbol: %-7ld Type: %s",
+ 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, fdr, indx + 1));
else
- fprintf (file, "\n Local symbol: %ld",
+ fprintf (file, _("\n Local symbol: %ld"),
((long) indx
+ (long) sym_base
+ (ecoff_data (abfd)
break;
case stStruct:
- fprintf (file, "\n struct; End+1 symbol: %ld",
+ fprintf (file, _("\n struct; End+1 symbol: %ld"),
(long) (indx + sym_base));
break;
case stUnion:
- fprintf (file, "\n union; End+1 symbol: %ld",
+ fprintf (file, _("\n union; End+1 symbol: %ld"),
(long) (indx + sym_base));
break;
case stEnum:
- fprintf (file, "\n enum; End+1 symbol: %ld",
+ 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",
+ fprintf (file, _("\n Type: %s"),
ecoff_type_to_string (abfd, fdr, indx));
break;
}
if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
return false;
-
+
internal_relocs = (arelent *) bfd_alloc (abfd,
(sizeof (arelent)
* section->reloc_count));
{
unsigned int count;
- if (section->flags & SEC_CONSTRUCTOR)
+ if (section->flags & SEC_CONSTRUCTOR)
{
arelent_chain *chain;
*relptr++ = &chain->relent;
}
else
- {
+ {
arelent *tblptr;
if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
and return the name of the source file and the line nearest to the
wanted location. */
-/*ARGSUSED*/
boolean
_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
filename_ptr, functionname_ptr, retline_ptr)
bfd *abfd;
asection *section;
- asymbol **ignore_symbols;
+ asymbol **ignore_symbols ATTRIBUTE_UNUSED;
bfd_vma offset;
CONST char **filename_ptr;
CONST char **functionname_ptr;
size_t c;
boolean local;
- /* This function is selected based on the input vector. We only
- want to copy information over if the output BFD also uses ECOFF
+ /* We only want to copy information over if both BFD's use ECOFF
format. */
- if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
+ if (bfd_get_flavour (ibfd) != bfd_target_ecoff_flavour
+ || bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
return true;
/* Copy the GP value and the register masks. */
/* Get the size of the section headers. */
-/*ARGSUSED*/
int
_bfd_ecoff_sizeof_headers (abfd, reloc)
bfd *abfd;
- boolean reloc;
+ boolean reloc ATTRIBUTE_UNUSED;
{
asection *current;
int c;
c = 0;
for (current = abfd->sections;
- current != (asection *)NULL;
- current = current->next)
+ current != (asection *)NULL;
+ current = current->next)
++c;
ret = (bfd_coff_filhsz (abfd)
asection *current;
unsigned int i;
file_ptr old_sofar;
+ boolean rdata_in_text;
boolean first_data, first_nonalloc;
const bfd_vma round = ecoff_backend (abfd)->round;
qsort (sorted_hdrs, abfd->section_count, sizeof (asection *),
ecoff_sort_hdrs);
+ /* Some versions of the OSF linker put the .rdata section in the
+ text segment, and some do not. */
+ rdata_in_text = ecoff_backend (abfd)->rdata_in_text;
+ if (rdata_in_text)
+ {
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ current = sorted_hdrs[i];
+ if (strcmp (current->name, _RDATA) == 0)
+ break;
+ if ((current->flags & SEC_CODE) == 0
+ && strcmp (current->name, _PDATA) != 0
+ && strcmp (current->name, _RCONST) != 0)
+ {
+ rdata_in_text = false;
+ break;
+ }
+ }
+ }
+ ecoff_data (abfd)->rdata_in_text = rdata_in_text;
+
first_data = true;
first_nonalloc = true;
for (i = 0; i < abfd->section_count; i++)
supposed to indicate the number of .pdata entries that are
really in the section. Each entry is 8 bytes. We store this
away in line_filepos before increasing the section size. */
- if (strcmp (current->name, _PDATA) != 0)
- alignment_power = current->alignment_power;
- else
- {
- current->line_filepos = current->_raw_size / 8;
- alignment_power = 4;
- }
+ if (strcmp (current->name, _PDATA) == 0)
+ current->line_filepos = current->_raw_size / 8;
+
+ alignment_power = current->alignment_power;
/* On Ultrix, the data sections in an executable file must be
aligned to a page boundary within the file. This does not
&& (abfd->flags & D_PAGED) != 0
&& ! first_data
&& (current->flags & SEC_CODE) == 0
- && (! ecoff_backend (abfd)->rdata_in_text
+ && (! rdata_in_text
|| strcmp (current->name, _RDATA) != 0)
&& strcmp (current->name, _PDATA) != 0
&& strcmp (current->name, _RCONST) != 0)
abort ();
abfd->output_has_begun = true;
}
-
+
reloc_base = ecoff_data (abfd)->reloc_filepos;
reloc_size = 0;
for (current = abfd->sections;
- current != (asection *)NULL;
- current = current->next)
+ current != (asection *)NULL;
+ current = current->next)
{
if (current->reloc_count == 0)
current->rel_filepos = 0;
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
-
+
return ecoff_data (abfd)->gp;
}
count = 1;
for (current = abfd->sections;
- current != (asection *)NULL;
- current = current->next)
+ current != (asection *)NULL;
+ current = current->next)
{
current->target_index = count;
++count;
if ((section.s_flags & STYP_TEXT) != 0
|| ((section.s_flags & STYP_RDATA) != 0
- && backend->rdata_in_text)
+ && ecoff_data (abfd)->rdata_in_text)
|| section.s_flags == STYP_PDATA
|| (section.s_flags & STYP_DYNAMIC) != 0
|| (section.s_flags & STYP_LIBLIST) != 0
/* Do nothing */ ;
else
abort ();
- }
+ }
/* Set up the file header. */
arelent *reloc;
asymbol *sym;
struct internal_reloc in;
-
+
memset ((PTR) &in, 0, sizeof in);
reloc = *reloc_ptr_ptr;
{
unsigned int hash;
+ if (hlog == 0)
+ return 0;
hash = *s++;
while (*s != '\0')
hash = ((hash >> 27) | (hash << 5)) + *s++;
char *raw_ptr;
struct symdef *symdef_ptr;
char *stringbase;
-
+
/* Get the name of the first element. */
i = bfd_read ((PTR) nextname, 1, 16, abfd);
if (i == 0)
return false;
parsed_size = mapdata->parsed_size;
bfd_release (abfd, (PTR) mapdata);
-
+
raw_armap = (char *) bfd_alloc (abfd, parsed_size);
if (raw_armap == (char *) NULL)
return false;
-
+
if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_release (abfd, (PTR) raw_armap);
return false;
}
-
+
ardata->tdata = (PTR) raw_armap;
count = bfd_h_get_32 (abfd, (PTR) raw_armap);
{
unsigned int name_offset, file_offset;
unsigned int hash, rehash, srch;
-
+
name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
if (file_offset == 0)
/* Ultrix appears to use as a hash table size the least power of two
greater than twice the number of entries. */
- for (hashlog = 0; (1 << hashlog) <= 2 * orl_count; hashlog++)
+ for (hashlog = 0; ((unsigned int) 1 << hashlog) <= 2 * orl_count; hashlog++)
;
hashsize = 1 << hashlog;
padit = stridx % 2;
stringsize = stridx + padit;
- /* Include 8 bytes to store symdefsize and stringsize in output. */
+ /* Include 8 bytes to store symdefsize and stringsize in output. */
mapsize = symdefsize + stringsize + 8;
firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
armap. */
hdr.ar_uid[0] = '0';
hdr.ar_gid[0] = '0';
+#if 0
hdr.ar_mode[0] = '0';
+#else
+ /* Building gcc ends up extracting the armap as a file - twice. */
+ hdr.ar_mode[0] = '6';
+ hdr.ar_mode[1] = '4';
+ hdr.ar_mode[2] = '4';
+#endif
sprintf (hdr.ar_size, "%-10d", (int) mapsize);
/* Turn all null bytes in the header into spaces. */
for (i = 0; i < sizeof (struct ar_hdr); i++)
- if (((char *)(&hdr))[i] == '\0')
- (((char *)(&hdr))[i]) = ' ';
+ if (((char *) (&hdr))[i] == '\0')
+ (((char *) (&hdr))[i]) = ' ';
if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
!= sizeof (struct ar_hdr))
bfd_h_put_32 (abfd, (bfd_vma) hashsize, temp);
if (bfd_write ((PTR) temp, 1, 4, abfd) != 4)
return false;
-
+
hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
if (!hashtable)
return false;
hash = srch;
}
-
+
bfd_h_put_32 (abfd, (bfd_vma) map[i].namidx,
(PTR) (hashtable + hash * 8));
bfd_h_put_32 (abfd, (bfd_vma) firstreal,
_bfd_ecoff_archive_p (abfd)
bfd *abfd;
{
+ struct artdata *tdata_hold;
char armag[SARMAG + 1];
- if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
- || strncmp (armag, ARMAG, SARMAG) != 0)
+ tdata_hold = abfd->tdata.aout_ar_data;
+
+ if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_wrong_format);
return (const bfd_target *) NULL;
}
+ if (strncmp (armag, ARMAG, SARMAG) != 0)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
/* We are setting bfd_ardata(abfd) here, but since bfd_ardata
involves a cast, we can't do it as the left operand of
assignment. */
(struct artdata *) bfd_zalloc (abfd, sizeof (struct artdata));
if (bfd_ardata (abfd) == (struct artdata *) NULL)
- return (const bfd_target *) NULL;
+ {
+ abfd->tdata.aout_ar_data = tdata_hold;
+ return (const bfd_target *) NULL;
+ }
bfd_ardata (abfd)->first_file_filepos = SARMAG;
bfd_ardata (abfd)->cache = NULL;
bfd_ardata (abfd)->symdefs = NULL;
bfd_ardata (abfd)->extended_names = NULL;
bfd_ardata (abfd)->tdata = NULL;
-
+
if (_bfd_ecoff_slurp_armap (abfd) == false
|| _bfd_ecoff_slurp_extended_name_table (abfd) == false)
{
bfd_release (abfd, bfd_ardata (abfd));
- abfd->tdata.aout_ar_data = (struct artdata *) NULL;
+ abfd->tdata.aout_ar_data = tdata_hold;
return (const bfd_target *) NULL;
}
-
+
+ if (bfd_has_map (abfd))
+ {
+ bfd *first;
+
+ /* This archive has a map, so we may presume that the contents
+ are object files. Make sure that if the first file in the
+ archive can be recognized as an object file, it is for this
+ target. If not, assume that this is the wrong format. If
+ the first file is not an object file, somebody is doing
+ something weird, and we permit it so that ar -t will work. */
+
+ first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+ if (first != NULL)
+ {
+ boolean fail;
+
+ first->target_defaulted = false;
+ fail = false;
+ if (bfd_check_format (first, bfd_object)
+ && first->xvec != abfd->xvec)
+ {
+ (void) bfd_close (first);
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = tdata_hold;
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* We ought to close first here, but we can't, because we
+ have no way to remove it from the archive cache. FIXME. */
+ }
+ }
+
return abfd->xvec;
}
\f
bfd *output_bfd = einfo->abfd;
boolean strip;
- /* We need to check if this symbol is being stripped. */
+ /* We need to check if this symbol is being stripped. */
if (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
strip = false;
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)