run: $(TARGET)
./$(TARGET)
-cflags-x86_32 := "-mno-accumulate-outgoing-args -Dstatic="
+TESTCASES := blowfish
-blowfish.h: blowfish.c blowfish.mk Makefile
- rm -f $@.new blowfish.bin
+blowfish-cflags := ""
+blowfish-cflags-x86_32 := "-mno-accumulate-outgoing-args -Dstatic="
+
+$(addsuffix .h,$(TESTCASES)): %.h: %.c testcase.mk Makefile
+ rm -f $@.new $*.bin
$(foreach arch,$(filter-out $(XEN_COMPILE_ARCH),x86_32) $(XEN_COMPILE_ARCH), \
- for cflags in "" $(cflags-$(arch)); do \
- $(MAKE) -f blowfish.mk XEN_TARGET_ARCH=$(arch) BLOWFISH_CFLAGS="$$cflags" all; \
+ for cflags in $($*-cflags) $($*-cflags-$(arch)); do \
+ $(MAKE) -f testcase.mk TESTCASE=$* XEN_TARGET_ARCH=$(arch) $*-cflags="$$cflags" all; \
flavor=$$(echo $${cflags} | sed -e 's, .*,,' -e 'y,-=,__,') ; \
- (echo "static unsigned int blowfish_$(arch)$${flavor}[] = {"; \
- od -v -t x blowfish.bin | sed -e 's/^[0-9]* /0x/' -e 's/ /, 0x/g' -e 's/$$/,/'; \
+ (echo "static const unsigned int $*_$(arch)$${flavor}[] = {"; \
+ od -v -t x $*.bin | sed -e 's/^[0-9]* /0x/' -e 's/ /, 0x/g' -e 's/$$/,/'; \
echo "};") >>$@.new; \
- rm -f blowfish.bin; \
+ rm -f $*.bin; \
done; \
)
mv $@.new $@
.PHONY: clean
clean:
- rm -rf $(TARGET) *.o *~ core blowfish.h blowfish.bin x86_emulate asm
+ rm -rf $(TARGET) *.o *~ core $(addsuffix .h,$(TESTCASES)) *.bin x86_emulate asm
.PHONY: distclean
distclean: clean
x86_emulate.o: x86_emulate.c x86_emulate/x86_emulate.c $(x86_emulate.h)
$(HOSTCC) $(HOSTCFLAGS) -D__XEN_TOOLS__ -c -g -o $@ $<
-test_x86_emulator.o: test_x86_emulator.c blowfish.h $(x86_emulate.h)
+test_x86_emulator.o: test_x86_emulator.c $(addsuffix .h,$(TESTCASES)) $(x86_emulate.h)
$(HOSTCC) $(HOSTCFLAGS) -c -g -o $@ $<
#define verbose false /* Switch to true for far more logging. */
+static void blowfish_set_regs(struct cpu_user_regs *regs)
+{
+ regs->eax = 2;
+ regs->edx = 1;
+}
+
+static bool blowfish_check_regs(const struct cpu_user_regs *regs)
+{
+ return regs->eax == 2 && regs->edx == 1;
+}
+
static const struct {
const void *code;
size_t size;
unsigned int bitness;
const char*name;
+ void (*set_regs)(struct cpu_user_regs *);
+ bool (*check_regs)(const struct cpu_user_regs *);
} blobs[] = {
- { blowfish_x86_32, sizeof(blowfish_x86_32), 32, "blowfish" },
- { blowfish_x86_32_mno_accumulate_outgoing_args,
- sizeof(blowfish_x86_32_mno_accumulate_outgoing_args),
- 32, "blowfish (push)" },
+#define BLOWFISH(bits, desc, tag) \
+ { .code = blowfish_x86_ ## bits ## tag, \
+ .size = sizeof(blowfish_x86_ ## bits ## tag), \
+ .bitness = bits, .name = #desc, \
+ .set_regs = blowfish_set_regs, \
+ .check_regs = blowfish_check_regs }
#ifdef __x86_64__
- { blowfish_x86_64, sizeof(blowfish_x86_64), 64, "blowfish" },
+ BLOWFISH(64, blowfish, ),
#endif
+ BLOWFISH(32, blowfish, ),
+ BLOWFISH(32, blowfish (push), _mno_accumulate_outgoing_args),
+#undef BLOWFISH
};
static unsigned int bytes_read;
for ( j = 0; j < ARRAY_SIZE(blobs); j++ )
{
+ if ( !blobs[j].size )
+ {
+ printf("%-39s n/a\n", blobs[j].name);
+ continue;
+ }
+
memcpy(res, blobs[j].code, blobs[j].size);
ctxt.addr_size = ctxt.sp_size = blobs[j].bitness;
+ if ( ctxt.addr_size == sizeof(void *) * CHAR_BIT )
+ {
+ i = printf("Testing %s native execution...", blobs[j].name);
+ if ( blobs[j].set_regs )
+ blobs[j].set_regs(®s);
+ asm volatile (
+#if defined(__i386__)
+ "call *%%ecx"
+#else
+ "call *%%rcx"
+#endif
+ : "+a" (regs.eax), "+d" (regs.edx) : "c" (res)
+#ifdef __x86_64__
+ : "rsi", "rdi", "r8", "r9", "r10", "r11"
+#endif
+ );
+ if ( !blobs[j].check_regs(®s) )
+ goto fail;
+ printf("%*sokay\n", i < 40 ? 40 - i : 0, "");
+ }
+
printf("Testing %s %u-bit code sequence",
blobs[j].name, ctxt.addr_size);
- regs.eax = 2;
- regs.edx = 1;
+ if ( blobs[j].set_regs )
+ blobs[j].set_regs(®s);
regs.eip = (unsigned long)res;
regs.esp = (unsigned long)res + MMAP_SZ - 4;
if ( ctxt.addr_size == 64 )
*(uint32_t *)(unsigned long)regs.esp = 0x12345678;
regs.eflags = 2;
i = 0;
- while ( regs.eip != 0x12345678 )
+ while ( regs.eip >= (unsigned long)res &&
+ regs.eip < (unsigned long)res + blobs[j].size )
{
if ( (i++ & 8191) == 0 )
printf(".");
rc = x86_emulate(&ctxt, &emulops);
if ( rc != X86EMUL_OKAY )
{
- printf("failed at %%eip == %08x\n", (unsigned int)regs.eip);
+ printf("failed at %%eip == %08lx (opcode %08x)\n",
+ (unsigned long)regs.eip, ctxt.opcode);
return 1;
}
}
- if ( (regs.esp != ((unsigned long)res + MMAP_SZ)) ||
- (regs.eax != 2) || (regs.edx != 1) )
+ for ( ; i < 2 * 8192; i += 8192 )
+ printf(".");
+ if ( (regs.eip != 0x12345678) ||
+ (regs.esp != ((unsigned long)res + MMAP_SZ)) ||
+ !blobs[j].check_regs(®s) )
goto fail;
printf("okay\n");
-
- if ( ctxt.addr_size != sizeof(void *) * CHAR_BIT )
- continue;
-
- i = printf("Testing %s native execution...", blobs[j].name);
- asm volatile (
-#if defined(__i386__)
- "movl $0x100000,%%ecx; call *%%ecx"
-#else
- "movl $0x100000,%%ecx; call *%%rcx"
-#endif
- : "=a" (regs.eax), "=d" (regs.edx)
- : "0" (2), "1" (1) : "ecx"
-#ifdef __x86_64__
- , "rsi", "rdi", "r8", "r9", "r10", "r11"
-#endif
- );
- if ( (regs.eax != 2) || (regs.edx != 1) )
- goto fail;
- printf("%*sokay\n", i < 40 ? 40 - i : 0, "");
}
return 0;