1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2010-2023 Free Software Foundation, Inc.
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.
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.
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/>. */
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
35 /* These globals are put in the trace buffer. */
39 int testglob2
= 271828;
41 /* But these below are not. */
43 const int constglob
= 10000;
45 int nonconstglob
= 14124;
48 start_trace_file (char *filename
)
51 mode_t mode
= S_IRUSR
| S_IWUSR
;
61 fd
= open (filename
, O_WRONLY
|O_CREAT
|O_APPEND
, mode
);
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);
75 finish_trace_file (int fd
)
81 tfile_write_64 (uint64_t value
)
83 memcpy (trptr
, &value
, sizeof (uint64_t));
84 trptr
+= sizeof (uint64_t);
88 tfile_write_16 (uint16_t value
)
90 memcpy (trptr
, &value
, sizeof (uint16_t));
91 trptr
+= sizeof (uint16_t);
95 tfile_write_8 (uint8_t value
)
97 memcpy (trptr
, &value
, sizeof (uint8_t));
98 trptr
+= sizeof (uint8_t);
102 tfile_write_addr (char *addr
)
104 tfile_write_64 ((uint64_t) (uintptr_t) addr
);
108 tfile_write_buf (const void *addr
, size_t size
)
110 memcpy (trptr
, addr
, size
);
115 add_memory_block (char *addr
, int size
)
118 tfile_write_addr (addr
);
119 tfile_write_16 (size
);
120 tfile_write_buf (addr
, size
);
123 /* Adjust a function's address to account for architectural
127 adjust_function_address (uintptr_t func_addr
)
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
;
141 /* Get a function's address as an integer. */
143 #define FUNCTION_ADDRESS(FUN) adjust_function_address ((uintptr_t) &FUN)
146 write_basic_trace_file (void)
149 unsigned long long func_addr
;
151 fd
= start_trace_file (TFILE_DIR
"tfile-basic.tf");
153 /* The next part of the file consists of newline-separated lines
154 defining status, tracepoints, etc. The section is terminated by
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
));
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
));
165 /* Dump tracepoint definitions, in syntax similar to that used
166 for reconnection uploads. */
167 func_addr
= FUNCTION_ADDRESS (write_basic_trace_file
);
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
174 /* Empty line marks the end of the definition section. */
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.) */
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);
193 /* Write end of tracebuffer marker. */
194 memset (trptr
, 0, 6);
197 write (fd
, trbuf
, trptr
- trbuf
);
199 finish_trace_file (fd
);
202 /* Convert number NIB to a hex digit. */
210 return 'a' + nib
- 10;
214 bin2hex (const char *bin
, char *hex
, int count
)
218 for (i
= 0; i
< count
; i
++)
220 *hex
++ = tohex ((*bin
>> 4) & 0xf);
221 *hex
++ = tohex (*bin
++ & 0xf);
228 write_error_trace_file (void)
231 const char made_up
[] = "made-up error";
232 char hex
[(sizeof (made_up
) - 1) * 2 + 1];
233 int len
= sizeof (made_up
) - 1;
235 fd
= start_trace_file (TFILE_DIR
"tfile-error.tf");
237 /* The next part of the file consists of newline-separated lines
238 defining status, tracepoints, etc. The section is terminated by
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
));
245 bin2hex (made_up
, hex
, len
);
247 /* Dump trace status, in the general form of the qTstatus reply. */
248 snprintf (spbuf
, sizeof spbuf
,
251 "tframes:0;tcreated:0;tfree:100;tsize:1000\n",
253 write (fd
, spbuf
, strlen (spbuf
));
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
263 /* Empty line marks the end of the definition section. */
268 /* Write end of tracebuffer marker. */
269 memset (trptr
, 0, 6);
272 write (fd
, trbuf
, trptr
- trbuf
);
274 finish_trace_file (fd
);
278 done_making_trace_files (void)
285 write_basic_trace_file ();
287 write_error_trace_file ();
289 done_making_trace_files ();