OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [common/] [sim-utils.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.