Skip to content

Commit abf6040

Browse files
committed
Re-add tracewrap code from tracewrap-8.1-hexagon
1 parent dbafb0c commit abf6040

File tree

3 files changed

+438
-0
lines changed

3 files changed

+438
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include "trace_info.h"
4+
5+
const uint64_t magic_number = 7456879624156307493LL;
6+
const uint64_t magic_number_offset = 0LL;
7+
const uint64_t trace_version_offset = 8LL;
8+
const uint64_t bfd_arch_offset = 16LL;
9+
const uint64_t bfd_machine_offset = 24LL;
10+
const uint64_t num_trace_frames_offset = 32LL;
11+
const uint64_t toc_offset_offset = 40LL;
12+
const uint64_t first_frame_offset = 48LL;
13+
const uint64_t out_trace_version = 2LL;
Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
#include "tracewrap.h"
2+
#include "trace_consts.h"
3+
#include "exec/cpu_ldst.h"
4+
5+
#include <glib.h>
6+
#include <err.h>
7+
#include "qemu/log.h"
8+
9+
#include <sys/types.h>
10+
#include <unistd.h>
11+
#include <sys/stat.h>
12+
13+
#include <limits.h>
14+
#include <stdlib.h>
15+
16+
17+
char tracer_name[] = "qemu";
18+
char tracer_version[] = "2.0.0/tracewrap";
19+
20+
static Frame * g_frame;
21+
static uint64_t frames_per_toc_entry = 64LL;
22+
static uint32_t open_frame = 0;
23+
static FILE *file = NULL;
24+
25+
/* don't use the following data directly!
26+
use toc_init, toc_update and toc_write functions instead */
27+
static uint64_t *toc = NULL;
28+
static int toc_entries = 0;
29+
static int toc_capacity = 0;
30+
static uint64_t toc_num_frames = 0;
31+
32+
#define MD5LEN 16
33+
static guchar target_md5[MD5LEN];
34+
static char target_path[PATH_MAX] = "unknown";
35+
36+
37+
#define WRITE(x) do { \
38+
if (!file) \
39+
err(1, "qemu_trace is not initialized"); \
40+
if (fwrite(&(x), sizeof(x),1,file) != 1) \
41+
err(1, "fwrite failed"); \
42+
} while(0)
43+
44+
#define WRITE_BUF(x,n) do { \
45+
if (!file) \
46+
err(1, "qemu_trace is not initialized"); \
47+
if (fwrite((x),1,(n),file) != n) \
48+
err(1, "fwrite failed"); \
49+
} while(0)
50+
51+
#define SEEK(off) do { \
52+
if (fseek(file,(off), SEEK_SET) < 0) \
53+
err(1, "stream not seekable"); \
54+
} while(0)
55+
56+
57+
static void toc_init(void) {
58+
if (toc_entries != 0)
59+
err(1, "qemu_trace was initialized twice");
60+
toc = g_new(uint64_t, 1024);
61+
toc_capacity = 1024;
62+
toc_entries = 0;
63+
}
64+
65+
static void toc_append(uint64_t entry) {
66+
if (toc_capacity <= toc_entries) {
67+
toc = g_renew(uint64_t, toc, toc_capacity * 2);
68+
toc_capacity *= 2;
69+
}
70+
toc[toc_entries++] = entry;
71+
}
72+
73+
static void toc_write(void) {
74+
int64_t toc_offset = ftell(file);
75+
if (toc_offset > 0) {
76+
int i = 0;
77+
WRITE(frames_per_toc_entry);
78+
for (i = 0; i < toc_entries; i++)
79+
WRITE(toc[i]);
80+
SEEK(num_trace_frames_offset);
81+
WRITE(toc_num_frames);
82+
SEEK(toc_offset_offset);
83+
WRITE(toc_offset);
84+
}
85+
}
86+
87+
static void toc_update(void) {
88+
toc_num_frames++;
89+
if (toc_num_frames % frames_per_toc_entry == 0) {
90+
int64_t off = ftell(file);
91+
if (off >= 0) toc_append(off);
92+
}
93+
}
94+
95+
static void write_header(void) {
96+
uint64_t toc_off = 0L;
97+
WRITE(magic_number);
98+
WRITE(out_trace_version);
99+
WRITE(frame_arch);
100+
WRITE(frame_mach);
101+
WRITE(toc_num_frames);
102+
WRITE(toc_off);
103+
}
104+
105+
static int list_length(char **list) {
106+
int n=0;
107+
if (list) {
108+
char **p = list;
109+
for (;*p;p++,n++);
110+
}
111+
return n;
112+
}
113+
114+
static void compute_target_md5(void) {
115+
const GChecksumType md5 = G_CHECKSUM_MD5;
116+
GChecksum *cs = g_checksum_new(md5);
117+
FILE *target = fopen(target_path, "r");
118+
guchar buf[BUFSIZ];
119+
gsize expected_length = MD5LEN;
120+
121+
if (!cs) err(1, "failed to create a checksum");
122+
if (!target) err(1, "failed to open target binary");
123+
if (g_checksum_type_get_length(md5) != expected_length) abort();
124+
125+
while (!feof(target)) {
126+
size_t len = fread(buf,1,BUFSIZ,target);
127+
if (ferror(target))
128+
err(1, "failed to read target binary");
129+
g_checksum_update(cs, buf, len);
130+
}
131+
132+
g_checksum_get_digest(cs, target_md5, &expected_length);
133+
fclose(target);
134+
}
135+
136+
static void store_to_trace(ProtobufCBuffer *self, size_t len, const uint8_t *data) {
137+
WRITE_BUF(data,len);
138+
}
139+
140+
static void init_tracer(Tracer *tracer, char **argv, char **envp) {
141+
tracer__init(tracer);
142+
tracer->name = tracer_name;
143+
tracer->n_args = list_length(argv);
144+
tracer->args = argv;
145+
tracer->n_envp = list_length(envp);
146+
tracer->envp = envp;
147+
tracer->version = tracer_version;
148+
}
149+
150+
static void init_target(Target *target, char **argv, char **envp) {
151+
compute_target_md5();
152+
153+
target__init(target);
154+
target->path = target_path;
155+
target->n_args = list_length(argv);
156+
target->args = argv;
157+
target->n_envp = list_length(envp);
158+
target->envp = envp;
159+
target->md5sum.len = MD5LEN;
160+
target->md5sum.data = target_md5;
161+
}
162+
163+
#ifdef G_OS_UNIX
164+
static void unix_fill_fstats(Fstats *fstats, char *path) {
165+
struct stat stats;
166+
if (stat(path, &stats) < 0)
167+
err(1, "failed to obtain file stats");
168+
169+
fstats->size = stats.st_size;
170+
fstats->atime = stats.st_atime;
171+
fstats->mtime = stats.st_mtime;
172+
fstats->ctime = stats.st_ctime;
173+
}
174+
#endif
175+
176+
177+
static void init_fstats(Fstats *fstats) {
178+
fstats__init(fstats);
179+
#ifdef G_OS_UNIX
180+
unix_fill_fstats(fstats, target_path);
181+
#endif
182+
}
183+
184+
185+
static void write_meta(
186+
char **tracer_argv,
187+
char **tracer_envp,
188+
char **target_argv,
189+
char **target_envp)
190+
{
191+
MetaFrame meta;
192+
Tracer tracer;
193+
Target target;
194+
Fstats fstats;
195+
ProtobufCBuffer buffer;
196+
197+
buffer.append = store_to_trace;
198+
199+
200+
meta_frame__init(&meta);
201+
init_tracer(&tracer, tracer_argv, tracer_envp);
202+
init_target(&target, target_argv, target_envp);
203+
init_fstats(&fstats);
204+
205+
meta.tracer = &tracer;
206+
meta.target = &target;
207+
meta.fstats = &fstats;
208+
meta.time = time(NULL);
209+
char *user = g_strdup(g_get_real_name());
210+
meta.user = user;
211+
212+
char *host = g_strdup(g_get_host_name());
213+
meta.host = host;
214+
215+
uint64_t size = meta_frame__get_packed_size(&meta);
216+
WRITE(size);
217+
218+
meta_frame__pack_to_buffer(&meta, &buffer);
219+
220+
free(user);
221+
free(host);
222+
}
223+
224+
225+
void qemu_trace_init(const char *filename,
226+
const char *targetname,
227+
char **argv, char **envp,
228+
char **target_argv,
229+
char **target_envp) {
230+
qemu_log("Initializing tracer\n");
231+
if (realpath(targetname,target_path) == NULL)
232+
err(1, "can't get target path");
233+
234+
235+
char *name = filename
236+
? g_strdup(filename)
237+
: g_strdup_printf("%s.frames", basename(target_path));
238+
file = fopen(name, "wb");
239+
if (file == NULL)
240+
err(1, "tracewrap: can't open trace file %s", name);
241+
write_header();
242+
write_meta(argv, envp, target_argv, target_envp);
243+
toc_init();
244+
g_free(name);
245+
}
246+
247+
248+
void qemu_trace_newframe(target_ulong addr, int __unused/*thread_id*/ ) {
249+
int thread_id = 1;
250+
if (open_frame) {
251+
qemu_log("frame is still open");
252+
qemu_trace_endframe(NULL, 0, 0);
253+
}
254+
255+
open_frame = 1;
256+
g_frame = g_new(Frame,1);
257+
frame__init(g_frame);
258+
259+
StdFrame *sframe = g_new(StdFrame, 1);
260+
std_frame__init(sframe);
261+
g_frame->std_frame = sframe;
262+
263+
sframe->address = addr;
264+
sframe->thread_id = thread_id;
265+
266+
OperandValueList *ol_in = g_new(OperandValueList,1);
267+
operand_value_list__init(ol_in);
268+
ol_in->n_elem = 0;
269+
sframe->operand_pre_list = ol_in;
270+
271+
OperandValueList *ol_out = g_new(OperandValueList,1);
272+
operand_value_list__init(ol_out);
273+
ol_out->n_elem = 0;
274+
sframe->operand_post_list = ol_out;
275+
}
276+
277+
static inline void free_operand(OperandInfo *oi) {
278+
OperandInfoSpecific *ois = oi->operand_info_specific;
279+
280+
//Free reg-operand
281+
RegOperand *ro = ois->reg_operand;
282+
if (ro && ro->name)
283+
g_free(ro->name);
284+
g_free(ro);
285+
286+
//Free mem-operand
287+
MemOperand *mo = ois->mem_operand;
288+
g_free(mo);
289+
g_free(oi->value.data);
290+
g_free(oi->taint_info);
291+
g_free(ois);
292+
g_free(oi->operand_usage);
293+
g_free(oi);
294+
}
295+
296+
void qemu_trace_add_operand(OperandInfo *oi, int inout) {
297+
if (!open_frame) {
298+
if (oi)
299+
free_operand(oi);
300+
return;
301+
}
302+
OperandValueList *ol;
303+
if (inout & 0x1) {
304+
ol = g_frame->std_frame->operand_pre_list;
305+
} else {
306+
ol = g_frame->std_frame->operand_post_list;
307+
}
308+
309+
oi->taint_info = g_new(TaintInfo, 1);
310+
taint_info__init(oi->taint_info);
311+
oi->taint_info->no_taint = 1;
312+
oi->taint_info->has_no_taint = 1;
313+
314+
ol->n_elem += 1;
315+
ol->elem = g_renew(OperandInfo *, ol->elem, ol->n_elem);
316+
ol->elem[ol->n_elem - 1] = oi;
317+
}
318+
319+
void qemu_trace_endframe(CPUArchState *env, target_ulong pc, target_ulong size) {
320+
int i = 0;
321+
StdFrame *sframe = g_frame->std_frame;
322+
323+
if (!open_frame) return;
324+
325+
sframe->rawbytes.len = size;
326+
sframe->rawbytes.data = g_malloc(size);
327+
for (i = 0; i < size; i++) {
328+
sframe->rawbytes.data[i] = cpu_ldub_code(env, pc+i);
329+
}
330+
331+
size_t msg_size = frame__get_packed_size(g_frame);
332+
uint8_t *packed_buffer = g_alloca(msg_size);
333+
uint64_t packed_size = frame__pack(g_frame, packed_buffer);
334+
WRITE(packed_size);
335+
WRITE_BUF(packed_buffer, packed_size);
336+
toc_update();
337+
338+
//counting num_frames in newframe does not work by far ...
339+
//how comes? disas_arm_insn might not always return at the end?
340+
for (i = 0; i < sframe->operand_pre_list->n_elem; i++)
341+
free_operand(sframe->operand_pre_list->elem[i]);
342+
g_free(sframe->operand_pre_list->elem);
343+
g_free(sframe->operand_pre_list);
344+
345+
for (i = 0; i < sframe->operand_post_list->n_elem; i++)
346+
free_operand(sframe->operand_post_list->elem[i]);
347+
g_free(sframe->operand_post_list->elem);
348+
g_free(sframe->operand_post_list);
349+
350+
g_free(sframe->rawbytes.data);
351+
g_free(sframe);
352+
g_free(g_frame);
353+
open_frame = 0;
354+
}
355+
356+
void qemu_trace_finish(uint32_t exit_code) {
357+
toc_write();
358+
if (fclose(file) != 0)
359+
err(1,"failed to write trace file, the file maybe corrupted");
360+
}

0 commit comments

Comments
 (0)