diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..c54f4ca3b1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# QEMU LibAFL Bridge
+
+This is a patched QEMU that exposes an interface for LibAFL-based fuzzers.
+
+This raw interface is used in `libafl_qemu` that expose a more Rusty API.
+
+#### License
+
+
+This project extends the QEMU emulator, and our contributions to previously existing files adopt those files' respective licenses; the files that we have added are made available under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.
+
+
+
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index e5c0ccd1a2..959b121df0 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -626,6 +626,18 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
{
+ //// --- Begin LibAFL code ---
+
+#define EXCP_LIBAFL_BP 0xf4775747
+
+ if (cpu->exception_index == EXCP_LIBAFL_BP) {
+ *ret = cpu->exception_index;
+ cpu->exception_index = -1;
+ return true;
+ }
+
+ //// --- End LibAFL code ---
+
if (cpu->exception_index < 0) {
#ifndef CONFIG_USER_ONLY
if (replay_has_exception()
@@ -851,6 +863,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,7 +984,27 @@ 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);
+ // 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);
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index e4e030043f..762c410969 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -31,6 +31,19 @@
#include "exec/log.h"
#include "tcg/tcg.h"
+//// --- Begin LibAFL code ---
+
+#define EXCP_LIBAFL_BP 0xf4775747
+
+void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
+{
+ CPUState* cpu = env_cpu(env);
+ cpu->exception_index = EXCP_LIBAFL_BP;
+ cpu_loop_exit(cpu);
+}
+
+//// --- End LibAFL code ---
+
/* 32-bit helpers */
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)
diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
index 37cbd722bf..20eda6f1ec 100644
--- a/accel/tcg/tcg-runtime.h
+++ b/accel/tcg/tcg-runtime.h
@@ -285,3 +285,9 @@ DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+
+//// --- Begin LibAFL code ---
+
+DEF_HELPER_FLAGS_1(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG, void, env)
+
+//// --- End LibAFL code ---
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index bbfcfb698c..3b5994b56a 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -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;
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index c53a7f8e44..2ad28db09f 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -18,6 +18,29 @@
#include "exec/plugin-gen.h"
#include "sysemu/replay.h"
+//// --- Begin LibAFL code ---
+
+#include "tcg/tcg-internal.h"
+
+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 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 +102,29 @@ 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;
+ }
+
+ struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
+ while (bp) {
+ if (bp->addr == db->pc_next) {
+ gen_helper_libafl_qemu_handle_breakpoint(cpu_env);
+ }
+ bp = bp->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
diff --git a/configure b/configure
index 6e308ed77f..6f1925bfa1 100755
--- a/configure
+++ b/configure
@@ -835,6 +835,8 @@ if test "$mingw32" = "yes" ; then
fi
werror=""
+as_shared_lib="no"
+as_static_lib="no"
for opt do
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
@@ -1581,6 +1583,16 @@ for opt do
;;
--disable-slirp-smbd) slirp_smbd=no
;;
+ --as-shared-lib)
+ as_shared_lib="yes"
+ QEMU_CFLAGS="$QEMU_CFLAGS -fPIC -DAS_LIB=1"
+ QEMU_CXXFLAGS="$QEMU_CXXFLAGS -fPIC -DAS_LIB=1"
+ ;;
+ --as-static-lib)
+ as_static_lib="yes"
+ QEMU_CFLAGS="$QEMU_CFLAGS -fPIC -DAS_LIB=1"
+ QEMU_CXXFLAGS="$QEMU_CXXFLAGS -fPIC -DAS_LIB=1"
+ ;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -4919,6 +4931,13 @@ if test "$secret_keyring" = "yes" ; then
echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak
fi
+if test "$as_shared_lib" = "yes" ; then
+ echo "AS_SHARED_LIB=y" >> $config_host_mak
+fi
+if test "$as_static_lib" = "yes" ; then
+ echo "AS_STATIC_LIB=y" >> $config_host_mak
+fi
+
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
diff --git a/cpu.c b/cpu.c
index e1799a15bc..7dd96b7dbf 100644
--- a/cpu.c
+++ b/cpu.c
@@ -40,6 +40,187 @@
#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_breakpoint {
+ target_ulong addr;
+ struct libafl_breakpoint* next;
+};
+
+struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
+
+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_breakpoint(uint64_t addr);
+int libafl_qemu_remove_breakpoint(uint64_t addr);
+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_breakpoint(uint64_t addr)
+{
+ CPUState *cpu;
+
+ target_ulong pc = (target_ulong) addr;
+ CPU_FOREACH(cpu) {
+ libafl_breakpoint_invalidate(cpu, pc);
+ }
+
+ struct libafl_breakpoint* bp = malloc(sizeof(struct libafl_breakpoint));
+ bp->addr = pc;
+ bp->next = libafl_qemu_breakpoints;
+ libafl_qemu_breakpoints = bp;
+ return 1;
+}
+
+int libafl_qemu_remove_breakpoint(uint64_t addr)
+{
+ CPUState *cpu;
+ int r = 0;
+
+ target_ulong pc = (target_ulong) addr;
+ 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;
+}
+
+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 +406,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 +435,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. */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index ee72a1c20f..57c904bda2 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -88,6 +88,16 @@ void cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch (trapnr) {
+
+//// --- Begin LibAFL code ---
+
+#define EXCP_LIBAFL_BP 0xf4775747
+
+ case EXCP_LIBAFL_BP:
+ return;
+
+//// --- End LibAFL code ---
+
case EXCP_SWI:
ret = do_syscall(env,
env->xregs[8],
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 69632d15be..20f0dc2f09 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -298,6 +298,16 @@ void cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch(trapnr) {
+
+//// --- Begin LibAFL code ---
+
+#define EXCP_LIBAFL_BP 0xf4775747
+
+ case EXCP_LIBAFL_BP:
+ return;
+
+//// --- End LibAFL code ---
+
case EXCP_UDEF:
case EXCP_NOCP:
case EXCP_INVSTATE:
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index f813e87294..f1a64cf278 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -209,6 +209,16 @@ void cpu_loop(CPUX86State *env)
process_queued_cpu_work(cs);
switch(trapnr) {
+
+//// --- Begin LibAFL code ---
+
+#define EXCP_LIBAFL_BP 0xf4775747
+
+ case EXCP_LIBAFL_BP:
+ return;
+
+//// --- End LibAFL code ---
+
case 0x80:
/* linux syscall from int $0x80 */
ret = do_syscall(env,
diff --git a/linux-user/main.c b/linux-user/main.c
index 37ed50d98e..a4b60a3955 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -582,6 +582,16 @@ static int parse_args(int argc, char **argv)
r++;
}
+ if (!strncmp(r, "libafl", 6)) {
+ if (optind >= argc) {
+ (void) fprintf(stderr,
+ "qemu: missing argument for option '%s'\n", r);
+ exit(EXIT_FAILURE);
+ }
+ optind++;
+ continue;
+ }
+
for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
if (!strcmp(r, arginfo->argv)) {
if (arginfo->has_arg) {
@@ -611,16 +621,51 @@ static int parse_args(int argc, char **argv)
exit(EXIT_FAILURE);
}
- exec_path = argv[optind];
+ exec_path = strdup(argv[optind]);
return optind;
}
+//// --- Begin LibAFL code ---
+
+uint64_t libafl_load_addr(void);
+int libafl_qemu_main(void);
+int libafl_qemu_run(void);
+
+extern __thread CPUArchState *libafl_qemu_env;
+
+struct image_info libafl_image_info;
+struct linux_binprm bprm;
+
+uint64_t libafl_load_addr(void) {
+ return libafl_image_info.load_addr;
+}
+
+__attribute__((weak)) int libafl_qemu_main(void)
+{
+ libafl_qemu_run();
+ return 0;
+}
+
+int libafl_qemu_run(void)
+{
+ cpu_loop(libafl_qemu_env);
+ return 1;
+}
+
+//// --- End LibAFL code ---
+
+#ifdef AS_LIB
+int qemu_user_init(int argc, char **argv, char **envp);
+int qemu_user_init(int argc, char **argv, char **envp)
+#else
int main(int argc, char **argv, char **envp)
+#endif
{
struct target_pt_regs regs1, *regs = ®s1;
- struct image_info info1, *info = &info1;
- struct linux_binprm bprm;
+ //struct image_info info1, *info = &info1;
+ struct image_info *info = &libafl_image_info;
+ // struct linux_binprm bprm;
TaskState *ts;
CPUArchState *env;
CPUState *cpu;
@@ -882,7 +927,18 @@ int main(int argc, char **argv, char **envp)
}
gdb_handlesig(cpu, 0);
}
- cpu_loop(env);
+ // cpu_loop(env);
+
+ //// --- Begin LibAFL code ---
+
+ libafl_qemu_env = env;
+
+#ifndef AS_LIB
+ return libafl_qemu_main();
+#endif
+
+ //// --- End LibAFL code ---
+
/* never exits */
return 0;
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ccd3892b2d..f43c132f2d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -756,6 +756,23 @@ void target_set_brk(abi_ulong new_brk)
brk_page = HOST_PAGE_ALIGN(target_brk);
}
+//// --- Begin LibAFL code ---
+
+uint64_t libafl_get_brk(void);
+uint64_t libafl_set_brk(uint64_t new_brk);
+
+uint64_t libafl_get_brk(void) {
+ return (uint64_t)target_brk;
+}
+
+uint64_t libafl_set_brk(uint64_t new_brk) {
+ uint64_t old_brk = (uint64_t)target_brk;
+ target_brk = (abi_ulong)new_brk;
+ return old_brk;
+}
+
+//// --- End LibAFL code ---
+
//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
#define DEBUGF_BRK(message, args...)
@@ -13115,6 +13132,67 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
return ret;
}
+//// --- Begin LibAFL code ---
+
+struct libafl_mapinfo {
+ uint64_t start, end;
+ uint64_t offset;
+ const char* path;
+ int flags, is_priv;
+};
+GSList * libafl_maps_next(GSList *map_info, struct libafl_mapinfo* ret);
+
+GSList * libafl_maps_next(GSList *map_info, struct libafl_mapinfo* ret) {
+ if (!map_info || !ret)
+ return NULL;
+ GSList *s = g_slist_next(map_info);
+ if (!s)
+ return NULL;
+ MapInfo *e = (MapInfo *) s->data;
+
+ if (h2g_valid(e->start)) {
+ unsigned long min = e->start;
+ unsigned long max = e->end;
+ int flags = page_get_flags(h2g(min));
+
+ max = h2g_valid(max - 1) ?
+ max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
+
+ if (page_check_range(h2g(min), max - min, flags) == -1) {
+ return libafl_maps_next(s, ret);
+ }
+
+ int libafl_flags = 0;
+ if (flags & PAGE_READ) libafl_flags |= PROT_READ;
+ if (flags & PAGE_WRITE_ORG) libafl_flags |= PROT_WRITE;
+ if (flags & PAGE_EXEC) libafl_flags |= PROT_EXEC;
+
+ ret->start = (uint64_t)min;
+ ret->end = (uint64_t)max;
+ ret->offset = (uint64_t)e->offset;
+ ret->path = e->path;
+ ret->flags = libafl_flags;
+ ret->is_priv = e->is_priv;
+
+ return s;
+ } else {
+ return libafl_maps_next(s, ret);
+ }
+}
+
+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 ---
+
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6, abi_long arg7,
@@ -13144,9 +13222,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
}
+ //// --- Begin LibAFL code ---
+
+ if (libafl_pre_syscall_hook) {
+ struct syshook_ret hook_ret = libafl_pre_syscall_hook(num,
+ (uint64_t)arg1,
+ (uint64_t)arg2,
+ (uint64_t)arg3,
+ (uint64_t)arg4,
+ (uint64_t)arg5,
+ (uint64_t)arg6,
+ (uint64_t)arg7,
+ (uint64_t)arg8);
+ if (hook_ret.skip_syscall) {
+ ret = (abi_ulong)hook_ret.retval;
+ goto after_syscall;
+ }
+ }
+
+ //// --- End LibAFL code ---
+
ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
arg5, arg6, arg7, arg8);
+ //// --- Begin LibAFL code ---
+
+ if (libafl_post_syscall_hook) {
+ ret = (abi_ulong)libafl_post_syscall_hook((uint64_t)ret, num,
+ (uint64_t)arg1,
+ (uint64_t)arg2,
+ (uint64_t)arg3,
+ (uint64_t)arg4,
+ (uint64_t)arg5,
+ (uint64_t)arg6,
+ (uint64_t)arg7,
+ (uint64_t)arg8);
+ }
+
+after_syscall:
+ //// --- End LibAFL code ---
+
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
print_syscall_ret(cpu_env, num, ret, arg1, arg2,
arg3, arg4, arg5, arg6);
diff --git a/meson.build b/meson.build
index b3e7ec0e92..d9e4d42e71 100644
--- a/meson.build
+++ b/meson.build
@@ -1797,7 +1797,8 @@ if capstone_opt == 'internal'
build_by_default: false,
sources: capstone_files,
c_args: capstone_cargs,
- include_directories: 'capstone/include')
+ include_directories: 'capstone/include',
+ pic: 'AS_SHARED_LIB' in config_host)
capstone = declare_dependency(link_with: libcapstone,
include_directories: 'capstone/include/capstone')
endif
@@ -1877,7 +1878,8 @@ if have_system
build_by_default: false,
sources: slirp_files,
c_args: slirp_cargs,
- include_directories: slirp_inc)
+ include_directories: slirp_inc,
+ pic: 'AS_SHARED_LIB' in config_host)
slirp = declare_dependency(link_with: libslirp,
dependencies: slirp_deps,
include_directories: slirp_inc)
@@ -1934,7 +1936,8 @@ if have_system
libfdt = static_library('fdt',
build_by_default: false,
sources: fdt_files,
- include_directories: fdt_inc)
+ include_directories: fdt_inc,
+ pic: 'AS_SHARED_LIB' in config_host)
fdt = declare_dependency(link_with: libfdt,
include_directories: fdt_inc)
endif
@@ -2202,7 +2205,8 @@ util_ss.add_all(trace_ss)
util_ss = util_ss.apply(config_all, strict: false)
libqemuutil = static_library('qemuutil',
sources: util_ss.sources() + stub_ss.sources() + genh,
- dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
+ dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman],
+ pic: 'AS_SHARED_LIB' in config_host)
qemuutil = declare_dependency(link_with: libqemuutil,
sources: genh + version_res)
@@ -2267,7 +2271,8 @@ if get_option('b_lto')
pagevary_flags += '-fno-sanitize=cfi-icall'
endif
pagevary = static_library('page-vary-common', sources: pagevary,
- c_args: pagevary_flags)
+ c_args: pagevary_flags,
+ pic: 'AS_SHARED_LIB' in config_host)
pagevary = declare_dependency(link_with: pagevary)
endif
common_ss.add(pagevary)
@@ -2393,7 +2398,8 @@ if enable_modules
input: modinfo_files,
command: [modinfo_generate, '@INPUT@'],
capture: true)
- modinfo_lib = static_library('modinfo', modinfo_src)
+ modinfo_lib = static_library('modinfo', modinfo_src,
+ pic: 'AS_SHARED_LIB' in config_host)
modinfo_dep = declare_dependency(link_whole: modinfo_lib)
softmmu_ss.add(modinfo_dep)
endif
@@ -2412,7 +2418,8 @@ qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
qom_ss = qom_ss.apply(config_host, strict: false)
libqom = static_library('qom', qom_ss.sources() + genh,
dependencies: [qom_ss.dependencies()],
- name_suffix: 'fa')
+ name_suffix: 'fa',
+ pic: 'AS_SHARED_LIB' in config_host)
qom = declare_dependency(link_whole: libqom)
@@ -2420,7 +2427,8 @@ authz_ss = authz_ss.apply(config_host, strict: false)
libauthz = static_library('authz', authz_ss.sources() + genh,
dependencies: [authz_ss.dependencies()],
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
authz = declare_dependency(link_whole: libauthz,
dependencies: qom)
@@ -2429,7 +2437,8 @@ crypto_ss = crypto_ss.apply(config_host, strict: false)
libcrypto = static_library('crypto', crypto_ss.sources() + genh,
dependencies: [crypto_ss.dependencies()],
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
crypto = declare_dependency(link_whole: libcrypto,
dependencies: [authz, qom])
@@ -2439,13 +2448,15 @@ libio = static_library('io', io_ss.sources() + genh,
dependencies: [io_ss.dependencies()],
link_with: libqemuutil,
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
io = declare_dependency(link_whole: libio, dependencies: [crypto, qom])
libmigration = static_library('migration', sources: migration_files + genh,
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
migration = declare_dependency(link_with: libmigration,
dependencies: [zlib, qom, io])
softmmu_ss.add(migration)
@@ -2455,7 +2466,8 @@ libblock = static_library('block', block_ss.sources() + genh,
dependencies: block_ss.dependencies(),
link_depends: block_syms,
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
block = declare_dependency(link_whole: [libblock],
link_args: '@block.syms',
@@ -2465,7 +2477,8 @@ blockdev_ss = blockdev_ss.apply(config_host, strict: false)
libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
dependencies: blockdev_ss.dependencies(),
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
blockdev = declare_dependency(link_whole: [libblockdev],
dependencies: [block])
@@ -2474,20 +2487,23 @@ qmp_ss = qmp_ss.apply(config_host, strict: false)
libqmp = static_library('qmp', qmp_ss.sources() + genh,
dependencies: qmp_ss.dependencies(),
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
qmp = declare_dependency(link_whole: [libqmp])
libchardev = static_library('chardev', chardev_ss.sources() + genh,
name_suffix: 'fa',
dependencies: [gnutls],
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
chardev = declare_dependency(link_whole: libchardev)
libhwcore = static_library('hwcore', sources: hwcore_files + genh,
name_suffix: 'fa',
- build_by_default: false)
+ build_by_default: false,
+ pic: 'AS_SHARED_LIB' in config_host)
hwcore = declare_dependency(link_whole: libhwcore)
common_ss.add(hwcore)
@@ -2515,7 +2531,8 @@ common_all = static_library('common',
sources: common_all.sources() + genh,
implicit_include_directories: false,
dependencies: common_all.dependencies(),
- name_suffix: 'fa')
+ name_suffix: 'fa',
+ pic: 'AS_SHARED_LIB' in config_host)
feature_to_c = find_program('scripts/feature_to_c.sh')
@@ -2609,7 +2626,8 @@ foreach target : target_dirs
include_directories: target_inc,
c_args: c_args,
build_by_default: false,
- name_suffix: 'fa')
+ name_suffix: 'fa',
+ pic: 'AS_SHARED_LIB' in config_host)
if target.endswith('-softmmu')
execs = [{
@@ -2649,15 +2667,34 @@ foreach target : target_dirs
exe_name += '-unsigned'
endif
- emulator = executable(exe_name, exe['sources'],
- install: true,
- c_args: c_args,
- dependencies: arch_deps + deps + exe['dependencies'],
- objects: lib.extract_all_objects(recursive: true),
- link_language: link_language,
- link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
- link_args: link_args,
- gui_app: exe['gui'])
+ if 'AS_SHARED_LIB' not in config_host and 'AS_STATIC_LIB' not in config_host
+ emulator = executable(exe_name, exe['sources'],
+ install: true,
+ c_args: c_args,
+ dependencies: arch_deps + deps + exe['dependencies'],
+ objects: lib.extract_all_objects(recursive: true),
+ link_language: link_language,
+ link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
+ link_args: link_args,
+ gui_app: exe['gui'])
+ else
+ if 'AS_SHARED_LIB' in config_host
+ emulator = shared_library(exe_name, exe['sources'],
+ install: true,
+ c_args: c_args,
+ dependencies: arch_deps + deps + exe['dependencies'],
+ objects: lib.extract_all_objects(recursive: true),
+ link_language: link_language,
+ link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
+ link_args: link_args)
+ endif
+ if 'AS_STATIC_LIB' in config_host
+ emulator = static_library(exe_name, exe['sources'],
+ c_args: c_args,
+ dependencies: arch_deps + deps + exe['dependencies'],
+ objects: lib.extract_all_objects(recursive: true))
+ endif
+ endif
if targetos == 'darwin'
icon = 'pc-bios/qemu.rsrc'
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 422e2ac0c9..d1fe577750 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4186,6 +4186,12 @@ static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
}
+//// --- Begin LibAFL code ---
+
+void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
+
+//// --- End LibAFL code ---
+
/*
* Add/subtract (immediate)
*
@@ -4217,6 +4223,16 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
imm <<= 12;
}
+//// --- Begin LibAFL code ---
+
+ if (rd == 31 && sub_op) { // cmp xX, imm
+ TCGv_i64 tcg_imm = tcg_const_i64(imm);
+ libafl_gen_cmp(s->pc_curr, tcg_rn, tcg_imm, is_64bit ? MO_64 : MO_32);
+ tcg_temp_free_i64(tcg_imm);
+ }
+
+//// --- End LibAFL code ---
+
tcg_result = tcg_temp_new_i64();
if (!setflags) {
if (sub_op) {
@@ -4879,6 +4895,13 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
tcg_rm = read_cpu_reg(s, rm, sf);
ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
+//// --- Begin LibAFL code ---
+
+ if (rd == 31 && sub_op) // cmp xX, xY
+ libafl_gen_cmp(s->pc_curr, tcg_rn, tcg_rm, sf ? MO_64 : MO_32);
+
+//// --- End LibAFL code ---
+
tcg_result = tcg_temp_new_i64();
if (!setflags) {
@@ -4943,6 +4966,13 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
+//// --- Begin LibAFL code ---
+
+ if (rd == 31 && sub_op) // cmp xX, xY
+ libafl_gen_cmp(s->pc_curr, tcg_rn, tcg_rm, sf ? MO_64 : MO_32);
+
+//// --- End LibAFL code ---
+
tcg_result = tcg_temp_new_i64();
if (!setflags) {
@@ -5225,6 +5255,12 @@ static void disas_cc(DisasContext *s, uint32_t insn)
}
tcg_rn = cpu_reg(s, rn);
+//// --- Begin LibAFL code ---
+
+ libafl_gen_cmp(s->pc_curr, tcg_rn, tcg_y, sf ? MO_64 : MO_32);
+
+//// --- End LibAFL code ---
+
/* Set the flags for the new comparison. */
tcg_tmp = tcg_temp_new_i64();
if (op) {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 80c282669f..8c91b4c924 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -5424,6 +5424,12 @@ static bool store_reg_kind(DisasContext *s, int rd,
g_assert_not_reached();
}
+//// --- Begin LibAFL code ---
+
+void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
+
+//// --- End LibAFL code ---
+
/*
* Data Processing (register)
*
@@ -5440,6 +5446,24 @@ static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
tmp1 = load_reg(s, a->rn);
+//// --- Begin LibAFL code ---
+
+ if (gen == gen_sub_CC || /*gen == gen_add_CC ||*/ gen == gen_rsb_CC) {
+#ifdef TARGET_AARCH64
+ TCGv tmp1_64 = tcg_temp_new();
+ TCGv tmp2_64 = tcg_temp_new();
+ tcg_gen_extu_i32_i64(tmp1_64, tmp1);
+ tcg_gen_extu_i32_i64(tmp2_64, tmp2);
+ libafl_gen_cmp(s->pc_curr, tmp1_64, tmp2_64, MO_32);
+ tcg_temp_free(tmp1_64);
+ tcg_temp_free(tmp2_64);
+#else
+ libafl_gen_cmp(s->pc_curr, tmp1, tmp2, MO_32);
+#endif
+ }
+
+//// --- End LibAFL code ---
+
gen(tmp1, tmp1, tmp2);
tcg_temp_free_i32(tmp2);
@@ -5532,6 +5556,24 @@ static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
tmp2 = tcg_const_i32(imm);
tmp1 = load_reg(s, a->rn);
+//// --- Begin LibAFL code ---
+
+ if (gen == gen_sub_CC || /*gen == gen_add_CC ||*/ gen == gen_rsb_CC) {
+#ifdef TARGET_AARCH64
+ TCGv tmp1_64 = tcg_temp_new();
+ TCGv tmp2_64 = tcg_temp_new();
+ tcg_gen_extu_i32_i64(tmp1_64, tmp1);
+ tcg_gen_extu_i32_i64(tmp2_64, tmp2);
+ libafl_gen_cmp(s->pc_curr, tmp1_64, tmp2_64, MO_32);
+ tcg_temp_free(tmp1_64);
+ tcg_temp_free(tmp2_64);
+#else
+ libafl_gen_cmp(s->pc_curr, tmp1, tmp2, MO_32);
+#endif
+ }
+
+//// --- End LibAFL code ---
+
gen(tmp1, tmp1, tmp2);
tcg_temp_free_i32(tmp2);
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index aacb605eee..45d8f68487 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -32,6 +32,12 @@
#include "exec/log.h"
+//// --- Begin LibAFL code ---
+
+void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
+
+//// --- End LibAFL code ---
+
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@@ -1445,6 +1451,13 @@ static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
} else {
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
+
+ //// --- Begin LibAFL code ---
+
+ libafl_gen_cmp(s1->pc, s1->T0, s1->T1, ot);
+
+ //// --- End LibAFL code ---
+
tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
gen_op_st_rm_T0_A0(s1, ot, d);
}
@@ -1488,6 +1501,13 @@ static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
case OP_CMPL:
tcg_gen_mov_tl(cpu_cc_src, s1->T1);
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
+
+ //// --- Begin LibAFL code ---
+
+ libafl_gen_cmp(s1->pc, s1->T0, s1->T1, ot);
+
+ //// --- End LibAFL code ---
+
tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
set_cc_op(s1, CC_OP_SUBB + ot);
break;
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index c754396575..5393e4ea22 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -2860,6 +2860,13 @@ static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
#endif
}
+//// --- Begin LibAFL code ---
+
+void libafl_gen_read(TCGv addr, MemOp ot);
+void libafl_gen_write(TCGv addr, MemOp ot);
+
+//// --- End LibAFL code ---
+
void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
{
MemOp orig_memop;
@@ -2879,6 +2886,13 @@ void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
}
addr = plugin_prep_mem_callbacks(addr);
+
+//// --- Begin LibAFL code ---
+
+ libafl_gen_read(addr, memop);
+
+//// --- End LibAFL code ---
+
gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
plugin_gen_mem_callbacks(addr, info);
@@ -2924,6 +2938,13 @@ void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
}
addr = plugin_prep_mem_callbacks(addr);
+
+//// --- Begin LibAFL code ---
+
+ libafl_gen_write(addr, memop);
+
+//// --- End LibAFL code ---
+
if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
} else {
@@ -2966,6 +2987,13 @@ void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
}
addr = plugin_prep_mem_callbacks(addr);
+
+//// --- Begin LibAFL code ---
+
+ libafl_gen_read(addr, memop);
+
+//// --- End LibAFL code ---
+
gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
plugin_gen_mem_callbacks(addr, info);
@@ -3024,6 +3052,13 @@ void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
}
addr = plugin_prep_mem_callbacks(addr);
+
+//// --- Begin LibAFL code ---
+
+ libafl_gen_write(addr, memop);
+
+//// --- End LibAFL code ---
+
gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
plugin_gen_mem_callbacks(addr, info);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index ca5bcc4635..2c6f9b6de8 100644
--- a/tcg/tcg.c
+++ b/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;