summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/as
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1993-11-30 20:57:41 +0000
committerjkh <jkh@FreeBSD.org>1993-11-30 20:57:41 +0000
commit901b86e422728e17ac5a7a0b44693603602d78ba (patch)
treeabc7116a910b413253db9db73c91b52a645995f9 /gnu/usr.bin/as
parent90b65690ecd280ea567bd543c551a0d528447130 (diff)
downloadFreeBSD-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.h6
-rw-r--r--gnu/usr.bin/as/config/obj-aout.c76
-rw-r--r--gnu/usr.bin/as/config/obj-aout.h5
-rw-r--r--gnu/usr.bin/as/config/tc-i386.c48
-rw-r--r--gnu/usr.bin/as/read.c86
-rw-r--r--gnu/usr.bin/as/read.h4
-rw-r--r--gnu/usr.bin/as/struc-symbol.h9
-rw-r--r--gnu/usr.bin/as/write.c4
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
OpenPOWER on IntegriCloud