#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "libaout.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/paccess.h>
#include <sys/region.h>
struct sco5_core_struct
{
struct user u;
};
static asection *make_bfd_asection
PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr));
static struct user *read_uarea PARAMS ((bfd *, int));
const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
bfd_boolean sco5_core_file_matches_executable_p
PARAMS ((bfd *core_bfd, bfd *exec_bfd));
static void swap_abort PARAMS ((void));
static asection *
make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
bfd *abfd;
const char *name;
flagword flags;
bfd_size_type _raw_size;
bfd_vma vma;
file_ptr filepos;
{
asection *asect;
asect = bfd_make_section_anyway (abfd, name);
if (!asect)
return NULL;
asect->flags = flags;
asect->_raw_size = _raw_size;
asect->vma = vma;
asect->filepos = filepos;
asect->alignment_power = 2;
return asect;
}
static struct user *
read_uarea(abfd, filepos)
bfd *abfd;
int filepos;
{
struct sco5_core_struct *rawptr;
bfd_size_type amt = sizeof (struct sco5_core_struct);
rawptr = (struct sco5_core_struct *) bfd_zmalloc (amt);
if (rawptr == NULL)
return NULL;
abfd->tdata.sco5_core_data = rawptr;
if (bfd_seek (abfd, (file_ptr) filepos, SEEK_SET) != 0
|| bfd_bread ((void *) &rawptr->u, (bfd_size_type) sizeof rawptr->u,
abfd) != sizeof rawptr->u)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (rawptr->u.u_dsize > 0x1000000)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (rawptr->u.u_ssize > 0x1000000)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
return &rawptr->u;
}
const bfd_target *
sco5_core_file_p (abfd)
bfd *abfd;
{
int coffset_siz, val, nsecs, cheadoffs;
int coresize;
struct user *u;
struct coreoffsets coffsets;
struct coresecthead chead;
char *secname;
flagword flags;
{
FILE *stream = bfd_cache_lookup (abfd);
struct stat statbuf;
if (stream == NULL)
return NULL;
if (fstat (fileno (stream), &statbuf) < 0)
{
bfd_set_error (bfd_error_system_call);
return NULL;
}
coresize = statbuf.st_size;
}
if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz),
SEEK_SET) != 0)
|| bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz,
abfd) != sizeof coffset_siz)
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0)
|| (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd)
!= sizeof coffsets)
|| ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
if (coffsets.u_info == 1)
{
u = read_uarea (abfd, coffsets.u_user);
if (! u)
goto fail;
if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
(bfd_size_type) coffsets.u_usize,
0 - (bfd_vma) u->u_ar0,
(file_ptr) coffsets.u_user))
goto fail;
if (!make_bfd_asection (abfd, ".data",
SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
((bfd_size_type) u->u_exdata.ux_dsize
+ u->u_exdata.ux_bsize),
(bfd_vma) u->u_exdata.ux_datorg,
(file_ptr) coffsets.u_data))
goto fail;
if (!make_bfd_asection (abfd, ".stack",
SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
(bfd_size_type) u->u_ssize * NBPC,
(bfd_vma) u->u_sub,
(file_ptr) coffsets.u_stack))
goto fail;
return abfd->xvec;
}
if ((bfd_seek (abfd,
(file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz),
SEEK_SET) != 0)
|| (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd)
!= sizeof nsecs)
|| (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs,
abfd) != sizeof cheadoffs)
|| (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0)
|| (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
!= sizeof chead)
|| (chead.cs_stype != CORES_OFFSETS)
|| (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
{
bfd_set_error (bfd_error_wrong_format);
goto fail;
}
nsecs--;
for (; nsecs; nsecs--)
{
if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0)
|| (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
!= sizeof chead))
{
bfd_set_error (bfd_error_wrong_format);
goto fail;
}
switch (chead.cs_stype)
{
case CORES_MAGIC:
if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
{
bfd_set_error (bfd_error_wrong_format);
goto fail;
}
secname = NULL;
nsecs++;
break;
case CORES_UAREA:
u = read_uarea (abfd, chead.cs_sseek);
if (! u)
goto fail;
chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
secname = ".reg";
flags = SEC_HAS_CONTENTS;
break;
case CORES_PREGION:
switch (chead.cs_x.csx_preg.csxp_rtyp)
{
case PT_DATA:
secname = ".data";
break;
case PT_STACK:
secname = ".stack";
break;
case PT_SHMEM:
secname = ".shmem";
break;
case PT_LIBDAT:
secname = ".libdat";
break;
case PT_V86:
secname = ".virt86";
break;
case PT_SHFIL:
secname = ".mmfile";
break;
case PT_XDATA0:
secname = ".Xdat0";
break;
default:
secname = "";
}
flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
break;
case CORES_PROC:
case CORES_ITIMER:
case CORES_SCOUTSNAME:
secname = NULL;
break;
default:
(*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
chead.cs_stype);
continue;
}
if (secname
&& !make_bfd_asection (abfd, secname, flags,
(bfd_size_type) chead.cs_vsize,
(bfd_vma) chead.cs_vaddr,
(file_ptr) chead.cs_sseek))
goto fail;
}
return abfd->xvec;
fail:
if (abfd->tdata.any)
{
bfd_release (abfd, abfd->tdata.any);
abfd->tdata.any = NULL;
}
bfd_section_list_clear (abfd);
return NULL;
}
char *
sco5_core_file_failing_command (abfd)
bfd *abfd;
{
char *com = abfd->tdata.sco5_core_data->u.u_comm;
if (*com)
return com;
else
return NULL;
}
int
sco5_core_file_failing_signal (ignore_abfd)
bfd *ignore_abfd;
{
return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
: -1);
}
bfd_boolean
sco5_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 sco5_core_vec =
{
"sco5-core",
bfd_target_unknown_flavour,
BFD_ENDIAN_LITTLE,
BFD_ENDIAN_LITTLE,
(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,
sco5_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 (sco5),
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
};