#define RS6000COFF_C 1
#if defined(_AIX41) && !defined(_LONG_LONG)
#define _LONG_LONG
#endif
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#ifdef AIX_CORE
#ifdef AOUTHDR
#undef AOUTHDR
#endif
#define AOUTHDR second_AOUTHDR
#undef SCNHDR
#include <sys/user.h>
#define __LDINFO_PTRACE32__
#define __LDINFO_PTRACE64__
#include <sys/ldr.h>
#include <sys/core.h>
#include <sys/systemcfg.h>
#define core_hdr(bfd) ((CoreHdr *) bfd->tdata.any)
#if defined(CORE_VERSION_1) && !CORE_VERSION_1
# undef CORE_VERSION_1
#endif
typedef union {
#ifdef __ld_info32
struct __ld_info32 l32;
struct __ld_info64 l64;
#else
struct ld_info l32;
struct ld_info l64;
#endif
} LdInfo;
typedef union {
#ifdef AIX_CORE_DUMPX_CORE
struct core_dumpx new;
#else
struct core_dump new;
#endif
struct core_dump old;
} CoreHdr;
#ifdef CORE_VERSION_1
typedef union {
#ifdef AIX_CORE_DUMPX_CORE
struct vm_infox new;
#else
struct vm_info new;
#endif
struct vm_info old;
} VmInfo;
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CORE_NEW(c) (!(c).old.c_entries)
#else
# define CORE_NEW(c) 0
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_STACKORG(c) (c).c_stackorg
#else
# define CNEW_STACKORG(c) 0
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_LOADER(c) (c).c_loader
#else
# define CNEW_LOADER(c) 0
#endif
#define COLD_LOADER(c) (c).c_tab
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_LSIZE(c) (c).c_lsize
#else
# define CNEW_LSIZE(c) 0
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_DATAORG(c) (c).c_dataorg
#else
# define CNEW_DATAORG(c) 0
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_DATASIZE(c) (c).c_datasize
#else
# define CNEW_DATASIZE(c) 0
#endif
#if defined (HAVE_ST_C_IMPL) || defined (AIX_5_CORE)
# define CNEW_IMPL(c) (c).c_impl
#else
# define CNEW_IMPL(c) 0
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_COMM(c) (c).c_u.U_proc.pi_comm
#else
# define CNEW_COMM(c) 0
#endif
#ifdef CORE_VERSION_1
# define COLD_COMM(c) (c).c_u.U_comm
#else
# define COLD_COMM(c) (c).c_u.u_comm
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_CONTEXT64(c) (c).c_flt.hctx.r64
#else
# define CNEW_CONTEXT64(c) c
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_MSTSAVE(c) (c).c_flt.hctx.r32
#else
# define CNEW_MSTSAVE(c) c
#endif
#ifdef CORE_VERSION_1
# define COLD_MSTSAVE(c) (c).c_mst
#else
# define COLD_MSTSAVE(c) (c).c_u.u_save
#endif
#ifdef AIX_CORE_DUMPX_CORE
# define CNEW_PROC64(c) IS_PROC64(&(c).c_u.U_proc)
#else
# define CNEW_PROC64(c) 0
#endif
#ifdef CORE_VERSION_1
# define COLD_STACKEND 0x2ff23000
#else
# define COLD_STACKEND 0x2ff80000
#endif
#define CORE_COMMONSZ ((int) &((struct core_dump *) 0)->c_entries \
+ sizeof (((struct core_dump *) 0)->c_entries))
static bfd_boolean
read_hdr (bfd *abfd, CoreHdr *core)
{
bfd_size_type size;
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
return FALSE;
size = CORE_COMMONSZ;
if (bfd_bread (core, size, abfd) != size)
return FALSE;
if (CORE_NEW (*core))
size = sizeof (core->new);
else
size = sizeof (core->old);
size -= CORE_COMMONSZ;
return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size;
}
static asection *
make_bfd_asection (abfd, name, flags, size, vma, filepos)
bfd *abfd;
const char *name;
flagword flags;
bfd_size_type size;
bfd_vma vma;
file_ptr filepos;
{
asection *asect;
asect = bfd_make_section_anyway (abfd, name);
if (!asect)
return NULL;
asect->flags = flags;
asect->size = size;
asect->vma = vma;
asect->filepos = filepos;
asect->alignment_power = 8;
return asect;
}
const bfd_target *
rs6000coff_core_p (abfd)
bfd *abfd;
{
CoreHdr core;
struct stat statbuf;
bfd_size_type size;
char *tmpptr;
int c_flag;
file_ptr c_stack, c_regoff, c_loader;
bfd_size_type c_size, c_regsize, c_lsize;
bfd_vma c_stackend;
void *c_regptr;
int proc64;
if (!read_hdr (abfd, &core))
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (CORE_NEW (core))
{
c_flag = core.new.c_flag;
c_stack = (file_ptr) core.new.c_stack;
c_size = core.new.c_size;
c_stackend = CNEW_STACKORG (core.new) + c_size;
c_lsize = CNEW_LSIZE (core.new);
c_loader = CNEW_LOADER (core.new);
proc64 = CNEW_PROC64 (core.new);
}
else
{
c_flag = core.old.c_flag;
c_stack = (file_ptr) core.old.c_stack;
c_size = core.old.c_size;
c_stackend = COLD_STACKEND;
c_lsize = 0x7ffffff;
c_loader = (file_ptr) COLD_LOADER (core.old);
proc64 = 0;
}
if (proc64)
{
c_regsize = sizeof (CNEW_CONTEXT64 (core.new));
c_regptr = &CNEW_CONTEXT64 (core.new);
}
else if (CORE_NEW (core))
{
c_regsize = sizeof (CNEW_MSTSAVE (core.new));
c_regptr = &CNEW_MSTSAVE (core.new);
}
else
{
c_regsize = sizeof (COLD_MSTSAVE (core.old));
c_regptr = &COLD_MSTSAVE (core.old);
}
c_regoff = (char *) c_regptr - (char *) &core;
if (bfd_stat (abfd, &statbuf) < 0)
{
bfd_set_error (bfd_error_system_call);
return NULL;
}
if (!(c_flag & UBLOCK_VALID)
|| !(c_flag & LE_VALID))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (!(c_flag & USTACK_VALID))
{
bfd_set_error (bfd_error_file_truncated);
return NULL;
}
if (!(c_flag & (FULL_CORE | CORE_TRUNC)))
{
if (c_stack + (file_ptr) c_size != statbuf.st_size)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
}
if (!CORE_NEW (core) && (c_loader < (file_ptr) sizeof core.old ||
c_loader >= statbuf.st_size ||
c_loader >= c_stack))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (c_flag & CORE_TRUNC)
(*_bfd_error_handler) (_("%s: warning core file truncated"),
bfd_get_filename (abfd));
size = CORE_NEW (core) ? sizeof (core.new) : sizeof (core.old);
tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size);
if (!tmpptr)
return NULL;
memcpy (tmpptr, &core, size);
set_tdata (abfd, tmpptr);
if (CORE_NEW (core))
{
enum bfd_architecture arch;
unsigned long mach;
switch (CNEW_IMPL (core.new))
{
case POWER_RS1:
case POWER_RSC:
case POWER_RS2:
arch = bfd_arch_rs6000;
mach = bfd_mach_rs6k;
break;
default:
arch = bfd_arch_powerpc;
mach = bfd_mach_ppc;
break;
}
bfd_default_set_arch_mach (abfd, arch, mach);
}
if (!make_bfd_asection (abfd, ".stack",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
c_size, c_stackend - c_size, c_stack))
goto fail;
if (!make_bfd_asection (abfd, ".reg",
SEC_HAS_CONTENTS,
c_regsize, (bfd_vma) 0, c_regoff))
goto fail;
if (!make_bfd_asection (abfd, ".ldinfo",
SEC_HAS_CONTENTS,
c_lsize, (bfd_vma) 0, c_loader))
goto fail;
#ifndef CORE_VERSION_1
if (c_flag & FULL_CORE)
{
if (!make_bfd_asection (abfd, ".data",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
(bfd_size_type) core.old.c_u.u_dsize,
(bfd_vma)
CDATA_ADDR (core.old.c_u.u_dsize),
c_stack + c_size))
goto fail;
}
#endif
#ifdef CORE_VERSION_1
{
LdInfo ldinfo;
bfd_size_type ldi_datasize;
file_ptr ldi_core;
uint ldi_next;
bfd_vma ldi_dataorg;
bfd_size_type c_datasize, c_vmregions;
file_ptr c_data, c_vmm;
if (CORE_NEW (core))
{
c_datasize = CNEW_DATASIZE (core.new);
c_data = (file_ptr) core.new.c_data;
c_vmregions = core.new.c_vmregions;
c_vmm = (file_ptr) core.new.c_vmm;
}
else
{
c_datasize = core.old.c_datasize;
c_data = (file_ptr) core.old.c_data;
c_vmregions = core.old.c_vmregions;
c_vmm = (file_ptr) core.old.c_vmm;
}
if (c_datasize)
{
if (!make_bfd_asection (abfd, ".data",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
c_datasize,
(bfd_vma) CDATA_ADDR (c_datasize),
c_data))
goto fail;
}
if (proc64)
size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
else
size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
while (1)
{
if (bfd_seek (abfd, c_loader, SEEK_SET) != 0)
goto fail;
if (bfd_bread (&ldinfo, size, abfd) != size)
goto fail;
if (proc64)
{
ldi_core = ldinfo.l64.ldinfo_core;
ldi_datasize = ldinfo.l64.ldinfo_datasize;
ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg;
ldi_next = ldinfo.l64.ldinfo_next;
}
else
{
ldi_core = ldinfo.l32.ldinfo_core;
ldi_datasize = ldinfo.l32.ldinfo_datasize;
ldi_dataorg = (bfd_vma) (long) ldinfo.l32.ldinfo_dataorg;
ldi_next = ldinfo.l32.ldinfo_next;
}
if (ldi_core)
if (!make_bfd_asection (abfd, ".data",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
ldi_datasize, ldi_dataorg, ldi_core))
goto fail;
if (ldi_next == 0)
break;
c_loader += ldi_next;
}
if (c_vmregions)
{
bfd_size_type i;
if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0)
goto fail;
for (i = 0; i < c_vmregions; i++)
{
VmInfo vminfo;
bfd_size_type vminfo_size;
file_ptr vminfo_offset;
bfd_vma vminfo_addr;
size = CORE_NEW (core) ? sizeof (vminfo.new) : sizeof (vminfo.old);
if (bfd_bread (&vminfo, size, abfd) != size)
goto fail;
if (CORE_NEW (core))
{
vminfo_addr = (bfd_vma) vminfo.new.vminfo_addr;
vminfo_size = vminfo.new.vminfo_size;
vminfo_offset = vminfo.new.vminfo_offset;
}
else
{
vminfo_addr = (bfd_vma) (long) vminfo.old.vminfo_addr;
vminfo_size = vminfo.old.vminfo_size;
vminfo_offset = vminfo.old.vminfo_offset;
}
if (vminfo_offset)
if (!make_bfd_asection (abfd, ".vmdata",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
vminfo_size, vminfo_addr,
vminfo_offset))
goto fail;
}
}
}
#endif
return abfd->xvec;
fail:
bfd_release (abfd, abfd->tdata.any);
abfd->tdata.any = NULL;
bfd_section_list_clear (abfd);
return NULL;
}
bfd_boolean
rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
bfd *core_bfd;
bfd *exec_bfd;
{
CoreHdr core;
bfd_size_type size;
char *path, *s;
size_t alloc;
const char *str1, *str2;
bfd_boolean ret;
file_ptr c_loader;
if (!read_hdr (core_bfd, &core))
return FALSE;
if (CORE_NEW (core))
c_loader = CNEW_LOADER (core.new);
else
c_loader = (file_ptr) COLD_LOADER (core.old);
if (CORE_NEW (core) && CNEW_PROC64 (core.new))
size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
else
size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0)
return FALSE;
alloc = 100;
path = bfd_malloc ((bfd_size_type) alloc);
if (path == NULL)
return FALSE;
s = path;
while (1)
{
if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1)
{
free (path);
return FALSE;
}
if (*s == '\0')
break;
++s;
if (s == path + alloc)
{
char *n;
alloc *= 2;
n = bfd_realloc (path, (bfd_size_type) alloc);
if (n == NULL)
{
free (path);
return FALSE;
}
s = n + (path - s);
path = n;
}
}
str1 = strrchr (path, '/');
str2 = strrchr (exec_bfd->filename, '/');
str1 = str1 != NULL ? str1 + 1 : path;
str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
if (strcmp (str1, str2) == 0)
ret = TRUE;
else
ret = FALSE;
free (path);
return ret;
}
char *
rs6000coff_core_file_failing_command (abfd)
bfd *abfd;
{
CoreHdr *core = core_hdr (abfd);
char *com = CORE_NEW (*core) ?
CNEW_COMM (core->new) : COLD_COMM (core->old);
if (*com)
return com;
else
return 0;
}
int
rs6000coff_core_file_failing_signal (abfd)
bfd *abfd;
{
CoreHdr *core = core_hdr (abfd);
return CORE_NEW (*core) ? core->new.c_signo : core->old.c_signo;
}
#endif