1 /* BFD back end for SCO5 core files (U-area and raw sections)
2    Copyright (C) 1998-2021 Free Software Foundation, Inc.
3    Written by Jouke Numan <jnuman@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 *
make_bfd_asection(bfd * abfd,const char * name,flagword flags,bfd_size_type size,bfd_vma vma,file_ptr filepos)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 *
read_uarea(bfd * abfd,int filepos)71 read_uarea (bfd *abfd, int filepos)
72 {
73   struct sco5_core_struct *rawptr;
74   size_t 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 bfd_cleanup
sco5_core_file_p(bfd * abfd)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 _bfd_no_cleanup;		/* 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 _bfd_no_cleanup;
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 *
sco5_core_file_failing_command(bfd * abfd)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
sco5_core_file_failing_signal(bfd * ignore_abfd)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
swap_abort(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     TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
362     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
363     NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
364     NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
365     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
366     NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
367     NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
368 
369     {				/* bfd_check_format */
370       _bfd_dummy_target,		/* unknown format */
371       _bfd_dummy_target,		/* object file */
372       _bfd_dummy_target,		/* archive */
373       sco5_core_file_p			/* a core file */
374     },
375     {				/* bfd_set_format */
376       _bfd_bool_bfd_false_error,
377       _bfd_bool_bfd_false_error,
378       _bfd_bool_bfd_false_error,
379       _bfd_bool_bfd_false_error
380     },
381     {				/* bfd_write_contents */
382       _bfd_bool_bfd_false_error,
383       _bfd_bool_bfd_false_error,
384       _bfd_bool_bfd_false_error,
385       _bfd_bool_bfd_false_error
386     },
387 
388     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
389     BFD_JUMP_TABLE_COPY (_bfd_generic),
390     BFD_JUMP_TABLE_CORE (sco5),
391     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
392     BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
393     BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
394     BFD_JUMP_TABLE_WRITE (_bfd_generic),
395     BFD_JUMP_TABLE_LINK (_bfd_nolink),
396     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
397 
398     NULL,
399 
400     NULL			/* backend_data */
401   };
402