Files
dreamlayers.netbsd-mopd/common/file.c
David Brownlee 2f79266747 Clean up CheckAOutFileInfo & GetAOutFileInfo
- Rework over complicated getMID with its double parameters and
  unnecessary assignments to a simple badMID, modelled on N_BADMAG
- Both CheckAOutFileInfo & GetAOutFileInfo now always rewind the
  fd before reading. They currently both leave the fd pointing
  directly after the in file exec struct header, but that matches
  the behaviour of similar methods
- Consistently handle swapped MID and AOUT magic values

We still have unnecessarily duplicated code here, but what is
here should be cleaner
2020-10-30 11:01:41 -04:00

1052 lines
23 KiB
C

/* $NetBSD: file.c,v 1.16 2016/06/08 01:11:49 christos Exp $ */
/*
* Copyright (c) 1995-96 Mats O Jansson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "port.h"
#ifndef lint
__RCSID("$NetBSD: file.c,v 1.16 2016/06/08 01:11:49 christos Exp $");
#endif
#include "os.h"
#include "common.h"
#include "file.h"
#include "mopdef.h"
#include <stddef.h>
#include <stdbool.h>
#ifndef NOAOUT
# if defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/exec_aout.h>
# elif defined(__FreeBSD__)
# include <sys/imgact_aout.h>
# else
# include "../netbsd_h/exec_aout.h"
# endif
# if !defined(MID_VAX)
# define MID_VAX 150
# endif
# if !defined(MID_VAX1K)
# define MID_VAX1K 140
# endif
#endif /* NOAOUT */
#ifndef NOELF
# if defined(__NetBSD__)
# include <sys/exec_elf.h>
# else
# include "../netbsd_h/exec_elf.h"
# endif
#endif /* NOELF */
#ifndef NOAOUT
static int getCLBYTES(int);
static bool badMID(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_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);
}
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: /* Native mode image (VAX) */
case IHD_C_RSX: /* RSX image produced by TKB */
case IHD_C_BPA: /* BASIC plus analog */
case IHD_C_ALIAS: /* Alias */
case IHD_C_CLI: /* Image is CLI */
case IHD_C_PMAX: /* PMAX system image */
case IHD_C_ALPHA: /* ALPHA system image */
break;
default:
return(-1);
}
return(0);
}
int
GetMopFileInfo(struct dllist *dl)
{
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: /* Native mode image (VAX) */
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;
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: /* RSX image produced by TKB */
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];
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: /* BASIC plus analog */
printf("BASIC-Plus Image, not supported\n");
return(-1);
break;
case IHD_C_ALIAS: /* Alias */
printf("Alias, not supported\n");
return(-1);
break;
case IHD_C_CLI: /* Image is CLI */
printf("CLI, not supported\n");
return(-1);
break;
case IHD_C_PMAX: /* PMAX system image */
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]);
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: /* ALPHA system image */
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;
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:
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
/* Returns true for unrecognised MID, else false */
static bool
badMID(int mid)
{
switch (mid) {
/* 0 is used by Athena 4.3BSD, Ultrix, and 4.3BSD-Quasijarus0c */
case 0:
break;
case MID_I386:
break;
#ifdef MID_M68K
case MID_M68K:
break;
#endif
#ifdef MID_M68K4K
case MID_M68K4K:
break;
#endif
#ifdef MID_NS32532
case MID_NS32532:
break;
#endif
case MID_SPARC:
break;
#ifdef MID_PMAX
case MID_PMAX:
break;
#endif
#ifdef MID_VAX
case MID_VAX:
break;
#endif
#ifdef MID_VAX1K
case MID_VAX1K:
break;
#endif
#ifdef MID_ALPHA
case MID_ALPHA:
break;
#endif
#ifdef MID_MIPS
case MID_MIPS:
break;
#endif
#ifdef MID_ARM6
case MID_ARM6:
break;
#endif
default:
return true;
}
return false;
}
static int
getCLBYTES(int mid)
{
int clbytes;
switch (mid) {
/* This works for Athena 4.3BSD. Is it valid for all mid == 0? */
case 0:
#ifdef MID_VAX1K
case MID_VAX1K:
#endif
clbytes = 1024;
break;
#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
#ifdef MID_VAX
case MID_VAX:
#endif
#if defined(MID_I386) || defined(MID_M68K4K) || defined(MID_NS32532) || \
defined(MID_PMAX) || defined(MID_MIPS) || defined(MID_ARM6) || \
defined(MID_VAX)
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);
/* Must be Elf32... */
if (ehdr.e_ident[EI_CLASS] != ELFCLASS32)
return(-1);
return(0);
#endif /* NOELF */
}
int
GetElfFileInfo(struct dllist *dl)
{
#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);
/* Must be Elf32... */
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);
}
dl->image_type = IMAGE_TYPE_ELF32;
dl->loadaddr = 0;
dl->xferaddr = e_entry; /* will relocate itself if necessary */
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);
}
}
/*
* In addition to padding between segments, this also
* takes care of memsz > filesz.
*/
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;
/*
* Now compute the logical offsets for each section.
*/
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;
}
/* Print info about the image. */
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 /* NOELF */
}
int
CheckAOutFile(int fd)
{
#ifdef NOAOUT
return(-1);
#else
struct exec ex, ex_swap;
(void)lseek(fd, (off_t) 0, SEEK_SET);
if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex))
return -1;
memcpy(&ex_swap, &ex, sizeof(ex));
mopFileSwapX((u_char *)&ex_swap, 0, 4);
if (N_BADMAG(ex) && N_BADMAG(ex_swap))
return -1;
if (badMID(N_GETMID(ex)) && badMID(N_GETMID(ex_swap)))
return -1;
return 0;
#endif /* NOAOUT */
}
int
GetAOutFileInfo(struct dllist *dl)
{
#ifdef NOAOUT
return(-1);
#else
u_int32_t mid;
u_int32_t magic, clbytes, clofset;
struct exec ex, ex_swap;
(void)lseek(dl->ldfd, (off_t) 0, SEEK_SET);
if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex))
return(-1);
memcpy(&ex_swap, &ex, sizeof(ex));
mopFileSwapX((u_char *)&ex_swap, 0, 4);
// XXX Does swapped magic always imply swapped MID?
if (N_BADMAG (ex)) {
if (N_BADMAG (ex_swap))
return -1;
mid = N_GETMID(ex_swap);
} else {
mid = N_GETMID(ex);
}
if (badMID(mid))
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_VAX1K
case MID_VAX1K:
#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;
}
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_VAX1K
case MID_VAX1K:
printf("vax 1k");
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 /* NOAOUT */
}
int
GetFileInfo(struct dllist *dl)
{
int error;
error = CheckElfFile(dl->ldfd);
if (error == 0) {
error = GetElfFileInfo(dl);
if (error != 0) {
return(-1);
}
return (0);
}
error = CheckAOutFile(dl->ldfd);
if (error == 0) {
error = GetAOutFileInfo(dl);
if (error != 0) {
return(-1);
}
return (0);
}
error = CheckMopFile(dl->ldfd);
if (error == 0) {
error = GetMopFileInfo(dl);
if (error != 0) {
return(-1);
}
return (0);
}
/* Unknown file format. */
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:
sec = dlslot->e_cursec;
/*
* We're pretty simplistic here. We do only file-backed
* or only zero-fill.
*/
/* Determine offset into section. */
secoff = dlslot->e_curpos - dlslot->e_sections[sec].s_loff;
/*
* If we're in the file-backed part of the section,
* transmit some of the file.
*/
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);
}
/*
* Otherwise, if we're in the zero-fill part of the
* section, transmit some zeros.
*/
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));
}
/*
* ...and if we haven't hit either of those cases,
* that's the end of the image.
*/
else {
return (0);
}
/*
* Advance the logical image pointer.
*/
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))
dlslot->e_cursec++;
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);
}