port libafl instrumentation
This commit is contained in:
parent
11e5d5be6a
commit
9658746a0c
@ -851,6 +851,14 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
#endif
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
||||
target_ulong dst_block, target_ulong cs_base,
|
||||
uint32_t flags, int cflags);
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* main execution loop */
|
||||
|
||||
int cpu_exec(CPUState *cpu)
|
||||
@ -964,8 +972,28 @@ int cpu_exec(CPUState *cpu)
|
||||
#endif
|
||||
/* See if we can patch the calling TB. */
|
||||
if (last_tb) {
|
||||
// tb_add_jump(last_tb, tb_exit, tb);
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
if (last_tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||
mmap_lock();
|
||||
TranslationBlock *edge = libafl_gen_edge(cpu, last_tb->pc, tb->pc,
|
||||
cs_base, flags, cflags);
|
||||
mmap_unlock();
|
||||
|
||||
if (edge) {
|
||||
tb_add_jump(last_tb, tb_exit, edge);
|
||||
tb_add_jump(edge, 0, tb);
|
||||
} else {
|
||||
tb_add_jump(last_tb, tb_exit, tb);
|
||||
}
|
||||
} else {
|
||||
tb_add_jump(last_tb, tb_exit, tb);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
}
|
||||
|
||||
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
|
||||
|
||||
|
@ -61,6 +61,375 @@
|
||||
#include "tb-context.h"
|
||||
#include "internal.h"
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "tcg/tcg-internal.h"
|
||||
#include "exec/helper-head.h"
|
||||
|
||||
void libafl_helper_table_add(TCGHelperInfo* info);
|
||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
||||
target_ulong dst_block, target_ulong cs_base,
|
||||
uint32_t flags, int cflags);
|
||||
void libafl_gen_read(TCGv addr, MemOp ot);
|
||||
void libafl_gen_read_N(TCGv addr, uint32_t size);
|
||||
void libafl_gen_write(TCGv addr, MemOp ot);
|
||||
void libafl_gen_write_N(TCGv addr, uint32_t size);
|
||||
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
|
||||
|
||||
void (*libafl_exec_edge_hook)(uint64_t id);
|
||||
uint64_t (*libafl_gen_edge_hook)(uint64_t src, uint64_t dst);
|
||||
|
||||
static TCGHelperInfo libafl_exec_edge_hook_info = {
|
||||
.func = NULL, .name = "libafl_exec_edge_hook", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
|
||||
};
|
||||
static int exec_edge_hook_added = 0;
|
||||
|
||||
void (*libafl_exec_block_hook)(uint64_t id);
|
||||
uint64_t (*libafl_gen_block_hook)(uint64_t pc);
|
||||
|
||||
static TCGHelperInfo libafl_exec_block_hook_info = {
|
||||
.func = NULL, .name = "libafl_exec_block_hook", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
|
||||
};
|
||||
static int exec_block_hook_added = 0;
|
||||
|
||||
void (*libafl_exec_read_hook1)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_read_hook2)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_read_hook4)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_read_hook8)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_read_hookN)(uint64_t id, uint64_t addr, uint32_t size);
|
||||
uint64_t (*libafl_gen_read_hook)(uint32_t size);
|
||||
|
||||
static TCGHelperInfo libafl_exec_read_hook1_info = {
|
||||
.func = NULL, .name = "libafl_exec_read_hook1", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_read_hook2_info = {
|
||||
.func = NULL, .name = "libafl_exec_read_hook2", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_read_hook4_info = {
|
||||
.func = NULL, .name = "libafl_exec_read_hook4", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_read_hook8_info = {
|
||||
.func = NULL, .name = "libafl_exec_read_hook8", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_read_hookN_info = {
|
||||
.func = NULL, .name = "libafl_exec_read_hookN", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i32, 2)
|
||||
};
|
||||
static int exec_read_hook_added = 0;
|
||||
|
||||
void libafl_gen_read(TCGv addr, MemOp ot)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
void* func = NULL;
|
||||
switch (ot & MO_SIZE) {
|
||||
case MO_64:
|
||||
size = 8;
|
||||
func = libafl_exec_read_hook8;
|
||||
break;
|
||||
case MO_32:
|
||||
size = 4;
|
||||
func = libafl_exec_read_hook4;
|
||||
break;
|
||||
case MO_16:
|
||||
size = 2;
|
||||
func = libafl_exec_read_hook2;
|
||||
break;
|
||||
case MO_8:
|
||||
size = 1;
|
||||
func = libafl_exec_read_hook1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_read_hook)
|
||||
libafl_id = libafl_gen_read_hook(size);
|
||||
if (func && libafl_id != (uint32_t)-1) {
|
||||
if (!exec_read_hook_added) {
|
||||
exec_read_hook_added = 1;
|
||||
libafl_exec_read_hook1_info.func = libafl_exec_read_hook1;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook1_info);
|
||||
libafl_exec_read_hook2_info.func = libafl_exec_read_hook2;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook2_info);
|
||||
libafl_exec_read_hook4_info.func = libafl_exec_read_hook4;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook4_info);
|
||||
libafl_exec_read_hook8_info.func = libafl_exec_read_hook8;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook8_info);
|
||||
libafl_exec_read_hookN_info.func = libafl_exec_read_hookN;
|
||||
libafl_helper_table_add(&libafl_exec_read_hookN_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGTemp *tmp1[2] = { tcgv_i64_temp(tmp0),
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcgv_i32_temp(addr) };
|
||||
#else
|
||||
tcgv_i64_temp(addr) };
|
||||
#endif
|
||||
tcg_gen_callN(func, NULL, 2, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
}
|
||||
|
||||
void libafl_gen_read_N(TCGv addr, uint32_t size)
|
||||
{
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_read_hook)
|
||||
libafl_id = libafl_gen_read_hook(size);
|
||||
if (libafl_id != (uint32_t)-1) {
|
||||
if (!exec_read_hook_added) {
|
||||
exec_read_hook_added = 1;
|
||||
libafl_exec_read_hook1_info.func = libafl_exec_read_hook1;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook1_info);
|
||||
libafl_exec_read_hook2_info.func = libafl_exec_read_hook2;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook2_info);
|
||||
libafl_exec_read_hook4_info.func = libafl_exec_read_hook4;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook4_info);
|
||||
libafl_exec_read_hook8_info.func = libafl_exec_read_hook8;
|
||||
libafl_helper_table_add(&libafl_exec_read_hook8_info);
|
||||
libafl_exec_read_hookN_info.func = libafl_exec_read_hookN;
|
||||
libafl_helper_table_add(&libafl_exec_read_hookN_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGv_i32 tmp1 = tcg_const_i32(size);
|
||||
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcgv_i32_temp(addr),
|
||||
#else
|
||||
tcgv_i64_temp(addr),
|
||||
#endif
|
||||
tcgv_i32_temp(tmp1)
|
||||
};
|
||||
tcg_gen_callN(libafl_exec_read_hookN, NULL, 3, tmp2);
|
||||
tcg_temp_free_i32(tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
}
|
||||
|
||||
void (*libafl_exec_write_hook1)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_write_hook2)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_write_hook4)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_write_hook8)(uint64_t id, uint64_t addr);
|
||||
void (*libafl_exec_write_hookN)(uint64_t id, uint64_t addr, uint32_t size);
|
||||
uint64_t (*libafl_gen_write_hook)(uint32_t size);
|
||||
|
||||
static TCGHelperInfo libafl_exec_write_hook1_info = {
|
||||
.func = NULL, .name = "libafl_exec_write_hook1", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_write_hook2_info = {
|
||||
.func = NULL, .name = "libafl_exec_write_hook2", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_write_hook4_info = {
|
||||
.func = NULL, .name = "libafl_exec_write_hook4", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_write_hook8_info = {
|
||||
.func = NULL, .name = "libafl_exec_write_hook8", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_write_hookN_info = {
|
||||
.func = NULL, .name = "libafl_exec_write_hookN", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i32, 2)
|
||||
};
|
||||
static int exec_write_hook_added = 0;
|
||||
|
||||
void libafl_gen_write(TCGv addr, MemOp ot)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
void* func = NULL;
|
||||
switch (ot & MO_SIZE) {
|
||||
case MO_64:
|
||||
size = 8;
|
||||
func = libafl_exec_write_hook8;
|
||||
break;
|
||||
case MO_32:
|
||||
size = 4;
|
||||
func = libafl_exec_write_hook4;
|
||||
break;
|
||||
case MO_16:
|
||||
size = 2;
|
||||
func = libafl_exec_write_hook2;
|
||||
break;
|
||||
case MO_8:
|
||||
size = 1;
|
||||
func = libafl_exec_write_hook1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_write_hook)
|
||||
libafl_id = libafl_gen_write_hook(size);
|
||||
if (func && libafl_id != (uint32_t)-1) {
|
||||
if (!exec_write_hook_added) {
|
||||
exec_write_hook_added = 1;
|
||||
libafl_exec_write_hook1_info.func = libafl_exec_write_hook1;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook1_info);
|
||||
libafl_exec_write_hook2_info.func = libafl_exec_write_hook2;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook2_info);
|
||||
libafl_exec_write_hook4_info.func = libafl_exec_write_hook4;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook4_info);
|
||||
libafl_exec_write_hook8_info.func = libafl_exec_write_hook8;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook8_info);
|
||||
libafl_exec_write_hookN_info.func = libafl_exec_write_hookN;
|
||||
libafl_helper_table_add(&libafl_exec_write_hookN_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGTemp *tmp1[2] = { tcgv_i64_temp(tmp0),
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcgv_i32_temp(addr) };
|
||||
#else
|
||||
tcgv_i64_temp(addr) };
|
||||
#endif
|
||||
tcg_gen_callN(func, NULL, 2, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
}
|
||||
|
||||
void libafl_gen_write_N(TCGv addr, uint32_t size)
|
||||
{
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_write_hook)
|
||||
libafl_id = libafl_gen_write_hook(size);
|
||||
if (libafl_id != (uint32_t)-1) {
|
||||
if (!exec_write_hook_added) {
|
||||
exec_write_hook_added = 1;
|
||||
libafl_exec_write_hook1_info.func = libafl_exec_write_hook1;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook1_info);
|
||||
libafl_exec_write_hook2_info.func = libafl_exec_write_hook2;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook2_info);
|
||||
libafl_exec_write_hook4_info.func = libafl_exec_write_hook4;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook4_info);
|
||||
libafl_exec_write_hook8_info.func = libafl_exec_write_hook8;
|
||||
libafl_helper_table_add(&libafl_exec_write_hook8_info);
|
||||
libafl_exec_write_hookN_info.func = libafl_exec_write_hookN;
|
||||
libafl_helper_table_add(&libafl_exec_write_hookN_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGv_i32 tmp1 = tcg_const_i32(size);
|
||||
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcgv_i32_temp(addr),
|
||||
#else
|
||||
tcgv_i64_temp(addr),
|
||||
#endif
|
||||
tcgv_i32_temp(tmp1)
|
||||
};
|
||||
tcg_gen_callN(libafl_exec_write_hookN, NULL, 3, tmp2);
|
||||
tcg_temp_free_i32(tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void (*libafl_exec_cmp_hook1)(uint64_t id, uint8_t v0, uint8_t v1);
|
||||
void (*libafl_exec_cmp_hook2)(uint64_t id, uint16_t v0, uint16_t v1);
|
||||
void (*libafl_exec_cmp_hook4)(uint64_t id, uint32_t v0, uint32_t v1);
|
||||
void (*libafl_exec_cmp_hook8)(uint64_t id, uint64_t v0, uint64_t v1);
|
||||
uint64_t (*libafl_gen_cmp_hook)(uint64_t pc, uint32_t size);
|
||||
|
||||
static TCGHelperInfo libafl_exec_cmp_hook1_info = {
|
||||
.func = NULL, .name = "libafl_exec_cmp_hook1", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i32, 1)
|
||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_cmp_hook2_info = {
|
||||
.func = NULL, .name = "libafl_exec_cmp_hook2", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i32, 1)
|
||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_cmp_hook4_info = {
|
||||
.func = NULL, .name = "libafl_exec_cmp_hook4", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i32, 1)
|
||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3)
|
||||
};
|
||||
static TCGHelperInfo libafl_exec_cmp_hook8_info = {
|
||||
.func = NULL, .name = "libafl_exec_cmp_hook8", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i32, 1)
|
||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3)
|
||||
};
|
||||
static int exec_cmp_hook_added = 0;
|
||||
|
||||
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
void* func = NULL;
|
||||
switch (ot & MO_SIZE) {
|
||||
case MO_64:
|
||||
size = 8;
|
||||
func = libafl_exec_cmp_hook8;
|
||||
break;
|
||||
case MO_32:
|
||||
size = 4;
|
||||
func = libafl_exec_cmp_hook4;
|
||||
break;
|
||||
case MO_16:
|
||||
size = 2;
|
||||
func = libafl_exec_cmp_hook2;
|
||||
break;
|
||||
case MO_8:
|
||||
size = 1;
|
||||
func = libafl_exec_cmp_hook1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_cmp_hook)
|
||||
libafl_id = libafl_gen_cmp_hook((uint64_t)pc, size);
|
||||
if (func && libafl_id != (uint32_t)-1) {
|
||||
if (!exec_cmp_hook_added) {
|
||||
exec_cmp_hook_added = 1;
|
||||
libafl_exec_cmp_hook1_info.func = libafl_exec_cmp_hook1;
|
||||
libafl_helper_table_add(&libafl_exec_cmp_hook1_info);
|
||||
libafl_exec_cmp_hook2_info.func = libafl_exec_cmp_hook2;
|
||||
libafl_helper_table_add(&libafl_exec_cmp_hook2_info);
|
||||
libafl_exec_cmp_hook4_info.func = libafl_exec_cmp_hook4;
|
||||
libafl_helper_table_add(&libafl_exec_cmp_hook4_info);
|
||||
libafl_exec_cmp_hook8_info.func = libafl_exec_cmp_hook8;
|
||||
libafl_helper_table_add(&libafl_exec_cmp_hook8_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGTemp *tmp1[3] = { tcgv_i64_temp(tmp0),
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcgv_i32_temp(op0), tcgv_i32_temp(op1) };
|
||||
#else
|
||||
tcgv_i64_temp(op0), tcgv_i64_temp(op1) };
|
||||
#endif
|
||||
tcg_gen_callN(func, NULL, 3, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* #define DEBUG_TB_INVALIDATE */
|
||||
/* #define DEBUG_TB_FLUSH */
|
||||
/* make various TB consistency checks */
|
||||
@ -1400,6 +1769,122 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
return tb;
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
/* Called with mmap_lock held for user mode emulation. */
|
||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
||||
target_ulong dst_block, target_ulong cs_base,
|
||||
uint32_t flags, int cflags)
|
||||
{
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
TranslationBlock *tb;
|
||||
tcg_insn_unit *gen_code_buf;
|
||||
int gen_code_size, search_size;
|
||||
|
||||
assert_memory_lock();
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_edge_hook)
|
||||
libafl_id = libafl_gen_edge_hook((uint64_t)src_block, (uint64_t)dst_block);
|
||||
if (!libafl_exec_edge_hook || libafl_id == (uint32_t)-1)
|
||||
return NULL;
|
||||
|
||||
if (!exec_edge_hook_added) {
|
||||
exec_edge_hook_added = 1;
|
||||
libafl_exec_edge_hook_info.func = libafl_exec_edge_hook;
|
||||
libafl_helper_table_add(&libafl_exec_edge_hook_info);
|
||||
}
|
||||
|
||||
buffer_overflow1:
|
||||
tb = tcg_tb_alloc(tcg_ctx);
|
||||
if (unlikely(!tb)) {
|
||||
/* flush must be done */
|
||||
tb_flush(cpu);
|
||||
mmap_unlock();
|
||||
/* Make the execution loop process the flush as soon as possible. */
|
||||
cpu->exception_index = EXCP_INTERRUPT;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
||||
libafl_exec_edge_hook(libafl_id);
|
||||
|
||||
gen_code_buf = tcg_ctx->code_gen_ptr;
|
||||
tb->tc.ptr = gen_code_buf;
|
||||
tb->pc = 0;
|
||||
tb->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
tb->cflags = cflags;
|
||||
tb->trace_vcpu_dstate = *cpu->trace_dstate;
|
||||
tcg_ctx->tb_cflags = 0;
|
||||
|
||||
tcg_func_start(tcg_ctx);
|
||||
|
||||
tcg_ctx->cpu = env_cpu(env);
|
||||
|
||||
TCGv_i64 tmp0 = tcg_const_i64(libafl_id);
|
||||
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||
tcg_gen_callN(libafl_exec_edge_hook, NULL, 1, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
|
||||
tcg_gen_goto_tb(0);
|
||||
tcg_gen_exit_tb(tb, 0);
|
||||
|
||||
tcg_ctx->cpu = NULL;
|
||||
|
||||
trace_translate_block(tb, tb->pc, tb->tc.ptr);
|
||||
|
||||
/* generate machine code */
|
||||
tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID;
|
||||
tb->jmp_reset_offset[1] = TB_JMP_RESET_OFFSET_INVALID;
|
||||
tcg_ctx->tb_jmp_reset_offset = tb->jmp_reset_offset;
|
||||
if (TCG_TARGET_HAS_direct_jump) {
|
||||
tcg_ctx->tb_jmp_insn_offset = tb->jmp_target_arg;
|
||||
tcg_ctx->tb_jmp_target_addr = NULL;
|
||||
} else {
|
||||
tcg_ctx->tb_jmp_insn_offset = NULL;
|
||||
tcg_ctx->tb_jmp_target_addr = tb->jmp_target_arg;
|
||||
}
|
||||
|
||||
/* ??? Overflow could be handled better here. In particular, we
|
||||
don't need to re-do gen_intermediate_code, nor should we re-do
|
||||
the tcg optimization currently hidden inside tcg_gen_code. All
|
||||
that should be required is to flush the TBs, allocate a new TB,
|
||||
re-initialize it per above, and re-do the actual code generation. */
|
||||
gen_code_size = tcg_gen_code(tcg_ctx, tb);
|
||||
if (unlikely(gen_code_size < 0)) {
|
||||
goto buffer_overflow1;
|
||||
}
|
||||
search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
|
||||
if (unlikely(search_size < 0)) {
|
||||
goto buffer_overflow1;
|
||||
}
|
||||
tb->tc.size = gen_code_size;
|
||||
|
||||
qatomic_set(&tcg_ctx->code_gen_ptr, (void *)
|
||||
ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,
|
||||
CODE_GEN_ALIGN));
|
||||
|
||||
/* init jump list */
|
||||
qemu_spin_init(&tb->jmp_lock);
|
||||
tb->jmp_list_head = (uintptr_t)NULL;
|
||||
tb->jmp_list_next[0] = (uintptr_t)NULL;
|
||||
tb->jmp_list_next[1] = (uintptr_t)NULL;
|
||||
tb->jmp_dest[0] = (uintptr_t)NULL;
|
||||
tb->jmp_dest[1] = (uintptr_t)NULL;
|
||||
|
||||
/* init original jump addresses which have been set during tcg_gen_code() */
|
||||
if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||
tb_reset_jump(tb, 0);
|
||||
}
|
||||
if (tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||
tb_reset_jump(tb, 1);
|
||||
}
|
||||
|
||||
return tb;
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* Called with mmap_lock held for user mode emulation. */
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
target_ulong pc, target_ulong cs_base,
|
||||
@ -1467,6 +1952,26 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tcg_func_start(tcg_ctx);
|
||||
|
||||
tcg_ctx->cpu = env_cpu(env);
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_block_hook)
|
||||
libafl_id = libafl_gen_block_hook((uint64_t)pc);
|
||||
if (libafl_exec_block_hook && libafl_id != (uint32_t)-1) {
|
||||
if (!exec_block_hook_added) {
|
||||
exec_block_hook_added = 1;
|
||||
libafl_exec_block_hook_info.func = libafl_exec_block_hook;
|
||||
libafl_helper_table_add(&libafl_exec_block_hook_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64((uint64_t)pc);
|
||||
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||
tcg_gen_callN(libafl_exec_block_hook, NULL, 1, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
gen_intermediate_code(cpu, tb, max_insns);
|
||||
assert(tb->size != 0);
|
||||
tcg_ctx->cpu = NULL;
|
||||
|
@ -18,6 +18,22 @@
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
#include "tcg/tcg-internal.h"
|
||||
|
||||
struct libafl_hook {
|
||||
target_ulong addr;
|
||||
void (*callback)(uint64_t);
|
||||
uint64_t value;
|
||||
TCGHelperInfo helper_info;
|
||||
struct libafl_hook* next;
|
||||
};
|
||||
|
||||
extern struct libafl_hook* libafl_qemu_hooks;
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* Pairs with tcg_clear_temp_count.
|
||||
To be called by #TranslatorOps.{translate_insn,tb_stop} if
|
||||
(1) the target is sufficiently clean to support reporting,
|
||||
@ -79,6 +95,21 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
plugin_gen_insn_start(cpu, db);
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
struct libafl_hook* hk = libafl_qemu_hooks;
|
||||
while (hk) {
|
||||
if (hk->addr == db->pc_next) {
|
||||
TCGv_i64 tmp0 = tcg_const_i64(hk->value);
|
||||
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||
tcg_gen_callN(hk->callback, NULL, 1, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
hk = hk->next;
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* Disassemble one instruction. The translate_insn hook should
|
||||
update db->pc_next and db->is_jmp to indicate what should be
|
||||
done next -- either exiting this loop or locate the start of
|
||||
|
152
cpu.c
152
cpu.c
@ -40,6 +40,140 @@
|
||||
#include "hw/core/accel-cpu.h"
|
||||
#include "trace/trace-root.h"
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "tcg/tcg-internal.h"
|
||||
#include "exec/helper-head.h"
|
||||
|
||||
struct libafl_hook {
|
||||
target_ulong addr;
|
||||
void (*callback)(uint64_t);
|
||||
uint64_t value;
|
||||
TCGHelperInfo helper_info;
|
||||
struct libafl_hook* next;
|
||||
};
|
||||
|
||||
struct libafl_hook* libafl_qemu_hooks = NULL;
|
||||
|
||||
__thread CPUArchState *libafl_qemu_env;
|
||||
|
||||
void libafl_helper_table_add(TCGHelperInfo* info);
|
||||
|
||||
static GByteArray *libafl_qemu_mem_buf = NULL;
|
||||
|
||||
int libafl_qemu_write_reg(int reg, uint8_t* val);
|
||||
int libafl_qemu_read_reg(int reg, uint8_t* val);
|
||||
int libafl_qemu_num_regs(void);
|
||||
int libafl_qemu_set_hook(uint64_t addr, void (*callback)(uint64_t), uint64_t value);
|
||||
int libafl_qemu_remove_hook(uint64_t addr);
|
||||
|
||||
int libafl_qemu_write_reg(int reg, uint8_t* val)
|
||||
{
|
||||
CPUState *cpu = current_cpu;
|
||||
if (!cpu) {
|
||||
cpu = env_cpu(libafl_qemu_env);
|
||||
if (!cpu) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
if (reg < cc->gdb_num_core_regs) {
|
||||
return cc->gdb_write_register(cpu, val, reg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libafl_qemu_read_reg(int reg, uint8_t* val)
|
||||
{
|
||||
CPUState *cpu = current_cpu;
|
||||
if (!cpu) {
|
||||
cpu = env_cpu(libafl_qemu_env);
|
||||
if (!cpu) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (libafl_qemu_mem_buf == NULL) {
|
||||
libafl_qemu_mem_buf = g_byte_array_sized_new(64);
|
||||
}
|
||||
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
if (reg < cc->gdb_num_core_regs) {
|
||||
g_byte_array_set_size(libafl_qemu_mem_buf, 0);
|
||||
int len = cc->gdb_read_register(cpu, libafl_qemu_mem_buf, reg);
|
||||
if (len > 0) {
|
||||
memcpy(val, libafl_qemu_mem_buf->data, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libafl_qemu_num_regs(void)
|
||||
{
|
||||
CPUState *cpu = current_cpu;
|
||||
if (!cpu) {
|
||||
cpu = env_cpu(libafl_qemu_env);
|
||||
if (!cpu) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
return cc->gdb_num_core_regs;
|
||||
}
|
||||
|
||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
|
||||
|
||||
int libafl_qemu_set_hook(uint64_t addr, void (*callback)(uint64_t), uint64_t value)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
target_ulong pc = (target_ulong) addr;
|
||||
CPU_FOREACH(cpu) {
|
||||
libafl_breakpoint_invalidate(cpu, pc);
|
||||
}
|
||||
|
||||
struct libafl_hook* hk = malloc(sizeof(struct libafl_hook));
|
||||
hk->addr = pc;
|
||||
hk->callback = callback;
|
||||
hk->value = value;
|
||||
hk->helper_info.func = callback;
|
||||
hk->helper_info.name = "libafl_hook";
|
||||
hk->helper_info.flags = dh_callflag(void);
|
||||
hk->helper_info.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1);
|
||||
hk->next = libafl_qemu_hooks;
|
||||
libafl_qemu_hooks = hk;
|
||||
libafl_helper_table_add(&hk->helper_info);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int libafl_qemu_remove_hook(uint64_t addr)
|
||||
{
|
||||
CPUState *cpu;
|
||||
int r = 0;
|
||||
|
||||
target_ulong pc = (target_ulong) addr;
|
||||
struct libafl_hook** hk = &libafl_qemu_hooks;
|
||||
while (*hk) {
|
||||
if ((*hk)->addr == pc) {
|
||||
CPU_FOREACH(cpu) {
|
||||
libafl_breakpoint_invalidate(cpu, pc);
|
||||
}
|
||||
|
||||
*hk = (*hk)->next;
|
||||
r = 1;
|
||||
} else {
|
||||
hk = &(*hk)->next;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
uintptr_t qemu_host_page_size;
|
||||
intptr_t qemu_host_page_mask;
|
||||
|
||||
@ -225,6 +359,15 @@ void tb_invalidate_phys_addr(target_ulong addr)
|
||||
tb_invalidate_phys_page_range(addr, addr + 1);
|
||||
mmap_unlock();
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||
{
|
||||
tb_invalidate_phys_addr(pc);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
#else
|
||||
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
|
||||
{
|
||||
@ -245,6 +388,15 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
|
||||
ram_addr = memory_region_get_ram_addr(mr) + addr;
|
||||
tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||
{
|
||||
tb_flush(cpu);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
#endif
|
||||
|
||||
/* Add a breakpoint. */
|
||||
|
10
tcg/tcg.c
10
tcg/tcg.c
@ -566,6 +566,16 @@ static void process_op_defs(TCGContext *s);
|
||||
static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
|
||||
TCGReg reg, const char *name);
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
void libafl_helper_table_add(TCGHelperInfo* info);
|
||||
void libafl_helper_table_add(TCGHelperInfo* info) {
|
||||
g_hash_table_insert(helper_table, (gpointer)info->func,
|
||||
(gpointer)info);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
static void tcg_context_init(unsigned max_cpus)
|
||||
{
|
||||
TCGContext *s = &tcg_init_ctx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user