mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-22 20:55:27 +00:00
Start moving examples in S files (#851)
* Move assembly to S files * more assembly files * osx compilation change * makefile mistake * add objcopy from crosstool * use gobjcopy on osx * start cmocka install cleanup * move wget to directory option * move back to cd * fix copy * First cut * free allocated memory * bad idea too much switching between python and c * add debug * cleanup bad size
This commit is contained in:
parent
7f116846c0
commit
da21bd0589
|
@ -1,8 +1,7 @@
|
||||||
language: c
|
language: c
|
||||||
sudo: false
|
sudo: false
|
||||||
before_install:
|
before_install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cmocka crosstool-ng; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cmocka; fi
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./install-cmocka-linux.sh; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./install-cmocka-linux.sh; fi
|
||||||
script:
|
script:
|
||||||
- make && make -C bindings/go && make -C bindings/go test && make test
|
- make && make -C bindings/go && make -C bindings/go test && make test
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
#!/bin/sh
|
#!/bin/sh -ex
|
||||||
set -ex
|
|
||||||
mkdir -p cmocka
|
mkdir -p cmocka
|
||||||
#wget https://cmocka.org/files/1.1/cmocka-1.1.0.tar.xz -O /tmp/cmocka-1.1.0.tar.xz
|
#wget https://cmocka.org/files/1.1/cmocka-1.1.0.tar.xz -O /tmp/cmocka-1.1.0.tar.xz
|
||||||
wget --no-check-certificate http://cmocka.org/files/1.1/cmocka-1.1.0.tar.xz -O /tmp/cmocka-1.1.0.tar.xz
|
wget --no-check-certificate https://cmocka.org/files/1.1/cmocka-1.1.1.tar.xz -P /tmp/
|
||||||
tar -xf /tmp/cmocka-1.1.0.tar.xz -C /tmp
|
tar -xf /tmp/cmocka-1.1.1.tar.xz -C /tmp
|
||||||
cd cmocka && cmake -DUNIT_TESTING=On /tmp/cmocka-1.1.0 && make && make test
|
cd cmocka && cmake -DUNIT_TESTING=On /tmp/cmocka-1.1.1 && make && make test
|
||||||
# cmake builds an so instead of a dll in mingw/msys
|
# cmake builds an so instead of a dll in mingw/msys
|
||||||
if [[ ! -z $MSYSTEM ]]; then
|
if [[ ! -z $MSYSTEM ]]; then
|
||||||
cp src/cmocka.so src/cmocka.dll
|
cp src/cmocka.so src/cmocka.dll
|
||||||
fi
|
fi
|
||||||
# cmocka does not include headers in build
|
# cmocka does not include headers in build
|
||||||
cp -R /tmp/cmocka-1.1.0/include/ .
|
cp -R /tmp/cmocka-1.1.1/include/ .
|
||||||
|
|
1
tests/unit/.gitignore
vendored
1
tests/unit/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
!*.c
|
!*.c
|
||||||
test_*
|
test_*
|
||||||
|
*.bin
|
||||||
|
|
|
@ -2,10 +2,15 @@ CFLAGS += -Wall -Werror -Wno-unused-function -g
|
||||||
CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
|
CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
|
||||||
CFLAGS += -L ../../ -I ../../include
|
CFLAGS += -L ../../ -I ../../include
|
||||||
CFLAGS += -L ../../cmocka/src -I ../../cmocka/include
|
CFLAGS += -L ../../cmocka/src -I ../../cmocka/include
|
||||||
|
ASFLAGS += --32
|
||||||
|
OBJCOPY = objcopy
|
||||||
|
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
ifeq ($(UNAME_S), Linux)
|
ifeq ($(UNAME_S), Linux)
|
||||||
LDLIBS += -lrt -pthread
|
LDLIBS += -lrt -pthread
|
||||||
|
else ifeq ($(UNAME_S), Darwin)
|
||||||
|
OBJCOPY = gobjcopy
|
||||||
|
ASFLAGS = -arch i386
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDLIBS += -lcmocka -lunicorn
|
LDLIBS += -lcmocka -lunicorn
|
||||||
|
@ -20,17 +25,24 @@ LDFLAGS := -fsanitize=address ${LDFLAGS}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ALL_TESTS_SOURCES = $(wildcard *.c)
|
ALL_TESTS_SOURCES = $(wildcard *.c)
|
||||||
|
TEST_ASSEMBLY = $(wildcard *.s)
|
||||||
|
TEST_PROGS = $(TEST_ASSEMBLY:%.s=%.o)
|
||||||
|
TEST_BINS = $(TEST_PROGS:%.o=%.bin)
|
||||||
ALL_TESTS = $(ALL_TESTS_SOURCES:%.c=%)
|
ALL_TESTS = $(ALL_TESTS_SOURCES:%.c=%)
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: ${ALL_TESTS}
|
all: ${TEST_BINS} ${ALL_TESTS}
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf ${ALL_TESTS}
|
rm -rf ${TEST_BINS} ${ALL_TESTS}
|
||||||
|
|
||||||
|
%.bin: %.o
|
||||||
|
${OBJCOPY} -O binary $^ $@
|
||||||
|
hexdump -C $@
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: ${ALL_TESTS}
|
test: all
|
||||||
${EXECUTE_VARS} ./test_sanity
|
${EXECUTE_VARS} ./test_sanity
|
||||||
${EXECUTE_VARS} ./test_x86
|
${EXECUTE_VARS} ./test_x86
|
||||||
${EXECUTE_VARS} ./test_mem_map
|
${EXECUTE_VARS} ./test_mem_map
|
||||||
|
|
3
tests/unit/gdt_idx.s
Normal file
3
tests/unit/gdt_idx.s
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.text
|
||||||
|
sidt (esp)
|
||||||
|
sgdt (esp+6)
|
6
tests/unit/high_address.s
Normal file
6
tests/unit/high_address.s
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
dec %eax
|
||||||
|
mov (%eax), %eax
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
9
tests/unit/pc_change.s
Normal file
9
tests/unit/pc_change.s
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.text
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
||||||
|
inc %edx
|
||||||
|
inc %edx
|
90
tests/unit/tb_x86.s
Normal file
90
tests/unit/tb_x86.s
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
mov %esp,%ecx
|
||||||
|
fxch %st(5)
|
||||||
|
fnstenv -0xc(%ecx)
|
||||||
|
pop %ebp
|
||||||
|
push %ebp
|
||||||
|
pop %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
dec %ecx
|
||||||
|
inc %ebx
|
||||||
|
inc %ebx
|
||||||
|
inc %ebx
|
||||||
|
inc %ebx
|
||||||
|
inc %ebx
|
||||||
|
inc %ebx
|
||||||
|
aaa
|
||||||
|
push %ecx
|
||||||
|
pop %edx
|
||||||
|
push $0x41
|
||||||
|
pop %eax
|
||||||
|
push %eax
|
||||||
|
xor %al,0x30(%ecx)
|
||||||
|
inc %ecx
|
||||||
|
imul $0x51,0x41(%ecx),%eax
|
||||||
|
xor 0x42(%ecx),%al
|
||||||
|
xor 0x42(%edx),%al
|
||||||
|
xor %al,0x42(%edx)
|
||||||
|
inc %ecx
|
||||||
|
inc %edx
|
||||||
|
pop %eax
|
||||||
|
push %eax
|
||||||
|
cmp %al,0x42(%ecx)
|
||||||
|
jne .+0x4c
|
||||||
|
dec %ecx
|
||||||
|
push %ecx
|
||||||
|
push %ecx
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
inc %edi
|
||||||
|
xor 0x34(%edi),%eax
|
||||||
|
push %ecx
|
||||||
|
push %ebp
|
||||||
|
push %ecx
|
||||||
|
push %esi
|
||||||
|
push %eax
|
||||||
|
inc %edi
|
||||||
|
inc %edi
|
||||||
|
cmp %al,0x39(%edi)
|
||||||
|
push %eax
|
||||||
|
dec %edx
|
||||||
|
push %eax
|
||||||
|
dec %ebx
|
||||||
|
push %eax
|
||||||
|
dec %esp
|
||||||
|
push %eax
|
||||||
|
dec %ebp
|
||||||
|
push %eax
|
||||||
|
dec %esi
|
||||||
|
push %eax
|
||||||
|
dec %edi
|
||||||
|
push %eax
|
||||||
|
push %eax
|
||||||
|
push %eax
|
||||||
|
xor %eax, 0x42(%edi)
|
||||||
|
inc %edi
|
||||||
|
inc %edx
|
||||||
|
push %eax
|
||||||
|
xor $0x50,%al
|
||||||
|
pop %edx
|
||||||
|
push %eax
|
||||||
|
inc %ebp
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
inc %esi
|
||||||
|
xor 0x31(%edi),%al
|
||||||
|
push %eax
|
||||||
|
dec %ebp
|
||||||
|
push %ecx
|
||||||
|
push %ecx
|
||||||
|
push %eax
|
||||||
|
dec %esi
|
||||||
|
inc %ecx
|
||||||
|
inc %ecx
|
|
@ -1,45 +1,9 @@
|
||||||
|
#include "unicorn_test.h"
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that err matches expect
|
|
||||||
*/
|
|
||||||
#define uc_assert_err(expect, err) \
|
|
||||||
do { \
|
|
||||||
uc_err __err = err; \
|
|
||||||
if (__err != expect) { \
|
|
||||||
fprintf(stderr, "%s", uc_strerror(__err)); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that err is UC_ERR_OK
|
|
||||||
*/
|
|
||||||
#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that err is anything but UC_ERR_OK
|
|
||||||
*
|
|
||||||
* Note: Better to use uc_assert_err(<specific error>, err),
|
|
||||||
* as this serves to document which errors a function will return
|
|
||||||
* in various scenarios.
|
|
||||||
*/
|
|
||||||
#define uc_assert_fail(err) \
|
|
||||||
do { \
|
|
||||||
uc_err __err = err; \
|
|
||||||
if (__err == UC_ERR_OK) { \
|
|
||||||
fprintf(stderr, "%s", uc_strerror(__err)); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define OK(x) uc_assert_success(x)
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
static void test_idt_gdt_i386(/*void **state*/)
|
static void test_idt_gdt_i386(/*void **state*/)
|
||||||
{
|
{
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
|
@ -50,7 +14,9 @@ static void test_idt_gdt_i386(/*void **state*/)
|
||||||
uc_x86_mmr ldt;
|
uc_x86_mmr ldt;
|
||||||
uc_x86_mmr tr;
|
uc_x86_mmr tr;
|
||||||
|
|
||||||
const uint8_t code[] = "\x0f\x01\x0c\x24\x0f\x01\x44\x24\x06"; // sidt [esp]; sgdt [esp+6]
|
struct stat info;
|
||||||
|
char * code = read_file("gdt_idx.bin", &info);
|
||||||
|
|
||||||
const uint64_t address = 0x1000000;
|
const uint64_t address = 0x1000000;
|
||||||
|
|
||||||
int r_esp = address + 0x1000 - 0x100; // initial esp
|
int r_esp = address + 0x1000 - 0x100; // initial esp
|
||||||
|
@ -79,7 +45,7 @@ static void test_idt_gdt_i386(/*void **state*/)
|
||||||
uc_assert_success(err);
|
uc_assert_success(err);
|
||||||
|
|
||||||
// write machine code to be emulated to memory
|
// write machine code to be emulated to memory
|
||||||
err = uc_mem_write(uc, address, code, sizeof(code)-1);
|
err = uc_mem_write(uc, address, code, info.st_size);
|
||||||
uc_assert_success(err);
|
uc_assert_success(err);
|
||||||
|
|
||||||
// initialize machine registers
|
// initialize machine registers
|
||||||
|
@ -141,7 +107,7 @@ static void test_idt_gdt_i386(/*void **state*/)
|
||||||
assert(memcmp(buf, "\xba\xdc\x21\x43\x65\x87", 6) == 0);
|
assert(memcmp(buf, "\xba\xdc\x21\x43\x65\x87", 6) == 0);
|
||||||
|
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
|
free(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -90,6 +90,8 @@ static void test_high_address_reads(void **state)
|
||||||
static void test_high_address_read_values(void **state)
|
static void test_high_address_read_values(void **state)
|
||||||
{
|
{
|
||||||
uc_engine *uc = *state;
|
uc_engine *uc = *state;
|
||||||
|
struct stat info;
|
||||||
|
char * code = read_file("high_address.bin", &info);
|
||||||
|
|
||||||
uint64_t addr = 0x0010000000000001;
|
uint64_t addr = 0x0010000000000001;
|
||||||
//addr = 0x000ffffffffffff8; // uncomment to fix wrong behaviour
|
//addr = 0x000ffffffffffff8; // uncomment to fix wrong behaviour
|
||||||
|
@ -100,15 +102,16 @@ static void test_high_address_read_values(void **state)
|
||||||
uc_assert_success(uc_mem_write(uc, addr, content, 8));
|
uc_assert_success(uc_mem_write(uc, addr, content, 8));
|
||||||
uc_assert_success(uc_reg_write(uc, UC_X86_REG_RAX, &addr));
|
uc_assert_success(uc_reg_write(uc, UC_X86_REG_RAX, &addr));
|
||||||
const uint64_t base_addr = 0x40000;
|
const uint64_t base_addr = 0x40000;
|
||||||
uint8_t code[] = {0x48,0x8b,0x00,0x90,0x90,0x90,0x90}; // mov rax, [rax], nops
|
|
||||||
uc_assert_success(uc_mem_map(uc, base_addr, 4096, UC_PROT_ALL));
|
uc_assert_success(uc_mem_map(uc, base_addr, 4096, UC_PROT_ALL));
|
||||||
uc_assert_success(uc_mem_write(uc, base_addr, code, 7));
|
uc_assert_success(uc_mem_write(uc, base_addr, code, info.st_size));
|
||||||
uc_assert_success(uc_emu_start(uc, base_addr, base_addr + 3, 0, 0));
|
uc_assert_success(uc_emu_start(uc, base_addr, base_addr + 3, 0, 0));
|
||||||
uint64_t rax = 0;
|
uint64_t rax = 0;
|
||||||
uc_assert_success(uc_reg_read(uc, UC_X86_REG_RAX, &rax));
|
uc_assert_success(uc_reg_read(uc, UC_X86_REG_RAX, &rax));
|
||||||
if(rax != 0x4242424242424242) {
|
if(rax != 0x4242424242424242) {
|
||||||
fail_msg("wrong memory read from code %"PRIx64, rax);
|
fail_msg("wrong memory read from code %"PRIx64, rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Test PC change during the callback. by Nguyen Anh Quynh, 2016
|
// Test PC change during the callback. by Nguyen Anh Quynh, 2016
|
||||||
#include "unicorn_test.h"
|
#include "unicorn_test.h"
|
||||||
#include "unicorn/unicorn.h"
|
#include "unicorn/unicorn.h"
|
||||||
|
#include "sys/stat.h"
|
||||||
|
|
||||||
#define OK(x) uc_assert_success(x)
|
#define OK(x) uc_assert_success(x)
|
||||||
|
|
||||||
|
@ -54,21 +55,12 @@ static void test_pc_change(void **state)
|
||||||
uc_engine *uc = *state;
|
uc_engine *uc = *state;
|
||||||
uc_hook trace1;
|
uc_hook trace1;
|
||||||
int32_t r_ecx = 3, r_edx = 15;
|
int32_t r_ecx = 3, r_edx = 15;
|
||||||
|
struct stat info;
|
||||||
|
char *code = read_file("pc_change.bin", &info);
|
||||||
|
|
||||||
#define BASEADDR 0x1000000
|
#define BASEADDR 0x1000000
|
||||||
|
|
||||||
uint64_t address = BASEADDR;
|
uint64_t address = BASEADDR;
|
||||||
const uint8_t code[] = {
|
|
||||||
0x41, // inc ECX @0x1000000
|
|
||||||
0x41, // inc ECX
|
|
||||||
0x41, // inc ECX
|
|
||||||
0x41, // inc ECX @0x1000003
|
|
||||||
0x41, // inc ECX
|
|
||||||
0x41, // inc ECX
|
|
||||||
|
|
||||||
0x42, // inc EDX @0x1000006
|
|
||||||
0x42, // inc EDX
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef BASEADDR
|
#undef BASEADDR
|
||||||
|
|
||||||
|
@ -76,7 +68,7 @@ static void test_pc_change(void **state)
|
||||||
OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL));
|
OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL));
|
||||||
|
|
||||||
// write machine code to be emulated to memory
|
// write machine code to be emulated to memory
|
||||||
OK(uc_mem_write(uc, address, code, sizeof(code)));
|
OK(uc_mem_write(uc, address, code, info.st_size));
|
||||||
|
|
||||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||||
|
@ -85,7 +77,7 @@ static void test_pc_change(void **state)
|
||||||
// trace all instructions
|
// trace all instructions
|
||||||
OK(uc_hook_add(uc, &trace1, UC_HOOK_CODE, test_code_hook, NULL, 1, 0));
|
OK(uc_hook_add(uc, &trace1, UC_HOOK_CODE, test_code_hook, NULL, 1, 0));
|
||||||
|
|
||||||
OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0));
|
OK(uc_emu_start(uc, address, address+info.st_size, 0, 0));
|
||||||
|
|
||||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||||
|
@ -93,6 +85,7 @@ static void test_pc_change(void **state)
|
||||||
printf("ECX = %u, EDX = %u\n", r_ecx, r_edx);
|
printf("ECX = %u, EDX = %u\n", r_ecx, r_edx);
|
||||||
assert_int_equal(r_ecx, 6);
|
assert_int_equal(r_ecx, 6);
|
||||||
assert_int_equal(r_edx, 17);
|
assert_int_equal(r_edx, 17);
|
||||||
|
free(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "unicorn/unicorn.h"
|
#include "unicorn/unicorn.h"
|
||||||
|
|
||||||
#define RIP_NEXT_TO_THE_SELFMODIFY_OPCODE (1)
|
#define RIP_NEXT_TO_THE_SELFMODIFY_OPCODE (1)
|
||||||
|
@ -21,17 +22,6 @@
|
||||||
#define CODE_SPACE (2 * 1024 * 1024)
|
#define CODE_SPACE (2 * 1024 * 1024)
|
||||||
#define PHY_STACK_REGION (0x60000000)
|
#define PHY_STACK_REGION (0x60000000)
|
||||||
|
|
||||||
#define X86_CODE32_ALPHA_MIXED \
|
|
||||||
"\x89\xe1\xd9\xcd\xd9\x71\xf4\x5d\x55\x59\x49\x49\x49\x49\x49\x49" \
|
|
||||||
"\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x58" \
|
|
||||||
"\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30" \
|
|
||||||
"\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49\x51\x51\x51\x52" \
|
|
||||||
"\x47\x33\x47\x34\x51\x55\x51\x56\x50\x47\x47\x38\x47\x39\x50\x4a" \
|
|
||||||
"\x50\x4b\x50\x4c\x50\x4d\x50\x4e\x50\x4f\x50\x50\x50\x31\x47\x42" \
|
|
||||||
"\x47\x42\x50\x34\x50\x5a\x50\x45\x51\x52\x46\x32\x47\x31\x50\x4d" \
|
|
||||||
"\x51\x51\x50\x4e\x41\x41"
|
|
||||||
|
|
||||||
|
|
||||||
/* Called before every test to set up a new instance */
|
/* Called before every test to set up a new instance */
|
||||||
static int setup(void **state)
|
static int setup(void **state)
|
||||||
{
|
{
|
||||||
|
@ -57,12 +47,12 @@ static int teardown(void **state)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void dump_stack_mem(uc_engine *uc)
|
static void dump_stack_mem(uc_engine *uc, const struct stat info)
|
||||||
{
|
{
|
||||||
uint8_t tmp[256];
|
uint8_t tmp[256];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
size = sizeof(X86_CODE32_ALPHA_MIXED);
|
size = sizeof(info.st_size);
|
||||||
if (size > 255) size = 255;
|
if (size > 255) size = 255;
|
||||||
if (!uc_mem_read(uc, PHY_STACK_REGION, tmp, size))
|
if (!uc_mem_read(uc, PHY_STACK_REGION, tmp, size))
|
||||||
{
|
{
|
||||||
|
@ -106,7 +96,8 @@ static void print_registers(uc_engine *uc)
|
||||||
static void hook_code32(uc_engine *uc,
|
static void hook_code32(uc_engine *uc,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
uint32_t size,
|
uint32_t size,
|
||||||
void *user_data)
|
void *user_data,
|
||||||
|
const struct stat info)
|
||||||
{
|
{
|
||||||
//uint8_t opcode[256];
|
//uint8_t opcode[256];
|
||||||
uint8_t tmp[16];
|
uint8_t tmp[16];
|
||||||
|
@ -126,7 +117,7 @@ static void hook_code32(uc_engine *uc,
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
dump_stack_mem(uc);
|
dump_stack_mem(uc, info);
|
||||||
|
|
||||||
|
|
||||||
if (address == 0x60000025)
|
if (address == 0x60000025)
|
||||||
|
@ -222,6 +213,8 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state)
|
||||||
{
|
{
|
||||||
uc_engine *uc = *state;
|
uc_engine *uc = *state;
|
||||||
uc_hook trace1, trace2;
|
uc_hook trace1, trace2;
|
||||||
|
struct stat info;
|
||||||
|
char * code = read_file("tb_x86.bin", &info);
|
||||||
//void *mem;
|
//void *mem;
|
||||||
#ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE
|
#ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE
|
||||||
// These values assumes just before PC = 0x60000021
|
// These values assumes just before PC = 0x60000021
|
||||||
|
@ -258,8 +251,8 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state)
|
||||||
UC_PROT_ALL));
|
UC_PROT_ALL));
|
||||||
uc_assert_success(uc_mem_write(uc,
|
uc_assert_success(uc_mem_write(uc,
|
||||||
PHY_STACK_REGION,
|
PHY_STACK_REGION,
|
||||||
X86_CODE32_ALPHA_MIXED,
|
code,
|
||||||
sizeof(X86_CODE32_ALPHA_MIXED) - 1));
|
info.st_size));
|
||||||
uc_assert_success(uc_reg_write(uc, UC_X86_REG_EAX, &eax));
|
uc_assert_success(uc_reg_write(uc, UC_X86_REG_EAX, &eax));
|
||||||
uc_assert_success(uc_reg_write(uc, UC_X86_REG_ECX, &ecx));
|
uc_assert_success(uc_reg_write(uc, UC_X86_REG_ECX, &ecx));
|
||||||
uc_assert_success(uc_reg_write(uc, UC_X86_REG_EDX, &edx));
|
uc_assert_success(uc_reg_write(uc, UC_X86_REG_EDX, &edx));
|
||||||
|
@ -275,7 +268,8 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state)
|
||||||
hook_code32,
|
hook_code32,
|
||||||
NULL,
|
NULL,
|
||||||
1,
|
1,
|
||||||
0));
|
0,
|
||||||
|
info));
|
||||||
|
|
||||||
uc_assert_success(uc_hook_add(uc,
|
uc_assert_success(uc_hook_add(uc,
|
||||||
&trace2,
|
&trace2,
|
||||||
|
@ -294,7 +288,7 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state)
|
||||||
#else
|
#else
|
||||||
PHY_STACK_REGION+0x0000,
|
PHY_STACK_REGION+0x0000,
|
||||||
#endif
|
#endif
|
||||||
PHY_STACK_REGION+sizeof(X86_CODE32_ALPHA_MIXED) - 1,
|
PHY_STACK_REGION+info.st_size,
|
||||||
0, 0));
|
0, 0));
|
||||||
|
|
||||||
uc_assert_success(uc_close(uc));
|
uc_assert_success(uc_close(uc));
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <cmocka.h>
|
#include <cmocka.h>
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert that err matches expect
|
* Assert that err matches expect
|
||||||
|
@ -38,5 +39,12 @@ do { \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
char * read_file(const char *filename, struct stat *info) {
|
||||||
|
stat(filename, info);
|
||||||
|
char *code = malloc(info->st_size);
|
||||||
|
FILE *fp = fopen(filename, "r");
|
||||||
|
fread(code, info->st_size, 1, fp);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* UNICORN_TEST_H */
|
#endif /* UNICORN_TEST_H */
|
||||||
|
|
49
tests/unit/x86_soft_paging_low.s
Normal file
49
tests/unit/x86_soft_paging_low.s
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Zero memory for page directories and page tables
|
||||||
|
mov $0x1000,%edi
|
||||||
|
mov $0x1000,%ecx
|
||||||
|
xor %eax,%eax
|
||||||
|
rep stos %eax,(%edi)
|
||||||
|
|
||||||
|
// Load DWORD [0x4000] with 0xDEADBEEF to retrieve later
|
||||||
|
mov $0x4000,%edi
|
||||||
|
mov $0xBEEF,%eax
|
||||||
|
mov %eax, (%edi)
|
||||||
|
|
||||||
|
// Identify map the first 4MiB of memory
|
||||||
|
mov $0x400,%ecx
|
||||||
|
mov $0x2000,%edi
|
||||||
|
mov $3, %eax
|
||||||
|
loop:
|
||||||
|
stos %eax,(%edi)
|
||||||
|
add $0x1000,%eax
|
||||||
|
loop loop
|
||||||
|
|
||||||
|
// Map phyiscal address 0x4000 to cirtual address 0x7FF000
|
||||||
|
mov $0x3ffc,%edi
|
||||||
|
mov $0x4003,%eax
|
||||||
|
mov %eax, (%edi)
|
||||||
|
|
||||||
|
// Add page tables into page directory
|
||||||
|
mov $0x1000, %edi
|
||||||
|
mov $0x2003, %eax
|
||||||
|
mov %eax, (%edi)
|
||||||
|
mov $0x1004, %edi
|
||||||
|
mov $0x3003, %eax
|
||||||
|
mov %eax, (%edi)
|
||||||
|
|
||||||
|
// Load the page directory register
|
||||||
|
mov $0x1000, %eax
|
||||||
|
mov %eax, %cr3
|
||||||
|
|
||||||
|
// Enable paging
|
||||||
|
mov %cr0, %eax
|
||||||
|
or $0x80000000, %eax
|
||||||
|
|
||||||
|
// Clear EAX
|
||||||
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
//Load using virtual memory address; EAX = 0xBEEF
|
||||||
|
xor %eax,%eax
|
||||||
|
mov $0x7FF000, %esi
|
||||||
|
mov (%esi), %eax
|
||||||
|
hlt
|
Loading…
Reference in a new issue