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