xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/common/sim-utils.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Miscellaneous simulator utilities.
2    Copyright (C) 1997-2023 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 <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #ifdef HAVE_SYS_RESOURCE_H
28 #include <sys/resource.h>
29 #endif
30 #include <sys/time.h> /* needed by sys/resource.h */
31 
32 #include "bfd.h"
33 #include "libiberty.h"
34 
35 #include "sim-main.h"
36 #include "sim-assert.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 (STATE_PROG_FILE (sd));
102   free (STATE_PROG_ARGV0 (sd));
103   freeargv (STATE_PROG_ENVP (sd));
104   free (sd);
105 }
106 
107 /* Return a pointer to the cpu data for CPU_NAME, or NULL if not found.  */
108 
109 sim_cpu *
110 sim_cpu_lookup (SIM_DESC sd, const char *cpu_name)
111 {
112   int i;
113 
114   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
115     if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0)
116       return STATE_CPU (sd, i);
117   return NULL;
118 }
119 
120 /* Return the prefix to use for a CPU specific message (typically an
121    error message).  */
122 
123 const char *
124 sim_cpu_msg_prefix (sim_cpu *cpu)
125 {
126 #if MAX_NR_PROCESSORS == 1
127   return "";
128 #else
129   static char *prefix;
130 
131   if (prefix == NULL)
132     {
133       int maxlen = 0;
134       for (i = 0; i < MAX_NR_PROCESSORS; ++i)
135 	{
136 	  int len = strlen (CPU_NAME (STATE_CPU (sd, i)));
137 	  if (len > maxlen)
138 	    maxlen = len;
139 	}
140       prefix = (char *) xmalloc (maxlen + 5);
141     }
142   sprintf (prefix, "%s: ", CPU_NAME (cpu));
143   return prefix;
144 #endif
145 }
146 
147 /* Cover fn to sim_io_eprintf.  */
148 
149 void
150 sim_io_eprintf_cpu (sim_cpu *cpu, const char *fmt, ...)
151 {
152   SIM_DESC sd = CPU_STATE (cpu);
153   va_list ap;
154 
155   va_start (ap, fmt);
156   sim_io_eprintf (sd, "%s", sim_cpu_msg_prefix (cpu));
157   sim_io_evprintf (sd, fmt, ap);
158   va_end (ap);
159 }
160 
161 /* Turn VALUE into a string with commas.  */
162 
163 char *
164 sim_add_commas (char *buf, int sizeof_buf, unsigned long value)
165 {
166   int comma = 3;
167   char *endbuf = buf + sizeof_buf - 1;
168 
169   *--endbuf = '\0';
170   do {
171     if (comma-- == 0)
172       {
173 	*--endbuf = ',';
174 	comma = 2;
175       }
176 
177     *--endbuf = (value % 10) + '0';
178   } while ((value /= 10) != 0);
179 
180   return endbuf;
181 }
182 
183 /* Analyze PROG_NAME/PROG_BFD and set these fields in the state struct:
184    STATE_ARCHITECTURE, if not set already and can be determined from the bfd
185    STATE_PROG_BFD
186    STATE_START_ADDR
187    STATE_TEXT_SECTION
188    STATE_TEXT_START
189    STATE_TEXT_END
190 
191    PROG_NAME is the file name of the executable or NULL.
192    PROG_BFD is its bfd or NULL.
193 
194    If both PROG_NAME and PROG_BFD are NULL, this function returns immediately.
195    If PROG_BFD is not NULL, PROG_NAME is ignored.
196 
197    Implicit inputs: STATE_MY_NAME(sd), STATE_TARGET(sd),
198                     STATE_ARCHITECTURE(sd).
199 
200    A new bfd is created so the app isn't required to keep its copy of the
201    bfd open.  */
202 
203 SIM_RC
204 sim_analyze_program (SIM_DESC sd, const char *prog_name, bfd *prog_bfd)
205 {
206   asection *s;
207   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
208 
209   if (prog_bfd != NULL)
210     {
211       if (prog_bfd == STATE_PROG_BFD (sd))
212 	/* already analyzed */
213 	return SIM_RC_OK;
214       else
215 	/* duplicate needed, save the name of the file to be re-opened */
216 	prog_name = bfd_get_filename (prog_bfd);
217     }
218 
219   /* do we need to duplicate anything? */
220   if (prog_name == NULL)
221     return SIM_RC_OK;
222 
223   /* open a new copy of the prog_bfd */
224   prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd));
225   if (prog_bfd == NULL)
226     {
227       sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n",
228 		      STATE_MY_NAME (sd),
229 		      prog_name,
230 		      bfd_errmsg (bfd_get_error ()));
231       return SIM_RC_FAIL;
232     }
233   if (!bfd_check_format (prog_bfd, bfd_object))
234     {
235       sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n",
236 		      STATE_MY_NAME (sd),
237 		      prog_name,
238 		      bfd_errmsg (bfd_get_error ()));
239       bfd_close (prog_bfd);
240       return SIM_RC_FAIL;
241     }
242   if (STATE_ARCHITECTURE (sd) != NULL)
243     bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd));
244   else
245     {
246       if (bfd_get_arch (prog_bfd) != bfd_arch_unknown
247 	  && bfd_get_arch (prog_bfd) != bfd_arch_obscure)
248 	{
249 	  STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd);
250 	}
251     }
252 
253   /* update the sim structure */
254   if (STATE_PROG_BFD (sd) != NULL)
255     bfd_close (STATE_PROG_BFD (sd));
256   STATE_PROG_BFD (sd) = prog_bfd;
257   STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd);
258 
259   for (s = prog_bfd->sections; s; s = s->next)
260     if (strcmp (bfd_section_name (s), ".text") == 0)
261       {
262 	STATE_TEXT_SECTION (sd) = s;
263 	STATE_TEXT_START (sd) = bfd_section_vma (s);
264 	STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (s);
265 	break;
266       }
267 
268   bfd_cache_close (prog_bfd);
269 
270   return SIM_RC_OK;
271 }
272 
273 /* Simulator timing support.  */
274 
275 /* Called before sim_elapsed_time_since to get a reference point.  */
276 
277 SIM_ELAPSED_TIME
278 sim_elapsed_time_get (void)
279 {
280 #ifdef HAVE_GETRUSAGE
281   struct rusage mytime;
282   if (getrusage (RUSAGE_SELF, &mytime) == 0)
283     return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000));
284   return 1;
285 #else
286 #ifdef HAVE_TIME
287   return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0);
288 #else
289   return 1;
290 #endif
291 #endif
292 }
293 
294 /* Return the elapsed time in milliseconds since START.
295    The actual time may be cpu usage (preferred) or wall clock.  */
296 
297 unsigned long
298 sim_elapsed_time_since (SIM_ELAPSED_TIME start)
299 {
300 #ifdef HAVE_GETRUSAGE
301   return sim_elapsed_time_get () - start;
302 #else
303 #ifdef HAVE_TIME
304   return (sim_elapsed_time_get () - start) * 1000;
305 #else
306   return 0;
307 #endif
308 #endif
309 }
310 
311 
312 
313 /* do_command but with printf style formatting of the arguments */
314 void
315 sim_do_commandf (SIM_DESC sd,
316 		 const char *fmt,
317 		 ...)
318 {
319   va_list ap;
320   char *buf;
321   int ret;
322 
323   va_start (ap, fmt);
324   ret = vasprintf (&buf, fmt, ap);
325   va_end (ap);
326 
327   if (ret < 0)
328     {
329       sim_io_eprintf (sd, "%s: asprintf failed for `%s'\n",
330 		      STATE_MY_NAME (sd), fmt);
331       return;
332     }
333 
334   sim_do_command (sd, buf);
335   free (buf);
336 }
337 
338 
339 /* sim-basics.h defines a number of enumerations, convert each of them
340    to a string representation */
341 const char *
342 map_to_str (unsigned map)
343 {
344   switch (map)
345     {
346     case read_map: return "read";
347     case write_map: return "write";
348     case exec_map: return "exec";
349     case io_map: return "io";
350     default:
351       {
352 	static char str[16];
353 	snprintf (str, sizeof(str), "(%ld)", (long) map);
354 	return str;
355       }
356     }
357 }
358 
359 const char *
360 access_to_str (unsigned access)
361 {
362   switch (access)
363     {
364     case access_invalid: return "invalid";
365     case access_read: return "read";
366     case access_write: return "write";
367     case access_exec: return "exec";
368     case access_io: return "io";
369     case access_read_write: return "read_write";
370     case access_read_exec: return "read_exec";
371     case access_write_exec: return "write_exec";
372     case access_read_write_exec: return "read_write_exec";
373     case access_read_io: return "read_io";
374     case access_write_io: return "write_io";
375     case access_read_write_io: return "read_write_io";
376     case access_exec_io: return "exec_io";
377     case access_read_exec_io: return "read_exec_io";
378     case access_write_exec_io: return "write_exec_io";
379     case access_read_write_exec_io: return "read_write_exec_io";
380     default:
381       {
382 	static char str[16];
383 	snprintf (str, sizeof(str), "(%ld)", (long) access);
384 	return str;
385       }
386     }
387 }
388 
389 const char *
390 transfer_to_str (unsigned transfer)
391 {
392   switch (transfer)
393     {
394     case read_transfer: return "read";
395     case write_transfer: return "write";
396     default: return "(error)";
397     }
398 }
399