Make gas generate our a.out format (for sparc and i386)

This commit is contained in:
kristerw 1998-09-13 13:28:24 +00:00
parent 45935a4c8d
commit b18f424e81
5 changed files with 264 additions and 6 deletions

View File

@ -65,6 +65,9 @@ const segT N_TYPE_seg[N_TYPE + 2] =
static void obj_aout_line PARAMS ((int));
static void obj_aout_weak PARAMS ((int));
static void obj_aout_type PARAMS ((int));
static void obj_aout_size PARAMS ((int));
int aout_pic_flag = 0;
const pseudo_typeS obj_pseudo_table[] =
{
@ -83,7 +86,7 @@ const pseudo_typeS obj_pseudo_table[] =
{"line", s_ignore, 0},
{"ln", s_ignore, 0},
{"scl", s_ignore, 0},
{"size", s_ignore, 0},
{"size", obj_aout_size, 0},
{"tag", s_ignore, 0},
{"val", s_ignore, 0},
{"version", s_ignore, 0},
@ -99,6 +102,54 @@ const pseudo_typeS obj_pseudo_table[] =
#ifdef BFD_ASSEMBLER
void
obj_aout_add_size_symbols()
{
/* We don't generate N_SIZE symbols unless we are working with PIC code. */
if (!aout_pic_flag)
return;
if (symbol_rootP)
{
symbolS *sym;
for (sym = symbol_rootP; sym; sym = symbol_next (sym))
{
int type, other;
type = S_GET_TYPE (sym);
other = S_GET_OTHER (sym);
/* We do only add SIZE symbols for objects (i.e other == 1)
that have a .size directive. */
if ((type != N_SIZE)
&& (type != (N_SIZE | N_EXT))
&& (other == 1)
&& ((expressionS*)sym->sy_sizexp != NULL))
{
expressionS *exp = (expressionS*)sym->sy_sizexp;
symbolS *new_sym;
int new_type;
long size;
new_type = N_SIZE;
if (type && N_EXT)
new_type |= N_EXT;
new_sym = symbol_make(S_GET_NAME(sym));
S_SET_TYPE(new_sym, new_type);
new_sym->bsym->section = bfd_abs_section_ptr;
new_sym->bsym->flags = sym->bsym->flags;
size = exp->X_add_number;
S_SET_VALUE(new_sym,size);
}
}
}
}
void
obj_aout_frob_symbol (sym, punt)
symbolS *sym;
@ -213,6 +264,14 @@ obj_aout_frob_file ()
(bfd_size_type) 1);
}
assert (x == true);
/* Some archetectures has a 'pic' flag in their a.out header. I'm not
sure this is the right place to set it, but this is the best hook
I have found... */
if (aout_pic_flag)
{
stdoutput->flags = BFD_PIC;
}
}
#else
@ -390,7 +449,7 @@ obj_aout_weak (ignore)
/* Handle .type. On {Net,Open}BSD, this is used to set the n_other field,
which is then apparently used when doing dynamic linking. Older
versions ogas ignored the .type pseudo-op, so we also ignore it if
versions of gas ignored the .type pseudo-op, so we also ignore it if
we can't parse it. */
static void
@ -403,7 +462,7 @@ obj_aout_type (ignore)
name = input_line_pointer;
c = get_symbol_end ();
sym = symbol_find (name);
sym = symbol_find_or_make (name);
*input_line_pointer = c;
if (sym != NULL)
{
@ -626,4 +685,113 @@ DEFUN_VOID (s_sect)
#endif /* ! BFD_ASSEMBLER */
static segT
get_segmented_expression (expP)
register expressionS *expP;
{
register segT retval;
retval = expression (expP);
if (expP->X_op == O_illegal
|| expP->X_op == O_absent
|| expP->X_op == O_big)
{
as_bad ("expected address expression; zero assumed");
expP->X_op = O_constant;
expP->X_add_number = 0;
retval = absolute_section;
}
return retval;
}
static segT
get_known_segmented_expression (expP)
register expressionS *expP;
{
register segT retval;
if ((retval = get_segmented_expression (expP)) == undefined_section)
{
/* There is no easy way to extract the undefined symbol from the
expression. */
if (expP->X_add_symbol != NULL
&& S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
as_warn ("symbol \"%s\" undefined; zero assumed",
S_GET_NAME (expP->X_add_symbol));
else
as_warn ("some symbol undefined; zero assumed");
retval = absolute_section;
expP->X_op = O_constant;
expP->X_add_number = 0;
}
know (retval == absolute_section || SEG_NORMAL (retval));
return (retval);
} /* get_known_segmented_expression() */
static void obj_aout_size(ignore)
int ignore;
{
register char *name;
register char c;
register char *p;
register int temp;
register symbolS *symbolP;
expressionS *exp;
segT seg;
segT retval;
/* SIZE_T is only used in PIC code. */
if (!aout_pic_flag)
{
s_ignore(0);
return;
}
SKIP_WHITESPACE();
name = input_line_pointer;
c = get_symbol_end();
/* just after name is now '\0' */
symbolP = symbol_find(name);
p = input_line_pointer;
*p = c;
if (symbolP == NULL || (S_GET_OTHER(symbolP) != 1))
{
/* Not an object. Ignore. */
/* XXX This assumes that the symbol is created before the .size
directive. */
s_ignore(0);
return;
}
SKIP_WHITESPACE();
if (*input_line_pointer != ',')
{
as_bad("Expected comma after symbol-name: rest of line ignored.");
ignore_rest_of_line();
return;
}
input_line_pointer ++; /* skip ',' */
exp = (expressionS *)xmalloc(sizeof(expressionS));
retval = get_known_segmented_expression(exp);
if (retval != absolute_section)
{
as_bad("Illegal .size expression");
ignore_rest_of_line();
return;
}
*p = 0;
symbolP = symbol_find_or_make(name);
*p = c;
if (symbolP->sy_sizexp) {
as_warn("\"%s\" already has a size", S_GET_NAME(symbolP));
} else
symbolP->sy_sizexp = (void *)exp;
demand_empty_rest_of_line();
} /* obj_aout_size() */
/* end of obj-aout.c */

View File

@ -232,4 +232,17 @@ void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT
#define AOUT_STABS
extern int aout_pic_flag;
#ifdef TE_NetBSD
extern void obj_aout_add_size_symbols PARAMS ((void));
#define TARGET_SYMBOL_FIELDS expressionS *sy_sizexp;
#define obj_frob_file_before_adjust() obj_aout_add_size_symbols ()
/* XXX This isn't the right thing to do... */
#define obj_fix_adjustable(X) (!(aout_pic_flag \
&& (S_IS_EXTERNAL (sym)) \
&& (strcmp(".data", sec->name) == 0)))
#endif /* TE_NetBSD */
/* end of obj-aout.h */

View File

@ -2342,8 +2342,19 @@ i386_operand (operand_string)
if ((cp = strchr (input_line_pointer,'@')) != NULL) {
char tmpbuf[BUFSIZ];
if(!GOT_symbol)
if(!GOT_symbol) {
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
/* gcc generates _GLOBAL_OFFSET_TABLE_, but an old
sun ld, that NetBSD by some reason wanted to be comatible
with, expexcted __GLOBAL_OFFSET_TABLE_. The problem
was solved this way in NetBSD's old gas. It should
probably be dealt with in libbfd... */
GOT_symbol
= symbol_find_or_make(NBSD_GLOBAL_OFFSET_TABLE_NAME);
#else
GOT_symbol = symbol_find_or_make(GLOBAL_OFFSET_TABLE_NAME);
#endif
}
if (strncmp(cp+1, "PLT", 3) == 0) {
i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32;
@ -2371,6 +2382,7 @@ i386_operand (operand_string)
#endif
exp_seg = expression (exp);
#if !(defined(TE_NetBSD) && defined(OBJ_AOUT)) /* XXX */
#ifdef BFD_ASSEMBLER
/* We do this to make sure that the section symbol is in
the symbol table. We will ultimately change the relocation
@ -2385,6 +2397,7 @@ i386_operand (operand_string)
exp->X_op_symbol = GOT_symbol;
i.disp_reloc[this_operand] = BFD_RELOC_32;
}
#endif
#endif
if (*input_line_pointer)
@ -2710,6 +2723,39 @@ md_apply_fix3 (fixP, valp, seg)
/* Fix a few things - the dynamic linker expects certain values here,
and we must not dissappoint it. */
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
if (fixP->fx_r_type == BFD_RELOC_32
&& GOT_symbol
&& fixP->fx_addsy == GOT_symbol)
{
fixP->fx_r_type = BFD_RELOC_386_GOTPC;
value += 1;
}
else if ((fixP->fx_r_type == BFD_RELOC_32)
&& aout_pic_flag
&& ((fixP->fx_addsy->bsym->flags & BSF_GLOBAL) != 0))
{
if (!bfd_is_com_section(bfd_get_section(fixP->fx_addsy->bsym)))
value = fixP->fx_offset - bfd_asymbol_value(fixP->fx_addsy->bsym);
}
switch(fixP->fx_r_type) {
case BFD_RELOC_386_PLT32:
break;
case BFD_RELOC_386_GOT32:
value = fixP->fx_offset;
break;
case BFD_RELOC_386_GOTPC:
value -= (fixP->fx_where + fixP->fx_frag->fr_address + 1);
break;
case BFD_RELOC_386_GOTOFF:
value = fixP->fx_offset;
break;
default:
break;
}
#endif
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& fixP->fx_addsy)
@ -2883,7 +2929,7 @@ parse_register (reg_string)
#ifdef OBJ_ELF
CONST char *md_shortopts = "kmVQ:";
#else
CONST char *md_shortopts = "m";
CONST char *md_shortopts = "mkK";
#endif
struct option md_longopts[] = {
{NULL, no_argument, NULL, 0}
@ -2916,6 +2962,12 @@ md_parse_option (c, arg)
case 'Q':
break;
#endif
#ifdef OBJ_AOUT
case 'k':
case 'K':
aout_pic_flag = 1;
break;
#endif
default:
return 0;
@ -2968,8 +3020,19 @@ md_undefined_symbol (name)
{
if(symbol_find(name))
as_bad("GOT already in symbol table");
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
/* gcc generates _GLOBAL_OFFSET_TABLE_, but an old
sun ld, that NetBSD by some reason wanted to be comatible
with, expexcted __GLOBAL_OFFSET_TABLE_. The problem
was solved this way in NetBSD's old gas. It should
probably be dealt with in libbfd... */
GOT_symbol = symbol_new (NBSD_GLOBAL_OFFSET_TABLE_NAME,
undefined_section,
(valueT) 0, &zero_address_frag);
#else
GOT_symbol = symbol_new (name, undefined_section,
(valueT) 0, &zero_address_frag);
#endif
};
return GOT_symbol;
}
@ -3052,6 +3115,17 @@ tc_gen_reloc (section, fixp)
switch(fixp->fx_r_type)
{
case BFD_RELOC_386_PLT32:
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
/* XXX */
if (fixp->fx_addsy != NULL)
{
asection *sec;
sec = bfd_get_section (fixp->fx_addsy->bsym);
if (strcmp(sec->name, ".text") == 0)
return 0;
}
#endif
/* FALLTHROUGH */
case BFD_RELOC_386_GOT32:
case BFD_RELOC_386_GOTOFF:
case BFD_RELOC_386_GOTPC:

View File

@ -382,6 +382,7 @@ base_index_byte;
#ifndef GLOBAL_OFFSET_TABLE_NAME
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
#endif
#define NBSD_GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
#ifdef BFD_ASSEMBLER
void i386_validate_fix PARAMS ((struct fix *));

View File

@ -2846,7 +2846,7 @@ print_insn (insn)
CONST char *md_shortopts = "A:K:VQ:sq";
#else
#ifdef OBJ_AOUT
CONST char *md_shortopts = "A:k";
CONST char *md_shortopts = "A:kK";
#else
CONST char *md_shortopts = "A:";
#endif
@ -2935,6 +2935,8 @@ md_parse_option (c, arg)
#ifdef OBJ_AOUT
case 'k':
case 'K':
aout_pic_flag = 1;
sparc_pic_code = 1;
break;
#endif