commit
34b0d11943
@ -68,558 +68,7 @@
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#include "tcg/tcg-op.h"
|
#include "libafl_extras/hook.h"
|
||||||
#include "tcg/tcg-internal.h"
|
|
||||||
#include "exec/helper-head.h"
|
|
||||||
|
|
||||||
#include "tcg/tcg-temp-internal.h"
|
|
||||||
|
|
||||||
#ifndef TARGET_LONG_BITS
|
|
||||||
#error "TARGET_LONG_BITS not defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
|
|
||||||
|
|
||||||
target_ulong libafl_gen_cur_pc;
|
|
||||||
|
|
||||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
|
||||||
target_ulong dst_block, int exit_n,
|
|
||||||
target_ulong cs_base, uint32_t flags,
|
|
||||||
int cflags);
|
|
||||||
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi);
|
|
||||||
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi);
|
|
||||||
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
|
|
||||||
void libafl_gen_backdoor(target_ulong pc);
|
|
||||||
|
|
||||||
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) | dh_typemask(i64, 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_edge_hook {
|
|
||||||
uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data);
|
|
||||||
void (*exec)(uint64_t id, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
uint64_t cur_id;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
struct libafl_edge_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_edge_hook* libafl_edge_hooks;
|
|
||||||
|
|
||||||
void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data),
|
|
||||||
void (*exec)(uint64_t id, uint64_t data),
|
|
||||||
uint64_t data);
|
|
||||||
void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data),
|
|
||||||
void (*exec)(uint64_t id, uint64_t data),
|
|
||||||
uint64_t data)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_edge_hook* hook = malloc(sizeof(struct libafl_edge_hook));
|
|
||||||
hook->gen = gen;
|
|
||||||
hook->exec = exec;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_edge_hooks;
|
|
||||||
libafl_edge_hooks = hook;
|
|
||||||
|
|
||||||
if (exec) {
|
|
||||||
memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info.func = exec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) | dh_typemask(i64, 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_block_hook {
|
|
||||||
uint64_t (*gen)(target_ulong pc, uint64_t data);
|
|
||||||
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data);
|
|
||||||
void (*exec)(uint64_t id, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
struct libafl_block_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_block_hook* libafl_block_hooks;
|
|
||||||
|
|
||||||
void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data),
|
|
||||||
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data),
|
|
||||||
void (*exec)(uint64_t id, uint64_t data), uint64_t data);
|
|
||||||
void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data),
|
|
||||||
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data),
|
|
||||||
void (*exec)(uint64_t id, uint64_t data), uint64_t data)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_block_hook* hook = malloc(sizeof(struct libafl_block_hook));
|
|
||||||
hook->gen = gen;
|
|
||||||
hook->post_gen = post_gen;
|
|
||||||
hook->exec = exec;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_block_hooks;
|
|
||||||
libafl_block_hooks = hook;
|
|
||||||
|
|
||||||
if (exec) {
|
|
||||||
memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info.func = exec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2)
|
|
||||||
| dh_typemask(i64, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
|
|
||||||
};
|
|
||||||
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(i64, 1) | dh_typemask(tl, 2)
|
|
||||||
| dh_typemask(i64, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_rw_hook {
|
|
||||||
uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data);
|
|
||||||
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data);
|
|
||||||
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data);
|
|
||||||
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data);
|
|
||||||
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data);
|
|
||||||
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info1;
|
|
||||||
TCGHelperInfo helper_info2;
|
|
||||||
TCGHelperInfo helper_info4;
|
|
||||||
TCGHelperInfo helper_info8;
|
|
||||||
TCGHelperInfo helper_infoN;
|
|
||||||
struct libafl_rw_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_rw_hook* libafl_read_hooks;
|
|
||||||
|
|
||||||
void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
|
|
||||||
uint64_t data);
|
|
||||||
void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
|
|
||||||
uint64_t data)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook));
|
|
||||||
hook->gen = gen;
|
|
||||||
hook->exec1 = exec1;
|
|
||||||
hook->exec2 = exec2;
|
|
||||||
hook->exec4 = exec4;
|
|
||||||
hook->exec8 = exec8;
|
|
||||||
hook->execN = execN;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_read_hooks;
|
|
||||||
libafl_read_hooks = hook;
|
|
||||||
|
|
||||||
if (exec1) {
|
|
||||||
memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info1.func = exec1;
|
|
||||||
}
|
|
||||||
if (exec2) {
|
|
||||||
memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info2.func = exec2;
|
|
||||||
}
|
|
||||||
if (exec4) {
|
|
||||||
memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info4.func = exec4;
|
|
||||||
}
|
|
||||||
if (exec8) {
|
|
||||||
memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info8.func = exec8;
|
|
||||||
}
|
|
||||||
if (execN) {
|
|
||||||
memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_infoN.func = execN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi)
|
|
||||||
{
|
|
||||||
size_t size = memop_size(get_memop(oi));
|
|
||||||
|
|
||||||
struct libafl_rw_hook* hook = libafl_read_hooks;
|
|
||||||
while (hook) {
|
|
||||||
uint64_t cur_id = 0;
|
|
||||||
if (hook->gen)
|
|
||||||
cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data);
|
|
||||||
TCGHelperInfo* info = NULL;
|
|
||||||
if (size == 1 && hook->exec1) info = &hook->helper_info1;
|
|
||||||
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
|
|
||||||
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
|
|
||||||
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
|
|
||||||
if (cur_id != (uint64_t)-1) {
|
|
||||||
if (info) {
|
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
|
|
||||||
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
|
|
||||||
addr,
|
|
||||||
tcgv_i64_temp(tmp1) };
|
|
||||||
tcg_gen_callN(info, NULL, tmp2);
|
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
} else if (hook->execN) {
|
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
|
||||||
TCGv tmp1 = tcg_constant_tl(size);
|
|
||||||
TCGv_i64 tmp2 = tcg_constant_i64(hook->data);
|
|
||||||
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
|
|
||||||
addr,
|
|
||||||
#if TARGET_LONG_BITS == 32
|
|
||||||
tcgv_i32_temp(tmp1),
|
|
||||||
#else
|
|
||||||
tcgv_i64_temp(tmp1),
|
|
||||||
#endif
|
|
||||||
tcgv_i64_temp(tmp2) };
|
|
||||||
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
|
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
#if TARGET_LONG_BITS == 32
|
|
||||||
tcg_temp_free_i32(tmp1);
|
|
||||||
#else
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
#endif
|
|
||||||
tcg_temp_free_i64(tmp2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hook = hook->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_rw_hook* libafl_write_hooks;
|
|
||||||
|
|
||||||
void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
|
|
||||||
uint64_t data);
|
|
||||||
void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
|
|
||||||
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
|
|
||||||
uint64_t data)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook));
|
|
||||||
hook->gen = gen;
|
|
||||||
hook->exec1 = exec1;
|
|
||||||
hook->exec2 = exec2;
|
|
||||||
hook->exec4 = exec4;
|
|
||||||
hook->exec8 = exec8;
|
|
||||||
hook->execN = execN;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_write_hooks;
|
|
||||||
libafl_write_hooks = hook;
|
|
||||||
|
|
||||||
if (exec1) {
|
|
||||||
memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info1.func = exec1;
|
|
||||||
}
|
|
||||||
if (exec2) {
|
|
||||||
memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info2.func = exec2;
|
|
||||||
}
|
|
||||||
if (exec4) {
|
|
||||||
memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info4.func = exec4;
|
|
||||||
}
|
|
||||||
if (exec8) {
|
|
||||||
memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info8.func = exec8;
|
|
||||||
}
|
|
||||||
if (execN) {
|
|
||||||
memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_infoN.func = execN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi)
|
|
||||||
{
|
|
||||||
size_t size = memop_size(get_memop(oi));
|
|
||||||
|
|
||||||
struct libafl_rw_hook* hook = libafl_write_hooks;
|
|
||||||
while (hook) {
|
|
||||||
uint64_t cur_id = 0;
|
|
||||||
if (hook->gen)
|
|
||||||
cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data);
|
|
||||||
TCGHelperInfo* info = NULL;
|
|
||||||
if (size == 1 && hook->exec1) info = &hook->helper_info1;
|
|
||||||
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
|
|
||||||
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
|
|
||||||
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
|
|
||||||
if (cur_id != (uint64_t)-1) {
|
|
||||||
if (info) {
|
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
|
|
||||||
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
|
|
||||||
addr,
|
|
||||||
tcgv_i64_temp(tmp1) };
|
|
||||||
tcg_gen_callN(info, NULL, tmp2);
|
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
} else if (hook->execN) {
|
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
|
||||||
TCGv tmp1 = tcg_constant_tl(size);
|
|
||||||
TCGv_i64 tmp2 = tcg_constant_i64(hook->data);
|
|
||||||
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
|
|
||||||
addr,
|
|
||||||
#if TARGET_LONG_BITS == 32
|
|
||||||
tcgv_i32_temp(tmp1),
|
|
||||||
#else
|
|
||||||
tcgv_i64_temp(tmp1),
|
|
||||||
#endif
|
|
||||||
tcgv_i64_temp(tmp2) };
|
|
||||||
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
|
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
#if TARGET_LONG_BITS == 32
|
|
||||||
tcg_temp_free_i32(tmp1);
|
|
||||||
#else
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
#endif
|
|
||||||
tcg_temp_free_i64(tmp2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hook = hook->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(i64, 1)
|
|
||||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
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(i64, 1)
|
|
||||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
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(i64, 1)
|
|
||||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
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(i64, 1)
|
|
||||||
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_cmp_hook {
|
|
||||||
uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data);
|
|
||||||
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data);
|
|
||||||
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data);
|
|
||||||
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data);
|
|
||||||
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info1;
|
|
||||||
TCGHelperInfo helper_info2;
|
|
||||||
TCGHelperInfo helper_info4;
|
|
||||||
TCGHelperInfo helper_info8;
|
|
||||||
struct libafl_cmp_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_cmp_hook* libafl_cmp_hooks;
|
|
||||||
|
|
||||||
void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data),
|
|
||||||
uint64_t data);
|
|
||||||
void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data),
|
|
||||||
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data),
|
|
||||||
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data),
|
|
||||||
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data),
|
|
||||||
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data),
|
|
||||||
uint64_t data)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_cmp_hook* hook = malloc(sizeof(struct libafl_cmp_hook));
|
|
||||||
hook->gen = gen;
|
|
||||||
hook->exec1 = exec1;
|
|
||||||
hook->exec2 = exec2;
|
|
||||||
hook->exec4 = exec4;
|
|
||||||
hook->exec8 = exec8;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_cmp_hooks;
|
|
||||||
libafl_cmp_hooks = hook;
|
|
||||||
|
|
||||||
if (exec1) {
|
|
||||||
memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info1.func = exec1;
|
|
||||||
}
|
|
||||||
if (exec2) {
|
|
||||||
memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info2.func = exec2;
|
|
||||||
}
|
|
||||||
if (exec4) {
|
|
||||||
memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info4.func = exec4;
|
|
||||||
}
|
|
||||||
if (exec8) {
|
|
||||||
memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info8.func = exec8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot)
|
|
||||||
{
|
|
||||||
size_t size = 0;
|
|
||||||
switch (ot & MO_SIZE) {
|
|
||||||
case MO_64:
|
|
||||||
size = 8;
|
|
||||||
break;
|
|
||||||
case MO_32:
|
|
||||||
size = 4;
|
|
||||||
break;
|
|
||||||
case MO_16:
|
|
||||||
size = 2;
|
|
||||||
break;
|
|
||||||
case MO_8:
|
|
||||||
size = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_cmp_hook* hook = libafl_cmp_hooks;
|
|
||||||
while (hook) {
|
|
||||||
uint64_t cur_id = 0;
|
|
||||||
if (hook->gen)
|
|
||||||
cur_id = hook->gen(pc, size, hook->data);
|
|
||||||
TCGHelperInfo* info = NULL;
|
|
||||||
if (size == 1 && hook->exec1) info = &hook->helper_info1;
|
|
||||||
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
|
|
||||||
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
|
|
||||||
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
|
|
||||||
if (cur_id != (uint64_t)-1 && info) {
|
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
|
|
||||||
TCGTemp *tmp2[4] = { 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
|
|
||||||
tcgv_i64_temp(tmp1) };
|
|
||||||
tcg_gen_callN(info, NULL, tmp2);
|
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
}
|
|
||||||
hook = hook->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static TCGHelperInfo libafl_exec_backdoor_hook_info = {
|
|
||||||
.func = NULL, .name = "libafl_exec_backdoor_hook", \
|
|
||||||
.flags = dh_callflag(void), \
|
|
||||||
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_backdoor_hook {
|
|
||||||
void (*exec)(target_ulong pc, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
struct libafl_backdoor_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_backdoor_hook* libafl_backdoor_hooks;
|
|
||||||
|
|
||||||
void libafl_add_backdoor_hook(void (*exec)(target_ulong pc, uint64_t data),
|
|
||||||
uint64_t data);
|
|
||||||
void libafl_add_backdoor_hook(void (*exec)(target_ulong id, uint64_t data),
|
|
||||||
uint64_t data)
|
|
||||||
{
|
|
||||||
struct libafl_backdoor_hook* hook = malloc(sizeof(struct libafl_backdoor_hook));
|
|
||||||
hook->exec = exec;
|
|
||||||
hook->data = data;
|
|
||||||
hook->next = libafl_backdoor_hooks;
|
|
||||||
libafl_backdoor_hooks = hook;
|
|
||||||
|
|
||||||
memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo));
|
|
||||||
hook->helper_info.func = exec;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
@ -840,10 +289,10 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,
|
|||||||
while (hook) {
|
while (hook) {
|
||||||
uint64_t cur_id = 0;
|
uint64_t cur_id = 0;
|
||||||
if (hook->gen)
|
if (hook->gen)
|
||||||
cur_id = hook->gen(pc, hook->data);
|
cur_id = hook->gen(hook->data, pc);
|
||||||
if (cur_id != (uint64_t)-1 && hook->exec) {
|
if (cur_id != (uint64_t)-1 && hook->helper_info.func) {
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
|
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
|
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||||
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
|
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
|
||||||
tcg_temp_free_i64(tmp0);
|
tcg_temp_free_i64(tmp0);
|
||||||
@ -912,8 +361,8 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
|||||||
while (hook) {
|
while (hook) {
|
||||||
hook->cur_id = 0;
|
hook->cur_id = 0;
|
||||||
if (hook->gen)
|
if (hook->gen)
|
||||||
hook->cur_id = hook->gen(src_block, dst_block, hook->data);
|
hook->cur_id = hook->gen(hook->data, src_block, dst_block);
|
||||||
if (hook->cur_id != (uint64_t)-1 && hook->exec)
|
if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func)
|
||||||
no_exec_hook = 0;
|
no_exec_hook = 0;
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
@ -970,10 +419,10 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
|||||||
hook = libafl_edge_hooks;
|
hook = libafl_edge_hooks;
|
||||||
size_t hcount = 0;
|
size_t hcount = 0;
|
||||||
while (hook) {
|
while (hook) {
|
||||||
if (hook->cur_id != (uint64_t)-1 && hook->exec) {
|
if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func) {
|
||||||
hcount++;
|
hcount++;
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(hook->cur_id);
|
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
|
TCGv_i64 tmp1 = tcg_constant_i64(hook->cur_id);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||||
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
|
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
|
||||||
tcg_temp_free_i64(tmp0);
|
tcg_temp_free_i64(tmp0);
|
||||||
@ -1193,7 +642,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
while (hook)
|
while (hook)
|
||||||
{
|
{
|
||||||
if (hook->post_gen)
|
if (hook->post_gen)
|
||||||
hook->post_gen(pc, tb->size, hook->data);
|
hook->post_gen(hook->data, pc, tb->size);
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,45 +114,13 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#include "tcg/tcg-internal.h"
|
#include "libafl_extras/exit.h"
|
||||||
#include "tcg/tcg-temp-internal.h"
|
#include "libafl_extras/hook.h"
|
||||||
|
|
||||||
#ifndef TARGET_LONG_BITS
|
#ifndef TARGET_LONG_BITS
|
||||||
#error "TARGET_LONG_BITS not defined"
|
#error "TARGET_LONG_BITS not defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
|
|
||||||
|
|
||||||
extern target_ulong libafl_gen_cur_pc;
|
|
||||||
|
|
||||||
struct libafl_breakpoint {
|
|
||||||
target_ulong addr;
|
|
||||||
struct libafl_breakpoint* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct libafl_breakpoint* libafl_qemu_breakpoints;
|
|
||||||
|
|
||||||
struct libafl_hook {
|
|
||||||
target_ulong addr;
|
|
||||||
void (*callback)(uint64_t);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
struct libafl_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct libafl_hook* libafl_qemu_hooks;
|
|
||||||
|
|
||||||
struct libafl_hook* libafl_search_hook(target_ulong addr);
|
|
||||||
|
|
||||||
struct libafl_backdoor_hook {
|
|
||||||
void (*exec)(target_ulong pc, uint64_t data);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
struct libafl_backdoor_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct libafl_backdoor_hook* libafl_backdoor_hooks;
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
bool translator_use_goto_tb(DisasContextBase *db, vaddr dest)
|
bool translator_use_goto_tb(DisasContextBase *db, vaddr dest)
|
||||||
@ -210,22 +178,22 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
|
|
||||||
struct libafl_hook* hk = libafl_search_hook(db->pc_next);
|
struct libafl_hook* hk = libafl_search_hook(db->pc_next);
|
||||||
if (hk) {
|
if (hk) {
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(hk->data);
|
TCGv_i64 tmp0 = tcg_constant_i64(hk->data);
|
||||||
#if TARGET_LONG_BITS == 32
|
#if TARGET_LONG_BITS == 32
|
||||||
TCGv_i32 tmp0 = tcg_constant_i32(db->pc_next);
|
TCGv_i32 tmp1 = tcg_constant_i32(db->pc_next);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i32_temp(tmp1) };
|
||||||
#else
|
#else
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(db->pc_next);
|
TCGv_i64 tmp1 = tcg_constant_i64(db->pc_next);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||||
#endif
|
#endif
|
||||||
// tcg_gen_callN(hk->callback, NULL, 2, tmp2);
|
// tcg_gen_callN(hk->callback, NULL, 2, tmp2);
|
||||||
tcg_gen_callN(&hk->helper_info, NULL, tmp2);
|
tcg_gen_callN(&hk->helper_info, NULL, tmp2);
|
||||||
#if TARGET_LONG_BITS == 32
|
#if TARGET_LONG_BITS == 32
|
||||||
tcg_temp_free_i32(tmp0);
|
tcg_temp_free_i32(tmp1);
|
||||||
#else
|
#else
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
#endif
|
|
||||||
tcg_temp_free_i64(tmp1);
|
tcg_temp_free_i64(tmp1);
|
||||||
|
#endif
|
||||||
|
tcg_temp_free_i64(tmp0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
|
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
|
||||||
@ -251,22 +219,22 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
if (backdoor == 0x44) {
|
if (backdoor == 0x44) {
|
||||||
struct libafl_backdoor_hook* bhk = libafl_backdoor_hooks;
|
struct libafl_backdoor_hook* bhk = libafl_backdoor_hooks;
|
||||||
while (bhk) {
|
while (bhk) {
|
||||||
TCGv_i64 tmp1 = tcg_constant_i64(bhk->data);
|
TCGv_i64 tmp0 = tcg_constant_i64(bhk->data);
|
||||||
#if TARGET_LONG_BITS == 32
|
#if TARGET_LONG_BITS == 32
|
||||||
TCGv_i32 tmp0 = tcg_constant_i32(db->pc_next);
|
TCGv_i32 tmp1 = tcg_constant_i32(db->pc_next);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i32_temp(tmp1) };
|
||||||
#else
|
#else
|
||||||
TCGv_i64 tmp0 = tcg_constant_i64(db->pc_next);
|
TCGv_i64 tmp1 = tcg_constant_i64(db->pc_next);
|
||||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||||
#endif
|
#endif
|
||||||
// tcg_gen_callN(bhk->exec, NULL, 2, tmp2);
|
// tcg_gen_callN(bhk->exec, NULL, 2, tmp2);
|
||||||
tcg_gen_callN(&bhk->helper_info, NULL, tmp2);
|
tcg_gen_callN(&bhk->helper_info, NULL, tmp2);
|
||||||
#if TARGET_LONG_BITS == 32
|
#if TARGET_LONG_BITS == 32
|
||||||
tcg_temp_free_i32(tmp0);
|
tcg_temp_free_i32(tmp1);
|
||||||
#else
|
#else
|
||||||
tcg_temp_free_i64(tmp0);
|
|
||||||
#endif
|
|
||||||
tcg_temp_free_i64(tmp1);
|
tcg_temp_free_i64(tmp1);
|
||||||
|
#endif
|
||||||
|
tcg_temp_free_i64(tmp0);
|
||||||
bhk = bhk->next;
|
bhk = bhk->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
166
cpu-target.c
166
cpu-target.c
@ -45,32 +45,8 @@
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#include "tcg/tcg-op.h"
|
|
||||||
#include "tcg/tcg-internal.h"
|
|
||||||
#include "exec/helper-head.h"
|
|
||||||
#include "libafl_extras/exit.h"
|
#include "libafl_extras/exit.h"
|
||||||
|
#include "libafl_extras/hook.h"
|
||||||
#define LIBAFL_TABLES_SIZE 16384
|
|
||||||
#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE)
|
|
||||||
|
|
||||||
struct libafl_breakpoint {
|
|
||||||
target_ulong addr;
|
|
||||||
struct libafl_breakpoint* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
|
|
||||||
|
|
||||||
struct libafl_hook {
|
|
||||||
target_ulong addr;
|
|
||||||
void (*callback)(target_ulong, uint64_t);
|
|
||||||
uint64_t data;
|
|
||||||
TCGHelperInfo helper_info;
|
|
||||||
size_t num;
|
|
||||||
struct libafl_hook* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
|
|
||||||
size_t libafl_qemu_hooks_num = 0;
|
|
||||||
|
|
||||||
static __thread GByteArray *libafl_qemu_mem_buf = NULL;
|
static __thread GByteArray *libafl_qemu_mem_buf = NULL;
|
||||||
|
|
||||||
@ -85,13 +61,6 @@ int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val);
|
|||||||
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val);
|
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val);
|
||||||
int libafl_qemu_num_regs(CPUState* cpu);
|
int libafl_qemu_num_regs(CPUState* cpu);
|
||||||
|
|
||||||
int libafl_qemu_set_breakpoint(target_ulong addr);
|
|
||||||
int libafl_qemu_remove_breakpoint(target_ulong addr);
|
|
||||||
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t),
|
|
||||||
uint64_t data, int invalidate);
|
|
||||||
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate);
|
|
||||||
int libafl_qemu_remove_hook(size_t num, int invalidate);
|
|
||||||
struct libafl_hook* libafl_search_hook(target_ulong addr);
|
|
||||||
void libafl_flush_jit(void);
|
void libafl_flush_jit(void);
|
||||||
|
|
||||||
extern int libafl_restoring_devices;
|
extern int libafl_restoring_devices;
|
||||||
@ -184,139 +153,6 @@ int libafl_qemu_num_regs(CPUState* cpu)
|
|||||||
return cc->gdb_num_core_regs;
|
return cc->gdb_num_core_regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
|
|
||||||
|
|
||||||
int libafl_qemu_set_breakpoint(target_ulong pc)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
libafl_breakpoint_invalidate(cpu, pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1);
|
|
||||||
bp->addr = pc;
|
|
||||||
bp->next = libafl_qemu_breakpoints;
|
|
||||||
libafl_qemu_breakpoints = bp;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_remove_breakpoint(target_ulong pc)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
struct libafl_breakpoint** bp = &libafl_qemu_breakpoints;
|
|
||||||
while (*bp) {
|
|
||||||
if ((*bp)->addr == pc) {
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
libafl_breakpoint_invalidate(cpu, pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
*bp = (*bp)->next;
|
|
||||||
r = 1;
|
|
||||||
} else {
|
|
||||||
bp = &(*bp)->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t),
|
|
||||||
uint64_t data, int invalidate)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
|
|
||||||
if (invalidate) {
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
libafl_breakpoint_invalidate(cpu, pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t idx = LIBAFL_TABLES_HASH(pc);
|
|
||||||
|
|
||||||
struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1);
|
|
||||||
hk->addr = pc;
|
|
||||||
hk->callback = callback;
|
|
||||||
hk->data = data;
|
|
||||||
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(tl, 1) | dh_typemask(i64, 2);
|
|
||||||
hk->num = libafl_qemu_hooks_num++;
|
|
||||||
hk->next = libafl_qemu_hooks[idx];
|
|
||||||
libafl_qemu_hooks[idx] = hk;
|
|
||||||
return hk->num;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
size_t r = 0;
|
|
||||||
|
|
||||||
size_t idx = LIBAFL_TABLES_HASH(addr);
|
|
||||||
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
|
|
||||||
while (*hk) {
|
|
||||||
if ((*hk)->addr == addr) {
|
|
||||||
if (invalidate) {
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
libafl_breakpoint_invalidate(cpu, addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tmp = *hk;
|
|
||||||
*hk = (*hk)->next;
|
|
||||||
free(tmp);
|
|
||||||
r++;
|
|
||||||
} else {
|
|
||||||
hk = &(*hk)->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_remove_hook(size_t num, int invalidate)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
size_t idx;
|
|
||||||
|
|
||||||
for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) {
|
|
||||||
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
|
|
||||||
while (*hk) {
|
|
||||||
if ((*hk)->num == num) {
|
|
||||||
if (invalidate) {
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
libafl_breakpoint_invalidate(cpu, (*hk)->addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tmp = *hk;
|
|
||||||
*hk = (*hk)->next;
|
|
||||||
free(tmp);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
hk = &(*hk)->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct libafl_hook* libafl_search_hook(target_ulong addr)
|
|
||||||
{
|
|
||||||
size_t idx = LIBAFL_TABLES_HASH(addr);
|
|
||||||
|
|
||||||
struct libafl_hook* hk = libafl_qemu_hooks[idx];
|
|
||||||
while (hk) {
|
|
||||||
if (hk->addr == addr) {
|
|
||||||
return hk;
|
|
||||||
}
|
|
||||||
hk = hk->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void libafl_flush_jit(void)
|
void libafl_flush_jit(void)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
@ -1601,8 +1601,8 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx)
|
|||||||
|
|
||||||
struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
|
struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
|
||||||
|
|
||||||
void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data);
|
void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data);
|
||||||
void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data)
|
void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data)
|
||||||
{
|
{
|
||||||
struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd));
|
struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd));
|
||||||
c->callback = callback;
|
c->callback = callback;
|
||||||
|
@ -236,7 +236,7 @@ int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
|
|||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
struct libafl_custom_gdb_cmd {
|
struct libafl_custom_gdb_cmd {
|
||||||
int (*callback)(uint8_t*, size_t, void*);
|
int (*callback)(void*, uint8_t*, size_t);
|
||||||
void* data;
|
void* data;
|
||||||
struct libafl_custom_gdb_cmd* next;
|
struct libafl_custom_gdb_cmd* next;
|
||||||
};
|
};
|
||||||
|
@ -534,7 +534,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx)
|
|||||||
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
||||||
int recognized = 0;
|
int recognized = 0;
|
||||||
while (*c) {
|
while (*c) {
|
||||||
recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data);
|
recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
|
||||||
c = &(*c)->next;
|
c = &(*c)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx)
|
|||||||
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
||||||
int recognized = 0;
|
int recognized = 0;
|
||||||
while (*c) {
|
while (*c) {
|
||||||
recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data);
|
recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
|
||||||
c = &(*c)->next;
|
c = &(*c)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,44 @@
|
|||||||
#define THREAD_MODIFIER
|
#define THREAD_MODIFIER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
|
||||||
|
|
||||||
|
int libafl_qemu_set_breakpoint(target_ulong pc)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
libafl_breakpoint_invalidate(cpu, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1);
|
||||||
|
bp->addr = pc;
|
||||||
|
bp->next = libafl_qemu_breakpoints;
|
||||||
|
libafl_qemu_breakpoints = bp;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_remove_breakpoint(target_ulong pc)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
struct libafl_breakpoint** bp = &libafl_qemu_breakpoints;
|
||||||
|
while (*bp) {
|
||||||
|
if ((*bp)->addr == pc) {
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
libafl_breakpoint_invalidate(cpu, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
*bp = (*bp)->next;
|
||||||
|
r = 1;
|
||||||
|
} else {
|
||||||
|
bp = &(*bp)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static THREAD_MODIFIER struct libafl_exit_reason last_exit_reason;
|
static THREAD_MODIFIER struct libafl_exit_reason last_exit_reason;
|
||||||
static THREAD_MODIFIER bool expected_exit = false;
|
static THREAD_MODIFIER bool expected_exit = false;
|
||||||
|
|
||||||
|
@ -5,6 +5,19 @@
|
|||||||
|
|
||||||
#define EXCP_LIBAFL_EXIT 0xf4775747
|
#define EXCP_LIBAFL_EXIT 0xf4775747
|
||||||
|
|
||||||
|
struct libafl_breakpoint {
|
||||||
|
target_ulong addr;
|
||||||
|
struct libafl_breakpoint* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_breakpoint* libafl_qemu_breakpoints;
|
||||||
|
|
||||||
|
// in cpu-target.c
|
||||||
|
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
|
||||||
|
|
||||||
|
int libafl_qemu_set_breakpoint(target_ulong pc);
|
||||||
|
int libafl_qemu_remove_breakpoint(target_ulong pc);
|
||||||
|
|
||||||
enum libafl_exit_reason_kind {
|
enum libafl_exit_reason_kind {
|
||||||
BREAKPOINT = 0,
|
BREAKPOINT = 0,
|
||||||
SYNC_BACKDOOR = 1
|
SYNC_BACKDOOR = 1
|
||||||
|
661
libafl_extras/hook.c
Normal file
661
libafl_extras/hook.c
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
#include "exec/exec-all.h"
|
||||||
|
#include "exec/tb-flush.h"
|
||||||
|
|
||||||
|
#include "hook.h"
|
||||||
|
#include "exit.h"
|
||||||
|
|
||||||
|
#ifndef TARGET_LONG_BITS
|
||||||
|
#error "TARGET_LONG_BITS not defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
target_ulong libafl_gen_cur_pc;
|
||||||
|
|
||||||
|
struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
|
||||||
|
size_t libafl_qemu_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t data, target_ulong pc),
|
||||||
|
uint64_t data, int invalidate)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
if (invalidate) {
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
libafl_breakpoint_invalidate(cpu, pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t idx = LIBAFL_TABLES_HASH(pc);
|
||||||
|
|
||||||
|
struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1);
|
||||||
|
hk->addr = pc;
|
||||||
|
// hk->callback = callback;
|
||||||
|
hk->data = data;
|
||||||
|
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) | dh_typemask(tl, 2);
|
||||||
|
// TODO check for overflow
|
||||||
|
hk->num = libafl_qemu_hooks_num++;
|
||||||
|
hk->next = libafl_qemu_hooks[idx];
|
||||||
|
libafl_qemu_hooks[idx] = hk;
|
||||||
|
return hk->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
size_t r = 0;
|
||||||
|
|
||||||
|
size_t idx = LIBAFL_TABLES_HASH(addr);
|
||||||
|
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
|
||||||
|
while (*hk) {
|
||||||
|
if ((*hk)->addr == addr) {
|
||||||
|
if (invalidate) {
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
libafl_breakpoint_invalidate(cpu, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *tmp = *hk;
|
||||||
|
*hk = (*hk)->next;
|
||||||
|
free(tmp);
|
||||||
|
r++;
|
||||||
|
} else {
|
||||||
|
hk = &(*hk)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_remove_hook(size_t num, int invalidate)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
size_t idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) {
|
||||||
|
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
|
||||||
|
while (*hk) {
|
||||||
|
if ((*hk)->num == num) {
|
||||||
|
if (invalidate) {
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
libafl_breakpoint_invalidate(cpu, (*hk)->addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *tmp = *hk;
|
||||||
|
*hk = (*hk)->next;
|
||||||
|
free(tmp);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
hk = &(*hk)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_hook* libafl_search_hook(target_ulong addr)
|
||||||
|
{
|
||||||
|
size_t idx = LIBAFL_TABLES_HASH(addr);
|
||||||
|
|
||||||
|
struct libafl_hook* hk = libafl_qemu_hooks[idx];
|
||||||
|
while (hk) {
|
||||||
|
if (hk->addr == addr) {
|
||||||
|
return hk;
|
||||||
|
}
|
||||||
|
hk = hk->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GEN_REMOVE_HOOK(name) \
|
||||||
|
int libafl_qemu_remove_##name##_hook(size_t num, int invalidate) \
|
||||||
|
{ \
|
||||||
|
CPUState *cpu; \
|
||||||
|
struct libafl_##name##_hook** hk = &libafl_##name##_hooks; \
|
||||||
|
\
|
||||||
|
while (*hk) { \
|
||||||
|
if ((*hk)->num == num) { \
|
||||||
|
if (invalidate) { \
|
||||||
|
CPU_FOREACH(cpu) { \
|
||||||
|
tb_flush(cpu); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void *tmp = *hk; \
|
||||||
|
*hk = (*hk)->next; \
|
||||||
|
free(tmp); \
|
||||||
|
return 1; \
|
||||||
|
} else { \
|
||||||
|
hk = &(*hk)->next; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GEN_REMOVE_HOOK1(name) \
|
||||||
|
int libafl_qemu_remove_##name##_hook(size_t num) \
|
||||||
|
{ \
|
||||||
|
struct libafl_##name##_hook** hk = &libafl_##name##_hooks; \
|
||||||
|
\
|
||||||
|
while (*hk) { \
|
||||||
|
if ((*hk)->num == num) { \
|
||||||
|
void *tmp = *hk; \
|
||||||
|
*hk = (*hk)->next; \
|
||||||
|
free(tmp); \
|
||||||
|
return 1; \
|
||||||
|
} else { \
|
||||||
|
hk = &(*hk)->next; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TCGHelperInfo libafl_exec_backdoor_hook_info = {
|
||||||
|
.func = NULL, .name = "libafl_exec_backdoor_hook", \
|
||||||
|
.flags = dh_callflag(void), \
|
||||||
|
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_backdoor_hook* libafl_backdoor_hooks;
|
||||||
|
size_t libafl_backdoor_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_backdoor_hook(void (*exec)(uint64_t data, target_ulong pc),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
struct libafl_backdoor_hook* hook = calloc(sizeof(struct libafl_backdoor_hook), 1);
|
||||||
|
// hook->exec = exec;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_backdoor_hooks_num++;
|
||||||
|
hook->next = libafl_backdoor_hooks;
|
||||||
|
libafl_backdoor_hooks = hook;
|
||||||
|
|
||||||
|
memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info.func = exec;
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(backdoor)
|
||||||
|
|
||||||
|
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) | dh_typemask(i64, 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_edge_hook* libafl_edge_hooks;
|
||||||
|
size_t libafl_edge_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst),
|
||||||
|
void (*exec)(uint64_t data, uint64_t id),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_edge_hook* hook = calloc(sizeof(struct libafl_edge_hook), 1);
|
||||||
|
hook->gen = gen;
|
||||||
|
// hook->exec = exec;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_edge_hooks_num++;
|
||||||
|
hook->next = libafl_edge_hooks;
|
||||||
|
libafl_edge_hooks = hook;
|
||||||
|
|
||||||
|
if (exec) {
|
||||||
|
memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info.func = exec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(edge)
|
||||||
|
|
||||||
|
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) | dh_typemask(i64, 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_block_hook* libafl_block_hooks;
|
||||||
|
size_t libafl_block_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc),
|
||||||
|
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length),
|
||||||
|
void (*exec)(uint64_t data, uint64_t id), uint64_t data)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_block_hook* hook = calloc(sizeof(struct libafl_block_hook), 1);
|
||||||
|
hook->gen = gen;
|
||||||
|
hook->post_gen = post_gen;
|
||||||
|
// hook->exec = exec;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_block_hooks_num++;
|
||||||
|
hook->next = libafl_block_hooks;
|
||||||
|
libafl_block_hooks = hook;
|
||||||
|
|
||||||
|
if (exec) {
|
||||||
|
memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info.func = exec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(block)
|
||||||
|
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2)
|
||||||
|
| dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
|
||||||
|
};
|
||||||
|
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(i64, 1) | dh_typemask(i64, 2)
|
||||||
|
| dh_typemask(tl, 3) | dh_typemask(i64, 4)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_rw_hook* libafl_read_hooks;
|
||||||
|
size_t libafl_read_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1);
|
||||||
|
hook->gen = gen;
|
||||||
|
/*hook->exec1 = exec1;
|
||||||
|
hook->exec2 = exec2;
|
||||||
|
hook->exec4 = exec4;
|
||||||
|
hook->exec8 = exec8;
|
||||||
|
hook->execN = execN;*/
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_read_hooks_num++;
|
||||||
|
hook->next = libafl_read_hooks;
|
||||||
|
libafl_read_hooks = hook;
|
||||||
|
|
||||||
|
if (exec1) {
|
||||||
|
memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info1.func = exec1;
|
||||||
|
}
|
||||||
|
if (exec2) {
|
||||||
|
memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info2.func = exec2;
|
||||||
|
}
|
||||||
|
if (exec4) {
|
||||||
|
memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info4.func = exec4;
|
||||||
|
}
|
||||||
|
if (exec8) {
|
||||||
|
memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info8.func = exec8;
|
||||||
|
}
|
||||||
|
if (execN) {
|
||||||
|
memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_infoN.func = execN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(read)
|
||||||
|
|
||||||
|
struct libafl_rw_hook* libafl_write_hooks;
|
||||||
|
size_t libafl_write_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1);
|
||||||
|
hook->gen = gen;
|
||||||
|
/*hook->exec1 = exec1;
|
||||||
|
hook->exec2 = exec2;
|
||||||
|
hook->exec4 = exec4;
|
||||||
|
hook->exec8 = exec8;
|
||||||
|
hook->execN = execN;*/
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_write_hooks_num++;
|
||||||
|
hook->next = libafl_write_hooks;
|
||||||
|
libafl_write_hooks = hook;
|
||||||
|
|
||||||
|
if (exec1) {
|
||||||
|
memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info1.func = exec1;
|
||||||
|
}
|
||||||
|
if (exec2) {
|
||||||
|
memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info2.func = exec2;
|
||||||
|
}
|
||||||
|
if (exec4) {
|
||||||
|
memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info4.func = exec4;
|
||||||
|
}
|
||||||
|
if (exec8) {
|
||||||
|
memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info8.func = exec8;
|
||||||
|
}
|
||||||
|
if (execN) {
|
||||||
|
memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_infoN.func = execN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(write)
|
||||||
|
|
||||||
|
static void libafl_gen_rw(TCGTemp *addr, MemOpIdx oi, struct libafl_rw_hook* hook)
|
||||||
|
{
|
||||||
|
size_t size = memop_size(get_memop(oi));
|
||||||
|
|
||||||
|
while (hook) {
|
||||||
|
uint64_t cur_id = 0;
|
||||||
|
if (hook->gen)
|
||||||
|
cur_id = hook->gen(hook->data, libafl_gen_cur_pc, oi);
|
||||||
|
TCGHelperInfo* info = NULL;
|
||||||
|
if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1;
|
||||||
|
else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2;
|
||||||
|
else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4;
|
||||||
|
else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8;
|
||||||
|
if (cur_id != (uint64_t)-1) {
|
||||||
|
if (info) {
|
||||||
|
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
|
||||||
|
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
|
||||||
|
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
|
||||||
|
tcgv_i64_temp(tmp1),
|
||||||
|
addr };
|
||||||
|
tcg_gen_callN(info, NULL, tmp2);
|
||||||
|
tcg_temp_free_i64(tmp0);
|
||||||
|
tcg_temp_free_i64(tmp1);
|
||||||
|
} else if (hook->helper_infoN.func) {
|
||||||
|
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
|
||||||
|
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
|
||||||
|
TCGv tmp2 = tcg_constant_tl(size);
|
||||||
|
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
|
||||||
|
tcgv_i64_temp(tmp1),
|
||||||
|
addr,
|
||||||
|
#if TARGET_LONG_BITS == 32
|
||||||
|
tcgv_i32_temp(tmp2) };
|
||||||
|
#else
|
||||||
|
tcgv_i64_temp(tmp2) };
|
||||||
|
#endif
|
||||||
|
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
|
||||||
|
tcg_temp_free_i64(tmp0);
|
||||||
|
tcg_temp_free_i64(tmp1);
|
||||||
|
#if TARGET_LONG_BITS == 32
|
||||||
|
tcg_temp_free_i32(tmp2);
|
||||||
|
#else
|
||||||
|
tcg_temp_free_i64(tmp2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hook = hook->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi)
|
||||||
|
{
|
||||||
|
libafl_gen_rw(addr, oi, libafl_read_hooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi)
|
||||||
|
{
|
||||||
|
libafl_gen_rw(addr, oi, libafl_write_hooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(i64, 1)
|
||||||
|
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
|
||||||
|
};
|
||||||
|
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(i64, 1)
|
||||||
|
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
|
||||||
|
};
|
||||||
|
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(i64, 1)
|
||||||
|
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
|
||||||
|
};
|
||||||
|
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(i64, 1)
|
||||||
|
| dh_typemask(i64, 2) | dh_typemask(i64, 3) | dh_typemask(i64, 4)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_cmp_hook* libafl_cmp_hooks;
|
||||||
|
size_t libafl_cmp_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_cmp_hook* hook = calloc(sizeof(struct libafl_cmp_hook), 1);
|
||||||
|
hook->gen = gen;
|
||||||
|
/*hook->exec1 = exec1;
|
||||||
|
hook->exec2 = exec2;
|
||||||
|
hook->exec4 = exec4;
|
||||||
|
hook->exec8 = exec8;*/
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_cmp_hooks_num++;
|
||||||
|
hook->next = libafl_cmp_hooks;
|
||||||
|
libafl_cmp_hooks = hook;
|
||||||
|
|
||||||
|
if (exec1) {
|
||||||
|
memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info1.func = exec1;
|
||||||
|
}
|
||||||
|
if (exec2) {
|
||||||
|
memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info2.func = exec2;
|
||||||
|
}
|
||||||
|
if (exec4) {
|
||||||
|
memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info4.func = exec4;
|
||||||
|
}
|
||||||
|
if (exec8) {
|
||||||
|
memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo));
|
||||||
|
hook->helper_info8.func = exec8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK(cmp)
|
||||||
|
|
||||||
|
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot)
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
switch (ot & MO_SIZE) {
|
||||||
|
case MO_64:
|
||||||
|
size = 8;
|
||||||
|
break;
|
||||||
|
case MO_32:
|
||||||
|
size = 4;
|
||||||
|
break;
|
||||||
|
case MO_16:
|
||||||
|
size = 2;
|
||||||
|
break;
|
||||||
|
case MO_8:
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_cmp_hook* hook = libafl_cmp_hooks;
|
||||||
|
while (hook) {
|
||||||
|
uint64_t cur_id = 0;
|
||||||
|
if (hook->gen)
|
||||||
|
cur_id = hook->gen(hook->data, pc, size);
|
||||||
|
TCGHelperInfo* info = NULL;
|
||||||
|
if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1;
|
||||||
|
else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2;
|
||||||
|
else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4;
|
||||||
|
else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8;
|
||||||
|
if (cur_id != (uint64_t)-1 && info) {
|
||||||
|
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
|
||||||
|
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
|
||||||
|
TCGTemp *tmp2[4] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1),
|
||||||
|
#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(info, NULL, tmp2);
|
||||||
|
tcg_temp_free_i64(tmp0);
|
||||||
|
tcg_temp_free_i64(tmp1);
|
||||||
|
}
|
||||||
|
hook = hook->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks;
|
||||||
|
struct libafl_post_syscall_hook* libafl_post_syscall_hooks;
|
||||||
|
|
||||||
|
size_t libafl_pre_syscall_hooks_num = 0;
|
||||||
|
size_t libafl_post_syscall_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_pre_syscall_hook(struct syshook_ret (*callback)(
|
||||||
|
uint64_t data, int sys_num, target_ulong arg0,
|
||||||
|
target_ulong arg1, target_ulong arg2,
|
||||||
|
target_ulong arg3, target_ulong arg4,
|
||||||
|
target_ulong arg5, target_ulong arg6,
|
||||||
|
target_ulong arg7),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
struct libafl_pre_syscall_hook* hook = calloc(sizeof(struct libafl_pre_syscall_hook), 1);
|
||||||
|
hook->callback = callback;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_pre_syscall_hooks_num++;
|
||||||
|
hook->next = libafl_pre_syscall_hooks;
|
||||||
|
libafl_pre_syscall_hooks = hook;
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t libafl_add_post_syscall_hook(target_ulong (*callback)(
|
||||||
|
uint64_t data, target_ulong ret, int sys_num,
|
||||||
|
target_ulong arg0, target_ulong arg1,
|
||||||
|
target_ulong arg2, target_ulong arg3,
|
||||||
|
target_ulong arg4, target_ulong arg5,
|
||||||
|
target_ulong arg6, target_ulong arg7),
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
struct libafl_post_syscall_hook* hook = calloc(sizeof(struct libafl_post_syscall_hook), 1);
|
||||||
|
hook->callback = callback;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_post_syscall_hooks_num++;
|
||||||
|
hook->next = libafl_post_syscall_hooks;
|
||||||
|
libafl_post_syscall_hooks = hook;
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK1(pre_syscall)
|
||||||
|
GEN_REMOVE_HOOK1(post_syscall)
|
||||||
|
|
||||||
|
struct libafl_new_thread_hook* libafl_new_thread_hooks;
|
||||||
|
size_t libafl_new_thread_hooks_num = 0;
|
||||||
|
|
||||||
|
size_t libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid),
|
||||||
|
uint64_t data) {
|
||||||
|
struct libafl_new_thread_hook* hook = calloc(sizeof(struct libafl_new_thread_hook), 1);
|
||||||
|
hook->callback = callback;
|
||||||
|
hook->data = data;
|
||||||
|
hook->num = libafl_new_thread_hooks_num++;
|
||||||
|
hook->next = libafl_new_thread_hooks;
|
||||||
|
libafl_new_thread_hooks = hook;
|
||||||
|
|
||||||
|
return hook->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_REMOVE_HOOK1(new_thread)
|
220
libafl_extras/hook.h
Normal file
220
libafl_extras/hook.h
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
#include "tcg/tcg-op.h"
|
||||||
|
#include "tcg/tcg-internal.h"
|
||||||
|
#include "tcg/tcg-temp-internal.h"
|
||||||
|
|
||||||
|
#define LIBAFL_TABLES_SIZE 16384
|
||||||
|
#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE)
|
||||||
|
|
||||||
|
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
|
||||||
|
|
||||||
|
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
||||||
|
target_ulong dst_block, int exit_n,
|
||||||
|
target_ulong cs_base, uint32_t flags,
|
||||||
|
int cflags);
|
||||||
|
|
||||||
|
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
|
||||||
|
void libafl_gen_backdoor(target_ulong pc);
|
||||||
|
|
||||||
|
extern target_ulong libafl_gen_cur_pc;
|
||||||
|
|
||||||
|
struct libafl_hook {
|
||||||
|
target_ulong addr;
|
||||||
|
// void (*callback)(uint64_t, target_ulong);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
TCGHelperInfo helper_info;
|
||||||
|
struct libafl_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
|
||||||
|
extern size_t libafl_qemu_hooks_num;
|
||||||
|
|
||||||
|
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t data, target_ulong pc),
|
||||||
|
uint64_t data, int invalidate);
|
||||||
|
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate);
|
||||||
|
int libafl_qemu_remove_hook(size_t num, int invalidate);
|
||||||
|
struct libafl_hook* libafl_search_hook(target_ulong addr);
|
||||||
|
|
||||||
|
struct libafl_backdoor_hook {
|
||||||
|
void (*exec)(uint64_t data, target_ulong pc);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
TCGHelperInfo helper_info;
|
||||||
|
struct libafl_backdoor_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_backdoor_hook* libafl_backdoor_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_backdoor_hook(void (*exec)(uint64_t data, target_ulong pc),
|
||||||
|
uint64_t data);
|
||||||
|
int libafl_qemu_remove_backdoor_hook(size_t num, int invalidate);
|
||||||
|
|
||||||
|
struct libafl_edge_hook {
|
||||||
|
uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst);
|
||||||
|
// void (*exec)(uint64_t data, uint64_t id);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
uint64_t cur_id;
|
||||||
|
TCGHelperInfo helper_info;
|
||||||
|
struct libafl_edge_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_edge_hook* libafl_edge_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst),
|
||||||
|
void (*exec)(uint64_t data, uint64_t id),
|
||||||
|
uint64_t data);
|
||||||
|
int libafl_qemu_remove_edge_hook(size_t num, int invalidate);
|
||||||
|
|
||||||
|
struct libafl_block_hook {
|
||||||
|
uint64_t (*gen)(uint64_t data, target_ulong pc);
|
||||||
|
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length);
|
||||||
|
// void (*exec)(uint64_t data, uint64_t id);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
TCGHelperInfo helper_info;
|
||||||
|
struct libafl_block_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_block_hook* libafl_block_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc),
|
||||||
|
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length),
|
||||||
|
void (*exec)(uint64_t data, uint64_t id), uint64_t data);
|
||||||
|
int libafl_qemu_remove_block_hook(size_t num, int invalidate);
|
||||||
|
|
||||||
|
struct libafl_rw_hook {
|
||||||
|
uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi);
|
||||||
|
/*void (*exec1)(uint64_t data, uint64_t id, target_ulong addr);
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr);
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr);
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr);
|
||||||
|
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size);*/
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
TCGHelperInfo helper_info1;
|
||||||
|
TCGHelperInfo helper_info2;
|
||||||
|
TCGHelperInfo helper_info4;
|
||||||
|
TCGHelperInfo helper_info8;
|
||||||
|
TCGHelperInfo helper_infoN;
|
||||||
|
struct libafl_rw_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// alias
|
||||||
|
#define libafl_read_hook libafl_rw_hook
|
||||||
|
#define libafl_write_hook libafl_rw_hook
|
||||||
|
|
||||||
|
extern struct libafl_rw_hook* libafl_read_hooks;
|
||||||
|
extern struct libafl_rw_hook* libafl_write_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
|
||||||
|
uint64_t data);
|
||||||
|
size_t libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
|
||||||
|
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
|
||||||
|
uint64_t data);
|
||||||
|
|
||||||
|
int libafl_qemu_remove_read_hook(size_t num, int invalidate);
|
||||||
|
int libafl_qemu_remove_write_hook(size_t num, int invalidate);
|
||||||
|
|
||||||
|
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi);
|
||||||
|
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi);
|
||||||
|
|
||||||
|
struct libafl_cmp_hook {
|
||||||
|
uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size);
|
||||||
|
/*void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1);
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1);
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1);
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1);*/
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
TCGHelperInfo helper_info1;
|
||||||
|
TCGHelperInfo helper_info2;
|
||||||
|
TCGHelperInfo helper_info4;
|
||||||
|
TCGHelperInfo helper_info8;
|
||||||
|
struct libafl_cmp_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_cmp_hook* libafl_cmp_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size),
|
||||||
|
void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1),
|
||||||
|
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1),
|
||||||
|
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1),
|
||||||
|
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1),
|
||||||
|
uint64_t data);
|
||||||
|
int libafl_qemu_remove_cmp_hook(size_t num, int invalidate);
|
||||||
|
|
||||||
|
struct syshook_ret {
|
||||||
|
target_ulong retval;
|
||||||
|
bool skip_syscall;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_pre_syscall_hook {
|
||||||
|
struct syshook_ret (*callback)(uint64_t data, int sys_num, target_ulong arg0,
|
||||||
|
target_ulong arg1, target_ulong arg2,
|
||||||
|
target_ulong arg3, target_ulong arg4,
|
||||||
|
target_ulong arg5, target_ulong arg6,
|
||||||
|
target_ulong arg7);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
struct libafl_pre_syscall_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libafl_post_syscall_hook {
|
||||||
|
target_ulong (*callback)(uint64_t data, target_ulong ret, int sys_num,
|
||||||
|
target_ulong arg0, target_ulong arg1,
|
||||||
|
target_ulong arg2, target_ulong arg3,
|
||||||
|
target_ulong arg4, target_ulong arg5,
|
||||||
|
target_ulong arg6, target_ulong arg7);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
struct libafl_post_syscall_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks;
|
||||||
|
extern struct libafl_post_syscall_hook* libafl_post_syscall_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_pre_syscall_hook(struct syshook_ret (*callback)(
|
||||||
|
uint64_t data, int sys_num, target_ulong arg0,
|
||||||
|
target_ulong arg1, target_ulong arg2,
|
||||||
|
target_ulong arg3, target_ulong arg4,
|
||||||
|
target_ulong arg5, target_ulong arg6,
|
||||||
|
target_ulong arg7),
|
||||||
|
uint64_t data);
|
||||||
|
size_t libafl_add_post_syscall_hook(target_ulong (*callback)(
|
||||||
|
uint64_t data, target_ulong ret, int sys_num,
|
||||||
|
target_ulong arg0, target_ulong arg1,
|
||||||
|
target_ulong arg2, target_ulong arg3,
|
||||||
|
target_ulong arg4, target_ulong arg5,
|
||||||
|
target_ulong arg6, target_ulong arg7),
|
||||||
|
uint64_t data);
|
||||||
|
|
||||||
|
int libafl_qemu_remove_pre_syscall_hook(size_t num);
|
||||||
|
int libafl_qemu_remove_post_syscall_hook(size_t num);
|
||||||
|
|
||||||
|
struct libafl_new_thread_hook {
|
||||||
|
bool (*callback)(uint64_t data, uint32_t tid);
|
||||||
|
uint64_t data;
|
||||||
|
size_t num;
|
||||||
|
struct libafl_new_thread_hook* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct libafl_new_thread_hook* libafl_new_thread_hooks;
|
||||||
|
|
||||||
|
size_t libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid),
|
||||||
|
uint64_t data);
|
||||||
|
int libafl_qemu_remove_new_thread_hook(size_t num);
|
@ -3,4 +3,4 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
|
|||||||
'syx-snapshot/syx-snapshot.c',
|
'syx-snapshot/syx-snapshot.c',
|
||||||
'syx-snapshot/channel-buffer-writeback.c',
|
'syx-snapshot/channel-buffer-writeback.c',
|
||||||
)])
|
)])
|
||||||
specific_ss.add(files('exit.c'))
|
specific_ss.add(files('exit.c', 'hook.c'))
|
||||||
|
@ -6522,8 +6522,9 @@ typedef struct {
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
|
#include "libafl_extras/hook.h"
|
||||||
|
|
||||||
extern __thread CPUArchState *libafl_qemu_env;
|
extern __thread CPUArchState *libafl_qemu_env;
|
||||||
void (*libafl_on_thread_hook)(uint32_t);
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
@ -6560,8 +6561,14 @@ static void *clone_func(void *arg)
|
|||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
libafl_qemu_env = env;
|
libafl_qemu_env = env;
|
||||||
if (libafl_on_thread_hook) {
|
if (libafl_new_thread_hooks) {
|
||||||
libafl_on_thread_hook(info->tid);
|
bool continue_execution = true;
|
||||||
|
struct libafl_new_thread_hook* h = libafl_new_thread_hooks;
|
||||||
|
while (h) {
|
||||||
|
continue_execution = h->callback(h->data, info->tid) && continue_execution;
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
if (continue_execution) cpu_loop(env);
|
||||||
} else {
|
} else {
|
||||||
cpu_loop(env);
|
cpu_loop(env);
|
||||||
}
|
}
|
||||||
@ -13706,17 +13713,6 @@ IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct syshook_ret {
|
|
||||||
uint64_t retval;
|
|
||||||
bool skip_syscall;
|
|
||||||
};
|
|
||||||
struct syshook_ret (*libafl_pre_syscall_hook)(int, uint64_t, uint64_t, uint64_t,
|
|
||||||
uint64_t, uint64_t, uint64_t,
|
|
||||||
uint64_t, uint64_t);
|
|
||||||
uint64_t (*libafl_post_syscall_hook)(uint64_t, int, uint64_t, uint64_t,
|
|
||||||
uint64_t, uint64_t, uint64_t, uint64_t,
|
|
||||||
uint64_t, uint64_t);
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
|
abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||||
@ -13750,21 +13746,26 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
if (libafl_pre_syscall_hook) {
|
bool skip_syscall = false;
|
||||||
struct syshook_ret hook_ret = libafl_pre_syscall_hook(num,
|
struct libafl_pre_syscall_hook* h = libafl_pre_syscall_hooks;
|
||||||
(uint64_t)arg1,
|
while (h) {
|
||||||
(uint64_t)arg2,
|
// no null check
|
||||||
(uint64_t)arg3,
|
struct syshook_ret hook_ret = h->callback(h->data, num,
|
||||||
(uint64_t)arg4,
|
(target_ulong)arg1,
|
||||||
(uint64_t)arg5,
|
(target_ulong)arg2,
|
||||||
(uint64_t)arg6,
|
(target_ulong)arg3,
|
||||||
(uint64_t)arg7,
|
(target_ulong)arg4,
|
||||||
(uint64_t)arg8);
|
(target_ulong)arg5,
|
||||||
if (hook_ret.skip_syscall) {
|
(target_ulong)arg6,
|
||||||
ret = (abi_ulong)hook_ret.retval;
|
(target_ulong)arg7,
|
||||||
goto after_syscall;
|
(target_ulong)arg8);
|
||||||
}
|
if (hook_ret.skip_syscall) {
|
||||||
|
skip_syscall = true;
|
||||||
|
ret = (abi_ulong)hook_ret.retval;
|
||||||
|
}
|
||||||
|
h = h->next;
|
||||||
}
|
}
|
||||||
|
if (skip_syscall) goto after_syscall;
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
@ -13773,19 +13774,22 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
after_syscall:
|
after_syscall:;
|
||||||
if (libafl_post_syscall_hook) {
|
struct libafl_post_syscall_hook* p = libafl_post_syscall_hooks;
|
||||||
ret = (abi_ulong)libafl_post_syscall_hook((uint64_t)ret, num,
|
while (p) {
|
||||||
(uint64_t)arg1,
|
// no null check
|
||||||
(uint64_t)arg2,
|
ret = (abi_ulong)p->callback(p->data, (target_ulong)ret, num,
|
||||||
(uint64_t)arg3,
|
(target_ulong)arg1,
|
||||||
(uint64_t)arg4,
|
(target_ulong)arg2,
|
||||||
(uint64_t)arg5,
|
(target_ulong)arg3,
|
||||||
(uint64_t)arg6,
|
(target_ulong)arg4,
|
||||||
(uint64_t)arg7,
|
(target_ulong)arg5,
|
||||||
(uint64_t)arg8);
|
(target_ulong)arg6,
|
||||||
|
(target_ulong)arg7,
|
||||||
|
(target_ulong)arg8);
|
||||||
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
|
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user