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