~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to bfd/sco5-core.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

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