From: Julian Seward Date: Sun, 11 May 2008 10:45:29 +0000 (+0000) Subject: Add a test case for #152818 (from Sergei Trofimovich) X-Git-Tag: svn/VALGRIND_3_4_0~596 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a1fdd2393baff1662c9562c7e8e26b413a859ef6;p=thirdparty%2Fvalgrind.git Add a test case for #152818 (from Sergei Trofimovich) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8043 --- diff --git a/none/tests/x86/Makefile.am b/none/tests/x86/Makefile.am index 86c613627d..e68e1dab0b 100644 --- a/none/tests/x86/Makefile.am +++ b/none/tests/x86/Makefile.am @@ -23,6 +23,8 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ bug132813-x86.stderr.exp bug132813-x86.stdout.exp bug132813-x86.vgtest \ bug135421-x86.stderr.exp bug135421-x86.stdout.exp bug135421-x86.vgtest \ bug137714-x86.stderr.exp bug137714-x86.stdout.exp bug137714-x86.vgtest \ + bug152818-x86.vgtest bug152818-x86.stdout.exp \ + bug152818-x86.stderr.exp \ cpuid.stderr.exp cpuid.stdout.exp cpuid.vgtest \ cmpxchg8b.stderr.exp cmpxchg8b.stdout.exp cmpxchg8b.vgtest \ cse_fail.stderr.exp cse_fail.stdout.exp cse_fail.vgtest \ @@ -60,6 +62,7 @@ check_PROGRAMS = \ bug132813-x86 \ bug135421-x86 \ bug137714-x86 \ + bug152818-x86 \ cmpxchg8b cpuid cse_fail \ faultstatus fcmovnu fpu_lazy_eflags fxtract \ getseg incdec_alt $(INSN_TESTS) \ diff --git a/none/tests/x86/bug152818-x86.c b/none/tests/x86/bug152818-x86.c new file mode 100644 index 0000000000..4df0c1fdca --- /dev/null +++ b/none/tests/x86/bug152818-x86.c @@ -0,0 +1,207 @@ +#include +#include +#include + +/* Test case supplied by Sergei Trofimovich */ + +/* + * Real life example (MSDOS file INFO.EXE) has code like this + * + * I don't know why author/compiler done code like this. Only guess: + * guess 1 (strong :]): + * This archaic code was used by dynamic memory regeneration + * handler (according to code around it's called from + * interrupt handler). + * + * guess 2: cache flush (whether processors had caches at that time?) + * + * a disasmed snippet: + * + * mov byte ptr [bx], 0FFh + * sti + * mov cx, 0FFFFh ; 65535 + * rep lods byte ptr es:[si] + * jcxz short somewhere_1 ; it seems code could be + * ; interrupted here + * + * call something_2 + * cmp dx, 4 + * mov byte ptr [bx], 0 + * jmp somewhere_3 + */ + +#define GET_BIT(var, bit_no) ((var >> bit_no) & 1) + +static char sz_eflags[] = " "; // 8 spaces +static void pp_eflags (unsigned int _8bits_eflags) +{ + assert (_8bits_eflags >= 0); + assert (_8bits_eflags <= 0xFF); + sz_eflags[0] = GET_BIT(_8bits_eflags, 7) ? 'S' : ' '; + sz_eflags[1] = GET_BIT(_8bits_eflags, 6) ? 'Z' : ' '; + sz_eflags[3] = GET_BIT(_8bits_eflags, 4) ? 'A' : ' '; + sz_eflags[5] = GET_BIT(_8bits_eflags, 2) ? 'P' : ' '; + sz_eflags[7] = GET_BIT(_8bits_eflags, 0) ? 'C' : ' '; +} + +#define EMIT_CALL(dir_insn, insn, in_eax, in_esi, in_eflags, out_eax, out_esi, out_eflags, count) \ + asm volatile( \ + "movl %3, %%eax \t\n" \ + "sahf \t\n" /* loading our eflags */ \ + "movl %4, %%eax \t\n" \ + "movl %5, %%esi \t\n" \ + "movl %6, %%ecx \t\n" \ + \ + dir_insn "\t\n" \ + insn "\t\n" \ + \ + /* return result */ \ + "movl %%eax, %0 \t\n" \ + "lahf \t\n" \ + "movl %%eax, %1 \t\n" \ + "movl %%esi, %2 \t\n" \ + : "=d"(out_eax), \ + "=b"(out_eflags), \ + "=r"(out_esi) \ + \ + : "m"(in_eflags), \ + "m"(in_eax), \ + "m"(in_esi), \ + "q"(count) \ + \ + : "%eax", "%esi", "%ecx", "cc" /* we mess up EFLAGS */); + +const signed char b_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4}; +const signed long l_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4}; +const signed short w_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4}; + +const int lens[] = { 4, 3, 2, 1, 0, 0, 1, 2, 3, 4}; + +int main () +{ + const signed char * b_center = (signed char *) memchr(b_mem_buff, 0xaa, sizeof (b_mem_buff)); + const signed char * w_center = (signed char *) memchr(w_mem_buff, 0xaa, sizeof (w_mem_buff)); + const signed char * l_center = (signed char *) memchr(l_mem_buff, 0xaa, sizeof (l_mem_buff)); + + int insn; + for (insn = 0; insn < 4; ++insn) //b,w[rep/addr],d,w[addr/rep] + { + int idx; + for (idx = 0; idx < sizeof (lens)/sizeof(lens[0]); ++idx) + { + unsigned int eflags; + unsigned int eax = 0x12348765; + unsigned int esi; + const char * i_name = NULL; + switch (insn) + { + case 0: //b + esi = (unsigned int) b_center; + i_name = "lodsb"; + break; + case 1: //w + esi = (unsigned int) w_center; + i_name = "lodsw[rep/addr]"; + break; + case 2: //d + esi = (unsigned int) l_center; + i_name = "lodsl"; + break; + case 3: //w + esi = (unsigned int) w_center; + i_name = "lodsw[addr/rep]"; + break; + } + + eflags = 0; + pp_eflags ((eflags >> 8) & 0xFF); // scratching off AH + printf ("REP %s (EAX = %08X, EFLAGS = %s) => ", i_name, eax, sz_eflags); + + unsigned int resulting_eflags = 0; + unsigned int resulting_eax = 0; + unsigned int resulting_esi; + + int len = lens[idx]; + int df = (idx >= (sizeof(lens)/sizeof(lens[0]))/2); + switch (insn) + { + case 0: //b + if (df) + { + EMIT_CALL("cld", + "rep lodsb", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + else + { + EMIT_CALL("std", + "rep lodsb", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + break; + case 1: //w[rep/addr] + if (df) + { + EMIT_CALL("cld", + // "rep lodsw", + // explicit: rep-pref addr-pref op + ".byte 0x66,0xf3,0xad", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + else + { + EMIT_CALL("std", + // "rep lodsw", + // explicit: rep-pref addr-pref op + ".byte 0x66,0xf3,0xad", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + break; + case 2: //d + if (df) + { + EMIT_CALL("cld", + "rep lodsl", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + else + { + EMIT_CALL("std", + "rep lodsl", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + break; + case 3: //w[addr/rep] + if (df) + { + EMIT_CALL("cld", + // "rep lodsw", + // explicit: rep-pref addr-pref op + ".byte 0xf3,0x66,0xad", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + else + { + EMIT_CALL("std", + // "rep lodsw", + // explicit: rep-pref addr-pref op + ".byte 0xf3,0x66,0xad", + eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags, + len); + } + break; + } + printf ("DF = %d, count = %2d ", df, len); + pp_eflags ((resulting_eflags >> 8) & 0xFF); // scratching off AH + printf ("(EAX = %08X, EFLAGS = %s)\n", resulting_eax, sz_eflags); + } + } + return 0; +} diff --git a/none/tests/x86/bug152818-x86.stderr.exp b/none/tests/x86/bug152818-x86.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/x86/bug152818-x86.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/x86/bug152818-x86.stdout.exp b/none/tests/x86/bug152818-x86.stdout.exp new file mode 100644 index 0000000000..68a65e86b8 --- /dev/null +++ b/none/tests/x86/bug152818-x86.stdout.exp @@ -0,0 +1,40 @@ +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 123487FD, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 123487FE, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 123487FF, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123487AA, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123487AA, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12348701, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12348702, EFLAGS = ) +REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12348703, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 1234FFFD, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 1234FFFE, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 1234FFFF, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123400AA, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123400AA, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12340001, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12340002, EFLAGS = ) +REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12340003, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = FFFFFFFD, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = FFFFFFFE, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = FFFFFFFF, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 000000AA, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 000000AA, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 00000001, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 00000002, EFLAGS = ) +REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 00000003, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 1234FFFD, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 1234FFFE, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 1234FFFF, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123400AA, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123400AA, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12340001, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12340002, EFLAGS = ) +REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12340003, EFLAGS = ) diff --git a/none/tests/x86/bug152818-x86.vgtest b/none/tests/x86/bug152818-x86.vgtest new file mode 100644 index 0000000000..8928a106a3 --- /dev/null +++ b/none/tests/x86/bug152818-x86.vgtest @@ -0,0 +1 @@ +prog: bug152818-x86