Back to index

cell-binutils  2.17cvs20070401
lynx-core.c
Go to the documentation of this file.
00001 /* BFD back end for Lynx core files
00002    Copyright 1993, 1994, 1995, 2001, 2002, 2004, 2006
00003    Free Software Foundation, Inc.
00004    Written by Stu Grossman of Cygnus Support.
00005 
00006 This file is part of BFD, the Binary File Descriptor library.
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "libbfd.h"
00025 
00026 #ifdef LYNX_CORE
00027 
00028 #include <sys/conf.h>
00029 #include <sys/kernel.h>
00030 /* sys/kernel.h should define this, but doesn't always, sigh.  */
00031 #ifndef __LYNXOS
00032 #define __LYNXOS
00033 #endif
00034 #include <sys/mem.h>
00035 #include <sys/signal.h>
00036 #include <sys/time.h>
00037 #include <sys/resource.h>
00038 #include <sys/itimer.h>
00039 #include <sys/file.h>
00040 #include <sys/proc.h>
00041 
00042 /* These are stored in the bfd's tdata */
00043 
00044 struct lynx_core_struct
00045 {
00046   int sig;
00047   char cmd[PNMLEN + 1];
00048 };
00049 
00050 #define core_hdr(bfd) ((bfd)->tdata.lynx_core_data)
00051 #define core_signal(bfd) (core_hdr(bfd)->sig)
00052 #define core_command(bfd) (core_hdr(bfd)->cmd)
00053 
00054 #define lynx_core_file_matches_executable_p generic_core_file_matches_executable_p
00055 
00056 /* Handle Lynx core dump file.  */
00057 
00058 static asection *
00059 make_bfd_asection (abfd, name, flags, size, vma, filepos)
00060      bfd *abfd;
00061      const char *name;
00062      flagword flags;
00063      bfd_size_type size;
00064      bfd_vma vma;
00065      file_ptr filepos;
00066 {
00067   asection *asect;
00068   char *newname;
00069 
00070   newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
00071   if (!newname)
00072     return NULL;
00073 
00074   strcpy (newname, name);
00075 
00076   asect = bfd_make_section_with_flags (abfd, newname, flags);
00077   if (!asect)
00078     return NULL;
00079 
00080   asect->size = size;
00081   asect->vma = vma;
00082   asect->filepos = filepos;
00083   asect->alignment_power = 2;
00084 
00085   return asect;
00086 }
00087 
00088 const bfd_target *
00089 lynx_core_file_p (abfd)
00090      bfd *abfd;
00091 {
00092   int secnum;
00093   struct pssentry pss;
00094   bfd_size_type tcontext_size;
00095   core_st_t *threadp;
00096   int pagesize;
00097   asection *newsect;
00098   bfd_size_type amt;
00099 
00100   pagesize = getpagesize ();       /* Serious cross-target issue here...  This
00101                                really needs to come from a system-specific
00102                                header file.  */
00103 
00104   /* Get the pss entry from the core file */
00105 
00106   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
00107     return NULL;
00108 
00109   amt = sizeof pss;
00110   if (bfd_bread ((void *) &pss, amt, abfd) != amt)
00111     {
00112       /* Too small to be a core file */
00113       if (bfd_get_error () != bfd_error_system_call)
00114        bfd_set_error (bfd_error_wrong_format);
00115       return NULL;
00116     }
00117 
00118   amt = sizeof (struct lynx_core_struct);
00119   core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);
00120 
00121   if (!core_hdr (abfd))
00122     return NULL;
00123 
00124   strncpy (core_command (abfd), pss.pname, PNMLEN + 1);
00125 
00126   /* Compute the size of the thread contexts */
00127 
00128   tcontext_size = pss.threadcnt * sizeof (core_st_t);
00129 
00130   /* Allocate space for the thread contexts */
00131 
00132   threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size);
00133   if (!threadp)
00134     goto fail;
00135 
00136   /* Save thread contexts */
00137 
00138   if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0)
00139     goto fail;
00140 
00141   if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size)
00142     {
00143       /* Probably too small to be a core file */
00144       if (bfd_get_error () != bfd_error_system_call)
00145        bfd_set_error (bfd_error_wrong_format);
00146       goto fail;
00147     }
00148 
00149   core_signal (abfd) = threadp->currsig;
00150 
00151   newsect = make_bfd_asection (abfd, ".stack",
00152                             SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
00153                             pss.ssize,
00154                             pss.slimit,
00155                             pagesize + tcontext_size);
00156   if (!newsect)
00157     goto fail;
00158 
00159   newsect = make_bfd_asection (abfd, ".data",
00160                             SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
00161                             pss.data_len + pss.bss_len,
00162                             pss.data_start,
00163                             pagesize + tcontext_size + pss.ssize
00164 #if defined (SPARC) || defined (__SPARC__)
00165                             /* SPARC Lynx seems to start dumping
00166                                   the .data section at a page
00167                                   boundary.  It's OK to check a
00168                                   #define like SPARC here because this
00169                                   file can only be compiled on a Lynx
00170                                   host.  */
00171                             + pss.data_start % pagesize
00172 #endif
00173                             );
00174   if (!newsect)
00175     goto fail;
00176 
00177 /* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
00178    .reg/XXX section, where XXX is the thread id (without leading zeros).  The
00179    currently running thread (at the time of the core dump) also has an alias
00180    called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
00181    opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
00182    point registers.  */
00183 
00184   newsect = make_bfd_asection (abfd, ".reg",
00185                             SEC_HAS_CONTENTS,
00186                             sizeof (core_st_t),
00187                             0,
00188                             pagesize);
00189   if (!newsect)
00190     goto fail;
00191 
00192   for (secnum = 0; secnum < pss.threadcnt; secnum++)
00193     {
00194       char secname[100];
00195 
00196       sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
00197       newsect = make_bfd_asection (abfd, secname,
00198                                SEC_HAS_CONTENTS,
00199                                sizeof (core_st_t),
00200                                0,
00201                                pagesize + secnum * sizeof (core_st_t));
00202       if (!newsect)
00203        goto fail;
00204     }
00205 
00206   return abfd->xvec;
00207 
00208  fail:
00209   bfd_release (abfd, core_hdr (abfd));
00210   core_hdr (abfd) = NULL;
00211   bfd_section_list_clear (abfd);
00212   return NULL;
00213 }
00214 
00215 char *
00216 lynx_core_file_failing_command (abfd)
00217      bfd *abfd;
00218 {
00219   return core_command (abfd);
00220 }
00221 
00222 int
00223 lynx_core_file_failing_signal (abfd)
00224      bfd *abfd;
00225 {
00226   return core_signal (abfd);
00227 }
00228 
00229 #endif /* LYNX_CORE */