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