Fixed bug in tc-i386.c which in rare but unpredictable circumstances would
screw up PC relative offsets to _GLOBAL_SYMBOL_TABLE_ (caused by me not quite understanding the inner workings of this phenomenon called `obstack'). Thanks to Thomas Eberhardt for creating rare and unpredictable circumstances. Changes to obj-aout.c to handle non-absolute `.size' expressions and to set the `n_other' field of symbols to the symbols type, as given by `.type' directives.
This commit is contained in:
parent
facd69a0ee
commit
7895f44731
|
@ -64,6 +64,12 @@ enum reloc_type {
|
||||||
#endif /* not TC_SPARC */
|
#endif /* not TC_SPARC */
|
||||||
NO_RELOC,
|
NO_RELOC,
|
||||||
|
|
||||||
|
#ifdef TC_I386
|
||||||
|
/* Used internally by gas */
|
||||||
|
RELOC_GOT,
|
||||||
|
RELOC_GOTOFF,
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* not TC_I860 */
|
#endif /* not TC_I860 */
|
||||||
#endif /* not TC_M88K */
|
#endif /* not TC_M88K */
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ const pseudo_typeS obj_pseudo_table[] = {
|
||||||
{ "scl", s_ignore, 0 },
|
{ "scl", s_ignore, 0 },
|
||||||
{ "size", s_size, 0 },
|
{ "size", s_size, 0 },
|
||||||
{ "tag", s_ignore, 0 },
|
{ "tag", s_ignore, 0 },
|
||||||
{ "type", s_ignore, 0 },
|
{ "type", s_type, 0 },
|
||||||
{ "val", s_ignore, 0 },
|
{ "val", s_ignore, 0 },
|
||||||
{ "version", s_ignore, 0 },
|
{ "version", s_ignore, 0 },
|
||||||
|
|
||||||
|
@ -228,9 +228,43 @@ symbolS *symbol_rootP;
|
||||||
temp = S_GET_NAME(symbolP);
|
temp = S_GET_NAME(symbolP);
|
||||||
S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
|
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. */
|
/* 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);
|
obj_symbol_to_chars(where, symbolP);
|
||||||
S_SET_NAME(symbolP,temp);
|
S_SET_NAME(symbolP,temp);
|
||||||
}
|
}
|
||||||
|
@ -458,6 +492,8 @@ object_headers *headers;
|
||||||
|
|
||||||
* symbols with no name (stabd's?)
|
* symbols with no name (stabd's?)
|
||||||
* symbols with debug info in their N_TYPE
|
* 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 don't are:
|
||||||
* symbols that are registers
|
* symbols that are registers
|
||||||
|
@ -506,31 +542,39 @@ object_headers *headers;
|
||||||
/*
|
/*
|
||||||
* If symbol has a known size, output an extra symbol
|
* If symbol has a known size, output an extra symbol
|
||||||
* of type N_SIZE and with the same name.
|
* 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']) {
|
if (flagseen['k'] &&
|
||||||
symbolS *addme;
|
S_GET_TYPE(symbolP) != N_SIZE &&
|
||||||
#ifdef USE_NSIZE_PREFIX /*XXX*/
|
#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];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
/*
|
buf[0] = NSIZE_PREFIX;
|
||||||
* Changed my mind, make name: "=symbol"
|
|
||||||
*/
|
|
||||||
buf[0] = '=';
|
|
||||||
strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2);
|
strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2);
|
||||||
addme = symbol_make(buf);
|
addme = symbol_make(buf);
|
||||||
#else
|
#else
|
||||||
addme = symbol_make(S_GET_NAME(symbolP));
|
addme = symbol_make(S_GET_NAME(symbolP));
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
/* Set type and transfer size expression */
|
||||||
S_SET_SEGMENT(addme, SEG_SIZE);
|
|
||||||
#endif
|
|
||||||
addme->sy_symbol.n_type = N_SIZE;
|
addme->sy_symbol.n_type = N_SIZE;
|
||||||
S_SET_VALUE(addme, symbolP->sy_size);
|
addme->sy_sizexp = symbolP->sy_sizexp;
|
||||||
/* Set external if symbolP is ? */
|
symbolP->sy_sizexp = NULL;
|
||||||
#if 1
|
|
||||||
|
/* Set external if symbolP is */
|
||||||
if (S_IS_EXTERN(symbolP))
|
if (S_IS_EXTERN(symbolP))
|
||||||
S_SET_EXTERNAL(addme);
|
S_SET_EXTERNAL(addme);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
symbolPP = &(symbol_next(symbolP));
|
symbolPP = &(symbol_next(symbolP));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
License along with GAS; see the file COPYING. If not, write
|
License along with GAS; see the file COPYING. If not, write
|
||||||
to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
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.2 1993/11/20 22:15:59 pk Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,9 @@ extern const segT N_TYPE_seg[];
|
||||||
#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC)
|
#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC)
|
||||||
#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */
|
#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */
|
||||||
|
|
||||||
|
/* First character of operand in `.type' directives */
|
||||||
|
#define TYPE_OPERAND_FMT '@'
|
||||||
|
|
||||||
/* SYMBOL TABLE */
|
/* SYMBOL TABLE */
|
||||||
/* Symbol table entry data type */
|
/* Symbol table entry data type */
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#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.4 1993/11/20 22:16:01 pk Exp $";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "as.h"
|
#include "as.h"
|
||||||
|
@ -1191,30 +1191,35 @@ char *line;
|
||||||
* Remember # of opcode bytes to put in pcrel_adjust
|
* Remember # of opcode bytes to put in pcrel_adjust
|
||||||
* for use in _GLOBAL_OFFSET_TABLE_ expressions.
|
* for use in _GLOBAL_OFFSET_TABLE_ expressions.
|
||||||
*/
|
*/
|
||||||
long opoffset = 0;
|
int nopbytes = 0;
|
||||||
if (flagseen['k'])
|
|
||||||
opoffset = obstack_next_free(&frags) - frag_now->fr_literal;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* First the prefix bytes. */
|
/* First the prefix bytes. */
|
||||||
for (q = i.prefix; q < i.prefix + i.prefixes; q++) {
|
for (q = i.prefix; q < i.prefix + i.prefixes; q++) {
|
||||||
p = frag_more (1);
|
p = frag_more (1);
|
||||||
|
nopbytes += 1;
|
||||||
md_number_to_chars (p, (unsigned int) *q, 1);
|
md_number_to_chars (p, (unsigned int) *q, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the opcode; be careful about word order here! */
|
/* Now the opcode; be careful about word order here! */
|
||||||
if (fits_in_unsigned_byte(t->base_opcode)) {
|
if (fits_in_unsigned_byte(t->base_opcode)) {
|
||||||
|
nopbytes += 1;
|
||||||
FRAG_APPEND_1_CHAR (t->base_opcode);
|
FRAG_APPEND_1_CHAR (t->base_opcode);
|
||||||
} else if (fits_in_unsigned_word(t->base_opcode)) {
|
} else if (fits_in_unsigned_word(t->base_opcode)) {
|
||||||
p = frag_more (2);
|
p = frag_more (2);
|
||||||
|
nopbytes += 2;
|
||||||
/* put out high byte first: can't use md_number_to_chars! */
|
/* put out high byte first: can't use md_number_to_chars! */
|
||||||
*p++ = (t->base_opcode >> 8) & 0xff;
|
*p++ = (t->base_opcode >> 8) & 0xff;
|
||||||
*p = t->base_opcode & 0xff;
|
*p = t->base_opcode & 0xff;
|
||||||
} else { /* opcode is either 3 or 4 bytes */
|
} else { /* opcode is either 3 or 4 bytes */
|
||||||
if (t->base_opcode & 0xff000000) {
|
if (t->base_opcode & 0xff000000) {
|
||||||
p = frag_more (4);
|
p = frag_more (4);
|
||||||
|
nopbytes += 4;
|
||||||
*p++ = (t->base_opcode >> 24) & 0xff;
|
*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 >> 16) & 0xff;
|
||||||
*p++ = (t->base_opcode >> 8) & 0xff;
|
*p++ = (t->base_opcode >> 8) & 0xff;
|
||||||
*p = (t->base_opcode ) & 0xff;
|
*p = (t->base_opcode ) & 0xff;
|
||||||
|
@ -1223,20 +1228,18 @@ char *line;
|
||||||
/* Now the modrm byte and base index byte (if present). */
|
/* Now the modrm byte and base index byte (if present). */
|
||||||
if (t->opcode_modifier & Modrm) {
|
if (t->opcode_modifier & Modrm) {
|
||||||
p = frag_more (1);
|
p = frag_more (1);
|
||||||
|
nopbytes += 1;
|
||||||
/* md_number_to_chars (p, i.rm, 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);
|
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)
|
/* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
|
||||||
==> need second modrm byte. */
|
==> need second modrm byte. */
|
||||||
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) {
|
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) {
|
||||||
p = frag_more (1);
|
p = frag_more (1);
|
||||||
|
nopbytes += 1;
|
||||||
/* md_number_to_chars (p, i.bi, 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);
|
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) {
|
if (i.disp_operands) {
|
||||||
register unsigned int n;
|
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);
|
i.disps[n]->X_add_number, 0, i.disp_reloc[n], i.disps[n]->X_got_symbol);
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
if (i.disps[n]->X_got_symbol) {
|
if (i.disps[n]->X_got_symbol) {
|
||||||
fixP->fx_pcrel_adjust = opoffset;
|
fixP->fx_pcrel_adjust = nopbytes;
|
||||||
opoffset = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1307,8 +1309,7 @@ char *line;
|
||||||
i.imms[n]->X_add_number, 0, NO_RELOC, i.imms[n]->X_got_symbol);
|
i.imms[n]->X_add_number, 0, NO_RELOC, i.imms[n]->X_got_symbol);
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
if (i.imms[n]->X_got_symbol) {
|
if (i.imms[n]->X_got_symbol) {
|
||||||
fixP->fx_pcrel_adjust = opoffset;
|
fixP->fx_pcrel_adjust = nopbytes;
|
||||||
opoffset = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1615,13 +1616,13 @@ char *operand_string;
|
||||||
strcat(tmpbuf, cp+1+3);
|
strcat(tmpbuf, cp+1+3);
|
||||||
*cp = '@';
|
*cp = '@';
|
||||||
} else if (strncmp(cp+1, "GOTOFF", 6) == 0) {
|
} 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';
|
*cp = '\0';
|
||||||
strcpy(tmpbuf, input_line_pointer);
|
strcpy(tmpbuf, input_line_pointer);
|
||||||
strcat(tmpbuf, cp+1+6);
|
strcat(tmpbuf, cp+1+6);
|
||||||
*cp = '@';
|
*cp = '@';
|
||||||
} else if (strncmp(cp+1, "GOT", 3) == 0) {
|
} 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';
|
*cp = '\0';
|
||||||
strcpy(tmpbuf, input_line_pointer);
|
strcpy(tmpbuf, input_line_pointer);
|
||||||
strcat(tmpbuf, cp+1+3);
|
strcat(tmpbuf, cp+1+3);
|
||||||
|
@ -1634,7 +1635,7 @@ char *operand_string;
|
||||||
#endif
|
#endif
|
||||||
exp_seg = expression(exp);
|
exp_seg = expression(exp);
|
||||||
#ifdef PIC
|
#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;
|
exp->X_add_symbol->sy_forceout = 1;
|
||||||
#endif
|
#endif
|
||||||
if (*input_line_pointer)
|
if (*input_line_pointer)
|
||||||
|
@ -2044,11 +2045,20 @@ relax_addressT segment_address_in_file;
|
||||||
r_symbolnum = fixP->fx_addsy->sy_number;
|
r_symbolnum = fixP->fx_addsy->sy_number;
|
||||||
extrn_bit = 1;
|
extrn_bit = 1;
|
||||||
break;
|
break;
|
||||||
case RELOC_GLOB_DAT:
|
case RELOC_GOT:
|
||||||
extra_bits = (1 << 4) & 0x10; /* r_baserel */
|
extra_bits = (1 << 4) & 0x10; /* r_baserel */
|
||||||
r_symbolnum = fixP->fx_addsy->sy_number;
|
r_symbolnum = fixP->fx_addsy->sy_number;
|
||||||
if (S_IS_EXTERNAL(fixP->fx_addsy))
|
if (!extrn_bit && !S_IS_EXTERNAL(fixP->fx_addsy))
|
||||||
extrn_bit = 1;
|
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 (extrn_bit || S_IS_EXTERNAL(fixP->fx_addsy))
|
||||||
|
as_warn("GOT relocation burb: `%s' should be static",
|
||||||
|
S_GET_NAME(fixP->fx_addsy));
|
||||||
break;
|
break;
|
||||||
case RELOC_JMP_TBL:
|
case RELOC_JMP_TBL:
|
||||||
extra_bits = (1 << 5) & 0x20; /* r_jmptable */
|
extra_bits = (1 << 5) & 0x20; /* r_jmptable */
|
||||||
|
|
Loading…
Reference in New Issue