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