138 lines
2.7 KiB
C++
138 lines
2.7 KiB
C++
#include "check.h"
|
|
|
|
|
|
#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
|
|
#define ASMNAME2(prefix, cname) STRING (prefix) cname
|
|
#define STRING(x) #x
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" void abort (void);
|
|
#else
|
|
extern void abort (void);
|
|
#endif
|
|
|
|
extern void foo(void);
|
|
|
|
#define INIT_EDI 1
|
|
#define INIT_ESI 2
|
|
#define INIT_EBX 3
|
|
|
|
/* Set DI/SI/BX to wrong value
|
|
Use following template so that RA will save/restore callee
|
|
save registers in prologue/epilogue */
|
|
#define ALTER_REGS() \
|
|
{ \
|
|
int dummy; \
|
|
__asm__ __volatile__ (\
|
|
"movl %1, %0" : "=D" (dummy) : "i" (-INIT_EDI)\
|
|
);\
|
|
__asm__ __volatile__ (\
|
|
"movl %1, %0" : "=S" (dummy) : "i" (-INIT_ESI)\
|
|
);\
|
|
__asm__ __volatile__ (\
|
|
"movl %1, %0" : "=b" (dummy) : "i" (-INIT_EBX)\
|
|
);\
|
|
}
|
|
|
|
#if defined __PIC__ || defined __USING_SJLJ_EXCEPTIONS__
|
|
int
|
|
main ()
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
void __attribute__ ((noinline))
|
|
copy (char *p, int size)
|
|
{
|
|
__builtin_strncpy (p, "good", size);
|
|
}
|
|
|
|
int g_edi=INIT_EDI, g_esi=INIT_ESI, g_ebx=INIT_EBX;
|
|
int g_ebp, g_ebp_save, g_esp, g_esp_save;
|
|
int n_error;
|
|
|
|
int
|
|
main()
|
|
{
|
|
int dummy;
|
|
// Init registers to correct value.
|
|
// Use following template so that RA will save/restore callee
|
|
// save registers in prologue/epilogue
|
|
__asm__ __volatile__ (
|
|
"movl %1, %0"
|
|
: "=D" (dummy)
|
|
: "i" (INIT_EDI)
|
|
);
|
|
__asm__ __volatile__ (
|
|
"movl %1, %0"
|
|
: "=S" (dummy)
|
|
: "i" (INIT_ESI)
|
|
);
|
|
__asm__ __volatile__ (
|
|
"movl %1, %0"
|
|
: "=b" (dummy)
|
|
: "i" (INIT_EBX)
|
|
);
|
|
__asm__ __volatile__ (
|
|
"movl %ebp," ASMNAME("g_ebp_save")"\n\t"
|
|
"movl %esp," ASMNAME("g_esp_save")"\n\t"
|
|
);
|
|
try {
|
|
foo();
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
|
|
// Get DI/SI/BX register value after exception caught
|
|
__asm__ __volatile__ (
|
|
"movl %edi," ASMNAME("g_edi")"\n\t"
|
|
"movl %esi," ASMNAME("g_esi")"\n\t"
|
|
"movl %ebx," ASMNAME("g_ebx")"\n\t"
|
|
"movl %ebp," ASMNAME("g_ebp")"\n\t"
|
|
"movl %esp," ASMNAME("g_esp")"\n\t"
|
|
);
|
|
|
|
// Check if DI/SI/BX register value are the same as before calling
|
|
// foo.
|
|
if (g_edi != INIT_EDI)
|
|
{
|
|
n_error++;
|
|
#ifdef DEBUG
|
|
printf("edi=%d, correct value:%d\n", g_edi, INIT_EDI);
|
|
#endif
|
|
}
|
|
if (g_esi != INIT_ESI)
|
|
{
|
|
n_error++;
|
|
#ifdef DEBUG
|
|
printf("esi=%d, correct value:%d\n", g_esi, INIT_ESI);
|
|
#endif
|
|
}
|
|
if (g_ebx != INIT_EBX)
|
|
{
|
|
n_error++;
|
|
#ifdef DEBUG
|
|
printf("ebx=%d, correct value:%d\n", g_ebx, INIT_EBX);
|
|
#endif
|
|
}
|
|
if (g_ebp != g_ebp_save)
|
|
{
|
|
n_error++;
|
|
#ifdef DEBUG
|
|
printf("ebp=0x%x, correct value:0x%x\n", g_ebp, g_ebp_save);
|
|
#endif
|
|
}
|
|
if (g_esp != g_esp_save)
|
|
{
|
|
n_error++;
|
|
#ifdef DEBUG
|
|
printf("esp=0x%x, correct value:0x%x\n", g_esp, g_esp_save);
|
|
#endif
|
|
}
|
|
if (n_error !=0)
|
|
abort();
|
|
return 0;
|
|
}
|
|
#endif
|