00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "libbfd.h"
00028
00029
00030 #include <signal.h>
00031
00032
00033 #ifndef SIGTRAP
00034 # define SIGTRAP 5
00035 #endif
00036 #ifndef SIGEMT
00037 # define SIGEMT 6
00038 #endif
00039 #ifndef SIGBUS
00040 # define SIGBUS 10
00041 #endif
00042
00043 int crash_info_locs[] = {
00044 0x0250,
00045 0x0400,
00046 0x0FFC,
00047 0x3000,
00048 0x4FFC,
00049 -1
00050 };
00051
00052 #define CRASH_MAGIC 0xdead1234
00053 #define MASK_ADDR(x) ((x) & 0x0fffffff)
00054
00055 typedef enum {
00056 CRASH_REASON_NOTCRASHED = 0,
00057 CRASH_REASON_EXCEPTION = 1,
00058 CRASH_REASON_CORRUPT = 2,
00059 } crashreason;
00060
00061 typedef struct {
00062 char magic[4];
00063 char version[4];
00064 char reason[4];
00065 char cpu_vector[4];
00066 char registers[4];
00067 char rambase[4];
00068 char textbase[4];
00069 char database[4];
00070 char bssbase[4];
00071 } crashinfo_external;
00072
00073 struct cisco_core_struct
00074 {
00075 int sig;
00076 };
00077
00078 static const bfd_target *cisco_core_file_validate PARAMS ((bfd *, int));
00079 static const bfd_target *cisco_core_file_p PARAMS ((bfd *));
00080 char *cisco_core_file_failing_command PARAMS ((bfd *));
00081 int cisco_core_file_failing_signal PARAMS ((bfd *));
00082 bfd_boolean cisco_core_file_matches_executable_p PARAMS ((bfd *, bfd *));
00083
00084
00085
00086
00087 static const bfd_target *
00088 cisco_core_file_validate (abfd, crash_info_loc)
00089 bfd *abfd;
00090 int crash_info_loc;
00091 {
00092 char buf[4];
00093 unsigned int crashinfo_offset;
00094 crashinfo_external crashinfo;
00095 int nread;
00096 unsigned int magic;
00097 unsigned int version;
00098 unsigned int rambase;
00099 sec_ptr asect;
00100 struct stat statbuf;
00101 bfd_size_type amt;
00102
00103 if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
00104 return NULL;
00105
00106 nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
00107 if (nread != 4)
00108 {
00109 if (bfd_get_error () != bfd_error_system_call)
00110 bfd_set_error (bfd_error_wrong_format);
00111 return NULL;
00112 }
00113 crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));
00114
00115 if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
00116 {
00117
00118 bfd_set_error (bfd_error_wrong_format);
00119 return NULL;
00120 }
00121
00122 nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
00123 if (nread != sizeof (crashinfo))
00124 {
00125 if (bfd_get_error () != bfd_error_system_call)
00126 bfd_set_error (bfd_error_wrong_format);
00127 return NULL;
00128 }
00129
00130 if (bfd_stat (abfd, &statbuf) < 0)
00131 {
00132 bfd_set_error (bfd_error_system_call);
00133 return NULL;
00134 }
00135
00136 magic = bfd_get_32 (abfd, crashinfo.magic);
00137 if (magic != CRASH_MAGIC)
00138 {
00139 bfd_set_error (bfd_error_wrong_format);
00140 return NULL;
00141 }
00142
00143 version = bfd_get_32 (abfd, crashinfo.version);
00144 if (version == 0)
00145 {
00146 bfd_set_error (bfd_error_wrong_format);
00147 return NULL;
00148 }
00149 else if (version == 1)
00150 {
00151
00152 rambase = 0;
00153 }
00154 else
00155 {
00156 rambase = bfd_get_32 (abfd, crashinfo.rambase);
00157 }
00158
00159
00160
00161 amt = sizeof (struct cisco_core_struct);
00162 abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
00163 if (abfd->tdata.cisco_core_data == NULL)
00164 return NULL;
00165
00166 switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
00167 {
00168 case CRASH_REASON_NOTCRASHED:
00169
00170 abfd->tdata.cisco_core_data->sig = 0;
00171 break;
00172 case CRASH_REASON_CORRUPT:
00173
00174
00175 abfd->tdata.cisco_core_data->sig = 0;
00176 break;
00177 case CRASH_REASON_EXCEPTION:
00178
00179
00180
00181
00182
00183
00184
00185 switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
00186 {
00187
00188 case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
00189
00190 case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
00191
00192 case 4 : abfd->tdata.cisco_core_data->sig = SIGILL; break;
00193
00194 case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00195
00196 case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00197
00198 case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00199
00200 case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
00201
00202 case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
00203
00204 case 10: abfd->tdata.cisco_core_data->sig = SIGILL; break;
00205
00206 case 11: abfd->tdata.cisco_core_data->sig = SIGILL; break;
00207
00208
00209
00210 case 13: abfd->tdata.cisco_core_data->sig = SIGBUS; break;
00211
00212
00213 case 31: abfd->tdata.cisco_core_data->sig = SIGINT; break;
00214
00215 case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
00216
00217
00218 case 48: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00219
00220 case 49: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00221
00222 case 50: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00223
00224 case 51: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00225
00226 case 52: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00227
00228 case 53: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00229
00230 case 54: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00231 default:
00232 #ifndef SIGEMT
00233 #define SIGEMT SIGTRAP
00234 #endif
00235
00236 abfd->tdata.cisco_core_data->sig = SIGEMT;
00237 }
00238 break;
00239 default:
00240
00241 abfd->tdata.cisco_core_data->sig = 0;
00242 break;
00243 }
00244
00245
00246
00247
00248 asect = bfd_make_section_anyway (abfd, ".data");
00249 if (asect == NULL)
00250 goto error_return;
00251 asect->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00252
00253 asect->size = statbuf.st_size;
00254 asect->vma = rambase;
00255 asect->filepos = 0;
00256
00257
00258
00259
00260 asect = bfd_make_section_anyway (abfd, ".crash");
00261 if (asect == NULL)
00262 goto error_return;
00263 asect->flags = SEC_HAS_CONTENTS;
00264 asect->vma = 0;
00265 asect->filepos = crashinfo_offset;
00266 asect->size = sizeof (crashinfo);
00267
00268
00269
00270
00271 asect = bfd_make_section_anyway (abfd, ".reg");
00272 if (asect == NULL)
00273 goto error_return;
00274 asect->flags = SEC_HAS_CONTENTS;
00275 asect->vma = 0;
00276 asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
00277
00278
00279
00280 nread = statbuf.st_size - asect->filepos;
00281 asect->size = (nread < 1024) ? nread : 1024;
00282
00283 return abfd->xvec;
00284
00285
00286
00287
00288 error_return:
00289 bfd_release (abfd, abfd->tdata.any);
00290 abfd->tdata.any = NULL;
00291 bfd_section_list_clear (abfd);
00292 return NULL;
00293 }
00294
00295 static const bfd_target *
00296 cisco_core_file_p (abfd)
00297 bfd *abfd;
00298 {
00299 int *crash_info_locp;
00300 const bfd_target *target = NULL;
00301
00302 for (crash_info_locp = crash_info_locs;
00303 *crash_info_locp != -1 && target == NULL;
00304 crash_info_locp++)
00305 {
00306 target = cisco_core_file_validate (abfd, *crash_info_locp);
00307 }
00308 return (target);
00309 }
00310
00311 char *
00312 cisco_core_file_failing_command (abfd)
00313 bfd *abfd ATTRIBUTE_UNUSED;
00314 {
00315 return NULL;
00316 }
00317
00318 int
00319 cisco_core_file_failing_signal (abfd)
00320 bfd *abfd ATTRIBUTE_UNUSED;
00321 {
00322 return abfd->tdata.cisco_core_data->sig;
00323 }
00324
00325 bfd_boolean
00326 cisco_core_file_matches_executable_p (core_bfd, exec_bfd)
00327 bfd *core_bfd ATTRIBUTE_UNUSED;
00328 bfd *exec_bfd ATTRIBUTE_UNUSED;
00329 {
00330 return TRUE;
00331 }
00332
00333 extern const bfd_target cisco_core_little_vec;
00334
00335 const bfd_target cisco_core_big_vec =
00336 {
00337 "cisco-ios-core-big",
00338 bfd_target_unknown_flavour,
00339 BFD_ENDIAN_BIG,
00340 BFD_ENDIAN_BIG,
00341 (HAS_RELOC | EXEC_P |
00342 HAS_LINENO | HAS_DEBUG |
00343 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00344 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
00345 0,
00346 ' ',
00347 16,
00348 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00349 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00350 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00351 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00352 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00353 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00354
00355 {
00356 _bfd_dummy_target,
00357 _bfd_dummy_target,
00358 _bfd_dummy_target,
00359 cisco_core_file_p
00360 },
00361 {
00362 bfd_false, bfd_false,
00363 bfd_false, bfd_false
00364 },
00365 {
00366 bfd_false, bfd_false,
00367 bfd_false, bfd_false
00368 },
00369
00370 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
00371 BFD_JUMP_TABLE_COPY (_bfd_generic),
00372 BFD_JUMP_TABLE_CORE (cisco),
00373 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00374 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
00375 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00376 BFD_JUMP_TABLE_WRITE (_bfd_generic),
00377 BFD_JUMP_TABLE_LINK (_bfd_nolink),
00378 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00379
00380 & cisco_core_little_vec,
00381
00382 (PTR) 0
00383 };
00384
00385 const bfd_target cisco_core_little_vec =
00386 {
00387 "cisco-ios-core-little",
00388 bfd_target_unknown_flavour,
00389 BFD_ENDIAN_LITTLE,
00390 BFD_ENDIAN_LITTLE,
00391 (HAS_RELOC | EXEC_P |
00392 HAS_LINENO | HAS_DEBUG |
00393 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00394 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
00395 0,
00396 ' ',
00397 16,
00398 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00399 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00400 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00401 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00402 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00403 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00404
00405 {
00406 _bfd_dummy_target,
00407 _bfd_dummy_target,
00408 _bfd_dummy_target,
00409 cisco_core_file_p
00410 },
00411 {
00412 bfd_false, bfd_false,
00413 bfd_false, bfd_false
00414 },
00415 {
00416 bfd_false, bfd_false,
00417 bfd_false, bfd_false
00418 },
00419
00420 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
00421 BFD_JUMP_TABLE_COPY (_bfd_generic),
00422 BFD_JUMP_TABLE_CORE (cisco),
00423 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00424 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
00425 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00426 BFD_JUMP_TABLE_WRITE (_bfd_generic),
00427 BFD_JUMP_TABLE_LINK (_bfd_nolink),
00428 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00429
00430 &cisco_core_big_vec,
00431
00432 (PTR) 0
00433 };