packaging: Enable testing infrastructure
[external/binutils.git] / bfd / sco5-core.c
1 /* BFD back end for SCO5 core files (U-area and raw sections)
2    Copyright (C) 1998-2019 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 *
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_bool_bfd_false_error, bfd_false,
376       _bfd_bool_bfd_false_error, bfd_false
377     },
378     {                           /* bfd_write_contents */
379       _bfd_bool_bfd_false_error, bfd_false,
380       _bfd_bool_bfd_false_error, 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   };