]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-utils.c
abb87f8c5a0403bc212cfeeb9e8f77265232dcb9
[thirdparty/binutils-gdb.git] / sim / common / sim-utils.c
1 /* Miscellaneous simulator utilities.
2 Copyright (C) 1997-2021 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #include "sim-main.h"
24 #include "sim-assert.h"
25
26 #include <stdlib.h>
27 #include <time.h>
28 #include <sys/time.h> /* needed by sys/resource.h */
29
30 #ifdef HAVE_SYS_RESOURCE_H
31 #include <sys/resource.h>
32 #endif
33 #include <string.h>
34
35 #include "libiberty.h"
36 #include "bfd.h"
37 #include "sim-utils.h"
38
39 /* Allocate zero filled memory with xcalloc - xcalloc aborts if the
40 allocation fails. */
41
42 void *
43 zalloc (unsigned long size)
44 {
45 return xcalloc (1, size);
46 }
47
48 /* Allocate a sim_state struct. */
49
50 SIM_DESC
51 sim_state_alloc (SIM_OPEN_KIND kind,
52 host_callback *callback)
53 {
54 SIM_DESC sd = ZALLOC (struct sim_state);
55
56 STATE_MAGIC (sd) = SIM_MAGIC_NUMBER;
57 STATE_CALLBACK (sd) = callback;
58 STATE_OPEN_KIND (sd) = kind;
59
60 #if 0
61 {
62 int cpu_nr;
63
64 /* Initialize the back link from the cpu struct to the state struct. */
65 /* ??? I can envision a design where the state struct contains an array
66 of pointers to cpu structs, rather than an array of structs themselves.
67 Implementing this is trickier as one may not know what to allocate until
68 one has parsed the args. Parsing the args twice wouldn't be unreasonable,
69 IMHO. If the state struct ever does contain an array of pointers then we
70 can't do this here.
71 ??? See also sim_post_argv_init*/
72 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
73 {
74 CPU_STATE (STATE_CPU (sd, cpu_nr)) = sd;
75 CPU_INDEX (STATE_CPU (sd, cpu_nr)) = cpu_nr;
76 }
77 }
78 #endif
79
80 #ifdef SIM_STATE_INIT
81 SIM_STATE_INIT (sd);
82 #endif
83
84 return sd;
85 }
86
87 /* Free a sim_state struct. */
88
89 void
90 sim_state_free (SIM_DESC sd)
91 {
92 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
93
94 #ifdef SIM_STATE_FREE
95 SIM_STATE_FREE (sd);
96 #endif
97
98 free (sd);
99 }
100
101 /* Return a pointer to the cpu data for CPU_NAME, or NULL if not found. */
102
103 sim_cpu *
104 sim_cpu_lookup (SIM_DESC sd, const char *cpu_name)
105 {
106 int i;
107
108 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
109 if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0)
110 return STATE_CPU (sd, i);
111 return NULL;
112 }
113
114 /* Return the prefix to use for a CPU specific message (typically an
115 error message). */
116
117 const char *
118 sim_cpu_msg_prefix (sim_cpu *cpu)
119 {
120 #if MAX_NR_PROCESSORS == 1
121 return "";
122 #else
123 static char *prefix;
124
125 if (prefix == NULL)
126 {
127 int maxlen = 0;
128 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
129 {
130 int len = strlen (CPU_NAME (STATE_CPU (sd, i)));
131 if (len > maxlen)
132 maxlen = len;
133 }
134 prefix = (char *) xmalloc (maxlen + 5);
135 }
136 sprintf (prefix, "%s: ", CPU_NAME (cpu));
137 return prefix;
138 #endif
139 }
140
141 /* Cover fn to sim_io_eprintf. */
142
143 void
144 sim_io_eprintf_cpu (sim_cpu *cpu, const char *fmt, ...)
145 {
146 SIM_DESC sd = CPU_STATE (cpu);
147 va_list ap;
148
149 va_start (ap, fmt);
150 sim_io_eprintf (sd, "%s", sim_cpu_msg_prefix (cpu));
151 sim_io_evprintf (sd, fmt, ap);
152 va_end (ap);
153 }
154
155 /* Turn VALUE into a string with commas. */
156
157 char *
158 sim_add_commas (char *buf, int sizeof_buf, unsigned long value)
159 {
160 int comma = 3;
161 char *endbuf = buf + sizeof_buf - 1;
162
163 *--endbuf = '\0';
164 do {
165 if (comma-- == 0)
166 {
167 *--endbuf = ',';
168 comma = 2;
169 }
170
171 *--endbuf = (value % 10) + '0';
172 } while ((value /= 10) != 0);
173
174 return endbuf;
175 }
176
177 /* Analyze PROG_NAME/PROG_BFD and set these fields in the state struct:
178 STATE_ARCHITECTURE, if not set already and can be determined from the bfd
179 STATE_PROG_BFD
180 STATE_START_ADDR
181 STATE_TEXT_SECTION
182 STATE_TEXT_START
183 STATE_TEXT_END
184
185 PROG_NAME is the file name of the executable or NULL.
186 PROG_BFD is its bfd or NULL.
187
188 If both PROG_NAME and PROG_BFD are NULL, this function returns immediately.
189 If PROG_BFD is not NULL, PROG_NAME is ignored.
190
191 Implicit inputs: STATE_MY_NAME(sd), STATE_TARGET(sd),
192 STATE_ARCHITECTURE(sd).
193
194 A new bfd is created so the app isn't required to keep its copy of the
195 bfd open. */
196
197 SIM_RC
198 sim_analyze_program (SIM_DESC sd, const char *prog_name, bfd *prog_bfd)
199 {
200 asection *s;
201 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
202
203 if (prog_bfd != NULL)
204 {
205 if (prog_bfd == STATE_PROG_BFD (sd))
206 /* already analyzed */
207 return SIM_RC_OK;
208 else
209 /* duplicate needed, save the name of the file to be re-opened */
210 prog_name = bfd_get_filename (prog_bfd);
211 }
212
213 /* do we need to duplicate anything? */
214 if (prog_name == NULL)
215 return SIM_RC_OK;
216
217 /* open a new copy of the prog_bfd */
218 prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd));
219 if (prog_bfd == NULL)
220 {
221 sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n",
222 STATE_MY_NAME (sd),
223 prog_name,
224 bfd_errmsg (bfd_get_error ()));
225 return SIM_RC_FAIL;
226 }
227 if (!bfd_check_format (prog_bfd, bfd_object))
228 {
229 sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n",
230 STATE_MY_NAME (sd),
231 prog_name,
232 bfd_errmsg (bfd_get_error ()));
233 bfd_close (prog_bfd);
234 return SIM_RC_FAIL;
235 }
236 if (STATE_ARCHITECTURE (sd) != NULL)
237 bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd));
238 else
239 {
240 if (bfd_get_arch (prog_bfd) != bfd_arch_unknown
241 && bfd_get_arch (prog_bfd) != bfd_arch_obscure)
242 {
243 STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd);
244 }
245 }
246
247 /* update the sim structure */
248 if (STATE_PROG_BFD (sd) != NULL)
249 bfd_close (STATE_PROG_BFD (sd));
250 STATE_PROG_BFD (sd) = prog_bfd;
251 STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd);
252
253 for (s = prog_bfd->sections; s; s = s->next)
254 if (strcmp (bfd_section_name (s), ".text") == 0)
255 {
256 STATE_TEXT_SECTION (sd) = s;
257 STATE_TEXT_START (sd) = bfd_section_vma (s);
258 STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (s);
259 break;
260 }
261
262 bfd_cache_close (prog_bfd);
263
264 return SIM_RC_OK;
265 }
266 \f
267 /* Simulator timing support. */
268
269 /* Called before sim_elapsed_time_since to get a reference point. */
270
271 SIM_ELAPSED_TIME
272 sim_elapsed_time_get (void)
273 {
274 #ifdef HAVE_GETRUSAGE
275 struct rusage mytime;
276 if (getrusage (RUSAGE_SELF, &mytime) == 0)
277 return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000));
278 return 1;
279 #else
280 #ifdef HAVE_TIME
281 return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0);
282 #else
283 return 1;
284 #endif
285 #endif
286 }
287
288 /* Return the elapsed time in milliseconds since START.
289 The actual time may be cpu usage (preferred) or wall clock. */
290
291 unsigned long
292 sim_elapsed_time_since (SIM_ELAPSED_TIME start)
293 {
294 #ifdef HAVE_GETRUSAGE
295 return sim_elapsed_time_get () - start;
296 #else
297 #ifdef HAVE_TIME
298 return (sim_elapsed_time_get () - start) * 1000;
299 #else
300 return 0;
301 #endif
302 #endif
303 }
304
305
306
307 /* do_command but with printf style formatting of the arguments */
308 void
309 sim_do_commandf (SIM_DESC sd,
310 const char *fmt,
311 ...)
312 {
313 va_list ap;
314 char *buf;
315 int ret;
316
317 va_start (ap, fmt);
318 ret = vasprintf (&buf, fmt, ap);
319 va_end (ap);
320
321 if (ret < 0)
322 {
323 sim_io_eprintf (sd, "%s: asprintf failed for `%s'\n",
324 STATE_MY_NAME (sd), fmt);
325 return;
326 }
327
328 sim_do_command (sd, buf);
329 free (buf);
330 }
331
332
333 /* sim-basics.h defines a number of enumerations, convert each of them
334 to a string representation */
335 const char *
336 map_to_str (unsigned map)
337 {
338 switch (map)
339 {
340 case read_map: return "read";
341 case write_map: return "write";
342 case exec_map: return "exec";
343 case io_map: return "io";
344 default:
345 {
346 static char str[16];
347 snprintf (str, sizeof(str), "(%ld)", (long) map);
348 return str;
349 }
350 }
351 }
352
353 const char *
354 access_to_str (unsigned access)
355 {
356 switch (access)
357 {
358 case access_invalid: return "invalid";
359 case access_read: return "read";
360 case access_write: return "write";
361 case access_exec: return "exec";
362 case access_io: return "io";
363 case access_read_write: return "read_write";
364 case access_read_exec: return "read_exec";
365 case access_write_exec: return "write_exec";
366 case access_read_write_exec: return "read_write_exec";
367 case access_read_io: return "read_io";
368 case access_write_io: return "write_io";
369 case access_read_write_io: return "read_write_io";
370 case access_exec_io: return "exec_io";
371 case access_read_exec_io: return "read_exec_io";
372 case access_write_exec_io: return "write_exec_io";
373 case access_read_write_exec_io: return "read_write_exec_io";
374 default:
375 {
376 static char str[16];
377 snprintf (str, sizeof(str), "(%ld)", (long) access);
378 return str;
379 }
380 }
381 }
382
383 const char *
384 transfer_to_str (unsigned transfer)
385 {
386 switch (transfer)
387 {
388 case read_transfer: return "read";
389 case write_transfer: return "write";
390 default: return "(error)";
391 }
392 }