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