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