diff options
author | jkh <jkh@FreeBSD.org> | 1993-11-30 20:57:41 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1993-11-30 20:57:41 +0000 |
commit | 901b86e422728e17ac5a7a0b44693603602d78ba (patch) | |
tree | abc7116a910b413253db9db73c91b52a645995f9 /gnu/usr.bin/as | |
parent | 90b65690ecd280ea567bd543c551a0d528447130 (diff) | |
download | FreeBSD-src-901b86e422728e17ac5a7a0b44693603602d78ba.zip FreeBSD-src-901b86e422728e17ac5a7a0b44693603602d78ba.tar.gz |
Latest from Paul K. for better checking of PIC code.
Diffstat (limited to 'gnu/usr.bin/as')
-rw-r--r-- | gnu/usr.bin/as/config/aout.h | 6 | ||||
-rw-r--r-- | gnu/usr.bin/as/config/obj-aout.c | 76 | ||||
-rw-r--r-- | gnu/usr.bin/as/config/obj-aout.h | 5 | ||||
-rw-r--r-- | gnu/usr.bin/as/config/tc-i386.c | 48 | ||||
-rw-r--r-- | gnu/usr.bin/as/read.c | 86 | ||||
-rw-r--r-- | gnu/usr.bin/as/read.h | 4 | ||||
-rw-r--r-- | gnu/usr.bin/as/struc-symbol.h | 9 | ||||
-rw-r--r-- | gnu/usr.bin/as/write.c | 4 |
8 files changed, 187 insertions, 51 deletions
diff --git a/gnu/usr.bin/as/config/aout.h b/gnu/usr.bin/as/config/aout.h index 4c9863b..23b085a 100644 --- a/gnu/usr.bin/as/config/aout.h +++ b/gnu/usr.bin/as/config/aout.h @@ -64,6 +64,12 @@ enum reloc_type { #endif /* not TC_SPARC */ NO_RELOC, +#ifdef TC_I386 + /* Used internally by gas */ + RELOC_GOT, + RELOC_GOTOFF, +#endif + #endif /* not TC_I860 */ #endif /* not TC_M88K */ }; diff --git a/gnu/usr.bin/as/config/obj-aout.c b/gnu/usr.bin/as/config/obj-aout.c index c0a470e..30eb2d1 100644 --- a/gnu/usr.bin/as/config/obj-aout.c +++ b/gnu/usr.bin/as/config/obj-aout.c @@ -99,7 +99,7 @@ const pseudo_typeS obj_pseudo_table[] = { { "scl", s_ignore, 0 }, { "size", s_size, 0 }, { "tag", s_ignore, 0 }, - { "type", s_ignore, 0 }, + { "type", s_type, 0 }, { "val", s_ignore, 0 }, { "version", s_ignore, 0 }, @@ -228,9 +228,43 @@ symbolS *symbol_rootP; temp = S_GET_NAME(symbolP); S_SET_OFFSET(symbolP, symbolP->sy_name_offset); + /* + * Put aux info in lower four bits of `n_other' field + * Do this only now, because things like S_IS_DEFINED() + * depend on S_GET_OTHER() for some unspecified reason. + */ + if (symbolP->sy_aux) + S_SET_OTHER(symbolP, (symbolP->sy_aux & 0xf)); + /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ - if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP)) S_SET_EXTERNAL(symbolP); + if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP)) + S_SET_EXTERNAL(symbolP); + if (S_GET_TYPE(symbolP) == N_SIZE) { + expressionS *exp = (expressionS*)symbolP->sy_sizexp; + long size = 0; + + if (exp == NULL) { + as_bad("Internal error: no size expression"); + return; + } + + switch (exp->X_seg) { + case SEG_ABSOLUTE: + size = exp->X_add_number; + break; + case SEG_DIFFERENCE: + size = S_GET_VALUE(exp->X_add_symbol) - + S_GET_VALUE(exp->X_subtract_symbol) + + exp->X_add_number; + break; + default: + as_bad("Unsupported .size expression"); + break; + } + S_SET_VALUE(symbolP, size); + } + obj_symbol_to_chars(where, symbolP); S_SET_NAME(symbolP,temp); } @@ -458,6 +492,8 @@ object_headers *headers; * symbols with no name (stabd's?) * symbols with debug info in their N_TYPE + * symbols marked "forceout" (to force out local `L' + symbols in PIC code) Symbols that don't are: * symbols that are registers @@ -506,31 +542,39 @@ object_headers *headers; /* * If symbol has a known size, output an extra symbol * of type N_SIZE and with the same name. + * We cannot evaluate the size expression just yet, as + * some its terms may not have had their final values + * set. We defer this until `obj_emit_symbols()' */ - if (symbolP->sy_size && flagseen['k']) { - symbolS *addme; -#ifdef USE_NSIZE_PREFIX /*XXX*/ + if (flagseen['k'] && + S_GET_TYPE(symbolP) != N_SIZE && +#ifndef GRACE_PERIOD_EXPIRED + /*Can be enabled when no more old ld's around*/ + (symbolP->sy_aux == AUX_OBJECT) && +#endif + symbolP->sy_sizexp) { + + symbolS *addme; + + /* Put a new symbol on the chain */ +#ifdef NSIZE_PREFIX /*XXX*/ char buf[BUFSIZ]; - /* - * Changed my mind, make name: "=symbol" - */ - buf[0] = '='; + buf[0] = NSIZE_PREFIX; strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2); addme = symbol_make(buf); #else addme = symbol_make(S_GET_NAME(symbolP)); #endif -#if 0 - S_SET_SEGMENT(addme, SEG_SIZE); -#endif + /* Set type and transfer size expression */ addme->sy_symbol.n_type = N_SIZE; - S_SET_VALUE(addme, symbolP->sy_size); - /* Set external if symbolP is ? */ -#if 1 + addme->sy_sizexp = symbolP->sy_sizexp; + symbolP->sy_sizexp = NULL; + + /* Set external if symbolP is */ if (S_IS_EXTERN(symbolP)) S_SET_EXTERNAL(addme); -#endif + } symbolPP = &(symbol_next(symbolP)); } else { diff --git a/gnu/usr.bin/as/config/obj-aout.h b/gnu/usr.bin/as/config/obj-aout.h index 4c91f9d..af3d9b0 100644 --- a/gnu/usr.bin/as/config/obj-aout.h +++ b/gnu/usr.bin/as/config/obj-aout.h @@ -17,7 +17,7 @@ License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id: obj-aout.h,v 1.1 1993/10/02 20:58:55 pk Exp $ + * $Id: obj-aout.h,v 1.1 1993/11/03 00:53:50 paul Exp $ */ @@ -39,6 +39,9 @@ extern const segT N_TYPE_seg[]; #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) #endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ +/* First character of operand in `.type' directives */ +#define TYPE_OPERAND_FMT '@' + /* SYMBOL TABLE */ /* Symbol table entry data type */ diff --git a/gnu/usr.bin/as/config/tc-i386.c b/gnu/usr.bin/as/config/tc-i386.c index 9a6e164..84848d2 100644 --- a/gnu/usr.bin/as/config/tc-i386.c +++ b/gnu/usr.bin/as/config/tc-i386.c @@ -25,7 +25,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: tc-i386.c,v 1.3 1993/10/27 00:14:50 pk Exp $"; +static char rcsid[] = "$Id: tc-i386.c,v 1.1 1993/11/03 00:54:23 paul Exp $"; #endif #include "as.h" @@ -1191,30 +1191,35 @@ char *line; * Remember # of opcode bytes to put in pcrel_adjust * for use in _GLOBAL_OFFSET_TABLE_ expressions. */ - long opoffset = 0; - if (flagseen['k']) - opoffset = obstack_next_free(&frags) - frag_now->fr_literal; + int nopbytes = 0; #endif /* First the prefix bytes. */ for (q = i.prefix; q < i.prefix + i.prefixes; q++) { p = frag_more (1); + nopbytes += 1; md_number_to_chars (p, (unsigned int) *q, 1); } /* Now the opcode; be careful about word order here! */ if (fits_in_unsigned_byte(t->base_opcode)) { + nopbytes += 1; FRAG_APPEND_1_CHAR (t->base_opcode); } else if (fits_in_unsigned_word(t->base_opcode)) { p = frag_more (2); + nopbytes += 2; /* put out high byte first: can't use md_number_to_chars! */ *p++ = (t->base_opcode >> 8) & 0xff; *p = t->base_opcode & 0xff; } else { /* opcode is either 3 or 4 bytes */ if (t->base_opcode & 0xff000000) { p = frag_more (4); + nopbytes += 4; *p++ = (t->base_opcode >> 24) & 0xff; - } else p = frag_more (3); + } else { + p = frag_more (3); + nopbytes += 3; + } *p++ = (t->base_opcode >> 16) & 0xff; *p++ = (t->base_opcode >> 8) & 0xff; *p = (t->base_opcode ) & 0xff; @@ -1223,20 +1228,18 @@ char *line; /* Now the modrm byte and base index byte (if present). */ if (t->opcode_modifier & Modrm) { p = frag_more (1); + nopbytes += 1; /* md_number_to_chars (p, i.rm, 1); */ md_number_to_chars (p, (i.rm.regmem<<0 | i.rm.reg<<3 | i.rm.mode<<6), 1); /* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode) ==> need second modrm byte. */ if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) { p = frag_more (1); + nopbytes += 1; /* md_number_to_chars (p, i.bi, 1); */ md_number_to_chars (p,(i.bi.base<<0 | i.bi.index<<3 | i.bi.scale<<6), 1); } } -#ifdef PIC - if (flagseen['k']) - opoffset = obstack_next_free(&frags) - frag_now->fr_literal - opoffset; -#endif if (i.disp_operands) { register unsigned int n; @@ -1264,8 +1267,7 @@ char *line; i.disps[n]->X_add_number, 0, i.disp_reloc[n], i.disps[n]->X_got_symbol); #ifdef PIC if (i.disps[n]->X_got_symbol) { - fixP->fx_pcrel_adjust = opoffset; - opoffset = 0; + fixP->fx_pcrel_adjust = nopbytes; } #endif } @@ -1307,8 +1309,7 @@ char *line; i.imms[n]->X_add_number, 0, NO_RELOC, i.imms[n]->X_got_symbol); #ifdef PIC if (i.imms[n]->X_got_symbol) { - fixP->fx_pcrel_adjust = opoffset; - opoffset = 0; + fixP->fx_pcrel_adjust = nopbytes; } #endif } @@ -1615,13 +1616,13 @@ char *operand_string; strcat(tmpbuf, cp+1+3); *cp = '@'; } else if (strncmp(cp+1, "GOTOFF", 6) == 0) { - i.disp_reloc[this_operand] = RELOC_GLOB_DAT; + i.disp_reloc[this_operand] = RELOC_GOTOFF; *cp = '\0'; strcpy(tmpbuf, input_line_pointer); strcat(tmpbuf, cp+1+6); *cp = '@'; } else if (strncmp(cp+1, "GOT", 3) == 0) { - i.disp_reloc[this_operand] = RELOC_GLOB_DAT; + i.disp_reloc[this_operand] = RELOC_GOT; *cp = '\0'; strcpy(tmpbuf, input_line_pointer); strcat(tmpbuf, cp+1+3); @@ -1634,7 +1635,7 @@ char *operand_string; #endif exp_seg = expression(exp); #ifdef PIC - if (i.disp_reloc[this_operand] == RELOC_GLOB_DAT) + if (i.disp_reloc[this_operand] == RELOC_GOTOFF) exp->X_add_symbol->sy_forceout = 1; #endif if (*input_line_pointer) @@ -2044,11 +2045,20 @@ relax_addressT segment_address_in_file; r_symbolnum = fixP->fx_addsy->sy_number; extrn_bit = 1; break; - case RELOC_GLOB_DAT: + case RELOC_GOT: + extra_bits = (1 << 4) & 0x10; /* r_baserel */ + r_symbolnum = fixP->fx_addsy->sy_number; + if (!extrn_bit && !S_IS_EXTERNAL(fixP->fx_addsy)) + as_warn("GOT relocation burb: `%s' should be global", + S_GET_NAME(fixP->fx_addsy)); + extrn_bit = 1; + break; + case RELOC_GOTOFF: extra_bits = (1 << 4) & 0x10; /* r_baserel */ r_symbolnum = fixP->fx_addsy->sy_number; - if (S_IS_EXTERNAL(fixP->fx_addsy)) - extrn_bit = 1; + if (extrn_bit || S_IS_EXTERNAL(fixP->fx_addsy)) + as_warn("GOT relocation burb: `%s' should be static", + S_GET_NAME(fixP->fx_addsy)); break; case RELOC_JMP_TBL: extra_bits = (1 << 5) & 0x20; /* r_jmptable */ diff --git a/gnu/usr.bin/as/read.c b/gnu/usr.bin/as/read.c index 61e9a3e..add26cc 100644 --- a/gnu/usr.bin/as/read.c +++ b/gnu/usr.bin/as/read.c @@ -19,7 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef lint -static char rcsid[] = "$Id: read.c,v 1.3 1993/10/02 20:57:51 pk Exp $"; +static char rcsid[] = "$Id: read.c,v 1.2 1993/11/03 00:52:11 paul Exp $"; #endif #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will @@ -1133,6 +1133,8 @@ void s_size() { register char *p; register int temp; register symbolS *symbolP; + expressionS *exp; + segT seg; name = input_line_pointer; c = get_symbol_end(); @@ -1146,28 +1148,90 @@ void s_size() { return; } input_line_pointer ++; /* skip ',' */ - if ((temp = get_absolute_expression()) < 0) { - as_warn(".size length (%d.) <0! Ignored.", temp); + if ((exp = (expressionS *)malloc(sizeof(expressionS))) == NULL) { + as_bad("Virtual memory exhausted"); + return; + } + switch (get_known_segmented_expression(exp)) { + case SEG_ABSOLUTE: + break; + case SEG_DIFFERENCE: + if (exp->X_add_symbol == NULL || exp->X_subtract_symbol == NULL + || S_GET_SEGMENT(exp->X_add_symbol) != + S_GET_SEGMENT(exp->X_subtract_symbol)) { + as_bad("Illegal .size expression"); + ignore_rest_of_line(); + return; + } + break; + default: + as_bad("Illegal .size expression"); ignore_rest_of_line(); return; } *p = 0; symbolP = symbol_find_or_make(name); *p = c; - if (S_IS_DEFINED(symbolP)) { - as_bad("Ignoring attempt to re-define symbol"); + 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(); +} /* s_size() */ + +void s_type() { + register char *name, *type; + register char c, c1; + register char *p; + register symbolS *symbolP; + int aux; + + name = input_line_pointer; + c = get_symbol_end(); + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + 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 ',' */ + SKIP_WHITESPACE(); + if (*input_line_pointer != TYPE_OPERAND_FMT) { + as_bad("Expected `%c' as start of operand: rest of line ignored.", TYPE_OPERAND_FMT); ignore_rest_of_line(); return; } - if (symbolP->sy_size && symbolP->sy_size != temp) { - as_bad("Size of .size \"%s\" is already %d. Not changed to %d.", - symbolP->sy_size, - temp); + input_line_pointer ++; /* skip '@' */ + type = input_line_pointer; + c1 = get_symbol_end(); + if (strcmp(type, "function") == 0) { + aux = AUX_FUNC; + } else if (strcmp(type, "object") == 0) { + aux = AUX_OBJECT; + } else { + as_warn("Unrecognized .type operand: \"%s\": rest of line ignored.", + type); + ignore_rest_of_line(); + return; + } + *input_line_pointer = c1; + + *p = 0; + symbolP = symbol_find_or_make(name); + *p = c; + + if (symbolP->sy_aux && symbolP->sy_aux != aux) { + as_bad("Type of \"%s\" is already %d. Not changed to %d.", + S_GET_NAME(symbolP), symbolP->sy_aux, aux); } else - symbolP->sy_size = temp; + symbolP->sy_aux = aux; demand_empty_rest_of_line(); -} /* s_size() */ +} /* s_type() */ void s_space() { long temp_repeat; diff --git a/gnu/usr.bin/as/read.h b/gnu/usr.bin/as/read.h index 5d8c391..b03fbab 100644 --- a/gnu/usr.bin/as/read.h +++ b/gnu/usr.bin/as/read.h @@ -18,7 +18,7 @@ along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id: read.h,v 1.3 1993/10/02 20:57:53 pk Exp $ + * $Id: read.h,v 1.2 1993/11/03 00:52:16 paul Exp $ */ @@ -95,6 +95,7 @@ void s_set(void); void s_size(void); void s_space(void); void s_text(void); +void s_type(void); #else /* not __STDC__ */ @@ -134,6 +135,7 @@ void s_set(); void s_size(); void s_space(); void s_text(); +void s_type(); #endif /* not __STDC__ */ diff --git a/gnu/usr.bin/as/struc-symbol.h b/gnu/usr.bin/as/struc-symbol.h index 787bcfe..e0030cd 100644 --- a/gnu/usr.bin/as/struc-symbol.h +++ b/gnu/usr.bin/as/struc-symbol.h @@ -17,7 +17,7 @@ along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id: struc-symbol.h,v 1.4 1993/10/02 20:57:53 pk Exp $ + * $Id: struc-symbol.h,v 1.2 1993/11/03 00:52:18 paul Exp $ */ @@ -47,7 +47,12 @@ struct symbol /* our version of an nlist node */ int sy_forceout; #endif /* Size of symbol as given by the .size directive */ - int sy_size; + void *sy_sizexp; /* (expressionS *) */ + + /* Auxiliary type information as given by the .type directive */ + int sy_aux; +#define AUX_OBJECT 1 +#define AUX_FUNC 2 }; typedef struct symbol symbolS; diff --git a/gnu/usr.bin/as/write.c b/gnu/usr.bin/as/write.c index 7cb1808..0658ac6 100644 --- a/gnu/usr.bin/as/write.c +++ b/gnu/usr.bin/as/write.c @@ -21,7 +21,7 @@ /* This thing should be set up to do byteordering correctly. But... */ #ifndef lint -static char rcsid[] = "$Id: write.c,v 1.6 1993/10/27 00:14:14 pk Exp $"; +static char rcsid[] = "$Id: write.c,v 1.2 1993/11/03 00:52:28 paul Exp $"; #endif #include "as.h" @@ -1065,6 +1065,8 @@ segT this_segment_type; /* N_TYPE bits for segment. */ */ if (!flagseen['k'] || (fixP->fx_r_type != RELOC_GLOB_DAT && + fixP->fx_r_type != RELOC_GOT && + fixP->fx_r_type != RELOC_GOTOFF && (fixP->fx_r_type != RELOC_32 || !S_IS_EXTERNAL(add_symbolP)))) #endif |