📄 ld.c
字号:
/* * link editor */#include <signal.h>#include "sys/types.h"#include "sys/stat.h"/* Layout of a.out file : * * header of 8 words magic number 405, 407, 410, 411 * text size ) * data size ) in bytes but even * bss size ) * symbol table size * entry point * {unused} * flag set if no relocation * * * header: 0 * text: 16 * data: 16+textsize * relocation: 16+textsize+datasize * symbol table: 16+2*(textsize+datasize) or 16+textsize+datasize * */#define TRUE 1#define FALSE 0#define ARCMAGIC 0177545#define OMAGIC 0405#define FMAGIC 0407#define NMAGIC 0410#define IMAGIC 0411#define EXTERN 040#define UNDEF 00#define ABS 01#define TEXT 02#define DATA 03#define BSS 04#define COMM 05 /* internal use only */#define RABS 00#define RTEXT 02#define RDATA 04#define RBSS 06#define REXT 010#define NOVLY 16#define RELFLG 01#define NROUT 256#define NSYM 1103#define NSYMPR 1000char premeof[] = "Premature EOF";char goodnm[] = "__.SYMDEF";/* table of contents stuff */#define TABSZ 700struct tab{ char cname[8]; long cloc;} tab[TABSZ];int tnum;/* overlay management */int vindex;struct overlay { int argsav; int symsav; struct liblist *libsav; char *vname; int ctsav, cdsav, cbsav; int offt, offd, offb, offs;} vnodes[NOVLY];/* input management */struct page { int nuser; int bno; int nibuf; int buff[256];} page[2];struct { int nuser; int bno;} fpage;struct stream { int *ptr; int bno; int nibuf; int size; struct page *pno;};struct stream text;struct stream reloc;struct { char aname[14]; long atime; char auid, agid; int amode; long asize;} archdr;struct { int fmagic; int tsize; int dsize; int bsize; int ssize; int entry; int pad; int relflg;} filhdr;/* one entry for each archive member referenced; * set in first pass; needs restoring for overlays */struct liblist { long loc;};struct liblist liblist[NROUT];struct liblist *libp = liblist;/* symbol management */struct symbol { char sname[8]; char stype; char spare; int svalue;};struct local { int locindex; /* index to symbol in file */ struct symbol *locsymbol; /* ptr to symbol table */};struct symbol cursym; /* current symbol */struct symbol symtab[NSYM]; /* actual symbols */struct symbol **symhash[NSYM]; /* ptr to hash table entry */struct symbol *lastsym; /* last symbol entered */int symindex; /* next available symbol table entry */struct symbol *hshtab[NSYM+2]; /* hash table for symbols */struct local local[NSYMPR];/* internal symbols */struct symbol *p_etext;struct symbol *p_edata;struct symbol *p_end;struct symbol *entrypt;int trace;/* flags */int xflag; /* discard local symbols */int Xflag; /* discard locals starting with 'L' */int Sflag; /* discard all except locals and globals*/int rflag; /* preserve relocation bits, don't define common */int arflag; /* original copy of rflag */int sflag; /* discard all symbols */int nflag; /* pure procedure */int Oflag; /* set magic # to 0405 (overlay) */int dflag; /* define common even with rflag */int iflag; /* I/D space separated */int vflag; /* overlays used */int ofilfnd;char *ofilename = "l.out";int infil;char *filname;/* cumulative sizes set in pass 1 */int tsize;int dsize;int bsize;int ssize;/* symbol relocation; both passes */int ctrel;int cdrel;int cbrel;int errlev;int delarg = 4;char tfname[] = "/tmp/ldaXXXXX";/* output management */struct buf { int fildes; int nleft; int *xnext; int iobuf[256];};struct buf toutb;struct buf doutb;struct buf troutb;struct buf droutb;struct buf soutb;struct symbol **lookup();struct symbol **slookup();struct symbol *lookloc();delexit(){ unlink("l.out"); if (delarg==0) chmod(ofilename, 0777 & ~umask(0)); exit(delarg);}main(argc, argv)char **argv;{ register int c, i; int num; register char *ap, **p; int found; int vscan; char save; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, delexit); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, delexit); if (argc == 1) exit(4); p = argv+1; /* scan files once to find symdefs */ for (c=1; c<argc; c++) { if (trace) printf("%s:\n", *p); filname = 0; ap = *p++; if (*ap == '-') { for (i=1; ap[i]; i++) { switch (ap[i]) { case 'o': if (++c >= argc) error(2, "Bad output file"); ofilename = *p++; ofilfnd++; continue; case 'u': case 'e': if (++c >= argc) error(2, "Bad 'use' or 'entry'"); enter(slookup(*p++)); if (ap[i]=='e') entrypt = lastsym; continue; case 'v': if (++c >= argc) error(2, "-v: arg missing"); vflag=TRUE; vscan = vindex; found=FALSE; while (--vscan>=0 && found==FALSE) found = eq(vnodes[vscan].vname, *p); if (found) { endload(c, argv); restore(vscan); } else record(c, *p); p++; continue; case 'D': if (++c >= argc) error(2, "-D: arg missing"); num = atoi(*p++); if (dsize>num) error(2, "-D: too small"); dsize = num; continue; case 'l': save = ap[--i]; ap[i]='-'; load1arg(&ap[i]); ap[i]=save; break; case 'x': xflag++; continue; case 'X': Xflag++; continue; case 'S': Sflag++; continue; case 'r': rflag++; arflag++; continue; case 's': sflag++; xflag++; continue; case 'n': nflag++; continue; case 'd': dflag++; continue; case 'i': iflag++; continue; case 'O': Oflag++; continue; case 't': trace++; continue; default: error(2, "bad flag"); } /*endsw*/ break; } /*endfor*/ } else load1arg(ap); } endload(argc, argv);}/* used after pass 1 */int nsym;int torigin;int dorigin;int borigin;endload(argc, argv)int argc; char **argv;{ register int c, i; int dnum; register char *ap, **p; filname = 0; middle(); setupout(); p = argv+1; libp = liblist; for (c=1; c<argc; c++) { ap = *p++; if (trace) printf("%s:\n", ap); if (*ap == '-') { for (i=1; ap[i]; i++) { switch (ap[i]) { case 'D': for (dnum = atoi(*p); dorigin<dnum; dorigin += 2) { putw(0, &doutb); if (rflag) putw(0, &droutb); } case 'u': case 'e': case 'o': case 'v': ++c; ++p; default: continue; case 'l': ap[--i]='-'; load2arg(&ap[i]); break; } /*endsw*/ break; } /*endfor*/ } else load2arg(ap); } finishout();}record(c, nam)int c; char *nam;{ register struct overlay *v; v = &vnodes[vindex++]; v->argsav = c; v->symsav = symindex; v->libsav = libp; v->vname = nam; v->offt = tsize; v->offd = dsize; v->offb = bsize; v->offs = ssize; v->ctsav = ctrel; v->cdsav = cdrel; v->cbsav = cbrel;}restore(vscan)int vscan;{ register struct overlay *v; register int saved; v = &vnodes[vscan]; vindex = vscan+1; libp = v->libsav; ctrel = v->ctsav; cdrel = v->cdsav; cbrel = v->cbsav; tsize = v->offt; dsize = v->offd; bsize = v->offb; ssize = v->offs; saved = v->symsav; while (symindex>saved) *symhash[--symindex]=0;}/* scan file to find defined symbols */load1arg(acp)char *acp;{ register char *cp; long nloc; cp = acp; switch ( getfile(cp)) { case 0: load1(0, 0L); break; /* regular archive */ case 1: nloc = 1; while ( step(nloc)) nloc += (archdr.asize + sizeof(archdr) + 1) >> 1; break; /* table of contents */ case 2: tnum = archdr.asize / sizeof(struct tab); if (tnum >= TABSZ) { error(2, "fast load buffer too small"); } lseek(infil, (long)(sizeof(filhdr.fmagic)+sizeof(archdr)), 0); read(infil, (char *)tab, tnum * sizeof(struct tab)); while (ldrand()); libp->loc = -1; libp++; break; /* out of date table of contents */ case 3: error(0, "out of date (warning)"); for(nloc = 1+((archdr.asize+sizeof(archdr)+1) >> 1); step(nloc); nloc += (archdr.asize + sizeof(archdr) + 1) >> 1); break; } close(infil);}step(nloc)long nloc;{ dseek(&text, nloc, sizeof archdr); if (text.size <= 0) { libp->loc = -1; libp++; return(0); } mget((int *)&archdr, sizeof archdr); if (load1(1, nloc + (sizeof archdr) / 2)) { libp->loc = nloc; libp++; } return(1);}ldrand(){ int i; struct symbol *sp, **pp; struct liblist *oldp = libp; for(i = 0; i<tnum; i++) { if ((pp = slookup(tab[i].cname)) == 0) continue; sp = *pp; if (sp->stype != EXTERN+UNDEF) continue; step(tab[i].cloc >> 1); } return(oldp != libp);}add(a,b,s)int a, b;char *s;{ long r; r = (long)(unsigned)a + (unsigned)b; if (r >= 0200000) error(1,s); return(r);}/* single file or archive member */load1(libflg, loc)long loc;{ register struct symbol *sp; int savindex; int ndef, nloc, type, mtype; readhdr(loc); ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; nloc = sizeof cursym; savindex = symindex; if ((filhdr.relflg&RELFLG)==1) { error(1, "No relocation bits"); return(0); } loc += (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize; dseek(&text, loc, filhdr.ssize); while (text.size > 0) { mget((int *)&cursym, sizeof cursym); type = cursym.stype; if (Sflag) { mtype = type&037; if (mtype==1 || mtype>4) { continue; } } if ((type&EXTERN)==0) { if (Xflag==0 || cursym.sname[0]!='L') nloc += sizeof cursym; continue; } symreloc(); if (enter(lookup())) continue; if ((sp = lastsym)->stype != EXTERN+UNDEF) continue; if (cursym.stype == EXTERN+UNDEF) { if (cursym.svalue > sp->svalue) sp->svalue = cursym.svalue; continue; } if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) continue; ndef++; sp->stype = cursym.stype; sp->svalue = cursym.svalue; } if (libflg==0 || ndef) { tsize = add(tsize,filhdr.tsize,"text overflow"); dsize = add(dsize,filhdr.dsize,"data overflow"); bsize = add(bsize,filhdr.bsize,"bss overflow"); ssize = add(ssize,nloc,"symbol table overflow"); return(1); } /* * No symbols defined by this library member. * Rip out the hash table entries and reset the symbol table. */ while (symindex>savindex) *symhash[--symindex]=0; return(0);}middle(){ register struct symbol *sp, *symp; register t, csize; int nund, corigin; torigin=0; dorigin=0; borigin=0; p_etext = *slookup("_etext"); p_edata = *slookup("_edata"); p_end = *slookup("_end"); /* * If there are any undefined symbols, save the relocation bits. */ symp = &symtab[symindex]; if (rflag==0) { for (sp = symtab; sp<symp; sp++) if (sp->stype==EXTERN+UNDEF && sp->svalue==0 && sp!=p_end && sp!=p_edata && sp!=p_etext) { rflag++; dflag = 0; break; } } if (rflag) nflag = sflag = iflag = Oflag = 0; /* * Assign common locations. */ csize = 0; if (dflag || rflag==0) { ldrsym(p_etext, tsize, EXTERN+TEXT); ldrsym(p_edata, dsize, EXTERN+DATA); ldrsym(p_end, bsize, EXTERN+BSS); for (sp = symtab; sp<symp; sp++) if (sp->stype==EXTERN+UNDEF && (t = sp->svalue)!=0) { t = (t+1) & ~01; sp->svalue = csize; sp->stype = EXTERN+COMM; csize = add(csize, t, "bss overflow"); } } /* * Now set symbols to their final value */ if (nflag || iflag) tsize = (tsize + 077) & ~077; dorigin = tsize; if (nflag)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -