You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
6.0 KiB
249 lines
6.0 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
/*
|
|
* A test which includes a large number of different push instructions.
|
|
*
|
|
* The idea is that we validate their behaviour here, so that we can check
|
|
* that they're still working correctly when we rewrite their addressing
|
|
* with Pin.
|
|
*
|
|
* Code assumes Gcc inline asm, so won't run on Windows.
|
|
* This shouldn't matter, since none of the rewriting is OS dependent.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
extern void * pushIW_(void *stack);
|
|
|
|
typedef long int addrint;
|
|
|
|
/* Macros for building test routines. */
|
|
#define switchStack(newSP) \
|
|
__asm__ ("mov %0,%%esp": :"r"(newSP): "%esp")
|
|
|
|
#define readStack(SP) \
|
|
__asm__ ("mov %%esp,%0": "=r"(SP) :: "%esp")
|
|
|
|
static void * pushI(void *stack)
|
|
{
|
|
// Don't use anything on the stack, since we're about to switch esp.
|
|
// (Since they're normally addressed relative to ebp locals should be OK,
|
|
// but this is safest)
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pushl $99");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
static void * pushIW(void *stack)
|
|
{
|
|
// Don't use anything on the stack, since we're about to switch esp.
|
|
// (Since they're normally addressed relative to ebp locals should be OK,
|
|
// but this is safest)
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pushw $-5");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
static void * pushSP(void *stack)
|
|
{
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pushl %esp");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
static void * pushSPIndirect(void *stack)
|
|
{
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pushl (%esp)");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
/* Can't easily check the results for this one, but at least we can
|
|
* see that the correct number of things were pushed.
|
|
*/
|
|
static void * pushA(void *stack)
|
|
{
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pusha");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
/* Can't easily check the results for this one, but at least we can
|
|
* see that the correct number of things were pushed.
|
|
*/
|
|
static void * pushF(void *stack)
|
|
{
|
|
register void * sp asm("%edx");
|
|
register void * osp asm("%ecx");
|
|
|
|
readStack(sp);
|
|
switchStack (stack);
|
|
__asm__ ("pushf");
|
|
readStack(osp);
|
|
switchStack(sp);
|
|
|
|
return osp;
|
|
}
|
|
|
|
static unsigned char xlat(unsigned char * base, unsigned char index)
|
|
{
|
|
// ebx is the PIC register, but its use is fixed in xlat. Preserve original value.
|
|
|
|
register unsigned char result asm ("%al") = index;
|
|
|
|
__asm__ (
|
|
"movl %%ebx, %%edx;"
|
|
"movl %2, %%ebx;"
|
|
"xlat;"
|
|
"movl %%edx, %%ebx;"
|
|
: "=a"(result)
|
|
: "0"(result), "m"(base)
|
|
: "%edx");
|
|
|
|
return result;
|
|
}
|
|
|
|
static int xlatTest()
|
|
{
|
|
unsigned char notV[256];
|
|
unsigned char xlated[256];
|
|
int i;
|
|
int failures = 0;
|
|
for (i=0;i<256; i++)
|
|
{
|
|
notV[i] = (unsigned char)~i;
|
|
}
|
|
|
|
for (i=0;i<256;i++)
|
|
{
|
|
xlated[i] = xlat(notV, (unsigned char)i);
|
|
}
|
|
|
|
for (i=0; i<256; i++)
|
|
{
|
|
if (xlated[i] != notV[i])
|
|
{
|
|
printf("XLAT failed : got %02x expected %02x\n", xlated[i], notV[i]);
|
|
failures++;
|
|
}
|
|
}
|
|
|
|
printf ("XLAT test %s\n", failures ? "FAILED" : "Passed");
|
|
return failures;
|
|
}
|
|
|
|
struct result
|
|
{
|
|
void * before;
|
|
void * after;
|
|
addrint expected;
|
|
addrint seen;
|
|
};
|
|
|
|
int printResult (const char * test, struct result *r)
|
|
{
|
|
printf ("%-8s %p %p %4ld %010p %010p %7ld\n",
|
|
test, r->before, r->after,
|
|
(int)(((char *)r->after) - (char *)r->before),
|
|
(void *) r->expected, (void *)r->seen, r->seen - r->expected);
|
|
|
|
return (r->expected != r->seen);
|
|
}
|
|
|
|
int main (int argc, char ** argv)
|
|
{
|
|
struct result r;
|
|
addrint stack[32];
|
|
addrint * stackp = &stack[32];
|
|
int failures = xlatTest();
|
|
|
|
printf (" Stack Pointer Value\n");
|
|
printf ("Test Before After Delta Expect See Delta\n");
|
|
|
|
r.before = stackp;
|
|
r.after = pushI(stackp);
|
|
r.expected = 99;
|
|
r.seen = stack[31];
|
|
failures += printResult ("I",&r);
|
|
|
|
r.before = stackp;
|
|
r.after = pushIW_(stackp); // Since ICC 11 is not supporting pushw in it's inline asm, the pushIW changed to an asm version pushIW_
|
|
r.expected = -5;
|
|
r.seen = *(short *)(((char *)stackp)-2);
|
|
failures += printResult ("IW",&r);
|
|
|
|
r.before = stackp;
|
|
r.after = pushSP(stackp);
|
|
r.expected = (addrint)stackp; /* push esp is an interesting case. See esp before decrement. */
|
|
r.seen = stack[31];
|
|
failures += printResult ("%esp",&r);
|
|
|
|
stack[31] = 101;
|
|
r.before = stackp-1;
|
|
r.after = pushSPIndirect(r.before);
|
|
r.expected = 101;
|
|
r.seen = stack[30];
|
|
failures += printResult("(%esp)", &r);
|
|
|
|
r.before = stackp;
|
|
r.after = pushA(stackp);
|
|
r.expected = 0;
|
|
r.seen = 0;
|
|
failures += printResult ("pusha",&r);
|
|
|
|
printf ("Flags result varies, not counted as a failure\n");
|
|
r.before = stackp;
|
|
r.after = pushF(stackp);
|
|
r.expected = 0x286;
|
|
r.seen = stack[31];
|
|
printResult ("pushf",&r);
|
|
|
|
printf ("Done\n");
|
|
|
|
return failures;
|
|
}
|
|
|