2007-07-03 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / bfd / sco5-core.c
CommitLineData
252b5132 1/* BFD back end for SCO5 core files (U-area and raw sections)
3db64b00 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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 21
252b5132 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
252b5132 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 */
9b818146 34#ifdef SCO5_CORE
252b5132
RH
35#include <sys/paccess.h>
36#include <sys/region.h>
9b818146 37#endif
252b5132
RH
38
39struct sco5_core_struct
40{
41 struct user u;
42};
43
44/* forward declarations */
45
b34976b6
AM
46static asection *make_bfd_asection
47 PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr));
252b5132
RH
48static struct user *read_uarea PARAMS ((bfd *, int));
49const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
50char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
51int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
69d246d9 52#define sco5_core_file_matches_executable_p generic_core_file_matches_executable_p
252b5132
RH
53static void swap_abort PARAMS ((void));
54
55static asection *
eea6121a 56make_bfd_asection (abfd, name, flags, size, vma, filepos)
252b5132
RH
57 bfd *abfd;
58 const char *name;
59 flagword flags;
eea6121a 60 bfd_size_type size;
252b5132
RH
61 bfd_vma vma;
62 file_ptr filepos;
63{
64 asection *asect;
65
117ed4f8 66 asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
252b5132
RH
67 if (!asect)
68 return NULL;
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
252b5132
RH
346/* If somebody calls any byte-swapping routines, shoot them. */
347static void
7b82c249 348swap_abort ()
252b5132 349{
7b82c249 350 abort (); /* This way doesn't require any declaration for ANSI to fuck up */
252b5132 351}
8ce8c090 352
edeb6e24
AM
353#define NO_GET ((bfd_vma (*) (const void *)) swap_abort)
354#define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
355#define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
8ce8c090
AM
356#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
357#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
358#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
252b5132
RH
359
360const bfd_target sco5_core_vec =
361 {
362 "sco5-core",
363 bfd_target_unknown_flavour,
b34976b6
AM
364 BFD_ENDIAN_LITTLE, /* target byte order */
365 BFD_ENDIAN_LITTLE, /* target headers byte order */
366 (HAS_RELOC | EXEC_P | /* object flags */
252b5132
RH
367 HAS_LINENO | HAS_DEBUG |
368 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
369 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
b34976b6
AM
370 0, /* symbol prefix */
371 ' ', /* ar_pad_char */
372 16, /* ar_max_namelen */
8ce8c090 373 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */
edeb6e24
AM
374 NO_GET, NO_GETS, NO_PUT, /* 32 bit data */
375 NO_GET, NO_GETS, NO_PUT, /* 16 bit data */
8ce8c090 376 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */
edeb6e24
AM
377 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */
378 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */
b34976b6
AM
379
380 { /* bfd_check_format */
8ce8c090
AM
381 _bfd_dummy_target, /* unknown format */
382 _bfd_dummy_target, /* object file */
383 _bfd_dummy_target, /* archive */
384 sco5_core_file_p /* a core file */
252b5132 385 },
b34976b6 386 { /* bfd_set_format */
8ce8c090
AM
387 bfd_false, bfd_false,
388 bfd_false, bfd_false
252b5132 389 },
b34976b6 390 { /* bfd_write_contents */
8ce8c090
AM
391 bfd_false, bfd_false,
392 bfd_false, bfd_false
252b5132
RH
393 },
394
3f3c5c34
AM
395 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
396 BFD_JUMP_TABLE_COPY (_bfd_generic),
397 BFD_JUMP_TABLE_CORE (sco5),
398 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
399 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
400 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
401 BFD_JUMP_TABLE_WRITE (_bfd_generic),
402 BFD_JUMP_TABLE_LINK (_bfd_nolink),
403 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
252b5132 404
c3c89269 405 NULL,
7b82c249 406
b34976b6 407 (PTR) 0 /* backend_data */
8ce8c090 408 };
This page took 0.424306 seconds and 4 git commands to generate.