]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/sco5-core.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / bfd / sco5-core.c
1 /* BFD back end for SCO5 core files (U-area and raw sections)
2 Copyright 1998 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "libaout.h" /* BFD a.out internal data structures */
25
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <signal.h>
31
32 #include <sys/user.h> /* After a.out.h */
33 #include <sys/paccess.h>
34 #include <sys/region.h>
35
36 struct sco5_core_struct
37 {
38 struct user u;
39 };
40
41 /* forward declarations */
42
43 static asection *
44 make_bfd_asection PARAMS ((bfd *, const char *, flagword, bfd_size_type,
45 bfd_vma, file_ptr));
46 static asymbol *sco5_core_make_empty_symbol PARAMS ((bfd *));
47 static struct user *read_uarea PARAMS ((bfd *, int));
48 const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
49 char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
50 int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
51 boolean sco5_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
52 bfd *exec_bfd));
53 static void swap_abort PARAMS ((void));
54
55 static asection *
56 make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
57 bfd *abfd;
58 const char *name;
59 flagword flags;
60 bfd_size_type _raw_size;
61 bfd_vma vma;
62 file_ptr filepos;
63 {
64 asection *asect;
65
66 asect = bfd_make_section_anyway (abfd, name);
67 if (!asect)
68 return NULL;
69 asect->flags = flags;
70 asect->_raw_size = _raw_size;
71 asect->vma = vma;
72 asect->filepos = filepos;
73 asect->alignment_power = 2;
74
75 return asect;
76 }
77
78 static asymbol *
79 sco5_core_make_empty_symbol (abfd)
80 bfd *abfd;
81 {
82 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
83 if (new)
84 new->the_bfd = abfd;
85 return new;
86 }
87
88 static struct user *
89 read_uarea(abfd, filepos)
90 bfd *abfd;
91 int filepos;
92
93 {
94 struct sco5_core_struct *rawptr;
95
96 rawptr = ((struct sco5_core_struct *)
97 bfd_zmalloc (sizeof (struct sco5_core_struct)));
98 if (rawptr == NULL)
99 return NULL;
100
101 abfd->tdata.sco5_core_data = rawptr;
102
103 if ((bfd_seek (abfd, filepos, SEEK_SET) != 0)
104 || (bfd_read ((void *)&rawptr->u, 1, sizeof rawptr->u, abfd)
105 != sizeof rawptr->u))
106 {
107 bfd_set_error (bfd_error_wrong_format);
108 return NULL;
109 }
110
111 /* Sanity check perhaps??? */
112 if (rawptr->u.u_dsize > 0x1000000) /* Remember, it's in pages... */
113 {
114 bfd_set_error (bfd_error_wrong_format);
115 return NULL;
116 }
117 if (rawptr->u.u_ssize > 0x1000000)
118 {
119 bfd_set_error (bfd_error_wrong_format);
120 return NULL;
121 }
122 return &rawptr->u;
123 }
124
125 /* ARGSUSED */
126 const bfd_target *
127 sco5_core_file_p (abfd)
128 bfd *abfd;
129 {
130 int coffset_siz, val, nsecs, cheadoffs;
131 int coresize;
132 struct user *u;
133 struct coreoffsets coffsets;
134 struct coresecthead chead;
135 char *secname;
136 flagword flags;
137
138 /* Read coreoffsets region at end of core (see core(FP)) */
139
140 {
141 FILE *stream = bfd_cache_lookup (abfd);
142 struct stat statbuf;
143 if (stream == NULL)
144 return NULL;
145 if (fstat (fileno (stream), &statbuf) < 0)
146 {
147 bfd_set_error (bfd_error_system_call);
148 return NULL;
149 }
150 coresize = statbuf.st_size;
151 }
152 /* Last long in core is sizeof struct coreoffsets, read it */
153 if ((bfd_seek (abfd, coresize-sizeof coffset_siz, SEEK_SET) != 0)
154 || (bfd_read ((void *)&coffset_siz, 1, sizeof coffset_siz, abfd)
155 != sizeof coffset_siz) )
156 {
157 bfd_set_error (bfd_error_wrong_format);
158 return NULL;
159 }
160
161 /* Use it to seek start of coreoffsets region, read it and determine
162 validity */
163 if ((bfd_seek (abfd, coresize-coffset_siz, SEEK_SET) != 0)
164 || (bfd_read ((void *)&coffsets, 1, sizeof coffsets, abfd)
165 != sizeof coffsets)
166 || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
167 {
168 bfd_set_error (bfd_error_wrong_format);
169 return NULL;
170 }
171
172
173 if (coffsets.u_info == 1)
174 {
175 /* Old version, no section heads, read info from user struct */
176
177 u = read_uarea(abfd, coffsets.u_user);
178 if (! u)
179 return NULL;
180
181 if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
182 (bfd_size_type) coffsets.u_usize,
183 0 - (bfd_vma) u->u_ar0,
184 (file_ptr) coffsets.u_user))
185 return NULL;
186
187 if (!make_bfd_asection (abfd, ".data",
188 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
189 ((bfd_size_type) u->u_exdata.ux_dsize
190 + u->u_exdata.ux_bsize),
191 (bfd_vma) u->u_exdata.ux_datorg,
192 (file_ptr) coffsets.u_data))
193 return NULL;
194
195 if (!make_bfd_asection (abfd, ".stack",
196 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
197 (bfd_size_type) u->u_ssize * NBPC,
198 (bfd_vma) u->u_sub,
199 (file_ptr) coffsets.u_stack))
200 return NULL;
201
202 return abfd->xvec; /* Done for version 1 */
203 }
204
205 /* Immediately before coreoffsets region is a long with offset in core
206 to first coresecthead (CORES_OFFSETS), the long before this is the
207 number of section heads in the list. Read both longs and read the
208 coresecthead and check its validity */
209
210 if ((bfd_seek (abfd,
211 coresize - coffset_siz - 2 * sizeof coffset_siz,
212 SEEK_SET) != 0)
213 || (bfd_read ((void *)&nsecs, 1, sizeof nsecs, abfd) != sizeof nsecs)
214 || (bfd_read ((void *)&cheadoffs, 1, sizeof cheadoffs, abfd)
215 != sizeof cheadoffs)
216 || (bfd_seek (abfd, cheadoffs, SEEK_SET) != 0)
217 || (bfd_read ((void *)&chead, 1, sizeof chead, abfd) != sizeof chead)
218 || (chead.cs_stype != CORES_OFFSETS)
219 || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
220 {
221 bfd_set_error (bfd_error_wrong_format);
222 return NULL;
223 }
224
225 /* OK, we believe you. You're a core file (sure, sure). */
226
227 /* Now loop over all regions and map them */
228 nsecs--; /* We've seen CORES_OFFSETS already */
229 for (; nsecs; nsecs--)
230 {
231 if ((bfd_seek (abfd, chead.cs_hseek, SEEK_SET) != 0)
232 || bfd_read ((void *)&chead, 1, sizeof chead, abfd) != sizeof chead)
233 {
234 bfd_set_error (bfd_error_wrong_format);
235 return NULL;
236 }
237
238 switch (chead.cs_stype)
239 {
240 case CORES_MAGIC: /* Core header, check magic */
241 if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
242 {
243 bfd_set_error (bfd_error_wrong_format);
244 return NULL;
245 }
246 secname = NULL;
247 nsecs++; /* MAGIC not in section cnt!*/
248 break;
249 case CORES_UAREA: /* U-area, read in tdata */
250 u = read_uarea(abfd, chead.cs_sseek);
251 if (! u)
252 return NULL;
253
254 /* This is tricky. As the "register section", we give them
255 the entire upage and stack. u.u_ar0 points to where
256 "register 0" is stored. There are two tricks with this,
257 though. One is that the rest of the registers might be
258 at positive or negative (or both) displacements from
259 *u_ar0. The other is that u_ar0 is sometimes an absolute
260 address in kernel memory, and on other systems it is an
261 offset from the beginning of the `struct user'.
262
263 As a practical matter, we don't know where the registers
264 actually are, so we have to pass the whole area to GDB.
265 We encode the value of u_ar0 by setting the .regs section
266 up so that its virtual memory address 0 is at the place
267 pointed to by u_ar0 (by setting the vma of the start of
268 the section to -u_ar0). GDB uses this info to locate the
269 regs, using minor trickery to get around the
270 offset-or-absolute-addr problem. */
271
272 chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
273
274
275 secname = ".reg";
276 flags = SEC_HAS_CONTENTS;
277
278 break;
279 case CORES_PREGION: /* A program region, map it */
280 switch (chead.cs_x.csx_preg.csxp_rtyp)
281 {
282 case PT_DATA:
283 secname = ".data"; /* Data region. */
284 break;
285 case PT_STACK:
286 secname = ".stack"; /* Stack region. */
287 break;
288 case PT_SHMEM:
289 secname = ".shmem"; /* Shared memory */
290 break;
291 case PT_LIBDAT:
292 secname = ".libdat"; /* Shared library data */
293 break;
294 case PT_V86:
295 secname = ".virt86"; /* Virtual 8086 mode */
296 break;
297 case PT_SHFIL:
298 secname = ".mmfile"; /* Memory mapped file */
299 break;
300 case PT_XDATA0:
301 secname = ".Xdat0"; /* XENIX data region, virtual 0 */
302 break;
303 default:
304 secname = "";
305 }
306 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
307 break;
308 case CORES_PROC: /* struct proc */
309 case CORES_ITIMER: /* interval timers */
310 case CORES_SCOUTSNAME: /* struct scoutsname */
311 secname = NULL; /* Ignore these */
312 break;
313 default:
314 (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
315 chead.cs_stype);
316 continue;
317 }
318
319 if (secname
320 && !make_bfd_asection (abfd, secname, flags,
321 (bfd_size_type) chead.cs_vsize,
322 (bfd_vma) chead.cs_vaddr,
323 (file_ptr) chead.cs_sseek))
324 return NULL;
325
326 }
327
328 return abfd->xvec;
329
330 }
331
332 char *
333 sco5_core_file_failing_command (abfd)
334 bfd *abfd;
335 {
336 char *com = abfd->tdata.sco5_core_data->u.u_comm;
337 if (*com)
338 return com;
339 else
340 return NULL;
341 }
342
343 /* ARGSUSED */
344 int
345 sco5_core_file_failing_signal (ignore_abfd)
346 bfd *ignore_abfd;
347 {
348 return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
349 ? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
350 : -1);
351 }
352
353 /* ARGSUSED */
354 boolean
355 sco5_core_file_matches_executable_p (core_bfd, exec_bfd)
356 bfd *core_bfd, *exec_bfd;
357 {
358 return true; /* FIXME, We have no way of telling at this point */
359 }
360
361 #define sco5_core_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
362 #define sco5_core_get_symtab _bfd_nosymbols_get_symtab
363 #define sco5_core_print_symbol _bfd_nosymbols_print_symbol
364 #define sco5_core_get_symbol_info _bfd_nosymbols_get_symbol_info
365 #define sco5_core_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
366 #define sco5_core_get_lineno _bfd_nosymbols_get_lineno
367 #define sco5_core_find_nearest_line _bfd_nosymbols_find_nearest_line
368 #define sco5_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
369 #define sco5_core_read_minisymbols _bfd_nosymbols_read_minisymbols
370 #define sco5_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
371
372 /* If somebody calls any byte-swapping routines, shoot them. */
373 static void
374 swap_abort()
375 {
376 abort(); /* This way doesn't require any declaration for ANSI to fuck up */
377 }
378 #define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
379 #define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
380 #define NO_SIGNED_GET \
381 ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
382
383 const bfd_target sco5_core_vec =
384 {
385 "sco5-core",
386 bfd_target_unknown_flavour,
387 BFD_ENDIAN_LITTLE, /* target byte order */
388 BFD_ENDIAN_LITTLE, /* target headers byte order */
389 (HAS_RELOC | EXEC_P | /* object flags */
390 HAS_LINENO | HAS_DEBUG |
391 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
392 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
393 0, /* symbol prefix */
394 ' ', /* ar_pad_char */
395 16, /* ar_max_namelen */
396 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
397 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
398 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
399 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
400 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
401 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
402
403 { /* bfd_check_format */
404 _bfd_dummy_target, /* unknown format */
405 _bfd_dummy_target, /* object file */
406 _bfd_dummy_target, /* archive */
407 sco5_core_file_p /* a core file */
408 },
409 { /* bfd_set_format */
410 bfd_false, bfd_false,
411 bfd_false, bfd_false
412 },
413 { /* bfd_write_contents */
414 bfd_false, bfd_false,
415 bfd_false, bfd_false
416 },
417
418 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
419 BFD_JUMP_TABLE_COPY (_bfd_generic),
420 BFD_JUMP_TABLE_CORE (sco5),
421 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
422 BFD_JUMP_TABLE_SYMBOLS (sco5_core),
423 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
424 BFD_JUMP_TABLE_WRITE (_bfd_generic),
425 BFD_JUMP_TABLE_LINK (_bfd_nolink),
426 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
427
428 (PTR) 0 /* backend_data */
429 };