1
0
mirror of https://github.com/DoctorWkt/unix-jun72.git synced 2026-02-14 20:07:17 +00:00
Files
DoctorWkt.unix-jun72/tools/disaout/aout.c

266 lines
8.0 KiB
C

#include "aout.h"
/* This code borrowed from Apout */
extern int special_magic(u_int16_t *cptr);
extern void load_0407_symbols(FILE *zin, int offset, int size, int base);
int Binary; /* Type of binary this a.out is */
u_int8_t *ispace, *dspace; /* Instruction and Data spaces */
static u_int8_t darray[PDP_MEM_SIZE], iarray[PDP_MEM_SIZE];
/* 2.11BSD allows up to 16 8K overlays in the 0430 and 0431 a.out types.
* Each overlay is loaded at the first 8K `click' above the end of the
* main text. The following structures hold the overlays from the current
* a.out, if there are any. Missing overlays have size 0 and pointer NULL.
*/
static struct {
u_int16_t size;
u_int8_t *ovlay;
} ovlist[NOVL] = {
{0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL},
{0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL},
{0, NULL}, {0, NULL}, {0, NULL}
};
static u_int8_t *ovbase; /* Base address of 2.11BSD overlays */
/* Load the a.out header from the given file pointer, and return it.
* Also return an integer describing which version of UNIX the a.out
* belongs to. If errors on reading, return -1.
*/
int load_aout_header(FILE * zin, struct exec * E)
{
char *cptr;
/* Read the a_magic value first */
/* This makes it easier to deal with */
/* parsing any script interpreter below */
if (fread(E, sizeof(u_int16_t), 1, zin) != 1) return (-1);
switch (E->a_magic) {
case ANY_SCRIPT: /* Shell script, return now */
return (IS_UNKNOWN);
case V1_NORMAL:
case ANY_NORMAL: /* These are recognised below */
case ANY_ROTEXT:
case ANY_SPLITID:
case BSD_OVERLAY:
case BSD_ROVERLAY:
case A68_MAGIC:
break;
default: /* Unrecognised binary, mark as such */
E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN);
}
/* We can deal with this a.out, so */
/* read in the rest of the header */
cptr = (char *) &(E->a_text);
if (fread(cptr, sizeof(struct exec) - sizeof(u_int16_t), 1, zin) != 1)
return (-1);
switch (E->a_magic) {
case A68_MAGIC: if (E->a_data==A68_DATA) return(IS_A68);
else { E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN); }
case V1_NORMAL: return (IS_V1);
case BSD_OVERLAY:
case BSD_ROVERLAY: return (IS_211BSD);
case ANY_NORMAL:
case ANY_ROTEXT:
case ANY_SPLITID: /* Check crt0.o 2nd magic for V2/V6/V7/2.11BSD */
if (E->a_magic2 == V2_M2) return (IS_V2);
if (E->a_magic2 == V6_M2) return (IS_V6);
if (E->a_magic2 == V7_M2) return (IS_V7);
if (E->a_magic2 == BSD_M2) return (IS_211BSD);
/* Still no idea, use checksum to determine */
return(special_magic((u_int16_t *) E));
default: /* Should never get here */
E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN);
}
}
/* Load the named PDP-11 executable file into the disassembler's memory.
* Returns 0 if ok, -1 if error.
*/
int load_a_out(const char *file, struct exec * e)
{ /* @globals errno,stdout,stderr; @ */
#define V12_MEMBASE 16384 /* Offset for V1/V2 binaries load */
FILE *zin;
u_int8_t *ibase, *dbase, *bbase; /* Instruction, data, bss bases */
u_int16_t size;
int i,j;
if ((zin = fopen(file, "r"))==NULL) /* Open the file */
return (-1);
Binary = load_aout_header(zin, e); /* Determine a.out & Unix type */
if (e->a_magic == ANY_SCRIPT) {
return (-1);
}
if (e->a_magic == UNKNOWN_AOUT) {
return (-1);
}
switch (e->a_magic) {
case V1_NORMAL: /* V1 a.out binary looks like */
e->a_bss = e->a_syms; /* 0405 */
e->a_syms = e->a_data; /* size of text */
e->a_data = 0; /* size of symbol table */
/* reloc bits */
/* size of data (i.e bss) */
/* unused and zeroed */
/* We must rearrange fields */
/* Move back to start of V1 header */
if (fseek(zin, 0, SEEK_SET) != 0) {
(void) fclose(zin); return (-1);
}
ispace = dspace = darray;
ibase = &(ispace[V12_MEMBASE]); /* Load & run the binary starting */
dbase = &(ispace[e->a_text]); /* at address 16384 (040000) */
bbase = &(ispace[e->a_text + e->a_data]);
e->a_entry = V12_MEMBASE + 12; /* Add 12 to skip over a.out hdr */
break;
case A68_MAGIC: /* Algol 68 image */
if (fseek(zin, 0, SEEK_SET) != 0) {
(void) fclose(zin); return (-1);
}
e->a_text= e->ov_siz[0]+1;
e->a_data= 0;
e->a_bss= 0160000-e->a_text;
e->a_entry= e->a_flag;
ibase = ispace = dspace = darray;
dbase= ibase;
bbase= &(ispace[e->a_text+e->a_data]);
break;
case ANY_NORMAL:
/* Move back to end of V5/6/7 header */
if (fseek(zin, 16, SEEK_SET) != 0) {
(void) fclose(zin); return (-1);
}
ibase = ispace = dspace = darray;
if (Binary == IS_V2) {
ibase = &(ispace[V12_MEMBASE]);
e->a_entry = V12_MEMBASE;
dbase = &(ispace[e->a_text + V12_MEMBASE]);
bbase = &(ispace[e->a_text + e->a_data + V12_MEMBASE]);
} else {
dbase = &(ispace[e->a_text]);
bbase = &(ispace[e->a_text + e->a_data]);
}
/* If there is a symbol table, load it */
if (e->a_syms)
load_0407_symbols(zin, 16 + e->a_text + e->a_data,e->a_syms,e->a_entry);
break;
case ANY_ROTEXT:
/* Move back to end of V5/6/7 header */
if (fseek(zin, 16, SEEK_SET) != 0) {
(void) fclose(zin); return (-1);
}
/* @fallthrough@ */
case BSD_OVERLAY:
/* Round up text area to next 8K boundary */
if (e->a_text % EIGHT_K) {
size = EIGHT_K * (1 + e->a_text / EIGHT_K);
} else size = e->a_text;
/* And the next 8K boundary if overlays! */
if (e->a_magic == BSD_OVERLAY) {
if (e->max_ovl % EIGHT_K) {
size += EIGHT_K * (1 + e->max_ovl / EIGHT_K);
} else size += e->max_ovl;
}
ibase = ispace = dspace = darray;
dbase = &(ispace[size]);
bbase = &(ispace[size + e->a_data]);
break;
case ANY_SPLITID:
/* Move back to end of V5/6/7 header */
if (fseek(zin, 16, SEEK_SET) != 0) {
(void) fclose(zin); return (-1);
}
/* @fallthrough@ */
case BSD_ROVERLAY:
ibase = ispace = iarray;
dbase = dspace = darray;
bbase = &(dspace[e->a_data]);
break;
default:
(void) fprintf(stderr, "Apout - unknown a.out format 0%o\n", e->a_magic);
(void) fclose(zin); return (-1);
}
memset(darray, 0, PDP_MEM_SIZE); /* Clear all memory */
if (ispace != dspace) memset(iarray, 0, PDP_MEM_SIZE);
/* Now load the text into ibase */
for (size = e->a_text; size;) {
i = (int) fread(ibase, 1, (size_t) size, zin);
if (i == -1) { (void) fclose(zin); return (i); }
size -= i;
ibase += i;
}
/* Now deal with any overlays */
if (Binary == IS_211BSD)
switch (e->a_magic) {
case BSD_OVERLAY:
case BSD_ROVERLAY:
/* Round up text area to next 8K boundary */
if (e->a_text % EIGHT_K) {
size = EIGHT_K * (1 + e->a_text / EIGHT_K);
} else size = e->a_text;
ovbase = &ispace[size];
for (i = 0; i < NOVL; i++) {
if (e->ov_siz[i] == 0) {
ovlist[i].size = 0;
ovlist[i].ovlay = NULL;
continue;
}
/* Create memory for the overlay */
ovlist[i].size = e->ov_siz[i];
if (ovlist[i].ovlay)
free(ovlist[i].ovlay);
ovlist[i].ovlay = (u_int8_t *) malloc(e->ov_siz[i]);
if (ovlist[i].ovlay == NULL) {
fprintf(stderr, "Apout - can't malloc overlay!\n");
exit(-1);
}
/* Load the overlay into memory */
for (size = ovlist[i].size, ibase = ovlist[i].ovlay; size;) {
j = fread(ibase, 1, size, zin);
if (j == -1) {
fclose(zin); return (j);
}
size -= j;
ibase += j;
}
}
}
/* Now load the data into dbase */
if (dbase)
for (size = e->a_data; size;) {
i = (int) fread(dbase, 1, (size_t) size, zin);
if (i == -1) { (void) fclose(zin); return (i); }
size -= i;
dbase += i;
}
/* Now clear the bss */
if ((bbase != 0) && (e->a_bss != 0))
memset(bbase, 0, (size_t) e->a_bss);
(void) fclose(zin);
return (0);
}