Skip to content

Make breakpoints work both in GDB and libafl qemu concurrently #117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,17 +714,15 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)

static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
{
//// --- Begin LibAFL code ---

//// --- Begin LibAFL code ---
if (cpu->exception_index == EXCP_LIBAFL_EXIT) {
*ret = cpu->exception_index;
cpu->exception_index = -1;

libafl_sync_exit_cpu();
return true;
}

//// --- End LibAFL code ---
//// --- End LibAFL code ---

if (cpu->exception_index < 0) {
#ifndef CONFIG_USER_ONLY
Expand Down
5 changes: 5 additions & 0 deletions include/libafl/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ int libafl_qemu_set_hw_breakpoint(vaddr addr);
int libafl_qemu_remove_hw_breakpoint(vaddr addr);

void libafl_qemu_init(int argc, char** argv);
int libafl_qemu_run(void);

size_t libafl_target_page_size(void);
int libafl_target_page_mask(void);
int libafl_target_page_offset_mask(void);
6 changes: 3 additions & 3 deletions include/libafl/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#include "exec/cpu-defs.h"

struct libafl_mapinfo {
target_ulong start;
target_ulong end;
target_ulong offset;
uint64_t start;
uint64_t end;
uint64_t offset;
const char* path;
int flags;
int is_priv;
Expand Down
6 changes: 6 additions & 0 deletions include/system/runstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,11 @@ void qemu_system_guest_crashloaded(GuestPanicInformation *info);
void qemu_system_guest_pvshutdown(void);
bool qemu_system_dump_in_progress(void);

//// --- Begin LibAFL code ---
#ifdef AS_LIB
void qemu_system_return_request(void);
#endif
//// --- End LibAFL code ---

#endif

4 changes: 2 additions & 2 deletions libafl/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static void prepare_qemu_exit(CPUState* cpu, target_ulong next_pc)
last_exit_reason.next_pc = next_pc;

#ifndef CONFIG_USER_ONLY
qemu_system_debug_request();
qemu_system_return_request();
#endif

// in usermode, this may be called from the syscall hook, thus already out
Expand Down Expand Up @@ -146,7 +146,7 @@ void libafl_exit_request_timeout(void)
last_exit_reason.kind = TIMEOUT;
last_exit_reason.cpu = current_cpu;

qemu_system_debug_request();
qemu_system_return_request();
}
#endif

Expand Down
22 changes: 21 additions & 1 deletion libafl/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,32 @@
#include "system/accel-ops.h"
#include "system/cpus.h"
#include "gdbstub/enums.h"
#include "exec/target_page.h"
#include "qemu/main-loop.h"
#include "system/replay.h"
#include "system/runstate.h"

#include "libafl/system.h"

int libafl_qemu_toggle_hw_breakpoint(vaddr addr, bool set);

void libafl_qemu_init(int argc, char** argv) { qemu_init(argc, argv); }
void libafl_qemu_init(int argc, char** argv)
{
qemu_init(argc, argv);
}

int libafl_qemu_run(void)
{
if (runstate_check(RUN_STATE_RET)) {
// we are resuming from a return to libafl
// transition to RUN_STATE_RUNNING
vm_start();
}

int status = qemu_main_loop();

return status;
}

int libafl_qemu_set_hw_breakpoint(vaddr addr)
{
Expand Down
6 changes: 0 additions & 6 deletions linux-user/arm/cpu_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,17 +297,13 @@ void cpu_loop(CPUARMState *env)
abi_ulong ret;

//// --- Begin LibAFL code ---

libafl_exit_signal_vm_start();

//// --- End LibAFL code ---

for(;;) {

//// --- Begin LibAFL code ---

if (libafl_exit_asap()) return;

//// --- End LibAFL code ---

cpu_exec_start(cs);
Expand All @@ -318,10 +314,8 @@ void cpu_loop(CPUARMState *env)
switch(trapnr) {

//// --- Begin LibAFL code ---

case EXCP_LIBAFL_EXIT:
return;

//// --- End LibAFL code ---

case EXCP_UDEF:
Expand Down
6 changes: 0 additions & 6 deletions linux-user/ppc/cpu_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,14 @@ void cpu_loop(CPUPPCState *env)
target_ulong ret;

//// --- Begin LibAFL code ---

libafl_exit_signal_vm_start();

//// --- End LibAFL code ---

for(;;) {
bool arch_interrupt;

//// --- Begin LibAFL code ---

if (libafl_exit_asap()) return;

//// --- End LibAFL code ---

cpu_exec_start(cs);
Expand All @@ -101,10 +97,8 @@ void cpu_loop(CPUPPCState *env)
switch (trapnr) {

//// --- Begin LibAFL code ---

case EXCP_LIBAFL_EXIT:
return;

//// --- End LibAFL code ---

case POWERPC_EXCP_NONE:
Expand Down
6 changes: 3 additions & 3 deletions linux-user/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -13953,9 +13953,9 @@ IntervalTreeNode * libafl_maps_next(IntervalTreeNode *pageflags_maps_node, Inter
if (flags & PAGE_EXEC) libafl_flags |= PROT_EXEC;

ret->is_valid = true;
ret->start = (target_ulong)h2g_nocheck(min);
ret->end = (target_ulong)h2g_nocheck(max);
ret->offset = (target_ulong)e->offset;
ret->start = (uint64_t) h2g_nocheck(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;
Expand Down
5 changes: 4 additions & 1 deletion qapi/run-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,15 @@
# @colo: guest is paused to save/restore VM state under colo
# checkpoint, VM can not get into this state unless colo
# capability is enabled for migration. (since 2.8)
#
# @ret: guest stopped to return to the library caller.
# this is only valid if QEMU is compiled as a library (with AS_LIB).
##
{ 'enum': 'RunState',
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
'guest-panicked', 'colo' ] }
'guest-panicked', 'colo', 'ret' ] }

##
# @ShutdownCause:
Expand Down
6 changes: 0 additions & 6 deletions system/cpus.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,19 +802,13 @@ int vm_prepare_start(bool step_pending)
}

//// --- Begin LibAFL code ---

void libafl_exit_signal_vm_start(void);


//// --- End LibAFL code ---

void vm_start(void)
{

//// --- Begin LibAFL code ---

libafl_exit_signal_vm_start();

//// --- End LibAFL code ---

if (!vm_prepare_start(false)) {
Expand Down
43 changes: 38 additions & 5 deletions system/runstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
{ RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
{ RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
{ RUN_STATE_RUNNING, RUN_STATE_COLO},
{ RUN_STATE_RUNNING, RUN_STATE_COLO },
{ RUN_STATE_RUNNING, RUN_STATE_RET },

{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
{ RUN_STATE_SAVE_VM, RUN_STATE_SUSPENDED },
Expand Down Expand Up @@ -183,6 +184,8 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },

{ RUN_STATE_RET, RUN_STATE_RUNNING },

{ RUN_STATE__MAX, RUN_STATE__MAX },
};

Expand Down Expand Up @@ -431,6 +434,12 @@ static NotifierList shutdown_notifiers =
NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);

//// --- Begin LibAFL code ---
#ifdef AS_LIB
static int return_requested;
#endif
//// --- End LibAFL code ---

ShutdownCause qemu_shutdown_requested_get(void)
{
return shutdown_requested;
Expand Down Expand Up @@ -499,6 +508,17 @@ static int qemu_powerdown_requested(void)
return r;
}

//// --- Begin LibAFL code ---
#ifdef AS_LIB
static int qemu_return_requested(void)
{
int r = return_requested;
return_requested = 0;
return r;
}
#endif
//// --- End LibAFL code ---

static int qemu_debug_requested(void)
{
int r = debug_requested;
Expand Down Expand Up @@ -796,6 +816,16 @@ void qemu_register_shutdown_notifier(Notifier *notifier)
notifier_list_add(&shutdown_notifiers, notifier);
}

//// --- Begin LibAFL code ---
#ifdef AS_LIB
void qemu_system_return_request(void)
{
return_requested = 1;
qemu_notify_event();
}
#endif
//// --- End LibAFL code ---

void qemu_system_debug_request(void)
{
debug_requested = 1;
Expand All @@ -807,15 +837,18 @@ static bool main_loop_should_exit(int *status)
RunState r;
ShutdownCause request;

if (qemu_debug_requested()) {
vm_stop(RUN_STATE_DEBUG);

//// --- Begin LibAFL code ---
#ifdef AS_LIB
return true; // exit back to fuzzing harness
if (qemu_return_requested()) {
// exit back to libafl qemu harness
vm_stop(RUN_STATE_RET);
return true;
}
#endif
//// --- End LibAFL code ---

if (qemu_debug_requested()) {
vm_stop(RUN_STATE_DEBUG);
}
if (qemu_suspend_requested()) {
qemu_system_suspend();
Expand Down
Loading