From 662be20af2628aa99044c795d4730bf2e1ff9cbf Mon Sep 17 00:00:00 2001 From: Manuel Egele Date: Fri, 19 Sep 2014 19:58:45 -0400 Subject: [PATCH 1/2] Clean up some loose ends Close frame after CC evaluation By closing the frame at the "correct"? position (i.e., after the conditional code evaluation), we should now be able to collect traces without specifying -singlestep explicitly. If frame remains open, print address of instruction that originally opened the frame. This makes it easier to debug problems with open frames as the correct (i.e., responsible) instruction is printed. Implement tracing also for arm-softmmu Back out tracewrap into the common area so it gets built with user-mode and system mode targets Add command line option for -tracefile Don't break build w/o --with-tracewrap gcc complains about unused variable tracefile if it's not enclosed in #ifdef/#endif The -tracefile option exists regardless of the --with-tracewrap configure option, this still needs to be addressed/fixed. --- Makefile.target | 2 ++ include/gtracewrap.h | 3 +++ include/tracewrap.h | 2 +- linux-user/Makefile.objs | 1 - qemu-options.hx | 10 ++++++++++ {linux-user => target-arm}/trace_consts.h | 0 target-arm/trace_helper.c | 2 +- {linux-user/arm => target-arm}/trace_info.h | 0 target-arm/translate.c | 7 ++++--- linux-user/tracewrap.c => tracewrap.c | 12 ++++++++---- vl.c | 17 +++++++++++++++++ 11 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 include/gtracewrap.h rename {linux-user => target-arm}/trace_consts.h (100%) rename {linux-user/arm => target-arm}/trace_info.h (100%) rename linux-user/tracewrap.c => tracewrap.c (94%) diff --git a/Makefile.target b/Makefile.target index ba1234063..71b5ff5a0 100644 --- a/Makefile.target +++ b/Makefile.target @@ -155,6 +155,8 @@ dummy := $(call unnest-vars,.., \ # Now restore obj-y obj-y := $(obj-y-save) +common-obj-$(HAS_TRACEWRAP) += tracewrap.o + all-obj-y = $(obj-y) $(common-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) diff --git a/include/gtracewrap.h b/include/gtracewrap.h new file mode 100644 index 000000000..ffdc3165d --- /dev/null +++ b/include/gtracewrap.h @@ -0,0 +1,3 @@ +#pragma once + +void do_qemu_set_trace(const char *tracefilename); diff --git a/include/tracewrap.h b/include/tracewrap.h index 1116f6d78..0fdd60fbf 100644 --- a/include/tracewrap.h +++ b/include/tracewrap.h @@ -4,6 +4,7 @@ #include #include #include "cpu.h" +#include "gtracewrap.h" #include "frame.piqi.pb-c.h" @@ -13,7 +14,6 @@ struct toc_entry { }; extern FILE *qemu_tracefile; -void do_qemu_set_trace(const char *tracefilename); void qemu_trace(Frame frame); void qemu_trace_newframe(uint64_t addr, int tread_id); void qemu_trace_add_operand(OperandInfo *oi, int inout); diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 0c6355ba9..5899d72d3 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -5,4 +5,3 @@ obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o obj-$(TARGET_ARM) += arm/nwfpe/ obj-$(TARGET_M68K) += m68k-sim.o -obj-$(HAS_TRACEWRAP) += tracewrap.o diff --git a/qemu-options.hx b/qemu-options.hx index 2d33815fb..c264ed319 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2573,6 +2573,16 @@ STEXI Like -monitor but opens in 'control' mode. ETEXI +DEF("tracefile", HAS_ARG, QEMU_OPTION_tracefile, \ + "-tracefile file write BAP traces to file\n", + QEMU_ARCH_ARM) +STEXI +@item -tracefile @var{file} +@findex -tracefile +Write BAP traces into file @var{file}. +Default: /dev/shm/proto +ETEXI + DEF("mon", HAS_ARG, QEMU_OPTION_mon, \ "-mon [chardev=]name[,mode=readline|control][,default]\n", QEMU_ARCH_ALL) STEXI diff --git a/linux-user/trace_consts.h b/target-arm/trace_consts.h similarity index 100% rename from linux-user/trace_consts.h rename to target-arm/trace_consts.h diff --git a/target-arm/trace_helper.c b/target-arm/trace_helper.c index 023a56165..f3534cede 100644 --- a/target-arm/trace_helper.c +++ b/target-arm/trace_helper.c @@ -60,7 +60,7 @@ OperandInfo * load_store_mem(uint32_t addr, uint32_t val, int ls, int len) } OperandInfo *oi = (OperandInfo *)malloc(sizeof(OperandInfo)); operand_info__init(oi); - oi->bit_length = 0; + oi->bit_length = len * 8; oi->operand_info_specific = ois; oi->operand_usage = ou; oi->value.len = len; diff --git a/linux-user/arm/trace_info.h b/target-arm/trace_info.h similarity index 100% rename from linux-user/arm/trace_info.h rename to target-arm/trace_info.h diff --git a/target-arm/translate.c b/target-arm/translate.c index 41601880b..1f78a96bd 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -10910,15 +10910,16 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, } else { disas_arm_insn(env, dc); } -#ifdef HAS_TRACEWRAP - gen_trace_endframe(dc); -#endif //HAS_TRACEWRAP if (dc->condjmp && !dc->is_jmp) { gen_set_label(dc->condlabel); dc->condjmp = 0; } +#ifdef HAS_TRACEWRAP + gen_trace_endframe(dc); +#endif //HAS_TRACEWRAP + if (tcg_check_temp_count()) { fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc); diff --git a/linux-user/tracewrap.c b/tracewrap.c similarity index 94% rename from linux-user/tracewrap.c rename to tracewrap.c index 02c3ea811..44b0740c4 100644 --- a/linux-user/tracewrap.c +++ b/tracewrap.c @@ -1,6 +1,5 @@ #include "tracewrap.h" #include "trace_consts.h" -#include Frame * g_frame; struct toc_entry *toc; @@ -13,6 +12,9 @@ FILE *qemu_tracefile; void do_qemu_set_trace(const char *tracefilename) { + if (tracefilename == NULL) { + tracefilename = "/dev/shm/proto"; + } printf("Setting qemu_tracefile at %s\n", tracefilename); qemu_tracefile = fopen(tracefilename, "wb"); if (qemu_tracefile == NULL) { @@ -28,7 +30,8 @@ void qemu_trace_newframe(uint64_t addr, int thread_id) { if (open_frame) { - fprintf(stderr, "frame still open! 0x%08lx\n", (long unsigned int)addr); + fprintf(stderr, "frame still open! 0x%08lx\n", + (long unsigned int)g_frame->std_frame->address); qemu_trace_endframe(NULL, 0, 0); } open_frame = 1; @@ -112,8 +115,9 @@ void qemu_trace_endframe(CPUArchState *env, target_ulong pc, size_t size) StdFrame *sframe = g_frame->std_frame; sframe->rawbytes.len = size; sframe->rawbytes.data = (uint8_t *)malloc(size); - for (i = 0; i < size; i++) - sframe->rawbytes.data[i] = cpu_ldub_code(env, pc+i); + for (i = 0; i < size; i++) { + sframe->rawbytes.data[i] = cpu_ldub_code(env, pc+i); + } size_t msg_size = frame__get_packed_size(g_frame); uint8_t *packed_buffer = (uint8_t *)malloc(msg_size); diff --git a/vl.c b/vl.c index 9975e5a4e..86402a86b 100644 --- a/vl.c +++ b/vl.c @@ -30,6 +30,10 @@ #include "config-host.h" +#ifdef HAS_TRACEWRAP +#include "gtracewrap.h" +#endif + #ifdef CONFIG_SECCOMP #include "sysemu/seccomp.h" #endif @@ -2957,6 +2961,9 @@ int main(int argc, char **argv, char **envp) bool userconfig = true; const char *log_mask = NULL; const char *log_file = NULL; +#ifdef HAS_TRACEWRAP + const char *tracefile = NULL; +#endif GMemVTable mem_trace = { .malloc = malloc_and_trace, .realloc = realloc_and_trace, @@ -3412,6 +3419,11 @@ int main(int argc, char **argv, char **envp) monitor_parse(optarg, "readline"); } break; +#ifdef HAS_TRACEWRAP + case QEMU_OPTION_tracefile: + tracefile = optarg; + break; +#endif case QEMU_OPTION_qmp: monitor_parse(optarg, "control"); default_monitor = 0; @@ -3907,6 +3919,11 @@ int main(int argc, char **argv, char **envp) } } } + +#ifdef HAS_TRACEWRAP + do_qemu_set_trace(tracefile); +#endif + loc_set_none(); if (qemu_init_main_loop()) { From dd87d0b66b30961ee4d7bba97f95864795617c64 Mon Sep 17 00:00:00 2001 From: Manuel Egele Date: Sun, 1 Mar 2015 22:08:05 -0500 Subject: [PATCH 2/2] convert traces into other formats (e.g., pkl, or txt) for ida python plugin --- python/printProto.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/python/printProto.py b/python/printProto.py index df37d5b00..657827f04 100755 --- a/python/printProto.py +++ b/python/printProto.py @@ -5,6 +5,13 @@ import getopt import sys import IPython +import pickle +from collections import defaultdict +import google + +FMT_TXT=0x1 +FMT_PKL_HIGHLIGHT=0x2 +FMT_UNIQ_INSNS=0x3 def getFrameLength(f): return struct.unpack("Q", f.read(8))[0] @@ -55,7 +62,7 @@ def printFrame(f): print "PRE: %s" % printOperandList(f.std_frame.operand_pre_list.elem) print "POST: %s" % printOperandList(f.std_frame.operand_post_list.elem) -def process(infileName, outfileName=None, maxCnt=0): +def process(infileName, outfileName=None, maxCnt=0, outFormat=FMT_TXT): out = sys.stdout if outfileName: out = open(outfileName, 'w') @@ -70,15 +77,24 @@ def process(infileName, outfileName=None, maxCnt=0): print "maxCnt: %i" % maxCnt + insns = defaultdict(lambda : 0) while (cnt <= maxCnt): cnt += 1 try: fr = getFrame(infile) + insns[fr.std_frame.address]+=1 except google.protobuf.message.DecodeError, e: print "maxCnt: %i, cnt: %i\n" % (maxCnt, cnt) print e break - out.write("0x%x, %r\n" % (fr.std_frame.address, fr.std_frame.rawbytes)) + if outFormat == FMT_TXT: + out.write("0x%x, %r\n" % (fr.std_frame.address, fr.std_frame.rawbytes)) + + if outFormat == FMT_PKL_HIGHLIGHT: + highlight_data = {1:set(insns.keys())} + pickle.dump(highlight_data, out) + elif outFormat == FMT_UNIQ_INSNS: + out.write("\n".join(["0x%x" % i for i in set(insns.keys())])) def getMetaData(f): f.seek(0x20) @@ -91,7 +107,8 @@ def main(): maxCnt = 0 infile = None outfile = None - opts,argv = getopt.getopt(sys.argv[1:], "f:c:o:d") + outFormat = FMT_TXT + opts,argv = getopt.getopt(sys.argv[1:], "f:c:o:F:d") for k,v in opts: if k == '-d': debug += 1 @@ -101,9 +118,14 @@ def main(): outfile = v if k == '-c': maxCnt = int(v) + if k == '-F': + if v == 'pkl': + outFormat = FMT_PKL_HIGHLIGHT + elif v == 'uniq': + outFormat = FMT_UNIQ_INSNS if infile: - process(infile, outfile, maxCnt) + process(infile, outfile, maxCnt, outFormat) if __name__ == "__main__": main()