source: trunk/binutils/bfd/trad-core.c

Last change on this file was 729, checked in by zap, 22 years ago

.

  • Property cvs2svn:cvs-rev set to 1.5
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 11.4 KB
Line 
1/* BFD back end for traditional Unix core files (U-area and raw sections)
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
3 2000, 2001, 2002
4 Free Software Foundation, Inc.
5 Written by John Gilmore of Cygnus Support.
6
7This file is part of BFD, the Binary File Descriptor library.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23#include "bfd.h"
24#include "sysdep.h"
25#include "libbfd.h"
26#include "libaout.h" /* BFD a.out internal data structures */
27
28#include <sys/param.h>
29#ifdef HAVE_DIRENT_H
30# include <dirent.h>
31#else
32# ifdef HAVE_SYS_NDIR_H
33# include <sys/ndir.h>
34# endif
35# ifdef HAVE_SYS_DIR_H
36# include <sys/dir.h>
37# endif
38# ifdef HAVE_NDIR_H
39# include <ndir.h>
40# endif
41#endif
42#include <signal.h>
43
44#include <sys/user.h> /* After a.out.h */
45
46#ifdef TRAD_HEADER
47#include TRAD_HEADER
48#endif
49
50struct trad_core_struct
51{
52 asection *data_section;
53#ifdef EMX
54 asection *heap_section;
55#endif /* EMX */
56 asection *stack_section;
57 asection *reg_section;
58 struct user u;
59};
60
61#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
62#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
63#ifdef EMX
64#define core_heapsec(bfd) ((bfd)->tdata.trad_core_data->heap_section)
65#endif /* EMX */
66#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
67#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
68
69/* forward declarations */
70
71const bfd_target *trad_unix_core_file_p PARAMS ((bfd *abfd));
72char * trad_unix_core_file_failing_command PARAMS ((bfd *abfd));
73int trad_unix_core_file_failing_signal PARAMS ((bfd *abfd));
74bfd_boolean trad_unix_core_file_matches_executable_p
75 PARAMS ((bfd *core_bfd, bfd *exec_bfd));
76static void swap_abort PARAMS ((void));
77
78/* Handle 4.2-style (and perhaps also sysV-style) core dump file. */
79
80/* ARGSUSED */
81const bfd_target *
82trad_unix_core_file_p (abfd)
83 bfd *abfd;
84
85{
86 int val;
87 struct user u;
88 struct trad_core_struct *rawptr;
89 bfd_size_type amt;
90
91#ifdef TRAD_CORE_USER_OFFSET
92 /* If defined, this macro is the file position of the user struct. */
93 if (bfd_seek (abfd, (file_ptr) TRAD_CORE_USER_OFFSET, SEEK_SET) != 0)
94 return 0;
95#endif
96
97 val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd);
98 if (val != sizeof u)
99 {
100 /* Too small to be a core file */
101 bfd_set_error (bfd_error_wrong_format);
102 return 0;
103 }
104
105 /* Sanity check perhaps??? */
106#ifdef EMX
107 if (u.u_magic != UMAGIC)
108 return 0;
109#else /* !EMX */
110 if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */
111 {
112 bfd_set_error (bfd_error_wrong_format);
113 return 0;
114 }
115 if (u.u_ssize > 0x1000000)
116 {
117 bfd_set_error (bfd_error_wrong_format);
118 return 0;
119 }
120
121 /* Check that the size claimed is no greater than the file size. */
122 {
123 FILE *stream = bfd_cache_lookup (abfd);
124 struct stat statbuf;
125 if (stream == NULL)
126 return 0;
127 if (fstat (fileno (stream), &statbuf) < 0)
128 {
129 bfd_set_error (bfd_error_system_call);
130 return 0;
131 }
132 if ((unsigned long) (NBPG * (UPAGES + u.u_dsize
133#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
134 - u.u_tsize
135#endif
136 + u.u_ssize))
137 > (unsigned long) statbuf.st_size)
138 {
139 bfd_set_error (bfd_error_wrong_format);
140 return 0;
141 }
142#ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE
143 if ((unsigned long) (NBPG * (UPAGES + u.u_dsize + u.u_ssize)
144#ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
145 /* Some systems write the file too big. */
146 + TRAD_CORE_EXTRA_SIZE_ALLOWED
147#endif
148 )
149 < (unsigned long) statbuf.st_size)
150 {
151 /* The file is too big. Maybe it's not a core file
152 or we otherwise have bad values for u_dsize and u_ssize). */
153 bfd_set_error (bfd_error_wrong_format);
154 return 0;
155 }
156#endif
157 }
158#endif /* !EMX */
159
160 /* OK, we believe you. You're a core file (sure, sure). */
161
162 /* Allocate both the upage and the struct core_data at once, so
163 a single free() will free them both. */
164 amt = sizeof (struct trad_core_struct);
165 rawptr = (struct trad_core_struct *) bfd_zmalloc (amt);
166 if (rawptr == NULL)
167 return 0;
168
169 abfd->tdata.trad_core_data = rawptr;
170
171 rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
172
173 /* Create the sections. */
174
175 core_stacksec(abfd) = bfd_make_section_anyway (abfd, ".stack");
176 if (core_stacksec (abfd) == NULL)
177 goto fail;
178 core_datasec (abfd) = bfd_make_section_anyway (abfd, ".data");
179 if (core_datasec (abfd) == NULL)
180 goto fail;
181 core_regsec (abfd) = bfd_make_section_anyway (abfd, ".reg");
182 if (core_regsec (abfd) == NULL)
183 goto fail;
184#ifdef EMX
185 core_heapsec (abfd) = bfd_make_section_anyway (abfd, ".heap");
186 if (core_heapsec (abfd) == NULL)
187 goto fail;
188#endif /* EMX */
189
190 core_stacksec (abfd)->name = ".stack";
191 core_datasec (abfd)->name = ".data";
192#ifdef EMX
193 core_heapsec (abfd)->name = ".heap";
194#endif /* EMX */
195 core_regsec (abfd)->name = ".reg";
196
197 core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
198 core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
199 core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
200#ifdef EMX
201 core_heapsec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
202#endif /* EMX */
203
204#ifdef EMX
205 core_datasec (abfd)->_raw_size = u.u_data_end - u.u_data_base;
206 core_heapsec (abfd)->_raw_size = u.u_heap_brk - u.u_heap_base;
207 core_stacksec (abfd)->_raw_size = u.u_stack_end - u.u_stack_low;
208 core_regsec (abfd)->_raw_size = sizeof (struct user);
209#else /* not EMX */
210 core_datasec (abfd)->_raw_size = NBPG * u.u_dsize
211#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
212 - NBPG * u.u_tsize
213#endif
214 ;
215 core_stacksec (abfd)->_raw_size = NBPG * u.u_ssize;
216 core_regsec (abfd)->_raw_size = NBPG * UPAGES; /* Larger than sizeof struct u */
217#endif /* not EMX */
218
219 /* What a hack... we'd like to steal it from the exec file,
220 since the upage does not seem to provide it. FIXME. */
221#ifdef EMX
222 core_datasec (abfd)->vma = u.u_data_base;
223 core_heapsec (abfd)->vma = u.u_heap_base;
224 core_stacksec (abfd)->vma = u.u_stack_low;
225#else /* not EMX */
226#ifdef HOST_DATA_START_ADDR
227 core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
228#else
229 core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
230#endif
231
232#ifdef HOST_STACK_START_ADDR
233 core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
234#else
235 core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
236#endif
237#endif /* not EMX */
238
239 /* This is tricky. As the "register section", we give them the entire
240 upage and stack. u.u_ar0 points to where "register 0" is stored.
241 There are two tricks with this, though. One is that the rest of the
242 registers might be at positive or negative (or both) displacements
243 from *u_ar0. The other is that u_ar0 is sometimes an absolute address
244 in kernel memory, and on other systems it is an offset from the beginning
245 of the `struct user'.
246
247 As a practical matter, we don't know where the registers actually are,
248 so we have to pass the whole area to GDB. We encode the value of u_ar0
249 by setting the .regs section up so that its virtual memory address
250 0 is at the place pointed to by u_ar0 (by setting the vma of the start
251 of the section to -u_ar0). GDB uses this info to locate the regs,
252 using minor trickery to get around the offset-or-absolute-addr problem. */
253 core_regsec (abfd)->vma = - (bfd_vma) (unsigned long) u.u_ar0;
254
255#ifdef EMX
256 core_datasec (abfd)->filepos = u.u_data_off;
257 core_heapsec (abfd)->filepos = u.u_heap_off;
258 core_stacksec (abfd)->filepos = u.u_stack_off;
259#else /* not EMX */
260 core_datasec (abfd)->filepos = NBPG * UPAGES;
261 core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize
262#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
263 - NBPG * u.u_tsize
264#endif
265 ;
266#endif /* not EMX */
267
268 core_regsec (abfd)->filepos = 0; /* Register segment is the upage */
269
270 /* Align to word at least */
271 core_stacksec (abfd)->alignment_power = 2;
272 core_datasec (abfd)->alignment_power = 2;
273#ifdef EMX
274 core_heapsec (abfd)->alignment_power = 2;
275#endif /* EMX */
276 core_regsec (abfd)->alignment_power = 2;
277
278 return abfd->xvec;
279
280 fail:
281 bfd_release (abfd, abfd->tdata.any);
282 abfd->tdata.any = NULL;
283 bfd_section_list_clear (abfd);
284 return NULL;
285}
286
287char *
288trad_unix_core_file_failing_command (abfd)
289 bfd *abfd;
290{
291#ifndef NO_CORE_COMMAND
292 char *com = abfd->tdata.trad_core_data->u.u_comm;
293 if (*com)
294 return com;
295 else
296#endif
297 return 0;
298}
299
300/* ARGSUSED */
301int
302trad_unix_core_file_failing_signal (ignore_abfd)
303 bfd *ignore_abfd ATTRIBUTE_UNUSED;
304{
305#ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
306 return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
307#else
308 return -1; /* FIXME, where is it? */
309#endif
310}
311
312/* ARGSUSED */
313bfd_boolean
314trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd)
315 bfd *core_bfd ATTRIBUTE_UNUSED;
316 bfd *exec_bfd ATTRIBUTE_UNUSED;
317{
318 return TRUE; /* FIXME, We have no way of telling at this point */
319}
320
321
322/* If somebody calls any byte-swapping routines, shoot them. */
323static void
324swap_abort ()
325{
326 abort (); /* This way doesn't require any declaration for ANSI to fuck up */
327}
328#define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
329#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
330#define NO_SIGNED_GET \
331 ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
332
333const bfd_target trad_core_vec =
334 {
335 "trad-core",
336 bfd_target_unknown_flavour,
337 BFD_ENDIAN_UNKNOWN, /* target byte order */
338 BFD_ENDIAN_UNKNOWN, /* target headers byte order */
339 (HAS_RELOC | EXEC_P | /* object flags */
340 HAS_LINENO | HAS_DEBUG |
341 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
342 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
343 0, /* symbol prefix */
344 ' ', /* ar_pad_char */
345 16, /* ar_max_namelen */
346 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
347 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
348 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
349 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
350 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
351 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
352
353 { /* bfd_check_format */
354 _bfd_dummy_target, /* unknown format */
355 _bfd_dummy_target, /* object file */
356 _bfd_dummy_target, /* archive */
357 trad_unix_core_file_p /* a core file */
358 },
359 { /* bfd_set_format */
360 bfd_false, bfd_false,
361 bfd_false, bfd_false
362 },
363 { /* bfd_write_contents */
364 bfd_false, bfd_false,
365 bfd_false, bfd_false
366 },
367
368 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
369 BFD_JUMP_TABLE_COPY (_bfd_generic),
370 BFD_JUMP_TABLE_CORE (trad_unix),
371 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
372 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
373 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
374 BFD_JUMP_TABLE_WRITE (_bfd_generic),
375 BFD_JUMP_TABLE_LINK (_bfd_nolink),
376 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
377
378 NULL,
379
380 (PTR) 0 /* backend_data */
381};
Note: See TracBrowser for help on using the repository browser.