~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/cisco-core.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* BFD back-end for CISCO crash dumps.
 
2
   Copyright 1994, 1997, 1999, 2000, 2001, 2002
 
3
   Free Software Foundation, Inc.
 
4
 
 
5
This file is part of BFD, the Binary File Descriptor library.
 
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 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, write to the Free Software
 
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
20
 
 
21
#include "bfd.h"
 
22
#include "sysdep.h"
 
23
#include "libbfd.h"
 
24
/* core_file_failing_signal returns a host signal (this probably should
 
25
   be fixed).  */
 
26
#include <signal.h>
 
27
 
 
28
/* for MSVC builds */
 
29
#ifndef SIGTRAP
 
30
# define SIGTRAP 5
 
31
#endif
 
32
#ifndef SIGEMT
 
33
# define SIGEMT 6
 
34
#endif
 
35
#ifndef SIGBUS
 
36
# define SIGBUS 10
 
37
#endif
 
38
 
 
39
int crash_info_locs[] = {
 
40
  0x0250,       /* mips, ppc, x86, i960 */
 
41
  0x0400,       /* m68k, mips, x86, i960 */
 
42
  0x0FFC,       /* m68k, mips, ppc, x86, i960 */
 
43
  0x3000,       /* ppc */
 
44
  0x4FFC,       /* m68k */
 
45
  -1
 
46
};
 
47
 
 
48
#define CRASH_MAGIC     0xdead1234
 
49
#define MASK_ADDR(x)    ((x) & 0x0fffffff)      /* Mask crash info address */
 
50
 
 
51
typedef enum {
 
52
    CRASH_REASON_NOTCRASHED = 0,
 
53
    CRASH_REASON_EXCEPTION = 1,
 
54
    CRASH_REASON_CORRUPT = 2,
 
55
} crashreason;
 
56
 
 
57
typedef struct {
 
58
  char magic[4];                /* Magic number */
 
59
  char version[4];              /* Version number */
 
60
  char reason[4];               /* Crash reason */
 
61
  char cpu_vector[4];           /* CPU vector for exceptions */
 
62
  char registers[4];            /* Pointer to saved registers */
 
63
  char rambase[4];              /* Base of RAM (not in V1 crash info) */
 
64
  char textbase[4];             /* Base of .text section (not in V3 crash info) */
 
65
  char database[4];             /* Base of .data section (not in V3 crash info) */
 
66
  char bssbase[4];              /* Base of .bss section (not in V3 crash info) */
 
67
} crashinfo_external;
 
68
 
 
69
struct cisco_core_struct
 
70
{
 
71
  int sig;
 
72
};
 
73
 
 
74
static const bfd_target *cisco_core_file_validate PARAMS ((bfd *, int));
 
75
static const bfd_target *cisco_core_file_p PARAMS ((bfd *));
 
76
char *cisco_core_file_failing_command PARAMS ((bfd *));
 
77
int cisco_core_file_failing_signal PARAMS ((bfd *));
 
78
boolean cisco_core_file_matches_executable_p PARAMS ((bfd *, bfd *));
 
79
 
 
80
/* Examine the file for a crash info struct at the offset given by
 
81
   CRASH_INFO_LOC.  */
 
82
 
 
83
static const bfd_target *
 
84
cisco_core_file_validate (abfd, crash_info_loc)
 
85
     bfd *abfd;
 
86
     int crash_info_loc;
 
87
{
 
88
  char buf[4];
 
89
  unsigned int crashinfo_offset;
 
90
  crashinfo_external crashinfo;
 
91
  int nread;
 
92
  unsigned int magic;
 
93
  unsigned int version;
 
94
  unsigned int rambase;
 
95
  sec_ptr asect;
 
96
  struct stat statbuf;
 
97
  bfd_size_type amt;
 
98
 
 
99
  if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
 
100
    return NULL;
 
101
 
 
102
  nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
 
103
  if (nread != 4)
 
104
    {
 
105
      if (bfd_get_error () != bfd_error_system_call)
 
106
        bfd_set_error (bfd_error_wrong_format);
 
107
      return NULL;
 
108
    }
 
109
  crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));
 
110
 
 
111
  if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
 
112
    {
 
113
      /* Most likely we failed because of a bogus (huge) offset */
 
114
      bfd_set_error (bfd_error_wrong_format);
 
115
      return NULL;
 
116
    }
 
117
 
 
118
  nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
 
119
  if (nread != sizeof (crashinfo))
 
120
    {
 
121
      if (bfd_get_error () != bfd_error_system_call)
 
122
        bfd_set_error (bfd_error_wrong_format);
 
123
      return NULL;
 
124
    }
 
125
 
 
126
  if (bfd_stat (abfd, &statbuf) < 0)
 
127
    {
 
128
      bfd_set_error (bfd_error_system_call);
 
129
      return NULL;
 
130
    }
 
131
 
 
132
  magic = bfd_get_32 (abfd, crashinfo.magic);
 
133
  if (magic != CRASH_MAGIC)
 
134
    {
 
135
      bfd_set_error (bfd_error_wrong_format);
 
136
      return NULL;
 
137
    }
 
138
 
 
139
  version = bfd_get_32 (abfd, crashinfo.version);
 
140
  if (version == 0)
 
141
    {
 
142
      bfd_set_error (bfd_error_wrong_format);
 
143
      return NULL;
 
144
    }
 
145
  else if (version == 1)
 
146
    {
 
147
      /* V1 core dumps don't specify the dump base, assume 0 */
 
148
      rambase = 0;
 
149
    }
 
150
  else
 
151
    {
 
152
      rambase = bfd_get_32 (abfd, crashinfo.rambase);
 
153
    }
 
154
 
 
155
  /* OK, we believe you.  You're a core file.  */
 
156
 
 
157
  amt = sizeof (struct cisco_core_struct);
 
158
  abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
 
159
  if (abfd->tdata.cisco_core_data == NULL)
 
160
    return NULL;
 
161
 
 
162
  switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
 
163
    {
 
164
    case CRASH_REASON_NOTCRASHED:
 
165
      /* Crash file probably came from write core.  */
 
166
      abfd->tdata.cisco_core_data->sig = 0;
 
167
      break;
 
168
    case CRASH_REASON_CORRUPT:
 
169
      /* The crash context area was corrupt -- proceed with caution.
 
170
         We have no way of passing this information back to the caller.  */
 
171
      abfd->tdata.cisco_core_data->sig = 0;
 
172
      break;
 
173
    case CRASH_REASON_EXCEPTION:
 
174
      /* Crash occured due to CPU exception.  */
 
175
 
 
176
      /* This is 68k-specific; for MIPS we'll need to interpret
 
177
         cpu_vector differently based on the target configuration
 
178
         (since CISCO core files don't seem to have the processor
 
179
         encoded in them).  */
 
180
 
 
181
      switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
 
182
        {
 
183
           /* bus error           */
 
184
        case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
 
185
           /* address error       */
 
186
        case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
 
187
           /* illegal instruction */
 
188
        case 4 : abfd->tdata.cisco_core_data->sig = SIGILL;  break;
 
189
           /* zero divide         */
 
190
        case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
191
           /* chk instruction     */
 
192
        case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
 
193
           /* trapv instruction   */
 
194
        case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
 
195
           /* privilege violation */
 
196
        case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
 
197
           /* trace trap          */
 
198
        case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;
 
199
           /* line 1010 emulator  */
 
200
        case 10: abfd->tdata.cisco_core_data->sig = SIGILL;  break;
 
201
           /* line 1111 emulator  */
 
202
        case 11: abfd->tdata.cisco_core_data->sig = SIGILL;  break;
 
203
 
 
204
          /* Coprocessor protocol violation.  Using a standard MMU or FPU
 
205
             this cannot be triggered by software.  Call it a SIGBUS.  */
 
206
        case 13: abfd->tdata.cisco_core_data->sig = SIGBUS;  break;
 
207
 
 
208
          /* interrupt           */
 
209
        case 31: abfd->tdata.cisco_core_data->sig = SIGINT;  break;
 
210
          /* breakpoint          */
 
211
        case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;
 
212
 
 
213
          /* floating point err  */
 
214
        case 48: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
215
          /* floating point err  */
 
216
        case 49: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
217
          /* zero divide         */
 
218
        case 50: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
219
          /* underflow           */
 
220
        case 51: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
221
          /* operand error       */
 
222
        case 52: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
223
           /* overflow            */
 
224
        case 53: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
225
          /* NAN                 */
 
226
        case 54: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
 
227
        default:
 
228
#ifndef SIGEMT
 
229
#define SIGEMT SIGTRAP
 
230
#endif
 
231
          /* "software generated"*/
 
232
          abfd->tdata.cisco_core_data->sig = SIGEMT;
 
233
        }
 
234
      break;
 
235
    default:
 
236
      /* Unknown crash reason.  */
 
237
      abfd->tdata.cisco_core_data->sig = 0;
 
238
      break;
 
239
    }
 
240
 
 
241
  /* Create a ".data" section that maps the entire file, which is
 
242
     essentially a dump of the target system's RAM.  */
 
243
 
 
244
  asect = bfd_make_section_anyway (abfd, ".data");
 
245
  if (asect == NULL)
 
246
    goto error_return;
 
247
  asect->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
 
248
  /* The size of memory is the size of the core file itself.  */
 
249
  asect->_raw_size = statbuf.st_size;
 
250
  asect->vma = rambase;
 
251
  asect->filepos = 0;
 
252
 
 
253
  /* Create a ".crash" section to allow access to the saved
 
254
     crash information.  */
 
255
 
 
256
  asect = bfd_make_section_anyway (abfd, ".crash");
 
257
  if (asect == NULL)
 
258
    goto error_return;
 
259
  asect->flags = SEC_HAS_CONTENTS;
 
260
  asect->vma = 0;
 
261
  asect->filepos = crashinfo_offset;
 
262
  asect->_raw_size = sizeof (crashinfo);
 
263
 
 
264
  /* Create a ".reg" section to allow access to the saved
 
265
     registers.  */
 
266
 
 
267
  asect = bfd_make_section_anyway (abfd, ".reg");
 
268
  if (asect == NULL)
 
269
    goto error_return;
 
270
  asect->flags = SEC_HAS_CONTENTS;
 
271
  asect->vma = 0;
 
272
  asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
 
273
  /* Since we don't know the exact size of the saved register info,
 
274
     choose a register section size that is either the remaining part
 
275
     of the file, or 1024, whichever is smaller.  */
 
276
  nread = statbuf.st_size - asect->filepos;
 
277
  asect->_raw_size = (nread < 1024) ? nread : 1024;
 
278
 
 
279
  return abfd->xvec;
 
280
 
 
281
  /* Get here if we have already started filling out the BFD
 
282
     and there is an error of some kind.  */
 
283
 
 
284
 error_return:
 
285
  bfd_release (abfd, abfd->tdata.any);
 
286
  abfd->tdata.any = NULL;
 
287
  bfd_section_list_clear (abfd);
 
288
  return NULL;
 
289
}
 
290
 
 
291
static const bfd_target *
 
292
cisco_core_file_p (abfd)
 
293
     bfd *abfd;
 
294
{
 
295
  int *crash_info_locp;
 
296
  const bfd_target *target = NULL;
 
297
 
 
298
  for (crash_info_locp = crash_info_locs;
 
299
       *crash_info_locp != -1  &&  target == NULL;
 
300
       crash_info_locp++)
 
301
    {
 
302
      target = cisco_core_file_validate (abfd, *crash_info_locp);
 
303
    }
 
304
  return (target);
 
305
}
 
306
 
 
307
char *
 
308
cisco_core_file_failing_command (abfd)
 
309
     bfd *abfd ATTRIBUTE_UNUSED;
 
310
{
 
311
  return NULL;
 
312
}
 
313
 
 
314
int
 
315
cisco_core_file_failing_signal (abfd)
 
316
     bfd *abfd ATTRIBUTE_UNUSED;
 
317
{
 
318
  return abfd->tdata.cisco_core_data->sig;
 
319
}
 
320
 
 
321
boolean
 
322
cisco_core_file_matches_executable_p (core_bfd, exec_bfd)
 
323
     bfd *core_bfd ATTRIBUTE_UNUSED;
 
324
     bfd *exec_bfd ATTRIBUTE_UNUSED;
 
325
{
 
326
  return true;
 
327
}
 
328
 
 
329
extern const bfd_target cisco_core_little_vec;
 
330
 
 
331
const bfd_target cisco_core_big_vec =
 
332
  {
 
333
    "cisco-ios-core-big",
 
334
    bfd_target_unknown_flavour,
 
335
    BFD_ENDIAN_BIG,             /* target byte order */
 
336
    BFD_ENDIAN_BIG,             /* target headers byte order */
 
337
    (HAS_RELOC | EXEC_P |       /* object flags */
 
338
     HAS_LINENO | HAS_DEBUG |
 
339
     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
 
340
    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
 
341
    0,                                                     /* symbol prefix */
 
342
    ' ',                                                   /* ar_pad_char */
 
343
    16,                                                    /* ar_max_namelen */
 
344
    bfd_getb64, bfd_getb_signed_64, bfd_putb64,
 
345
    bfd_getb32, bfd_getb_signed_32, bfd_putb32,
 
346
    bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
 
347
    bfd_getb64, bfd_getb_signed_64, bfd_putb64,
 
348
    bfd_getb32, bfd_getb_signed_32, bfd_putb32,
 
349
    bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
 
350
 
 
351
    {                           /* bfd_check_format */
 
352
     _bfd_dummy_target,         /* unknown format */
 
353
     _bfd_dummy_target,         /* object file */
 
354
     _bfd_dummy_target,         /* archive */
 
355
     cisco_core_file_p  /* a core file */
 
356
    },
 
357
    {                           /* bfd_set_format */
 
358
     bfd_false, bfd_false,
 
359
     bfd_false, bfd_false
 
360
    },
 
361
    {                           /* bfd_write_contents */
 
362
     bfd_false, bfd_false,
 
363
     bfd_false, bfd_false
 
364
    },
 
365
 
 
366
       BFD_JUMP_TABLE_GENERIC (_bfd_generic),
 
367
       BFD_JUMP_TABLE_COPY (_bfd_generic),
 
368
       BFD_JUMP_TABLE_CORE (cisco),
 
369
       BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
 
370
       BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
 
371
       BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
 
372
       BFD_JUMP_TABLE_WRITE (_bfd_generic),
 
373
       BFD_JUMP_TABLE_LINK (_bfd_nolink),
 
374
       BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
 
375
 
 
376
    & cisco_core_little_vec,
 
377
 
 
378
    (PTR) 0                     /* backend_data */
 
379
};
 
380
 
 
381
const bfd_target cisco_core_little_vec =
 
382
  {
 
383
    "cisco-ios-core-little",
 
384
    bfd_target_unknown_flavour,
 
385
    BFD_ENDIAN_LITTLE,          /* target byte order */
 
386
    BFD_ENDIAN_LITTLE,          /* target headers byte order */
 
387
    (HAS_RELOC | EXEC_P |       /* object flags */
 
388
     HAS_LINENO | HAS_DEBUG |
 
389
     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
 
390
    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
 
391
    0,                                                     /* symbol prefix */
 
392
    ' ',                                                   /* ar_pad_char */
 
393
    16,                                                    /* ar_max_namelen */
 
394
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
 
395
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
 
396
    bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
 
397
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
 
398
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
 
399
    bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
 
400
 
 
401
    {                           /* bfd_check_format */
 
402
     _bfd_dummy_target,         /* unknown format */
 
403
     _bfd_dummy_target,         /* object file */
 
404
     _bfd_dummy_target,         /* archive */
 
405
     cisco_core_file_p  /* a core file */
 
406
    },
 
407
    {                           /* bfd_set_format */
 
408
     bfd_false, bfd_false,
 
409
     bfd_false, bfd_false
 
410
    },
 
411
    {                           /* bfd_write_contents */
 
412
     bfd_false, bfd_false,
 
413
     bfd_false, bfd_false
 
414
    },
 
415
 
 
416
       BFD_JUMP_TABLE_GENERIC (_bfd_generic),
 
417
       BFD_JUMP_TABLE_COPY (_bfd_generic),
 
418
       BFD_JUMP_TABLE_CORE (cisco),
 
419
       BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
 
420
       BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
 
421
       BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
 
422
       BFD_JUMP_TABLE_WRITE (_bfd_generic),
 
423
       BFD_JUMP_TABLE_LINK (_bfd_nolink),
 
424
       BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
 
425
 
 
426
    &cisco_core_big_vec,
 
427
 
 
428
    (PTR) 0                     /* backend_data */
 
429
};