gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / bfd / hpux-core.c
CommitLineData
252b5132 1/* BFD back-end for HP/UX core files.
250d07de 2 Copyright (C) 1993-2021 Free Software Foundation, Inc.
252b5132
RH
3 Written by Stu Grossman, Cygnus Support.
4 Converted to back-end form by Ian Lance Taylor, Cygnus SUpport
5
cd123cb7 6 This file is part of BFD, the Binary File Descriptor library.
252b5132 7
cd123cb7
NC
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.
252b5132 12
cd123cb7
NC
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. */
252b5132 22
252b5132
RH
23
24/* This file can only be compiled on systems which use HP/UX style
25 core files. */
26
252b5132 27#include "sysdep.h"
3db64b00 28#include "bfd.h"
252b5132
RH
29#include "libbfd.h"
30
dc12032b 31#if defined (HOST_HPPAHPUX) || defined (HOST_HPPAMPEIX)
252b5132
RH
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>
83c79df8 51#include <dirent.h>
252b5132 52#include <signal.h>
9b818146 53#ifdef HPUX_CORE
252b5132 54#include <machine/reg.h>
9b818146 55#endif
252b5132
RH
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)
07d6d2b8 71#define CORE_ANON_SHMEM 0x00000200 /* anonymous shared memory */
252b5132
RH
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. */
3fde5a36 79struct hpux_core_struct
252b5132
RH
80{
81 int sig;
07d6d2b8 82 int lwpid; /* Kernel thread ID. */
252b5132
RH
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)
69d246d9 92#define hpux_core_core_file_matches_executable_p generic_core_file_matches_executable_p
261b8d08 93#define hpux_core_core_file_pid _bfd_nocore_core_file_pid
252b5132 94
69d246d9 95static asection *make_bfd_asection (bfd *, const char *, flagword,
07d6d2b8 96 bfd_size_type, bfd_vma, unsigned int);
40b35c78 97static bfd_cleanup hpux_core_core_file_p (bfd *);
69d246d9
JB
98static char *hpux_core_core_file_failing_command (bfd *);
99static int hpux_core_core_file_failing_signal (bfd *);
100static void swap_abort (void);
252b5132
RH
101
102static asection *
69d246d9 103make_bfd_asection (bfd *abfd, const char *name, flagword flags,
07d6d2b8
AM
104 bfd_size_type size, bfd_vma vma,
105 unsigned int alignment_power)
252b5132
RH
106{
107 asection *asect;
108 char *newname;
109
dc810e39 110 newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
252b5132
RH
111 if (!newname)
112 return NULL;
113
114 strcpy (newname, name);
115
117ed4f8 116 asect = bfd_make_section_anyway_with_flags (abfd, newname, flags);
252b5132
RH
117 if (!asect)
118 return NULL;
119
eea6121a 120 asect->size = size;
252b5132
RH
121 asect->vma = vma;
122 asect->filepos = bfd_tell (abfd);
123 asect->alignment_power = alignment_power;
124
125 return asect;
126}
127
94ea025a
JB
128/* Return true if the given core file section corresponds to a thread,
129 based on its name. */
130
131static int
132thread_section_p (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
133 asection *sect,
134 void *obj ATTRIBUTE_UNUSED)
94ea025a 135{
08dedd66 136 return startswith (sect->name, ".reg/");
94ea025a
JB
137}
138
252b5132
RH
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*/
601b73d5 148static bfd_cleanup
69d246d9 149hpux_core_core_file_p (bfd *abfd)
252b5132
RH
150{
151 int good_sections = 0;
152 int unknown_sections = 0;
153
154 core_hdr (abfd) = (struct hpux_core_struct *)
dc810e39 155 bfd_zalloc (abfd, (bfd_size_type) sizeof (struct hpux_core_struct));
252b5132
RH
156 if (!core_hdr (abfd))
157 return NULL;
158
159 while (1)
160 {
161 int val;
162 struct corehead core_header;
163
dc810e39
AM
164 val = bfd_bread ((void *) &core_header,
165 (bfd_size_type) sizeof core_header, abfd);
252b5132
RH
166 if (val <= 0)
167 break;
168 switch (core_header.type)
169 {
170 case CORE_KERNEL:
171 case CORE_FORMAT:
dc810e39
AM
172 /* Just skip this. */
173 bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
07d6d2b8 174 good_sections++;
252b5132
RH
175 break;
176 case CORE_EXEC:
177 {
178 struct proc_exec proc_exec;
dc810e39
AM
179 if (bfd_bread ((void *) &proc_exec, (bfd_size_type) core_header.len,
180 abfd) != core_header.len)
252b5132
RH
181 break;
182 strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1);
07d6d2b8 183 good_sections++;
252b5132
RH
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
07d6d2b8
AM
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. */
dc810e39 194 if (bfd_bread (&proc_info, (bfd_size_type) core_header.len, abfd)
252b5132
RH
195 != core_header.len)
196 break;
197
07d6d2b8
AM
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;
252b5132
RH
202
203#if defined(PROC_INFO_HAS_THREAD_ID)
07d6d2b8
AM
204 core_kernel_thread_id (abfd) = proc_info.lwpid;
205 core_user_thread_id (abfd) = proc_info.user_tid;
252b5132 206#else
07d6d2b8
AM
207 core_kernel_thread_id (abfd) = 0;
208 core_user_thread_id (abfd) = 0;
252b5132 209#endif
07d6d2b8
AM
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",
3dd2fcf0
DA
226 SEC_HAS_CONTENTS,
227 core_header.len,
228 (bfd_vma) offsetof (struct proc_info,
229 hw_regs),
230 2))
9e7b37b3 231 goto fail;
07d6d2b8
AM
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 {
252b5132
RH
239 if (!make_bfd_asection (abfd, ".reg",
240 SEC_HAS_CONTENTS,
241 core_header.len,
3dd2fcf0
DA
242 (bfd_vma)offsetof (struct proc_info,
243 hw_regs),
252b5132 244 2))
9e7b37b3 245 goto fail;
07d6d2b8
AM
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,
3dd2fcf0
DA
250 SEC_HAS_CONTENTS,
251 core_header.len,
252 (bfd_vma) offsetof (struct proc_info,
253 hw_regs),
254 2))
9e7b37b3 255 goto fail;
07d6d2b8 256 }
252b5132 257 core_signal (abfd) = proc_info.sig;
07d6d2b8
AM
258 if (bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR) != 0)
259 break;
260 good_sections++;
252b5132
RH
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,
5198ba8b
DA
272 core_header.len,
273 (bfd_vma) core_header.addr, 2))
9e7b37b3 274 goto fail;
252b5132 275
dc810e39 276 bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
07d6d2b8 277 good_sections++;
252b5132
RH
278 break;
279
280 case CORE_NONE:
07d6d2b8
AM
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 */
252b5132 287 unknown_sections++;
07d6d2b8 288 break;
3fde5a36 289
07d6d2b8 290 default:
9e7b37b3 291 goto fail; /*unrecognized core file type */
252b5132
RH
292 }
293 }
294
295 /* OK, we believe you. You're a core file (sure, sure). */
296
94ea025a
JB
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)
07d6d2b8
AM
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 }
94ea025a
JB
318 }
319
252b5132
RH
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))
4eca0228 327 _bfd_error_handler
871b3ab2 328 ("%pB appears to be a core file,\nbut contains unknown sections."
dae82561
AM
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);
252b5132 332
601b73d5 333 return _bfd_no_cleanup;
9e7b37b3
AM
334
335 fail:
336 bfd_release (abfd, core_hdr (abfd));
337 core_hdr (abfd) = NULL;
338 bfd_section_list_clear (abfd);
339 return NULL;
252b5132
RH
340}
341
342static char *
69d246d9 343hpux_core_core_file_failing_command (bfd *abfd)
252b5132
RH
344{
345 return core_command (abfd);
346}
347
252b5132 348static int
69d246d9 349hpux_core_core_file_failing_signal (bfd *abfd)
252b5132
RH
350{
351 return core_signal (abfd);
352}
353
252b5132 354\f
252b5132
RH
355/* If somebody calls any byte-swapping routines, shoot them. */
356static void
69d246d9 357swap_abort (void)
252b5132
RH
358{
359 abort(); /* This way doesn't require any declaration for ANSI to fuck up */
360}
8ce8c090 361
edeb6e24
AM
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)
8ce8c090
AM
365#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
366#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
367#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
252b5132 368
6d00b590 369const bfd_target core_hpux_vec =
252b5132
RH
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 */
d3aeb6ee
AM
379 0, /* symbol prefix */
380 ' ', /* ar_pad_char */
381 16, /* ar_max_namelen */
382 0, /* match priority. */
d1bcae83 383 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
8ce8c090 384 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */
edeb6e24
AM
385 NO_GET, NO_GETS, NO_PUT, /* 32 bit data */
386 NO_GET, NO_GETS, NO_PUT, /* 16 bit data */
8ce8c090 387 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */
edeb6e24
AM
388 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */
389 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */
252b5132
RH
390
391 { /* bfd_check_format */
8ce8c090
AM
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 */
252b5132
RH
396 },
397 { /* bfd_set_format */
d00dd7dc
AM
398 _bfd_bool_bfd_false_error,
399 _bfd_bool_bfd_false_error,
400 _bfd_bool_bfd_false_error,
401 _bfd_bool_bfd_false_error
252b5132
RH
402 },
403 { /* bfd_write_contents */
d00dd7dc
AM
404 _bfd_bool_bfd_false_error,
405 _bfd_bool_bfd_false_error,
406 _bfd_bool_bfd_false_error,
407 _bfd_bool_bfd_false_error
252b5132 408 },
3fde5a36 409
3f3c5c34
AM
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),
252b5132 419
c3c89269 420 NULL,
3fde5a36 421
2c3fc389 422 NULL /* backend_data */
8ce8c090 423 };
This page took 1.175162 seconds and 4 git commands to generate.