source: trunk/binutils/bfd/cisco-core.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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