diff options
Diffstat (limited to 'bin86-0.3/ld/readobj.c')
-rw-r--r-- | bin86-0.3/ld/readobj.c | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/bin86-0.3/ld/readobj.c b/bin86-0.3/ld/readobj.c deleted file mode 100644 index 5c4dd72..0000000 --- a/bin86-0.3/ld/readobj.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * bin86/ld/readobj.c - * - * Copyright (C) 1992 Bruce Evans - */ - -/* readobj.c - read object file for linker */ - -#include "ar.h" /* maybe local copy of <ar.h> for cross-link */ -#include "const.h" -#include "byteord.h" -#include "obj.h" -#include "type.h" -#include "globvar.h" - -/* - Linking takes 2 passes. The 1st pass reads through all files specified -in the command line, and all libraries. All public symbols are extracted -and stored in a chained hash table. For each module, its file and header -data recorded, and the resulting structures are chained together -(interleaved with the symbols). - - The symbol descriptors are separated from the symbol names, so we must -record all the descriptors of a module before putting the symbols in the -symbol table (poor design). The descriptors are stored in the symbol -table, then moved to the top of the table to make room for the symols. -The symbols referred to in a given module are linked together by a chain -beginning in the module descriptor. -*/ - -PRIVATE char convertsize[NSEG / 4] = {0, 1, 2, 4}; -PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */ -PRIVATE struct redlist *redlast; /* last on list of redefined symbols */ -PRIVATE struct modstruct *modlast; /* data for last module */ - -FORWARD long readarheader P((char **parchentry)); -FORWARD unsigned readfileheader P((void)); -FORWARD void readmodule P((char *filename, char *archentry)); -FORWARD void reedmodheader P((void)); -FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value)); -FORWARD unsigned checksum P((char *string, unsigned length)); -FORWARD unsigned segbits P((unsigned seg, char *sizedesc)); - -/* initialise object file handler */ - -PUBLIC void objinit() -{ - modfirst = modlast = NULL; - entryfirst = entrylast = NULL; - redfirst = redlast = NULL; -} - -/* read all symbol definitions in an object file */ - -PUBLIC void readsyms(filename, trace) -char *filename; -bool_pt trace; -{ - char *archentry; - long filelength; - char filemagic[SARMAG]; - long filepos; - unsigned modcount; - - if (trace) - errtrace(filename, 0); - openin(filename); /* input is not open, so position is start */ - switch ((unsigned) readsize(2)) - { - case OMAGIC: - seekin(0L); - for (modcount = readfileheader(); modcount-- != 0;) - readmodule(filename, (char *) NULL); - break; - default: - seekin(0L); - readin(filemagic, sizeof filemagic); - if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0) - input1error(" has bad magic number"); - filepos = SARMAG; - while ((filelength = readarheader(&archentry)) > 0) - { - if (trace) - errtrace(archentry, 2); - filepos += sizeof(struct ar_hdr); - for (modcount = readfileheader(); modcount-- != 0;) - { - readmodule(stralloc(filename), archentry); - modlast->textoffset += filepos; - } - seekin(filepos += ld_roundup(filelength, 2, long)); - } - break; - } - closein(); -} - -/* read archive header and return length */ - -PRIVATE long readarheader(parchentry) -char **parchentry; -{ - struct ar_hdr arheader; - char *endptr; - char *nameptr; - - if (readineofok((char *) &arheader, sizeof arheader)) - return 0; - strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1), - arheader.ar_name, sizeof arheader.ar_name); - endptr = nameptr + sizeof arheader.ar_name; - do - *endptr = 0; - while (endptr > nameptr && *--endptr == ' '); - return strtoul(arheader.ar_size, (char **) NULL, 0); -} - -/* read and check file header of the object file just opened */ - -PRIVATE unsigned readfileheader() -{ - struct - { - char magic[2]; - char count[2]; /* really an int */ - } - fileheader; - char filechecksum; /* part of fileheader but would unalign */ - - readin((char *) &fileheader, sizeof fileheader); - readin(&filechecksum, sizeof filechecksum); - if (filechecksum != checksum((char *) &fileheader, sizeof fileheader)) - input1error(" is not an object file"); - return c2u2(fileheader.count); -} - -/* read the next module */ - -PRIVATE void readmodule(filename, archentry) -char *filename; -char *archentry; -{ - struct symdstruct /* to save parts of symbol before name known */ - { - offset_t dvalue; - flags_t dflags; - }; - struct symdstruct *endsymdptr; - flags_t flags; - unsigned nsymbol; - struct symdstruct *symdptr; - char *symname; - struct symstruct **symparray; - struct symstruct *symptr; - - reedmodheader(); - modlast->filename = filename; - modlast->archentry = archentry; - nsymbol = readsize(2); - symdptr = (struct symdstruct *) - ourmalloc(nsymbol * sizeof(struct symdstruct)); - for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr) - { - readsize(2); /* discard string offset, assume strings seq */ - symdptr->dflags = flags = readsize(2); - symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT); - /* NB unsigned flags to give logical shift */ - /* bug in Xenix 2.5 cc causes (int) of the */ - /* argument to turn flags into an int */ - } - symdptr = (struct symdstruct *) - moveup(nsymbol * sizeof(struct symdstruct)); - modlast->symparray = symparray = (struct symstruct **) - ourmalloc((nsymbol + 1) * sizeof(struct symstruct *)); - symname = readstring(); /* module name */ - modlast->modname = stralloc(symname); /* likely OK overlapped copy */ - for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; - *symparray++ = symptr, release((char *) ++symdptr)) - { - symname = readstring(); - if ((flags = symdptr->dflags) & (E_MASK | I_MASK) && - (symptr = findsym(symname)) != NULL) - { - /* - weaken segment-checking by letting the maximum segment - (SEGM_MASK) mean any segment - */ - if ((symptr->flags & SEGM_MASK) == SEGM_MASK) - symptr->flags &= ~SEGM_MASK | (flags & SEGM_MASK); - else if ((flags & SEGM_MASK) == SEGM_MASK) - flags &= ~SEGM_MASK | (symptr->flags & SEGM_MASK); - if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK)) - { - redefined(symname, " with different segment or relocatability", - archentry, symptr->modptr->filename, - symptr->modptr->archentry); - continue; - } - if (symptr->flags & E_MASK) - { - if (flags & E_MASK && redsym(symptr, symdptr->dvalue)) - redefined(symname, "", archentry, symptr->modptr->filename, - symptr->modptr->archentry); - continue; - } - if (flags & I_MASK && symdptr->dvalue <= symptr->value) - continue; - } - else - symptr = addsym(symname); - symptr->modptr = modlast; - symptr->value = symdptr->dvalue; - symptr->flags = flags; - if (flags & N_MASK) - entrysym(symptr); - } - *symparray = NULL; -} - -/* put symbol on entry symbol list if it is not already */ - -PUBLIC void entrysym(symptr) -struct symstruct *symptr; -{ - register struct entrylist *elptr; - - for (elptr = entryfirst; elptr != NULL; elptr = elptr->elnext) - if (symptr == elptr->elsymptr) - return; - elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist)); - elptr->elnext = NULL; - elptr->elsymptr = symptr; - if (entryfirst == NULL) - entryfirst = elptr; - else - entrylast->elnext = elptr; - entrylast = elptr; -} - -/* read the header of the next module */ - -PRIVATE void reedmodheader() -{ - struct - { - char htextoffset[4]; /* offset to module text in file */ - char htextsize[4]; /* size of text (may be 0 for last mod) */ - char stringssize[2]; /* size of string area */ - char hclass; /* module class */ - char revision; /* module revision */ - } - modheader; - unsigned seg; - unsigned count; - char *cptr; - struct modstruct *modptr; - - readin((char *) &modheader, sizeof modheader); - modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct)); - modptr->modnext = NULL; - modptr->textoffset = c4u4(modheader.htextoffset); - modptr->class = modheader.hclass; - readin(modptr->segmaxsize, sizeof modptr->segmaxsize); - readin(modptr->segsizedesc, sizeof modptr->segsizedesc); - cptr = modptr->segsize; - for (seg = 0; seg < NSEG; ++seg) - { - if ((count = segsizecount(seg, modptr)) != 0) - { - if (cptr == modptr->segsize) - ourmalloc(count - 1); /* 1st byte reserved in struct */ - else - ourmalloc(count); - readin(cptr, count); - cptr += count; - } - } - if (modfirst == NULL) - modfirst = modptr; - else - modlast->modnext = modptr; - modlast = modptr; -} - -PRIVATE bool_pt redsym(symptr, value) -register struct symstruct *symptr; -offset_t value; -{ - register struct redlist *rlptr; - char class; - - if (symptr->modptr->class != (class = modlast->class)) - for (rlptr = redfirst;; rlptr = rlptr->rlnext) - { - if (rlptr == NULL) - { - rlptr = (struct redlist *) - ourmalloc(sizeof(struct redlist)); - rlptr->rlnext = NULL; - rlptr->rlsymptr = symptr; - if (symptr->modptr->class < class) - /* prefer lower class - put other on redlist */ - { - rlptr->rlmodptr = modlast; - rlptr->rlvalue = value; - } - else - { - rlptr->rlmodptr = symptr->modptr; - symptr->modptr = modlast; - rlptr->rlvalue = symptr->value; - symptr->value = value; - } - if (redfirst == NULL) - redfirst = rlptr; - else - redlast->rlnext = rlptr; - redlast = rlptr; - return FALSE; - } - if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class) - break; - } - return TRUE; -} - -PRIVATE unsigned checksum(string, length) -char *string; -unsigned length; -{ - unsigned char sum; /* this is a 1-byte checksum */ - - for (sum = 0; length-- != 0;) - sum += *string++ & 0xFF; - return sum; -} - -PUBLIC offset_t readconvsize(countindex) -unsigned countindex; -{ - return readsize(convertsize[countindex]); -} - -PUBLIC offset_t readsize(count) -unsigned count; -{ - char buf[MAX_OFFSET_SIZE]; - - if (count == 0) - return 0; - readin(buf, count); - return cntooffset(buf, count); -} - -PRIVATE unsigned segbits(seg, sizedesc) -unsigned seg; -char *sizedesc; -{ - return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4))); - /* unsigned to give logical shift */ -} - -PUBLIC unsigned segsizecount(seg, modptr) -unsigned seg; -struct modstruct *modptr; -{ - return convertsize[segbits(seg, modptr->segsizedesc)]; -} |