Skip to content

Commit 52e4c5a

Browse files
committed
Add mode of frame.
1 parent 44a49b6 commit 52e4c5a

File tree

5 files changed

+159
-115
lines changed

5 files changed

+159
-115
lines changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,21 @@
33
This QEMU fork implements the TCG plugin to generate execution traces in the
44
[bap-frame](https://github.com/BinaryAnalysisPlatform/bap-frames) format.
55

6+
This plugin does not yet support all targets.
7+
If not listed below it is untested.
8+
9+
Known to work:
10+
11+
- Sparc
12+
- Hexagon
13+
- PPC
14+
15+
Needs fixes:
16+
17+
- ARM (cannot get current mode of VCPU if target can switch between ARM/Thumb).
18+
619
Previous traces were generated with a patched QEMU.
7-
You can find these in the branches tracewrap-6.2.0 for ARM and x86 and tracewrap-8.1 for Hexagon.
20+
You can find these in tracewrap-* branches.
821

922
## Dependencies
1023

contrib/plugins/bap-tracing/frame_buffer.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#include "frame_buffer.h"
55
#include "trace_meta.h"
66

7-
static Frame *frame_new_std(uint64_t addr, int vcpu_id, uint8_t *bytes,
8-
size_t bytes_len) {
7+
static Frame *frame_new_std(uint64_t addr, int vcpu_id, const char *mode_id,
8+
uint8_t *bytes, size_t bytes_len) {
99
Frame *frame = g_new(Frame, 1);
1010
frame__init(frame);
1111

@@ -14,6 +14,9 @@ static Frame *frame_new_std(uint64_t addr, int vcpu_id, uint8_t *bytes,
1414
frame->std_frame = sframe;
1515

1616
sframe->address = addr;
17+
if (mode_id) {
18+
sframe->mode = g_strdup(mode_id);
19+
}
1720
sframe->thread_id = vcpu_id;
1821
sframe->rawbytes.len = bytes_len;
1922
sframe->rawbytes.data = g_malloc(bytes_len);
@@ -190,12 +193,12 @@ uint64_t frame_buffer_flush_to_file(FrameBuffer *buf, WLOCKED FILE *file, bool a
190193
}
191194

192195
bool frame_buffer_new_frame_std(FrameBuffer *buf, unsigned int thread_id,
193-
uint64_t vaddr, uint8_t *bytes,
194-
size_t bytes_len) {
196+
uint64_t vaddr, const char *mode,
197+
uint8_t *bytes, size_t bytes_len) {
195198
if (frame_buffer_is_full(buf)) {
196199
return false;
197200
}
198-
Frame *frame = frame_new_std(vaddr, thread_id, bytes, bytes_len);
201+
Frame *frame = frame_new_std(vaddr, thread_id, mode, bytes, bytes_len);
199202
if (!frame) {
200203
return false;
201204
}

contrib/plugins/bap-tracing/frame_buffer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ void frame_buffer_close_frame(FrameBuffer *buf);
3535
char *frame_buffer_as_str(const FrameBuffer *buf);
3636

3737
bool frame_buffer_new_frame_std(FrameBuffer *buf, unsigned int thread_id,
38-
uint64_t vaddr, uint8_t *bytes,
39-
size_t bytes_len);
38+
uint64_t vaddr, const char *mode_id,
39+
uint8_t *bytes, size_t bytes_len);
4040

4141
bool frame_buffer_append_mem_info(FrameBuffer *fbuf, uint64_t vaddr,
4242
qemu_plugin_mem_value *mval, bool is_store);

contrib/plugins/bap-tracing/tracing.c

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@ static void add_pre_reg_state(VCPU *vcpu, unsigned int vcpu_index,
7676
}
7777
}
7878

79-
static bool add_new_insn_frame(VCPU *vcpu, unsigned int vcpu_index,
80-
FrameBuffer *fbuf, Instruction *insn) {
81-
return frame_buffer_new_frame_std(fbuf, vcpu_index, insn->vaddr, insn->bytes,
82-
insn->size);
83-
}
84-
8579
static GPtrArray *registers_init(void) {
8680
GArray *reg_list = qemu_plugin_get_registers();
8781

@@ -105,7 +99,8 @@ static void write_toc_entry(FrameBuffer *fbuf, bool add_padding) {
10599
g_rw_lock_writer_lock(&state.toc_entries_offsets_lock);
106100
g_rw_lock_writer_lock(&state.total_num_frames_lock);
107101

108-
state.total_num_frames += frame_buffer_flush_to_file(fbuf, state.file, add_padding);
102+
state.total_num_frames +=
103+
frame_buffer_flush_to_file(fbuf, state.file, add_padding);
109104
uint64_t next_toc_entry = ftell(state.file);
110105
g_array_append_val(state.toc_entries_offsets, next_toc_entry);
111106

@@ -135,9 +130,15 @@ static void log_insn_reg_access(unsigned int vcpu_index, void *udata) {
135130

136131
// Open new one.
137132
Instruction *insn = udata;
138-
if (!add_new_insn_frame(vcpu, vcpu_index, fbuf, insn)) {
133+
g_rw_lock_reader_lock(&state.vcpu_mode_lock);
134+
if (!frame_buffer_new_frame_std(
135+
fbuf, vcpu_index, insn->vaddr,
136+
g_ptr_array_index(state.vcpu_modes, vcpu_index), insn->bytes,
137+
insn->size)) {
139138
err(1, "Failed to add new frame.\n");
140139
}
140+
g_rw_lock_reader_unlock(&state.vcpu_mode_lock);
141+
141142
add_pre_reg_state(vcpu, vcpu_index, current_regs, fbuf);
142143

143144
g_rw_lock_writer_unlock(&state.frame_buffer_lock);
@@ -161,6 +162,7 @@ Register *init_vcpu_register(qemu_plugin_reg_descriptor *desc) {
161162
static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) {
162163
g_rw_lock_writer_lock(&state.vcpus_array_lock);
163164
g_rw_lock_writer_lock(&state.frame_buffer_lock);
165+
g_rw_lock_writer_lock(&state.vcpu_mode_lock);
164166

165167
VCPU *vcpu = g_malloc0(sizeof(VCPU));
166168
vcpu->registers = registers_init();
@@ -170,6 +172,22 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) {
170172
FrameBuffer *vcpu_frame_buffer = frame_buffer_new();
171173
g_ptr_array_insert(state.frame_buffer, vcpu_index, vcpu_frame_buffer);
172174

175+
uint64_t frame_arch = 0;
176+
uint64_t frame_mach = 0;
177+
if (!get_frame_arch_mach(state.target_name, &frame_arch, &frame_mach)) {
178+
qemu_plugin_outs("Failed to get arch/mach.\n");
179+
}
180+
const char *mode = FRAME_MODE_NONE;
181+
if (frame_arch == frame_arch_powerpc && frame_mach == frame_mach_ppc64) {
182+
mode = FRAME_MODE_PPC64;
183+
} else if (frame_arch == frame_arch_powerpc && frame_mach == frame_mach_ppc) {
184+
mode = FRAME_MODE_PPC32;
185+
}
186+
// TODO: handle ARM
187+
g_ptr_array_insert(state.vcpu_modes, vcpu_index,
188+
mode ? g_strdup(mode) : NULL);
189+
190+
g_rw_lock_writer_unlock(&state.vcpu_mode_lock);
173191
g_rw_lock_writer_unlock(&state.frame_buffer_lock);
174192
g_rw_lock_writer_unlock(&state.vcpus_array_lock);
175193
}
@@ -238,21 +256,6 @@ static void plugin_exit(qemu_plugin_id_t id, void *udata) {
238256
qemu_plugin_outs("Finished trace\n");
239257
}
240258

241-
static bool get_frame_arch_mach(const char *target_name, uint64_t *arch,
242-
uint64_t *mach) {
243-
*mach = 0;
244-
*arch = frame_arch_last;
245-
const char *aname = arch_map[0].name;
246-
for (size_t i = 0; arch_map[i].name; ++i) {
247-
aname = arch_map[i].name;
248-
if (!strncmp(aname, target_name, strlen(aname))) {
249-
*arch = arch_map[i].val;
250-
break;
251-
}
252-
}
253-
return *arch != frame_arch_last;
254-
}
255-
256259
static bool write_header(FILE *file, const char *target_name) {
257260
uint64_t frame_arch = 0;
258261
uint64_t frame_mach = 0;
@@ -285,9 +288,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
285288
exit(1);
286289
}
287290

291+
state.target_name = g_strdup(info->target_name);
288292
state.frame_buffer = g_ptr_array_new();
289293
state.toc_entries_offsets = g_array_new(false, true, sizeof(uint64_t));
290294
state.vcpus = g_ptr_array_new();
295+
state.vcpu_modes = g_ptr_array_new();
291296
state.file = fopen(output, "wb");
292297
if (!(state.frame_buffer || state.vcpus || state.file ||
293298
!state.toc_entries_offsets)) {

contrib/plugins/bap-tracing/tracing.h

Lines changed: 107 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -15,95 +15,113 @@
1515

1616
struct arch_enum_entry {
1717
const char *name;
18-
enum frame_architecture val;
18+
enum frame_architecture arch;
19+
size_t machine;
1920
};
2021

2122
static struct arch_enum_entry arch_map[] = {
22-
{.name = "unknown", .val = frame_arch_unknown},
23-
{.name = "obscure", .val = frame_arch_obscure},
24-
{.name = "m68k", .val = frame_arch_m68k},
25-
{.name = "vax", .val = frame_arch_vax},
26-
{.name = "i960", .val = frame_arch_i960},
27-
{.name = "or32", .val = frame_arch_or32},
28-
{.name = "sparc", .val = frame_arch_sparc},
29-
{.name = "spu", .val = frame_arch_spu},
30-
{.name = "mips", .val = frame_arch_mips},
31-
{.name = "i386", .val = frame_arch_i386},
32-
{.name = "l1om", .val = frame_arch_l1om},
33-
{.name = "we32k", .val = frame_arch_we32k},
34-
{.name = "tahoe", .val = frame_arch_tahoe},
35-
{.name = "i860", .val = frame_arch_i860},
36-
{.name = "i370", .val = frame_arch_i370},
37-
{.name = "romp", .val = frame_arch_romp},
38-
{.name = "convex", .val = frame_arch_convex},
39-
{.name = "m88k", .val = frame_arch_m88k},
40-
{.name = "m98k", .val = frame_arch_m98k},
41-
{.name = "pyramid", .val = frame_arch_pyramid},
42-
{.name = "h8300", .val = frame_arch_h8300},
43-
{.name = "pdp11", .val = frame_arch_pdp11},
44-
{.name = "plugin", .val = frame_arch_plugin},
45-
{.name = "powerpc", .val = frame_arch_powerpc},
46-
{.name = "rs6000", .val = frame_arch_rs6000},
47-
{.name = "hppa", .val = frame_arch_hppa},
48-
{.name = "d10v", .val = frame_arch_d10v},
49-
{.name = "d30v", .val = frame_arch_d30v},
50-
{.name = "dlx", .val = frame_arch_dlx},
51-
{.name = "m68hc11", .val = frame_arch_m68hc11},
52-
{.name = "m68hc12", .val = frame_arch_m68hc12},
53-
{.name = "z8k", .val = frame_arch_z8k},
54-
{.name = "h8500", .val = frame_arch_h8500},
55-
{.name = "sh", .val = frame_arch_sh},
56-
{.name = "alpha", .val = frame_arch_alpha},
57-
{.name = "arm", .val = frame_arch_arm},
58-
{.name = "ns32k", .val = frame_arch_ns32k},
59-
{.name = "w65", .val = frame_arch_w65},
60-
{.name = "tic30", .val = frame_arch_tic30},
61-
{.name = "tic4x", .val = frame_arch_tic4x},
62-
{.name = "tic54x", .val = frame_arch_tic54x},
63-
{.name = "tic6x", .val = frame_arch_tic6x},
64-
{.name = "tic80", .val = frame_arch_tic80},
65-
{.name = "v850", .val = frame_arch_v850},
66-
{.name = "arc", .val = frame_arch_arc},
67-
{.name = "m32c", .val = frame_arch_m32c},
68-
{.name = "m32r", .val = frame_arch_m32r},
69-
{.name = "mn10200", .val = frame_arch_mn10200},
70-
{.name = "mn10300", .val = frame_arch_mn10300},
71-
{.name = "fr30", .val = frame_arch_fr30},
72-
{.name = "frv", .val = frame_arch_frv},
73-
{.name = "moxie", .val = frame_arch_moxie},
74-
{.name = "mcore", .val = frame_arch_mcore},
75-
{.name = "mep", .val = frame_arch_mep},
76-
{.name = "ia64", .val = frame_arch_ia64},
77-
{.name = "ip2k", .val = frame_arch_ip2k},
78-
{.name = "iq2000", .val = frame_arch_iq2000},
79-
{.name = "mt", .val = frame_arch_mt},
80-
{.name = "pj", .val = frame_arch_pj},
81-
{.name = "avr", .val = frame_arch_avr},
82-
{.name = "bfin", .val = frame_arch_bfin},
83-
{.name = "cr16", .val = frame_arch_cr16},
84-
{.name = "cr16c", .val = frame_arch_cr16c},
85-
{.name = "crx", .val = frame_arch_crx},
86-
{.name = "cris", .val = frame_arch_cris},
87-
{.name = "rx", .val = frame_arch_rx},
88-
{.name = "s390", .val = frame_arch_s390},
89-
{.name = "score", .val = frame_arch_score},
90-
{.name = "openrisc", .val = frame_arch_openrisc},
91-
{.name = "mmix", .val = frame_arch_mmix},
92-
{.name = "xstormy16", .val = frame_arch_xstormy16},
93-
{.name = "msp430", .val = frame_arch_msp430},
94-
{.name = "xc16x", .val = frame_arch_xc16x},
95-
{.name = "xtensa", .val = frame_arch_xtensa},
96-
{.name = "z80", .val = frame_arch_z80},
97-
{.name = "lm32", .val = frame_arch_lm32},
98-
{.name = "microblaze", .val = frame_arch_microblaze},
99-
{.name = "6502", .val = frame_arch_6502},
100-
{.name = "aarch64", .val = frame_arch_aarch64},
101-
{.name = "8051", .val = frame_arch_8051},
102-
{.name = "sm83", .val = frame_arch_sm83},
103-
{.name = "hexagon", .val = frame_arch_hexagon},
104-
{.name = NULL, .val = frame_arch_last},
23+
{.name = "unknown", .arch = frame_arch_unknown, .machine = 0},
24+
{.name = "obscure", .arch = frame_arch_obscure, .machine = 0},
25+
{.name = "m68k", .arch = frame_arch_m68k, .machine = 0},
26+
{.name = "vax", .arch = frame_arch_vax, .machine = 0},
27+
{.name = "i960", .arch = frame_arch_i960, .machine = 0},
28+
{.name = "or32", .arch = frame_arch_or32, .machine = 0},
29+
{.name = "sparc", .arch = frame_arch_sparc, .machine = 0},
30+
{.name = "spu", .arch = frame_arch_spu, .machine = 0},
31+
{.name = "mips", .arch = frame_arch_mips, .machine = 0},
32+
{.name = "i386", .arch = frame_arch_i386, .machine = 0},
33+
{.name = "l1om", .arch = frame_arch_l1om, .machine = 0},
34+
{.name = "we32k", .arch = frame_arch_we32k, .machine = 0},
35+
{.name = "tahoe", .arch = frame_arch_tahoe, .machine = 0},
36+
{.name = "i860", .arch = frame_arch_i860, .machine = 0},
37+
{.name = "i370", .arch = frame_arch_i370, .machine = 0},
38+
{.name = "romp", .arch = frame_arch_romp, .machine = 0},
39+
{.name = "convex", .arch = frame_arch_convex, .machine = 0},
40+
{.name = "m88k", .arch = frame_arch_m88k, .machine = 0},
41+
{.name = "m98k", .arch = frame_arch_m98k, .machine = 0},
42+
{.name = "pyramid", .arch = frame_arch_pyramid, .machine = 0},
43+
{.name = "h8300", .arch = frame_arch_h8300, .machine = 0},
44+
{.name = "pdp11", .arch = frame_arch_pdp11, .machine = 0},
45+
{.name = "plugin", .arch = frame_arch_plugin, .machine = 0},
46+
{.name = "ppc", .arch = frame_arch_powerpc, .machine = frame_mach_ppc},
47+
{.name = "ppc64", .arch = frame_arch_powerpc, .machine = frame_mach_ppc64},
48+
{.name = "rs6000", .arch = frame_arch_rs6000, .machine = 0},
49+
{.name = "hppa", .arch = frame_arch_hppa, .machine = 0},
50+
{.name = "d10v", .arch = frame_arch_d10v, .machine = 0},
51+
{.name = "d30v", .arch = frame_arch_d30v, .machine = 0},
52+
{.name = "dlx", .arch = frame_arch_dlx, .machine = 0},
53+
{.name = "m68hc11", .arch = frame_arch_m68hc11, .machine = 0},
54+
{.name = "m68hc12", .arch = frame_arch_m68hc12, .machine = 0},
55+
{.name = "z8k", .arch = frame_arch_z8k, .machine = 0},
56+
{.name = "h8500", .arch = frame_arch_h8500, .machine = 0},
57+
{.name = "sh", .arch = frame_arch_sh, .machine = 0},
58+
{.name = "alpha", .arch = frame_arch_alpha, .machine = 0},
59+
{.name = "arm", .arch = frame_arch_arm, .machine = 0},
60+
{.name = "ns32k", .arch = frame_arch_ns32k, .machine = 0},
61+
{.name = "w65", .arch = frame_arch_w65, .machine = 0},
62+
{.name = "tic30", .arch = frame_arch_tic30, .machine = 0},
63+
{.name = "tic4x", .arch = frame_arch_tic4x, .machine = 0},
64+
{.name = "tic54x", .arch = frame_arch_tic54x, .machine = 0},
65+
{.name = "tic6x", .arch = frame_arch_tic6x, .machine = 0},
66+
{.name = "tic80", .arch = frame_arch_tic80, .machine = 0},
67+
{.name = "v850", .arch = frame_arch_v850, .machine = 0},
68+
{.name = "arc", .arch = frame_arch_arc, .machine = 0},
69+
{.name = "m32c", .arch = frame_arch_m32c, .machine = 0},
70+
{.name = "m32r", .arch = frame_arch_m32r, .machine = 0},
71+
{.name = "mn10200", .arch = frame_arch_mn10200, .machine = 0},
72+
{.name = "mn10300", .arch = frame_arch_mn10300, .machine = 0},
73+
{.name = "fr30", .arch = frame_arch_fr30, .machine = 0},
74+
{.name = "frv", .arch = frame_arch_frv, .machine = 0},
75+
{.name = "moxie", .arch = frame_arch_moxie, .machine = 0},
76+
{.name = "mcore", .arch = frame_arch_mcore, .machine = 0},
77+
{.name = "mep", .arch = frame_arch_mep, .machine = 0},
78+
{.name = "ia64", .arch = frame_arch_ia64, .machine = 0},
79+
{.name = "ip2k", .arch = frame_arch_ip2k, .machine = 0},
80+
{.name = "iq2000", .arch = frame_arch_iq2000, .machine = 0},
81+
{.name = "mt", .arch = frame_arch_mt, .machine = 0},
82+
{.name = "pj", .arch = frame_arch_pj, .machine = 0},
83+
{.name = "avr", .arch = frame_arch_avr, .machine = 0},
84+
{.name = "bfin", .arch = frame_arch_bfin, .machine = 0},
85+
{.name = "cr16", .arch = frame_arch_cr16, .machine = 0},
86+
{.name = "cr16c", .arch = frame_arch_cr16c, .machine = 0},
87+
{.name = "crx", .arch = frame_arch_crx, .machine = 0},
88+
{.name = "cris", .arch = frame_arch_cris, .machine = 0},
89+
{.name = "rx", .arch = frame_arch_rx, .machine = 0},
90+
{.name = "s390", .arch = frame_arch_s390, .machine = 0},
91+
{.name = "score", .arch = frame_arch_score, .machine = 0},
92+
{.name = "openrisc", .arch = frame_arch_openrisc, .machine = 0},
93+
{.name = "mmix", .arch = frame_arch_mmix, .machine = 0},
94+
{.name = "xstormy16", .arch = frame_arch_xstormy16, .machine = 0},
95+
{.name = "msp430", .arch = frame_arch_msp430, .machine = 0},
96+
{.name = "xc16x", .arch = frame_arch_xc16x, .machine = 0},
97+
{.name = "xtensa", .arch = frame_arch_xtensa, .machine = 0},
98+
{.name = "z80", .arch = frame_arch_z80, .machine = 0},
99+
{.name = "lm32", .arch = frame_arch_lm32, .machine = 0},
100+
{.name = "microblaze", .arch = frame_arch_microblaze, .machine = 0},
101+
{.name = "6502", .arch = frame_arch_6502, .machine = 0},
102+
{.name = "aarch64", .arch = frame_arch_aarch64, .machine = 0},
103+
{.name = "8051", .arch = frame_arch_8051, .machine = 0},
104+
{.name = "sm83", .arch = frame_arch_sm83, .machine = 0},
105+
{.name = "hexagon", .arch = frame_arch_hexagon, .machine = 0},
106+
{.name = NULL, .arch = frame_arch_last, .machine = 0},
105107
};
106108

109+
static inline bool get_frame_arch_mach(const char *target_name, uint64_t *arch,
110+
uint64_t *mach) {
111+
*mach = 0;
112+
*arch = frame_arch_last;
113+
const char *aname = arch_map[0].name;
114+
for (size_t i = 0; arch_map[i].name; ++i) {
115+
aname = arch_map[i].name;
116+
if (!strncmp(aname, target_name, strlen(aname))) {
117+
*arch = arch_map[i].arch;
118+
*mach = arch_map[i].machine;
119+
break;
120+
}
121+
}
122+
return *arch != frame_arch_last;
123+
}
124+
107125
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
108126

109127
/**
@@ -142,6 +160,11 @@ typedef struct {
142160

143161
GRWLock file_lock;
144162
FILE *file;
163+
164+
GRWLock vcpu_mode_lock;
165+
GPtrArray /*<const char *>*/ *vcpu_modes; ///< Indexed by vcpu id.
166+
167+
const char *target_name;
145168
} TraceState;
146169

147170
VCPU *vcpu_new(void);

0 commit comments

Comments
 (0)