]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/binutils/bfd/trad-core.c
This commit was generated by cvs2svn to compensate for changes in r53140,
[FreeBSD/FreeBSD.git] / contrib / binutils / bfd / trad-core.c
1 /* BFD back end for traditional Unix core files (U-area and raw sections)
2    Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3    Written by John Gilmore of Cygnus Support.
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
34 #ifdef TRAD_HEADER
35 #include TRAD_HEADER
36 #endif
37
38   struct trad_core_struct 
39     {
40       asection *data_section;
41       asection *stack_section;
42       asection *reg_section;
43       struct user u;
44     };
45
46 #define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
47 #define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
48 #define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
49 #define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
50
51 /* forward declarations */
52
53 const bfd_target *trad_unix_core_file_p PARAMS ((bfd *abfd));
54 char *          trad_unix_core_file_failing_command PARAMS ((bfd *abfd));
55 int             trad_unix_core_file_failing_signal PARAMS ((bfd *abfd));
56 boolean         trad_unix_core_file_matches_executable_p
57                          PARAMS ((bfd *core_bfd, bfd *exec_bfd));
58 static void     swap_abort PARAMS ((void));
59
60 /* Handle 4.2-style (and perhaps also sysV-style) core dump file.  */
61
62 /* ARGSUSED */
63 const bfd_target *
64 trad_unix_core_file_p (abfd)
65      bfd *abfd;
66
67 {
68   int val;
69   struct user u;
70   struct trad_core_struct *rawptr;
71
72 #ifdef TRAD_CORE_USER_OFFSET
73   /* If defined, this macro is the file position of the user struct.  */
74   if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) != 0)
75     return 0;
76 #endif
77     
78   val = bfd_read ((void *)&u, 1, sizeof u, abfd);
79   if (val != sizeof u)
80     {
81       /* Too small to be a core file */
82       bfd_set_error (bfd_error_wrong_format);
83       return 0;
84     }
85
86   /* Sanity check perhaps??? */
87   if (u.u_dsize > 0x1000000)    /* Remember, it's in pages... */
88     {
89       bfd_set_error (bfd_error_wrong_format);
90       return 0;
91     }
92   if (u.u_ssize > 0x1000000)
93     {
94       bfd_set_error (bfd_error_wrong_format);
95       return 0;
96     }
97
98   /* Check that the size claimed is no greater than the file size.  */
99   {
100     FILE *stream = bfd_cache_lookup (abfd);
101     struct stat statbuf;
102     if (stream == NULL)
103       return 0;
104     if (fstat (fileno (stream), &statbuf) < 0)
105       {
106         bfd_set_error (bfd_error_system_call);
107         return 0;
108       }
109     if (NBPG * (UPAGES + u.u_dsize
110 #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
111                 - u.u_tsize
112 #endif
113                 + u.u_ssize) > statbuf.st_size)
114       {
115         bfd_set_error (bfd_error_file_truncated);
116         return 0;
117       }
118 #ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE
119     if (NBPG * (UPAGES + u.u_dsize + u.u_ssize)
120 #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
121         /* Some systems write the file too big.  */
122         + TRAD_CORE_EXTRA_SIZE_ALLOWED
123 #endif
124         < statbuf.st_size)
125       {
126         /* The file is too big.  Maybe it's not a core file
127            or we otherwise have bad values for u_dsize and u_ssize).  */
128         bfd_set_error (bfd_error_wrong_format);
129         return 0;
130       }
131 #endif
132   }
133
134   /* OK, we believe you.  You're a core file (sure, sure).  */
135
136   /* Allocate both the upage and the struct core_data at once, so
137      a single free() will free them both.  */
138   rawptr = (struct trad_core_struct *)
139                 bfd_zmalloc (sizeof (struct trad_core_struct));
140   if (rawptr == NULL)
141     return 0;
142   
143   abfd->tdata.trad_core_data = rawptr;
144
145   rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
146
147   /* Create the sections.  This is raunchy, but bfd_close wants to free
148      them separately.  */
149
150   core_stacksec(abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
151   if (core_stacksec (abfd) == NULL)
152     return NULL;
153   core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
154   if (core_datasec (abfd) == NULL)
155     return NULL;
156   core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
157   if (core_regsec (abfd) == NULL)
158     return NULL;
159
160   core_stacksec (abfd)->name = ".stack";
161   core_datasec (abfd)->name = ".data";
162   core_regsec (abfd)->name = ".reg";
163
164   core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
165   core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
166   core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
167
168   core_datasec (abfd)->_raw_size =  NBPG * u.u_dsize
169 #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
170     - NBPG * u.u_tsize
171 #endif
172       ;
173   core_stacksec (abfd)->_raw_size = NBPG * u.u_ssize;
174   core_regsec (abfd)->_raw_size = NBPG * UPAGES; /* Larger than sizeof struct u */
175
176   /* What a hack... we'd like to steal it from the exec file,
177      since the upage does not seem to provide it.  FIXME.  */
178 #ifdef HOST_DATA_START_ADDR
179   core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
180 #else
181   core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
182 #endif
183
184 #ifdef HOST_STACK_START_ADDR
185   core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
186 #else
187   core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
188 #endif
189
190   /* This is tricky.  As the "register section", we give them the entire
191      upage and stack.  u.u_ar0 points to where "register 0" is stored.
192      There are two tricks with this, though.  One is that the rest of the
193      registers might be at positive or negative (or both) displacements
194      from *u_ar0.  The other is that u_ar0 is sometimes an absolute address
195      in kernel memory, and on other systems it is an offset from the beginning
196      of the `struct user'.
197      
198      As a practical matter, we don't know where the registers actually are,
199      so we have to pass the whole area to GDB.  We encode the value of u_ar0
200      by setting the .regs section up so that its virtual memory address
201      0 is at the place pointed to by u_ar0 (by setting the vma of the start
202      of the section to -u_ar0).  GDB uses this info to locate the regs,
203      using minor trickery to get around the offset-or-absolute-addr problem. */
204   core_regsec (abfd)->vma = 0 - (bfd_vma) u.u_ar0;
205
206   core_datasec (abfd)->filepos = NBPG * UPAGES;
207   core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize
208 #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
209     - NBPG * u.u_tsize
210 #endif
211       ;
212   core_regsec (abfd)->filepos = 0; /* Register segment is the upage */
213
214   /* Align to word at least */
215   core_stacksec (abfd)->alignment_power = 2;
216   core_datasec (abfd)->alignment_power = 2;
217   core_regsec (abfd)->alignment_power = 2;
218
219   abfd->sections = core_stacksec (abfd);
220   core_stacksec (abfd)->next = core_datasec (abfd);
221   core_datasec (abfd)->next = core_regsec (abfd);
222   abfd->section_count = 3;
223
224   return abfd->xvec;
225 }
226
227 char *
228 trad_unix_core_file_failing_command (abfd)
229      bfd *abfd;
230 {
231 #ifndef NO_CORE_COMMAND
232   char *com = abfd->tdata.trad_core_data->u.u_comm;
233   if (*com)
234     return com;
235   else
236 #endif
237     return 0;
238 }
239
240 /* ARGSUSED */
241 int
242 trad_unix_core_file_failing_signal (ignore_abfd)
243      bfd *ignore_abfd;
244 {
245 #ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
246   return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
247 #else
248   return -1;            /* FIXME, where is it? */
249 #endif
250 }
251
252 /* ARGSUSED */
253 boolean
254 trad_unix_core_file_matches_executable_p  (core_bfd, exec_bfd)
255      bfd *core_bfd, *exec_bfd;
256 {
257   return true;          /* FIXME, We have no way of telling at this point */
258 }
259 \f
260 /* If somebody calls any byte-swapping routines, shoot them.  */
261 static void
262 swap_abort()
263 {
264   abort(); /* This way doesn't require any declaration for ANSI to fuck up */
265 }
266 #define NO_GET  ((bfd_vma (*) PARAMS ((   const bfd_byte *))) swap_abort )
267 #define NO_PUT  ((void    (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
268 #define NO_SIGNED_GET \
269   ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
270
271 const bfd_target trad_core_vec =
272   {
273     "trad-core",
274     bfd_target_unknown_flavour,
275     BFD_ENDIAN_UNKNOWN,         /* target byte order */
276     BFD_ENDIAN_UNKNOWN,         /* target headers byte order */
277     (HAS_RELOC | EXEC_P |       /* object flags */
278      HAS_LINENO | HAS_DEBUG |
279      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
280     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
281     0,                                                     /* symbol prefix */
282     ' ',                                                   /* ar_pad_char */
283     16,                                                    /* ar_max_namelen */
284     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 64 bit data */
285     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 32 bit data */
286     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 16 bit data */
287     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 64 bit hdrs */
288     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 32 bit hdrs */
289     NO_GET, NO_SIGNED_GET, NO_PUT,      /* 16 bit hdrs */
290
291     {                           /* bfd_check_format */
292      _bfd_dummy_target,         /* unknown format */
293      _bfd_dummy_target,         /* object file */
294      _bfd_dummy_target,         /* archive */
295      trad_unix_core_file_p      /* a core file */
296     },
297     {                           /* bfd_set_format */
298      bfd_false, bfd_false,
299      bfd_false, bfd_false
300     },
301     {                           /* bfd_write_contents */
302      bfd_false, bfd_false,
303      bfd_false, bfd_false
304     },
305     
306        BFD_JUMP_TABLE_GENERIC (_bfd_generic),
307        BFD_JUMP_TABLE_COPY (_bfd_generic),
308        BFD_JUMP_TABLE_CORE (trad_unix),
309        BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
310        BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
311        BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
312        BFD_JUMP_TABLE_WRITE (_bfd_generic),
313        BFD_JUMP_TABLE_LINK (_bfd_nolink),
314        BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
315
316     (PTR) 0                     /* backend_data */
317 };