diff options
| author | kristerw <kristerw@NetBSD.org> | 1998-09-13 13:28:24 +0000 |
|---|---|---|
| committer | kristerw <kristerw@NetBSD.org> | 1998-09-13 13:28:24 +0000 |
| commit | b18f424e810c0dc52d76a361335da89cdbfd01a6 (patch) | |
| tree | 6cef9900205b76c7ca177200257e32f4395eb584 /gnu | |
| parent | 45935a4c8d5459a6a0972e191e25ab8d90f86b4c (diff) | |
Make gas generate our a.out format (for sparc and i386)
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/dist/gas/config/obj-aout.c | 174 | ||||
| -rw-r--r-- | gnu/dist/gas/config/obj-aout.h | 13 | ||||
| -rw-r--r-- | gnu/dist/gas/config/tc-i386.c | 78 | ||||
| -rw-r--r-- | gnu/dist/gas/config/tc-i386.h | 1 | ||||
| -rw-r--r-- | gnu/dist/gas/config/tc-sparc.c | 4 |
5 files changed, 264 insertions, 6 deletions
diff --git a/gnu/dist/gas/config/obj-aout.c b/gnu/dist/gas/config/obj-aout.c index bb566e1e374..d487f466ad5 100644 --- a/gnu/dist/gas/config/obj-aout.c +++ b/gnu/dist/gas/config/obj-aout.c @@ -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}, @@ -100,6 +103,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; int *punt; @@ -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 */ diff --git a/gnu/dist/gas/config/obj-aout.h b/gnu/dist/gas/config/obj-aout.h index ab47ab653a3..90099a5a815 100644 --- a/gnu/dist/gas/config/obj-aout.h +++ b/gnu/dist/gas/config/obj-aout.h @@ -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 */ diff --git a/gnu/dist/gas/config/tc-i386.c b/gnu/dist/gas/config/tc-i386.c index 3981a2d73a1..8b78a8383f8 100644 --- a/gnu/dist/gas/config/tc-i386.c +++ b/gnu/dist/gas/config/tc-i386.c @@ -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 @@ -2386,6 +2398,7 @@ i386_operand (operand_string) i.disp_reloc[this_operand] = BFD_RELOC_32; } #endif +#endif if (*input_line_pointer) as_bad ("Ignoring junk '%s' after expression", 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: diff --git a/gnu/dist/gas/config/tc-i386.h b/gnu/dist/gas/config/tc-i386.h index 8205f532054..e0a055d57dd 100644 --- a/gnu/dist/gas/config/tc-i386.h +++ b/gnu/dist/gas/config/tc-i386.h @@ -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 *)); diff --git a/gnu/dist/gas/config/tc-sparc.c b/gnu/dist/gas/config/tc-sparc.c index 2efad68e122..886b88e36d6 100644 --- a/gnu/dist/gas/config/tc-sparc.c +++ b/gnu/dist/gas/config/tc-sparc.c @@ -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 |
