ack/util/ass/assrl.c
2019-03-17 22:46:32 +08:00

324 lines
7.4 KiB
C

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*
*/
#include <stdio.h>
#include "ass00.h"
#include "assex.h"
#include "asscm.h"
#include "assrl.h"
#define COPYFINAL 1
#define COPYTEMP 0
/*
* collection of routines to deal with relocation business
*/
static void dataprocess(FILE *, FILE *);
static void textprocess(FILE *, FILE *);
relc_t * text_reloc(glob_t *glosym, FOFFSET off, int typ)
{
/*
* prepare the relocation that has to be done at text-offset off
* according to global symbol glosym.
* NOTE: The pointer glosym will point into mglobs[], while at
* the time copyout() is called all the symbols here
* will have disappeared.
* The procedure upd_reloc() will change this pointer
* into the one in xglobs[] later.
*/
register relc_t *nxtextreloc;
nxtextreloc = rlp_cast getarea(sizeof *nxtextreloc);
if (!f_text)
{
f_text = nxtextreloc;
}
else
{
l_text->r_next = nxtextreloc;
}
nxtextreloc->r_next = rlp_cast 0;
l_text = nxtextreloc;
nxtextreloc->r_off = off;
nxtextreloc->r_val.rel_gp = glosym;
nxtextreloc->r_typ = typ; /* flags of instruction */
return (nxtextreloc);
}
relc_t * data_reloc(char *arg ,FOFFSET off, int typ)
{
/*
* Same as above.
*/
register relc_t *nxdatareloc;
nxdatareloc = rlp_cast getarea(sizeof *nxdatareloc);
if (!f_data)
{
f_data = nxdatareloc;
}
else
{
l_data->r_next = nxdatareloc;
}
nxdatareloc->r_next = rlp_cast 0;
l_data = nxdatareloc;
nxdatareloc->r_off = off;
nxdatareloc->r_val.rel_lp = lbp_cast arg;
nxdatareloc->r_typ = typ;
return (nxdatareloc);
}
void copyout(void)
{
register int i;
int remtext;
/*
* Make the e.out file that looks as follows:
*
* __________________________
* | MAGIC | \
* | FLAGS | \
* | UNRESOLVED | \
* | VERSION | | 8*(2-byte word) header
* | WORDSIZE | | for interpreter selection
* | PTRSIZE | /
* | <UNUSED> | /
* | <UNUSED> | /
* | NTEXT | \
* | NDATA | \
* | NPROC | \
* | ENTRY-POINT | | 8*(wordsize-word) header
* | NLINES | | for interpreter proper
* | <UNUSED> | /
* | <UNUSED> | /
* | <UNUSED> | /
* |________________________|
* | |
* | TEXT | zero filled
* | | if not word multiple
* |________________________|
* | |
* | DATA |
* | |
* |________________________|
* | |
* | PROCTABLE |
* | |
* |________________________|
*
*
*/
remtext = textbytes % wordsize;
if (remtext != 0)
remtext = wordsize - remtext;
if ((ifile = fopen(eout, "w")) == 0)
fatal("can't create e.out");
rewind(tfile);
rewind(dfile);
xput16(as_magic, ifile);
xput16(intflags, ifile);
xput16(unresolved, ifile);
xput16(VERSION, ifile);
xput16(wordsize, ifile);
xput16(ptrsize, ifile);
xput16(0, ifile);
xput16(0, ifile);
xputa(textbytes + remtext, ifile);
xputa((cons_t) datablocks, ifile);
xputa((cons_t) procnum, ifile);
xputa((cons_t) searchproc(MAIN, xprocs, oursize->n_xproc)->p_num, ifile);
xputa((cons_t) sourcelines, ifile);
xputa((cons_t) databytes, ifile);
xputa((cons_t) 0, ifile);
xputa((cons_t) 0, ifile);
textprocess(tfile, ifile);
while (remtext--)
xputc(0, ifile);
dataprocess(dfile, ifile);
for (i = 0; i < procnum; i++)
{
xputarb(ptrsize, proctab[i].pr_loc, ifile);
xputarb(ptrsize, proctab[i].pr_off, ifile);
}
if (fclose(ifile) == EOF)
;
}
static void dataprocess(FILE *f1, FILE *outf)
{
relc_t datareloc;
FOFFSET i;
register int ieof;
rewind(rdfile);
ieof = getblk(rdfile, (char *) (&datareloc.r_off),
sizeof datareloc - sizeof datareloc.r_next);
for (i = 0; i < dataoff && !ieof; i++)
{
if (i == datareloc.r_off)
{
switch (datareloc.r_typ)
{
case RELADR:
xputa(xgeta(f1) + datareloc.r_val.rel_i, outf);
i += ptrsize - 1;
break;
case RELGLO:
if (datareloc.r_val.rel_gp->g_status & DEF)
{
xputa(xgeta(f1) + datareloc.r_val.rel_gp->g_val.g_addr, outf);
i += ptrsize - 1;
break;
}
if (unresolved == 0)
fatal("Definition botch");
case RELHEAD:
xputc((int) (xgetc(f1) + datareloc.r_val.rel_i), outf);
break;
default:
fatal("Bad r_typ in dataprocess");
}
ieof = getblk(rdfile, (char *) (&datareloc.r_off),
sizeof datareloc - sizeof datareloc.r_next);
}
else
xputc(xgetc(f1), outf);
}
for (; i < dataoff; i++)
xputc(xgetc(f1), outf);
if (!ieof && !getblk(rdfile, (char *) &datareloc, 1))
fatal("data relocation botch");
}
static void textprocess(FILE *f1, FILE *outf)
{
relc_t textreloc;
cons_t n;
FOFFSET i;
FILE *otfile;
int insl;
register int ieof;
char *op_curr;
register FOFFSET keep;
rewind(rtfile);
keep = textoff;
textoff = 0;
otfile = tfile;
tfile = outf;
/* This redirects the output of genop */
ieof = getblk(rtfile, (char *) (&textreloc.r_off),
sizeof textreloc - sizeof textreloc.r_next);
for (i = 0; i < keep && !ieof; i++)
{
if (i == textreloc.r_off)
{
if (textreloc.r_typ & RELMNS)
{
n = textreloc.r_val.rel_i;
}
else
{
if (textreloc.r_val.rel_gp->g_status & DEF)
{
n = textreloc.r_val.rel_gp->g_val.g_addr;
}
else
{
if (unresolved == 0)
fatal("Definition botch");
xputc(xgetc(f1), outf);
ieof = getblk(rtfile, (char *) (&textreloc.r_off),
sizeof textreloc - sizeof textreloc.r_next);
continue;
}
}
op_curr = &opchoice[textreloc.r_typ & ~RELMNS];
insl = oplength(*op_curr);
genop(op_curr, n + xgetarb(insl, f1), PAR_G);
i += insl - 1;
ieof = getblk(rtfile, (char *) (&textreloc.r_off),
sizeof textreloc - sizeof textreloc.r_next);
}
else
{
xputc(xgetc(f1), outf);
}
}
for (; i < keep; i++)
xputc(xgetc(f1), outf);
if (!ieof && !getblk(rtfile, (char *) &textreloc, 1))
fatal("text relocation botch");
textoff = keep;
tfile = otfile;
}
void upd_reloc(void)
{
register relc_t *p;
register glob_t *gbp;
/*
* Change reloc-tables such that for every pointer into mglobs
* either the corresponding pointer into xglobs or its value
* is substituted.
*
* Use is made of the known order of mglobs and xglobs
* see also getcore()
*/
while ( (p = f_text) != NULL)
{
gbp = p->r_val.rel_gp;
if (gbp->g_status & DEF)
{
p->r_typ |= RELMNS;
p->r_val.rel_i = gbp->g_val.g_addr;
}
else
p->r_val.rel_gp = gbp->g_val.g_gp;
putblk(rtfile, (char *) (&(p->r_off)), sizeof *p - sizeof p);
f_text = p->r_next;
freearea((area_t) p, sizeof *p);
}
while ( (p = f_data) != NULL)
{
if (p->r_typ == RELGLO)
{
gbp = p->r_val.rel_gp;
if (gbp->g_status & DEF)
{
p->r_typ = RELADR;
p->r_val.rel_i = gbp->g_val.g_addr;
}
else
p->r_val.rel_gp = gbp->g_val.g_gp;
}
putblk(rdfile, (char *) (&(p->r_off)), sizeof *p - sizeof p);
f_data = p->r_next;
freearea((area_t) p, sizeof *p);
}
l_data = rlp_cast 0;
}