2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
20 #define DEFAULT_REPORT_INTERVAL 1000
27 static const char* func
;
29 const struct options_t opt
[] =
31 { "--out=s", .s
=&tracing
, .ds
=0, .h
="Create trace file/fifo =name" },
32 { "--trace=s", .s
=&tracing
, .ds
=0, .h
="synonym for --out" },
33 { "--buffer=i", .i
=&bufsize
, .di
=12, .h
="Shared memory buffer size is 2^ =n bytes" },
34 { "--func=s", .s
=&func
, .ds
="_start", .h
="Trace function =name" },
35 { "--withregs", .b
=&core
.params
.flags
, .bv
=tr_has_reg
, .h
="Include register values in trace" },
36 { "--after=i", .i
=&core
.params
.after
, .di
=1, .h
="Start tracing function after =number calls" },
37 { "--every=i", .i
=&core
.params
.every
, .di
=1, .h
="Trace only every =number times function is called" },
38 { "--skip=i", .i
=&core
.params
.skip
, .di
=1, .h
="Trace function once every =number times called" },
39 { "--report=i", .i
=&core
.params
.report
, .di
=1000, .h
="Progress report every =number million instructions" },
40 { "--quiet", .b
=&core
.params
.quiet
, .bv
=1, .h
="Don't report progress to stderr" },
41 { "-q", .b
=&core
.params
.quiet
, .bv
=1, .h
="short for --quiet" },
44 const char* usage
= "caveat [caveat-options] target-program [target-options]";
46 int main(int argc
, const char* argv
[], const char* envp
[])
48 struct timeval start_timeval
;
49 gettimeofday(&start_timeval
, 0);
50 init_core(&core
, clock(), &start_timeval
);
52 int numopts
= parse_options(argv
+1);
53 if (argc
== numopts
+1)
55 core
.params
.report
*= 1000000; /* unit is millions of instructions */
56 Addr_t entry_pc
= load_elf_binary(argv
[1+numopts
], 1);
58 Addr_t stack_top
= initialize_stack(argc
-1-numopts
, argv
+1+numopts
, envp
);
60 core
.reg
[SP
].a
= stack_top
;
64 if (! find_symbol(func
, &core
.params
.breakpoint
, 0)) {
65 fprintf(stderr
, "function %s cannot be found in symbol table\n", func
);
68 fprintf(stderr
, "Tracing %s at 0x%lx\n", func
, core
.params
.breakpoint
);
69 core
.params
.flags
|= tr_has_pc
| tr_has_mem
;
70 core
.tb
= fifo_create(tracing
, bufsize
);
73 core
.params
.breakpoint
= 0;
74 int rc
= run_program(&core
);
76 fifo_put(core
.tb
, trM(tr_eof
, 0));
85 jmp_buf return_to_top_level
;
87 void signal_handler(int nSIGnum
, siginfo_t
* si
, void* vcontext
)
89 // ucontext_t* context = (ucontext_t*)vcontext;
90 // context->uc_mcontext.gregs[]
91 fprintf(stderr
, "\n\nSegV %p\n", si
->si_addr
);
92 longjmp(return_to_top_level
, 1);
95 int run_program(struct core_t
* cpu
)
97 struct sigaction action
;
98 memset(&action
, 0, sizeof(struct sigaction
));
99 sigemptyset(&action
.sa_mask
);
100 sigemptyset(&action
.sa_mask
);
101 // action.sa_flags = SA_SIGINFO;
102 action
.sa_sigaction
= signal_handler
;
105 sigaction(SIGSEGV
, &action
, NULL
);
106 if (setjmp(return_to_top_level
) != 0) {
107 //fprintf(stderr, "Back to main\n");
108 print_insn(cpu
->pc
, stderr
);
109 print_registers(cpu
->reg
, stderr
);
112 return outer_loop(&core
);