Commit | Line | Data |
---|---|---|
ba65b2f4 DE |
1 | /* Miscellaneous simulator utilities. |
2 | Copyright (C) 1997 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 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 | ||
56 | /* Allocate zero filled memory with xmalloc. */ | |
57 | ||
58 | void * | |
59 | zalloc (unsigned long size) | |
60 | { | |
61 | void *memory = (void *) xmalloc (size); | |
62 | memset (memory, 0, size); | |
63 | return memory; | |
64 | } | |
65 | ||
66 | void | |
67 | zfree (void *data) | |
68 | { | |
69 | free (data); | |
70 | } | |
71 | ||
72 | /* Allocate a sim_state struct. */ | |
73 | ||
74 | SIM_DESC | |
75 | sim_state_alloc (void) | |
76 | { | |
77 | SIM_DESC sd = zalloc (sizeof (struct sim_state)); | |
78 | sd->base.magic = SIM_MAGIC_NUMBER; | |
79 | return sd; | |
80 | } | |
81 | ||
82 | /* Free a sim_state struct. */ | |
83 | ||
84 | void | |
85 | sim_state_free (SIM_DESC sd) | |
86 | { | |
87 | ASSERT (sd->base.magic == SIM_MAGIC_NUMBER); | |
88 | zfree (sd); | |
89 | } | |
90 | ||
2317a499 DE |
91 | /* Turn VALUE into a string with commas. */ |
92 | ||
93 | char * | |
94 | sim_add_commas (char *buf, int sizeof_buf, unsigned long value) | |
95 | { | |
96 | int comma = 3; | |
97 | char *endbuf = buf + sizeof_buf - 1; | |
98 | ||
99 | *--endbuf = '\0'; | |
100 | do { | |
101 | if (comma-- == 0) | |
102 | { | |
103 | *--endbuf = ','; | |
104 | comma = 2; | |
105 | } | |
106 | ||
107 | *--endbuf = (value % 10) + '0'; | |
108 | } while ((value /= 10) != 0); | |
109 | ||
110 | return endbuf; | |
111 | } | |
112 | ||
fafce69a AC |
113 | /* Analyze a prog_name/prog_bfd and set various fields in the state |
114 | struct. */ | |
ba65b2f4 | 115 | |
fafce69a AC |
116 | SIM_RC |
117 | sim_analyze_program (sd, prog_name, prog_bfd) | |
ba65b2f4 | 118 | SIM_DESC sd; |
fafce69a | 119 | char *prog_name; |
ba65b2f4 DE |
120 | bfd *prog_bfd; |
121 | { | |
122 | asection *s; | |
d07dddd2 | 123 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); |
fafce69a AC |
124 | |
125 | if (prog_bfd != NULL) | |
126 | { | |
127 | if (prog_bfd == STATE_PROG_BFD (sd)) | |
128 | /* already analyzed */ | |
129 | return SIM_RC_OK; | |
130 | else | |
131 | /* duplicate needed, save the name of the file to be re-opened */ | |
132 | prog_name = bfd_get_filename (prog_bfd); | |
133 | } | |
134 | ||
135 | /* do we need to duplicate anything? */ | |
136 | if (prog_name == NULL) | |
137 | return SIM_RC_OK; | |
138 | ||
139 | /* open a new copy of the prog_bfd */ | |
18c319ae | 140 | prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd)); |
fafce69a AC |
141 | if (prog_bfd == NULL) |
142 | { | |
143 | sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n", | |
144 | STATE_MY_NAME (sd), | |
145 | prog_name, | |
146 | bfd_errmsg (bfd_get_error ())); | |
147 | return SIM_RC_FAIL; | |
148 | } | |
149 | if (!bfd_check_format (prog_bfd, bfd_object)) | |
150 | { | |
151 | sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n", | |
152 | STATE_MY_NAME (sd), | |
153 | prog_name, | |
154 | bfd_errmsg (bfd_get_error ())); | |
155 | bfd_close (prog_bfd); | |
156 | return SIM_RC_FAIL; | |
157 | } | |
18c319ae AC |
158 | if (STATE_ARCHITECTURE (sd) != NULL) |
159 | bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd)); | |
fafce69a AC |
160 | |
161 | /* update the sim structure */ | |
162 | if (STATE_PROG_BFD (sd) != NULL) | |
163 | bfd_close (STATE_PROG_BFD (sd)); | |
ba65b2f4 DE |
164 | STATE_PROG_BFD (sd) = prog_bfd; |
165 | STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd); | |
166 | ||
167 | for (s = prog_bfd->sections; s; s = s->next) | |
168 | if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) | |
169 | { | |
170 | STATE_TEXT_SECTION (sd) = s; | |
171 | STATE_TEXT_START (sd) = bfd_get_section_vma (prog_bfd, s); | |
172 | STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (prog_bfd, s); | |
173 | break; | |
174 | } | |
fafce69a AC |
175 | |
176 | return SIM_RC_OK; | |
ba65b2f4 | 177 | } |
2317a499 DE |
178 | \f |
179 | /* Simulator timing support. */ | |
180 | ||
181 | /* Called before sim_elapsed_time_since to get a reference point. */ | |
182 | ||
183 | SIM_ELAPSED_TIME | |
184 | sim_elapsed_time_get () | |
185 | { | |
186 | #ifdef HAVE_GETRUSAGE | |
187 | struct rusage mytime; | |
188 | if (getrusage (RUSAGE_SELF, &mytime) == 0) | |
189 | return (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000)); | |
190 | return 0; | |
191 | #else | |
192 | #ifdef HAVE_TIME | |
193 | return (SIM_ELAPSED_TIME) time ((time_t) 0); | |
194 | #else | |
195 | return 0; | |
196 | #endif | |
197 | #endif | |
198 | } | |
199 | ||
200 | /* Return the elapsed time in milliseconds since START. | |
201 | The actual time may be cpu usage (prefered) or wall clock. */ | |
202 | ||
203 | unsigned long | |
204 | sim_elapsed_time_since (start) | |
205 | SIM_ELAPSED_TIME start; | |
206 | { | |
207 | #ifdef HAVE_GETRUSAGE | |
208 | return sim_elapsed_time_get () - start; | |
209 | #else | |
210 | #ifdef HAVE_TIME | |
211 | return (sim_elapsed_time_get () - start) * 1000; | |
212 | #else | |
213 | return 0; | |
214 | #endif | |
215 | #endif | |
216 | } |