So a task proposed by @a1ex was to make qemu export function calls directly in r2 format.
Here is what I came up with. To be honest I just poked the code and it magically worked right away. (I'm still trying to shut my mouth on the techniques used in qemu_log.c to produce the input parameter including command line doc )
Here's what I did. In log.h add a line (around line 85):
#define EOS_LOG_R2 (1LL << 59) /* export unique calls to radare2 */
in qemu_log.c below EOS_LOG_IDC:
{ EOS_LOG_R2 | EOS_LOG_CALLSTACK | CPU_LOG_TB_NOCHAIN, "r2",
"EOS: export called functions to radare2 (implies callstack,nochain,singlestep)" },
and finally in logging.c
static FILE * r2 = NULL;
/* QEMU is usually closed with CTRL-C, so call this when finished */
static void close_r2(void)
{
fprintf(r2, "\n");
fclose(r2);
fprintf(stderr, "%s saved.\n", idc_path);
}
static void eos_r2_log_call(EOSState *s, CPUState *cpu, CPUARMState *env,
TranslationBlock *tb, uint32_t prev_pc, uint32_t prev_lr, uint32_t prev_size)
{
static int stderr_dup = 0;
if (!r2)
{
snprintf(idc_path, sizeof(idc_path), "%s.r2", MACHINE_GET_CLASS(current_machine)->name);
fprintf(stderr, "Exporting called functions to %s.\n", idc_path);
r2 = fopen(idc_path, "w");
assert(r2);
atexit(close_r2);
fprintf(r2, "# List of functions called during execution. */");
fprintf(r2, "# Generated from QEMU. \n\n");
stderr_dup = dup(fileno(stderr));
}
/* bit array for every possible PC & ~3 */
static uint32_t saved_pcs[(1 << 30) / 32] = {0};
uint32_t pc = env->regs[15];
uint32_t lr = env->regs[14];
uint32_t sp = env->regs[13];
/* log each called function to IDC, only once */
int pca = pc >> 2;
if (!(saved_pcs[pca/32] & (1 << (pca%32))))
{
saved_pcs[pca/32] |= (1 << pca%32);
/* log_target_disas writes to stderr; redirect it to our output file */
/* todo: any other threads that might output to stderr? */
assert(stderr_dup);
fflush(stderr); fflush(r2);
dup2(fileno(r2), fileno(stderr));
fprintf(stderr, " /* from "); log_target_disas(cpu, prev_pc, prev_size, 0);
fprintf(stderr, " * -> "); log_target_disas(cpu, tb->pc, tb->size, 0);
char * task_name = eos_get_current_task_name(s);
fprintf(stderr, " * %s%sPC:%x->%x LR:%x->%x SP:%x */\n",
task_name ? task_name : "", task_name ? " " : "",
prev_pc, pc, prev_lr, lr, sp
);
fprintf(stderr, " s 0x%X \n", pc);
env->thumb == 1? fprintf(stderr, " afB 16\n af @ 0x%X\n", pc):fprintf(stderr, " af @ 0x%X\n", pc);
//TODO find solution for name printf("afn 0x%08X %s\n",ea,name);
fprintf(stderr, "\n");
dup2(stderr_dup, fileno(stderr));
}
}
Maybe I find some time and integrate the function with the original idc function and don't duplicate code.
And then use the script from a1ex to create the "afn" commands.