]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.trace/tfile.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.trace / tfile.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3 Copyright 2010-2024 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 /* This program does two things; it generates valid trace files, and
19 it can also be traced so as to test trace file creation from
20 GDB. */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <sys/stat.h>
27 #include <stdint.h>
28
29 char spbuf[200];
30
31 char trbuf[1000];
32 char *trptr;
33 char *tfsizeptr;
34
35 /* These globals are put in the trace buffer. */
36
37 int testglob = 31415;
38
39 int testglob2 = 271828;
40
41 /* But these below are not. */
42
43 const int constglob = 10000;
44
45 int nonconstglob = 14124;
46
47 int
48 start_trace_file (char *filename)
49 {
50 int fd;
51 mode_t mode = S_IRUSR | S_IWUSR;
52
53 #ifdef S_IRGRP
54 mode |= S_IRGRP;
55 #endif
56
57 #ifdef S_IROTH
58 mode |= S_IROTH;
59 #endif
60
61 fd = open (filename, O_WRONLY|O_CREAT|O_APPEND, mode);
62
63 if (fd < 0)
64 return fd;
65
66 /* Write a file header, with a high-bit-set char to indicate a
67 binary file, plus a hint as what this file is, and a version
68 number in case of future needs. */
69 write (fd, "\x7fTRACE0\n", 8);
70
71 return fd;
72 }
73
74 void
75 finish_trace_file (int fd)
76 {
77 close (fd);
78 }
79
80 static void
81 tfile_write_64 (uint64_t value)
82 {
83 memcpy (trptr, &value, sizeof (uint64_t));
84 trptr += sizeof (uint64_t);
85 }
86
87 static void
88 tfile_write_16 (uint16_t value)
89 {
90 memcpy (trptr, &value, sizeof (uint16_t));
91 trptr += sizeof (uint16_t);
92 }
93
94 static void
95 tfile_write_8 (uint8_t value)
96 {
97 memcpy (trptr, &value, sizeof (uint8_t));
98 trptr += sizeof (uint8_t);
99 }
100
101 static void
102 tfile_write_addr (char *addr)
103 {
104 tfile_write_64 ((uint64_t) (uintptr_t) addr);
105 }
106
107 static void
108 tfile_write_buf (const void *addr, size_t size)
109 {
110 memcpy (trptr, addr, size);
111 trptr += size;
112 }
113
114 void
115 add_memory_block (char *addr, int size)
116 {
117 tfile_write_8 ('M');
118 tfile_write_addr (addr);
119 tfile_write_16 (size);
120 tfile_write_buf (addr, size);
121 }
122
123 /* Adjust a function's address to account for architectural
124 particularities. */
125
126 static uintptr_t
127 adjust_function_address (uintptr_t func_addr)
128 {
129 #if defined(__thumb__) || defined(__thumb2__)
130 /* Although Thumb functions are two-byte aligned, function
131 pointers have the Thumb bit set. Clear it. */
132 return func_addr & ~1;
133 #elif defined __powerpc64__ && _CALL_ELF != 2
134 /* Get function address from function descriptor. */
135 return *(uintptr_t *) func_addr;
136 #else
137 return func_addr;
138 #endif
139 }
140
141 /* Get a function's address as an integer. */
142
143 #define FUNCTION_ADDRESS(FUN) adjust_function_address ((uintptr_t) &FUN)
144
145 void
146 write_basic_trace_file (void)
147 {
148 int fd, int_x;
149 unsigned long long func_addr;
150
151 fd = start_trace_file (TFILE_DIR "tfile-basic.tf");
152
153 /* The next part of the file consists of newline-separated lines
154 defining status, tracepoints, etc. The section is terminated by
155 an empty line. */
156
157 /* Dump the size of the R (register) blocks in traceframes. */
158 snprintf (spbuf, sizeof spbuf, "R %x\n", 500 /* FIXME get from arch */);
159 write (fd, spbuf, strlen (spbuf));
160
161 /* Dump trace status, in the general form of the qTstatus reply. */
162 snprintf (spbuf, sizeof spbuf, "status 0;tstop:0;tframes:1;tcreated:1;tfree:100;tsize:1000\n");
163 write (fd, spbuf, strlen (spbuf));
164
165 /* Dump tracepoint definitions, in syntax similar to that used
166 for reconnection uploads. */
167 func_addr = FUNCTION_ADDRESS (write_basic_trace_file);
168
169 snprintf (spbuf, sizeof spbuf, "tp T1:%llx:E:0:0\n", func_addr);
170 write (fd, spbuf, strlen (spbuf));
171 /* (Note that we would only need actions defined if we wanted to
172 test tdump.) */
173
174 /* Empty line marks the end of the definition section. */
175 write (fd, "\n", 1);
176
177 /* Make up a simulated trace buffer. */
178 /* (Encapsulate better if we're going to do lots of this; note that
179 buffer endianness is the target program's endianness.) */
180 trptr = trbuf;
181 tfile_write_16 (1);
182
183 tfsizeptr = trptr;
184 trptr += 4;
185 add_memory_block ((char *) &testglob, sizeof (testglob));
186 /* Divide a variable between two separate memory blocks. */
187 add_memory_block ((char *) &testglob2, 1);
188 add_memory_block (((char*) &testglob2) + 1, sizeof (testglob2) - 1);
189 /* Go back and patch in the frame size. */
190 int_x = trptr - tfsizeptr - sizeof (int);
191 memcpy (tfsizeptr, &int_x, 4);
192
193 /* Write end of tracebuffer marker. */
194 memset (trptr, 0, 6);
195 trptr += 6;
196
197 write (fd, trbuf, trptr - trbuf);
198
199 finish_trace_file (fd);
200 }
201
202 /* Convert number NIB to a hex digit. */
203
204 static int
205 tohex (int nib)
206 {
207 if (nib < 10)
208 return '0' + nib;
209 else
210 return 'a' + nib - 10;
211 }
212
213 int
214 bin2hex (const char *bin, char *hex, int count)
215 {
216 int i;
217
218 for (i = 0; i < count; i++)
219 {
220 *hex++ = tohex ((*bin >> 4) & 0xf);
221 *hex++ = tohex (*bin++ & 0xf);
222 }
223 *hex = 0;
224 return i;
225 }
226
227 void
228 write_error_trace_file (void)
229 {
230 int fd;
231 const char made_up[] = "made-up error";
232 char hex[(sizeof (made_up) - 1) * 2 + 1];
233 int len = sizeof (made_up) - 1;
234
235 fd = start_trace_file (TFILE_DIR "tfile-error.tf");
236
237 /* The next part of the file consists of newline-separated lines
238 defining status, tracepoints, etc. The section is terminated by
239 an empty line. */
240
241 /* Dump the size of the R (register) blocks in traceframes. */
242 snprintf (spbuf, sizeof spbuf, "R %x\n", 500 /* FIXME get from arch */);
243 write (fd, spbuf, strlen (spbuf));
244
245 bin2hex (made_up, hex, len);
246
247 /* Dump trace status, in the general form of the qTstatus reply. */
248 snprintf (spbuf, sizeof spbuf,
249 "status 0;"
250 "terror:%s:1;"
251 "tframes:0;tcreated:0;tfree:100;tsize:1000\n",
252 hex);
253 write (fd, spbuf, strlen (spbuf));
254
255 /* Dump tracepoint definitions, in syntax similar to that used
256 for reconnection uploads. */
257 snprintf (spbuf, sizeof spbuf, "tp T1:%llx:E:0:0\n",
258 (unsigned long long) FUNCTION_ADDRESS (write_basic_trace_file));
259 write (fd, spbuf, strlen (spbuf));
260 /* (Note that we would only need actions defined if we wanted to
261 test tdump.) */
262
263 /* Empty line marks the end of the definition section. */
264 write (fd, "\n", 1);
265
266 trptr = trbuf;
267
268 /* Write end of tracebuffer marker. */
269 memset (trptr, 0, 6);
270 trptr += 6;
271
272 write (fd, trbuf, trptr - trbuf);
273
274 finish_trace_file (fd);
275 }
276
277 void
278 done_making_trace_files (void)
279 {
280 }
281
282 int
283 main (void)
284 {
285 write_basic_trace_file ();
286
287 write_error_trace_file ();
288
289 done_making_trace_files ();
290
291 return 0;
292 }
293