(root)/
binutils-2.41/
bfd/
hpux-core.c
       1  /* BFD back-end for HP/UX core files.
       2     Copyright (C) 1993-2023 Free Software Foundation, Inc.
       3     Written by Stu Grossman, Cygnus Support.
       4     Converted to back-end form by Ian Lance Taylor, Cygnus SUpport
       5  
       6     This file is part of BFD, the Binary File Descriptor library.
       7  
       8     This program is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program; if not, write to the Free Software
      20     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21     MA 02110-1301, USA.  */
      22  
      23  
      24  /* This file can only be compiled on systems which use HP/UX style
      25     core files.  */
      26  
      27  #include "sysdep.h"
      28  #include "bfd.h"
      29  #include "libbfd.h"
      30  
      31  #if defined (HOST_HPPAHPUX) || defined (HOST_HPPAMPEIX)
      32  
      33  /* FIXME: sys/core.h doesn't exist for HPUX version 7.  HPUX version
      34     5, 6, and 7 core files seem to be standard trad-core.c type core
      35     files; can we just use trad-core.c in addition to this file?  */
      36  
      37  #include <sys/core.h>
      38  #include <sys/utsname.h>
      39  
      40  #endif /* HOST_HPPAHPUX */
      41  
      42  #ifdef HOST_HPPABSD
      43  
      44  /* Not a very swift place to put it, but that's where the BSD port
      45     puts them.  */
      46  #include "/hpux/usr/include/sys/core.h"
      47  
      48  #endif /* HOST_HPPABSD */
      49  
      50  #include <sys/param.h>
      51  #include <dirent.h>
      52  #include <signal.h>
      53  #ifdef HPUX_CORE
      54  #include <machine/reg.h>
      55  #endif
      56  #include <sys/file.h>
      57  
      58  /* Kludge: There's no explicit mechanism provided by sys/core.h to
      59     conditionally know whether a proc_info has thread id fields.
      60     However, CORE_ANON_SHMEM shows up first at 10.30, which is
      61     happily also when meaningful thread id's show up in proc_info. */
      62  #if defined(CORE_ANON_SHMEM)
      63  #define PROC_INFO_HAS_THREAD_ID (1)
      64  #endif
      65  
      66  /* This type appears at HP-UX 10.30.  Defining it if not defined
      67     by sys/core.h allows us to build for older HP-UX's, and (since
      68     it won't be encountered in core-dumps from older HP-UX's) is
      69     harmless. */
      70  #if !defined(CORE_ANON_SHMEM)
      71  #define CORE_ANON_SHMEM 0x00000200	   /* anonymous shared memory */
      72  #endif
      73  
      74  /* These are stored in the bfd's tdata */
      75  
      76  /* .lwpid and .user_tid are only valid if PROC_INFO_HAS_THREAD_ID, else they
      77     are set to 0.  Also, until HP-UX implements MxN threads, .user_tid and
      78     .lwpid are synonymous. */
      79  struct hpux_core_struct
      80  {
      81    int sig;
      82    int lwpid;		   /* Kernel thread ID. */
      83    unsigned long user_tid;  /* User thread ID. */
      84    char cmd[MAXCOMLEN + 1];
      85  };
      86  
      87  #define core_hdr(bfd) ((bfd)->tdata.hpux_core_data)
      88  #define core_signal(bfd) (core_hdr(bfd)->sig)
      89  #define core_command(bfd) (core_hdr(bfd)->cmd)
      90  #define core_kernel_thread_id(bfd) (core_hdr(bfd)->lwpid)
      91  #define core_user_thread_id(bfd) (core_hdr(bfd)->user_tid)
      92  #define hpux_core_core_file_matches_executable_p generic_core_file_matches_executable_p
      93  #define hpux_core_core_file_pid _bfd_nocore_core_file_pid
      94  
      95  static asection *make_bfd_asection (bfd *, const char *, flagword,
      96  				    bfd_size_type, bfd_vma, unsigned int);
      97  static bfd_cleanup hpux_core_core_file_p (bfd *);
      98  static char *hpux_core_core_file_failing_command (bfd *);
      99  static int hpux_core_core_file_failing_signal (bfd *);
     100  static void swap_abort (void);
     101  
     102  static asection *
     103  make_bfd_asection (bfd *abfd, const char *name, flagword flags,
     104  		   bfd_size_type size, bfd_vma vma,
     105  		   unsigned int alignment_power)
     106  {
     107    asection *asect;
     108    char *newname;
     109  
     110    newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
     111    if (!newname)
     112      return NULL;
     113  
     114    strcpy (newname, name);
     115  
     116    asect = bfd_make_section_anyway_with_flags (abfd, newname, flags);
     117    if (!asect)
     118      return NULL;
     119  
     120    asect->size = size;
     121    asect->vma = vma;
     122    asect->filepos = bfd_tell (abfd);
     123    asect->alignment_power = alignment_power;
     124  
     125    return asect;
     126  }
     127  
     128  /* Return true if the given core file section corresponds to a thread,
     129     based on its name.  */
     130  
     131  static int
     132  thread_section_p (bfd *abfd ATTRIBUTE_UNUSED,
     133  		  asection *sect,
     134  		  void *obj ATTRIBUTE_UNUSED)
     135  {
     136    return startswith (sect->name, ".reg/");
     137  }
     138  
     139  /* this function builds a bfd target if the file is a corefile.
     140     It returns null or 0 if it finds out thaat it is not a core file.
     141     The way it checks this is by looking for allowed 'type' field values.
     142     These are declared in sys/core.h
     143     There are some values which are 'reserved for future use'. In particular
     144     CORE_NONE is actually defined as 0. This may be a catch-all for cases
     145     in which the core file is generated by some non-hpux application.
     146     (I am just guessing here!)
     147  */
     148  static bfd_cleanup
     149  hpux_core_core_file_p (bfd *abfd)
     150  {
     151    int  good_sections = 0;
     152    int  unknown_sections = 0;
     153  
     154    core_hdr (abfd) = (struct hpux_core_struct *)
     155      bfd_zalloc (abfd, (bfd_size_type) sizeof (struct hpux_core_struct));
     156    if (!core_hdr (abfd))
     157      return NULL;
     158  
     159    while (1)
     160      {
     161        int val;
     162        struct corehead core_header;
     163  
     164        val = bfd_bread ((void *) &core_header,
     165  		      (bfd_size_type) sizeof core_header, abfd);
     166        if (val <= 0)
     167  	break;
     168        switch (core_header.type)
     169  	{
     170  	case CORE_KERNEL:
     171  	case CORE_FORMAT:
     172  	  /* Just skip this.  */
     173  	  bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
     174  	  good_sections++;
     175  	  break;
     176  	case CORE_EXEC:
     177  	  {
     178  	    struct proc_exec proc_exec;
     179  	    if (bfd_bread ((void *) &proc_exec, (bfd_size_type) core_header.len,
     180  			  abfd) != core_header.len)
     181  	      break;
     182  	    strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1);
     183  	    good_sections++;
     184  	  }
     185  	  break;
     186  	case CORE_PROC:
     187  	  {
     188  	    struct proc_info proc_info;
     189  	    char  secname[100];  /* Of arbitrary size, but plenty large. */
     190  
     191  	    /* We need to read this section, 'cause we need to determine
     192  	       whether the core-dumped app was threaded before we create
     193  	       any .reg sections. */
     194  	    if (bfd_bread (&proc_info, (bfd_size_type) core_header.len, abfd)
     195  		!= core_header.len)
     196  	      break;
     197  
     198  	      /* However, we also want to create those sections with the
     199  		 file positioned at the start of the record, it seems. */
     200  	    if (bfd_seek (abfd, -((file_ptr) core_header.len), SEEK_CUR) != 0)
     201  	      break;
     202  
     203  #if defined(PROC_INFO_HAS_THREAD_ID)
     204  	    core_kernel_thread_id (abfd) = proc_info.lwpid;
     205  	    core_user_thread_id (abfd) = proc_info.user_tid;
     206  #else
     207  	    core_kernel_thread_id (abfd) = 0;
     208  	    core_user_thread_id (abfd) = 0;
     209  #endif
     210  	    /* If the program was unthreaded, then we'll just create a
     211  	       .reg section.
     212  
     213  	       If the program was threaded, then we'll create .reg/XXXXX
     214  	       section for each thread, where XXXXX is a printable
     215  	       representation of the kernel thread id.  We'll also
     216  	       create a .reg section for the thread that was running
     217  	       and signalled at the time of the core-dump (i.e., this
     218  	       is effectively an alias, needed to keep GDB happy.)
     219  
     220  	       Note that we use `.reg/XXXXX' as opposed to '.regXXXXX'
     221  	       because GDB expects that .reg2 will be the floating-
     222  	       point registers. */
     223  	    if (core_kernel_thread_id (abfd) == 0)
     224  	      {
     225  		if (!make_bfd_asection (abfd, ".reg",
     226  					SEC_HAS_CONTENTS,
     227  					core_header.len,
     228  					(bfd_vma) offsetof (struct proc_info,
     229  							    hw_regs),
     230  					2))
     231  		  goto fail;
     232  	      }
     233  	    else
     234  	      {
     235  		/* There are threads.  Is this the one that caused the
     236  		   core-dump?  We'll claim it was the running thread. */
     237  		if (proc_info.sig != -1)
     238  		  {
     239  		    if (!make_bfd_asection (abfd, ".reg",
     240  					    SEC_HAS_CONTENTS,
     241  					    core_header.len,
     242  					    (bfd_vma)offsetof (struct proc_info,
     243  							       hw_regs),
     244  					    2))
     245  		      goto fail;
     246  		  }
     247  		/* We always make one of these sections, for every thread. */
     248  		sprintf (secname, ".reg/%d", core_kernel_thread_id (abfd));
     249  		if (!make_bfd_asection (abfd, secname,
     250  					SEC_HAS_CONTENTS,
     251  					core_header.len,
     252  					(bfd_vma) offsetof (struct proc_info,
     253  							    hw_regs),
     254  					2))
     255  		  goto fail;
     256  	      }
     257  	    core_signal (abfd) = proc_info.sig;
     258  	    if (bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR) != 0)
     259  	      break;
     260  	    good_sections++;
     261  	  }
     262  	  break;
     263  
     264  	case CORE_DATA:
     265  	case CORE_STACK:
     266  	case CORE_TEXT:
     267  	case CORE_MMF:
     268  	case CORE_SHM:
     269  	case CORE_ANON_SHMEM:
     270  	  if (!make_bfd_asection (abfd, ".data",
     271  				  SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
     272  				  core_header.len,
     273  				  (bfd_vma) core_header.addr, 2))
     274  	    goto fail;
     275  
     276  	  bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
     277  	  good_sections++;
     278  	  break;
     279  
     280  	case CORE_NONE:
     281  	  /* Let's not punt if we encounter a section of unknown
     282  	     type.  Rather, let's make a note of it.  If we later
     283  	     see that there were also "good" sections, then we'll
     284  	     declare that this a core file, but we'll also warn that
     285  	     it may be incompatible with this gdb.
     286  	     */
     287  	  unknown_sections++;
     288  	  break;
     289  
     290  	 default:
     291  	   goto fail; /*unrecognized core file type */
     292  	}
     293      }
     294  
     295    /* OK, we believe you.  You're a core file (sure, sure).  */
     296  
     297    /* On HP/UX, we sometimes encounter core files where none of the threads
     298       was found to be the running thread (ie the signal was set to -1 for
     299       all threads).  This happens when the program was aborted externally
     300       via a TT_CORE ttrace system call.  In that case, we just pick one
     301       thread at random to be the active thread.  */
     302    if (core_kernel_thread_id (abfd) != 0
     303        && bfd_get_section_by_name (abfd, ".reg") == NULL)
     304      {
     305        asection *asect = bfd_sections_find_if (abfd, thread_section_p, NULL);
     306        asection *reg_sect;
     307  
     308        if (asect != NULL)
     309  	{
     310  	  reg_sect = make_bfd_asection (abfd, ".reg", asect->flags,
     311  					asect->size, asect->vma,
     312  					asect->alignment_power);
     313  	  if (reg_sect == NULL)
     314  	    goto fail;
     315  
     316  	  reg_sect->filepos = asect->filepos;
     317  	}
     318      }
     319  
     320    /* Were there sections of unknown type?  If so, yet there were
     321       at least some complete sections of known type, then, issue
     322       a warning.  Possibly the core file was generated on a version
     323       of HP-UX that is incompatible with that for which this gdb was
     324       built.
     325       */
     326    if ((unknown_sections > 0) && (good_sections > 0))
     327      _bfd_error_handler
     328        ("%pB appears to be a core file,\nbut contains unknown sections."
     329         "  It may have been created on an incompatible\nversion of HP-UX."
     330         "  As a result, some information may be unavailable.\n",
     331         abfd);
     332  
     333    return _bfd_no_cleanup;
     334  
     335   fail:
     336    bfd_release (abfd, core_hdr (abfd));
     337    core_hdr (abfd) = NULL;
     338    bfd_section_list_clear (abfd);
     339    return NULL;
     340  }
     341  
     342  static char *
     343  hpux_core_core_file_failing_command (bfd *abfd)
     344  {
     345    return core_command (abfd);
     346  }
     347  
     348  static int
     349  hpux_core_core_file_failing_signal (bfd *abfd)
     350  {
     351    return core_signal (abfd);
     352  }
     353  
     354  
     355  /* If somebody calls any byte-swapping routines, shoot them.  */
     356  static void
     357  swap_abort (void)
     358  {
     359    abort(); /* This way doesn't require any declaration for ANSI to fuck up */
     360  }
     361  
     362  #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
     363  #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
     364  #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
     365  #define	NO_GET64 ((uint64_t (*) (const void *)) swap_abort)
     366  #define	NO_PUT64 ((void (*) (uint64_t, void *)) swap_abort)
     367  #define	NO_GETS64 ((int64_t (*) (const void *)) swap_abort)
     368  
     369  const bfd_target core_hpux_vec =
     370    {
     371      "hpux-core",
     372      bfd_target_unknown_flavour,
     373      BFD_ENDIAN_BIG,		/* target byte order */
     374      BFD_ENDIAN_BIG,		/* target headers byte order */
     375      (HAS_RELOC | EXEC_P |	/* object flags */
     376       HAS_LINENO | HAS_DEBUG |
     377       HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
     378      (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
     379      0,				/* symbol prefix */
     380      ' ',			/* ar_pad_char */
     381      16,				/* ar_max_namelen */
     382      0,				/* match priority.  */
     383      TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
     384      NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
     385      NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
     386      NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
     387      NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
     388      NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
     389      NO_GET, NO_GETS, 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        hpux_core_core_file_p		/* a core file */
     396      },
     397      {				/* bfd_set_format */
     398        _bfd_bool_bfd_false_error,
     399        _bfd_bool_bfd_false_error,
     400        _bfd_bool_bfd_false_error,
     401        _bfd_bool_bfd_false_error
     402      },
     403      {				/* bfd_write_contents */
     404        _bfd_bool_bfd_false_error,
     405        _bfd_bool_bfd_false_error,
     406        _bfd_bool_bfd_false_error,
     407        _bfd_bool_bfd_false_error
     408      },
     409  
     410      BFD_JUMP_TABLE_GENERIC (_bfd_generic),
     411      BFD_JUMP_TABLE_COPY (_bfd_generic),
     412      BFD_JUMP_TABLE_CORE (hpux_core),
     413      BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
     414      BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
     415      BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
     416      BFD_JUMP_TABLE_WRITE (_bfd_generic),
     417      BFD_JUMP_TABLE_LINK (_bfd_nolink),
     418      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
     419  
     420      NULL,
     421  
     422      NULL			/* backend_data */
     423    };