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