64bit: Fix addends > 32 bits

If a symbolic reference is offsetted by a constant > 32bit
the backends can't deal with that, so don't construct such
values.
master
Michael Matz 2016-10-09 00:44:22 +02:00
parent a2a596e767
commit 235711f3d3
3 changed files with 27 additions and 2 deletions

View File

@ -1775,8 +1775,13 @@ static void gen_opic(int op)
/* symbol + constant case */ /* symbol + constant case */
if (op == '-') if (op == '-')
l2 = -l2; l2 = -l2;
l2 += vtop[-1].c.i;
/* The backends can't always deal with addends to symbols
larger than +-1<<31. Don't construct such. */
if ((int)l2 != l2)
goto general_case;
vtop--; vtop--;
vtop->c.i += l2; vtop->c.i = l2;
} else { } else {
general_case: general_case:
if (!nocode_wanted) { if (!nocode_wanted) {

View File

@ -2429,6 +2429,19 @@ void getmyaddress(void)
{ {
printf("in getmyaddress\n"); printf("in getmyaddress\n");
} }
#ifdef __LP64__
long __pa_symbol(void)
{
/* This 64bit constant was handled incorrectly, it was used as addend
(which can hold 64bit just fine) in connection with a symbol,
and TCC generates wrong code for that (displacements are 32bit only).
This effectively is "+ 0x80000000", and if addresses of globals
are below 2GB the result should be a number without high 32 bits set. */
return ((long)(((unsigned long)(&rel1))) - (0xffffffff80000000UL));
}
#endif
unsigned long theaddress = (unsigned long)getmyaddress; unsigned long theaddress = (unsigned long)getmyaddress;
void relocation_test(void) void relocation_test(void)
{ {
@ -2436,6 +2449,9 @@ void relocation_test(void)
printf("*rel1=%d\n", *rel1); printf("*rel1=%d\n", *rel1);
printf("*rel2=%d\n", *rel2); printf("*rel2=%d\n", *rel2);
fptr(); fptr();
#ifdef __LP64__
printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63);
#endif
} }
void old_style_f(a,b,c) void old_style_f(a,b,c)

View File

@ -349,6 +349,8 @@ void load(int r, SValue *sv)
fr = sv->r; fr = sv->r;
ft = sv->type.t & ~VT_DEFSIGN; ft = sv->type.t & ~VT_DEFSIGN;
fc = sv->c.i; fc = sv->c.i;
if (fc != sv->c.i && (fr & VT_SYM))
tcc_error("64 bit addend in load");
ft &= ~(VT_VOLATILE | VT_CONSTANT); ft &= ~(VT_VOLATILE | VT_CONSTANT);
@ -528,9 +530,11 @@ void store(int r, SValue *v)
v = pe_getimport(v, &v2); v = pe_getimport(v, &v2);
#endif #endif
fr = v->r & VT_VALMASK;
ft = v->type.t; ft = v->type.t;
fc = v->c.i; fc = v->c.i;
fr = v->r & VT_VALMASK; if (fc != v->c.i && (fr & VT_SYM))
tcc_error("64 bit addend in store");
ft &= ~(VT_VOLATILE | VT_CONSTANT); ft &= ~(VT_VOLATILE | VT_CONSTANT);
bt = ft & VT_BTYPE; bt = ft & VT_BTYPE;