1 /* BFD back-end for CISCO crash dumps.
2 Copyright 1994, 1997, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007,
4 Free Software Foundation, Inc.
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
26 /* core_file_failing_signal returns a host signal (this probably should
41 int crash_info_locs
[] = {
42 0x0250, /* mips, ppc, x86, i960 */
43 0x0400, /* m68k, mips, x86, i960 */
44 0x0FFC, /* m68k, mips, ppc, x86, i960 */
50 #define CRASH_MAGIC 0xdead1234
51 #define MASK_ADDR(x) ((x) & 0x0fffffff) /* Mask crash info address */
54 CRASH_REASON_NOTCRASHED
= 0,
55 CRASH_REASON_EXCEPTION
= 1,
56 CRASH_REASON_CORRUPT
= 2,
60 char magic
[4]; /* Magic number */
61 char version
[4]; /* Version number */
62 char reason
[4]; /* Crash reason */
63 char cpu_vector
[4]; /* CPU vector for exceptions */
64 char registers
[4]; /* Pointer to saved registers */
65 char rambase
[4]; /* Base of RAM (not in V1 crash info) */
66 char textbase
[4]; /* Base of .text section (not in V3 crash info) */
67 char database
[4]; /* Base of .data section (not in V3 crash info) */
68 char bssbase
[4]; /* Base of .bss section (not in V3 crash info) */
71 struct cisco_core_struct
76 static const bfd_target
*cisco_core_file_validate
PARAMS ((bfd
*, int));
77 static const bfd_target
*cisco_core_file_p
PARAMS ((bfd
*));
78 char *cisco_core_file_failing_command
PARAMS ((bfd
*));
79 int cisco_core_file_failing_signal
PARAMS ((bfd
*));
80 #define cisco_core_file_matches_executable_p generic_core_file_matches_executable_p
81 #define cisco_core_file_pid _bfd_nocore_core_file_pid
83 /* Examine the file for a crash info struct at the offset given by
86 static const bfd_target
*
87 cisco_core_file_validate (abfd
, crash_info_loc
)
92 unsigned int crashinfo_offset
;
93 crashinfo_external crashinfo
;
103 if (bfd_seek (abfd
, (file_ptr
) crash_info_loc
, SEEK_SET
) != 0)
106 nread
= bfd_bread (buf
, (bfd_size_type
) 4, abfd
);
109 if (bfd_get_error () != bfd_error_system_call
)
110 bfd_set_error (bfd_error_wrong_format
);
113 crashinfo_offset
= MASK_ADDR (bfd_get_32 (abfd
, buf
));
115 if (bfd_seek (abfd
, (file_ptr
) crashinfo_offset
, SEEK_SET
) != 0)
117 /* Most likely we failed because of a bogus (huge) offset */
118 bfd_set_error (bfd_error_wrong_format
);
122 nread
= bfd_bread (&crashinfo
, (bfd_size_type
) sizeof (crashinfo
), abfd
);
123 if (nread
!= sizeof (crashinfo
))
125 if (bfd_get_error () != bfd_error_system_call
)
126 bfd_set_error (bfd_error_wrong_format
);
130 if (bfd_stat (abfd
, &statbuf
) < 0)
132 bfd_set_error (bfd_error_system_call
);
136 magic
= bfd_get_32 (abfd
, crashinfo
.magic
);
137 if (magic
!= CRASH_MAGIC
)
139 bfd_set_error (bfd_error_wrong_format
);
143 version
= bfd_get_32 (abfd
, crashinfo
.version
);
146 bfd_set_error (bfd_error_wrong_format
);
149 else if (version
== 1)
151 /* V1 core dumps don't specify the dump base, assume 0 */
156 rambase
= bfd_get_32 (abfd
, crashinfo
.rambase
);
159 /* OK, we believe you. You're a core file. */
161 amt
= sizeof (struct cisco_core_struct
);
162 abfd
->tdata
.cisco_core_data
= (struct cisco_core_struct
*) bfd_zmalloc (amt
);
163 if (abfd
->tdata
.cisco_core_data
== NULL
)
166 switch ((crashreason
) bfd_get_32 (abfd
, crashinfo
.reason
))
168 case CRASH_REASON_NOTCRASHED
:
169 /* Crash file probably came from write core. */
170 abfd
->tdata
.cisco_core_data
->sig
= 0;
172 case CRASH_REASON_CORRUPT
:
173 /* The crash context area was corrupt -- proceed with caution.
174 We have no way of passing this information back to the caller. */
175 abfd
->tdata
.cisco_core_data
->sig
= 0;
177 case CRASH_REASON_EXCEPTION
:
178 /* Crash occured due to CPU exception. */
180 /* This is 68k-specific; for MIPS we'll need to interpret
181 cpu_vector differently based on the target configuration
182 (since CISCO core files don't seem to have the processor
185 switch (bfd_get_32 (abfd
, crashinfo
.cpu_vector
))
188 case 2 : abfd
->tdata
.cisco_core_data
->sig
= SIGBUS
; break;
190 case 3 : abfd
->tdata
.cisco_core_data
->sig
= SIGBUS
; break;
191 /* illegal instruction */
192 case 4 : abfd
->tdata
.cisco_core_data
->sig
= SIGILL
; break;
194 case 5 : abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
195 /* chk instruction */
196 case 6 : abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
197 /* trapv instruction */
198 case 7 : abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
199 /* privilege violation */
200 case 8 : abfd
->tdata
.cisco_core_data
->sig
= SIGSEGV
; break;
202 case 9 : abfd
->tdata
.cisco_core_data
->sig
= SIGTRAP
; break;
203 /* line 1010 emulator */
204 case 10: abfd
->tdata
.cisco_core_data
->sig
= SIGILL
; break;
205 /* line 1111 emulator */
206 case 11: abfd
->tdata
.cisco_core_data
->sig
= SIGILL
; break;
208 /* Coprocessor protocol violation. Using a standard MMU or FPU
209 this cannot be triggered by software. Call it a SIGBUS. */
210 case 13: abfd
->tdata
.cisco_core_data
->sig
= SIGBUS
; break;
213 case 31: abfd
->tdata
.cisco_core_data
->sig
= SIGINT
; break;
215 case 33: abfd
->tdata
.cisco_core_data
->sig
= SIGTRAP
; break;
217 /* floating point err */
218 case 48: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
219 /* floating point err */
220 case 49: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
222 case 50: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
224 case 51: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
226 case 52: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
228 case 53: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
230 case 54: abfd
->tdata
.cisco_core_data
->sig
= SIGFPE
; break;
233 #define SIGEMT SIGTRAP
235 /* "software generated"*/
236 abfd
->tdata
.cisco_core_data
->sig
= SIGEMT
;
240 /* Unknown crash reason. */
241 abfd
->tdata
.cisco_core_data
->sig
= 0;
245 /* Create a ".data" section that maps the entire file, which is
246 essentially a dump of the target system's RAM. */
248 flags
= SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
;
249 asect
= bfd_make_section_anyway_with_flags (abfd
, ".data", flags
);
252 /* The size of memory is the size of the core file itself. */
253 asect
->size
= statbuf
.st_size
;
254 asect
->vma
= rambase
;
257 /* Create a ".crash" section to allow access to the saved
258 crash information. */
260 flags
= SEC_HAS_CONTENTS
;
261 asect
= bfd_make_section_anyway_with_flags (abfd
, ".crash", flags
);
265 asect
->filepos
= crashinfo_offset
;
266 asect
->size
= sizeof (crashinfo
);
268 /* Create a ".reg" section to allow access to the saved
271 asect
= bfd_make_section_anyway_with_flags (abfd
, ".reg", flags
);
275 asect
->filepos
= bfd_get_32 (abfd
, crashinfo
.registers
) - rambase
;
276 /* Since we don't know the exact size of the saved register info,
277 choose a register section size that is either the remaining part
278 of the file, or 1024, whichever is smaller. */
279 nread
= statbuf
.st_size
- asect
->filepos
;
280 asect
->size
= (nread
< 1024) ? nread
: 1024;
284 /* Get here if we have already started filling out the BFD
285 and there is an error of some kind. */
288 bfd_release (abfd
, abfd
->tdata
.any
);
289 abfd
->tdata
.any
= NULL
;
290 bfd_section_list_clear (abfd
);
294 static const bfd_target
*
295 cisco_core_file_p (abfd
)
298 int *crash_info_locp
;
299 const bfd_target
*target
= NULL
;
301 for (crash_info_locp
= crash_info_locs
;
302 *crash_info_locp
!= -1 && target
== NULL
;
305 target
= cisco_core_file_validate (abfd
, *crash_info_locp
);
311 cisco_core_file_failing_command (abfd
)
312 bfd
*abfd ATTRIBUTE_UNUSED
;
318 cisco_core_file_failing_signal (abfd
)
319 bfd
*abfd ATTRIBUTE_UNUSED
;
321 return abfd
->tdata
.cisco_core_data
->sig
;
324 extern const bfd_target cisco_core_little_vec
;
326 const bfd_target cisco_core_big_vec
=
328 "cisco-ios-core-big",
329 bfd_target_unknown_flavour
,
330 BFD_ENDIAN_BIG
, /* target byte order */
331 BFD_ENDIAN_BIG
, /* target headers byte order */
332 (HAS_RELOC
| EXEC_P
| /* object flags */
333 HAS_LINENO
| HAS_DEBUG
|
334 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
335 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
336 0, /* symbol prefix */
337 ' ', /* ar_pad_char */
338 16, /* ar_max_namelen */
339 0, /* match priority. */
340 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
341 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
342 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
343 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
344 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
345 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
347 { /* bfd_check_format */
348 _bfd_dummy_target
, /* unknown format */
349 _bfd_dummy_target
, /* object file */
350 _bfd_dummy_target
, /* archive */
351 cisco_core_file_p
/* a core file */
353 { /* bfd_set_format */
354 bfd_false
, bfd_false
,
357 { /* bfd_write_contents */
358 bfd_false
, bfd_false
,
362 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
363 BFD_JUMP_TABLE_COPY (_bfd_generic
),
364 BFD_JUMP_TABLE_CORE (cisco
),
365 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive
),
366 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
367 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
368 BFD_JUMP_TABLE_WRITE (_bfd_generic
),
369 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
370 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),
372 & cisco_core_little_vec
,
374 (PTR
) 0 /* backend_data */
377 const bfd_target cisco_core_little_vec
=
379 "cisco-ios-core-little",
380 bfd_target_unknown_flavour
,
381 BFD_ENDIAN_LITTLE
, /* target byte order */
382 BFD_ENDIAN_LITTLE
, /* target headers byte order */
383 (HAS_RELOC
| EXEC_P
| /* object flags */
384 HAS_LINENO
| HAS_DEBUG
|
385 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
),
386 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
387 0, /* symbol prefix */
388 ' ', /* ar_pad_char */
389 16, /* ar_max_namelen */
390 0, /* match_priority */
391 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
392 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
393 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* data */
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
, /* hdrs */
398 { /* bfd_check_format */
399 _bfd_dummy_target
, /* unknown format */
400 _bfd_dummy_target
, /* object file */
401 _bfd_dummy_target
, /* archive */
402 cisco_core_file_p
/* a core file */
404 { /* bfd_set_format */
405 bfd_false
, bfd_false
,
408 { /* bfd_write_contents */
409 bfd_false
, bfd_false
,
413 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
414 BFD_JUMP_TABLE_COPY (_bfd_generic
),
415 BFD_JUMP_TABLE_CORE (cisco
),
416 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive
),
417 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
418 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
419 BFD_JUMP_TABLE_WRITE (_bfd_generic
),
420 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
421 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),
425 (PTR
) 0 /* backend_data */