#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#if defined (HOST_HPPAHPUX) || defined (HOST_HP300HPUX) || defined (HOST_HPPAMPEIX)
#include <sys/core.h>
#include <sys/utsname.h>
#endif
#ifdef HOST_HPPABSD
#include "/hpux/usr/include/sys/core.h"
#endif
#include <sys/param.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#else
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#include <signal.h>
#include <machine/reg.h>
#include <sys/user.h>
#include <sys/file.h>
#if defined(CORE_ANON_SHMEM)
#define PROC_INFO_HAS_THREAD_ID (1)
#endif
#if !defined(CORE_ANON_SHMEM)
#define CORE_ANON_SHMEM 0x00000200
#endif
struct hpux_core_struct
{
int sig;
int lwpid;
unsigned long user_tid;
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)
static asection *make_bfd_asection
PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma,
unsigned int));
static const bfd_target *hpux_core_core_file_p
PARAMS ((bfd *));
static char *hpux_core_core_file_failing_command
PARAMS ((bfd *));
static int hpux_core_core_file_failing_signal
PARAMS ((bfd *));
static bfd_boolean hpux_core_core_file_matches_executable_p
PARAMS ((bfd *, bfd *));
static void swap_abort
PARAMS ((void));
static asection *
make_bfd_asection (abfd, name, flags, _raw_size, vma, alignment_power)
bfd *abfd;
const char *name;
flagword flags;
bfd_size_type _raw_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 (abfd, newname);
if (!asect)
return NULL;
asect->flags = flags;
asect->_raw_size = _raw_size;
asect->vma = vma;
asect->filepos = bfd_tell (abfd);
asect->alignment_power = alignment_power;
return asect;
}
static const bfd_target *
hpux_core_core_file_p (abfd)
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_bread ((void *) &core_header,
(bfd_size_type) sizeof core_header, abfd);
if (val <= 0)
break;
switch (core_header.type)
{
case CORE_KERNEL:
case CORE_FORMAT:
bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
good_sections++;
break;
case CORE_EXEC:
{
struct proc_exec proc_exec;
if (bfd_bread ((void *) &proc_exec, (bfd_size_type) core_header.len,
abfd) != core_header.len)
break;
strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1);
good_sections++;
}
break;
case CORE_PROC:
{
struct proc_info proc_info;
char secname[100];
if (bfd_bread (&proc_info, (bfd_size_type) core_header.len, abfd)
!= core_header.len)
break;
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 (core_kernel_thread_id (abfd) == 0)
{
if (!make_bfd_asection (abfd, ".reg",
SEC_HAS_CONTENTS,
core_header.len,
(int) &proc_info - (int) & proc_info.hw_regs,
2))
goto fail;
}
else
{
if (proc_info.sig != -1)
{
if (!make_bfd_asection (abfd, ".reg",
SEC_HAS_CONTENTS,
core_header.len,
(int) &proc_info - (int) & proc_info.hw_regs,
2))
goto fail;
}
sprintf (secname, ".reg/%d", core_kernel_thread_id (abfd));
if (!make_bfd_asection (abfd, secname,
SEC_HAS_CONTENTS,
core_header.len,
(int) &proc_info - (int) & 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, core_header.addr, 2))
goto fail;
bfd_seek (abfd, (file_ptr) core_header.len, SEEK_CUR);
good_sections++;
break;
case CORE_NONE:
unknown_sections++;
break;
default:
goto fail;
}
}
if ((unknown_sections > 0) && (good_sections > 0))
(*_bfd_error_handler)
("%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",
abfd->filename);
return abfd->xvec;
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 (abfd)
bfd *abfd;
{
return core_command (abfd);
}
static int
hpux_core_core_file_failing_signal (abfd)
bfd *abfd;
{
return core_signal (abfd);
}
static bfd_boolean
hpux_core_core_file_matches_executable_p (core_bfd, exec_bfd)
bfd *core_bfd ATTRIBUTE_UNUSED;
bfd *exec_bfd ATTRIBUTE_UNUSED;
{
return TRUE;
}
static void
swap_abort ()
{
abort();
}
#define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
#define NO_SIGNED_GET \
((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
const bfd_target hpux_core_vec =
{
"hpux-core",
bfd_target_unknown_flavour,
BFD_ENDIAN_BIG,
BFD_ENDIAN_BIG,
(HAS_RELOC | EXEC_P |
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
0,
' ',
16,
NO_GET, NO_SIGNED_GET, NO_PUT,
NO_GET, NO_SIGNED_GET, NO_PUT,
NO_GET, NO_SIGNED_GET, NO_PUT,
NO_GET, NO_SIGNED_GET, NO_PUT,
NO_GET, NO_SIGNED_GET, NO_PUT,
NO_GET, NO_SIGNED_GET, NO_PUT,
{
_bfd_dummy_target,
_bfd_dummy_target,
_bfd_dummy_target,
hpux_core_core_file_p
},
{
bfd_false, bfd_false,
bfd_false, bfd_false
},
{
bfd_false, bfd_false,
bfd_false, bfd_false
},
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,
(PTR) 0
};