Back to index

cell-binutils  2.17cvs20070401
cisco-core.c
Go to the documentation of this file.
00001 /* BFD back-end for CISCO crash dumps.
00002    Copyright 1994, 1997, 1999, 2000, 2001, 2002, 2004, 2006
00003    Free Software Foundation, Inc.
00004 
00005 This file is part of BFD, the Binary File Descriptor library.
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "bfd.h"
00022 #include "sysdep.h"
00023 #include "libbfd.h"
00024 /* core_file_failing_signal returns a host signal (this probably should
00025    be fixed).  */
00026 #include <signal.h>
00027 
00028 /* for MSVC builds */
00029 #ifndef SIGTRAP
00030 # define SIGTRAP 5
00031 #endif
00032 #ifndef SIGEMT
00033 # define SIGEMT 6
00034 #endif
00035 #ifndef SIGBUS
00036 # define SIGBUS 10
00037 #endif
00038 
00039 int crash_info_locs[] = {
00040   0x0250,     /* mips, ppc, x86, i960 */
00041   0x0400,     /* m68k, mips, x86, i960 */
00042   0x0FFC,     /* m68k, mips, ppc, x86, i960 */
00043   0x3000,     /* ppc */
00044   0x4FFC,     /* m68k */
00045   -1
00046 };
00047 
00048 #define CRASH_MAGIC  0xdead1234
00049 #define MASK_ADDR(x) ((x) & 0x0fffffff)   /* Mask crash info address */
00050 
00051 typedef enum {
00052     CRASH_REASON_NOTCRASHED = 0,
00053     CRASH_REASON_EXCEPTION = 1,
00054     CRASH_REASON_CORRUPT = 2,
00055 } crashreason;
00056 
00057 typedef struct {
00058   char magic[4];            /* Magic number */
00059   char version[4];          /* Version number */
00060   char reason[4];           /* Crash reason */
00061   char cpu_vector[4];              /* CPU vector for exceptions */
00062   char registers[4];        /* Pointer to saved registers */
00063   char rambase[4];          /* Base of RAM (not in V1 crash info) */
00064   char textbase[4];         /* Base of .text section (not in V3 crash info) */
00065   char database[4];         /* Base of .data section (not in V3 crash info) */
00066   char bssbase[4];          /* Base of .bss section (not in V3 crash info) */
00067 } crashinfo_external;
00068 
00069 struct cisco_core_struct
00070 {
00071   int sig;
00072 };
00073 
00074 static const bfd_target *cisco_core_file_validate PARAMS ((bfd *, int));
00075 static const bfd_target *cisco_core_file_p PARAMS ((bfd *));
00076 char *cisco_core_file_failing_command PARAMS ((bfd *));
00077 int cisco_core_file_failing_signal PARAMS ((bfd *));
00078 #define cisco_core_file_matches_executable_p generic_core_file_matches_executable_p
00079 
00080 /* Examine the file for a crash info struct at the offset given by
00081    CRASH_INFO_LOC.  */
00082 
00083 static const bfd_target *
00084 cisco_core_file_validate (abfd, crash_info_loc)
00085      bfd *abfd;
00086      int crash_info_loc;
00087 {
00088   char buf[4];
00089   unsigned int crashinfo_offset;
00090   crashinfo_external crashinfo;
00091   bfd_size_type nread;
00092   unsigned int magic;
00093   unsigned int version;
00094   unsigned int rambase;
00095   sec_ptr asect;
00096   struct stat statbuf;
00097   bfd_size_type amt;
00098   flagword flags;
00099 
00100   if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0)
00101     return NULL;
00102 
00103   nread = bfd_bread (buf, (bfd_size_type) 4, abfd);
00104   if (nread != 4)
00105     {
00106       if (bfd_get_error () != bfd_error_system_call)
00107        bfd_set_error (bfd_error_wrong_format);
00108       return NULL;
00109     }
00110   crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf));
00111 
00112   if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0)
00113     {
00114       /* Most likely we failed because of a bogus (huge) offset */
00115       bfd_set_error (bfd_error_wrong_format);
00116       return NULL;
00117     }
00118 
00119   nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd);
00120   if (nread != sizeof (crashinfo))
00121     {
00122       if (bfd_get_error () != bfd_error_system_call)
00123        bfd_set_error (bfd_error_wrong_format);
00124       return NULL;
00125     }
00126 
00127   if (bfd_stat (abfd, &statbuf) < 0)
00128     {
00129       bfd_set_error (bfd_error_system_call);
00130       return NULL;
00131     }
00132 
00133   magic = bfd_get_32 (abfd, crashinfo.magic);
00134   if (magic != CRASH_MAGIC)
00135     {
00136       bfd_set_error (bfd_error_wrong_format);
00137       return NULL;
00138     }
00139 
00140   version = bfd_get_32 (abfd, crashinfo.version);
00141   if (version == 0)
00142     {
00143       bfd_set_error (bfd_error_wrong_format);
00144       return NULL;
00145     }
00146   else if (version == 1)
00147     {
00148       /* V1 core dumps don't specify the dump base, assume 0 */
00149       rambase = 0;
00150     }
00151   else
00152     {
00153       rambase = bfd_get_32 (abfd, crashinfo.rambase);
00154     }
00155 
00156   /* OK, we believe you.  You're a core file.  */
00157 
00158   amt = sizeof (struct cisco_core_struct);
00159   abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt);
00160   if (abfd->tdata.cisco_core_data == NULL)
00161     return NULL;
00162 
00163   switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
00164     {
00165     case CRASH_REASON_NOTCRASHED:
00166       /* Crash file probably came from write core.  */
00167       abfd->tdata.cisco_core_data->sig = 0;
00168       break;
00169     case CRASH_REASON_CORRUPT:
00170       /* The crash context area was corrupt -- proceed with caution.
00171         We have no way of passing this information back to the caller.  */
00172       abfd->tdata.cisco_core_data->sig = 0;
00173       break;
00174     case CRASH_REASON_EXCEPTION:
00175       /* Crash occured due to CPU exception.  */
00176 
00177       /* This is 68k-specific; for MIPS we'll need to interpret
00178         cpu_vector differently based on the target configuration
00179         (since CISCO core files don't seem to have the processor
00180         encoded in them).  */
00181 
00182       switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
00183        {
00184           /* bus error           */
00185        case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
00186           /* address error       */
00187        case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
00188           /* illegal instruction */
00189        case 4 : abfd->tdata.cisco_core_data->sig = SIGILL;  break;
00190           /* zero divide         */
00191        case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00192           /* chk instruction     */
00193        case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00194           /* trapv instruction   */
00195        case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
00196           /* privilege violation */
00197        case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
00198           /* trace trap          */
00199        case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;
00200           /* line 1010 emulator  */
00201        case 10: abfd->tdata.cisco_core_data->sig = SIGILL;  break;
00202           /* line 1111 emulator  */
00203        case 11: abfd->tdata.cisco_core_data->sig = SIGILL;  break;
00204 
00205          /* Coprocessor protocol violation.  Using a standard MMU or FPU
00206             this cannot be triggered by software.  Call it a SIGBUS.  */
00207        case 13: abfd->tdata.cisco_core_data->sig = SIGBUS;  break;
00208 
00209          /* interrupt           */
00210        case 31: abfd->tdata.cisco_core_data->sig = SIGINT;  break;
00211          /* breakpoint          */
00212        case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP;  break;
00213 
00214          /* floating point err  */
00215        case 48: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00216          /* floating point err  */
00217        case 49: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00218          /* zero divide         */
00219        case 50: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00220          /* underflow           */
00221        case 51: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00222          /* operand error       */
00223        case 52: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00224           /* overflow            */
00225        case 53: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00226          /* NAN                 */
00227        case 54: abfd->tdata.cisco_core_data->sig = SIGFPE;  break;
00228        default:
00229 #ifndef SIGEMT
00230 #define SIGEMT SIGTRAP
00231 #endif
00232          /* "software generated"*/
00233          abfd->tdata.cisco_core_data->sig = SIGEMT;
00234        }
00235       break;
00236     default:
00237       /* Unknown crash reason.  */
00238       abfd->tdata.cisco_core_data->sig = 0;
00239       break;
00240     }
00241 
00242   /* Create a ".data" section that maps the entire file, which is
00243      essentially a dump of the target system's RAM.  */
00244 
00245   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00246   asect = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
00247   if (asect == NULL)
00248     goto error_return;
00249   /* The size of memory is the size of the core file itself.  */
00250   asect->size = statbuf.st_size;
00251   asect->vma = rambase;
00252   asect->filepos = 0;
00253 
00254   /* Create a ".crash" section to allow access to the saved
00255      crash information.  */
00256 
00257   flags = SEC_HAS_CONTENTS;
00258   asect = bfd_make_section_anyway_with_flags (abfd, ".crash", flags);
00259   if (asect == NULL)
00260     goto error_return;
00261   asect->vma = 0;
00262   asect->filepos = crashinfo_offset;
00263   asect->size = sizeof (crashinfo);
00264 
00265   /* Create a ".reg" section to allow access to the saved
00266      registers.  */
00267 
00268   asect = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
00269   if (asect == NULL)
00270     goto error_return;
00271   asect->vma = 0;
00272   asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
00273   /* Since we don't know the exact size of the saved register info,
00274      choose a register section size that is either the remaining part
00275      of the file, or 1024, whichever is smaller.  */
00276   nread = statbuf.st_size - asect->filepos;
00277   asect->size = (nread < 1024) ? nread : 1024;
00278 
00279   return abfd->xvec;
00280 
00281   /* Get here if we have already started filling out the BFD
00282      and there is an error of some kind.  */
00283 
00284  error_return:
00285   bfd_release (abfd, abfd->tdata.any);
00286   abfd->tdata.any = NULL;
00287   bfd_section_list_clear (abfd);
00288   return NULL;
00289 }
00290 
00291 static const bfd_target *
00292 cisco_core_file_p (abfd)
00293      bfd *abfd;
00294 {
00295   int *crash_info_locp;
00296   const bfd_target *target = NULL;
00297 
00298   for (crash_info_locp = crash_info_locs;
00299        *crash_info_locp != -1  &&  target == NULL;
00300        crash_info_locp++)
00301     {
00302       target = cisco_core_file_validate (abfd, *crash_info_locp);
00303     }
00304   return (target);
00305 }
00306 
00307 char *
00308 cisco_core_file_failing_command (abfd)
00309      bfd *abfd ATTRIBUTE_UNUSED;
00310 {
00311   return NULL;
00312 }
00313 
00314 int
00315 cisco_core_file_failing_signal (abfd)
00316      bfd *abfd ATTRIBUTE_UNUSED;
00317 {
00318   return abfd->tdata.cisco_core_data->sig;
00319 }
00320 
00321 extern const bfd_target cisco_core_little_vec;
00322 
00323 const bfd_target cisco_core_big_vec =
00324   {
00325     "cisco-ios-core-big",
00326     bfd_target_unknown_flavour,
00327     BFD_ENDIAN_BIG,         /* target byte order */
00328     BFD_ENDIAN_BIG,         /* target headers byte order */
00329     (HAS_RELOC | EXEC_P |   /* object flags */
00330      HAS_LINENO | HAS_DEBUG |
00331      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00332     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
00333     0,                                                  /* symbol prefix */
00334     ' ',                                            /* ar_pad_char */
00335     16,                                                    /* ar_max_namelen */
00336     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00337     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00338     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
00339     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00340     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00341     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
00342 
00343     {                       /* bfd_check_format */
00344      _bfd_dummy_target,            /* unknown format */
00345      _bfd_dummy_target,            /* object file */
00346      _bfd_dummy_target,            /* archive */
00347      cisco_core_file_p      /* a core file */
00348     },
00349     {                       /* bfd_set_format */
00350      bfd_false, bfd_false,
00351      bfd_false, bfd_false
00352     },
00353     {                       /* bfd_write_contents */
00354      bfd_false, bfd_false,
00355      bfd_false, bfd_false
00356     },
00357 
00358        BFD_JUMP_TABLE_GENERIC (_bfd_generic),
00359        BFD_JUMP_TABLE_COPY (_bfd_generic),
00360        BFD_JUMP_TABLE_CORE (cisco),
00361        BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00362        BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
00363        BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00364        BFD_JUMP_TABLE_WRITE (_bfd_generic),
00365        BFD_JUMP_TABLE_LINK (_bfd_nolink),
00366        BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00367 
00368     & cisco_core_little_vec,
00369 
00370     (PTR) 0                 /* backend_data */
00371 };
00372 
00373 const bfd_target cisco_core_little_vec =
00374   {
00375     "cisco-ios-core-little",
00376     bfd_target_unknown_flavour,
00377     BFD_ENDIAN_LITTLE,             /* target byte order */
00378     BFD_ENDIAN_LITTLE,             /* target headers byte order */
00379     (HAS_RELOC | EXEC_P |   /* object flags */
00380      HAS_LINENO | HAS_DEBUG |
00381      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00382     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
00383     0,                                                  /* symbol prefix */
00384     ' ',                                            /* ar_pad_char */
00385     16,                                                    /* ar_max_namelen */
00386     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00387     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00388     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
00389     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00390     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00391     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
00392 
00393     {                       /* bfd_check_format */
00394      _bfd_dummy_target,            /* unknown format */
00395      _bfd_dummy_target,            /* object file */
00396      _bfd_dummy_target,            /* archive */
00397      cisco_core_file_p      /* a core file */
00398     },
00399     {                       /* bfd_set_format */
00400      bfd_false, bfd_false,
00401      bfd_false, bfd_false
00402     },
00403     {                       /* bfd_write_contents */
00404      bfd_false, bfd_false,
00405      bfd_false, bfd_false
00406     },
00407 
00408        BFD_JUMP_TABLE_GENERIC (_bfd_generic),
00409        BFD_JUMP_TABLE_COPY (_bfd_generic),
00410        BFD_JUMP_TABLE_CORE (cisco),
00411        BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00412        BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
00413        BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00414        BFD_JUMP_TABLE_WRITE (_bfd_generic),
00415        BFD_JUMP_TABLE_LINK (_bfd_nolink),
00416        BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00417 
00418     &cisco_core_big_vec,
00419 
00420     (PTR) 0                 /* backend_data */
00421 };