binutils-gdb/gas/config/obj-coff.c
Ken Raeburn 8fb85d50cd * obj-coff.h (TARGET_FORMAT) [TC_I960]: Select little endian version.
* obj-coffbfd.h (TARGET_FORMAT) [TC_I960]: Ditto.

* obj-coff.c (coff_frob_section): Round up the size of every section to a
multiple of the alignment, so that BFD doesn't surprise us.

Eliminate many simple differences between the two COFF back ends:

* obj-coffbfd.c: Removed all uses of DEFUN and DEFUN_VOID.  Made minor
stylistic changes, deleted some register declarations.
(stack_top): Deleted.
(symbol_to_chars): Use absolute_section and reg_section instead of the
corresponding SEG_* symbols.
(obj_coff_endef, tag_find_or_make, fixup_segment): Likewise.
(stack typedef, stack_init, stack_delete, stack_push, stack_pop): Moved to just
after pseudo-op table.  All functions now static.
(stack_delete): Removed declaration.
(tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just after stack
functions.
* obj-coffbfd.h: Reordered some declarations and macros.
(stack_init, stack_delete, stack_push, stack_pop): Don't declare.
(stack typedef): Deleted.
(SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test.
(SYM_AUXENT): New macro.
(SA_GET_*, SA_SET_*): Define in terms of SYM_AUXENT when feasible.
(SF_GET_*, SF_SET_*): Define in terms of SF_GET when feasible.
(SA_GET_SYM_TAGNDX, SA_GET_SYM_ENDNDX, SA_SET_SYM_TAGNDX, SA_SET_SYM_ENDNDX,
object_headers typedef, data_section_header, text_section_header): Delete
non-BFD_HEADERS versions, since we always define that symbol now.

* obj-coff.c (stack_top): Deleted.
(obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size, obj_coff_scl,
obj_coff_tag, obj_coff_type, obj_coff_val): Change argument name from "ignored"
to "ignore".
(obj_coff_val): Use frag_now_fix.
(obj_pseudo_table): Removed IGNORE_DEBUG version, since it doesn't get used.
(stack typedef, stack_init, stack_delete, stack_push, stack_pop): Moved to just
after pseudo-op table.  All functions now static.
(tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just after stack
functions.
* obj-coff.h: Reordered some declarations and macros.  Protected against
multiple inclusions.
(stack_init, stack_delete, stack_push, stack_pop): Don't declare.
(stack typedef): Deleted.
(SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test.
(stdoutput): Deleted declaration.
(TARGET_FORMAT) [TC_I386]: Don't define if already defined.
1994-05-04 06:19:26 +00:00

1261 lines
31 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* coff object file format
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994
Free Software Foundation, Inc.
This file is part of GAS.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "as.h"
#include "obstack.h"
#include "subsegs.h"
static symbolS *tag_find_or_make PARAMS ((char *name));
static symbolS *tag_find PARAMS ((char *name));
static void tag_init PARAMS ((void));
static void tag_insert PARAMS ((const char *name, symbolS * symbolP));
const char *s_get_name PARAMS ((symbolS * s));
static void obj_coff_def PARAMS ((int));
static void obj_coff_dim PARAMS ((int));
static void obj_coff_endef PARAMS ((int));
static void obj_coff_line PARAMS ((int));
static void obj_coff_ln PARAMS ((int));
static void obj_coff_scl PARAMS ((int));
static void obj_coff_size PARAMS ((int));
static void obj_coff_tag PARAMS ((int));
static void obj_coff_type PARAMS ((int));
static void obj_coff_val PARAMS ((int));
static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *));
static struct hash_control *tag_hash;
static symbolS *def_symbol_in_progress;
const pseudo_typeS obj_pseudo_table[] =
{
{"def", obj_coff_def, 0},
{"dim", obj_coff_dim, 0},
{"endef", obj_coff_endef, 0},
{"line", obj_coff_line, 0},
{"ln", obj_coff_ln, 0},
{"appline", obj_coff_ln, 1},
{"scl", obj_coff_scl, 0},
{"size", obj_coff_size, 0},
{"tag", obj_coff_tag, 0},
{"type", obj_coff_type, 0},
{"val", obj_coff_val, 0},
{ "section", obj_coff_section, 0 },
{"ident", s_ignore, 0}, /* we don't yet handle this. */
{"optim", s_ignore, 0}, /* For sun386i cc (?) */
/* other stuff */
{"ABORT", s_abort, 0},
{NULL} /* end sentinel */
}; /* obj_pseudo_table */
/* stack stuff */
typedef struct
{
unsigned long chunk_size;
unsigned long element_size;
unsigned long size;
char *data;
unsigned long pointer;
}
stack;
static stack *
stack_init (chunk_size, element_size)
unsigned long chunk_size;
unsigned long element_size;
{
stack *st;
st = (stack *) malloc (sizeof (stack));
if (!st)
return 0;
st->data = malloc (chunk_size);
if (!st->data)
{
free (st);
return 0;
}
st->pointer = 0;
st->size = chunk_size;
st->chunk_size = chunk_size;
st->element_size = element_size;
return st;
}
static void
stack_delete (st)
stack *st;
{
free (st->data);
free (st);
}
static char *
stack_push (st, element)
stack *st;
char *element;
{
if (st->pointer + st->element_size >= st->size)
{
st->size += st->chunk_size;
if ((st->data = xrealloc (st->data, st->size)) == (char *) 0)
return (char *) 0;
}
memcpy (st->data + st->pointer, element, st->element_size);
st->pointer += st->element_size;
return st->data + st->pointer;
}
static char *
stack_pop (st)
stack *st;
{
if (st->pointer < st->element_size)
{
st->pointer = 0;
return (char *) 0;
}
st->pointer -= st->element_size;
return st->data + st->pointer;
}
/*
* Maintain a list of the tagnames of the structres.
*/
static void
tag_init ()
{
tag_hash = hash_new ();
}
static void
tag_insert (name, symbolP)
const char *name;
symbolS *symbolP;
{
const char *error_string;
if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
{
as_fatal ("Inserting \"%s\" into structure table failed: %s",
name, error_string);
}
}
static symbolS *
tag_find_or_make (name)
char *name;
{
symbolS *symbolP;
if ((symbolP = tag_find (name)) == NULL)
{
symbolP = symbol_new (name, undefined_section,
0, &zero_address_frag);
tag_insert (S_GET_NAME (symbolP), symbolP);
symbol_table_insert (symbolP);
} /* not found */
return symbolP;
}
static symbolS *
tag_find (name)
char *name;
{
#ifdef STRIP_UNDERSCORE
if (*name == '_')
name++;
#endif /* STRIP_UNDERSCORE */
return (symbolS *) hash_find (tag_hash, name);
}
struct line_no {
struct line_no *next;
fragS *frag;
alent l;
};
#define GET_FILENAME_STRING(X) \
((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
/* @@ Ick. */
static segT
fetch_coff_debug_section ()
{
static segT debug_section;
if (!debug_section)
{
CONST asymbol *s;
s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0);
assert (s != 0);
debug_section = s->section;
}
return debug_section;
}
void
SA_SET_SYM_ENDNDX (sym, val)
symbolS *sym;
symbolS *val;
{
combined_entry_type *entry, *p;
entry = &coffsymbol (sym->bsym)->native[1];
p = coffsymbol (val->bsym)->native;
entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
entry->fix_end = 1;
}
static void
SA_SET_SYM_TAGNDX (sym, val)
symbolS *sym;
symbolS *val;
{
combined_entry_type *entry, *p;
entry = &coffsymbol (sym->bsym)->native[1];
p = coffsymbol (val->bsym)->native;
entry->u.auxent.x_sym.x_tagndx.p = p;
entry->fix_tag = 1;
}
static int
S_GET_DATA_TYPE (sym)
symbolS *sym;
{
return coffsymbol (sym->bsym)->native->u.syment.n_type;
}
int
S_SET_DATA_TYPE (sym, val)
symbolS *sym;
int val;
{
coffsymbol (sym->bsym)->native->u.syment.n_type = val;
return val;
}
int
S_GET_STORAGE_CLASS (sym)
symbolS *sym;
{
return coffsymbol (sym->bsym)->native->u.syment.n_sclass;
}
int
S_SET_STORAGE_CLASS (sym, val)
symbolS *sym;
int val;
{
coffsymbol (sym->bsym)->native->u.syment.n_sclass = val;
return val;
}
/* Merge a debug symbol containing debug information into a normal symbol. */
void
c_symbol_merge (debug, normal)
symbolS *debug;
symbolS *normal;
{
S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
/* take the most we have */
S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
if (S_GET_NUMBER_AUXILIARY (debug) > 0)
{
/* Move all the auxiliary information. */
/* @@ How many fields do we want to preserve? Would it make more
sense to pick and choose those we want to copy? Should look
into this further.... [raeburn:19920512.2209EST] */
alent *linenos;
linenos = coffsymbol (normal->bsym)->lineno;
memcpy ((char *) &coffsymbol (normal->bsym)->native,
(char *) &coffsymbol (debug->bsym)->native,
S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
coffsymbol (normal->bsym)->lineno = linenos;
}
/* Move the debug flags. */
SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
}
static symbolS *previous_file_symbol;
void
c_dot_file_symbol (filename)
char *filename;
{
symbolS *symbolP;
symbolP = symbol_new (filename, &bfd_abs_section, 0,
&zero_address_frag);
S_SET_STORAGE_CLASS (symbolP, C_FILE);
S_SET_NUMBER_AUXILIARY (symbolP, 1);
symbolP->bsym->flags = BSF_DEBUGGING;
#ifndef NO_LISTING
{
extern int listing;
if (listing)
{
listing_source_file (filename);
}
}
#endif
S_SET_VALUE (symbolP, (long) previous_file_symbol);
previous_file_symbol = symbolP;
/* Make sure that the symbol is first on the symbol chain */
if (symbol_rootP != symbolP)
{
if (symbolP == symbol_lastP)
{
symbol_lastP = symbol_lastP->sy_previous;
} /* if it was the last thing on the list */
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
symbol_rootP = symbolP;
} /* if not first on the list */
}
/*
* Build a 'section static' symbol.
*/
char *
c_section_symbol (name, value, length, nreloc, nlnno)
char *name;
long value;
long length;
unsigned short nreloc;
unsigned short nlnno;
{
symbolS *symbolP;
symbolP = symbol_new (name,
(name[1] == 't'
? text_section
: name[1] == 'd'
? data_section
: bss_section),
value,
&zero_address_frag);
S_SET_STORAGE_CLASS (symbolP, C_STAT);
S_SET_NUMBER_AUXILIARY (symbolP, 1);
SA_SET_SCN_SCNLEN (symbolP, length);
SA_SET_SCN_NRELOC (symbolP, nreloc);
SA_SET_SCN_NLINNO (symbolP, nlnno);
SF_SET_STATICS (symbolP);
return (char *) symbolP;
}
/* Line number handling */
int coff_line_base;
/* Symbol of last function, which we should hang line#s off of. */
static symbolS *line_fsym;
#define in_function() (line_fsym != 0)
#define clear_function() (line_fsym = 0)
#define set_function(F) (line_fsym = (F), coff_add_linesym (F))
void
obj_symbol_new_hook (symbolP)
symbolS *symbolP;
{
char underscore = 0; /* Symbol has leading _ */
{
long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
char *s = (char *) bfd_alloc_by_size_t (stdoutput, sz);
memset (s, 0, sz);
coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s;
}
S_SET_DATA_TYPE (symbolP, T_NULL);
S_SET_STORAGE_CLASS (symbolP, 0);
S_SET_NUMBER_AUXILIARY (symbolP, 0);
if (S_IS_STRING (symbolP))
SF_SET_STRING (symbolP);
if (!underscore && S_IS_LOCAL (symbolP))
SF_SET_LOCAL (symbolP);
}
/*
* Handle .ln directives.
*/
static symbolS *current_lineno_sym;
static struct line_no *line_nos;
static void
add_lineno (frag, offset, num)
fragS *frag;
int offset;
int num;
{
struct line_no *new_line = (struct line_no *) bfd_alloc_by_size_t (stdoutput,
sizeof (struct line_no));
if (!current_lineno_sym)
{
abort ();
}
new_line->next = line_nos;
new_line->frag = frag;
new_line->l.line_number = num;
new_line->l.u.offset = offset;
line_nos = new_line;
}
void
coff_add_linesym (sym)
symbolS *sym;
{
if (line_nos)
{
add_lineno (0, 0, 0);
coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos;
line_nos = 0;
}
current_lineno_sym = sym;
}
static void
obj_coff_ln (appline)
int appline;
{
int l;
if (! appline && def_symbol_in_progress != NULL)
{
as_warn (".ln pseudo-op inside .def/.endef: ignored.");
demand_empty_rest_of_line ();
return;
}
l = get_absolute_expression ();
if (!appline)
{
add_lineno (frag_now, frag_now_fix (), l);
}
#ifndef NO_LISTING
{
extern int listing;
if (listing)
{
if (! appline)
l += coff_line_base - 1;
listing_source_line (l);
}
}
#endif
demand_empty_rest_of_line ();
}
/*
* def()
*
* Handle .def directives.
*
* One might ask : why can't we symbol_new if the symbol does not
* already exist and fill it with debug information. Because of
* the C_EFCN special symbol. It would clobber the value of the
* function symbol before we have a chance to notice that it is
* a C_EFCN. And a second reason is that the code is more clear this
* way. (at least I think it is :-).
*
*/
#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
*input_line_pointer == '\t') \
input_line_pointer++;
static void
obj_coff_def (what)
int what;
{
char name_end; /* Char after the end of name */
char *symbol_name; /* Name of the debug symbol */
char *symbol_name_copy; /* Temporary copy of the name */
unsigned int symbol_name_length;
if (def_symbol_in_progress != NULL)
{
as_warn (".def pseudo-op used inside of .def/.endef: ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
SKIP_WHITESPACES ();
symbol_name = input_line_pointer;
#ifdef STRIP_UNDERSCORE
if (symbol_name[0] == '_' && symbol_name[1] != 0)
symbol_name++;
#endif /* STRIP_UNDERSCORE */
name_end = get_symbol_end ();
symbol_name_length = strlen (symbol_name);
symbol_name_copy = xmalloc (symbol_name_length + 1);
strcpy (symbol_name_copy, symbol_name);
/* Initialize the new symbol */
def_symbol_in_progress = symbol_make (symbol_name_copy);
def_symbol_in_progress->sy_frag = &zero_address_frag;
S_SET_VALUE (def_symbol_in_progress, 0);
if (S_IS_STRING (def_symbol_in_progress))
SF_SET_STRING (def_symbol_in_progress);
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
}
unsigned int dim_index;
static void
obj_coff_endef (ignore)
int ignore;
{
symbolS *symbolP;
/* DIM BUG FIX sac@cygnus.com */
dim_index = 0;
if (def_symbol_in_progress == NULL)
{
as_warn (".endef pseudo-op used outside of .def/.endef: ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
/* Set the section number according to storage class. */
switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
{
case C_STRTAG:
case C_ENTAG:
case C_UNTAG:
SF_SET_TAG (def_symbol_in_progress);
/* intentional fallthrough */
case C_FILE:
case C_TPDEF:
SF_SET_DEBUG (def_symbol_in_progress);
S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
break;
case C_EFCN:
SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */
/* intentional fallthrough */
case C_BLOCK:
SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */
/* intentional fallthrough */
case C_FCN:
{
CONST char *name;
S_SET_SEGMENT (def_symbol_in_progress, text_section);
name = bfd_asymbol_name (def_symbol_in_progress->bsym);
if (name[1] == 'b' && name[2] == 'f')
{
if (! in_function ())
as_warn ("`%s' symbol without preceding function", name);
/* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/
/* Will need relocating */
SF_SET_PROCESS (def_symbol_in_progress);
clear_function ();
}
}
break;
#ifdef C_AUTOARG
case C_AUTOARG:
#endif /* C_AUTOARG */
case C_AUTO:
case C_REG:
case C_MOS:
case C_MOE:
case C_MOU:
case C_ARG:
case C_REGPARM:
case C_FIELD:
case C_EOS:
SF_SET_DEBUG (def_symbol_in_progress);
S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
break;
case C_EXT:
case C_STAT:
case C_LABEL:
/* Valid but set somewhere else (s_comm, s_lcomm, colon) */
break;
case C_USTATIC:
case C_EXTDEF:
case C_ULABEL:
as_warn ("unexpected storage class %d",
S_GET_STORAGE_CLASS (def_symbol_in_progress));
break;
} /* switch on storage class */
/* Now that we have built a debug symbol, try to find if we should
merge with an existing symbol or not. If a symbol is C_EFCN or
SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */
/* Two cases for functions. Either debug followed by definition or
definition followed by debug. For definition first, we will
merge the debug symbol into the definition. For debug first, the
lineno entry MUST point to the definition function or else it
will point off into space when obj_crawl_symbol_chain() merges
the debug symbol into the real symbol. Therefor, let's presume
the debug symbol is a real function reference. */
/* FIXME-SOON If for some reason the definition label/symbol is
never seen, this will probably leave an undefined symbol at link
time. */
if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
|| (!strcmp (bfd_get_section_name (stdoutput,
S_GET_SEGMENT (def_symbol_in_progress)),
"*DEBUG*")
&& !SF_GET_TAG (def_symbol_in_progress))
|| S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
|| (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL)
{
if (def_symbol_in_progress != symbol_lastP)
symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
&symbol_lastP);
}
else
{
/* This symbol already exists, merge the newly created symbol
into the old one. This is not mandatory. The linker can
handle duplicate symbols correctly. But I guess that it save
a *lot* of space if the assembly file defines a lot of
symbols. [loic] */
/* The debug entry (def_symbol_in_progress) is merged into the
previous definition. */
c_symbol_merge (def_symbol_in_progress, symbolP);
/* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
def_symbol_in_progress = symbolP;
if (SF_GET_FUNCTION (def_symbol_in_progress)
|| SF_GET_TAG (def_symbol_in_progress))
{
/* For functions, and tags, the symbol *must* be where the
debug symbol appears. Move the existing symbol to the
current place. */
/* If it already is at the end of the symbol list, do nothing */
if (def_symbol_in_progress != symbol_lastP)
{
symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
}
}
}
if (SF_GET_TAG (def_symbol_in_progress)
&& symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL)
{
tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
}
if (SF_GET_FUNCTION (def_symbol_in_progress))
{
know (sizeof (def_symbol_in_progress) <= sizeof (long));
set_function (def_symbol_in_progress);
SF_SET_PROCESS (def_symbol_in_progress);
if (symbolP == NULL)
{
/* That is, if this is the first time we've seen the
function... */
symbol_table_insert (def_symbol_in_progress);
} /* definition follows debug */
} /* Create the line number entry pointing to the function being defined */
def_symbol_in_progress = NULL;
demand_empty_rest_of_line ();
}
static void
obj_coff_dim (ignore)
int ignore;
{
int dim_index;
if (def_symbol_in_progress == NULL)
{
as_warn (".dim pseudo-op used outside of .def/.endef: ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
for (dim_index = 0; dim_index < DIMNUM; dim_index++)
{
SKIP_WHITESPACES ();
SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
get_absolute_expression ());
switch (*input_line_pointer)
{
case ',':
input_line_pointer++;
break;
default:
as_warn ("badly formed .dim directive ignored");
/* intentional fallthrough */
case '\n':
case ';':
dim_index = DIMNUM;
break;
}
}
demand_empty_rest_of_line ();
}
static void
obj_coff_line (ignore)
int ignore;
{
int this_base;
if (def_symbol_in_progress == NULL)
{
/* Probably stabs-style line? */
obj_coff_ln (0);
return;
}
this_base = get_absolute_expression ();
if (this_base > coff_line_base)
coff_line_base = this_base;
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
demand_empty_rest_of_line ();
}
static void
obj_coff_size (ignore)
int ignore;
{
if (def_symbol_in_progress == NULL)
{
as_warn (".size pseudo-op used outside of .def/.endef ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
demand_empty_rest_of_line ();
}
static void
obj_coff_scl (ignore)
int ignore;
{
if (def_symbol_in_progress == NULL)
{
as_warn (".scl pseudo-op used outside of .def/.endef ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
demand_empty_rest_of_line ();
}
static void
obj_coff_tag (ignore)
int ignore;
{
char *symbol_name;
char name_end;
if (def_symbol_in_progress == NULL)
{
as_warn (".tag pseudo-op used outside of .def/.endef ignored.");
demand_empty_rest_of_line ();
return;
}
S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
symbol_name = input_line_pointer;
name_end = get_symbol_end ();
/* Assume that the symbol referred to by .tag is always defined.
This was a bad assumption. I've added find_or_make. xoxorich. */
SA_SET_SYM_TAGNDX (def_symbol_in_progress,
tag_find_or_make (symbol_name));
if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
{
as_warn ("tag not found for .tag %s", symbol_name);
} /* not defined */
SF_SET_TAGGED (def_symbol_in_progress);
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
}
static void
obj_coff_type (ignore)
int ignore;
{
if (def_symbol_in_progress == NULL)
{
as_warn (".type pseudo-op used outside of .def/.endef ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
{
SF_SET_FUNCTION (def_symbol_in_progress);
} /* is a function */
demand_empty_rest_of_line ();
}
static void
obj_coff_val (ignore)
int ignore;
{
if (def_symbol_in_progress == NULL)
{
as_warn (".val pseudo-op used outside of .def/.endef ignored.");
demand_empty_rest_of_line ();
return;
} /* if not inside .def/.endef */
if (is_name_beginner (*input_line_pointer))
{
char *symbol_name = input_line_pointer;
char name_end = get_symbol_end ();
if (!strcmp (symbol_name, "."))
{
def_symbol_in_progress->sy_frag = frag_now;
S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
/* If the .val is != from the .def (e.g. statics) */
}
else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
{
def_symbol_in_progress->sy_value.X_op = O_symbol;
def_symbol_in_progress->sy_value.X_add_symbol =
symbol_find_or_make (symbol_name);
def_symbol_in_progress->sy_value.X_op_symbol = NULL;
def_symbol_in_progress->sy_value.X_add_number = 0;
/* If the segment is undefined when the forward reference is
resolved, then copy the segment id from the forward
symbol. */
SF_SET_GET_SEGMENT (def_symbol_in_progress);
}
/* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
*input_line_pointer = name_end;
}
else
{
S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
} /* if symbol based */
demand_empty_rest_of_line ();
}
void
obj_read_begin_hook ()
{
/* These had better be the same. Usually 18 bytes. */
#ifndef BFD_HEADERS
know (sizeof (SYMENT) == sizeof (AUXENT));
know (SYMESZ == AUXESZ);
#endif
tag_init ();
}
symbolS *coff_last_function;
void
coff_frob_symbol (symp, punt)
symbolS *symp;
int *punt;
{
static symbolS *last_tagP;
static stack *block_stack;
static symbolS *set_end;
if (symp == &abs_symbol)
{
*punt = 1;
return;
}
if (current_lineno_sym)
coff_add_linesym ((symbolS *) 0);
if (!block_stack)
block_stack = stack_init (512, sizeof (symbolS*));
if (!S_IS_DEFINED (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT)
S_SET_STORAGE_CLASS (symp, C_EXT);
if (!SF_GET_DEBUG (symp))
{
symbolS *real;
if (!SF_GET_LOCAL (symp)
&& (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
&& real != symp)
{
c_symbol_merge (symp, real);
*punt = 1;
}
if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
{
assert (S_GET_VALUE (symp) == 0);
S_SET_EXTERNAL (symp);
}
else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
{
if (S_GET_SEGMENT (symp) == text_section)
S_SET_STORAGE_CLASS (symp, C_LABEL);
else
S_SET_STORAGE_CLASS (symp, C_STAT);
}
if (SF_GET_PROCESS (symp))
{
if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
{
if (!strcmp (S_GET_NAME (symp), ".bb"))
stack_push (block_stack, (char *) &symp);
else
{
symbolS *begin;
begin = *(symbolS **) stack_pop (block_stack);
if (begin == 0)
as_warn ("mismatched .eb");
else
set_end = begin;
}
}
if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
{
union internal_auxent *auxp;
coff_last_function = symp;
if (S_GET_NUMBER_AUXILIARY (symp) < 1)
S_SET_NUMBER_AUXILIARY (symp, 1);
auxp = &coffsymbol (symp->bsym)->native[1].u.auxent;
memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
}
if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
{
if (coff_last_function == 0)
as_fatal ("C_EFCN symbol out of scope");
SA_SET_SYM_FSIZE (coff_last_function,
(long) (S_GET_VALUE (symp)
- S_GET_VALUE (coff_last_function)));
set_end = coff_last_function;
coff_last_function = 0;
}
}
else if (SF_GET_TAG (symp))
last_tagP = symp;
else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
set_end = last_tagP;
else if (S_GET_STORAGE_CLASS (symp) == C_FILE)
{
if (S_GET_VALUE (symp))
{
S_SET_VALUE ((symbolS *) S_GET_VALUE (symp), 0xdeadbeef);
S_SET_VALUE (symp, 0);
}
}
if (S_IS_EXTERNAL (symp))
S_SET_STORAGE_CLASS (symp, C_EXT);
else if (SF_GET_LOCAL (symp))
*punt = 1;
/* more ... */
}
if (set_end != (symbolS *) NULL
&& ! *punt)
{
SA_SET_SYM_ENDNDX (set_end, symp);
set_end = NULL;
}
if (coffsymbol (symp->bsym)->lineno)
{
int i, n;
struct line_no *lptr;
alent *l;
lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
for (i = 0; lptr; lptr = lptr->next)
i++;
n = i + 1;
lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
l = (alent *) bfd_alloc_by_size_t (stdoutput, n * sizeof (alent));
coffsymbol (symp->bsym)->lineno = l;
for (i = n - 1; i > 0; i--)
{
if (lptr->frag)
lptr->l.u.offset += lptr->frag->fr_address;
l[i] = lptr->l;
lptr = lptr->next;
}
}
}
/*
* implement the .section pseudo op:
* .section name {, "flags"}
* ^ ^
* | +--- optional flags: 'b' for bss
* | 'i' for info
* +-- section name 'l' for lib
* 'n' for noload
* 'o' for over
* 'w' for data
* 'd' (apparently m88k for data)
* 'x' for text
* But if the argument is not a quoted string, treat it as a
* subsegment number.
*/
void
obj_coff_section (ignore)
int ignore;
{
/* Strip out the section name */
char *section_name;
char c;
char *name;
unsigned int exp;
flagword flags;
asection *sec;
section_name = input_line_pointer;
c = get_symbol_end ();
name = xmalloc (input_line_pointer - section_name + 1);
strcpy (name, section_name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
exp = 0;
flags = SEC_NO_FLAGS;
if (*input_line_pointer == ',')
{
++input_line_pointer;
SKIP_WHITESPACE ();
if (*input_line_pointer != '"')
exp = get_absolute_expression ();
else
{
++input_line_pointer;
while (*input_line_pointer != '"'
&& ! is_end_of_line[(unsigned char) *input_line_pointer])
{
switch (*input_line_pointer)
{
case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break;
case 'n': flags &=~ SEC_LOAD; break;
case 'd':
case 'w': flags &=~ SEC_READONLY; break;
case 'x': flags |= SEC_CODE; break;
case 'i': /* STYP_INFO */
case 'l': /* STYP_LIB */
case 'o': /* STYP_OVER */
as_warn ("unsupported section attribute '%c'",
*input_line_pointer);
break;
default:
as_warn("unknown section attribute '%c'",
*input_line_pointer);
break;
}
++input_line_pointer;
}
if (*input_line_pointer == '"')
++input_line_pointer;
}
}
sec = subseg_new (name, (subsegT) exp);
if (flags != SEC_NO_FLAGS)
{
if (! bfd_set_section_flags (stdoutput, sec, flags))
as_warn ("error setting flags for \"%s\": %s",
bfd_section_name (stdoutput, sec),
bfd_errmsg (bfd_get_error ()));
}
}
void
coff_frob_file ()
{
if (symbol_rootP == NULL
|| S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
{
assert (previous_file_symbol == 0);
c_dot_file_symbol ("fake");
}
}
void
coff_frob_section (sec)
segT sec;
{
segT strsec;
char *strname, *p;
fragS *fragp;
bfd_vma size, n_entries, mask;
/* The COFF back end in BFD requires that all section sizes be
rounded up to multiples of the corresponding section alignments.
Seems kinda silly to me, but that's the way it is. */
size = bfd_get_section_size_before_reloc (sec);
assert (sec->alignment_power >= stdoutput->xvec->align_power_min);
mask = ((bfd_vma) 1 << (bfd_vma) sec->alignment_power) - 1;
if (size & mask)
bfd_set_section_size (stdoutput, sec, (size + mask) & ~mask);
/* @@ these should be in a "stabs.h" file, or maybe as.h */
#ifndef STAB_SECTION_NAME
#define STAB_SECTION_NAME ".stab"
#endif
#ifndef STAB_STRING_SECTION_NAME
#define STAB_STRING_SECTION_NAME ".stabstr"
#endif
if (strcmp (STAB_STRING_SECTION_NAME, sec->name))
return;
strsec = sec;
sec = subseg_get (STAB_SECTION_NAME, 0);
/* size is already rounded up, since other section will be listed first */
size = bfd_get_section_size_before_reloc (strsec);
n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1;
/* Find first non-empty frag. It should be large enough. */
fragp = seg_info (sec)->frchainP->frch_root;
while (fragp && fragp->fr_fix == 0)
fragp = fragp->fr_next;
assert (fragp != 0 && fragp->fr_fix >= 12);
/* Store the values. */
p = fragp->fr_literal;
bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
}
void
obj_coff_init_stab_section (seg)
segT seg;
{
char *file;
char *p;
char *stabstr_name;
unsigned int stroff;
/* Make space for this first symbol. */
p = frag_more (12);
/* Zero it out. */
memset (p, 0, 12);
as_where (&file, (unsigned int *) NULL);
stabstr_name = (char *) alloca (strlen (seg->name) + 4);
strcpy (stabstr_name, seg->name);
strcat (stabstr_name, "str");
stroff = get_stab_string_offset (file, stabstr_name);
know (stroff == 1);
md_number_to_chars (p, stroff, 4);
}
#ifdef DEBUG
/* for debugging */
const char *
s_get_name (s)
symbolS *s;
{
return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
}
void
symbol_dump ()
{
symbolS *symbolP;
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
{
printf("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n",
(unsigned long) symbolP,
S_GET_NAME(symbolP),
(long) S_GET_DATA_TYPE(symbolP),
S_GET_STORAGE_CLASS(symbolP),
(int) S_GET_SEGMENT(symbolP));
}
}
#endif /* DEBUG */
/* end of obj-coff.c */