1987-03-09 19:15:41 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*/
|
1985-01-10 13:35:39 +00:00
|
|
|
#ifndef lint
|
|
|
|
static char rcsid[] = "$Header$";
|
|
|
|
#endif
|
|
|
|
|
1986-10-20 10:17:57 +00:00
|
|
|
#include <out.h>
|
1985-01-10 13:35:39 +00:00
|
|
|
#include "const.h"
|
|
|
|
#include "defs.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "orig.h"
|
|
|
|
#include "scan.h"
|
|
|
|
|
|
|
|
extern bool incore;
|
1990-07-30 11:56:28 +00:00
|
|
|
extern ushort NLocals;
|
1985-01-10 13:35:39 +00:00
|
|
|
extern int flagword;
|
1990-07-30 11:56:28 +00:00
|
|
|
extern struct outname *searchname();
|
1985-01-10 13:35:39 +00:00
|
|
|
|
1985-06-10 10:48:49 +00:00
|
|
|
static adjust_names();
|
|
|
|
static handle_relos();
|
|
|
|
static put_locals();
|
|
|
|
static compute_origins();
|
|
|
|
|
1985-01-10 13:35:39 +00:00
|
|
|
/*
|
|
|
|
* We know all there is to know about the current module.
|
|
|
|
* Now we relocate the values in the emitted bytes and write
|
|
|
|
* those to the final output file. Then we compute the relative origins
|
|
|
|
* for the next module.
|
|
|
|
*/
|
|
|
|
finish()
|
|
|
|
{
|
|
|
|
struct outhead *head;
|
|
|
|
struct outsect *sects;
|
|
|
|
struct outname *names;
|
|
|
|
char *chars;
|
|
|
|
|
|
|
|
get_modul();
|
|
|
|
head = (struct outhead *)modulptr(IND_HEAD);
|
|
|
|
sects = (struct outsect *)modulptr(IND_SECT(*head));
|
|
|
|
names = (struct outname *)modulptr(IND_NAME(*head));
|
|
|
|
chars = (char *)modulptr(IND_CHAR(*head));
|
|
|
|
adjust_names(names, head, chars);
|
|
|
|
handle_relos(head, sects, names);
|
|
|
|
if (!incore && !(flagword & SFLAG)) {
|
1986-10-20 10:17:57 +00:00
|
|
|
put_locals(names, head->oh_nname);
|
1985-01-10 13:35:39 +00:00
|
|
|
#ifdef SYMDBUG
|
|
|
|
put_dbug(OFF_DBUG(*head));
|
|
|
|
#endif SYMDBUG
|
|
|
|
}
|
|
|
|
compute_origins(sects, head->oh_nsect);
|
|
|
|
skip_modul(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust all local names for the move into core.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
adjust_names(name, head, chars)
|
|
|
|
register struct outname *name;
|
|
|
|
struct outhead *head;
|
|
|
|
register char *chars;
|
|
|
|
{
|
|
|
|
register int cnt;
|
1987-10-15 12:42:55 +00:00
|
|
|
register long charoff;
|
1990-07-30 11:56:28 +00:00
|
|
|
struct outname *base = name;
|
1985-01-10 13:35:39 +00:00
|
|
|
|
|
|
|
cnt = head->oh_nname;
|
|
|
|
charoff = OFF_CHAR(*head);
|
|
|
|
while (cnt--) {
|
|
|
|
if (name->on_foff != (long)0)
|
1987-10-15 12:42:55 +00:00
|
|
|
name->on_mptr = chars + (ind_t)(name->on_foff - charoff);
|
1985-01-10 13:35:39 +00:00
|
|
|
name++;
|
|
|
|
}
|
1990-07-30 11:56:28 +00:00
|
|
|
if (! incore) {
|
|
|
|
do_crs(base, head->oh_nname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
do_crs(base, count)
|
|
|
|
struct outname *base;
|
|
|
|
unsigned short count;
|
|
|
|
{
|
|
|
|
register struct outname *name = base;
|
|
|
|
|
|
|
|
while (count--) {
|
|
|
|
if ((name->on_type & S_TYP) == S_CRS) {
|
|
|
|
char *s;
|
|
|
|
struct outname *p;
|
|
|
|
|
|
|
|
s = address(ALLOGCHR, (ind_t) name->on_valu);
|
|
|
|
p = searchname(s, hash(s));
|
|
|
|
|
|
|
|
if (flagword & RFLAG) {
|
|
|
|
name->on_valu = NLocals + (p -
|
|
|
|
(struct outname *)
|
|
|
|
address(ALLOGLOB, (ind_t) 0));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
name->on_valu = p->on_valu;
|
|
|
|
name->on_type &= ~S_TYP;
|
|
|
|
name->on_type |= (p->on_type & S_TYP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
name++;
|
|
|
|
}
|
1985-01-10 13:35:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If all sections are in core, we can access them randomly, so we need only
|
|
|
|
* scan the relocation table once. Otherwise we must for each section scan
|
|
|
|
* the relocation table again, because the relocation entries of one section
|
|
|
|
* need not be consecutive.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
handle_relos(head, sects, names)
|
|
|
|
struct outhead *head;
|
|
|
|
struct outsect *sects;
|
|
|
|
struct outname *names;
|
|
|
|
{
|
|
|
|
register struct outrelo *relo;
|
|
|
|
register int sectindex;
|
|
|
|
register int nrelo;
|
|
|
|
register char *emit;
|
|
|
|
extern char *getemit();
|
|
|
|
extern struct outrelo *nextrelo();
|
1986-10-20 10:17:57 +00:00
|
|
|
static long zeros[MAXSECT];
|
1985-01-10 13:35:39 +00:00
|
|
|
|
|
|
|
if (incore) {
|
|
|
|
nrelo = head->oh_nrelo; sectindex = -1;
|
|
|
|
startrelo(head); relo = nextrelo();
|
|
|
|
while (nrelo--) {
|
|
|
|
if (sectindex != relo->or_sect - S_MIN) {
|
|
|
|
sectindex = relo->or_sect - S_MIN;
|
|
|
|
emit = getemit(head, sects, sectindex);
|
|
|
|
}
|
1987-05-21 10:06:14 +00:00
|
|
|
relocate(head, emit, names, relo, 0L);
|
1985-01-10 13:35:39 +00:00
|
|
|
relo++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
|
1986-10-20 10:17:57 +00:00
|
|
|
if (sects[sectindex].os_flen) {
|
1987-05-21 10:06:14 +00:00
|
|
|
wrt_nulls(sectindex, zeros[sectindex]);
|
|
|
|
zeros[sectindex] = 0;
|
1987-04-08 17:15:30 +00:00
|
|
|
emit = getemit(head, sects, sectindex);
|
1987-05-21 10:06:14 +00:00
|
|
|
if (emit) {
|
|
|
|
nrelo = head->oh_nrelo; startrelo(head);
|
|
|
|
while (nrelo--) {
|
1987-04-08 17:15:30 +00:00
|
|
|
relo = nextrelo();
|
|
|
|
if (relo->or_sect - S_MIN == sectindex) {
|
1987-05-21 10:06:14 +00:00
|
|
|
relocate(head,emit,names,relo,0L);
|
1987-04-08 17:15:30 +00:00
|
|
|
/*
|
|
|
|
* Write out the (probably changed)
|
|
|
|
* relocation information.
|
|
|
|
*/
|
1987-08-26 13:22:44 +00:00
|
|
|
if (flagword & (RFLAG|CFLAG))
|
1987-04-08 17:15:30 +00:00
|
|
|
wr_relo(relo, 1);
|
|
|
|
}
|
1987-05-21 10:06:14 +00:00
|
|
|
}
|
|
|
|
wrt_emit(emit, sectindex,
|
|
|
|
sects[sectindex].os_flen);
|
1987-04-08 17:15:30 +00:00
|
|
|
}
|
1987-05-21 10:06:14 +00:00
|
|
|
else {
|
|
|
|
long sz = sects[sectindex].os_flen;
|
|
|
|
long sf = 0;
|
|
|
|
long blksz;
|
|
|
|
char *getblk();
|
|
|
|
|
|
|
|
emit = getblk(sz, &blksz, sectindex);
|
|
|
|
while (sz) {
|
|
|
|
long sz2 = sz > blksz ? blksz : sz;
|
|
|
|
|
|
|
|
rd_emit(emit, sz2);
|
|
|
|
nrelo = head->oh_nrelo; startrelo(head);
|
|
|
|
while (nrelo--) {
|
|
|
|
relo = nextrelo();
|
|
|
|
if (relo->or_sect-S_MIN==sectindex
|
|
|
|
&&
|
|
|
|
relo->or_addr >= sf
|
|
|
|
&&
|
|
|
|
relo->or_addr < sf + sz2){
|
|
|
|
relocate(head,emit,names,relo,
|
|
|
|
sf);
|
|
|
|
/*
|
|
|
|
* Write out the (probably changed)
|
|
|
|
* relocation information.
|
|
|
|
*/
|
1987-08-26 13:22:44 +00:00
|
|
|
if (flagword & (RFLAG|CFLAG))
|
1987-05-21 10:06:14 +00:00
|
|
|
wr_relo(relo, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wrt_emit(emit, sectindex, sz2);
|
|
|
|
sz -= sz2;
|
|
|
|
sf += sz2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endemit(emit);
|
1986-10-20 10:17:57 +00:00
|
|
|
}
|
|
|
|
zeros[sectindex] += sects[sectindex].os_size -
|
|
|
|
sects[sectindex].os_flen;
|
1985-01-10 13:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write out the local names that must be saved.
|
|
|
|
*/
|
|
|
|
static
|
1986-10-20 10:17:57 +00:00
|
|
|
put_locals(name, nnames)
|
1987-04-08 17:15:30 +00:00
|
|
|
struct outname *name;
|
1985-01-10 13:35:39 +00:00
|
|
|
register ushort nnames;
|
|
|
|
{
|
1987-04-08 17:15:30 +00:00
|
|
|
register struct outname *oname = name;
|
|
|
|
register struct outname *iname = oname;
|
|
|
|
|
1985-01-10 13:35:39 +00:00
|
|
|
while (nnames--) {
|
1987-04-08 17:15:30 +00:00
|
|
|
if ((iname->on_type & S_EXT) == 0 && mustsavelocal(iname)) {
|
|
|
|
namerelocate(iname);
|
|
|
|
addbase(iname);
|
|
|
|
wrt_name(iname, 0);
|
|
|
|
*oname++ = *iname;
|
1985-01-10 13:35:39 +00:00
|
|
|
}
|
1987-04-08 17:15:30 +00:00
|
|
|
iname++;
|
1985-01-10 13:35:39 +00:00
|
|
|
}
|
1987-09-02 18:42:21 +00:00
|
|
|
wr_name(name, (unsigned int) (oname - name));
|
1985-01-10 13:35:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add all flen's and all (size - flen == zero)'s of preceding sections
|
|
|
|
* with the same number.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
compute_origins(sect, nsect)
|
|
|
|
register struct outsect *sect;
|
|
|
|
register ushort nsect;
|
|
|
|
{
|
|
|
|
extern struct orig relorig[];
|
|
|
|
register struct orig *orig = relorig;
|
|
|
|
|
|
|
|
while (nsect--) {
|
1986-10-20 10:17:57 +00:00
|
|
|
|
|
|
|
orig->org_size += sect->os_size;
|
1985-01-10 13:35:39 +00:00
|
|
|
orig++; sect++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef SYMDBUG
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write out what is after the string area. This is likely to be
|
|
|
|
* debugging information.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
put_dbug(offdbug)
|
|
|
|
long offdbug;
|
|
|
|
{
|
|
|
|
char buf[512];
|
|
|
|
register int nbytes;
|
|
|
|
register long dbugsize;
|
|
|
|
extern long objectsize;
|
|
|
|
|
|
|
|
dbugsize = objectsize - offdbug;
|
|
|
|
while (dbugsize) {
|
|
|
|
nbytes = dbugsize > 512 ? 512 : dbugsize;
|
1986-10-20 10:17:57 +00:00
|
|
|
rd_dbug(buf, (long)nbytes);
|
|
|
|
wr_dbug(buf, (long) nbytes);
|
1985-01-10 13:35:39 +00:00
|
|
|
dbugsize -= nbytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif SYMDBUG
|