Back to index

cell-binutils  2.17cvs20070401
sco5-core.c
Go to the documentation of this file.
00001 /* BFD back end for SCO5 core files (U-area and raw sections)
00002    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003    Free Software Foundation, Inc.
00004    Written by Jouke Numan <jnuman@hiscom.nl>
00005 
00006 This file is part of BFD, the Binary File Descriptor library.
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "libbfd.h"
00025 #include "libaout.h"        /* BFD a.out internal data structures */
00026 
00027 #include <stdio.h>
00028 #include <sys/types.h>
00029 #include <sys/param.h>
00030 #include <sys/dir.h>
00031 #include <signal.h>
00032 
00033 #include <sys/user.h>              /* After a.out.h  */
00034 #ifdef SCO5_CORE
00035 #include <sys/paccess.h>
00036 #include <sys/region.h>
00037 #endif
00038 
00039 struct sco5_core_struct
00040 {
00041   struct user u;
00042 };
00043 
00044 /* forward declarations */
00045 
00046 static asection *make_bfd_asection
00047   PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr));
00048 static struct user *read_uarea PARAMS ((bfd *, int));
00049 const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
00050 char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
00051 int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
00052 #define sco5_core_file_matches_executable_p generic_core_file_matches_executable_p
00053 static void swap_abort PARAMS ((void));
00054 
00055 static asection *
00056 make_bfd_asection (abfd, name, flags, size, vma, filepos)
00057      bfd *abfd;
00058      const char *name;
00059      flagword flags;
00060      bfd_size_type size;
00061      bfd_vma vma;
00062      file_ptr filepos;
00063 {
00064   asection *asect;
00065 
00066   asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
00067   if (!asect)
00068     return NULL;
00069   asect->size = size;
00070   asect->vma = vma;
00071   asect->filepos = filepos;
00072   asect->alignment_power = 2;
00073 
00074   return asect;
00075 }
00076 
00077 static struct user *
00078 read_uarea(abfd, filepos)
00079      bfd *abfd;
00080      int filepos;
00081 
00082 {
00083   struct sco5_core_struct *rawptr;
00084   bfd_size_type amt = sizeof (struct sco5_core_struct);
00085 
00086   rawptr = (struct sco5_core_struct *) bfd_zmalloc (amt);
00087   if (rawptr == NULL)
00088     return NULL;
00089 
00090   abfd->tdata.sco5_core_data = rawptr;
00091 
00092   if (bfd_seek (abfd, (file_ptr) filepos, SEEK_SET) != 0
00093       || bfd_bread ((void *) &rawptr->u, (bfd_size_type) sizeof rawptr->u,
00094                  abfd) != sizeof rawptr->u)
00095     {
00096       bfd_set_error (bfd_error_wrong_format);
00097       return NULL;
00098     }
00099 
00100   /* Sanity check perhaps??? */
00101   if (rawptr->u.u_dsize > 0x1000000)    /* Remember, it's in pages...  */
00102     {
00103       bfd_set_error (bfd_error_wrong_format);
00104       return NULL;
00105     }
00106   if (rawptr->u.u_ssize > 0x1000000)
00107     {
00108       bfd_set_error (bfd_error_wrong_format);
00109       return NULL;
00110     }
00111   return &rawptr->u;
00112 }
00113 
00114 const bfd_target *
00115 sco5_core_file_p (abfd)
00116      bfd *abfd;
00117 {
00118   int coffset_siz, val, nsecs, cheadoffs;
00119   int coresize;
00120   struct user *u;
00121   struct coreoffsets coffsets;
00122   struct coresecthead chead;
00123   char *secname;
00124   flagword flags;
00125 
00126   /* Read coreoffsets region at end of core (see core(FP)).  */
00127 
00128   {
00129     struct stat statbuf;
00130 
00131     if (bfd_stat (abfd, &statbuf) < 0)
00132       return NULL;
00133 
00134     coresize = statbuf.st_size;
00135   }
00136   /* Last long in core is sizeof struct coreoffsets, read it */
00137   if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz),
00138                SEEK_SET) != 0)
00139       || bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz,
00140                  abfd) != sizeof coffset_siz)
00141     {
00142       bfd_set_error (bfd_error_wrong_format);
00143       return NULL;
00144     }
00145 
00146   /* Use it to seek start of coreoffsets region, read it and determine
00147      validity */
00148   if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0)
00149       || (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd)
00150          != sizeof coffsets)
00151       || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
00152     {
00153       bfd_set_error (bfd_error_wrong_format);
00154       return NULL;
00155     }
00156 
00157   if (coffsets.u_info == 1)
00158     {
00159       /* Old version, no section heads, read info from user struct */
00160 
00161       u = read_uarea (abfd, coffsets.u_user);
00162       if (! u)
00163        goto fail;
00164 
00165       if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
00166                            (bfd_size_type) coffsets.u_usize,
00167                            0 - (bfd_vma) u->u_ar0,
00168                            (file_ptr) coffsets.u_user))
00169        goto fail;
00170 
00171       if (!make_bfd_asection (abfd, ".data",
00172                            SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
00173                            ((bfd_size_type) u->u_exdata.ux_dsize
00174                             + u->u_exdata.ux_bsize),
00175                            (bfd_vma) u->u_exdata.ux_datorg,
00176                            (file_ptr) coffsets.u_data))
00177        goto fail;
00178 
00179       if (!make_bfd_asection (abfd, ".stack",
00180                            SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
00181                            (bfd_size_type) u->u_ssize * NBPC,
00182                            (bfd_vma) u->u_sub,
00183                            (file_ptr) coffsets.u_stack))
00184        goto fail;
00185 
00186       return abfd->xvec;           /* Done for version 1 */
00187     }
00188 
00189   /* Immediately before coreoffsets region is a long with offset in core
00190      to first coresecthead (CORES_OFFSETS), the long before this is the
00191      number of section heads in the list. Read both longs and read the
00192      coresecthead and check its validity */
00193 
00194   if ((bfd_seek (abfd,
00195                (file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz),
00196                SEEK_SET) != 0)
00197       || (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd)
00198          != sizeof nsecs)
00199       || (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs,
00200                   abfd) != sizeof cheadoffs)
00201       || (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0)
00202       || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
00203          != sizeof chead)
00204       || (chead.cs_stype != CORES_OFFSETS)
00205       || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
00206     {
00207       bfd_set_error (bfd_error_wrong_format);
00208       goto fail;
00209     }
00210 
00211   /* OK, we believe you.  You're a core file (sure, sure).  */
00212 
00213   /* Now loop over all regions and map them */
00214   nsecs--;                         /* We've seen CORES_OFFSETS already */
00215   for (; nsecs; nsecs--)
00216     {
00217       if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0)
00218          || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
00219              != sizeof chead))
00220        {
00221          bfd_set_error (bfd_error_wrong_format);
00222          goto fail;
00223        }
00224 
00225       switch (chead.cs_stype)
00226        {
00227        case CORES_MAGIC:                  /* Core header, check magic */
00228          if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
00229            {
00230              bfd_set_error (bfd_error_wrong_format);
00231              goto fail;
00232            }
00233          secname = NULL;
00234          nsecs++;                         /* MAGIC not in section cnt!*/
00235          break;
00236        case CORES_UAREA:                  /* U-area, read in tdata */
00237          u = read_uarea (abfd, chead.cs_sseek);
00238          if (! u)
00239            goto fail;
00240 
00241          /* This is tricky.  As the "register section", we give them
00242             the entire upage and stack.  u.u_ar0 points to where
00243             "register 0" is stored.  There are two tricks with this,
00244             though.  One is that the rest of the registers might be
00245             at positive or negative (or both) displacements from
00246             *u_ar0.  The other is that u_ar0 is sometimes an absolute
00247             address in kernel memory, and on other systems it is an
00248             offset from the beginning of the `struct user'.
00249 
00250             As a practical matter, we don't know where the registers
00251             actually are, so we have to pass the whole area to GDB.
00252             We encode the value of u_ar0 by setting the .regs section
00253             up so that its virtual memory address 0 is at the place
00254             pointed to by u_ar0 (by setting the vma of the start of
00255             the section to -u_ar0).  GDB uses this info to locate the
00256             regs, using minor trickery to get around the
00257             offset-or-absolute-addr problem.  */
00258 
00259          chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
00260 
00261          secname = ".reg";
00262          flags = SEC_HAS_CONTENTS;
00263 
00264          break;
00265        case CORES_PREGION:                /* A program region, map it */
00266          switch (chead.cs_x.csx_preg.csxp_rtyp)
00267            {
00268            case PT_DATA:
00269              secname = ".data";    /* Data region.              */
00270              break;
00271            case PT_STACK:
00272              secname = ".stack";   /* Stack region.      */
00273              break;
00274            case PT_SHMEM:
00275              secname = ".shmem";   /* Shared memory      */
00276              break;
00277            case PT_LIBDAT:
00278              secname = ".libdat";  /* Shared library data       */
00279              break;
00280            case PT_V86:
00281              secname = ".virt86";  /* Virtual 8086 mode  */
00282              break;
00283            case PT_SHFIL:
00284              secname = ".mmfile";  /* Memory mapped file        */
00285              break;
00286            case PT_XDATA0:
00287              secname = ".Xdat0";   /* XENIX data region, virtual 0 */
00288              break;
00289            default:
00290              secname = "";
00291            }
00292          flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
00293          break;
00294        case CORES_PROC:                   /* struct proc */
00295        case CORES_ITIMER:                 /* interval timers */
00296        case CORES_SCOUTSNAME:                    /* struct scoutsname */
00297          secname = NULL;    /* Ignore these */
00298          break;
00299        default:
00300          (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
00301                              chead.cs_stype);
00302          continue;
00303        }
00304 
00305       if (secname
00306          && !make_bfd_asection (abfd, secname, flags,
00307                              (bfd_size_type) chead.cs_vsize,
00308                              (bfd_vma) chead.cs_vaddr,
00309                              (file_ptr) chead.cs_sseek))
00310        goto fail;
00311 
00312     }
00313 
00314   return abfd->xvec;
00315 
00316  fail:
00317   if (abfd->tdata.any)
00318     {
00319       bfd_release (abfd, abfd->tdata.any);
00320       abfd->tdata.any = NULL;
00321     }
00322   bfd_section_list_clear (abfd);
00323   return NULL;
00324 }
00325 
00326 char *
00327 sco5_core_file_failing_command (abfd)
00328      bfd *abfd;
00329 {
00330   char *com = abfd->tdata.sco5_core_data->u.u_comm;
00331   if (*com)
00332     return com;
00333   else
00334     return NULL;
00335 }
00336 
00337 int
00338 sco5_core_file_failing_signal (ignore_abfd)
00339      bfd *ignore_abfd;
00340 {
00341   return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
00342          ? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
00343          : -1);
00344 }
00345 
00346 /* If somebody calls any byte-swapping routines, shoot them.  */
00347 static void
00348 swap_abort ()
00349 {
00350   abort (); /* This way doesn't require any declaration for ANSI to fuck up */
00351 }
00352 
00353 #define       NO_GET ((bfd_vma (*) (const void *)) swap_abort)
00354 #define       NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
00355 #define       NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
00356 #define       NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
00357 #define       NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
00358 #define       NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
00359 
00360 const bfd_target sco5_core_vec =
00361   {
00362     "sco5-core",
00363     bfd_target_unknown_flavour,
00364     BFD_ENDIAN_LITTLE,             /* target byte order */
00365     BFD_ENDIAN_LITTLE,             /* target headers byte order */
00366     (HAS_RELOC | EXEC_P |   /* object flags */
00367      HAS_LINENO | HAS_DEBUG |
00368      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00369     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
00370     0,                                              /* symbol prefix */
00371     ' ',                                            /* ar_pad_char */
00372     16,                                                    /* ar_max_namelen */
00373     NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */
00374     NO_GET, NO_GETS, NO_PUT,              /* 32 bit data */
00375     NO_GET, NO_GETS, NO_PUT,              /* 16 bit data */
00376     NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */
00377     NO_GET, NO_GETS, NO_PUT,              /* 32 bit hdrs */
00378     NO_GET, NO_GETS, NO_PUT,              /* 16 bit hdrs */
00379 
00380     {                       /* bfd_check_format */
00381       _bfd_dummy_target,           /* unknown format */
00382       _bfd_dummy_target,           /* object file */
00383       _bfd_dummy_target,           /* archive */
00384       sco5_core_file_p                    /* a core file */
00385     },
00386     {                       /* bfd_set_format */
00387       bfd_false, bfd_false,
00388       bfd_false, bfd_false
00389     },
00390     {                       /* bfd_write_contents */
00391       bfd_false, bfd_false,
00392       bfd_false, bfd_false
00393     },
00394 
00395     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
00396     BFD_JUMP_TABLE_COPY (_bfd_generic),
00397     BFD_JUMP_TABLE_CORE (sco5),
00398     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00399     BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
00400     BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00401     BFD_JUMP_TABLE_WRITE (_bfd_generic),
00402     BFD_JUMP_TABLE_LINK (_bfd_nolink),
00403     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00404 
00405     NULL,
00406 
00407     (PTR) 0                 /* backend_data */
00408   };