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