Commit | Line | Data |
---|---|---|
ba65b2f4 | 1 | /* Miscellaneous simulator utilities. |
966df580 | 2 | Copyright (C) 1997, 1998 Free Software Foundation, Inc. |
ba65b2f4 DE |
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 2, or (at your option) | |
10 | 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 along | |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "sim-main.h" | |
22 | #include "sim-assert.h" | |
d07dddd2 | 23 | |
ba65b2f4 DE |
24 | #ifdef HAVE_STDLIB_H |
25 | #include <stdlib.h> | |
26 | #endif | |
d07dddd2 | 27 | |
2317a499 DE |
28 | #ifdef HAVE_TIME_H |
29 | #include <time.h> | |
30 | #endif | |
d07dddd2 | 31 | |
2317a499 DE |
32 | #ifdef HAVE_SYS_TIME_H |
33 | #include <sys/time.h> /* needed by sys/resource.h */ | |
34 | #endif | |
d07dddd2 | 35 | |
2317a499 DE |
36 | #ifdef HAVE_SYS_RESOURCE_H |
37 | #include <sys/resource.h> | |
38 | #endif | |
d07dddd2 AC |
39 | |
40 | #ifdef HAVE_STRING_H | |
41 | #include <string.h> | |
42 | #else | |
43 | #ifdef HAVE_STRINGS_H | |
44 | #include <strings.h> | |
45 | #endif | |
46 | #endif | |
47 | ||
ba65b2f4 DE |
48 | #include "libiberty.h" |
49 | #include "bfd.h" | |
d07dddd2 | 50 | #include "sim-utils.h" |
ba65b2f4 DE |
51 | |
52 | /* Global pointer to all state data. | |
53 | Set by sim_resume. */ | |
54 | struct sim_state *current_state; | |
55 | ||
4b2a6aed AC |
56 | /* Allocate zero filled memory with xmalloc - xmalloc aborts of the |
57 | allocation fails. */ | |
ba65b2f4 DE |
58 | |
59 | void * | |
60 | zalloc (unsigned long size) | |
61 | { | |
62 | void *memory = (void *) xmalloc (size); | |
63 | memset (memory, 0, size); | |
64 | return memory; | |
65 | } | |
66 | ||
67 | void | |
68 | zfree (void *data) | |
69 | { | |
70 | free (data); | |
71 | } | |
72 | ||
73 | /* Allocate a sim_state struct. */ | |
74 | ||
75 | SIM_DESC | |
4b2a6aed AC |
76 | sim_state_alloc (SIM_OPEN_KIND kind, |
77 | host_callback *callback) | |
ba65b2f4 | 78 | { |
4b2a6aed | 79 | SIM_DESC sd = ZALLOC (struct sim_state); |
7e13b934 | 80 | |
4b2a6aed AC |
81 | STATE_MAGIC (sd) = SIM_MAGIC_NUMBER; |
82 | STATE_CALLBACK (sd) = callback; | |
83 | STATE_OPEN_KIND (sd) = kind; | |
7e13b934 DE |
84 | |
85 | #if 0 | |
966df580 DE |
86 | { |
87 | int cpu_nr; | |
88 | ||
89 | /* Initialize the back link from the cpu struct to the state struct. */ | |
90 | /* ??? I can envision a design where the state struct contains an array | |
91 | of pointers to cpu structs, rather than an array of structs themselves. | |
92 | Implementing this is trickier as one may not know what to allocate until | |
93 | one has parsed the args. Parsing the args twice wouldn't be unreasonable, | |
94 | IMHO. If the state struct ever does contain an array of pointers then we | |
95 | can't do this here. */ | |
96 | for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) | |
97 | CPU_STATE (STATE_CPU (sd, cpu_nr)) = sd; | |
98 | } | |
7e13b934 DE |
99 | #endif |
100 | ||
101 | #ifdef SIM_STATE_INIT | |
102 | SIM_STATE_INIT (sd); | |
103 | #endif | |
104 | ||
ba65b2f4 DE |
105 | return sd; |
106 | } | |
107 | ||
108 | /* Free a sim_state struct. */ | |
109 | ||
110 | void | |
111 | sim_state_free (SIM_DESC sd) | |
112 | { | |
113 | ASSERT (sd->base.magic == SIM_MAGIC_NUMBER); | |
7e13b934 DE |
114 | |
115 | #ifdef SIM_STATE_FREE | |
116 | SIM_STATE_FREE (sd); | |
117 | #endif | |
118 | ||
ba65b2f4 DE |
119 | zfree (sd); |
120 | } | |
121 | ||
966df580 DE |
122 | /* Return a pointer to the cpu data for CPU_NAME, or NULL if not found. */ |
123 | ||
124 | sim_cpu * | |
125 | sim_cpu_lookup (SIM_DESC sd, const char *cpu_name) | |
126 | { | |
127 | int i; | |
128 | ||
129 | for (i = 0; i < MAX_NR_PROCESSORS; ++i) | |
130 | if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0) | |
131 | return STATE_CPU (sd, i); | |
132 | return NULL; | |
133 | } | |
134 | ||
2317a499 DE |
135 | /* Turn VALUE into a string with commas. */ |
136 | ||
137 | char * | |
138 | sim_add_commas (char *buf, int sizeof_buf, unsigned long value) | |
139 | { | |
140 | int comma = 3; | |
141 | char *endbuf = buf + sizeof_buf - 1; | |
142 | ||
143 | *--endbuf = '\0'; | |
144 | do { | |
145 | if (comma-- == 0) | |
146 | { | |
147 | *--endbuf = ','; | |
148 | comma = 2; | |
149 | } | |
150 | ||
151 | *--endbuf = (value % 10) + '0'; | |
152 | } while ((value /= 10) != 0); | |
153 | ||
154 | return endbuf; | |
155 | } | |
156 | ||
fafce69a AC |
157 | /* Analyze a prog_name/prog_bfd and set various fields in the state |
158 | struct. */ | |
ba65b2f4 | 159 | |
fafce69a AC |
160 | SIM_RC |
161 | sim_analyze_program (sd, prog_name, prog_bfd) | |
ba65b2f4 | 162 | SIM_DESC sd; |
fafce69a | 163 | char *prog_name; |
ba65b2f4 DE |
164 | bfd *prog_bfd; |
165 | { | |
166 | asection *s; | |
d07dddd2 | 167 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); |
fafce69a AC |
168 | |
169 | if (prog_bfd != NULL) | |
170 | { | |
171 | if (prog_bfd == STATE_PROG_BFD (sd)) | |
172 | /* already analyzed */ | |
173 | return SIM_RC_OK; | |
174 | else | |
175 | /* duplicate needed, save the name of the file to be re-opened */ | |
176 | prog_name = bfd_get_filename (prog_bfd); | |
177 | } | |
178 | ||
179 | /* do we need to duplicate anything? */ | |
180 | if (prog_name == NULL) | |
181 | return SIM_RC_OK; | |
182 | ||
183 | /* open a new copy of the prog_bfd */ | |
18c319ae | 184 | prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd)); |
fafce69a AC |
185 | if (prog_bfd == NULL) |
186 | { | |
187 | sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n", | |
188 | STATE_MY_NAME (sd), | |
189 | prog_name, | |
190 | bfd_errmsg (bfd_get_error ())); | |
191 | return SIM_RC_FAIL; | |
192 | } | |
193 | if (!bfd_check_format (prog_bfd, bfd_object)) | |
194 | { | |
195 | sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n", | |
196 | STATE_MY_NAME (sd), | |
197 | prog_name, | |
198 | bfd_errmsg (bfd_get_error ())); | |
199 | bfd_close (prog_bfd); | |
200 | return SIM_RC_FAIL; | |
201 | } | |
18c319ae AC |
202 | if (STATE_ARCHITECTURE (sd) != NULL) |
203 | bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd)); | |
7e13b934 DE |
204 | else |
205 | { | |
206 | if (bfd_get_arch (prog_bfd) != bfd_arch_unknown | |
207 | && bfd_get_arch (prog_bfd) != bfd_arch_obscure) | |
208 | { | |
209 | STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd); | |
210 | } | |
211 | } | |
fafce69a AC |
212 | |
213 | /* update the sim structure */ | |
214 | if (STATE_PROG_BFD (sd) != NULL) | |
215 | bfd_close (STATE_PROG_BFD (sd)); | |
ba65b2f4 DE |
216 | STATE_PROG_BFD (sd) = prog_bfd; |
217 | STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd); | |
218 | ||
219 | for (s = prog_bfd->sections; s; s = s->next) | |
220 | if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) | |
221 | { | |
222 | STATE_TEXT_SECTION (sd) = s; | |
223 | STATE_TEXT_START (sd) = bfd_get_section_vma (prog_bfd, s); | |
224 | STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (prog_bfd, s); | |
225 | break; | |
226 | } | |
fafce69a AC |
227 | |
228 | return SIM_RC_OK; | |
ba65b2f4 | 229 | } |
2317a499 DE |
230 | \f |
231 | /* Simulator timing support. */ | |
232 | ||
233 | /* Called before sim_elapsed_time_since to get a reference point. */ | |
234 | ||
235 | SIM_ELAPSED_TIME | |
236 | sim_elapsed_time_get () | |
237 | { | |
238 | #ifdef HAVE_GETRUSAGE | |
239 | struct rusage mytime; | |
240 | if (getrusage (RUSAGE_SELF, &mytime) == 0) | |
a34abff8 AC |
241 | return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000)); |
242 | return 1; | |
2317a499 DE |
243 | #else |
244 | #ifdef HAVE_TIME | |
a34abff8 | 245 | return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0); |
2317a499 | 246 | #else |
a34abff8 | 247 | return 1; |
2317a499 DE |
248 | #endif |
249 | #endif | |
250 | } | |
251 | ||
252 | /* Return the elapsed time in milliseconds since START. | |
253 | The actual time may be cpu usage (prefered) or wall clock. */ | |
254 | ||
255 | unsigned long | |
256 | sim_elapsed_time_since (start) | |
257 | SIM_ELAPSED_TIME start; | |
258 | { | |
259 | #ifdef HAVE_GETRUSAGE | |
260 | return sim_elapsed_time_get () - start; | |
261 | #else | |
262 | #ifdef HAVE_TIME | |
263 | return (sim_elapsed_time_get () - start) * 1000; | |
264 | #else | |
265 | return 0; | |
266 | #endif | |
267 | #endif | |
268 | } | |
1b465b54 AC |
269 | |
270 | ||
271 | ||
272 | /* do_command but with printf style formatting of the arguments */ | |
273 | void | |
274 | sim_do_commandf (SIM_DESC sd, | |
275 | const char *fmt, | |
276 | ...) | |
277 | { | |
278 | va_list ap; | |
279 | char *buf; | |
280 | va_start (ap, fmt); | |
281 | vasprintf (&buf, fmt, ap); | |
282 | sim_do_command (sd, buf); | |
283 | va_end (ap); | |
284 | free (buf); | |
285 | } |