* trad-core.c: Pass the u.u_ar0 value as the negative of the
[external/binutils.git] / bfd / trad-core.c
1 /* BFD back end for traditional Unix core files (U-area and raw sections)
2    Copyright (C) 1988, 1989, 1991 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* To use this file on a particular host, configure the host with these
22    parameters in the config/h-HOST file:
23
24         HDEFINES=-DTRAD_CORE
25         HDEPFILES=trad-core.o
26
27  */
28
29 #include "bfd.h"
30 #include "sysdep.h"
31 #include "libbfd.h"
32 #include "libaout.h"           /* BFD a.out internal data structures */
33
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/dir.h>
38 #include <signal.h>
39 #include <machine/reg.h>
40
41 #include <sys/user.h>           /* After a.out.h  */
42 #include <sys/file.h>
43
44 #include <errno.h>
45
46 /* These are stored in the bfd's tdata */
47 struct core_data {
48   struct user *upage;             /* core file header */
49   asection *data_section;
50   asection *stack_section;
51   asection *reg_section;
52 };
53
54 #define core_hdr(bfd) (((struct core_data *) (bfd->tdata))->hdr)
55 #define core_upage(bfd) (((struct core_data *) ((bfd)->tdata))->upage)
56 #define core_datasec(bfd) (((struct core_data *) ((bfd)->tdata))->data_section)
57 #define core_stacksec(bfd) (((struct core_data*)((bfd)->tdata))->stack_section)
58 #define core_regsec(bfd) (((struct core_data *) ((bfd)->tdata))->reg_section)
59
60 /* Handle 4.2-style (and perhaps also sysV-style) core dump file.  */
61
62 /* ARGSUSED */
63 bfd_target *
64 trad_unix_core_file_p (abfd)
65      bfd *abfd;
66 {
67   int val;
68   struct user u;
69   unsigned int reg_offset, fp_reg_offset;
70   /* This struct is just for allocating two things with one zalloc, so
71      they will be freed together, without violating alignment constraints. */
72   struct core_user {
73         struct core_data        coredata;
74         struct user             u;
75   } *rawptr;
76
77   val = bfd_read ((void *)&u, 1, sizeof u, abfd);
78   if (val != sizeof u)
79     return 0;                   /* Too small to be a core file */
80
81   /* Sanity check perhaps??? */
82   if (u.u_dsize > 0x1000000)    /* Remember, it's in pages... */
83     return 0;
84   if (u.u_ssize > 0x1000000)
85     return 0;
86   /* Check that the size claimed is no greater than the file size. FIXME. */
87
88   /* OK, we believe you.  You're a core file (sure, sure).  */
89
90   /* Allocate both the upage and the struct core_data at once, so
91      a single free() will free them both.  */
92   rawptr = (struct core_user *)bfd_zalloc (abfd, sizeof (struct core_user));
93   if (rawptr == NULL) {
94     bfd_error = no_memory;
95     return 0;
96   }
97   
98   set_tdata (abfd, &rawptr->coredata);
99   core_upage (abfd) = &rawptr->u;
100   *core_upage (abfd) = u;               /* Save that upage! */
101
102   /* Create the sections.  This is raunchy, but bfd_close wants to free
103      them separately.  */
104   core_stacksec (abfd) = (asection *) zalloc (sizeof (asection));
105   if (core_stacksec (abfd) == NULL) {
106 loser:
107     bfd_error = no_memory;
108     free ((void *)rawptr);
109     return 0;
110   }
111   core_datasec (abfd) = (asection *) zalloc (sizeof (asection));
112   if (core_datasec (abfd) == NULL) {
113 loser1:
114     free ((void *)core_stacksec (abfd));
115     goto loser;
116   }
117   core_regsec (abfd) = (asection *) zalloc (sizeof (asection));
118   if (core_regsec (abfd) == NULL) {
119 loser2:
120     free ((void *)core_datasec (abfd));
121     goto loser1;
122   }
123
124   core_stacksec (abfd)->name = ".stack";
125   core_datasec (abfd)->name = ".data";
126   core_regsec (abfd)->name = ".reg";
127
128   core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
129   core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
130   core_regsec (abfd)->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
131
132   core_datasec (abfd)->size =  NBPG * u.u_dsize;
133   core_stacksec (abfd)->size = NBPG * u.u_ssize;
134   core_regsec (abfd)->size = NBPG * UPAGES;  /* Larger than sizeof struct u */
135
136   /* What a hack... we'd like to steal it from the exec file,
137      since the upage does not seem to provide it.  FIXME.  */
138 #ifdef HOST_DATA_START_ADDR
139   core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
140 #else
141   core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
142 #endif
143   core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
144   /* This is tricky.  As the "register section", we give them the entire
145      upage and stack.  u.u_ar0 points to where "register 0" is stored.
146      There are two tricks with this, though.  One is that the rest of the
147      registers might be at positive or negative (or both) displacements
148      from *u_ar0.  The other is that u_ar0 is sometimes an absolute address
149      in kernel memory, and on other systems it is an offset from the beginning
150      of the `struct user'.
151
152      As a practical matter, we don't know where the registers actually are,
153      so we have to pass the whole area to GDB.  We encode the value of u_ar0
154      by setting the .regs section up so that its virtual memory address
155      0 is at the place pointed to by u_ar0 (by setting the vma of the start
156      of the section to -u_ar0).  GDB uses this info to locate the regs,
157      using minor trickery to get around the offset-or-absolute-addr problem. */
158   core_regsec (abfd)->vma = 0 - (int) u.u_ar0;
159
160   core_datasec (abfd)->filepos = NBPG * UPAGES;
161   core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize;
162   core_regsec (abfd)->filepos = 0;      /* Register segment is the upage */
163
164   /* Align to word at least */
165   core_stacksec (abfd)->alignment_power = 2;
166   core_datasec (abfd)->alignment_power = 2;
167   core_regsec (abfd)->alignment_power = 2;
168
169   abfd->sections = core_stacksec (abfd);
170   core_stacksec (abfd)->next = core_datasec (abfd);
171   core_datasec (abfd)->next = core_regsec (abfd);
172   abfd->section_count = 3;
173
174   return abfd->xvec;
175 }
176
177 char *
178 trad_unix_core_file_failing_command (abfd)
179      bfd *abfd;
180 {
181   if (*core_upage (abfd)->u_comm)
182     return core_upage (abfd)->u_comm;
183   else
184     return 0;
185 }
186
187 /* ARGSUSED */
188 int
189 trad_unix_core_file_failing_signal (ignore_abfd)
190      bfd *ignore_abfd;
191 {
192   return -1;            /* FIXME, where is it? */
193 }
194
195 /* ARGSUSED */
196 boolean
197 trad_unix_core_file_matches_executable_p  (core_bfd, exec_bfd)
198      bfd *core_bfd, *exec_bfd;
199 {
200   return true;          /* FIXME, We have no way of telling at this point */
201 }
202 \f
203 /* No archive file support via this BFD */
204 #define trad_unix_openr_next_archived_file      bfd_generic_openr_next_archived_file
205 #define trad_unix_generic_stat_arch_elt         bfd_generic_stat_arch_elt
206 #define trad_unix_slurp_armap                   bfd_false
207 #define trad_unix_slurp_extended_name_table     bfd_true
208 #define trad_unix_write_armap                   (PROTO (boolean, (*),   \
209      (bfd *arch, unsigned int elength, struct orl *map, int orl_count,  \
210       int stridx))) bfd_false
211 #define trad_unix_truncate_arname               bfd_dont_truncate_arname
212 #define aout_32_openr_next_archived_file        bfd_generic_openr_next_archived_file
213
214 #define trad_unix_close_and_cleanup             bfd_generic_close_and_cleanup
215 #define trad_unix_set_section_contents          (PROTO(boolean, (*),    \
216          (bfd *abfd, asection *section, PTR data, file_ptr offset,      \
217          bfd_size_type count))) bfd_false
218 #define trad_unix_get_section_contents          bfd_generic_get_section_contents
219 #define trad_unix_new_section_hook              (PROTO (boolean, (*),   \
220         (bfd *, sec_ptr))) bfd_true
221 #define trad_unix_get_symtab_upper_bound        bfd_0u
222 #define trad_unix_get_symtab                    (PROTO (unsigned int, (*), \
223         (bfd *, struct symbol_cache_entry **))) bfd_0u
224 #define trad_unix_get_reloc_upper_bound         (PROTO (unsigned int, (*), \
225         (bfd *, sec_ptr))) bfd_0u
226 #define trad_unix_canonicalize_reloc            (PROTO (unsigned int, (*), \
227         (bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u
228 #define trad_unix_make_empty_symbol             (PROTO (                \
229         struct symbol_cache_entry *, (*), (bfd *))) bfd_false
230 #define trad_unix_print_symbol                  (PROTO (void, (*),      \
231         (bfd *, PTR, struct symbol_cache_entry  *,                      \
232          bfd_print_symbol_type))) bfd_false
233 #define trad_unix_get_lineno                    (PROTO (alent *, (*),   \
234         (bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr
235 #define trad_unix_set_arch_mach                 (PROTO (boolean, (*),   \
236         (bfd *, enum bfd_architecture, unsigned long))) bfd_false
237 #define trad_unix_find_nearest_line             (PROTO (boolean, (*),   \
238         (bfd *abfd, struct sec  *section,                               \
239          struct symbol_cache_entry  **symbols,bfd_vma offset,           \
240          CONST char **file, CONST char **func, unsigned int *line))) bfd_false
241 #define trad_unix_sizeof_headers                (PROTO (int, (*),       \
242         (bfd *, boolean))) bfd_0
243
244 #define trad_unix_bfd_debug_info_start          bfd_void
245 #define trad_unix_bfd_debug_info_end            bfd_void
246 #define trad_unix_bfd_debug_info_accumulate     (PROTO (void, (*),      \
247         (bfd *, struct sec *))) bfd_void
248
249 /* If somebody calls any byte-swapping routines, shoot them.  */
250 void
251 swap_abort()
252 {
253   abort(); /* This way doesn't require any declaration for ANSI to fuck up */
254 }
255 #define NO_GET  ((PROTO(bfd_vma, (*), (         bfd_byte *))) swap_abort )
256 #define NO_PUT  ((PROTO(void,    (*), (bfd_vma, bfd_byte *))) swap_abort )
257
258 bfd_target trad_core_vec =
259   {
260     "trad-core",
261     bfd_target_unknown_flavour,
262     true,                       /* target byte order */
263     true,                       /* target headers byte order */
264     (HAS_RELOC | EXEC_P |       /* object flags */
265      HAS_LINENO | HAS_DEBUG |
266      HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
267     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
268     ' ',                                                   /* ar_pad_char */
269     16,                                                    /* ar_max_namelen */
270     3,                                                     /* minimum alignment power */
271     NO_GET, NO_PUT, NO_GET, NO_PUT, NO_GET, NO_PUT, /* data */
272     NO_GET, NO_PUT, NO_GET, NO_PUT, NO_GET, NO_PUT, /* hdrs */
273
274     {_bfd_dummy_target, _bfd_dummy_target,
275      _bfd_dummy_target, trad_unix_core_file_p},
276     {bfd_false, bfd_false,      /* bfd_create_object */
277      bfd_false, bfd_false},
278     {bfd_false, bfd_false,      /* bfd_write_contents */
279      bfd_false, bfd_false},
280     
281     JUMP_TABLE(trad_unix)
282 };