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