#include "os.h"
#include "common.h"
#include "file.h"
#include "mopdef.h"
#include <stddef.h>
#ifndef NOAOUT
#if defined(__OpenBSD__)
#include <a.out.h>
#endif
#if defined(__bsdi__)
#define NOAOUT
#endif
#if defined(__FreeBSD__)
#include <sys/imgact_aout.h>
#endif
#if !defined(MID_I386)
#define MID_I386 134
#endif
#if !defined(MID_SPARC)
#define MID_SPARC 138
#endif
#if !defined(MID_VAX)
#define MID_VAX 140
#endif
#endif
#ifndef NOELF
#if defined(__OpenBSD__)
#include <elf.h>
#else
#define NOELF
#endif
#endif
#ifndef NOELF
#if !defined(_LP64)
#define NOELF64
#endif
#endif
#ifndef NOAOUT
static int getCLBYTES(int);
static int getMID(int, int);
#endif
const char *
FileTypeName(mopd_imagetype type)
{
switch (type) {
case IMAGE_TYPE_MOP:
return ("MOP");
case IMAGE_TYPE_ELF32:
return ("Elf32");
case IMAGE_TYPE_ELF64:
return ("Elf64");
case IMAGE_TYPE_AOUT:
return ("a.out");
}
abort();
}
void
mopFilePutLX(u_char *buf, int idx, u_int32_t value, int cnt)
{
int i;
for (i = 0; i < cnt; i++) {
buf[idx+i] = value % 256;
value = value / 256;
}
}
void
mopFilePutBX(u_char *buf, int idx, u_int32_t value, int cnt)
{
int i;
for (i = 0; i < cnt; i++) {
buf[idx+cnt-1-i] = value % 256;
value = value / 256;
}
}
u_int32_t
mopFileGetLX(u_char *buf, int idx, int cnt)
{
u_int32_t ret = 0;
int i;
for (i = 0; i < cnt; i++) {
int j = idx + cnt - 1 - i;
if (j < 0)
abort();
ret = ret * 256 + buf[j];
}
return(ret);
}
u_int32_t
mopFileGetBX(u_char *buf, int idx, int cnt)
{
u_int32_t ret = 0;
int i;
for (i = 0; i < cnt; i++) {
int j = idx + i;
if (j < 0)
abort();
ret = ret * 256 + buf[j];
}
return(ret);
}
#if !defined(NOELF) && !defined(NOELF64)
u_int64_t
mopFileGetLXX(u_char *buf, int idx, int cnt)
{
u_int64_t ret = 0;
int i;
for (i = 0; i < cnt; i++) {
int j = idx + cnt - 1 - i;
if (j < 0)
abort();
ret = ret * 256 + buf[j];
}
return(ret);
}
u_int64_t
mopFileGetBXX(u_char *buf, int idx, int cnt)
{
u_int64_t ret = 0;
int i;
for (i = 0; i < cnt; i++) {
int j = idx + i;
if (j < 0)
abort();
ret = ret * 256 + buf[j];
}
return(ret);
}
#endif
void
mopFileSwapX(u_char *buf, int idx, int cnt)
{
int i;
u_char c;
for (i = 0; i < (cnt / 2); i++) {
c = buf[idx+i];
buf[idx+i] = buf[idx+cnt-1-i];
buf[idx+cnt-1-i] = c;
}
}
int
CheckMopFile(int fd)
{
u_char header[512];
short image_type;
if (read(fd, header, 512) != 512)
return(-1);
(void)lseek(fd, (off_t) 0, SEEK_SET);
image_type = (u_short)(header[IHD_W_ALIAS+1]*256 + header[IHD_W_ALIAS]);
switch(image_type) {
case IHD_C_NATIVE:
case IHD_C_RSX:
case IHD_C_BPA:
case IHD_C_ALIAS:
case IHD_C_CLI:
case IHD_C_PMAX:
case IHD_C_ALPHA:
break;
default:
return(-1);
}
return(0);
}
int
GetMopFileInfo(struct dllist *dl, int info)
{
u_char header[512];
short image_type;
u_int32_t load_addr, xfr_addr, isd, iha, hbcnt, isize;
if (read(dl->ldfd, header, 512) != 512)
return(-1);
image_type = (u_short)(header[IHD_W_ALIAS+1]*256 +
header[IHD_W_ALIAS]);
switch (image_type) {
case IHD_C_NATIVE:
isd = (header[IHD_W_SIZE+1]*256 +
header[IHD_W_SIZE]);
iha = (header[IHD_W_ACTIVOFF+1]*256 +
header[IHD_W_ACTIVOFF]);
hbcnt = (header[IHD_B_HDRBLKCNT]);
isize = (header[isd+ISD_W_PAGCNT+1]*256 +
header[isd+ISD_W_PAGCNT]) * 512;
load_addr = ((header[isd+ISD_V_VPN+1]*256 +
header[isd+ISD_V_VPN]) & ISD_M_VPN)
* 512;
xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 +
header[iha+IHA_L_TFRADR1+2]*0x10000 +
header[iha+IHA_L_TFRADR1+1]*0x100 +
header[iha+IHA_L_TFRADR1]) & 0x7fffffff;
if (info == INFO_PRINT) {
printf("Native Image (VAX)\n");
printf("Header Block Count: %d\n",hbcnt);
printf("Image Size: %08x\n",isize);
printf("Load Address: %08x\n",load_addr);
printf("Transfer Address: %08x\n",xfr_addr);
}
break;
case IHD_C_RSX:
hbcnt = header[L_BBLK+1]*256 + header[L_BBLK];
isize = (header[L_BLDZ+1]*256 + header[L_BLDZ]) * 64;
load_addr = header[L_BSA+1]*256 + header[L_BSA];
xfr_addr = header[L_BXFR+1]*256 + header[L_BXFR];
if (info == INFO_PRINT) {
printf("RSX Image\n");
printf("Header Block Count: %d\n",hbcnt);
printf("Image Size: %08x\n",isize);
printf("Load Address: %08x\n",load_addr);
printf("Transfer Address: %08x\n",xfr_addr);
}
break;
case IHD_C_BPA:
if (info == INFO_PRINT) {
printf("BASIC-Plus Image, not supported\n");
}
return(-1);
break;
case IHD_C_ALIAS:
if (info == INFO_PRINT) {
printf("Alias, not supported\n");
}
return(-1);
break;
case IHD_C_CLI:
if (info == INFO_PRINT) {
printf("CLI, not supported\n");
}
return(-1);
break;
case IHD_C_PMAX:
isd = (header[IHD_W_SIZE+1]*256 +
header[IHD_W_SIZE]);
iha = (header[IHD_W_ACTIVOFF+1]*256 +
header[IHD_W_ACTIVOFF]);
hbcnt = (header[IHD_B_HDRBLKCNT]);
isize = (header[isd+ISD_W_PAGCNT+1]*256 +
header[isd+ISD_W_PAGCNT]) * 512;
load_addr = (header[isd+ISD_V_VPN+1]*256 +
header[isd+ISD_V_VPN]) * 512;
xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 +
header[iha+IHA_L_TFRADR1+2]*0x10000 +
header[iha+IHA_L_TFRADR1+1]*0x100 +
header[iha+IHA_L_TFRADR1]);
if (info == INFO_PRINT) {
printf("PMAX Image \n");
printf("Header Block Count: %d\n",hbcnt);
printf("Image Size: %08x\n",isize);
printf("Load Address: %08x\n",load_addr);
printf("Transfer Address: %08x\n",xfr_addr);
}
break;
case IHD_C_ALPHA:
isd = (header[EIHD_L_ISDOFF+3]*0x1000000 +
header[EIHD_L_ISDOFF+2]*0x10000 +
header[EIHD_L_ISDOFF+1]*0x100 +
header[EIHD_L_ISDOFF]);
hbcnt = (header[EIHD_L_HDRBLKCNT+3]*0x1000000 +
header[EIHD_L_HDRBLKCNT+2]*0x10000 +
header[EIHD_L_HDRBLKCNT+1]*0x100 +
header[EIHD_L_HDRBLKCNT]);
isize = (header[isd+EISD_L_SECSIZE+3]*0x1000000 +
header[isd+EISD_L_SECSIZE+2]*0x10000 +
header[isd+EISD_L_SECSIZE+1]*0x100 +
header[isd+EISD_L_SECSIZE]);
load_addr = 0;
xfr_addr = 0;
if (info == INFO_PRINT) {
printf("Alpha Image \n");
printf("Header Block Count: %d\n",hbcnt);
printf("Image Size: %08x\n",isize);
printf("Load Address: %08x\n",load_addr);
printf("Transfer Address: %08x\n",xfr_addr);
}
break;
default:
if (info == INFO_PRINT) {
printf("Unknown Image (%d)\n",image_type);
}
return(-1);
}
dl->image_type = IMAGE_TYPE_MOP;
dl->loadaddr = load_addr;
dl->xferaddr = xfr_addr;
return(0);
}
#ifndef NOAOUT
static int
getMID(int old_mid, int new_mid)
{
int mid;
mid = old_mid;
switch (new_mid) {
case MID_I386:
mid = MID_I386;
break;
#ifdef MID_M68K
case MID_M68K:
mid = MID_M68K;
break;
#endif
#ifdef MID_M68K4K
case MID_M68K4K:
mid = MID_M68K4K;
break;
#endif
#ifdef MID_NS32532
case MID_NS32532:
mid = MID_NS32532;
break;
#endif
case MID_SPARC:
mid = MID_SPARC;
break;
#ifdef MID_PMAX
case MID_PMAX:
mid = MID_PMAX;
break;
#endif
#ifdef MID_VAX
case MID_VAX:
mid = MID_VAX;
break;
#endif
#ifdef MID_ALPHA
case MID_ALPHA:
mid = MID_ALPHA;
break;
#endif
#ifdef MID_MIPS
case MID_MIPS:
mid = MID_MIPS;
break;
#endif
#ifdef MID_ARM6
case MID_ARM6:
mid = MID_ARM6;
break;
#endif
default:
break;
}
return(mid);
}
static int
getCLBYTES(int mid)
{
int clbytes;
switch (mid) {
#ifdef MID_VAX
case MID_VAX:
clbytes = 1024;
break;
#endif
#ifdef MID_I386
case MID_I386:
#endif
#ifdef MID_M68K4K
case MID_M68K4K:
#endif
#ifdef MID_NS32532
case MID_NS32532:
#endif
#ifdef MID_PMAX
case MID_PMAX:
#endif
#ifdef MID_MIPS
case MID_MIPS:
#endif
#ifdef MID_ARM6
case MID_ARM6:
#endif
#if defined(MID_I386) || defined(MID_M68K4K) || defined(MID_NS32532) || \
defined(MID_PMAX) || defined(MID_MIPS) || defined(MID_ARM6)
clbytes = 4096;
break;
#endif
#ifdef MID_M68K
case MID_M68K:
#endif
#ifdef MID_ALPHA
case MID_ALPHA:
#endif
#ifdef MID_SPARC
case MID_SPARC:
#endif
#if defined(MID_M68K) || defined(MID_ALPHA) || defined(MID_SPARC)
clbytes = 8192;
break;
#endif
default:
clbytes = 0;
}
return(clbytes);
}
#endif
int
CheckElfFile(int fd)
{
#ifdef NOELF
return(-1);
#else
Elf32_Ehdr ehdr;
(void)lseek(fd, (off_t) 0, SEEK_SET);
if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
return(-1);
if (ehdr.e_ident[0] != ELFMAG0 ||
ehdr.e_ident[1] != ELFMAG1 ||
ehdr.e_ident[2] != ELFMAG2 ||
ehdr.e_ident[3] != ELFMAG3)
return(-1);
if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 &&
ehdr.e_ident[EI_CLASS] != ELFCLASS64)
return(-1);
return(0);
#endif
}
int
GetElf32FileInfo(struct dllist *dl, int info)
{
#ifdef NOELF
return(-1);
#else
Elf32_Ehdr ehdr;
Elf32_Phdr phdr;
uint32_t e_machine, e_entry;
uint32_t e_phoff, e_phentsize, e_phnum;
int ei_data, i;
(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
return(-1);
if (ehdr.e_ident[0] != ELFMAG0 ||
ehdr.e_ident[1] != ELFMAG1 ||
ehdr.e_ident[2] != ELFMAG2 ||
ehdr.e_ident[3] != ELFMAG3)
return(-1);
if (ehdr.e_ident[EI_CLASS] != ELFCLASS32)
return(-1);
ei_data = ehdr.e_ident[EI_DATA];
switch (ei_data) {
case ELFDATA2LSB:
e_machine = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_machine),
sizeof(ehdr.e_machine));
e_entry = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_entry),
sizeof(ehdr.e_entry));
e_phoff = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phoff),
sizeof(ehdr.e_phoff));
e_phentsize = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phentsize),
sizeof(ehdr.e_phentsize));
e_phnum = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phnum),
sizeof(ehdr.e_phnum));
break;
case ELFDATA2MSB:
e_machine = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_machine),
sizeof(ehdr.e_machine));
e_entry = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_entry),
sizeof(ehdr.e_entry));
e_phoff = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phoff),
sizeof(ehdr.e_phoff));
e_phentsize = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phentsize),
sizeof(ehdr.e_phentsize));
e_phnum = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf32_Ehdr, e_phnum),
sizeof(ehdr.e_phnum));
break;
default:
return(-1);
}
if (e_phnum > SEC_MAX)
return(-1);
dl->e_nsec = e_phnum;
for (i = 0; i < dl->e_nsec; i++) {
if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize),
SEEK_SET) == (off_t) -1)
return(-1);
if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) !=
sizeof(phdr))
return(-1);
switch (ei_data) {
case ELFDATA2LSB:
dl->e_sections[i].s_foff =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_offset),
sizeof(phdr.p_offset));
dl->e_sections[i].s_vaddr =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_vaddr),
sizeof(phdr.p_vaddr));
dl->e_sections[i].s_fsize =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_filesz),
sizeof(phdr.p_filesz));
dl->e_sections[i].s_msize =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_memsz),
sizeof(phdr.p_memsz));
break;
case ELFDATA2MSB:
dl->e_sections[i].s_foff =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_offset),
sizeof(phdr.p_offset));
dl->e_sections[i].s_vaddr =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_vaddr),
sizeof(phdr.p_vaddr));
dl->e_sections[i].s_fsize =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_filesz),
sizeof(phdr.p_filesz));
dl->e_sections[i].s_msize =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf32_Phdr, p_memsz),
sizeof(phdr.p_memsz));
break;
default:
return(-1);
}
}
for (i = 0; i < dl->e_nsec - 1; i++) {
dl->e_sections[i].s_pad =
dl->e_sections[i + 1].s_vaddr -
(dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize);
}
dl->e_sections[dl->e_nsec - 1].s_pad =
dl->e_sections[dl->e_nsec - 1].s_msize -
dl->e_sections[dl->e_nsec - 1].s_fsize;
dl->e_sections[0].s_loff = 0;
for (i = 1; i < dl->e_nsec; i++) {
dl->e_sections[i].s_loff =
dl->e_sections[i - 1].s_loff +
dl->e_sections[i - 1].s_fsize +
dl->e_sections[i - 1].s_pad;
}
dl->image_type = IMAGE_TYPE_ELF32;
dl->loadaddr = 0;
#if 0
dl->xferaddr = e_entry;
#else
dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr;
#endif
if (info == INFO_PRINT) {
printf("Elf32 image (");
switch (e_machine) {
#ifdef EM_VAX
case EM_VAX:
printf("VAX");
break;
#endif
default:
printf("machine %d", e_machine);
break;
}
printf(")\n");
printf("Transfer Address: %08x\n", dl->xferaddr);
printf("Program Sections: %d\n", dl->e_nsec);
for (i = 0; i < dl->e_nsec; i++) {
printf(" S%d File Size: %08x\n", i,
dl->e_sections[i].s_fsize);
printf(" S%d Pad Size: %08x\n", i,
dl->e_sections[i].s_pad);
}
}
dl->e_machine = e_machine;
dl->e_curpos = 0;
dl->e_cursec = 0;
return(0);
#endif
}
int
GetElf64FileInfo(struct dllist *dl, int info)
{
#if defined(NOELF) || defined(NOELF64)
return(-1);
#else
Elf64_Ehdr ehdr;
Elf64_Phdr phdr;
uint32_t e_machine;
uint32_t e_phentsize, e_phnum;
uint64_t e_entry, e_phoff;
int ei_data, i;
(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
if (read(dl->ldfd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
return(-1);
if (ehdr.e_ident[0] != ELFMAG0 ||
ehdr.e_ident[1] != ELFMAG1 ||
ehdr.e_ident[2] != ELFMAG2 ||
ehdr.e_ident[3] != ELFMAG3)
return(-1);
if (ehdr.e_ident[EI_CLASS] != ELFCLASS64)
return(-1);
ei_data = ehdr.e_ident[EI_DATA];
switch (ei_data) {
case ELFDATA2LSB:
e_machine = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_machine),
sizeof(ehdr.e_machine));
e_entry = mopFileGetLXX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_entry),
sizeof(ehdr.e_entry));
e_phoff = mopFileGetLXX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phoff),
sizeof(ehdr.e_phoff));
e_phentsize = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phentsize),
sizeof(ehdr.e_phentsize));
e_phnum = mopFileGetLX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phnum),
sizeof(ehdr.e_phnum));
break;
case ELFDATA2MSB:
e_machine = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_machine),
sizeof(ehdr.e_machine));
e_entry = mopFileGetBXX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_entry),
sizeof(ehdr.e_entry));
e_phoff = mopFileGetBXX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phoff),
sizeof(ehdr.e_phoff));
e_phentsize = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phentsize),
sizeof(ehdr.e_phentsize));
e_phnum = mopFileGetBX((u_char *) &ehdr,
offsetof(Elf64_Ehdr, e_phnum),
sizeof(ehdr.e_phnum));
break;
default:
return(-1);
}
if (e_phnum > SEC_MAX)
return(-1);
dl->e_nsec = e_phnum;
for (i = 0; i < dl->e_nsec; i++) {
if (lseek(dl->ldfd, (off_t) e_phoff + (i * e_phentsize),
SEEK_SET) == (off_t) -1)
return(-1);
if (read(dl->ldfd, (char *) &phdr, sizeof(phdr)) !=
sizeof(phdr))
return(-1);
switch (ei_data) {
case ELFDATA2LSB:
dl->e_sections[i].s_foff =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_offset),
sizeof(phdr.p_offset));
dl->e_sections[i].s_vaddr =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_vaddr),
sizeof(phdr.p_vaddr));
dl->e_sections[i].s_fsize =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_filesz),
sizeof(phdr.p_filesz));
dl->e_sections[i].s_msize =
mopFileGetLX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_memsz),
sizeof(phdr.p_memsz));
break;
case ELFDATA2MSB:
dl->e_sections[i].s_foff =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_offset),
sizeof(phdr.p_offset));
dl->e_sections[i].s_vaddr =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_vaddr),
sizeof(phdr.p_vaddr));
dl->e_sections[i].s_fsize =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_filesz),
sizeof(phdr.p_filesz));
dl->e_sections[i].s_msize =
mopFileGetBX((u_char *) &phdr,
offsetof(Elf64_Phdr, p_memsz),
sizeof(phdr.p_memsz));
break;
default:
return(-1);
}
}
for (i = 0; i < dl->e_nsec - 1; i++) {
dl->e_sections[i].s_pad =
dl->e_sections[i + 1].s_vaddr -
(dl->e_sections[i].s_vaddr + dl->e_sections[i].s_fsize);
}
dl->e_sections[dl->e_nsec - 1].s_pad =
dl->e_sections[dl->e_nsec - 1].s_msize -
dl->e_sections[dl->e_nsec - 1].s_fsize;
dl->e_sections[0].s_loff = 0;
for (i = 1; i < dl->e_nsec; i++) {
dl->e_sections[i].s_loff =
dl->e_sections[i - 1].s_loff +
dl->e_sections[i - 1].s_fsize +
dl->e_sections[i - 1].s_pad;
}
dl->image_type = IMAGE_TYPE_ELF64;
dl->loadaddr = 0;
#if 0
dl->xferaddr = e_entry;
#else
dl->xferaddr = e_entry - dl->e_sections[0].s_vaddr;
#endif
if (info == INFO_PRINT) {
printf("Elf64 image (");
switch (e_machine) {
#ifdef EM_ALPHA
case EM_ALPHA:
#endif
#ifdef EM_ALPHA_EXP
case EM_ALPHA_EXP:
#endif
#if defined(EM_ALPHA) || defined(EM_ALPHA_EXP)
printf("ALPHA");
break;
#endif
default:
printf("machine %d", e_machine);
break;
}
printf(")\n");
printf("Transfer Address: %08x\n", dl->xferaddr);
printf("Program Sections: %d\n", dl->e_nsec);
for (i = 0; i < dl->e_nsec; i++) {
printf(" S%d File Size: %08x\n", i,
dl->e_sections[i].s_fsize);
printf(" S%d Pad Size: %08x\n", i,
dl->e_sections[i].s_pad);
}
}
dl->e_machine = e_machine;
dl->e_curpos = 0;
dl->e_cursec = 0;
return(0);
#endif
}
int
CheckAOutFile(int fd)
{
#ifdef NOAOUT
return(-1);
#else
struct exec ex, ex_swap;
int mid = -1;
if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex))
return(-1);
(void)lseek(fd, (off_t) 0, SEEK_SET);
if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap))
return(-1);
(void)lseek(fd, (off_t) 0, SEEK_SET);
mid = getMID(mid, N_GETMID (ex));
if (mid == -1) {
mid = getMID(mid, N_GETMID (ex_swap));
}
if (mid != -1) {
return(0);
} else {
return(-1);
}
#endif
}
int
GetAOutFileInfo(struct dllist *dl, int info)
{
#ifdef NOAOUT
return(-1);
#else
struct exec ex, ex_swap;
u_int32_t mid = -1;
u_int32_t magic, clbytes, clofset;
if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex))
return(-1);
(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
if (read(dl->ldfd, (char *)&ex_swap,
sizeof(ex_swap)) != sizeof(ex_swap))
return(-1);
mopFileSwapX((u_char *)&ex_swap, 0, 4);
mid = getMID(mid, N_GETMID (ex));
if (mid == (uint32_t)-1) {
mid = getMID(mid, N_GETMID (ex_swap));
if (mid != (uint32_t)-1) {
mopFileSwapX((u_char *)&ex, 0, 4);
}
}
if (mid == (uint32_t)-1) {
return(-1);
}
if (N_BADMAG (ex)) {
return(-1);
}
switch (mid) {
case MID_I386:
#ifdef MID_NS32532
case MID_NS32532:
#endif
#ifdef MID_PMAX
case MID_PMAX:
#endif
#ifdef MID_VAX
case MID_VAX:
#endif
#ifdef MID_ALPHA
case MID_ALPHA:
#endif
#ifdef MID_ARM6
case MID_ARM6:
#endif
ex.a_text = mopFileGetLX((u_char *)&ex_swap, 4, 4);
ex.a_data = mopFileGetLX((u_char *)&ex_swap, 8, 4);
ex.a_bss = mopFileGetLX((u_char *)&ex_swap, 12, 4);
ex.a_syms = mopFileGetLX((u_char *)&ex_swap, 16, 4);
ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4);
ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4);
ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4);
break;
#ifdef MID_M68K
case MID_M68K:
#endif
#ifdef MID_M68K4K
case MID_M68K4K:
#endif
case MID_SPARC:
#ifdef MID_MIPS
case MID_MIPS:
#endif
ex.a_text = mopFileGetBX((u_char *)&ex_swap, 4, 4);
ex.a_data = mopFileGetBX((u_char *)&ex_swap, 8, 4);
ex.a_bss = mopFileGetBX((u_char *)&ex_swap, 12, 4);
ex.a_syms = mopFileGetBX((u_char *)&ex_swap, 16, 4);
ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4);
ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4);
ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4);
break;
default:
break;
}
if (info == INFO_PRINT) {
printf("a.out image (");
switch (N_GETMID (ex)) {
case MID_I386:
printf("i386");
break;
#ifdef MID_M68K
case MID_M68K:
printf("m68k");
break;
#endif
#ifdef MID_M68K4K
case MID_M68K4K:
printf("m68k 4k");
break;
#endif
#ifdef MID_NS32532
case MID_NS32532:
printf("pc532");
break;
#endif
case MID_SPARC:
printf("sparc");
break;
#ifdef MID_PMAX
case MID_PMAX:
printf("pmax");
break;
#endif
#ifdef MID_VAX
case MID_VAX:
printf("vax");
break;
#endif
#ifdef MID_ALPHA
case MID_ALPHA:
printf("alpha");
break;
#endif
#ifdef MID_MIPS
case MID_MIPS:
printf("mips");
break;
#endif
#ifdef MID_ARM6
case MID_ARM6:
printf("arm32");
break;
#endif
default:
break;
}
printf(") Magic: ");
switch (N_GETMAGIC (ex)) {
case OMAGIC:
printf("OMAGIC");
break;
case NMAGIC:
printf("NMAGIC");
break;
case ZMAGIC:
printf("ZMAGIC");
break;
case QMAGIC:
printf("QMAGIC");
break;
default:
printf("Unknown %ld", (long) N_GETMAGIC (ex));
}
printf("\n");
printf("Size of text: %08lx\n", (long)ex.a_text);
printf("Size of data: %08lx\n", (long)ex.a_data);
printf("Size of bss: %08lx\n", (long)ex.a_bss);
printf("Size of symbol tab: %08lx\n", (long)ex.a_syms);
printf("Transfer Address: %08lx\n", (long)ex.a_entry);
printf("Size of reloc text: %08lx\n", (long)ex.a_trsize);
printf("Size of reloc data: %08lx\n", (long)ex.a_drsize);
}
magic = N_GETMAGIC (ex);
clbytes = getCLBYTES(mid);
clofset = clbytes - 1;
dl->image_type = IMAGE_TYPE_AOUT;
dl->loadaddr = 0;
dl->xferaddr = ex.a_entry;
dl->a_text = ex.a_text;
if (magic == ZMAGIC || magic == NMAGIC) {
dl->a_text_fill = clbytes - (ex.a_text & clofset);
if (dl->a_text_fill == clbytes)
dl->a_text_fill = 0;
} else
dl->a_text_fill = 0;
dl->a_data = ex.a_data;
if (magic == ZMAGIC || magic == NMAGIC) {
dl->a_data_fill = clbytes - (ex.a_data & clofset);
if (dl->a_data_fill == clbytes)
dl->a_data_fill = 0;
} else
dl->a_data_fill = 0;
dl->a_bss = ex.a_bss;
if (magic == ZMAGIC || magic == NMAGIC) {
dl->a_bss_fill = clbytes - (ex.a_bss & clofset);
if (dl->a_bss_fill == clbytes)
dl->a_bss_fill = 0;
} else {
dl->a_bss_fill = clbytes -
((ex.a_text+ex.a_data+ex.a_bss) & clofset);
if (dl->a_bss_fill == clbytes)
dl->a_bss_fill = 0;
}
dl->a_mid = mid;
return(0);
#endif
}
int
GetFileInfo(struct dllist *dl, int info)
{
int error;
error = CheckElfFile(dl->ldfd);
if (error == 0) {
error = GetElf32FileInfo(dl, info);
if (error != 0)
error = GetElf64FileInfo(dl, info);
if (error != 0) {
return(-1);
}
return (0);
}
error = CheckAOutFile(dl->ldfd);
if (error == 0) {
error = GetAOutFileInfo(dl, info);
if (error != 0) {
return(-1);
}
return (0);
}
error = CheckMopFile(dl->ldfd);
if (error == 0) {
error = GetMopFileInfo(dl, info);
if (error != 0) {
return(-1);
}
return (0);
}
return(-1);
}
ssize_t
mopFileRead(struct dllist *dlslot, u_char *buf)
{
ssize_t len, outlen;
int bsz, sec;
int32_t pos, notdone, total;
uint32_t secoff;
switch (dlslot->image_type) {
case IMAGE_TYPE_MOP:
len = read(dlslot->ldfd,buf,dlslot->dl_bsz);
break;
case IMAGE_TYPE_ELF32:
case IMAGE_TYPE_ELF64:
sec = dlslot->e_cursec;
secoff = dlslot->e_curpos - dlslot->e_sections[sec].s_loff;
if (secoff < dlslot->e_sections[sec].s_fsize) {
bsz = dlslot->e_sections[sec].s_fsize - secoff;
if (bsz > dlslot->dl_bsz)
bsz = dlslot->dl_bsz;
if (lseek(dlslot->ldfd,
dlslot->e_sections[sec].s_foff + secoff,
SEEK_SET) == (off_t) -1)
return (-1);
len = read(dlslot->ldfd, buf, bsz);
}
else if (secoff < (dlslot->e_sections[sec].s_fsize +
dlslot->e_sections[sec].s_pad)) {
bsz = dlslot->e_sections[sec].s_pad -
(secoff - dlslot->e_sections[sec].s_fsize);
if (bsz > dlslot->dl_bsz)
bsz = dlslot->dl_bsz;
memset(buf, 0, (len = bsz));
}
else {
return (0);
}
dlslot->e_curpos += bsz;
if (dlslot->e_curpos >= (dlslot->e_sections[sec].s_loff +
dlslot->e_sections[sec].s_fsize +
dlslot->e_sections[sec].s_pad))
if (++sec != dlslot->e_nsec)
dlslot->e_cursec = sec;
break;
case IMAGE_TYPE_AOUT:
bsz = dlslot->dl_bsz;
pos = dlslot->a_lseek;
len = 0;
total = dlslot->a_text;
if (pos < total) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = read(dlslot->ldfd,&buf[len],notdone);
} else {
outlen = read(dlslot->ldfd,&buf[len],bsz);
}
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
total = total + dlslot->a_text_fill;
if ((bsz > 0) && (pos < total)) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = notdone;
} else {
outlen = bsz;
}
memset(&buf[len], 0, outlen);
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
total = total + dlslot->a_data;
if ((bsz > 0) && (pos < total)) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = read(dlslot->ldfd,&buf[len],notdone);
} else {
outlen = read(dlslot->ldfd,&buf[len],bsz);
}
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
total = total + dlslot->a_data_fill;
if ((bsz > 0) && (pos < total)) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = notdone;
} else {
outlen = bsz;
}
memset(&buf[len], 0, outlen);
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
total = total + dlslot->a_bss;
if ((bsz > 0) && (pos < total)) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = notdone;
} else {
outlen = bsz;
}
memset(&buf[len], 0, outlen);
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
total = total + dlslot->a_bss_fill;
if ((bsz > 0) && (pos < total)) {
notdone = total - pos;
if (notdone <= bsz) {
outlen = notdone;
} else {
outlen = bsz;
}
memset(&buf[len], 0, outlen);
len = len + outlen;
pos = pos + outlen;
bsz = bsz - outlen;
}
dlslot->a_lseek = pos;
break;
default:
abort();
}
return(len);
}