Compare commits
72 Commits
fret_v2
...
wcet_syste
Author | SHA1 | Date | |
---|---|---|---|
85e0a3f630 | |||
ab54074925 | |||
f5b92c8907 | |||
f438967783 | |||
3493dfa219 | |||
a5a49c3292 | |||
8a379ba198 | |||
6ffc2bbe4f | |||
0cf10fb0ff | |||
404cb91655 | |||
ff823f26ff | |||
80af255c2e | |||
e62b0072ea | |||
6ec50ee9c3 | |||
88a0358a4e | |||
78dac2f524 | |||
9caef2e60f | |||
b781a3ebce | |||
5a1cf4d873 | |||
c1dba1b39d | |||
![]() |
54e1f5be86 | ||
![]() |
fddd169de5 | ||
![]() |
711bd602cc | ||
![]() |
e88636b4d4 | ||
![]() |
34833f361b | ||
![]() |
43583f0c07 | ||
![]() |
1ce084af08 | ||
![]() |
fec12fc888 | ||
![]() |
ef0cf1887e | ||
![]() |
71ba2adfeb | ||
![]() |
7629818574 | ||
![]() |
4658dfcbc0 | ||
![]() |
2b2eb343a0 | ||
![]() |
932333c5f0 | ||
![]() |
8c2d5911de | ||
![]() |
08e46e6d92 | ||
![]() |
df1c9c3039 | ||
![]() |
7204b8f3c6 | ||
![]() |
36c651c226 | ||
![]() |
fceaefb43f | ||
![]() |
7d71e6bfb0 | ||
![]() |
c2c7f108b8 | ||
![]() |
3488bb205d | ||
![]() |
cddfaf96ab | ||
![]() |
43a457841f | ||
![]() |
ebf660beb1 | ||
![]() |
bbbdedb386 | ||
![]() |
8319de607f | ||
![]() |
a759dc19ec | ||
![]() |
24101e36f1 | ||
![]() |
a43e057bd6 | ||
![]() |
3aa2c2cd67 | ||
![]() |
9e80a430ed | ||
![]() |
c66f5dfc12 | ||
![]() |
5cf977a2a1 | ||
![]() |
36cfd11a86 | ||
![]() |
246ccfbf44 | ||
![]() |
3ee93e456d | ||
![]() |
ec08035102 | ||
![]() |
f97853c8cb | ||
![]() |
abeee2a470 | ||
![]() |
ff6d391e10 | ||
![]() |
b19de1137b | ||
![]() |
3c6e5df1f6 | ||
![]() |
695c25e167 | ||
![]() |
23ba9f170f | ||
![]() |
f0dee5a40d | ||
![]() |
7637373b23 | ||
![]() |
4c34ef3d34 | ||
![]() |
9e41f16fca | ||
![]() |
3054f772de | ||
![]() |
aa77e375a5 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -15,3 +15,6 @@ GTAGS
|
||||
*.depend_raw
|
||||
*.swp
|
||||
*.patch
|
||||
.cache
|
||||
*.axf
|
||||
*.qcow2
|
72
3k.c
Normal file
72
3k.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void libafl_qemu_main_loop( void );
|
||||
void libafl_qemu_sys_init(int argc, char **argv, char **envp);
|
||||
void libafl_qemu_cleanup( void );
|
||||
|
||||
void libafl_qemu_set_breakpoint( unsigned long int );
|
||||
|
||||
void libafl_qemu_remove_native_breakpoint( unsigned long int );
|
||||
void libafl_qemu_set_native_breakpoint( unsigned long int );
|
||||
void libafl_snapshot_save( const char* );
|
||||
void libafl_snapshot_load( const char* );
|
||||
|
||||
void libafl_phys_read(uint32_t, uint8_t*, int);
|
||||
|
||||
void libafl_phys_write(uint32_t, uint8_t*, int);
|
||||
|
||||
int64_t icount_to_ns(int64_t icount);
|
||||
|
||||
int64_t libafl_get_clock( void );
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
unsigned char buf[32] = "_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
unsigned char buf2[32] = "0";
|
||||
unsigned char buf3[32] = "z";
|
||||
unsigned char buf4[32] = "a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
unsigned char buf5[32] = "b!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
libafl_qemu_sys_init(argc, argv, envp);
|
||||
int pheader = 0x00006a4c;
|
||||
// libafl_phys_read(0x20000110-0x20000100+pheader, buf,32);
|
||||
// printf("FUZZ_INPUT[0]: %c\n", buf[0]);
|
||||
// Start pre-run
|
||||
libafl_qemu_set_native_breakpoint(0x4ce2);//send 217028
|
||||
libafl_qemu_main_loop();
|
||||
libafl_qemu_remove_native_breakpoint(0x4ce2);
|
||||
// End pre-run
|
||||
libafl_snapshot_save("Start");
|
||||
libafl_qemu_set_native_breakpoint(0x4be0);
|
||||
int64_t tmp = libafl_get_clock();
|
||||
printf("snapshot icount: %ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
libafl_snapshot_load("Start");
|
||||
tmp = libafl_get_clock();
|
||||
printf("snapshot icount after load: %ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf);
|
||||
libafl_snapshot_load("Start");
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf2,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf2);
|
||||
libafl_snapshot_load("Start");
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf3,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf3);
|
||||
libafl_snapshot_load("Start");
|
||||
/*int counter = 3000;
|
||||
do {
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_qemu_main_loop();
|
||||
int64_t tmp = libafl_get_clock();
|
||||
printf("%ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
libafl_snapshot_load("Start");
|
||||
// puts("Reload has occured");
|
||||
counter--;
|
||||
} while (counter);*/
|
||||
libafl_qemu_cleanup();
|
||||
return 0;
|
||||
}
|
13
README.md
Normal file
13
README.md
Normal file
@ -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
|
||||
|
||||
<sup>
|
||||
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.
|
||||
</sup>
|
||||
|
||||
<br>
|
@ -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,15 @@ 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);
|
||||
void libafl_exec_edge_one_off(target_ulong src_block, target_ulong dst_block);
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* main execution loop */
|
||||
|
||||
int cpu_exec(CPUState *cpu)
|
||||
@ -950,6 +971,12 @@ int cpu_exec(CPUState *cpu)
|
||||
*/
|
||||
qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||
}
|
||||
//// --- Begin LibAFL code ---
|
||||
// This will save an edge (0,pc) after interrupts
|
||||
// if (!last_tb) {
|
||||
// libafl_exec_edge_one_off(0, tb->pc);
|
||||
// }
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/*
|
||||
@ -964,7 +991,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);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
@ -35,6 +36,26 @@
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
|
||||
typedef struct MttcgForceRcuNotifier {
|
||||
Notifier notifier;
|
||||
CPUState *cpu;
|
||||
} MttcgForceRcuNotifier;
|
||||
|
||||
static void do_nothing(CPUState *cpu, run_on_cpu_data d)
|
||||
{
|
||||
}
|
||||
|
||||
static void mttcg_force_rcu(Notifier *notify, void *data)
|
||||
{
|
||||
CPUState *cpu = container_of(notify, MttcgForceRcuNotifier, notifier)->cpu;
|
||||
|
||||
/*
|
||||
* Called with rcu_registry_lock held, using async_run_on_cpu() ensures
|
||||
* that there are no deadlocks.
|
||||
*/
|
||||
async_run_on_cpu(cpu, do_nothing, RUN_ON_CPU_NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the multi-threaded case each vCPU has its own thread. The TLS
|
||||
* variable current_cpu can be used deep in the code to find the
|
||||
@ -43,12 +64,16 @@
|
||||
|
||||
static void *mttcg_cpu_thread_fn(void *arg)
|
||||
{
|
||||
MttcgForceRcuNotifier force_rcu;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
g_assert(!icount_enabled());
|
||||
|
||||
rcu_register_thread();
|
||||
force_rcu.notifier.notify = mttcg_force_rcu;
|
||||
force_rcu.cpu = cpu;
|
||||
rcu_add_force_rcu_notifier(&force_rcu.notifier);
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
@ -100,6 +125,7 @@ static void *mttcg_cpu_thread_fn(void *arg)
|
||||
|
||||
tcg_cpus_destroy(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
rcu_remove_force_rcu_notifier(&force_rcu.notifier);
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
@ -135,6 +136,11 @@ static void rr_deal_with_unplugged_cpus(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void rr_force_rcu(Notifier *notify, void *data)
|
||||
{
|
||||
rr_kick_next_cpu();
|
||||
}
|
||||
|
||||
/*
|
||||
* In the single-threaded case each vCPU is simulated in turn. If
|
||||
* there is more than a single vCPU we create a simple timer to kick
|
||||
@ -145,10 +151,13 @@ static void rr_deal_with_unplugged_cpus(void)
|
||||
|
||||
static void *rr_cpu_thread_fn(void *arg)
|
||||
{
|
||||
Notifier force_rcu;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
rcu_register_thread();
|
||||
force_rcu.notify = rr_force_rcu;
|
||||
rcu_add_force_rcu_notifier(&force_rcu);
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
@ -257,6 +266,7 @@ static void *rr_cpu_thread_fn(void *arg)
|
||||
rr_deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
rcu_remove_force_rcu_notifier(&force_rcu);
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 ---
|
||||
|
@ -61,6 +61,386 @@
|
||||
#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);
|
||||
void libafl_gen_jmp(target_ulong src, target_ulong dst);
|
||||
void libafl_exec_edge_one_off(target_ulong src_block, target_ulong dst_block);
|
||||
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);
|
||||
void (*libafl_exec_jmp_hook)(uint64_t src, uint64_t dst, uint64_t id);
|
||||
uint64_t (*libafl_gen_jmp_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;
|
||||
|
||||
static TCGHelperInfo libafl_exec_jmp_hook_info = {
|
||||
.func = NULL, .name = "libafl_exec_jmp_hook", \
|
||||
.flags = dh_callflag(void), \
|
||||
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 3)
|
||||
};
|
||||
static int exec_jmp_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 +1780,157 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
return tb;
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
void libafl_exec_edge_one_off(target_ulong src_block, target_ulong dst_block)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
libafl_exec_edge_hook(libafl_id);
|
||||
}
|
||||
|
||||
void libafl_gen_jmp(target_ulong src, target_ulong dst)
|
||||
{
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_jmp_hook)
|
||||
libafl_id = libafl_gen_jmp_hook((uint64_t)src, (uint64_t)dst);
|
||||
if (!libafl_exec_jmp_hook || libafl_id == (uint32_t)-1)
|
||||
return;
|
||||
if (!exec_jmp_hook_added) {
|
||||
exec_jmp_hook_added = 1;
|
||||
libafl_exec_jmp_hook_info.func = libafl_exec_jmp_hook;
|
||||
libafl_helper_table_add(&libafl_exec_jmp_hook_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64(src);
|
||||
TCGv_i64 tmp1 = tcg_const_i64(dst);
|
||||
TCGv_i64 tmp2 = tcg_const_i64(libafl_id);
|
||||
TCGTemp *tmp3[3] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1), tcgv_i64_temp(tmp2) };
|
||||
tcg_gen_callN(libafl_exec_jmp_hook, NULL, 3, tmp3);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
tb->icount = 0;
|
||||
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,
|
||||
@ -1450,6 +1981,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tb->flags = flags;
|
||||
tb->cflags = cflags;
|
||||
tb->trace_vcpu_dstate = *cpu->trace_dstate;
|
||||
tb->icount = 0;
|
||||
tcg_ctx->tb_cflags = cflags;
|
||||
tb_overflow:
|
||||
|
||||
@ -1467,6 +1999,26 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tcg_func_start(tcg_ctx);
|
||||
|
||||
tcg_ctx->cpu = env_cpu(env);
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
uint32_t libafl_id = 0;
|
||||
if (libafl_gen_block_hook)
|
||||
libafl_id = libafl_gen_block_hook((uint64_t)pc);
|
||||
if (libafl_exec_block_hook && libafl_id != (uint32_t)-1) {
|
||||
if (!exec_block_hook_added) {
|
||||
exec_block_hook_added = 1;
|
||||
libafl_exec_block_hook_info.func = libafl_exec_block_hook;
|
||||
libafl_helper_table_add(&libafl_exec_block_hook_info);
|
||||
}
|
||||
TCGv_i64 tmp0 = tcg_const_i64((uint64_t)pc);
|
||||
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||
tcg_gen_callN(libafl_exec_block_hook, NULL, 1, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
gen_intermediate_code(cpu, tb, max_insns);
|
||||
assert(tb->size != 0);
|
||||
tcg_ctx->cpu = NULL;
|
||||
|
@ -18,6 +18,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
|
||||
|
@ -1978,6 +1978,12 @@ uint32_t blk_get_max_transfer(BlockBackend *blk)
|
||||
return ROUND_DOWN(max, blk_get_request_alignment(blk));
|
||||
}
|
||||
|
||||
int blk_get_max_hw_iov(BlockBackend *blk)
|
||||
{
|
||||
return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
|
||||
blk->root->bs->bl.max_iov);
|
||||
}
|
||||
|
||||
int blk_get_max_iov(BlockBackend *blk)
|
||||
{
|
||||
return blk->root->bs->bl.max_iov;
|
||||
|
@ -1273,7 +1273,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
|
||||
ret = hdev_get_max_segments(s->fd, &st);
|
||||
if (ret > 0) {
|
||||
bs->bl.max_iov = ret;
|
||||
bs->bl.max_hw_iov = ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1807,7 +1807,7 @@ static int handle_aiocb_copy_range(void *opaque)
|
||||
static int handle_aiocb_discard(void *opaque)
|
||||
{
|
||||
RawPosixAIOData *aiocb = opaque;
|
||||
int ret = -EOPNOTSUPP;
|
||||
int ret = -ENOTSUP;
|
||||
BDRVRawState *s = aiocb->bs->opaque;
|
||||
|
||||
if (!s->has_discard) {
|
||||
@ -1829,7 +1829,7 @@ static int handle_aiocb_discard(void *opaque)
|
||||
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
|
||||
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
aiocb->aio_offset, aiocb->aio_nbytes);
|
||||
ret = translate_err(-errno);
|
||||
ret = translate_err(ret);
|
||||
#elif defined(__APPLE__) && (__MACH__)
|
||||
fpunchhole_t fpunchhole;
|
||||
fpunchhole.fp_flags = 0;
|
||||
|
@ -136,6 +136,7 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
|
||||
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
|
||||
src->min_mem_alignment);
|
||||
dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
|
||||
dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov);
|
||||
}
|
||||
|
||||
typedef struct BdrvRefreshLimitsState {
|
||||
|
@ -320,7 +320,6 @@ static void wctablet_chr_finalize(Object *obj)
|
||||
TabletChardev *tablet = WCTABLET_CHARDEV(obj);
|
||||
|
||||
qemu_input_handler_unregister(tablet->hs);
|
||||
g_free(tablet);
|
||||
}
|
||||
|
||||
static void wctablet_chr_open(Chardev *chr,
|
||||
|
29
configure
vendored
29
configure
vendored
@ -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"
|
||||
@ -2246,9 +2258,11 @@ static THREAD int tls_var;
|
||||
int main(void) { return tls_var; }
|
||||
EOF
|
||||
|
||||
# Check we support --no-pie first; we will need this for building ROMs.
|
||||
# Check we support -fno-pie and -no-pie first; we will need the former for
|
||||
# building ROMs, and both for everything if --disable-pie is passed.
|
||||
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
||||
CFLAGS_NOPIE="-fno-pie"
|
||||
LDFLAGS_NOPIE="-no-pie"
|
||||
fi
|
||||
|
||||
if test "$static" = "yes"; then
|
||||
@ -2264,6 +2278,7 @@ if test "$static" = "yes"; then
|
||||
fi
|
||||
elif test "$pie" = "no"; then
|
||||
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
||||
CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS"
|
||||
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
||||
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
||||
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
|
||||
@ -3187,9 +3202,8 @@ glib_req_ver=2.56
|
||||
glib_modules=gthread-2.0
|
||||
if test "$modules" = yes; then
|
||||
glib_modules="$glib_modules gmodule-export-2.0"
|
||||
fi
|
||||
if test "$plugins" = "yes"; then
|
||||
glib_modules="$glib_modules gmodule-2.0"
|
||||
elif test "$plugins" = "yes"; then
|
||||
glib_modules="$glib_modules gmodule-no-export-2.0"
|
||||
fi
|
||||
|
||||
for i in $glib_modules; do
|
||||
@ -4917,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
|
||||
|
@ -67,7 +67,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata)
|
||||
/* Print previous instruction in cache */
|
||||
if (s->len) {
|
||||
qemu_plugin_outs(s->str);
|
||||
qemu_plugin_outs("s\n");
|
||||
qemu_plugin_outs("\n");
|
||||
}
|
||||
|
||||
/* Store new instruction in cache */
|
||||
|
204
cpu.c
204
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;
|
||||
|
||||
@ -58,7 +239,12 @@ static int cpu_common_post_load(void *opaque, int version_id)
|
||||
* memory we've translated code from. So we must flush all TBs,
|
||||
* which will now be stale.
|
||||
*/
|
||||
/* Begin LibAFL instrumentation */
|
||||
// Do not flush old tbs on loadvm, when fuzzing in system-mode
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(AS_SHARED_LIB)
|
||||
tb_flush(cpu);
|
||||
#endif
|
||||
/* End LibAFL instrumentation */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -225,6 +411,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 +440,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. */
|
||||
|
@ -98,8 +98,10 @@ driver options if ``--image-opts`` is specified.
|
||||
|
||||
.. option:: --cache=CACHE
|
||||
|
||||
The cache mode to be used with the file. See the documentation of
|
||||
the emulator's ``-drive cache=...`` option for allowed values.
|
||||
The cache mode to be used with the file. Valid values are:
|
||||
``none``, ``writeback`` (the default), ``writethrough``,
|
||||
``directsync`` and ``unsafe``. See the documentation of
|
||||
the emulator's ``-drive cache=...`` option for more info.
|
||||
|
||||
.. option:: -n, --nocache
|
||||
|
||||
|
@ -51,7 +51,9 @@
|
||||
*/ \
|
||||
qemu_coroutine_yield(); \
|
||||
qemu_bh_delete(co_bh); \
|
||||
code_block; \
|
||||
do { \
|
||||
code_block; \
|
||||
} while (0); \
|
||||
/* re-enter back to qemu thread */ \
|
||||
qemu_coroutine_yield(); \
|
||||
} while (0)
|
||||
|
@ -2677,10 +2677,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set the IOMMU type. "
|
||||
"Valid values are none and smmuv3");
|
||||
|
||||
object_class_property_add_bool(oc, "default_bus_bypass_iommu",
|
||||
object_class_property_add_bool(oc, "default-bus-bypass-iommu",
|
||||
virt_get_default_bus_bypass_iommu,
|
||||
virt_set_default_bus_bypass_iommu);
|
||||
object_class_property_set_description(oc, "default_bus_bypass_iommu",
|
||||
object_class_property_set_description(oc, "default-bus-bypass-iommu",
|
||||
"Set on/off to enable/disable "
|
||||
"bypass_iommu for default root bus");
|
||||
|
||||
|
@ -222,7 +222,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
|
||||
memory_region_transaction_commit();
|
||||
|
||||
while (j--) {
|
||||
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
|
||||
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
|
||||
}
|
||||
goto fail_host_notifiers;
|
||||
}
|
||||
|
@ -61,6 +61,12 @@
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Anonymous BlockBackend for empty drive */
|
||||
static BlockBackend *blk_create_empty_drive(void)
|
||||
{
|
||||
return blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
/* qdev floppy bus */
|
||||
|
||||
@ -486,8 +492,7 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
|
||||
}
|
||||
|
||||
if (!dev->conf.blk) {
|
||||
/* Anonymous BlockBackend for an empty drive */
|
||||
dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
|
||||
dev->conf.blk = blk_create_empty_drive();
|
||||
ret = blk_attach_dev(dev->conf.blk, qdev);
|
||||
assert(ret == 0);
|
||||
|
||||
@ -1161,7 +1166,19 @@ static FDrive *get_drv(FDCtrl *fdctrl, int unit)
|
||||
|
||||
static FDrive *get_cur_drv(FDCtrl *fdctrl)
|
||||
{
|
||||
return get_drv(fdctrl, fdctrl->cur_drv);
|
||||
FDrive *cur_drv = get_drv(fdctrl, fdctrl->cur_drv);
|
||||
|
||||
if (!cur_drv->blk) {
|
||||
/*
|
||||
* Kludge: empty drive line selected. Create an anonymous
|
||||
* BlockBackend to avoid NULL deref with various BlockBackend
|
||||
* API calls within this model (CVE-2021-20196).
|
||||
* Due to the controller QOM model limitations, we don't
|
||||
* attach the created to the controller device.
|
||||
*/
|
||||
cur_drv->blk = blk_create_empty_drive();
|
||||
}
|
||||
return cur_drv;
|
||||
}
|
||||
|
||||
/* Status A register : 0x00 (read-only) */
|
||||
|
@ -43,6 +43,7 @@ GlobalProperty hw_compat_6_0[] = {
|
||||
{ "nvme-ns", "eui64-default", "off"},
|
||||
{ "e1000", "init-vet", "off" },
|
||||
{ "e1000e", "init-vet", "off" },
|
||||
{ "vhost-vsock-device", "seqpacket", "off" },
|
||||
};
|
||||
const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0);
|
||||
|
||||
|
@ -1170,8 +1170,8 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
}
|
||||
|
||||
buf = vram_write_buffer(s);
|
||||
posy = ADDR_TO_Y(addr);
|
||||
posx = ADDR_TO_X(addr);
|
||||
posy = ADDR_TO_Y(addr >> 2);
|
||||
posx = ADDR_TO_X(addr >> 2);
|
||||
|
||||
if (!buf->size) {
|
||||
return;
|
||||
@ -1232,8 +1232,8 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
posy = ADDR_TO_Y(addr);
|
||||
posx = ADDR_TO_X(addr);
|
||||
posy = ADDR_TO_Y(addr >> 2);
|
||||
posx = ADDR_TO_X(addr >> 2);
|
||||
|
||||
if (posy > buf->height || posx > buf->width) {
|
||||
return 0;
|
||||
|
@ -2252,7 +2252,7 @@ static int qxl_pre_save(void *opaque)
|
||||
} else {
|
||||
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
|
||||
}
|
||||
if (d->last_release_offset < d->vga.vram_size) {
|
||||
if (d->last_release_offset >= d->vga.vram_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1763,7 +1763,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
object_class_property_add_bool(oc, "hpet",
|
||||
pc_machine_get_hpet, pc_machine_set_hpet);
|
||||
|
||||
object_class_property_add_bool(oc, "default_bus_bypass_iommu",
|
||||
object_class_property_add_bool(oc, "default-bus-bypass-iommu",
|
||||
pc_machine_get_default_bus_bypass_iommu,
|
||||
pc_machine_set_default_bus_bypass_iommu);
|
||||
|
||||
|
@ -243,7 +243,7 @@ static void pc_q35_init(MachineState *machine)
|
||||
NULL);
|
||||
|
||||
if (acpi_pcihp) {
|
||||
object_register_sugar_prop(TYPE_PCIE_SLOT, "native-hotplug",
|
||||
object_register_sugar_prop(TYPE_PCIE_SLOT, "x-native-hotplug",
|
||||
"false", true);
|
||||
}
|
||||
|
||||
|
@ -2999,3 +2999,25 @@ static void armv7m_nvic_register_types(void)
|
||||
}
|
||||
|
||||
type_init(armv7m_nvic_register_types)
|
||||
|
||||
/* Begin LibAFL instrumentation */
|
||||
#include "qemu/main-loop.h"
|
||||
void libafl_send_irq(int irqn);
|
||||
void libafl_send_irq(int irqn) {
|
||||
bool haslock = qemu_mutex_iothread_locked();
|
||||
if (!haslock) {
|
||||
qemu_mutex_lock_iothread();
|
||||
}
|
||||
CPUState *cpu;
|
||||
CPU_FOREACH(cpu) {
|
||||
CPUARMState* env = cpu->env_ptr;
|
||||
NVICState* nvic = env->nvic;
|
||||
// set_irq_level(nvic, irqn, 1);
|
||||
// set_irq_level(nvic, irqn, 0);
|
||||
armv7m_nvic_set_pending(nvic, irqn+16, false);
|
||||
}
|
||||
if (!haslock) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
}
|
||||
/* End LibAFL instrumentation */
|
@ -304,7 +304,14 @@ type_init(virt_machine_register_types)
|
||||
} \
|
||||
type_init(machvirt_machine_##major##_##minor##_init);
|
||||
|
||||
static void virt_machine_6_0_options(MachineClass *mc)
|
||||
static void virt_machine_6_1_options(MachineClass *mc)
|
||||
{
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(6, 0, true)
|
||||
DEFINE_VIRT_MACHINE(6, 1, true)
|
||||
|
||||
static void virt_machine_6_0_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_6_1_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(6, 0, false)
|
||||
|
@ -107,6 +107,7 @@ struct E1000State_st {
|
||||
e1000x_txd_props props;
|
||||
e1000x_txd_props tso_props;
|
||||
uint16_t tso_frames;
|
||||
bool busy;
|
||||
} tx;
|
||||
|
||||
struct {
|
||||
@ -763,6 +764,11 @@ start_xmit(E1000State *s)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->tx.busy) {
|
||||
return;
|
||||
}
|
||||
s->tx.busy = true;
|
||||
|
||||
while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
|
||||
base = tx_desc_base(s) +
|
||||
sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
|
||||
@ -789,6 +795,7 @@ start_xmit(E1000State *s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
s->tx.busy = false;
|
||||
set_ics(s, 0, cause);
|
||||
}
|
||||
|
||||
|
@ -1746,10 +1746,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
|
||||
size_t lens[VIRTQUEUE_MAX_SIZE];
|
||||
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
|
||||
struct virtio_net_hdr_mrg_rxbuf mhdr;
|
||||
unsigned mhdr_cnt = 0;
|
||||
size_t offset, i, guest_offset;
|
||||
size_t offset, i, guest_offset, j;
|
||||
ssize_t err;
|
||||
|
||||
if (!virtio_net_can_receive(nc)) {
|
||||
return -1;
|
||||
@ -1780,6 +1783,12 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
|
||||
total = 0;
|
||||
|
||||
if (i == VIRTQUEUE_MAX_SIZE) {
|
||||
virtio_error(vdev, "virtio-net unexpected long buffer chain");
|
||||
err = size;
|
||||
goto err;
|
||||
}
|
||||
|
||||
elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
if (i) {
|
||||
@ -1791,7 +1800,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
n->guest_hdr_len, n->host_hdr_len,
|
||||
vdev->guest_features);
|
||||
}
|
||||
return -1;
|
||||
err = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (elem->in_num < 1) {
|
||||
@ -1799,7 +1809,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
"virtio-net receive queue contains no in buffers");
|
||||
virtqueue_detach_element(q->rx_vq, elem, 0);
|
||||
g_free(elem);
|
||||
return -1;
|
||||
err = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sg = elem->in_sg;
|
||||
@ -1836,12 +1847,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
if (!n->mergeable_rx_bufs && offset < size) {
|
||||
virtqueue_unpop(q->rx_vq, elem, total);
|
||||
g_free(elem);
|
||||
return size;
|
||||
err = size;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* signal other side */
|
||||
virtqueue_fill(q->rx_vq, elem, total, i++);
|
||||
g_free(elem);
|
||||
elems[i] = elem;
|
||||
lens[i] = total;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (mhdr_cnt) {
|
||||
@ -1851,10 +1863,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
&mhdr.num_buffers, sizeof mhdr.num_buffers);
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
/* signal other side */
|
||||
virtqueue_fill(q->rx_vq, elems[j], lens[j], j);
|
||||
g_free(elems[j]);
|
||||
}
|
||||
|
||||
virtqueue_flush(q->rx_vq, i);
|
||||
virtio_notify(vdev, q->rx_vq);
|
||||
|
||||
return size;
|
||||
|
||||
err:
|
||||
for (j = 0; j < i; j++) {
|
||||
g_free(elems[j]);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
|
||||
|
@ -1441,6 +1441,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
vmxnet3_setup_rx_filtering(s);
|
||||
/* Cache fields from shared memory */
|
||||
s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
|
||||
assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU);
|
||||
VMW_CFPRN("MTU is %u", s->mtu);
|
||||
|
||||
s->max_rx_frags =
|
||||
@ -1486,6 +1487,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
/* Read rings memory locations for TX queues */
|
||||
pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.txRingBasePA);
|
||||
size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.txRingSize);
|
||||
if (size > VMXNET3_TX_RING_MAX_SIZE) {
|
||||
size = VMXNET3_TX_RING_MAX_SIZE;
|
||||
}
|
||||
|
||||
vmxnet3_ring_init(d, &s->txq_descr[i].tx_ring, pa, size,
|
||||
sizeof(struct Vmxnet3_TxDesc), false);
|
||||
@ -1496,6 +1500,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
/* TXC ring */
|
||||
pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.compRingBasePA);
|
||||
size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.compRingSize);
|
||||
if (size > VMXNET3_TC_RING_MAX_SIZE) {
|
||||
size = VMXNET3_TC_RING_MAX_SIZE;
|
||||
}
|
||||
vmxnet3_ring_init(d, &s->txq_descr[i].comp_ring, pa, size,
|
||||
sizeof(struct Vmxnet3_TxCompDesc), true);
|
||||
VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring);
|
||||
@ -1537,6 +1544,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
/* RX rings */
|
||||
pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.rxRingBasePA[j]);
|
||||
size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.rxRingSize[j]);
|
||||
if (size > VMXNET3_RX_RING_MAX_SIZE) {
|
||||
size = VMXNET3_RX_RING_MAX_SIZE;
|
||||
}
|
||||
vmxnet3_ring_init(d, &s->rxq_descr[i].rx_ring[j], pa, size,
|
||||
sizeof(struct Vmxnet3_RxDesc), false);
|
||||
VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d",
|
||||
@ -1546,6 +1556,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
/* RXC ring */
|
||||
pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.compRingBasePA);
|
||||
size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.compRingSize);
|
||||
if (size > VMXNET3_RC_RING_MAX_SIZE) {
|
||||
size = VMXNET3_RC_RING_MAX_SIZE;
|
||||
}
|
||||
vmxnet3_ring_init(d, &s->rxq_descr[i].comp_ring, pa, size,
|
||||
sizeof(struct Vmxnet3_RxCompDesc), true);
|
||||
VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size);
|
||||
|
@ -4164,6 +4164,11 @@ static uint16_t nvme_changed_nslist(NvmeCtrl *n, uint8_t rae, uint32_t buf_len,
|
||||
int i = 0;
|
||||
uint32_t nsid;
|
||||
|
||||
if (off >= sizeof(nslist)) {
|
||||
trace_pci_nvme_err_invalid_log_page_offset(off, sizeof(nslist));
|
||||
return NVME_INVALID_FIELD | NVME_DNR;
|
||||
}
|
||||
|
||||
memset(nslist, 0x0, sizeof(nslist));
|
||||
trans_len = MIN(sizeof(nslist) - off, buf_len);
|
||||
|
||||
|
@ -448,11 +448,11 @@ int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
|
||||
PCIBridgeQemuCap cap = {
|
||||
.len = cap_len,
|
||||
.type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
|
||||
.bus_res = res_reserve.bus,
|
||||
.io = res_reserve.io,
|
||||
.mem = res_reserve.mem_non_pref,
|
||||
.mem_pref_32 = res_reserve.mem_pref_32,
|
||||
.mem_pref_64 = res_reserve.mem_pref_64
|
||||
.bus_res = cpu_to_le32(res_reserve.bus),
|
||||
.io = cpu_to_le64(res_reserve.io),
|
||||
.mem = cpu_to_le32(res_reserve.mem_non_pref),
|
||||
.mem_pref_32 = cpu_to_le32(res_reserve.mem_pref_32),
|
||||
.mem_pref_64 = cpu_to_le64(res_reserve.mem_pref_64)
|
||||
};
|
||||
|
||||
int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
|
||||
|
@ -148,7 +148,7 @@ static Property pcie_slot_props[] = {
|
||||
DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
|
||||
DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
|
||||
DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true),
|
||||
DEFINE_PROP_BOOL("native-hotplug", PCIESlot, native_hotplug, true),
|
||||
DEFINE_PROP_BOOL("x-native-hotplug", PCIESlot, native_hotplug, true),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
|
@ -1087,6 +1087,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
|
||||
uint8_t *p = *p_outbuf + 2;
|
||||
int length;
|
||||
|
||||
assert(page < ARRAY_SIZE(mode_sense_valid));
|
||||
if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -1428,6 +1429,11 @@ static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* MODE_PAGE_ALLS is only valid for MODE SENSE commands */
|
||||
if (page == MODE_PAGE_ALLS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = mode_current;
|
||||
memset(mode_current, 0, inlen + 2);
|
||||
len = mode_sense_page(s, page, &p, 0);
|
||||
|
@ -180,7 +180,7 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
|
||||
page = r->req.cmd.buf[2];
|
||||
if (page == 0xb0) {
|
||||
uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
|
||||
uint32_t max_iov = blk_get_max_iov(s->conf.blk);
|
||||
uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
|
||||
|
||||
assert(max_transfer);
|
||||
max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)
|
||||
|
@ -38,7 +38,6 @@ static inline int64_t systick_scale(SysTickState *s)
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
|
||||
static void systick_timer_tick(void *opaque)
|
||||
{
|
||||
SysTickState *s = (SysTickState *)opaque;
|
||||
@ -248,3 +247,28 @@ static void armv7m_systick_register_types(void)
|
||||
}
|
||||
|
||||
type_init(armv7m_systick_register_types)
|
||||
|
||||
/* Begin LibAFL instrumentation */
|
||||
extern void libafl_send_irq(int irqn);
|
||||
volatile unsigned int libafl_int_offset = 0;
|
||||
static ptimer_state* mytimer;
|
||||
/* This can be moved to a helper function later */
|
||||
static void libafl_timed_int_hook(void*);
|
||||
static void libafl_timed_int_hook(void* arg)
|
||||
{
|
||||
libafl_send_irq(0);
|
||||
}
|
||||
void libafl_start_int_timer( void );
|
||||
void libafl_start_int_timer( void ) {
|
||||
if (libafl_int_offset==0) {return;}
|
||||
if (!mytimer) {
|
||||
mytimer = ptimer_init(&libafl_timed_int_hook, NULL, 0);
|
||||
}
|
||||
ptimer_transaction_begin(mytimer);
|
||||
ptimer_stop(mytimer);
|
||||
ptimer_set_period(mytimer, libafl_int_offset);
|
||||
ptimer_set_count(mytimer, 8);
|
||||
ptimer_run(mytimer, 1);
|
||||
ptimer_transaction_commit(mytimer);
|
||||
}
|
||||
/* End LibAFL instrumentation */
|
@ -840,6 +840,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||
}
|
||||
break;
|
||||
case UAS_PIPE_ID_STATUS:
|
||||
if (p->stream > UAS_MAX_STREAMS) {
|
||||
goto err_stream;
|
||||
}
|
||||
if (p->stream) {
|
||||
QTAILQ_FOREACH(st, &uas->results, next) {
|
||||
if (st->stream == p->stream) {
|
||||
@ -867,6 +870,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||
break;
|
||||
case UAS_PIPE_ID_DATA_IN:
|
||||
case UAS_PIPE_ID_DATA_OUT:
|
||||
if (p->stream > UAS_MAX_STREAMS) {
|
||||
goto err_stream;
|
||||
}
|
||||
if (p->stream) {
|
||||
req = usb_uas_find_request(uas, p->stream);
|
||||
} else {
|
||||
@ -902,6 +908,11 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
|
||||
err_stream:
|
||||
error_report("%s: invalid stream %d", __func__, p->stream);
|
||||
p->status = USB_RET_STALL;
|
||||
return;
|
||||
}
|
||||
|
||||
static void usb_uas_unrealize(USBDevice *dev)
|
||||
|
@ -551,6 +551,7 @@ static int vfio_host_win_del(VFIOContainer *container, hwaddr min_iova,
|
||||
QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
|
||||
if (hostwin->min_iova == min_iova && hostwin->max_iova == max_iova) {
|
||||
QLIST_REMOVE(hostwin, hostwin_next);
|
||||
g_free(hostwin);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2230,6 +2231,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
|
||||
if (QLIST_EMPTY(&container->group_list)) {
|
||||
VFIOAddressSpace *space = container->space;
|
||||
VFIOGuestIOMMU *giommu, *tmp;
|
||||
VFIOHostDMAWindow *hostwin, *next;
|
||||
|
||||
QLIST_REMOVE(container, next);
|
||||
|
||||
@ -2240,6 +2242,12 @@ static void vfio_disconnect_container(VFIOGroup *group)
|
||||
g_free(giommu);
|
||||
}
|
||||
|
||||
QLIST_FOREACH_SAFE(hostwin, &container->hostwin_list, hostwin_next,
|
||||
next) {
|
||||
QLIST_REMOVE(hostwin, hostwin_next);
|
||||
g_free(hostwin);
|
||||
}
|
||||
|
||||
trace_vfio_disconnect_container(container->fd);
|
||||
close(container->fd);
|
||||
g_free(container);
|
||||
|
@ -1469,8 +1469,9 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
|
||||
|
||||
name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]",
|
||||
user, queue_idx);
|
||||
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
|
||||
page_size, addr);
|
||||
if (!n->mr.ram) /* Don't init again after suspend. */
|
||||
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
|
||||
page_size, addr);
|
||||
g_free(name);
|
||||
|
||||
if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) {
|
||||
|
@ -114,10 +114,21 @@ static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
|
||||
Error **errp)
|
||||
{
|
||||
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
|
||||
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||
|
||||
virtio_add_feature(&requested_features, VIRTIO_VSOCK_F_SEQPACKET);
|
||||
return vhost_get_features(&vvc->vhost_dev, feature_bits,
|
||||
requested_features);
|
||||
if (vsock->seqpacket != ON_OFF_AUTO_OFF) {
|
||||
virtio_add_feature(&requested_features, VIRTIO_VSOCK_F_SEQPACKET);
|
||||
}
|
||||
|
||||
requested_features = vhost_get_features(&vvc->vhost_dev, feature_bits,
|
||||
requested_features);
|
||||
|
||||
if (vsock->seqpacket == ON_OFF_AUTO_ON &&
|
||||
!virtio_has_feature(requested_features, VIRTIO_VSOCK_F_SEQPACKET)) {
|
||||
error_setg(errp, "vhost-vsock backend doesn't support seqpacket");
|
||||
}
|
||||
|
||||
return requested_features;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_virtio_vhost_vsock = {
|
||||
@ -218,6 +229,8 @@ static void vhost_vsock_device_unrealize(DeviceState *dev)
|
||||
static Property vhost_vsock_properties[] = {
|
||||
DEFINE_PROP_UINT64("guest-cid", VHostVSock, conf.guest_cid, 0),
|
||||
DEFINE_PROP_STRING("vhostfd", VHostVSock, conf.vhostfd),
|
||||
DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSock, seqpacket,
|
||||
ON_OFF_AUTO_AUTO),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "migration/misc.h"
|
||||
#include "migration/migration.h"
|
||||
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
@ -662,6 +663,18 @@ virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pages hinted via qemu_guest_free_page_hint() are cleared from the dirty
|
||||
* bitmap and will not get migrated, especially also not when the postcopy
|
||||
* destination starts using them and requests migration from the source; the
|
||||
* faulting thread will stall until postcopy migration finishes and
|
||||
* all threads are woken up. Let's not start free page hinting if postcopy
|
||||
* is possible.
|
||||
*/
|
||||
if (migrate_postcopy_ram()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (pnd->reason) {
|
||||
case PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC:
|
||||
virtio_balloon_free_page_stop(dev);
|
||||
|
@ -88,13 +88,8 @@ static void virtio_mem_pci_size_change_notify(Notifier *notifier, void *data)
|
||||
size_change_notifier);
|
||||
DeviceState *dev = DEVICE(pci_mem);
|
||||
const uint64_t * const size_p = data;
|
||||
const char *id = NULL;
|
||||
|
||||
if (dev->id) {
|
||||
id = g_strdup(dev->id);
|
||||
}
|
||||
|
||||
qapi_event_send_memory_device_size_change(!!id, id, *size_p);
|
||||
qapi_event_send_memory_device_size_change(!!dev->id, dev->id, *size_p);
|
||||
}
|
||||
|
||||
static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -249,13 +249,10 @@ static void vring_packed_event_read(VirtIODevice *vdev,
|
||||
hwaddr off_off = offsetof(VRingPackedDescEvent, off_wrap);
|
||||
hwaddr off_flags = offsetof(VRingPackedDescEvent, flags);
|
||||
|
||||
address_space_read_cached(cache, off_flags, &e->flags,
|
||||
sizeof(e->flags));
|
||||
e->flags = virtio_lduw_phys_cached(vdev, cache, off_flags);
|
||||
/* Make sure flags is seen before off_wrap */
|
||||
smp_rmb();
|
||||
address_space_read_cached(cache, off_off, &e->off_wrap,
|
||||
sizeof(e->off_wrap));
|
||||
virtio_tswap16s(vdev, &e->off_wrap);
|
||||
e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off);
|
||||
virtio_tswap16s(vdev, &e->flags);
|
||||
}
|
||||
|
||||
@ -265,8 +262,7 @@ static void vring_packed_off_wrap_write(VirtIODevice *vdev,
|
||||
{
|
||||
hwaddr off = offsetof(VRingPackedDescEvent, off_wrap);
|
||||
|
||||
virtio_tswap16s(vdev, &off_wrap);
|
||||
address_space_write_cached(cache, off, &off_wrap, sizeof(off_wrap));
|
||||
virtio_stw_phys_cached(vdev, cache, off, off_wrap);
|
||||
address_space_cache_invalidate(cache, off, sizeof(off_wrap));
|
||||
}
|
||||
|
||||
@ -275,8 +271,7 @@ static void vring_packed_flags_write(VirtIODevice *vdev,
|
||||
{
|
||||
hwaddr off = offsetof(VRingPackedDescEvent, flags);
|
||||
|
||||
virtio_tswap16s(vdev, &flags);
|
||||
address_space_write_cached(cache, off, &flags, sizeof(flags));
|
||||
virtio_stw_phys_cached(vdev, cache, off, flags);
|
||||
address_space_cache_invalidate(cache, off, sizeof(flags));
|
||||
}
|
||||
|
||||
@ -509,11 +504,9 @@ static void vring_packed_desc_read_flags(VirtIODevice *vdev,
|
||||
MemoryRegionCache *cache,
|
||||
int i)
|
||||
{
|
||||
address_space_read_cached(cache,
|
||||
i * sizeof(VRingPackedDesc) +
|
||||
offsetof(VRingPackedDesc, flags),
|
||||
flags, sizeof(*flags));
|
||||
virtio_tswap16s(vdev, flags);
|
||||
hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
|
||||
|
||||
*flags = virtio_lduw_phys_cached(vdev, cache, off);
|
||||
}
|
||||
|
||||
static void vring_packed_desc_read(VirtIODevice *vdev,
|
||||
@ -566,8 +559,7 @@ static void vring_packed_desc_write_flags(VirtIODevice *vdev,
|
||||
{
|
||||
hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
|
||||
|
||||
virtio_tswap16s(vdev, &desc->flags);
|
||||
address_space_write_cached(cache, off, &desc->flags, sizeof(desc->flags));
|
||||
virtio_stw_phys_cached(vdev, cache, off, desc->flags);
|
||||
address_space_cache_invalidate(cache, off, sizeof(desc->flags));
|
||||
}
|
||||
|
||||
|
@ -702,6 +702,13 @@ typedef struct BlockLimits {
|
||||
*/
|
||||
uint64_t max_hw_transfer;
|
||||
|
||||
/* Maximal number of scatter/gather elements allowed by the hardware.
|
||||
* Applies whenever transfers to the device bypass the kernel I/O
|
||||
* scheduler, for example with SG_IO. If larger than max_iov
|
||||
* or if zero, blk_get_max_hw_iov will fall back to max_iov.
|
||||
*/
|
||||
int max_hw_iov;
|
||||
|
||||
/* memory alignment, in bytes so that no bounce buffer is needed */
|
||||
size_t min_mem_alignment;
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "hw/acpi/tco.h"
|
||||
|
||||
#define ACPI_PCIHP_ADDR_ICH9 0x0cc4
|
||||
#define ACPI_PCIHP_ADDR_ICH9 0x0cc0
|
||||
|
||||
typedef struct ICH9LPCPMRegs {
|
||||
/*
|
||||
|
@ -30,6 +30,9 @@ struct VHostVSock {
|
||||
VHostVSockCommon parent;
|
||||
VHostVSockConf conf;
|
||||
|
||||
/* features */
|
||||
OnOffAuto seqpacket;
|
||||
|
||||
/*< public >*/
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/sys_membarrier.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -66,6 +67,13 @@ struct rcu_reader_data {
|
||||
|
||||
/* Data used for registry, protected by rcu_registry_lock */
|
||||
QLIST_ENTRY(rcu_reader_data) node;
|
||||
|
||||
/*
|
||||
* NotifierList used to force an RCU grace period. Accessed under
|
||||
* rcu_registry_lock. Note that the notifier is called _outside_
|
||||
* the thread!
|
||||
*/
|
||||
NotifierList force_rcu;
|
||||
};
|
||||
|
||||
extern __thread struct rcu_reader_data rcu_reader;
|
||||
@ -180,6 +188,13 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock)
|
||||
#define RCU_READ_LOCK_GUARD() \
|
||||
g_autoptr(RCUReadAuto) _rcu_read_auto __attribute__((unused)) = rcu_read_auto_lock()
|
||||
|
||||
/*
|
||||
* Force-RCU notifiers tell readers that they should exit their
|
||||
* read-side critical section.
|
||||
*/
|
||||
void rcu_add_force_rcu_notifier(Notifier *n);
|
||||
void rcu_remove_force_rcu_notifier(Notifier *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -210,6 +210,7 @@ uint32_t blk_get_request_alignment(BlockBackend *blk);
|
||||
uint32_t blk_get_max_transfer(BlockBackend *blk);
|
||||
uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
|
||||
int blk_get_max_iov(BlockBackend *blk);
|
||||
int blk_get_max_hw_iov(BlockBackend *blk);
|
||||
void blk_set_guest_block_size(BlockBackend *blk, int align);
|
||||
void *blk_try_blockalign(BlockBackend *blk, size_t size);
|
||||
void *blk_blockalign(BlockBackend *blk, size_t size);
|
||||
|
@ -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],
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
91
meson.build
91
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'
|
||||
|
@ -1496,7 +1496,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
if (strcmp(target, "passwd") == 0 ||
|
||||
strcmp(target, "password") == 0) {
|
||||
if (arg) {
|
||||
if (!arg) {
|
||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||
monitor_read_password(hmp_mon, hmp_change_read_arg, NULL);
|
||||
return;
|
||||
|
70
myconfigure.sh
Executable file
70
myconfigure.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
mkdir -p build
|
||||
cd build
|
||||
../configure --target-list=arm-linux-user,arm-softmmu,x86_64-linux-user,x86_64-softmmu \
|
||||
--audio-drv-list= \
|
||||
--disable-blobs \
|
||||
--disable-bochs \
|
||||
--disable-brlapi \
|
||||
--disable-bsd-user \
|
||||
--disable-bzip2 \
|
||||
--disable-cap-ng \
|
||||
--disable-cloop \
|
||||
--disable-curl \
|
||||
--disable-curses \
|
||||
--disable-dmg \
|
||||
--enable-fdt \
|
||||
--disable-gcrypt \
|
||||
--disable-glusterfs \
|
||||
--disable-gnutls \
|
||||
--disable-gtk \
|
||||
--disable-guest-agent \
|
||||
--disable-iconv \
|
||||
--disable-libiscsi \
|
||||
--disable-libnfs \
|
||||
--disable-libssh \
|
||||
--disable-libusb \
|
||||
--disable-linux-aio \
|
||||
--disable-live-block-migration \
|
||||
--disable-lzo \
|
||||
--disable-nettle \
|
||||
--disable-numa \
|
||||
--disable-opengl \
|
||||
--disable-parallels \
|
||||
--disable-plugins \
|
||||
--disable-qcow1 \
|
||||
--disable-qed \
|
||||
--disable-rbd \
|
||||
--disable-rdma \
|
||||
--disable-replication \
|
||||
--disable-sdl \
|
||||
--disable-seccomp \
|
||||
--disable-smartcard \
|
||||
--disable-snappy \
|
||||
--disable-spice \
|
||||
--enable-system \
|
||||
--disable-tools \
|
||||
--disable-tpm \
|
||||
--disable-usb-redir \
|
||||
--disable-vde \
|
||||
--disable-vdi \
|
||||
--disable-vhost-crypto \
|
||||
--disable-vhost-kernel \
|
||||
--disable-vhost-net \
|
||||
--disable-vhost-scsi \
|
||||
--disable-vhost-user \
|
||||
--disable-vhost-vdpa \
|
||||
--disable-vhost-vsock \
|
||||
--disable-virglrenderer \
|
||||
--disable-virtfs \
|
||||
--disable-vnc \
|
||||
--disable-vnc-jpeg \
|
||||
--disable-vnc-png \
|
||||
--disable-vnc-sasl \
|
||||
--disable-vte \
|
||||
--disable-vvfat \
|
||||
--disable-xen \
|
||||
--disable-xen-pci-passthrough \
|
||||
--disable-xfsctl \
|
||||
--as-shared-lib
|
69
myconfigureunshared.sh
Executable file
69
myconfigureunshared.sh
Executable file
@ -0,0 +1,69 @@
|
||||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
mkdir -p build
|
||||
cd build
|
||||
../configure --target-list=arm-linux-user,arm-softmmu \
|
||||
--audio-drv-list= \
|
||||
--disable-blobs \
|
||||
--disable-bochs \
|
||||
--disable-brlapi \
|
||||
--disable-bsd-user \
|
||||
--disable-bzip2 \
|
||||
--disable-cap-ng \
|
||||
--disable-cloop \
|
||||
--disable-curl \
|
||||
--disable-curses \
|
||||
--disable-dmg \
|
||||
--enable-fdt \
|
||||
--disable-gcrypt \
|
||||
--disable-glusterfs \
|
||||
--disable-gnutls \
|
||||
--disable-gtk \
|
||||
--disable-guest-agent \
|
||||
--disable-iconv \
|
||||
--disable-libiscsi \
|
||||
--disable-libnfs \
|
||||
--disable-libssh \
|
||||
--disable-libusb \
|
||||
--disable-linux-aio \
|
||||
--disable-live-block-migration \
|
||||
--disable-lzo \
|
||||
--disable-nettle \
|
||||
--disable-numa \
|
||||
--disable-opengl \
|
||||
--disable-parallels \
|
||||
--disable-plugins \
|
||||
--disable-qcow1 \
|
||||
--disable-qed \
|
||||
--disable-rbd \
|
||||
--disable-rdma \
|
||||
--disable-replication \
|
||||
--disable-sdl \
|
||||
--disable-seccomp \
|
||||
--disable-smartcard \
|
||||
--disable-snappy \
|
||||
--disable-spice \
|
||||
--enable-system \
|
||||
--disable-tools \
|
||||
--disable-tpm \
|
||||
--disable-usb-redir \
|
||||
--disable-vde \
|
||||
--disable-vdi \
|
||||
--disable-vhost-crypto \
|
||||
--disable-vhost-kernel \
|
||||
--disable-vhost-net \
|
||||
--disable-vhost-scsi \
|
||||
--disable-vhost-user \
|
||||
--disable-vhost-vdpa \
|
||||
--disable-vhost-vsock \
|
||||
--disable-virglrenderer \
|
||||
--disable-virtfs \
|
||||
--disable-vnc \
|
||||
--disable-vnc-jpeg \
|
||||
--disable-vnc-png \
|
||||
--disable-vnc-sasl \
|
||||
--disable-vte \
|
||||
--disable-vvfat \
|
||||
--disable-xen \
|
||||
--disable-xen-pci-passthrough \
|
||||
--disable-xfsctl
|
31
mytest.c
Normal file
31
mytest.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void libafl_qemu_main_loop( void );
|
||||
void libafl_qemu_sys_init(int argc, char **argv, char **envp);
|
||||
void libafl_qemu_cleanup( void );
|
||||
|
||||
void libafl_qemu_set_breakpoint( unsigned long int );
|
||||
void libafl_qemu_remove_native_breakpoint( unsigned long int );
|
||||
void libafl_qemu_set_native_breakpoint( unsigned long int );
|
||||
void libafl_snapshot_save( const char* );
|
||||
void libafl_snapshot_load( const char* );
|
||||
int64_t libafl_get_clock( void );
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
libafl_qemu_sys_init(argc, argv, envp);
|
||||
libafl_qemu_set_native_breakpoint(0x4c60);//send 217028
|
||||
libafl_qemu_main_loop();
|
||||
libafl_qemu_remove_native_breakpoint(0x4c60);
|
||||
libafl_qemu_set_native_breakpoint(0x00004f5c);
|
||||
libafl_snapshot_save("Start");
|
||||
printf("Snap start icount: %lu\n",libafl_get_clock());
|
||||
libafl_qemu_main_loop();
|
||||
printf("tr1 icount: %lu\n",libafl_get_clock());
|
||||
libafl_snapshot_load("Start");
|
||||
libafl_qemu_main_loop();
|
||||
printf("tr2 icount: %lu\n",libafl_get_clock());
|
||||
libafl_qemu_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
12
myteststarter.sh
Executable file
12
myteststarter.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
if [ ! -f dummy.qcow2 ]; then
|
||||
qemu-img create -f qcow2 dummy.qcow2 32M
|
||||
fi
|
||||
export LD_LIBRARY_PATH=./build
|
||||
build/qemu-system-arm -machine mps2-an385 -monitor null -semihosting \
|
||||
--semihosting-config enable=on,target=native \
|
||||
-kernel $1 \
|
||||
-serial stdio -nographic \
|
||||
-snapshot -drive if=none,format=qcow2,file=dummy.qcow2 \
|
||||
-icount shift=3,align=off,sleep=off \
|
||||
-S
|
@ -1413,6 +1413,9 @@ static int nbd_receive_request(NBDClient *client, NBDRequest *request,
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Request
|
||||
[ 0 .. 3] magic (NBD_REQUEST_MAGIC)
|
||||
|
@ -1,9 +1,11 @@
|
||||
if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host
|
||||
plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')]
|
||||
elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host
|
||||
plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')]
|
||||
else
|
||||
plugin_ldflags = []
|
||||
plugin_ldflags = []
|
||||
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
|
||||
if not enable_modules
|
||||
if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host
|
||||
plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')]
|
||||
elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host
|
||||
plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')]
|
||||
endif
|
||||
endif
|
||||
|
||||
specific_ss.add(when: 'CONFIG_PLUGIN', if_true: [files(
|
||||
|
@ -135,7 +135,9 @@ static void usage(const char *name)
|
||||
" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
|
||||
" '[ID_OR_NAME]'\n"
|
||||
" -n, --nocache disable host cache\n"
|
||||
" --cache=MODE set cache mode (none, writeback, ...)\n"
|
||||
" --cache=MODE set cache mode used to access the disk image, the\n"
|
||||
" valid options are: 'none', 'writeback' (default),\n"
|
||||
" 'writethrough', 'directsync' and 'unsafe'\n"
|
||||
" --aio=MODE set AIO mode (native, io_uring or threads)\n"
|
||||
" --discard=MODE set discard mode (ignore, unmap)\n"
|
||||
" --detect-zeroes=MODE set detect-zeroes mode (off, on, unmap)\n"
|
||||
@ -552,7 +554,7 @@ int main(int argc, char **argv)
|
||||
bool alloc_depth = false;
|
||||
const char *tlscredsid = NULL;
|
||||
bool imageOpts = false;
|
||||
bool writethrough = true;
|
||||
bool writethrough = false; /* Client will flush as needed. */
|
||||
bool fork_process = false;
|
||||
bool list = false;
|
||||
int old_stderr = -1;
|
||||
|
@ -305,7 +305,10 @@ void cpu_handle_guest_debug(CPUState *cpu)
|
||||
cpu_single_step(cpu, 0);
|
||||
}
|
||||
} else {
|
||||
gdb_set_stop_cpu(cpu);
|
||||
/* Begin LibAFL changes */
|
||||
// With LibAFL Breakpoints there is no gdb attached.
|
||||
// gdb_set_stop_cpu(cpu);
|
||||
/* End LibAFL changes */
|
||||
qemu_system_debug_request();
|
||||
cpu->stopped = true;
|
||||
}
|
||||
|
128
softmmu/main.c
128
softmmu/main.c
@ -44,11 +44,139 @@ int main(int argc, char **argv)
|
||||
#define main qemu_main
|
||||
#endif /* CONFIG_COCOA */
|
||||
|
||||
/* Begin LibAFL instrumentation */
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "migration/snapshot.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "exec/memory.h"
|
||||
void libafl_qemu_main_loop( void );
|
||||
void libafl_qemu_run( void );
|
||||
void libafl_qemu_sys_init(int argc, char **argv, char **envp);
|
||||
void libafl_qemu_cleanup( void );
|
||||
|
||||
void libafl_qemu_sys_init(int argc, char **argv, char **envp) { qemu_init(argc, argv, envp); }
|
||||
void libafl_qemu_cleanup( void ) { qemu_cleanup(); }
|
||||
void libafl_qemu_set_native_breakpoint( vaddr );
|
||||
void libafl_qemu_remove_native_breakpoint( vaddr );
|
||||
int libafl_snapshot_save( const char* );
|
||||
int libafl_snapshot_load( const char* );
|
||||
void libafl_phys_read(vaddr, uint8_t*, int);
|
||||
void libafl_phys_write(vaddr, uint8_t*, int);
|
||||
int64_t libafl_get_clock( void );
|
||||
|
||||
#ifdef TARGET_ARM
|
||||
extern void libafl_start_int_timer(void);
|
||||
#endif
|
||||
void libafl_qemu_main_loop( void )
|
||||
{
|
||||
#ifdef TARGET_ARM
|
||||
libafl_start_int_timer();
|
||||
#endif
|
||||
vm_start();
|
||||
qemu_main_loop();
|
||||
}
|
||||
void libafl_qemu_run( void ) { libafl_qemu_main_loop(); }
|
||||
|
||||
void libafl_qemu_set_native_breakpoint(vaddr pc)
|
||||
{
|
||||
CPUState *cpu;
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_breakpoint_insert(cpu, pc, BP_GDB, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void libafl_qemu_remove_native_breakpoint(vaddr pc)
|
||||
{
|
||||
CPUState *cpu;
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_breakpoint_remove(cpu, pc, BP_GDB);
|
||||
}
|
||||
}
|
||||
|
||||
int libafl_snapshot_save( const char* name )
|
||||
{
|
||||
Error *err = NULL;
|
||||
save_snapshot(name, true, NULL, false, NULL, &err);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
int libafl_snapshot_load( const char* name )
|
||||
{
|
||||
Error *err = NULL;
|
||||
load_snapshot(name, NULL, false, NULL, &err);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
void libafl_phys_read(vaddr addr, uint8_t* buf, int len)
|
||||
{
|
||||
cpu_physical_memory_read(addr, buf, len);
|
||||
}
|
||||
void libafl_phys_write(vaddr addr, uint8_t* buf, int len)
|
||||
{
|
||||
cpu_physical_memory_write(addr, buf, len);
|
||||
}
|
||||
|
||||
int64_t libafl_get_clock( void )
|
||||
{
|
||||
return icount_get_raw();
|
||||
}
|
||||
|
||||
#ifndef AS_SHARED_LIB
|
||||
#ifdef TARGET_ARM
|
||||
extern unsigned int libafl_int_offset;
|
||||
#endif
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
qemu_init(argc, argv, envp);
|
||||
qemu_main_loop();
|
||||
qemu_cleanup();
|
||||
//LIBAFL Instrumentation Demo
|
||||
/*
|
||||
// unsigned char buf[32] = "_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
#ifdef TARGET_ARM
|
||||
libafl_int_offset = 375000;
|
||||
#endif
|
||||
// unsigned char buf[32] = "\x02\x9b\x02\x9b\x02\x9b\x02\x9b"; // 0xFA71 x 4
|
||||
unsigned char buf[32] = "\x05\x29\x07\x1f\x0b\x17\x01\x17"; // 5*73 7*59 11*43
|
||||
unsigned char len = 8;
|
||||
libafl_qemu_sys_init(argc, argv, envp);
|
||||
int pheader = 0x5be4;
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_phys_read(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_phys_write(0x20000108-0x20000100+pheader, &len,1);
|
||||
printf("FUZZ_INPUT[0]: %x\n", buf[0]);
|
||||
libafl_qemu_set_native_breakpoint(0xae);
|
||||
libafl_snapshot_save("Start");
|
||||
int counter = 3;
|
||||
do {
|
||||
libafl_qemu_main_loop();
|
||||
libafl_snapshot_load("Start");
|
||||
puts("Reload has occured");
|
||||
counter--;
|
||||
} while (runstate_check(RUN_STATE_DEBUG) && counter);
|
||||
libafl_qemu_cleanup();
|
||||
*/
|
||||
/*
|
||||
// Clock comparison
|
||||
unsigned char ex1[32] = "_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
// unsigned char ex1[32] = "a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
unsigned char ex2[32] = "a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
libafl_qemu_sys_init(argc, argv, envp);
|
||||
libafl_qemu_set_native_breakpoint(0x4be0);
|
||||
libafl_snapshot_save("Start");
|
||||
libafl_phys_write(0x20000110-0x20000100+0x00006ae4, ex1,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("Post ex1: %ld\n",libafl_get_clock());
|
||||
libafl_snapshot_load("Start");
|
||||
libafl_phys_write(0x20000110-0x20000100+0x00006ae4, ex2,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("Post ex2: %ld\n",libafl_get_clock());
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* End LibAFL instrumentation */
|
||||
|
@ -668,6 +668,10 @@ static bool main_loop_should_exit(void)
|
||||
|
||||
if (qemu_debug_requested()) {
|
||||
vm_stop(RUN_STATE_DEBUG);
|
||||
/* Begin LibAFL instrumentation */
|
||||
// main loop will exit back to fuzzer
|
||||
return true;
|
||||
/* End LibAFL instrumentation */
|
||||
}
|
||||
if (qemu_suspend_requested()) {
|
||||
qemu_system_suspend();
|
||||
|
10
starter.sh
Executable file
10
starter.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
if [ ! -f dummy.qcow2 ]; then
|
||||
qemu-img create -f qcow2 dummy.qcow2 32M
|
||||
fi
|
||||
build/qemu-system-arm -machine mps2-an385 -monitor null -semihosting \
|
||||
--semihosting-config enable=on,target=native \
|
||||
-kernel $1 \
|
||||
-serial stdio -nographic \
|
||||
-snapshot -drive if=none,format=qcow2,file=dummy.qcow2 \
|
||||
-icount shift=auto,align=off,sleep=off
|
@ -816,6 +816,7 @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
||||
shadow_regions[j].gpa = dev->regions[i].gpa;
|
||||
shadow_regions[j].size = dev->regions[i].size;
|
||||
shadow_regions[j].qva = dev->regions[i].qva;
|
||||
shadow_regions[j].mmap_addr = dev->regions[i].mmap_addr;
|
||||
shadow_regions[j].mmap_offset = dev->regions[i].mmap_offset;
|
||||
j++;
|
||||
} else {
|
||||
|
@ -265,12 +265,15 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||
}
|
||||
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
|
||||
#endif
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
uint32_t initial_msp; /* Loaded from 0x0 */
|
||||
uint32_t initial_pc; /* Loaded from 0x4 */
|
||||
uint8_t *rom;
|
||||
uint32_t vecbase;
|
||||
#endif
|
||||
|
||||
if (cpu_isar_feature(aa32_lob, cpu)) {
|
||||
/*
|
||||
@ -324,6 +327,8 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
|
||||
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Unlike A/R profile, M profile defines the reset LR value */
|
||||
env->regs[14] = 0xffffffff;
|
||||
|
||||
@ -352,8 +357,22 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
env->regs[13] = initial_msp & 0xFFFFFFFC;
|
||||
env->regs[15] = initial_pc & ~1;
|
||||
env->thumb = initial_pc & 1;
|
||||
#else
|
||||
/*
|
||||
* For user mode we run non-secure and with access to the FPU.
|
||||
* The FPU context is active (ie does not need further setup)
|
||||
* and is owned by non-secure.
|
||||
*/
|
||||
env->v7m.secure = false;
|
||||
env->v7m.nsacr = 0xcff;
|
||||
env->v7m.cpacr[M_REG_NS] = 0xf0ffff;
|
||||
env->v7m.fpccr[M_REG_S] &=
|
||||
~(R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK);
|
||||
env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
|
||||
* executing as AArch32 then check if highvecs are enabled and
|
||||
* adjust the PC accordingly.
|
||||
|
@ -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) {
|
||||
|
@ -2615,8 +2615,14 @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
|
||||
}
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
void libafl_gen_jmp(target_ulong src, target_ulong dst); // see translate-all.c
|
||||
//// --- End LibAFL code ---
|
||||
static inline void gen_jmp(DisasContext *s, uint32_t dest)
|
||||
{
|
||||
//// --- Begin LibAFL code ---
|
||||
libafl_gen_jmp(s->pc_curr,dest);
|
||||
//// --- End LibAFL code ---
|
||||
gen_jmp_tb(s, dest, 0);
|
||||
}
|
||||
|
||||
@ -5424,6 +5430,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 +5452,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 +5562,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);
|
||||
|
||||
|
@ -3102,7 +3102,7 @@ static const X86CPUDefinition builtin_x86_defs[] = {
|
||||
MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO |
|
||||
MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO,
|
||||
.features[FEAT_7_1_EAX] =
|
||||
CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_AVX512_BF16,
|
||||
CPUID_7_1_EAX_AVX512_BF16,
|
||||
/* XSAVES is added in version 2 */
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
|
||||
|
@ -257,6 +257,7 @@ typedef enum X86Seg {
|
||||
| CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \
|
||||
| CR4_MCE_MASK | CR4_PGE_MASK | CR4_PCE_MASK \
|
||||
| CR4_OSFXSR_MASK | CR4_OSXMMEXCPT_MASK |CR4_UMIP_MASK \
|
||||
| CR4_LA57_MASK \
|
||||
| CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \
|
||||
| CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK))
|
||||
|
||||
|
@ -90,19 +90,10 @@ static int mmu_translate(CPUState *cs, hwaddr addr, MMUTranslateFunc get_hphys_f
|
||||
target_ulong pdpe_addr;
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
if (pg_mode & PG_MODE_LMA) {
|
||||
bool la57 = pg_mode & PG_MODE_LA57;
|
||||
uint64_t pml5e_addr, pml5e;
|
||||
uint64_t pml4e_addr, pml4e;
|
||||
int32_t sext;
|
||||
|
||||
/* test virtual address sign extension */
|
||||
sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
|
||||
if (get_hphys_func && sext != 0 && sext != -1) {
|
||||
env->error_code = 0;
|
||||
cs->exception_index = EXCP0D_GPF;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (la57) {
|
||||
pml5e_addr = ((cr3 & ~0xfff) +
|
||||
@ -287,7 +278,7 @@ do_check_protect_pse36:
|
||||
*prot |= PAGE_EXEC;
|
||||
}
|
||||
|
||||
if (!(env->hflags & HF_LMA_MASK)) {
|
||||
if (!(pg_mode & PG_MODE_LMA)) {
|
||||
pkr = 0;
|
||||
} else if (ptep & PG_USER_MASK) {
|
||||
pkr = pg_mode & PG_MODE_PKE ? env->pkru : 0;
|
||||
@ -423,6 +414,18 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size,
|
||||
page_size = 4096;
|
||||
} else {
|
||||
pg_mode = get_pg_mode(env);
|
||||
if (pg_mode & PG_MODE_LMA) {
|
||||
int32_t sext;
|
||||
|
||||
/* test virtual address sign extension */
|
||||
sext = (int64_t)addr >> (pg_mode & PG_MODE_LA57 ? 56 : 47);
|
||||
if (sext != 0 && sext != -1) {
|
||||
env->error_code = 0;
|
||||
cs->exception_index = EXCP0D_GPF;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
error_code = mmu_translate(cs, addr, get_hphys, env->cr[3], is_write1,
|
||||
mmu_idx, pg_mode,
|
||||
&paddr, &page_size, &prot);
|
||||
|
@ -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;
|
||||
|
@ -2477,8 +2477,13 @@ static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
|
||||
tcg_out_vldst(s, INSN_VLD1 | 0x7d0, arg, arg1, arg2);
|
||||
return;
|
||||
case TCG_TYPE_V128:
|
||||
/* regs 2; size 8; align 16 */
|
||||
tcg_out_vldst(s, INSN_VLD1 | 0xae0, arg, arg1, arg2);
|
||||
/*
|
||||
* We have only 8-byte alignment for the stack per the ABI.
|
||||
* Rather than dynamically re-align the stack, it's easier
|
||||
* to simply not request alignment beyond that. So:
|
||||
* regs 2; size 8; align 8
|
||||
*/
|
||||
tcg_out_vldst(s, INSN_VLD1 | 0xad0, arg, arg1, arg2);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@ -2497,8 +2502,8 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
|
||||
tcg_out_vldst(s, INSN_VST1 | 0x7d0, arg, arg1, arg2);
|
||||
return;
|
||||
case TCG_TYPE_V128:
|
||||
/* regs 2; size 8; align 16 */
|
||||
tcg_out_vldst(s, INSN_VST1 | 0xae0, arg, arg1, arg2);
|
||||
/* See tcg_out_ld re alignment: regs 2; size 8; align 8 */
|
||||
tcg_out_vldst(s, INSN_VST1 | 0xad0, arg, arg1, arg2);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
35
tcg/tcg-op.c
35
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);
|
||||
|
||||
|
18
tcg/tcg.c
18
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;
|
||||
@ -3060,7 +3070,13 @@ static void temp_allocate_frame(TCGContext *s, TCGTemp *ts)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
assert(align <= TCG_TARGET_STACK_ALIGN);
|
||||
/*
|
||||
* Assume the stack is sufficiently aligned.
|
||||
* This affects e.g. ARM NEON, where we have 8 byte stack alignment
|
||||
* and do not require 16 byte vector alignment. This seems slightly
|
||||
* easier than fully parameterizing the above switch statement.
|
||||
*/
|
||||
align = MIN(TCG_TARGET_STACK_ALIGN, align);
|
||||
off = ROUND_UP(s->current_frame_offset, align);
|
||||
|
||||
/* If we've exhausted the stack frame, restart with a smaller TB. */
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/data/acpi/q35/DSDT.multi-bridge
Normal file
BIN
tests/data/acpi/q35/DSDT.multi-bridge
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -859,6 +859,23 @@ static void test_acpi_q35_tcg_bridge(void)
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
static void test_acpi_q35_multif_bridge(void)
|
||||
{
|
||||
test_data data = {
|
||||
.machine = MACHINE_Q35,
|
||||
.variant = ".multi-bridge",
|
||||
};
|
||||
test_acpi_one("-device pcie-root-port,id=pcie-root-port-0,"
|
||||
"multifunction=on,"
|
||||
"port=0x0,chassis=1,addr=0x2,bus=pcie.0 "
|
||||
"-device pcie-root-port,id=pcie-root-port-1,"
|
||||
"port=0x1,chassis=2,addr=0x3.0x1,bus=pcie.0 "
|
||||
"-device virtio-balloon,id=balloon0,"
|
||||
"bus=pcie.0,addr=0x4.0x2",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
static void test_acpi_q35_tcg_mmio64(void)
|
||||
{
|
||||
test_data data = {
|
||||
@ -1528,6 +1545,7 @@ int main(int argc, char *argv[])
|
||||
test_acpi_piix4_no_acpi_pci_hotplug);
|
||||
qtest_add_func("acpi/q35", test_acpi_q35_tcg);
|
||||
qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
|
||||
qtest_add_func("acpi/q35/multif-bridge", test_acpi_q35_multif_bridge);
|
||||
qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64);
|
||||
qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi);
|
||||
qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi);
|
||||
|
@ -32,6 +32,9 @@
|
||||
/* TODO actually test the results and get rid of this */
|
||||
#define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
|
||||
|
||||
#define DRIVE_FLOPPY_BLANK \
|
||||
"-drive if=floppy,file=null-co://,file.read-zeroes=on,format=raw,size=1440k"
|
||||
|
||||
#define TEST_IMAGE_SIZE 1440 * 1024
|
||||
|
||||
#define FLOPPY_BASE 0x3f0
|
||||
@ -546,6 +549,40 @@ static void fuzz_registers(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool qtest_check_clang_sanitizer(void)
|
||||
{
|
||||
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
|
||||
return true;
|
||||
#else
|
||||
g_test_skip("QEMU not configured using --enable-sanitizers");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
static void test_cve_2021_20196(void)
|
||||
{
|
||||
QTestState *s;
|
||||
|
||||
if (!qtest_check_clang_sanitizer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
s = qtest_initf("-nographic -m 32M -nodefaults " DRIVE_FLOPPY_BLANK);
|
||||
|
||||
qtest_outw(s, 0x3f4, 0x0500);
|
||||
qtest_outb(s, 0x3f5, 0x00);
|
||||
qtest_outb(s, 0x3f5, 0x00);
|
||||
qtest_outw(s, 0x3f4, 0x0000);
|
||||
qtest_outb(s, 0x3f5, 0x00);
|
||||
qtest_outw(s, 0x3f1, 0x0400);
|
||||
qtest_outw(s, 0x3f4, 0x0000);
|
||||
qtest_outw(s, 0x3f4, 0x0000);
|
||||
qtest_outb(s, 0x3f5, 0x00);
|
||||
qtest_outb(s, 0x3f5, 0x01);
|
||||
qtest_outw(s, 0x3f1, 0x0500);
|
||||
qtest_outb(s, 0x3f5, 0x00);
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
@ -576,6 +613,7 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
|
||||
qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
|
||||
qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
|
||||
qtest_add_func("/fdc/fuzz/cve_2021_20196", test_cve_2021_20196);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
|
@ -16,7 +16,10 @@ SECTIONS {
|
||||
*(.rodata)
|
||||
} :text
|
||||
|
||||
/* Keep build ID and PVH notes in same section */
|
||||
/DISCARD/ : {
|
||||
*(.note.gnu*)
|
||||
}
|
||||
|
||||
.notes : {
|
||||
*(.note.*)
|
||||
} :note
|
||||
|
@ -1345,25 +1345,22 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
|
||||
SocketAddress *addr;
|
||||
struct sockaddr_un *su = (struct sockaddr_un *)sa;
|
||||
|
||||
assert(salen >= sizeof(su->sun_family) + 1 &&
|
||||
salen <= sizeof(struct sockaddr_un));
|
||||
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
|
||||
salen -= offsetof(struct sockaddr_un, sun_path);
|
||||
#ifdef CONFIG_LINUX
|
||||
if (!su->sun_path[0]) {
|
||||
if (salen > 0 && !su->sun_path[0]) {
|
||||
/* Linux abstract socket */
|
||||
addr->u.q_unix.path = g_strndup(su->sun_path + 1,
|
||||
salen - sizeof(su->sun_family) - 1);
|
||||
addr->u.q_unix.path = g_strndup(su->sun_path + 1, salen - 1);
|
||||
addr->u.q_unix.has_abstract = true;
|
||||
addr->u.q_unix.abstract = true;
|
||||
addr->u.q_unix.has_tight = true;
|
||||
addr->u.q_unix.tight = salen < sizeof(*su);
|
||||
addr->u.q_unix.tight = salen < sizeof(su->sun_path);
|
||||
return addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
addr->u.q_unix.path = g_strndup(su->sun_path, sizeof(su->sun_path));
|
||||
addr->u.q_unix.path = g_strndup(su->sun_path, salen);
|
||||
return addr;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
19
util/rcu.c
19
util/rcu.c
@ -46,6 +46,7 @@
|
||||
unsigned long rcu_gp_ctr = RCU_GP_LOCKED;
|
||||
|
||||
QemuEvent rcu_gp_event;
|
||||
static int in_drain_call_rcu;
|
||||
static QemuMutex rcu_registry_lock;
|
||||
static QemuMutex rcu_sync_lock;
|
||||
|
||||
@ -107,6 +108,8 @@ static void wait_for_readers(void)
|
||||
* get some extra futex wakeups.
|
||||
*/
|
||||
qatomic_set(&index->waiting, false);
|
||||
} else if (qatomic_read(&in_drain_call_rcu)) {
|
||||
notifier_list_notify(&index->force_rcu, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,8 +342,10 @@ void drain_call_rcu(void)
|
||||
* assumed.
|
||||
*/
|
||||
|
||||
qatomic_inc(&in_drain_call_rcu);
|
||||
call_rcu1(&rcu_drain.rcu, drain_rcu_callback);
|
||||
qemu_event_wait(&rcu_drain.drain_complete_event);
|
||||
qatomic_dec(&in_drain_call_rcu);
|
||||
|
||||
if (locked) {
|
||||
qemu_mutex_lock_iothread();
|
||||
@ -363,6 +368,20 @@ void rcu_unregister_thread(void)
|
||||
qemu_mutex_unlock(&rcu_registry_lock);
|
||||
}
|
||||
|
||||
void rcu_add_force_rcu_notifier(Notifier *n)
|
||||
{
|
||||
qemu_mutex_lock(&rcu_registry_lock);
|
||||
notifier_list_add(&rcu_reader.force_rcu, n);
|
||||
qemu_mutex_unlock(&rcu_registry_lock);
|
||||
}
|
||||
|
||||
void rcu_remove_force_rcu_notifier(Notifier *n)
|
||||
{
|
||||
qemu_mutex_lock(&rcu_registry_lock);
|
||||
notifier_remove(n);
|
||||
qemu_mutex_unlock(&rcu_registry_lock);
|
||||
}
|
||||
|
||||
static void rcu_init_complete(void)
|
||||
{
|
||||
QemuThread thread;
|
||||
|
Loading…
x
Reference in New Issue
Block a user