mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-10 22:05:34 +00:00
Merge pull request #669 from adrianherrera/improvement/uc_context_sample
Added uc_context_* sample
This commit is contained in:
commit
ed6060737d
|
@ -40,6 +40,10 @@ x86Code32JmpInvalid = BS.pack [0xe9, 0xe9, 0xee, 0xee, 0xee, 0x41, 0x4a]
|
||||||
x86Code32InOut :: BS.ByteString
|
x86Code32InOut :: BS.ByteString
|
||||||
x86Code32InOut = BS.pack [0x41, 0xe4, 0x3f, 0x4a, 0xe6, 0x46, 0x43]
|
x86Code32InOut = BS.pack [0x41, 0xe4, 0x3f, 0x4a, 0xe6, 0x46, 0x43]
|
||||||
|
|
||||||
|
-- inc eax
|
||||||
|
x86Code32Inc :: BS.ByteString
|
||||||
|
x86Code32Inc = BS.pack [0x40]
|
||||||
|
|
||||||
x86Code64 :: BS.ByteString
|
x86Code64 :: BS.ByteString
|
||||||
x86Code64 = BS.pack [0x41, 0xbc, 0x3b, 0xb0, 0x28, 0x2a, 0x49, 0x0f, 0xc9,
|
x86Code64 = BS.pack [0x41, 0xbc, 0x3b, 0xb0, 0x28, 0x2a, 0x49, 0x0f, 0xc9,
|
||||||
0x90, 0x4d, 0x0f, 0xad, 0xcf, 0x49, 0x87, 0xfd, 0x90,
|
0x90, 0x4d, 0x0f, 0xad, 0xcf, 0x49, 0x87, 0xfd, 0x90,
|
||||||
|
@ -494,6 +498,70 @@ testI386InOut = do
|
||||||
Left err -> putStrLn $ "Failed with error " ++ show err ++ ": " ++
|
Left err -> putStrLn $ "Failed with error " ++ show err ++ ": " ++
|
||||||
strerror err
|
strerror err
|
||||||
|
|
||||||
|
-- Emulate code and save/restore the CPU context
|
||||||
|
testI386ContextSave :: IO ()
|
||||||
|
testI386ContextSave = do
|
||||||
|
putStrLn "==================================="
|
||||||
|
putStrLn "Save/restore CPU context in opaque blob"
|
||||||
|
|
||||||
|
result <- runEmulator $ do
|
||||||
|
-- Initialize emulator in X86-32bit mode
|
||||||
|
uc <- open ArchX86 [Mode32]
|
||||||
|
|
||||||
|
-- Map 8KB memory for this emulation
|
||||||
|
memMap uc address (8 * 1024) [ProtAll]
|
||||||
|
|
||||||
|
-- Write machine code to be emulated to memory
|
||||||
|
memWrite uc address x86Code32Inc
|
||||||
|
|
||||||
|
-- Initialize machine registers
|
||||||
|
regWrite uc X86.Eax 0x1
|
||||||
|
|
||||||
|
-- Emulate machine code in infinite time
|
||||||
|
emuPutStrLn ">>> Running emulation for the first time"
|
||||||
|
|
||||||
|
let codeLen = codeLength x86Code32Inc
|
||||||
|
start uc address (address + codeLen) Nothing Nothing
|
||||||
|
|
||||||
|
-- Now print out some registers
|
||||||
|
emuPutStrLn ">>> Emulation done. Below is the CPU context"
|
||||||
|
|
||||||
|
eax <- regRead uc X86.Eax
|
||||||
|
|
||||||
|
emuPutStrLn $ ">>> EAX = 0x" ++ showHex eax
|
||||||
|
|
||||||
|
-- Allocate and save the CPU context
|
||||||
|
emuPutStrLn ">>> Saving CPU context"
|
||||||
|
|
||||||
|
context <- contextAllocate uc
|
||||||
|
contextSave uc context
|
||||||
|
|
||||||
|
-- Emulate machine code again
|
||||||
|
emuPutStrLn ">>> Running emulation for the second time"
|
||||||
|
|
||||||
|
start uc address (address + codeLen) Nothing Nothing
|
||||||
|
|
||||||
|
-- Now print out some registers
|
||||||
|
emuPutStrLn ">>> Emulation done. Below is the CPU context"
|
||||||
|
|
||||||
|
eax <- regRead uc X86.Eax
|
||||||
|
|
||||||
|
emuPutStrLn $ ">>> EAX = 0x" ++ showHex eax
|
||||||
|
|
||||||
|
-- Restore CPU context
|
||||||
|
contextRestore uc context
|
||||||
|
|
||||||
|
-- Now print out some registers
|
||||||
|
emuPutStrLn ">>> Emulation done. Below is the CPU context"
|
||||||
|
|
||||||
|
eax <- regRead uc X86.Eax
|
||||||
|
|
||||||
|
emuPutStrLn $ ">>> EAX = 0x" ++ showHex eax
|
||||||
|
case result of
|
||||||
|
Right _ -> return ()
|
||||||
|
Left err -> putStrLn $ "Failed with error " ++ show err ++ ": " ++
|
||||||
|
strerror err
|
||||||
|
|
||||||
testX8664 :: IO ()
|
testX8664 :: IO ()
|
||||||
testX8664 = do
|
testX8664 = do
|
||||||
putStrLn "Emulate x86_64 code"
|
putStrLn "Emulate x86_64 code"
|
||||||
|
@ -660,6 +728,7 @@ main = do
|
||||||
["-32"] -> do
|
["-32"] -> do
|
||||||
testI386
|
testI386
|
||||||
testI386InOut
|
testI386InOut
|
||||||
|
testI386ContextSave
|
||||||
testI386Jump
|
testI386Jump
|
||||||
testI386Loop
|
testI386Loop
|
||||||
testI386InvalidMemRead
|
testI386InvalidMemRead
|
||||||
|
|
|
@ -38,7 +38,7 @@ module Unicorn
|
||||||
|
|
||||||
-- * Context operations
|
-- * Context operations
|
||||||
, Context
|
, Context
|
||||||
, contextAlloc
|
, contextAllocate
|
||||||
, contextSave
|
, contextSave
|
||||||
, contextRestore
|
, contextRestore
|
||||||
|
|
||||||
|
@ -273,9 +273,9 @@ memRegions uc = do
|
||||||
-- CPU context, which includes registers and some internal metadata. Contexts
|
-- CPU context, which includes registers and some internal metadata. Contexts
|
||||||
-- may not be shared across engine instances with differing architectures or
|
-- may not be shared across engine instances with differing architectures or
|
||||||
-- modes.
|
-- modes.
|
||||||
contextAlloc :: Engine -- ^ 'Unicon' engine handle
|
contextAllocate :: Engine -- ^ 'Unicon' engine handle
|
||||||
-> Emulator Context -- ^ A CPU context
|
-> Emulator Context -- ^ A CPU context
|
||||||
contextAlloc uc = do
|
contextAllocate uc = do
|
||||||
(err, contextPtr) <- lift $ ucContextAlloc uc
|
(err, contextPtr) <- lift $ ucContextAlloc uc
|
||||||
if err == ErrOk then
|
if err == ErrOk then
|
||||||
-- Return a CPU context if ucContextAlloc completed successfully
|
-- Return a CPU context if ucContextAlloc completed successfully
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx
|
#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx
|
||||||
#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||||
|
#define X86_CODE32_INC "\x40" // INC eax
|
||||||
|
|
||||||
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash
|
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash
|
||||||
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
|
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
|
||||||
|
@ -668,6 +669,105 @@ static void test_i386_inout(void)
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emulate code and save/restore the CPU context
|
||||||
|
static void test_i386_context_save(void)
|
||||||
|
{
|
||||||
|
uc_engine *uc;
|
||||||
|
uc_context *context;
|
||||||
|
uc_err err;
|
||||||
|
|
||||||
|
int r_eax = 0x1; // EAX register
|
||||||
|
|
||||||
|
printf("===================================\n");
|
||||||
|
printf("Save/restore CPU context in opaque blob\n");
|
||||||
|
|
||||||
|
// initialize emulator in X86-32bit mode
|
||||||
|
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map 8KB memory for this emulation
|
||||||
|
uc_mem_map(uc, ADDRESS, 8 * 1024, UC_PROT_ALL);
|
||||||
|
|
||||||
|
// write machine code to be emulated to memory
|
||||||
|
if (uc_mem_write(uc, ADDRESS, X86_CODE32_INC, sizeof(X86_CODE32_INC) - 1)) {
|
||||||
|
printf("Failed to write emulation code to memory, quit!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize machine registers
|
||||||
|
uc_reg_write(uc, UC_X86_REG_EAX, &r_eax);
|
||||||
|
|
||||||
|
// emulate machine code in infinite time
|
||||||
|
printf(">>> Running emulation for the first time\n");
|
||||||
|
|
||||||
|
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||||
|
err, uc_strerror(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now print out some registers
|
||||||
|
printf(">>> Emulation done. Below is the CPU context\n");
|
||||||
|
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
|
||||||
|
printf(">>> EAX = 0x%x\n", r_eax);
|
||||||
|
|
||||||
|
// allocate and save the CPU context
|
||||||
|
printf(">>> Saving CPU context\n");
|
||||||
|
|
||||||
|
err = uc_context_alloc(uc, &context);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_context_alloc() with error returned: %u\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_context_save(uc, context);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_context_save() with error returned: %u\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// emulate machine code again
|
||||||
|
printf(">>> Running emulation for the second time\n");
|
||||||
|
|
||||||
|
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||||
|
err, uc_strerror(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now print out some registers
|
||||||
|
printf(">>> Emulation done. Below is the CPU context\n");
|
||||||
|
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
|
||||||
|
printf(">>> EAX = 0x%x\n", r_eax);
|
||||||
|
|
||||||
|
// restore CPU context
|
||||||
|
err = uc_context_restore(uc, context);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_context_restore() with error returned: %u\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now print out some registers
|
||||||
|
printf(">>> CPU context restored. Below is the CPU context\n");
|
||||||
|
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &r_eax);
|
||||||
|
printf(">>> EAX = 0x%x\n", r_eax);
|
||||||
|
|
||||||
|
// free the CPU context
|
||||||
|
err = uc_context_free(context);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed on uc_context_free() with error returned: %u\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uc_close(uc);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_x86_64(void)
|
static void test_x86_64(void)
|
||||||
{
|
{
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
|
@ -906,6 +1006,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
test_i386();
|
test_i386();
|
||||||
test_i386_map_ptr();
|
test_i386_map_ptr();
|
||||||
test_i386_inout();
|
test_i386_inout();
|
||||||
|
test_i386_context_save();
|
||||||
test_i386_jump();
|
test_i386_jump();
|
||||||
test_i386_loop();
|
test_i386_loop();
|
||||||
test_i386_invalid_mem_read();
|
test_i386_invalid_mem_read();
|
||||||
|
|
Loading…
Reference in a new issue