]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/cisco-core.c
Switch sources over to use the GPL version 3
[thirdparty/binutils-gdb.git] / bfd / cisco-core.c
CommitLineData
252b5132 1/* BFD back-end for CISCO crash dumps.
3db64b00 2 Copyright 1994, 1997, 1999, 2000, 2001, 2002, 2004, 2006, 2007
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
252b5132 80\f
f4bda984 81/* Examine the file for a crash info struct at the offset given by
e60b52c6 82 CRASH_INFO_LOC. */
f4bda984 83
252b5132 84static const bfd_target *
f4bda984 85cisco_core_file_validate (abfd, crash_info_loc)
252b5132 86 bfd *abfd;
f4bda984 87 int crash_info_loc;
252b5132
RH
88{
89 char buf[4];
90 unsigned int crashinfo_offset;
f4bda984 91 crashinfo_external crashinfo;
74633dd0 92 bfd_size_type nread;
f4bda984
RH
93 unsigned int magic;
94 unsigned int version;
252b5132
RH
95 unsigned int rambase;
96 sec_ptr asect;
97 struct stat statbuf;
dc810e39 98 bfd_size_type amt;
117ed4f8 99 flagword flags;
252b5132 100
dc810e39 101 if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
252b5132
RH
102 return NULL;
103
dc810e39 104 nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
252b5132
RH
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 }
f4bda984 111 crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));
252b5132 112
dc810e39 113 if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
f4bda984
RH
114 {
115 /* Most likely we failed because of a bogus (huge) offset */
116 bfd_set_error (bfd_error_wrong_format);
117 return NULL;
118 }
252b5132 119
dc810e39 120 nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
252b5132
RH
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
f4bda984
RH
134 magic = bfd_get_32 (abfd, crashinfo.magic);
135 if (magic != CRASH_MAGIC)
252b5132
RH
136 {
137 bfd_set_error (bfd_error_wrong_format);
138 return NULL;
139 }
140
f4bda984
RH
141 version = bfd_get_32 (abfd, crashinfo.version);
142 if (version == 0)
252b5132 143 {
252b5132
RH
144 bfd_set_error (bfd_error_wrong_format);
145 return NULL;
f4bda984
RH
146 }
147 else if (version == 1)
148 {
149 /* V1 core dumps don't specify the dump base, assume 0 */
252b5132 150 rambase = 0;
f4bda984
RH
151 }
152 else
153 {
252b5132 154 rambase = bfd_get_32 (abfd, crashinfo.rambase);
252b5132
RH
155 }
156
157 /* OK, we believe you. You're a core file. */
158
dc810e39
AM
159 amt = sizeof (struct cisco_core_struct);
160 abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
252b5132
RH
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
9e7b37b3
AM
243 /* Create a ".data" section that maps the entire file, which is
244 essentially a dump of the target system's RAM. */
f4bda984 245
117ed4f8
AM
246 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
247 asect = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
252b5132
RH
248 if (asect == NULL)
249 goto error_return;
9e7b37b3 250 /* The size of memory is the size of the core file itself. */
eea6121a 251 asect->size = statbuf.st_size;
9e7b37b3
AM
252 asect->vma = rambase;
253 asect->filepos = 0;
252b5132 254
f4bda984 255 /* Create a ".crash" section to allow access to the saved
e60b52c6 256 crash information. */
f4bda984 257
117ed4f8
AM
258 flags = SEC_HAS_CONTENTS;
259 asect = bfd_make_section_anyway_with_flags (abfd, ".crash", flags);
f4bda984
RH
260 if (asect == NULL)
261 goto error_return;
f4bda984
RH
262 asect->vma = 0;
263 asect->filepos = crashinfo_offset;
eea6121a 264 asect->size = sizeof (crashinfo);
f4bda984 265
9e7b37b3
AM
266 /* Create a ".reg" section to allow access to the saved
267 registers. */
f4bda984 268
117ed4f8 269 asect = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
252b5132
RH
270 if (asect == NULL)
271 goto error_return;
9e7b37b3
AM
272 asect->vma = 0;
273 asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
274 /* Since we don't know the exact size of the saved register info,
275 choose a register section size that is either the remaining part
276 of the file, or 1024, whichever is smaller. */
277 nread = statbuf.st_size - asect->filepos;
eea6121a 278 asect->size = (nread < 1024) ? nread : 1024;
252b5132
RH
279
280 return abfd->xvec;
281
f4bda984 282 /* Get here if we have already started filling out the BFD
e60b52c6 283 and there is an error of some kind. */
f4bda984 284
252b5132 285 error_return:
9e7b37b3
AM
286 bfd_release (abfd, abfd->tdata.any);
287 abfd->tdata.any = NULL;
288 bfd_section_list_clear (abfd);
289 return NULL;
252b5132
RH
290}
291
f4bda984
RH
292static const bfd_target *
293cisco_core_file_p (abfd)
294 bfd *abfd;
295{
296 int *crash_info_locp;
297 const bfd_target *target = NULL;
298
299 for (crash_info_locp = crash_info_locs;
300 *crash_info_locp != -1 && target == NULL;
301 crash_info_locp++)
302 {
303 target = cisco_core_file_validate (abfd, *crash_info_locp);
304 }
305 return (target);
306}
307
252b5132
RH
308char *
309cisco_core_file_failing_command (abfd)
dc810e39 310 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
311{
312 return NULL;
313}
314
315int
316cisco_core_file_failing_signal (abfd)
dc810e39 317 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
318{
319 return abfd->tdata.cisco_core_data->sig;
320}
252b5132 321\f
f4bda984
RH
322extern const bfd_target cisco_core_little_vec;
323
324const bfd_target cisco_core_big_vec =
252b5132 325 {
f4bda984 326 "cisco-ios-core-big",
252b5132
RH
327 bfd_target_unknown_flavour,
328 BFD_ENDIAN_BIG, /* target byte order */
329 BFD_ENDIAN_BIG, /* target headers byte order */
330 (HAS_RELOC | EXEC_P | /* object flags */
331 HAS_LINENO | HAS_DEBUG |
332 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
333 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
334 0, /* symbol prefix */
335 ' ', /* ar_pad_char */
336 16, /* ar_max_namelen */
337 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
338 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
339 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
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, /* hdrs */
343
344 { /* bfd_check_format */
345 _bfd_dummy_target, /* unknown format */
346 _bfd_dummy_target, /* object file */
347 _bfd_dummy_target, /* archive */
348 cisco_core_file_p /* a core file */
349 },
350 { /* bfd_set_format */
351 bfd_false, bfd_false,
352 bfd_false, bfd_false
353 },
354 { /* bfd_write_contents */
355 bfd_false, bfd_false,
356 bfd_false, bfd_false
357 },
e60b52c6 358
252b5132
RH
359 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
360 BFD_JUMP_TABLE_COPY (_bfd_generic),
361 BFD_JUMP_TABLE_CORE (cisco),
362 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
363 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
364 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
365 BFD_JUMP_TABLE_WRITE (_bfd_generic),
366 BFD_JUMP_TABLE_LINK (_bfd_nolink),
367 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
368
f4bda984 369 & cisco_core_little_vec,
e60b52c6 370
f4bda984
RH
371 (PTR) 0 /* backend_data */
372};
373
374const bfd_target cisco_core_little_vec =
375 {
376 "cisco-ios-core-little",
377 bfd_target_unknown_flavour,
378 BFD_ENDIAN_LITTLE, /* target byte order */
379 BFD_ENDIAN_LITTLE, /* target headers byte order */
380 (HAS_RELOC | EXEC_P | /* object flags */
381 HAS_LINENO | HAS_DEBUG |
382 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
383 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
384 0, /* symbol prefix */
385 ' ', /* ar_pad_char */
386 16, /* ar_max_namelen */
387 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
388 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
389 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
390 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
391 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
392 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
393
394 { /* bfd_check_format */
395 _bfd_dummy_target, /* unknown format */
396 _bfd_dummy_target, /* object file */
397 _bfd_dummy_target, /* archive */
398 cisco_core_file_p /* a core file */
399 },
400 { /* bfd_set_format */
401 bfd_false, bfd_false,
402 bfd_false, bfd_false
403 },
404 { /* bfd_write_contents */
405 bfd_false, bfd_false,
406 bfd_false, bfd_false
407 },
e60b52c6 408
f4bda984
RH
409 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
410 BFD_JUMP_TABLE_COPY (_bfd_generic),
411 BFD_JUMP_TABLE_CORE (cisco),
412 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
413 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
414 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
415 BFD_JUMP_TABLE_WRITE (_bfd_generic),
416 BFD_JUMP_TABLE_LINK (_bfd_nolink),
417 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
418
419 &cisco_core_big_vec,
e60b52c6 420
252b5132
RH
421 (PTR) 0 /* backend_data */
422};