Skip to content

Commit

Permalink
fix Win64 stack corruption
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Sep 25, 2012
1 parent 1ceefcf commit 2d58039
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
41 changes: 40 additions & 1 deletion src/backend/cgelem.c
Expand Up @@ -3955,7 +3955,44 @@ STATIC elem * elbyteint(elem *e)
}
return e;
}


/****************************
* Handle OPu64_d
*/

STATIC elem *elu64_d(elem *e)
{
if (e->E1->Eoper != OPconst && (I64 || (I32 && config.inline8087)))
{
/* Rewrite as:
* u >= 0 ? OPi64_d(u) : OPi64_d(u & 0x7FFF_FFFF_FFFF_FFFF) + 0x8000_0000_0000_0000
*/
elem *u = e->E1;
u->Ety = TYllong;
elem *u1 = el_copytree(u);
if (EOP(u))
fixside(&u, &u1);
elem *u2 = el_copytree(u1);

u = el_bin(OPge, TYint, u, el_long(TYllong, 0));

u1 = el_una(OPs64_d, e->Ety, u1);

u2 = el_bin(OPand, TYllong, u2, el_long(TYllong, 0x7FFFFFFFFFFFFFFFLL));
u2 = el_una(OPs64_d, e->Ety, u2);
elem *eadjust = el_una(OPu64_d, e->Ety, el_long(TYullong, 0x8000000000000000LL));
u2 = el_bin(OPadd, e->Ety, u2, eadjust);

e->Eoper = OPcond;
e->E1 = u;
e->E2 = el_bin(OPcolon, e->Ety, u1, u2);
return optelem(e, TRUE);
}
else
return evalu8(e);
}


/************************
* Handle <<, OProl and OPror
*/
Expand Down Expand Up @@ -4430,6 +4467,8 @@ STATIC elem * optelem(elem *e,HINT goal)
ex = ex->E1;
if (ex->Eoper == OPbit)
ex->E1 = optelem(ex->E1, leftgoal);
else if (e1->Eoper == OPu64_d)
e1->E1 = optelem(e1->E1, leftgoal);
else
e1 = e->E1 = optelem(e1,leftgoal);
}
Expand Down
20 changes: 20 additions & 0 deletions src/backend/cod1.c
Expand Up @@ -2029,6 +2029,10 @@ code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask)

Y(mST0,"_U64_LDBL"), // CLIBu64_ldbl
Y(mST0|mAX|mDX,"__LDBLULLNG"), // CLIBld_u64


Y(DOUBLEREGS_32,"__DBLULLNG"), // CLIBdblullng_win64
Y(DOUBLEREGS_32,"__ULLNGDBL"), // CLIBullngdbl_win64
};
#endif

Expand Down Expand Up @@ -2121,6 +2125,11 @@ code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask)

{mST0,mST0,0,INF32|INF64|INFfloat,2,1}, // _U64_LDBL
{0,mDX|mAX,0,INF32|INF64|INFfloat,1,2}, // __LDBLULLNG

#if TARGET_WINDOS
{0,mAX,0,INFfloat,2,2}, // __DBLULLNG CLIBdblullng_win64
{0,mAX,0,INFfloat,1,1}, // __ULLNGDBL CLIBullngdbl_win64
#endif
};

if (!clib_inited) /* if not initialized */
Expand Down Expand Up @@ -2178,6 +2187,17 @@ code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask)
#undef Z

assert(clib < CLIBMAX);
#if TARGET_WINDOS
if (config.exe == EX_WIN64)
{
switch (clib)
{
case CLIBdblullng: clib = CLIBdblullng_win64; break;
case CLIBullngdbl: clib = CLIBullngdbl_win64; break;
case CLIBu64_ldbl: assert(0); break;
}
}
#endif
symbol *s = &lib[clib];
if (I16)
assert(!(info[clib].flags & (INF32 | INF64)));
Expand Down
1 change: 1 addition & 0 deletions src/backend/cod3.c
Expand Up @@ -3436,6 +3436,7 @@ void epilog(block *b)
c = genc2(c,0xC2,0,4); // RET 4
}
else if (!typfunc(tym) || // if caller cleans the stack
config.exe == EX_WIN64 ||
Poffset == 0) // or nothing pushed on the stack anyway
{ op++; // to a regular RET
c = gen1(c,op);
Expand Down
6 changes: 6 additions & 0 deletions src/backend/code_x86.h
Expand Up @@ -352,6 +352,12 @@ enum CLIB
CLIBu64_ldbl,
CLIBld_u64,

#if TARGET_WINDOS
// Win64 versions
CLIBdblullng_win64,
CLIBullngdbl_win64,
#endif

CLIBMAX
};

Expand Down
2 changes: 1 addition & 1 deletion src/backend/optabgen.c
Expand Up @@ -605,7 +605,7 @@ void dotab()
case OPd_s64: X("d_s64", evalu8, cdcnvt);
case OPs64_d: X("s64_d", evalu8, cdcnvt);
case OPd_u64: X("d_u64", evalu8, cdcnvt);
case OPu64_d: X("u64_d", evalu8, cdcnvt);
case OPu64_d: X("u64_d", elu64_d, cdcnvt);
case OPld_u64: X("ld_u64", evalu8, cdcnvt);
case OPparam: X("param", elparam, cderr);
case OPsizeof: X("sizeof", elzot, cderr);
Expand Down

0 comments on commit 2d58039

Please sign in to comment.