Maybe some minor changes.
This commit is contained in:
524
util/led/scan.c
Normal file
524
util/led/scan.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user