Commit | Line | Data |
---|---|---|
00bf0b85 SS |
1 | /* This program does two things; it generates valid trace files, and |
2 | it can also be traced so as to test trace file creation from | |
3 | GDB. */ | |
4 | ||
5 | #include <stdio.h> | |
6 | #include <string.h> | |
7 | #include <fcntl.h> | |
8 | #include <sys/stat.h> | |
9 | ||
10 | char spbuf[200]; | |
11 | ||
12 | char trbuf[1000]; | |
13 | char *trptr; | |
14 | char *tfsizeptr; | |
15 | ||
3f1175a9 PA |
16 | /* These globals are put in the trace buffer. */ |
17 | ||
00bf0b85 SS |
18 | int testglob = 31415; |
19 | ||
fce3c1f0 SS |
20 | int testglob2 = 271828; |
21 | ||
3f1175a9 PA |
22 | /* But these below are not. */ |
23 | ||
fce3c1f0 SS |
24 | const int constglob = 10000; |
25 | ||
3f1175a9 PA |
26 | int nonconstglob = 14124; |
27 | ||
00bf0b85 SS |
28 | int |
29 | start_trace_file (char *filename) | |
30 | { | |
31 | int fd; | |
32 | ||
33 | fd = open (filename, O_WRONLY|O_CREAT|O_APPEND, | |
34 | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | |
35 | ||
36 | if (fd < 0) | |
37 | return fd; | |
38 | ||
39 | /* Write a file header, with a high-bit-set char to indicate a | |
40 | binary file, plus a hint as what this file is, and a version | |
41 | number in case of future needs. */ | |
42 | write (fd, "\x7fTRACE0\n", 8); | |
43 | ||
44 | return fd; | |
45 | } | |
46 | ||
47 | void | |
48 | finish_trace_file (int fd) | |
49 | { | |
50 | close (fd); | |
51 | } | |
52 | ||
fce3c1f0 SS |
53 | |
54 | void | |
55 | add_memory_block (char *addr, int size) | |
56 | { | |
57 | short short_x; | |
ba4a8bdd | 58 | unsigned long long ll_x; |
fce3c1f0 SS |
59 | |
60 | *((char *) trptr) = 'M'; | |
61 | trptr += 1; | |
ba4a8bdd YQ |
62 | ll_x = (unsigned long) addr; |
63 | memcpy (trptr, &ll_x, sizeof (unsigned long long)); | |
64 | trptr += sizeof (unsigned long long); | |
fce3c1f0 SS |
65 | short_x = size; |
66 | memcpy (trptr, &short_x, 2); | |
67 | trptr += 2; | |
68 | memcpy (trptr, addr, size); | |
69 | trptr += size; | |
70 | } | |
71 | ||
00bf0b85 | 72 | void |
6c28cbf2 | 73 | write_basic_trace_file (void) |
00bf0b85 | 74 | { |
6c28cbf2 SS |
75 | int fd, int_x; |
76 | short short_x; | |
00bf0b85 SS |
77 | |
78 | fd = start_trace_file ("basic.tf"); | |
79 | ||
80 | /* The next part of the file consists of newline-separated lines | |
81 | defining status, tracepoints, etc. The section is terminated by | |
82 | an empty line. */ | |
83 | ||
84 | /* Dump the size of the R (register) blocks in traceframes. */ | |
85 | snprintf (spbuf, sizeof spbuf, "R %x\n", 500 /* FIXME get from arch */); | |
86 | write (fd, spbuf, strlen (spbuf)); | |
87 | ||
88 | /* Dump trace status, in the general form of the qTstatus reply. */ | |
89 | snprintf (spbuf, sizeof spbuf, "status 0;tstop:0;tframes:1;tcreated:1;tfree:100;tsize:1000\n"); | |
90 | write (fd, spbuf, strlen (spbuf)); | |
91 | ||
92 | /* Dump tracepoint definitions, in syntax similar to that used | |
93 | for reconnection uploads. */ | |
6c28cbf2 | 94 | /* FIXME need a portable way to print function address in hex */ |
00bf0b85 SS |
95 | snprintf (spbuf, sizeof spbuf, "tp T1:%lx:E:0:0\n", |
96 | (long) &write_basic_trace_file); | |
97 | write (fd, spbuf, strlen (spbuf)); | |
98 | /* (Note that we would only need actions defined if we wanted to | |
99 | test tdump.) */ | |
100 | ||
101 | /* Empty line marks the end of the definition section. */ | |
102 | write (fd, "\n", 1); | |
103 | ||
104 | /* Make up a simulated trace buffer. */ | |
6c28cbf2 SS |
105 | /* (Encapsulate better if we're going to do lots of this; note that |
106 | buffer endianness is the target program's enddianness.) */ | |
00bf0b85 | 107 | trptr = trbuf; |
6c28cbf2 SS |
108 | short_x = 1; |
109 | memcpy (trptr, &short_x, 2); | |
110 | trptr += 2; | |
00bf0b85 | 111 | tfsizeptr = trptr; |
6c28cbf2 | 112 | trptr += 4; |
fce3c1f0 SS |
113 | add_memory_block (&testglob, sizeof (testglob)); |
114 | /* Divide a variable between two separate memory blocks. */ | |
115 | add_memory_block (&testglob2, 1); | |
116 | add_memory_block (((char*) &testglob2) + 1, sizeof (testglob2) - 1); | |
00bf0b85 | 117 | /* Go back and patch in the frame size. */ |
6c28cbf2 SS |
118 | int_x = trptr - tfsizeptr - sizeof (int); |
119 | memcpy (tfsizeptr, &int_x, 4); | |
120 | ||
121 | /* Write end of tracebuffer marker. */ | |
122 | memset (trptr, 0, 6); | |
123 | trptr += 6; | |
124 | ||
125 | write (fd, trbuf, trptr - trbuf); | |
126 | ||
127 | finish_trace_file (fd); | |
128 | } | |
129 | ||
610197fd PA |
130 | /* Convert number NIB to a hex digit. */ |
131 | ||
132 | static int | |
133 | tohex (int nib) | |
134 | { | |
135 | if (nib < 10) | |
136 | return '0' + nib; | |
137 | else | |
138 | return 'a' + nib - 10; | |
139 | } | |
140 | ||
141 | int | |
142 | bin2hex (const char *bin, char *hex, int count) | |
143 | { | |
144 | int i; | |
145 | ||
146 | for (i = 0; i < count; i++) | |
147 | { | |
148 | *hex++ = tohex ((*bin >> 4) & 0xf); | |
149 | *hex++ = tohex (*bin++ & 0xf); | |
150 | } | |
151 | *hex = 0; | |
152 | return i; | |
153 | } | |
154 | ||
6c28cbf2 SS |
155 | void |
156 | write_error_trace_file (void) | |
157 | { | |
158 | int fd; | |
610197fd PA |
159 | const char made_up[] = "made-up error"; |
160 | int len = sizeof (made_up) - 1; | |
161 | char *hex = alloca (len * 2 + 1); | |
6c28cbf2 SS |
162 | |
163 | fd = start_trace_file ("error.tf"); | |
164 | ||
165 | /* The next part of the file consists of newline-separated lines | |
166 | defining status, tracepoints, etc. The section is terminated by | |
167 | an empty line. */ | |
168 | ||
169 | /* Dump the size of the R (register) blocks in traceframes. */ | |
170 | snprintf (spbuf, sizeof spbuf, "R %x\n", 500 /* FIXME get from arch */); | |
171 | write (fd, spbuf, strlen (spbuf)); | |
172 | ||
610197fd PA |
173 | bin2hex (made_up, hex, len); |
174 | ||
6c28cbf2 | 175 | /* Dump trace status, in the general form of the qTstatus reply. */ |
610197fd PA |
176 | snprintf (spbuf, sizeof spbuf, |
177 | "status 0;" | |
178 | "terror:%s:1;" | |
179 | "tframes:0;tcreated:0;tfree:100;tsize:1000\n", | |
180 | hex); | |
6c28cbf2 SS |
181 | write (fd, spbuf, strlen (spbuf)); |
182 | ||
183 | /* Dump tracepoint definitions, in syntax similar to that used | |
184 | for reconnection uploads. */ | |
185 | /* FIXME need a portable way to print function address in hex */ | |
186 | snprintf (spbuf, sizeof spbuf, "tp T1:%lx:E:0:0\n", | |
187 | (long) &write_basic_trace_file); | |
188 | write (fd, spbuf, strlen (spbuf)); | |
189 | /* (Note that we would only need actions defined if we wanted to | |
190 | test tdump.) */ | |
191 | ||
192 | /* Empty line marks the end of the definition section. */ | |
193 | write (fd, "\n", 1); | |
194 | ||
195 | trptr = trbuf; | |
00bf0b85 SS |
196 | |
197 | /* Write end of tracebuffer marker. */ | |
6c28cbf2 SS |
198 | memset (trptr, 0, 6); |
199 | trptr += 6; | |
00bf0b85 SS |
200 | |
201 | write (fd, trbuf, trptr - trbuf); | |
202 | ||
203 | finish_trace_file (fd); | |
204 | } | |
205 | ||
206 | void | |
207 | done_making_trace_files (void) | |
208 | { | |
209 | } | |
210 | ||
211 | int | |
212 | main (int argc, char **argv, char **envp) | |
213 | { | |
214 | write_basic_trace_file (); | |
215 | ||
6c28cbf2 SS |
216 | write_error_trace_file (); |
217 | ||
00bf0b85 SS |
218 | done_making_trace_files (); |
219 | ||
220 | return 0; | |
221 | } | |
222 |