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