Home | History | Annotate | Download | only in bfd
      1 /* BFD back end for SCO5 core files (U-area and raw sections)
      2    Copyright (C) 1998-2014 Free Software Foundation, Inc.
      3    Written by Jouke Numan <jnuman (at) hiscom.nl>
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      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.
     11 
     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.
     16 
     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.  */
     21 
     22 #include "sysdep.h"
     23 #include "bfd.h"
     24 #include "libbfd.h"
     25 #include "libaout.h"		/* BFD a.out internal data structures */
     26 
     27 #include <stdio.h>
     28 #include <sys/types.h>
     29 #include <sys/param.h>
     30 #include <sys/dir.h>
     31 #include <signal.h>
     32 
     33 #include <sys/user.h>		/* After a.out.h  */
     34 #ifdef SCO5_CORE
     35 #include <sys/paccess.h>
     36 #include <sys/region.h>
     37 #endif
     38 
     39 struct sco5_core_struct
     40 {
     41   struct user u;
     42 };
     43 
     44 /* forward declarations */
     45 
     46 #define sco5_core_file_matches_executable_p generic_core_file_matches_executable_p
     47 #define sco5_core_file_pid _bfd_nocore_core_file_pid
     48 
     49 static asection *
     50 make_bfd_asection (bfd *abfd,
     51 		   const char *name,
     52 		   flagword flags,
     53 		   bfd_size_type size,
     54 		   bfd_vma vma,
     55 		   file_ptr filepos)
     56 {
     57   asection *asect;
     58 
     59   asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
     60   if (!asect)
     61     return NULL;
     62   asect->size = size;
     63   asect->vma = vma;
     64   asect->filepos = filepos;
     65   asect->alignment_power = 2;
     66 
     67   return asect;
     68 }
     69 
     70 static struct user *
     71 read_uarea (bfd *abfd, int filepos)
     72 {
     73   struct sco5_core_struct *rawptr;
     74   bfd_size_type amt = sizeof (struct sco5_core_struct);
     75 
     76   rawptr = (struct sco5_core_struct *) bfd_zmalloc (amt);
     77   if (rawptr == NULL)
     78     return NULL;
     79 
     80   abfd->tdata.sco5_core_data = rawptr;
     81 
     82   if (bfd_seek (abfd, (file_ptr) filepos, SEEK_SET) != 0
     83       || bfd_bread ((void *) &rawptr->u, (bfd_size_type) sizeof rawptr->u,
     84 		   abfd) != sizeof rawptr->u)
     85     {
     86       bfd_set_error (bfd_error_wrong_format);
     87       return NULL;
     88     }
     89 
     90   /* Sanity check perhaps??? */
     91   if (rawptr->u.u_dsize > 0x1000000)    /* Remember, it's in pages...  */
     92     {
     93       bfd_set_error (bfd_error_wrong_format);
     94       return NULL;
     95     }
     96   if (rawptr->u.u_ssize > 0x1000000)
     97     {
     98       bfd_set_error (bfd_error_wrong_format);
     99       return NULL;
    100     }
    101   return &rawptr->u;
    102 }
    103 
    104 const bfd_target *
    105 sco5_core_file_p (bfd *abfd)
    106 {
    107   int coffset_siz, val, nsecs, cheadoffs;
    108   int coresize;
    109   struct user *u;
    110   struct coreoffsets coffsets;
    111   struct coresecthead chead;
    112   char *secname;
    113   flagword flags;
    114 
    115   /* Read coreoffsets region at end of core (see core(FP)).  */
    116 
    117   {
    118     struct stat statbuf;
    119 
    120     if (bfd_stat (abfd, &statbuf) < 0)
    121       return NULL;
    122 
    123     coresize = statbuf.st_size;
    124   }
    125   /* Last long in core is sizeof struct coreoffsets, read it */
    126   if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz),
    127 		 SEEK_SET) != 0)
    128       || bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz,
    129 		   abfd) != sizeof coffset_siz)
    130     {
    131       bfd_set_error (bfd_error_wrong_format);
    132       return NULL;
    133     }
    134 
    135   /* Use it to seek start of coreoffsets region, read it and determine
    136      validity */
    137   if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0)
    138       || (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd)
    139 	  != sizeof coffsets)
    140       || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
    141     {
    142       bfd_set_error (bfd_error_wrong_format);
    143       return NULL;
    144     }
    145 
    146   if (coffsets.u_info == 1)
    147     {
    148       /* Old version, no section heads, read info from user struct */
    149 
    150       u = read_uarea (abfd, coffsets.u_user);
    151       if (! u)
    152 	goto fail;
    153 
    154       if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
    155 			      (bfd_size_type) coffsets.u_usize,
    156 			      0 - (bfd_vma) u->u_ar0,
    157 			      (file_ptr) coffsets.u_user))
    158 	goto fail;
    159 
    160       if (!make_bfd_asection (abfd, ".data",
    161 			      SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
    162 			      ((bfd_size_type) u->u_exdata.ux_dsize
    163 			       + u->u_exdata.ux_bsize),
    164 			      (bfd_vma) u->u_exdata.ux_datorg,
    165 			      (file_ptr) coffsets.u_data))
    166 	goto fail;
    167 
    168       if (!make_bfd_asection (abfd, ".stack",
    169 			      SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
    170 			      (bfd_size_type) u->u_ssize * NBPC,
    171 			      (bfd_vma) u->u_sub,
    172 			      (file_ptr) coffsets.u_stack))
    173 	goto fail;
    174 
    175       return abfd->xvec;		/* Done for version 1 */
    176     }
    177 
    178   /* Immediately before coreoffsets region is a long with offset in core
    179      to first coresecthead (CORES_OFFSETS), the long before this is the
    180      number of section heads in the list. Read both longs and read the
    181      coresecthead and check its validity */
    182 
    183   if ((bfd_seek (abfd,
    184 		 (file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz),
    185 		 SEEK_SET) != 0)
    186       || (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd)
    187 	  != sizeof nsecs)
    188       || (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs,
    189 		    abfd) != sizeof cheadoffs)
    190       || (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0)
    191       || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
    192 	  != sizeof chead)
    193       || (chead.cs_stype != CORES_OFFSETS)
    194       || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
    195     {
    196       bfd_set_error (bfd_error_wrong_format);
    197       goto fail;
    198     }
    199 
    200   /* OK, we believe you.  You're a core file (sure, sure).  */
    201 
    202   /* Now loop over all regions and map them */
    203   nsecs--;				/* We've seen CORES_OFFSETS already */
    204   for (; nsecs; nsecs--)
    205     {
    206       if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0)
    207 	  || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
    208 	      != sizeof chead))
    209 	{
    210 	  bfd_set_error (bfd_error_wrong_format);
    211 	  goto fail;
    212 	}
    213 
    214       switch (chead.cs_stype)
    215 	{
    216 	case CORES_MAGIC:			/* Core header, check magic */
    217 	  if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
    218 	    {
    219 	      bfd_set_error (bfd_error_wrong_format);
    220 	      goto fail;
    221 	    }
    222 	  secname = NULL;
    223 	  nsecs++;				/* MAGIC not in section cnt!*/
    224 	  break;
    225 	case CORES_UAREA:			/* U-area, read in tdata */
    226 	  u = read_uarea (abfd, chead.cs_sseek);
    227 	  if (! u)
    228 	    goto fail;
    229 
    230 	  /* This is tricky.  As the "register section", we give them
    231 	     the entire upage and stack.  u.u_ar0 points to where
    232 	     "register 0" is stored.  There are two tricks with this,
    233 	     though.  One is that the rest of the registers might be
    234 	     at positive or negative (or both) displacements from
    235 	     *u_ar0.  The other is that u_ar0 is sometimes an absolute
    236 	     address in kernel memory, and on other systems it is an
    237 	     offset from the beginning of the `struct user'.
    238 
    239 	     As a practical matter, we don't know where the registers
    240 	     actually are, so we have to pass the whole area to GDB.
    241 	     We encode the value of u_ar0 by setting the .regs section
    242 	     up so that its virtual memory address 0 is at the place
    243 	     pointed to by u_ar0 (by setting the vma of the start of
    244 	     the section to -u_ar0).  GDB uses this info to locate the
    245 	     regs, using minor trickery to get around the
    246 	     offset-or-absolute-addr problem.  */
    247 
    248 	  chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
    249 
    250 	  secname = ".reg";
    251 	  flags = SEC_HAS_CONTENTS;
    252 
    253 	  break;
    254 	case CORES_PREGION:			/* A program region, map it */
    255 	  switch (chead.cs_x.csx_preg.csxp_rtyp)
    256 	    {
    257 	    case PT_DATA:
    258 	      secname = ".data";	/* Data region.		 */
    259 	      break;
    260 	    case PT_STACK:
    261 	      secname = ".stack";	/* Stack region.	 */
    262 	      break;
    263 	    case PT_SHMEM:
    264 	      secname = ".shmem";	/* Shared memory	 */
    265 	      break;
    266 	    case PT_LIBDAT:
    267 	      secname = ".libdat";	/* Shared library data	 */
    268 	      break;
    269 	    case PT_V86:
    270 	      secname = ".virt86";	/* Virtual 8086 mode	 */
    271 	      break;
    272 	    case PT_SHFIL:
    273 	      secname = ".mmfile";	/* Memory mapped file	 */
    274 	      break;
    275 	    case PT_XDATA0:
    276 	      secname = ".Xdat0";	/* XENIX data region, virtual 0 */
    277 	      break;
    278 	    default:
    279 	      secname = "";
    280 	    }
    281 	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
    282 	  break;
    283 	case CORES_PROC:			/* struct proc */
    284 	case CORES_ITIMER:			/* interval timers */
    285 	case CORES_SCOUTSNAME:			/* struct scoutsname */
    286 	  secname = NULL;	/* Ignore these */
    287 	  break;
    288 	default:
    289 	  (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
    290 				 chead.cs_stype);
    291 	  continue;
    292 	}
    293 
    294       if (secname
    295 	  && !make_bfd_asection (abfd, secname, flags,
    296 				 (bfd_size_type) chead.cs_vsize,
    297 				 (bfd_vma) chead.cs_vaddr,
    298 				 (file_ptr) chead.cs_sseek))
    299 	goto fail;
    300 
    301     }
    302 
    303   return abfd->xvec;
    304 
    305  fail:
    306   if (abfd->tdata.any)
    307     {
    308       bfd_release (abfd, abfd->tdata.any);
    309       abfd->tdata.any = NULL;
    310     }
    311   bfd_section_list_clear (abfd);
    312   return NULL;
    313 }
    314 
    315 char *
    316 sco5_core_file_failing_command (bfd *abfd)
    317 {
    318   char *com = abfd->tdata.sco5_core_data->u.u_comm;
    319   if (*com)
    320     return com;
    321   else
    322     return NULL;
    323 }
    324 
    325 int
    326 sco5_core_file_failing_signal (bfd *ignore_abfd)
    327 {
    328   return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
    329 	  ? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
    330 	  : -1);
    331 }
    332 
    333 /* If somebody calls any byte-swapping routines, shoot them.  */
    334 static void
    335 swap_abort (void)
    336 {
    337   abort (); /* This way doesn't require any declaration for ANSI to fuck up */
    338 }
    339 
    340 #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
    341 #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
    342 #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
    343 #define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
    344 #define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
    345 #define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
    346 
    347 const bfd_target core_sco5_vec =
    348   {
    349     "sco5-core",
    350     bfd_target_unknown_flavour,
    351     BFD_ENDIAN_LITTLE,	       /* target byte order */
    352     BFD_ENDIAN_LITTLE,	       /* target headers byte order */
    353     (HAS_RELOC | EXEC_P |	/* object flags */
    354      HAS_LINENO | HAS_DEBUG |
    355      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
    356     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
    357     0,				/* symbol prefix */
    358     ' ',			/* ar_pad_char */
    359     16,				/* ar_max_namelen */
    360     0,				/* match priority.  */
    361     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
    362     NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
    363     NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
    364     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
    365     NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
    366     NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
    367 
    368     {				/* bfd_check_format */
    369       _bfd_dummy_target,		/* unknown format */
    370       _bfd_dummy_target,		/* object file */
    371       _bfd_dummy_target,		/* archive */
    372       sco5_core_file_p			/* a core file */
    373     },
    374     {				/* bfd_set_format */
    375       bfd_false, bfd_false,
    376       bfd_false, bfd_false
    377     },
    378     {				/* bfd_write_contents */
    379       bfd_false, bfd_false,
    380       bfd_false, bfd_false
    381     },
    382 
    383     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
    384     BFD_JUMP_TABLE_COPY (_bfd_generic),
    385     BFD_JUMP_TABLE_CORE (sco5),
    386     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
    387     BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    388     BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    389     BFD_JUMP_TABLE_WRITE (_bfd_generic),
    390     BFD_JUMP_TABLE_LINK (_bfd_nolink),
    391     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    392 
    393     NULL,
    394 
    395     NULL			/* backend_data */
    396   };
    397