Maybe some minor changes.

This commit is contained in:
duk 1985-01-10 13:35:39 +00:00
parent 58126396af
commit d7fb9edfe2
20 changed files with 2251 additions and 112 deletions

120
h/out.h Normal file
View file

@ -0,0 +1,120 @@
/* $Header$ */
/*
* output format for ACK assemblers
*/
#ifndef ushort
#define ushort unsigned short
#endif ushort
struct outhead {
ushort oh_magic; /* magic number */
ushort oh_stamp; /* version stamp */
ushort oh_flags; /* several format flags */
ushort oh_nsect; /* number of outsect structures */
ushort oh_nrelo; /* number of outrelo structures */
ushort oh_nname; /* number of outname structures */
long oh_nemit; /* sum of all os_flen */
long oh_nchar; /* size of string area */
};
#define O_MAGIC 0x0201 /* magic number of output file */
#define O_STAMP 0 /* version stamp */
#ifdef JOHAN
#define HF_BREV 0x0001 /* high order byte lowest address */
#define HF_WREV 0x0002 /* high order word lowest address */
#endif JOHAN
#define HF_LINK 0x0004 /* unresolved references left */
#define HF_8086 0x0008 /* os_base specially encoded */
struct outsect {
long os_base; /* startaddress in machine */
long os_size; /* section size in machine */
long os_foff; /* startaddress in file */
long os_flen; /* section size in file */
long os_lign; /* section alignment */
};
struct outrelo {
char or_type; /* type of reference */
char or_sect; /* referencing section */
ushort or_nami; /* referenced symbol index */
long or_addr; /* referencing address */
};
struct outname {
union {
char *on_ptr; /* symbol name (in core) */
long on_off; /* symbol name (in file) */
} on_u;
#define on_mptr on_u.on_ptr
#define on_foff on_u.on_off
ushort on_type; /* symbol type */
ushort on_desc; /* debug info */
long on_valu; /* symbol value */
};
/*
* relocation type bits
*/
#define RELSZ 0x07 /* relocation length */
#define RELO1 1 /* 1 byte */
#define RELO2 2 /* 2 bytes */
#define RELO4 4 /* 4 bytes */
#define RELPC 0x08 /* pc relative */
#ifndef JOHAN
#define RELBR 0x10 /* High order byte lowest address. */
#define RELWR 0x20 /* High order word lowest address. */
#endif JOHAN
/*
* section type bits and fields
*/
#define S_TYP 0x007F /* undefined, absolute or relative */
#define S_EXT 0x0080 /* external flag */
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
/*
* S_TYP field values
*/
#define S_UND 0x0000 /* undefined item */
#define S_ABS 0x0001 /* absolute item */
#define S_MIN 0x0002 /* first user section */
#define S_MAX S_TYP /* last user section */
/*
* S_ETC field values
*/
#define S_SCT 0x0100 /* section names */
#define S_LIN 0x0200 /* hll source line item */
#define S_FIL 0x0300 /* hll source file item */
#define S_MOD 0x0400 /* ass source file item */
#ifndef JOHAN
#define S_COM 0x1000 /* Common name. */
#endif JOHAN
/*
* structure format strings
*/
#define SF_HEAD "22222244"
#define SF_SECT "44444"
#define SF_RELO "1124"
#define SF_NAME "4224"
/*
* structure sizes (bytes in file; add digits in SF_*)
*/
#define SZ_HEAD 20
#define SZ_SECT 20
#define SZ_RELO 8
#define SZ_NAME 12
/*
* file access macros
*/
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
#define OFF_SECT(x) SZ_HEAD
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))

25
h/ranlib.h Normal file
View file

@ -0,0 +1,25 @@
/* $Header$ */
#ifndef SYMDEF
# define SYMDEF "__.SYMDEF"
#endif SYMDEF
/*
* Structure of the SYMDEF table of contents for an archive.
* SYMDEF begins with a long giving the number of ranlib
* structures that immediately follow, and then continues with a string
* table consisting of a long giving the number of bytes of
* strings that follow and then the strings themselves.
*/
struct ranlib {
union {
char *ran__ptr; /* symbol name (in core) */
long ran__off; /* symbol name (in file) */
} ran_u;
#define ran_ptr ran_u.ran__ptr
#define ran_off ran_u.ran__off
long ran_pos; /* library member is at this position */
};
#define SZ_RAN 8
#define SF_RAN "44"

178
util/led/archive.c Normal file
View file

@ -0,0 +1,178 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
#include "arch.h"
#include "out.h"
#include "ranlib.h"
#include "const.h"
#include "debug.h"
#include "defs.h"
#include "memory.h"
#define ENDLIB ((long)0)
extern ind_t hard_alloc();
static struct ar_hdr arhdr;
/*
* First read a long telling how many ranlib structs there are, then
* the structs themselves. Second read a long telling how many chars there are
* in the string table, then the string table itself.
* We keep only one ranlib table in core, so this table always starts at offset
* (ind_t)0 from its base.
*/
static long
getsymdeftable()
{
register ind_t off;
register struct ranlib *ran;
register long count;
register long nran, nchar;
extern long getlong();
count = nran = getlong();
debug("%ld ranlib structs, ", nran, 0, 0, 0);
off = hard_alloc(ALLORANL, nran * sizeof(struct ranlib));
if (off == BADOFF)
fatal("no space for ranlib structs");
ran = (struct ranlib *)address(ALLORANL, off);
read_table(ran, count);
nchar = getlong();
debug("%ld ranlib chars\n", nchar, 0, 0, 0);
if ((off = hard_alloc(ALLORANL, nchar)) == BADOFF)
fatal("no space for ranlib strings");
read_char(address(ALLORANL, off), nchar);
ran = (struct ranlib *)address(ALLORANL, (ind_t)0);
while (count--) {
/*
* Adjust because names are now in core, not on file.
* Note that `ran_off' is measured from the beginning of the
* string area, NOT from the beginning of the file.
*/
if (ran->ran_off >= nchar)
fatal("bad ranlib string offset");
ran->ran_off += off;
ran++;
}
return nran;
}
extern char *modulname;
extern long position;
/*
* Process archive with table of contents. The table of contents tells
* of symbols in which module they are defined. We scan the table for
* symbols that are known but not yet defined. Then we extract all necessary
* information from the corresponding module. This module may need symbols that
* were defined in modules located before this one in the archive, so we
* scan the table again. We perform these actions as long as new symbols
* are defined.
*/
arch()
{
long nran;
bool resolved;
nran = getsymdeftable();
savemagic();
do {
register ind_t ranindex;
register long count;
debug("(re)scan ranlib table\n", 0, 0, 0, 0);
ranindex = (ind_t)0;
count = nran;
resolved = FALSE;
while (count > 0) {
register struct ranlib *ran;
register char *string;
register struct outname *name;
register long pos;
extern int hash();
extern struct outname *searchname();
ran = (struct ranlib *)address(ALLORANL, ranindex);
string = address(ALLORANL, (ind_t)ran->ran_off);
name = searchname(string, hash(string));
if (name == (struct outname *)0 || !ISUNDEFINED(name)) {
ranindex += sizeof(struct ranlib);
count--;
continue;
}
seek(ran->ran_pos);
get_archive_header(&arhdr);
modulname = arhdr.ar_name;
debug("%s defines %s\n", modulname, string, 0, 0);
position = ran->ran_pos + SZ_ARCH;
resolved = TRUE;
/*
* This archive member is going to be linked,
* so we don't need to know what else it defines.
* Note that we assume that all ranlib information of
* one archive member is contiguous.
*/
pos = ran->ran_pos;
do {
count--; ran++;
ranindex += sizeof(struct ranlib);
} while (count > 0 && ran->ran_pos == pos);
notelib(pos);
savehdr(&arhdr);
extract();
}
} while (resolved);
dealloc(ALLORANL);
notelib(ENDLIB);
}
/*
* An archive member that will be loaded is remembered by storing its position
* in the archive into the table of positions.
*/
notelib(pos)
long pos;
{
register ind_t off;
if ((off = hard_alloc(ALLOARCH, (long)sizeof(long))) == BADOFF)
fatal("no space for archive position");
*(long *)address(ALLOARCH, off) = pos;
}
/*
* Index of position of first archive member of next archive.
*/
static ind_t posindex = (ind_t)0;
/*
* Process the archive in pass 2.
* We walk through the table of positions telling at what byte offset the
* archive header + module is located, until this position is ENDLIB, meaning
* that we've processed all needed modules in this archive. Each group of
* positions of an archive is terminated with ENDLIB.
*/
arch2()
{
register long *pos;
register ind_t localpos;
localpos = posindex;
for ( pos = (long *)address(ALLOARCH, localpos);
*pos != ENDLIB;
pos++, localpos += sizeof(long)
) {
seek(*pos);
get_archive_header(&arhdr);
modulname = arhdr.ar_name;
debug("%s: archive member\n", modulname, 0, 0, 0);
position = *pos + SZ_ARCH;
finish();
}
localpos += sizeof(long); /* Skip ENDLIB. */
posindex = localpos; /* Remember for next call. */
}

18
util/led/assert.h Normal file
View file

@ -0,0 +1,18 @@
/* $Header$ */
#ifndef lint
#ifdef NASSERT
#define assert(ex)
#else NASSERT
#define assert(ex) \
{if (!(ex)) fatal("Assertion failed: file %s, line %d", __FILE__, __LINE__);}
#endif NASSERT
#else lint
#define assert(ex)
#endif lint

90
util/led/byte_order.c Normal file
View file

@ -0,0 +1,90 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif lint
#include "const.h"
#include "assert.h"
bool bytes_reversed = FALSE;
bool words_reversed = FALSE;
/*
* Determine the byte/word order in shorts/longs, assuming the size of a short
* is 2 chars, and the size of a long is 4 chars. Not all theoretical
* possibilities are tested; only bytes reversed and/or words reversed.
*/
determine_ordering()
{
short s;
long l;
register char *cp;
register short *sp;
cp = (char *)&s;
cp[0] = 0x01; cp[1] = 0x02;
if (s != 0x01 + (0x02 << 8))
bytes_reversed = TRUE;
sp = (short *)&l;
sp[0] = 0x0001; sp[1] = 0x0002;
if (l != 0x0001 + (0x0002 << 16))
words_reversed = TRUE;
}
/*
* `Format' is a string of digits indicating how many bytes must be taken
* from `buf' to form an integer of some type. E.g. if the digit is '2', two
* bytes are taken to form a short.
*/
swap(buf, format)
register char *buf;
register char *format;
{
register char savebyte;
while (*format) {
switch (*format++) {
case '1':
buf += 1;
break;
case '2':
if (bytes_reversed) {
savebyte = buf[0];
buf[0] = buf[1];
buf[1] = savebyte;
}
buf += 2;
break;
case '4':
/*
* Written out to save recursive calls.
*/
if (bytes_reversed && words_reversed) {
savebyte = buf[0];
buf[0] = buf[3];
buf[3] = savebyte;
savebyte = buf[1];
buf[1] = buf[2];
buf[2] = savebyte;
} else if (bytes_reversed) {
savebyte = buf[0];
buf[0] = buf[1];
buf[1] = savebyte;
savebyte = buf[2];
buf[2] = buf[3];
buf[3] = savebyte;
} else if (words_reversed) {
savebyte = buf[0];
buf[0] = buf[2];
buf[2] = savebyte;
savebyte = buf[1];
buf[1] = buf[3];
buf[3] = savebyte;
}
buf += 4;
break;
default:
assert(FALSE);
break;
}
}
}

26
util/led/const.h Normal file
View file

@ -0,0 +1,26 @@
/* $Header$ */
typedef int bool;
#define FALSE 0
#define TRUE 1
#define S_ZER 0x2000 /* Internal use only. */
#define WIDTH 8 /* Number of bits in a byte. */
#define BYTEMASK 0xFF /* Mask to get low order byte. */
#define MININT (1 << (sizeof(int) * WIDTH - 1))
#define MAXCHUNK (-(MININT + 1)) /* Highest count we write(2). */
#define RFLAG 0x01 /* -r flag given. */
#define SFLAG 0x02 /* -s flag given. */
#define MAXSECT 64 /* Maximum number of sections. */
#define PLAIN 0 /* Input file is a normal file. */
#define ARCHIVE 1 /* Input file is an archive. */
#define FIRST 1 /* Pass number. */
#define SECOND 2 /* Idem. */
#define BADOFF ((ind_t)-1)

11
util/led/debug.h Normal file
View file

@ -0,0 +1,11 @@
/* $Header$ */
#ifdef NDEBUG
#define debug(s, a1, a2, a3, a4)
#else
#define debug(s, a1, a2, a3, a4) printf(s, a1, a2, a3, a4)
#endif

10
util/led/defs.h Normal file
View file

@ -0,0 +1,10 @@
/* $Header$ */
/*
* We need the S_EXT because we leave locals alone.
*/
#define ISUNDEFINED(n) (((n)->on_type & (S_TYP | S_EXT)) == (S_UND | S_EXT))
#define ISABSOLUTE(n) (((n)->on_type & (S_TYP | S_EXT)) == (S_ABS | S_EXT))
#define ISCOMMON(n) (((n)->on_type & (S_COM | S_EXT)) == (S_COM | S_EXT))
#define mustsavelocal(name) (!((name)->on_type & S_SCT))

182
util/led/finish.c Normal file
View file

@ -0,0 +1,182 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
#include "out.h"
#include "const.h"
#include "defs.h"
#include "memory.h"
#include "orig.h"
#include "scan.h"
extern bool incore;
extern int flagword;
/*
* 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, sects);
#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();
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, sects);
relo++;
}
} else {
for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
emit = getemit(head, sects, sectindex);
nrelo = head->oh_nrelo; startrelo(head);
while (nrelo--) {
relo = nextrelo();
if (relo->or_sect - S_MIN == sectindex) {
relocate(head,emit,names,relo,sects);
/*
* Write out the (probably changed)
* relocation information.
*/
if (flagword & RFLAG)
wrt_relo(relo);
}
}
wrt_emit(emit, sectindex, sects[sectindex].os_flen);
/*
* XXX We should be able to free the emitted bytes.
*/
}
}
}
/*
* Write out the local names that must be saved.
*/
static
put_locals(name, nnames, sects)
register struct outname *name;
register ushort nnames;
register struct outsect *sects;
{
while (nnames--) {
if ((name->on_type & S_EXT) == 0 && mustsavelocal(name)) {
namerelocate(name, sects);
addbase(name);
wrt_name(name);
}
name++;
}
}
/*
* 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_flen += sect->os_flen;
orig->org_zero += sect->os_size - sect->os_flen;
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;
extern long position;
dbugsize = objectsize - offdbug;
seek(position + offdbug);
while (dbugsize) {
nbytes = dbugsize > 512 ? 512 : dbugsize;
read_char(buf, (long)nbytes);
wrt_dbug(buf, nbytes);
dbugsize -= nbytes;
}
}
#endif SYMDBUG

24
util/led/mach.c Normal file
View file

@ -0,0 +1,24 @@
/*
* $Header$
*/
/*
* Values depend on the machine on which this program should run.
* Now for Vax 11/750.
*/
#define K 1024
mems[ALLOEMIT + 0].mem_left = 64 * K;
mems[ALLOEMIT + 1].mem_left = 64 * K;
mems[ALLORELO].mem_left = 64 * K;
mems[ALLOLOCL].mem_left = 64 * K;
mems[ALLOGLOB].mem_left = 64 * K;
mems[ALLOLCHR].mem_left = 64 * K;
mems[ALLOGCHR].mem_left = 64 * K;
#ifdef SYMDBUG
mems[ALLODBUG].mem_left = 64 * K;
#endif SYMDBUG
mems[ALLOSYMB].mem_left = 4 * K;
mems[ALLOARCH].mem_left = 1 * K;
mems[ALLOMODL].mem_left = 3 * 64 * K;
mems[ALLORANL].mem_left = 4 * K;

View file

@ -9,7 +9,6 @@ static char rcsid[] = "$Header$";
* is done and pieces after the one that requested the growth are moved up.
*/
#include <stdio.h>
#include "out.h"
#include "const.h"
#include "assert.h"
@ -19,7 +18,7 @@ static char rcsid[] = "$Header$";
struct memory mems[NMEMS];
bool incore = TRUE; /* TRUE while everything can be kept in core. */
off_t core_position = (off_t)0; /* Index of current module. */
ind_t core_position = (ind_t)0; /* Index of current module. */
#define AT_LEAST 2 /* See comment about string areas. */
@ -29,51 +28,18 @@ off_t core_position = (off_t)0; /* Index of current module. */
*/
init_core()
{
FILE *ledrc;
int piece;
off_t left;
register char *base;
register off_t total_size;
register ind_t total_size;
register struct memory *mem;
extern char *sbrk();
#ifndef TJALK
/*
* Read in what should be allocated for each piece initially.
* This facilitates testing, but is slower and should not
* be done in the final version. XXX
*/
incore = (ledrc = fopen(".ledrc", "r")) != (FILE *)0;
#include "mach.c"
if (incore) {
while (fscanf(ledrc, "%d %d", &piece, &left) == 2)
mems[piece].mem_left = left;
fclose(ledrc);
}
#else TJALK
mems[ALLOHEAD].mem_left = 20; /*XXX*/
mems[ALLOSECT].mem_left = 60; /*XXX*/
mems[ALLOEMIT + 0].mem_left = 65536;
mems[ALLOEMIT + 1].mem_left = 65536;
mems[ALLORELO].mem_left = 65536;
mems[ALLOLOCL].mem_left = 65536;
mems[ALLOGLOB].mem_left = 65536;
mems[ALLOLCHR].mem_left = 65536;
mems[ALLOGCHR].mem_left = 65536;
#ifdef SYMDBUG
mems[ALLODBUG].mem_left = 65536;
#endif SYMDBUG
mems[ALLOSYMB].mem_left = 4096;
mems[ALLOARCH].mem_left = 512;
mems[ALLOMODL].mem_left = 196608;
mems[ALLORANL].mem_left = 4096;
#endif TJALK
total_size = (off_t)0;/* Will accumulate the sizes. */
total_size = (ind_t)0; /* Will accumulate the sizes. */
base = sbrk(0); /* First free. */
for (mem = mems; mem < &mems[NMEMS]; mem++) {
mem->mem_base = base;
mem->mem_full = (off_t)0;
mem->mem_full = (ind_t)0;
base += mem->mem_left; /* Each piece will start after prev. */
total_size += mem->mem_left;
}
@ -93,12 +59,11 @@ init_core()
mems[ALLOLCHR].mem_full = 1;
mems[ALLOGCHR].mem_full = 1;
if ((int)sbrk(total_size) == -1) {
if (total_size != (int)total_size || (int)sbrk((int)total_size) == -1) {
incore = FALSE; /* In core strategy failed. */
if ((int)sbrk(AT_LEAST) == -1)
fatal("no core at all");
}
}
/*
@ -109,13 +74,13 @@ init_core()
static bool
move_up(piece, incr)
register int piece;
register off_t incr;
register ind_t incr;
{
register struct memory *mem;
extern char *sbrk();
debug("move_up(%d, %d)\n", piece, (int)incr, 0, 0);
if ((int)sbrk(incr) == -1)
if (incr != (int)incr || (int)sbrk((int)incr) == -1)
return FALSE;
for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--)
@ -137,33 +102,33 @@ extern int passnumber;
static bool
compact(piece, incr)
register int piece;
register off_t incr;
register ind_t incr;
{
register off_t gain;
register ind_t gain;
register struct memory *mem;
debug("compact(%d, %d)\n", piece, (int)incr, 0, 0);
gain = mems[0].mem_left;
mems[0].mem_left = (off_t)0;
mems[0].mem_left = (ind_t)0;
for (mem = &mems[1]; mem <= &mems[piece]; mem++) {
/* Here memory is inserted before a piece. */
assert(passnumber == FIRST || gain == (off_t)0);
assert(passnumber == FIRST || gain == (ind_t)0);
copy_down(mem, gain);
gain += mem->mem_left;
mem->mem_left = (off_t)0;
mem->mem_left = (ind_t)0;
}
/*
* Note that we already added the left bytes of the piece we want to
* enlarge to `gain'.
*/
if (gain < incr) {
register off_t up = (off_t)0;
register ind_t up = (ind_t)0;
for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--) {
/* Here memory is appended after a piece. */
up += mem->mem_left;
copy_up(mem, up);
mem->mem_left = (off_t)0;
mem->mem_left = (ind_t)0;
}
gain += up;
}
@ -180,11 +145,11 @@ compact(piece, incr)
static
copy_down(mem, dist)
register struct memory *mem;
off_t dist;
ind_t dist;
{
register char *old;
register char *new;
register off_t size;
register ind_t size;
size = mem->mem_full;
old = mem->mem_base;
@ -203,11 +168,11 @@ copy_down(mem, dist)
static
copy_up(mem, dist)
register struct memory *mem;
off_t dist;
ind_t dist;
{
register char *old;
register char *new;
register off_t size;
register ind_t size;
size = mem->mem_full;
old = mem->mem_base + size;
@ -224,18 +189,20 @@ copy_up(mem, dist)
* how many times the area is moved, because of another allocate, this offset
* remains valid.
*/
off_t
ind_t
alloc(piece, size)
register int piece;
register off_t size;
register long size;
{
register off_t incr = 0;
register off_t left = mems[piece].mem_left;
register off_t full = mems[piece].mem_full;
register ind_t incr = 0;
register ind_t left = mems[piece].mem_left;
register ind_t full = mems[piece].mem_full;
assert(passnumber == FIRST || (!incore && piece == ALLOMODL));
if (size == (off_t)0)
if (size == (long)0)
return full;
if (size != (ind_t)size)
return BADOFF;
while (left + incr < size)
incr += INCRSIZE;
@ -254,14 +221,16 @@ alloc(piece, size)
* Same as alloc() but for a piece which really needs it. If the first
* attempt fails, release the space occupied by other pieces and try again.
*/
off_t
ind_t
hard_alloc(piece, size)
int piece;
off_t size;
register int piece;
register long size;
{
off_t ret;
register ind_t ret;
register int i;
if (size != (ind_t)size)
return BADOFF;
if ((ret = alloc(piece, size)) != BADOFF)
return ret;
@ -270,8 +239,6 @@ hard_alloc(piece, size)
*/
for (i = 0; i < NMEMS; i++) {
switch (i) {
case ALLOHEAD:
case ALLOSECT:
case ALLOGLOB:
case ALLOGCHR:
case ALLOSYMB:
@ -296,7 +263,7 @@ hard_alloc(piece, size)
static
free_saved_moduls()
{
register off_t size;
register ind_t size;
register char *old, *new;
register struct memory *mem = &mems[ALLOMODL];
@ -307,7 +274,7 @@ free_saved_moduls()
*new++ = *old++;
mem->mem_full -= core_position;
mem->mem_left += core_position;
core_position = (off_t)0;
core_position = (ind_t)0;
}
/*
@ -320,22 +287,20 @@ dealloc(piece)
/*
* Some pieces need their memory throughout the program.
*/
assert(piece != ALLOHEAD);
assert(piece != ALLOSECT);
assert(piece != ALLOGLOB);
assert(piece != ALLOGCHR);
assert(piece != ALLOSYMB);
assert(piece != ALLOARCH);
mems[piece].mem_left += mems[piece].mem_full;
mems[piece].mem_full = (off_t)0;
mems[piece].mem_full = (ind_t)0;
}
char *
core_alloc(piece, size)
register int piece;
register off_t size;
register long size;
{
register off_t off;
register ind_t off;
if ((off = alloc(piece, size)) == BADOFF)
return (char *)0;
@ -350,15 +315,13 @@ freeze_core()
{
register int i;
core_position = (off_t)0;
core_position = (ind_t)0;
if (incore)
return;
for (i = 0; i < NMEMS; i++) {
switch (i) {
case ALLOHEAD:
case ALLOSECT:
case ALLOGLOB:
case ALLOGCHR:
case ALLOSYMB:
@ -369,7 +332,7 @@ freeze_core()
break;
}
}
compact(NMEMS - 1, (off_t)0);
compact(NMEMS - 1, (ind_t)0);
}
/* ------------------------------------------------------------------------- */
@ -383,24 +346,24 @@ extern bool words_reversed;
*/
write_bytes()
{
register struct outhead *head;
ushort nsect, nrelo;
long offchar;
int fd;
register int piece;
extern ushort NLocals, NGlobals;
extern long NLChars, NGChars;
extern int flagword;
extern char *outputname;
ushort nsect, nrelo;
long offchar;
int fd;
register struct memory *mem;
extern ushort NLocals, NGlobals;
extern long NLChars, NGChars;
extern int flagword;
extern struct outhead outhead;
extern struct outsect outsect[];
extern char *outputname;
head = (struct outhead *)mems[ALLOHEAD].mem_base;
nsect = head->oh_nsect;
nrelo = head->oh_nrelo;
offchar = OFF_CHAR(*head);
nsect = outhead.oh_nsect;
nrelo = outhead.oh_nrelo;
offchar = OFF_CHAR(outhead);
if (bytes_reversed || words_reversed) {
headswap();
sectswap(nsect);
swap((char *)&outhead, SF_HEAD);
sectswap(outsect, nsect);
reloswap(nrelo);
}
/*
@ -423,8 +386,10 @@ write_bytes()
/*
* These pieces must always be written.
*/
for (piece = ALLOHEAD; piece < ALLORELO; piece++)
writelong(fd, mems[piece].mem_base, mems[piece].mem_full);
writelong(fd, (char *)&outhead, (ind_t)SZ_HEAD);
writelong(fd, (char *)outsect, (ind_t)nsect * SZ_SECT);
for (mem = &mems[ALLOEMIT]; mem < &mems[ALLORELO]; mem++)
writelong(fd, mem->mem_base, mem->mem_full);
/*
* The rest depends on the flags.
*/
@ -433,10 +398,10 @@ write_bytes()
if (!(flagword & SFLAG)) {
writelong(fd, mems[ALLOLOCL].mem_base, mems[ALLOLOCL].mem_full);
writelong(fd, mems[ALLOGLOB].mem_base, mems[ALLOGLOB].mem_full);
writelong(fd, mems[ALLOLCHR].mem_base + 1, NLChars);
writelong(fd, mems[ALLOGCHR].mem_base + 1, NGChars);
writelong(fd, mems[ALLOLCHR].mem_base + 1, (ind_t)NLChars);
writelong(fd, mems[ALLOGCHR].mem_base + 1, (ind_t)NGChars);
#ifdef SYMDBUG
writelong(fd, mems[ALLODBUG].mem_base, mems[ALLODBUG].mem_size);
writelong(fd, mems[ALLODBUG].mem_base, mems[ALLODBUG].mem_full);
#endif SYMDBUG
}
close(fd);
@ -446,12 +411,12 @@ static
writelong(fd, base, size)
register int fd;
register char *base;
register off_t size;
register ind_t size;
{
register int chunk;
while (size) {
chunk = size > (off_t)MAXCHUNK ? MAXCHUNK : size;
chunk = size > (ind_t)MAXCHUNK ? MAXCHUNK : size;
write(fd, base, chunk);
size -= chunk;
base += chunk;
@ -459,21 +424,10 @@ writelong(fd, base, size)
}
static
headswap()
{
register struct outhead *head;
head = (struct outhead *)mems[ALLOHEAD].mem_base;
swap((char *)head, SF_HEAD);
}
static
sectswap(nsect)
sectswap(sect, nsect)
register struct outsect *sect;
register ushort nsect;
{
register struct outsect *sect;
sect = (struct outsect *)mems[ALLOSECT].mem_base;
while (nsect--)
swap((char *)sect++, SF_SECT);
}

35
util/led/memory.h Normal file
View file

@ -0,0 +1,35 @@
/* $Header$ */
#define ALLOEMIT 0 /* Section contents. */
#define ALLORELO (ALLOEMIT + MAXSECT) /* Relocation table. */
#define ALLOLOCL (ALLORELO + 1) /* Saved local names. */
#define ALLOGLOB (ALLOLOCL + 1) /* Saved global names. */
#define ALLOLCHR (ALLOGLOB + 1) /* Strings of local names. */
#define ALLOGCHR (ALLOLCHR + 1) /* Strings of global names. */
#ifdef SYMDEBUG
#define ALLODBUG (ALLOGCHR + 1) /* Symbolic debugging info. */
#else SYMDEBUG
#define ALLODBUG ALLOGCHR
#endif SYMDEBUG
#define ALLOSYMB (ALLODBUG + 1) /* Symbol table. */
#define ALLOARCH (ALLOSYMB + 1) /* Archive positions. */
#define ALLOMODL (ALLOARCH + 1) /* Modules. */
#define ALLORANL (ALLOMODL + 1) /* Ranlib information. */
#define NMEMS (ALLORANL + 1)
#define INCRSIZE 1024
typedef unsigned int ind_t;
#define BADOFF ((ind_t)-1)
struct memory {
char *mem_base;
ind_t mem_full;
ind_t mem_left;
};
extern struct memory mems[];
#define address(piece,offset) (mems[(piece)].mem_base+(offset))
#define modulptr(offset) (mems[ALLOMODL].mem_base+core_position+(offset))
extern ind_t core_position;

6
util/led/orig.h Normal file
View file

@ -0,0 +1,6 @@
/* $Header$ */
struct orig {
long org_flen; /* Accumulated length of preceding sections. */
long org_zero; /* " " " zeroparts. */
};

134
util/led/read.c Normal file
View file

@ -0,0 +1,134 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
/*
* Routines to read in the various parts of the object file.
*/
#include "arch.h"
#include "out.h"
#include "ranlib.h"
#include "const.h"
#include "assert.h"
int infile; /* The current input file. */
extern bool bytes_reversed;
extern bool words_reversed;
ushort
getushort()
{
ushort ubuf;
if (read(infile, (char *)&ubuf, 2) != 2)
fatal("premature EOF");
if (bytes_reversed)
swap((char *)&ubuf, "2");
return ubuf;
}
long
getlong()
{
long lbuf;
if (read(infile, (char *)&lbuf, 4) != 4)
fatal("premature EOF");
if (bytes_reversed || words_reversed)
swap((char *)&lbuf, "4");
return lbuf;
}
read_head(head)
register struct outhead *head;
{
if (read(infile, (char *)head, SZ_HEAD) != SZ_HEAD)
fatal("premature EOF");
if (bytes_reversed || words_reversed)
swap((char *)head, SF_HEAD);
if (BADMAGIC(*head))
fatal("bad magic number");
}
/*
* Someone inadvertently misaligned a long, thereby creating a hole.
* Therefore we can't read the header in one chunk.
*/
read_arhdr(arhdr)
register struct ar_hdr *arhdr;
{
if (read(infile, (char *)arhdr, 14) != 14)
fatal("premature EOF");
if (read(infile, (char *)&arhdr->ar_date, SZ_ARCH - 14) != SZ_ARCH - 14)
fatal("premature EOF");
if (bytes_reversed || words_reversed)
swap((char *)&arhdr->ar_date, SF_ARCH);
}
read_table(ran, cnt)
register struct ranlib *ran;
register long cnt;
{
read_char((char *)ran, cnt * SZ_RAN);
if (bytes_reversed || words_reversed)
while (cnt--)
swap((char *)ran++, SF_RAN);
}
read_sect(sect, cnt)
register struct outsect *sect;
register ushort cnt;
{
if (read(infile, (char *)sect, cnt * SZ_SECT) != cnt * SZ_SECT)
fatal("premature EOF");
if (bytes_reversed || words_reversed)
while (cnt--)
swap((char *)sect++, SF_SECT);
}
read_emit(emit, cnt)
register char *emit;
register long cnt;
{
read_char(emit, cnt);
}
read_relo(relo, cnt)
register struct outrelo *relo;
register ushort cnt;
{
read_char((char *)relo, (long)cnt * SZ_RELO);
if (bytes_reversed || words_reversed)
while (cnt--)
swap((char *)relo++, SF_RELO);
}
read_name(name, cnt)
register struct outname *name;
register ushort cnt;
{
read_char((char *)name, (long)cnt * SZ_NAME);
if (bytes_reversed || words_reversed)
while (cnt--)
swap((char *)name++, SF_NAME);
}
/*
* We don't have to worry about byte order here.
*/
read_char(string, cnt)
register char *string;
register long cnt;
{
register int n;
while (cnt) {
n = cnt >= MAXCHUNK ? MAXCHUNK : cnt;
if (read(infile, string, n) != n)
fatal("premature EOF");
string += n;
cnt -= n;
}
}

256
util/led/relocate.c Normal file
View file

@ -0,0 +1,256 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
#include "out.h"
#include "const.h"
#include "debug.h"
#include "defs.h"
#include "orig.h"
#define UBYTE(x) ((x) & BYTEMASK)
/*
* The bits in type indicate how many bytes the value occupies and what
* significance should be attributed to each byte.
*/
static long
getvalu(addr, type)
char addr[];
char type;
{
ushort word0, word1;
switch (type & RELSZ) {
case RELO1:
return UBYTE(addr[0]);
case RELO2:
if (type & RELBR)
return (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
else
return (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
case RELO4:
if (type & RELBR) {
word0 = (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
word1 = (UBYTE(addr[2]) << WIDTH) + UBYTE(addr[3]);
} else {
word0 = (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
word1 = (UBYTE(addr[3]) << WIDTH) + UBYTE(addr[2]);
}
if (type & RELWR)
return ((long)word0 << (2 * WIDTH)) + word1;
else
return ((long)word1 << (2 * WIDTH)) + word0;
default:
fatal("bad relocation size");
}
/* NOTREACHED */
}
/*
* The bits in type indicate how many bytes the value occupies and what
* significance should be attributed to each byte.
* We do not check for overflow.
*/
static
putvalu(valu, addr, type)
long valu;
char addr[];
char type;
{
ushort word0, word1;
switch (type & RELSZ) {
case RELO1:
addr[0] = valu;
break;
case RELO2:
if (type & RELBR) {
addr[0] = valu >> WIDTH;
addr[1] = valu;
} else {
addr[0] = valu;
addr[1] = valu >> WIDTH;
}
break;
case RELO4:
if (type & RELWR) {
word0 = valu >> (2 * WIDTH);
word1 = valu;
} else {
word0 = valu;
word1 = valu >> (2 * WIDTH);
}
if (type & RELBR) {
addr[0] = word0 >> WIDTH;
addr[1] = word0;
addr[2] = word1 >> WIDTH;
addr[3] = word1;
} else {
addr[0] = word0;
addr[1] = word0 >> WIDTH;
addr[2] = word1;
addr[3] = word1 >> WIDTH;
}
break;
default:
fatal("bad relocation size");
}
}
/*
* Returns whether `valu' refers to the zero part of its section.
* The address of its zero part (relative to the beginning of the section)
* is in `zero_addr'. If `valu' is used in a pc-relative address computation,
* we have to do that computation ourselves. A pc-relative address is the
* difference between the address of the byte after the value and the "real"
* address:
* referencing address + its size + pc-relative address == "real" address.
*/
static bool
refers_zero(valu, relo, zero_addr)
register long valu;
struct outrelo *relo;
long zero_addr;
{
if (relo->or_type & RELPC) {
valu += relo->or_addr;
/*
* Below is a dirty switch-statement. But an even dirtier
* statement would be: valu += (relo->or_type & RELSZ),
* because in that case you would have to know the values
* of the RELO[124] symbols.
*/
switch (relo->or_type & RELSZ) {
case RELO4: valu += 1;
valu += 1;
case RELO2: valu += 1;
case RELO1: valu += 1;
}
}
return valu >= zero_addr;
}
extern ushort NLocals, NGlobals;
extern struct outsect outsect[];
extern struct orig relorig[];
/*
* There are two cases: `local' is an undefined external or common name,
* or `local' is a section name.
* First case: if the name has been defined in another module,
* its value is known and can be added. Or_nami will be the
* index of the name of the section in which this name was
* defined. Otherwise we must change or_nami to the index of
* this name in the name table of the output file and leave
* its value unchanged.
* Second case: we must update the value by the change
* in position of the section of local.
*/
static ushort
addrelo(relo, names, sects, valu_out)
struct outrelo *relo;
struct outname *names;
struct outsect *sects;
long *valu_out; /* Out variable. */
{
register struct outname *local = &names[relo->or_nami];
register ushort index = NLocals;
register long valu = *valu_out;
if (ISUNDEFINED(local) || ISCOMMON(local)) {
register struct outname *name;
extern int hash();
extern struct outname *searchname();
extern ushort indexof();
name = searchname(local->on_mptr, hash(local->on_mptr));
if (name == (struct outname *)0)
fatal("name %s not found in pass 2", local->on_mptr);
if (ISCOMMON(name) || ISUNDEFINED(name)) {
debug("can't relocate from %s\n",local->on_mptr,0,0,0);
index += indexof(name);
} else {
valu += name->on_valu;
index += NGlobals + (name->on_type & S_TYP) - S_MIN;
}
} else {
register int sectindex = (local->on_type & S_TYP) - S_MIN;
if (!(local->on_type & S_SCT))
fatal("bad relocation index");
if (refers_zero(valu, relo, sects[sectindex].os_flen)) {
valu -= sects[sectindex].os_flen;
valu += outsect[sectindex].os_flen;
valu += relorig[sectindex].org_zero;
} else {
valu += relorig[sectindex].org_flen;
}
valu += outsect[sectindex].os_base;
index += NGlobals + sectindex;
}
*valu_out = valu;
return index;
}
/*
* This routine relocates a value in a section pointed to by `emit', of
* which the header is pointed to by `head'. Relocation is relative to the
* names in `names'; `relo' tells how to relocate.
*/
relocate(head, emit, names, relo, sects)
struct outhead *head;
char *emit;
struct outname names[];
struct outrelo *relo;
struct outsect *sects;
{
long valu;
int sectindex = relo->or_sect - S_MIN;
extern struct outhead outhead;
/*
* Pick up previous value at location to be relocated.
*/
valu = getvalu(emit + relo->or_addr, relo->or_type);
/*
* Or_nami is an index in the name table of the considered module.
* The name of which it is an index can be:
* - an undefined external or a common name
* - a section name
* - the first name outside! the name table (argh)
*/
if (relo->or_nami < head->oh_nname) {
/* First two cases. */
relo->or_nami = addrelo(relo, names, sects, &valu);
} else {
/*
* Third case: it is absolute. The relocation of absolute
* names is always 0. We only need to change the index.
*/
relo->or_nami = NLocals + NGlobals + outhead.oh_nsect;
}
/*
* If relocation is pc-relative, we had to update the value by
* the change in distance between the referencING and referencED
* section. We already added the origin of the referencED section;
* now we subtract the origin of the referencING section.
* Note that the the value to be relocated cannot lie within the
* zero part.
*/
if (relo->or_type & RELPC)
valu -= relorig[sectindex].org_flen+outsect[sectindex].os_base;
/*
* Now put the value back.
*/
putvalu(valu, emit + relo->or_addr, relo->or_type);
/*
* We must change the offset within the section of the value to be
* relocated to its offset in the new section. `Or_addr' must again be
* in the normal part, of course.
*/
relo->or_addr += relorig[sectindex].org_flen;
}

104
util/led/save.c Normal file
View file

@ -0,0 +1,104 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
/*
* If everything is kept in core, we must save some things for the second pass.
*/
#include "arch.h"
#include "out.h"
#include "const.h"
#include "assert.h"
#include "memory.h"
extern bool incore;
extern char *core_alloc();
savemagic()
{
register char *p;
if (!incore)
return;
if ((p = core_alloc(ALLOMODL, (long)sizeof(ushort))) != (char *)0) {
*(ushort *)p = ARMAG;
core_position += sizeof(ushort);
}
}
savehdr(hdr)
struct ar_hdr *hdr;
{
register char *p;
if (!incore)
return;
if ((p=core_alloc(ALLOMODL,(long)sizeof(struct ar_hdr)))!=(char *)0) {
*(struct ar_hdr *)p = *hdr;
core_position += sizeof(struct ar_hdr);
}
}
long NLChars = 0; /* Size of string area for local names. */
long NGChars = 0; /* Idem for global names. */
/*
* Put the string in cp into the block allocated for the string area.
* Return its offset in this area. We don't use the first char of the string
* area, so that empty strings can be distinguished from the first string.
*/
ind_t
savechar(piece, off)
register int piece;
register ind_t off;
{
register long len;
register ind_t newoff;
extern int strlen();
extern ind_t alloc();
extern ind_t hard_alloc();
extern char *strcpy();
if (off == (ind_t)0)
return 0;
len = strlen(modulptr(off)) + 1;
if (piece == ALLOLCHR) {
NLChars += len;
if (!incore || (newoff = alloc(piece, len)) == BADOFF)
return BADOFF;
} else {
assert(piece == ALLOGCHR);
NGChars += len;
if ((newoff = hard_alloc(piece, len)) == BADOFF)
return BADOFF;
}
strcpy(address(piece, newoff), modulptr(off));
return newoff;
}
/*
* Put the local in `name' in the piece allocated for local names that must
* be saved. `Name' points to a private copy, so will not become invalid after
* allocation, but the string of which name->on_foff is the offset may be
* destroyed, so we save that first.
*/
savelocal(name)
struct outname *name;
{
ind_t savindex;
struct outname *new;
if ((savindex = savechar(ALLOLCHR, (ind_t)name->on_foff)) == BADOFF)
return;
new = (struct outname *)
core_alloc(ALLOLOCL, (long)sizeof(struct outname));
if (new != (struct outname *)0) {
*new = *name;
new->on_foff = savindex;
}
}

524
util/led/scan.c Normal file
View file

@ -0,0 +1,524 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
#ifdef SYMDBUG
#include <sys/types.h>
#include <sys/stat.h>
#endif SYMDBUG
#include "arch.h"
#include "out.h"
#include "ranlib.h"
#include "const.h"
#include "assert.h"
#include "memory.h"
#include "scan.h"
#define READ 0
#define IND_EMIT(x) (IND_CHAR(x) + (ind_t)align((x).oh_nchar))
#define IND_RELO(x) (IND_EMIT(x) + (x).oh_nsect * sizeof(ind_t))
#ifdef SYMDBUG
#define IND_DBUG(x) (IND_RELO(x) + sizeof(ind_t))
#endif SYMDBUG
extern long lseek();
extern bool incore;
extern int infile;
extern int passnumber;
char *archname; /* Name of archive, if reading from archive. */
char *modulname; /* Name of object module. */
long position; /* Byte offset within cuurent input file. */
#ifdef SYMDBUG
long objectsize;
#endif SYMDBUG
static long align();
static char *modulbase;
static long modulsize();
/*
* Open the file with name `filename' (if necessary) and examine the first
* few bytes to see if it's a plain file or an archive.
* In case of a plain file, the file pointer is repositioned after the
* examination. Otherwise it is at the beginning of the table of contents.
*/
int
getfile(filename)
char *filename;
{
struct ar_hdr archive_header;
ushort magic_number;
#ifdef SYMDBUG
struct stat statbuf;
extern int fstat();
#endif SYMDBUG
extern ushort getushort();
archname = (char *)0;
modulname = (char *)0;
if (passnumber == FIRST || !incore) {
if ((infile = open(filename, READ)) < 0)
fatal("can't read %s", filename);
magic_number = getushort();
} else {
modulbase = modulptr((ind_t)0);
magic_number = *(ushort *)modulbase;
}
switch (magic_number) {
case O_MAGIC:
#ifdef SYMDBUG
if (passnumber == FIRST || !incore) {
if (fstat(infile, &statbuf) < 0)
fatal("cannot stat");
objectsize = statbuf.st_size;
}
#endif SYMDBUG
position = (long)0;
seek((long)0);
modulname = filename;
return PLAIN;
case ARMAG:
archname = filename;
if (passnumber == FIRST) {
read_arhdr(&archive_header);
if (strcmp(archive_header.ar_name, SYMDEF))
fatal("no table of contents");
} else if (incore) {
modulbase += sizeof(ushort);
core_position += sizeof(ushort);
}
return ARCHIVE;
default:
fatal("wrong magic number");
}
/* NOTREACHED */
}
/* ARGSUSED */
closefile(filename)
char *filename;
{
if (passnumber == FIRST || !incore)
close(infile);
}
get_archive_header(archive_header)
register struct ar_hdr *archive_header;
{
if (passnumber == FIRST || !incore) {
read_arhdr(archive_header);
} else {
/* Copy structs. */
*archive_header = *(struct ar_hdr *)modulbase;
modulbase += sizeof(struct ar_hdr);
core_position += sizeof(struct ar_hdr);
}
#ifdef SYMDBUG
objectsize = archive_header.ar_size;
#endif SYMDBUG
}
get_modul()
{
if (passnumber == FIRST) {
scan_modul();
} else if (!incore) {
read_modul();
}
}
/*
* Read module from the current file. If it doesn't fit into core, the strategy
* to keep everything in core is abandoned, but we will always put the header,
* the section table, and the name and string table into core.
*/
static
scan_modul()
{
bool space;
struct outhead *head;
struct outsect *sect;
space = all_alloc();
head = (struct outhead *)modulptr(IND_HEAD);
if (space) {
sect = (struct outsect *)modulptr(IND_SECT(*head));
get_indirect(head, sect);
} else {
lseek(infile, OFF_NAME(*head) - OFF_EMIT(*head), 1);
}
read_name((struct outname *)modulptr(IND_NAME(*head)), head->oh_nname);
read_char((char *)modulptr(IND_CHAR(*head)), head->oh_nchar);
#ifdef SYMDBUG
if (space) {
get_dbug(*(ind_t *)modulptr(IND_DBUG(*head)),
ojectsize - OFF_DBUG(*head)
);
}
#endif SYMDBUG
}
/*
* Allocate space for and read in the header and section table.
* First get the header. With this we can determine what to allocate
* for the rest of the module, and with the rest we can determine what
* to allocate for the section contents.
* If possible, allocate space for the rest of the module. Return whether
* this was possible.
*/
static bool
all_alloc()
{
struct outhead head;
extern ind_t hard_alloc();
if (hard_alloc(ALLOMODL, (long)sizeof(struct outhead)) == BADOFF)
fatal("no space for module header");
read_head((struct outhead *)modulptr(IND_HEAD));
/*
* Copy the header because we need it so often.
*/
head = *(struct outhead *)modulptr(IND_HEAD);
return direct_alloc(&head) && indirect_alloc(&head);
}
/*
* Allocate space for the rest of the direct bytes.
* First allocate the section table and read it in, then allocate the rest
* and return whether this succeeded.
*/
static bool
direct_alloc(head)
struct outhead *head;
{
ind_t sectindex = IND_SECT(*head);
ushort nsect = head->oh_nsect;
long size, rest;
extern ind_t hard_alloc();
extern ind_t alloc();
#ifdef SYMDBUG
rest = nsect * sizeof(ind_t) + sizeof(ind_t) + sizeof(ind_t);
#else SYMDBUG
rest = nsect * sizeof(ind_t) + sizeof(ind_t);
#endif SYMDBUG
/*
* We already allocated space for the header, we now need
* the section, name an string table.
*/
size = modulsize(head) - sizeof(struct outhead) - rest;
if (hard_alloc(ALLOMODL, size) == BADOFF)
fatal("no space for module");
read_sect((struct outsect *)modulptr(sectindex), nsect);
return incore && alloc(ALLOMODL, rest) != BADOFF;
}
/*
* Allocate space for the indirectly accessed pieces: the section contents and
* the relocation table, and put their indices in the right place.
*/
static bool
indirect_alloc(head)
struct outhead *head;
{
register int allopiece;
ushort nsect = head->oh_nsect;
ushort nrelo = head->oh_nrelo;
ind_t sectindex = IND_SECT(*head);
ind_t emitoff = IND_EMIT(*head);
ind_t relooff = IND_RELO(*head);
#ifdef SYMDBUG
ind_t dbugoff = IND_DBUG(*head);
extern long objectsize;
long dbugsize = objectsize - OFF_DBUG(*head);
#endif SYMDBUG
assert(incore);
for (allopiece = ALLOEMIT; allopiece < ALLOEMIT + nsect; allopiece++) {
if (!putemitindex(sectindex, emitoff, allopiece))
return FALSE;
sectindex += sizeof(struct outsect);
emitoff += sizeof(ind_t);
}
#ifdef SYMDBUG
return putreloindex(relooff, (long)nrelo * sizeof(struct outrelo))
&&
putdbugindex(dbugoff, dbugsize);
#else SYMDBUG
return putreloindex(relooff, (long)nrelo * sizeof(struct outrelo));
#endif SYMDBUG
}
/*
* Allocate space for the contents of the section of which the table entry is
* at offset `sectindex'. Put the offset of the allocated piece at offset
* `emitoff'.
*/
static bool
putemitindex(sectindex, emitoff, allopiece)
ind_t sectindex;
ind_t emitoff;
int allopiece;
{
long flen;
ind_t emitindex;
extern ind_t alloc();
flen = ((struct outsect *)modulptr(sectindex))->os_flen;
if ((emitindex = alloc(allopiece, flen)) != BADOFF) {
*(ind_t *)modulptr(emitoff) = emitindex;
return TRUE;
}
return FALSE;
}
/*
* Allocate space for a relocation table with `nrelobytes' bytes, and put the
* offset at `relooff'.
*/
static bool
putreloindex(relooff, nrelobytes)
ind_t relooff;
long nrelobytes;
{
ind_t reloindex;
extern ind_t alloc();
if ((reloindex = alloc(ALLORELO, nrelobytes)) != BADOFF) {
*(ind_t *)modulptr(relooff) = reloindex;
return TRUE;
}
return FALSE;
}
#ifdef SYMDBUG
/*
* Allocate space for debugging information and put the offset at `dbugoff'.
*/
static bool
putdbugindex(dbugoff, ndbugbytes)
ind_t relooff;
long ndbugbytes;
{
ind_t dbugindex;
extern ind_t alloc();
if ((dbugindex = alloc(ALLORELO, ndbugbytes)) != BADOFF) {
*(ind_t *)modulptr(dbugoff) = dbugindex;
return TRUE;
}
return FALSE;
}
#endif SYMDBUG
/*
* Compute addresses and read in. Remember that the contents of the sections
* and also the relocation table are accessed indirectly.
*/
static
get_indirect(head, sect)
register struct outhead *head;
register struct outsect *sect;
{
register ind_t *emitindex;
register int nsect;
register int piece;
ind_t *reloindex;
emitindex = (ind_t *)modulptr(IND_EMIT(*head));
nsect = head->oh_nsect; piece = ALLOEMIT;
while (nsect--) {
read_emit(address(piece, *emitindex), sect->os_flen);
piece++; emitindex++; sect++;
}
reloindex = (ind_t *)modulptr(IND_RELO(*head));
read_relo((struct outrelo *)address(ALLORELO, *reloindex),
head->oh_nrelo
);
}
/*
* Set the file pointer at `pos'.
*/
seek(pos)
long pos;
{
if (passnumber == FIRST || !incore)
lseek(infile, pos, 0);
}
/*
* A file pointer is advanced automatically when reading, a char pointer
* is not. That's why we do it here. If we don't keep everything in core,
* we give the space allocated for a module back.
*/
skip_modul(head)
struct outhead *head;
{
register ind_t skip = modulsize(head);
if (incore) {
core_position += skip;
if (passnumber == SECOND)
modulbase += skip;
} else {
dealloc(ALLOMODL);
core_position = (ind_t)0;
}
}
/*
* Read in what we need in pass 2, because we couldn't keep it in core.
*/
static
read_modul()
{
struct outhead *head;
struct outsect *sects;
struct outname *names;
char *chars;
ind_t sectindex, nameindex, charindex;
ushort nsect, nname;
long size;
long nchar;
long skip;
extern ind_t hard_alloc();
assert(passnumber == SECOND);
assert(!incore);
if (hard_alloc(ALLOMODL, (long)sizeof(struct outhead)) == BADOFF)
fatal("no space for module header");
head = (struct outhead *)modulptr(IND_HEAD);
read_head(head);
nsect = head->oh_nsect; sectindex = IND_SECT(*head);
nname = head->oh_nname; nameindex = IND_NAME(*head);
nchar = head->oh_nchar; charindex = IND_CHAR(*head);
skip = OFF_NAME(*head) - OFF_EMIT(*head);
#ifdef SYMDBUG
size = modulsize(head) - (nsect * sizeof(ind_t) + 2 * sizeof(ind_t));
#else SYMDBUG
size = modulsize(head) - (nsect * sizeof(ind_t) + sizeof(ind_t));
#endif SYMDBUG
if (hard_alloc(ALLOMODL, size) == BADOFF)
fatal("no space for module");
sects = (struct outsect *)modulptr(sectindex);
names = (struct outname *)modulptr(nameindex);
chars = modulptr(charindex);
read_sect(sects, nsect);
lseek(infile, skip, 1);
read_name(names, nname);
read_char(chars, nchar);
}
/*
* Align `size' to a multiple of the size of a double.
* This is assumed to be a power of 2.
*/
static long
align(size)
register long size;
{
size += sizeof(double) - 1;
return size - (size & (sizeof(double) - 1));
}
/*
* Compute how many DIRECT bytes must be allocated for a module of which the
* header is pointed to by `head':
* 0. the header,
* 1. the section table,
* 2. the name table,
* 3. the string table,
* 4. for each section the offset of its contents,
* 5. the offset of the relocation table.
#ifdef SYMDBUG
* 6. the offset of the debugging information.
#endif SYMDBUG
*/
static long
modulsize(head)
register struct outhead *head;
{
return sizeof(struct outhead) + /* 0 */
head->oh_nsect * sizeof(struct outsect) + /* 1 */
head->oh_nname * sizeof(struct outname) + /* 2 */
align(head->oh_nchar) + /* 3 */
head->oh_nsect * sizeof(ind_t) + /* 4 */
#ifdef SYMDBUG
sizeof(ind_t) + /* 5 */
sizeof(ind_t); /* 6 */
#else SYMDBUG
sizeof(ind_t); /* 5 */
#endif SYMDBUG
}
/* ------------------------------------------------------------------------- */
/*
* Walk through the relocation table of the current module. We must either walk
* through core or through file. Startrelo() should be called first.
*/
static struct outrelo *walkrelo;
startrelo(head)
struct outhead *head;
{
ind_t reloindex;
if (incore) {
reloindex = *(ind_t *)(modulbase + IND_RELO(*head));
walkrelo = (struct outrelo *)address(ALLORELO, reloindex);
} else
lseek(infile, position + OFF_RELO(*head), 0);
}
struct outrelo *
nextrelo()
{
static struct outrelo relobuf;
if (incore)
return walkrelo++;
read_relo(&relobuf, (ushort)1);
return &relobuf;
}
/* ------------------------------------------------------------------------- */
/*
* Get the section contents in core of which the describing struct has index
* `sectindex'. `Head' points to the header of the module.
*/
char *
getemit(head, sects, sectindex)
struct outhead *head;
struct outsect *sects;
int sectindex;
{
char *ret;
ind_t off;
extern char *core_alloc();
if (!incore) {
ret = core_alloc(ALLOMODL, sects[sectindex].os_flen);
if (ret == (char *)0)
fatal("no space for section contents");
lseek(infile, position + sects[sectindex].os_foff, 0);
read_emit(ret, sects[sectindex].os_flen);
return ret;
}
/*
* We have an offset in the contents of the final output
* "file" where normally the contents would be.
*/
off = *((ind_t *)(modulbase + IND_EMIT(*head)) + sectindex);
return address(ALLOEMIT + sectindex, off);
}

13
util/led/scan.h Normal file
View file

@ -0,0 +1,13 @@
/* $Header$ */
/*
* Offsets of the pieces of the input module in core.
*/
#define IND_HEAD ((ind_t)0)
#define IND_SECT(x) (IND_HEAD + sizeof(struct outhead))
#define IND_NAME(x) (IND_SECT(x) + (x).oh_nsect * sizeof(struct outsect))
#define IND_CHAR(x) (IND_NAME(x) + (x).oh_nname * sizeof(struct outname))
#ifdef SYMDBUG
#define OFF_DBUG(x) (OFF_CHAR(x) + (x).oh_nchar)
#endif SYMDBUG

132
util/led/sym.c Normal file
View file

@ -0,0 +1,132 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
/*
* Symbol table management.
*/
#include "out.h"
#include "const.h"
#include "memory.h"
/*
* Symbol table types. Each hash table entry contains the offset of a symbol
* struct. `Sy_name' contains the offset the name in the piece of global
* names. `Sy_next' contains the offset of the next symbol of which the
* corresponding name has the same hash value.
*/
struct symbol {
ind_t sy_name;
ind_t sy_next;
};
#define NHASH 256 /* Size of hash table. Should be even. */
static ind_t hashtable[NHASH];
/*
* Initialize the symbol table. All indices should be noticeably invalid.
*/
init_symboltable()
{
register ind_t *rap;
for (rap = hashtable; rap < &hashtable[NHASH]; rap++)
*rap = BADOFF;
}
/*
* Search for `string' in the symboltable. The hash value of `string' is in
* `hashval'. The linked list belonging to the entry of hashval
* in the hash table is followed. If the names match, a pointer to the outname
* in this element of the list is returned. When a match cannot be found,
* NIL is returned.
*/
struct outname *
searchname(string, hashval)
char *string;
int hashval;
{
register char *rcp;
register char *namestring;
register ind_t symindex;
register struct outname *name;
register struct symbol *sym;
symindex = hashtable[hashval];
while (symindex != BADOFF) {
sym = (struct symbol *)address(ALLOSYMB, symindex);
name = (struct outname *)address(ALLOGLOB, sym->sy_name);
namestring = address(ALLOGCHR, (ind_t)name->on_foff);
rcp = string;
while (*rcp == *namestring++)
if (*rcp++ == '\0')
return name;
symindex = sym->sy_next;
}
/* Not found. */
return (struct outname *)0;
}
/*
* Enter a new name in the symbol table. We must copy everything to a
* new entry. `Name' is a private copy, i.e. the pointer to it will not be
* destroyed by allocation. However, the string of which name->on_foff is the
* offset can be destroyed, so we save it first.
*/
entername(name, hashval)
struct outname *name;
int hashval;
{
ind_t savindex;
ind_t symindex;
ind_t namindex;
struct symbol *sym;
struct outname *newname;
extern ind_t savechar();
extern ind_t hard_alloc();
savindex = savechar(ALLOGCHR, (ind_t)name->on_foff);
symindex = hard_alloc(ALLOSYMB, (long)sizeof(struct symbol));
namindex = hard_alloc(ALLOGLOB, (long)sizeof(struct outname));
if (savindex == BADOFF || symindex == BADOFF || namindex == BADOFF)
fatal("symbol table overflow");
sym = (struct symbol *)address(ALLOSYMB, symindex);
sym->sy_name = namindex;
newname = (struct outname *)address(ALLOGLOB, namindex);
*newname = *name;
newname->on_foff = savindex;
sym->sy_next = hashtable[hashval];
hashtable[hashval] = symindex;
}
/*
* Return the index of `name' in the symbol table in the order in which
* it was entered. We need a REAL index, not a byte offset.
*/
ushort
indexof(name)
struct outname *name;
{
return name - (struct outname *)address(ALLOGLOB, (ind_t)0);
}
/*
* Assign an integer to the string in p.
* 0 <= hash(p) < NHASH, so it can - and will - be used
* as index in a hash table.
*/
int
hash(p)
register char *p;
{
register unsigned int h = 0;
register int c;
while (c = *p++) {
h <<= 2;
h += c;
}
return h & (NHASH - 1);
}

297
util/led/write.c Normal file
View file

@ -0,0 +1,297 @@
#ifndef lint
static char rcsid[] = "$Header$";
#endif
/*
* You can choose between two strategies:
* - Open the output file several times, once for each logical part, and
* write to it in multiple places.
* - Open the output file once and seek back and forth to each logical
* part. In this case #define OUTSEEK.
*/
#include <stdio.h>
#include "out.h"
#include "const.h"
#include "assert.h"
#include "memory.h"
#include "orig.h"
extern long lseek();
#define WRITE 1 /* Argument to open(). */
/*
* Parts of the output file.
*/
#define PARTEMIT 0
#define PARTRELO 1
#define PARTNAME 2
#define PARTCHAR 3
#ifdef SYMDBUG
#define PARTDBUG 4
#else SYMDBUG
#define PARTDBUG PARTCHAR
#endif SYMDBUG
#define NPARTS (PARTDBUG + 1)
/*
* Call OUTPART() with the part you want to write on as argument, before
* you call OUTWRITE().
*/
static int outpart = NPARTS;
#ifdef OUTSEEK
static int outfile;
static long outseek[NPARTS];
#define OUTPART(p) \
{ if (outpart != (p)) {\
outpart = (p);\
lseek(outfile, outseek[(p)], 0);\
}\
}
#define OUTSECT(i) \
{ outpart = NPARTS;\
outseek[PARTEMIT] =\
outsect[(i)].os_foff + relorig[(i)].org_flen;\
}
#define OUTWRITE(b, n) \
{ if (write(outfile, (b), (n)) != (n))\
fatal("write error");\
outseek[outpart] += (n);\
}
#define BEGINSEEK(p, o) \
{ outseek[(p)] = (o);\
}
#else OUTSEEK
static int outfile[NPARTS];
#define OUTPART(p) \
{ outpart = (p);\
}
#define OUTSECT(i) \
{ lseek( outfile[PARTEMIT],\
outsect[(i)].os_foff + relorig[(i)].org_flen,\
0\
);\
}
#define OUTWRITE(b, n) \
{ if (write(outfile[outpart], (b), (n)) != (n))\
fatal("write error");\
}
#define BEGINSEEK(p, o) \
{ lseek(outfile[(p)], (o), 0);\
}
#endif OUTSEEK
extern struct outhead outhead;
extern struct outsect outsect[];
extern int flagword;
extern struct orig relorig[];
extern bool bytes_reversed, words_reversed;
extern bool incore;
static long offchar;
/*
* Open the output file according to the chosen strategy.
* Write away the header and section table: they will not change anymore.
*/
begin_write()
{
register long off;
openoutput();
BEGINSEEK(PARTEMIT, (long)0);
wrt_head(&outhead);
wrt_sect(outsect, outhead.oh_nsect);
off = SZ_HEAD + (long)outhead.oh_nsect * SZ_SECT + outhead.oh_nemit;
if (flagword & RFLAG) {
/* A relocation table will be produced. */
BEGINSEEK(PARTRELO, off);
off += (long)outhead.oh_nrelo * SZ_RELO;
}
if (flagword & SFLAG)
return;
/* A name table will be produced. */
BEGINSEEK(PARTNAME, off);
off += (long)outhead.oh_nname * SZ_NAME;
BEGINSEEK(PARTCHAR, off);
offchar = off; /* See wrt_name(). */
#ifdef SYMDBUG
off += outhead.oh_nchar;
BEGINSEEK(PARTDBUG, off);
#endif SYMDBUG
}
static
openoutput()
{
#ifndef OUTSEEK
register int *fdp;
#endif OUTSEEK
extern char *outputname;
close(creat(outputname, 0666));
#ifdef OUTSEEK
if ((outfile = open(outputname, WRITE)) < 0)
fatal("can't write %s", outputname);
#else OUTSEEK
for (fdp = &outfile[PARTEMIT]; fdp < &outfile[NPARTS]; fdp++)
if ((*fdp = open(outputname, WRITE)) < 0)
fatal("can't write %s", outputname);
#endif OUTSEEK
}
static struct outname *
sectname(sectindex)
int sectindex;
{
static struct outname namebuf;
namebuf.on_foff = (long)0; /* No string name. */
namebuf.on_type = (S_MIN + sectindex) | S_SCT;
namebuf.on_desc = 0;
namebuf.on_valu = outsect[sectindex].os_base;
return &namebuf;
}
/*
* Write out the symbol table and the section names.
*/
end_write()
{
register ushort cnt;
register struct outname *name;
register int sectindex;
extern ushort NGlobals;
assert(!incore);
assert(!(flagword & SFLAG));
cnt = NGlobals;
name = (struct outname *)address(ALLOGLOB, (ind_t)0);
while (cnt--) {
if (name->on_foff != (long)0) {
name->on_mptr = address(ALLOGCHR, (ind_t)name->on_foff);
} else {
name->on_mptr = (char *)0;
}
wrt_name(name);
name++;
}
for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++)
wrt_name(sectname(sectindex));
}
static
wrt_head(head)
register struct outhead *head;
{
assert(!incore);
OUTPART(PARTEMIT);
if (bytes_reversed || words_reversed)
swap((char *)head, SF_HEAD);
OUTWRITE((char *)head, SZ_HEAD);
/*
* Swap back because we will need it again.
*/
if (bytes_reversed || words_reversed)
swap((char *)head, SF_HEAD);
}
static
wrt_sect(sect, cnt)
register struct outsect *sect;
register ushort cnt;
{
assert(!incore);
OUTPART(PARTEMIT);
while (cnt--) {
if (bytes_reversed || words_reversed)
swap((char *)sect, SF_SECT);
OUTWRITE((char *)sect, SZ_SECT);
/*
* Swap back because we will need it again.
*/
if (bytes_reversed || words_reversed)
swap((char *)sect, SF_SECT);
sect++;
}
}
/*
* We don't have to worry about byte order here.
*/
wrt_emit(emit, sectindex, cnt)
register char *emit;
int sectindex;
register long cnt;
{
register int n;
assert(!incore);
OUTPART(PARTEMIT);
OUTSECT(sectindex);
while (cnt) {
n = cnt >= BUFSIZ ? BUFSIZ : cnt;
OUTWRITE(emit, n);
emit += n;
cnt -= n;
}
}
wrt_relo(relo)
register struct outrelo *relo;
{
assert(!incore);
assert(flagword & RFLAG);
OUTPART(PARTRELO);
if (bytes_reversed || words_reversed)
swap((char *)relo, SF_RELO);
OUTWRITE((char *)relo, SZ_RELO);
}
wrt_name(name)
register struct outname *name;
{
assert(!incore);
assert(!(flagword & SFLAG));
if (name->on_mptr != (char *)0) {
register int len = strlen(name->on_mptr) + 1;
OUTPART(PARTCHAR);
OUTWRITE(name->on_mptr, len);
name->on_foff = offchar;
offchar += len;
} else {
name->on_foff = (long)0;
}
OUTPART(PARTNAME);
if (bytes_reversed || words_reversed)
swap((char *)name, SF_NAME);
OUTWRITE((char *)name, SZ_NAME);
}
#ifdef SYMDBUG
wrt_dbug(buf, size)
char *buf;
int size;
{
assert(!incore);
assert(!(flagword & SFLAG));
OUTPART(PARTDBUG);
OUTWRITE((char *)buf, size);
}
#endif SYMDBUG