ack/util/led/finish.c

236 lines
5.2 KiB
C
Raw Normal View History

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
#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;
extern int flagword;
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)) {
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;
register ind_t charoff;
cnt = head->oh_nname;
charoff = OFF_CHAR(*head);
while (cnt--) {
if (name->on_foff != (long)0)
name->on_mptr = chars + name->on_foff - charoff;
name++;
}
}
/*
* 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();
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);
}
relocate(head, emit, names, relo, 0L);
1985-01-10 13:35:39 +00:00
relo++;
}
} else {
for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
if (sects[sectindex].os_flen) {
wrt_nulls(sectindex, zeros[sectindex]);
zeros[sectindex] = 0;
1987-04-08 17:15:30 +00:00
emit = getemit(head, sects, sectindex);
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) {
relocate(head,emit,names,relo,0L);
1987-04-08 17:15:30 +00:00
/*
* Write out the (probably changed)
* relocation information.
*/
if (flagword & RFLAG)
wr_relo(relo, 1);
}
}
wrt_emit(emit, sectindex,
sects[sectindex].os_flen);
1987-04-08 17:15:30 +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.
*/
if (flagword & RFLAG)
wr_relo(relo, 1);
}
}
wrt_emit(emit, sectindex, sz2);
sz -= sz2;
sf += sz2;
}
}
endemit(emit);
}
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
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-04-08 17:15:30 +00:00
wr_name(name, 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--) {
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;
rd_dbug(buf, (long)nbytes);
wr_dbug(buf, (long) nbytes);
1985-01-10 13:35:39 +00:00
dbugsize -= nbytes;
}
}
#endif SYMDBUG