Make gas generate our a.out format (for sparc and i386)
This commit is contained in:
parent
45935a4c8d
commit
b18f424e81
174
gnu/dist/gas/config/obj-aout.c
vendored
174
gnu/dist/gas/config/obj-aout.c
vendored
@ -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 */
|
||||
|
13
gnu/dist/gas/config/obj-aout.h
vendored
13
gnu/dist/gas/config/obj-aout.h
vendored
@ -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 */
|
||||
|
78
gnu/dist/gas/config/tc-i386.c
vendored
78
gnu/dist/gas/config/tc-i386.c
vendored
@ -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:
|
||||
|
1
gnu/dist/gas/config/tc-i386.h
vendored
1
gnu/dist/gas/config/tc-i386.h
vendored
@ -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 *));
|
||||
|
4
gnu/dist/gas/config/tc-sparc.c
vendored
4
gnu/dist/gas/config/tc-sparc.c
vendored
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user