📄 ld.c
字号:
dorigin = (tsize+017777) & ~017777; if (iflag) dorigin = 0; corigin = dorigin + dsize; borigin = corigin + csize; nund = 0; for (sp = symtab; sp<symp; sp++) switch (sp->stype) { case EXTERN+UNDEF: errlev |= 01; if (arflag==0 && sp->svalue==0) { if (nund==0) printf("Undefined:\n"); nund++; printf("%.8s\n", sp->sname); } continue; case EXTERN+ABS: default: continue; case EXTERN+TEXT: sp->svalue += torigin; continue; case EXTERN+DATA: sp->svalue += dorigin; continue; case EXTERN+BSS: sp->svalue += borigin; continue; case EXTERN+COMM: sp->stype = EXTERN+BSS; sp->svalue += corigin; continue; } if (sflag || xflag) ssize = 0; bsize = add(bsize, csize, "bss overflow"); nsym = ssize / (sizeof cursym);}ldrsym(asp, val, type)struct symbol *asp;{ register struct symbol *sp; if ((sp = asp) == 0) return; if (sp->stype != EXTERN+UNDEF || sp->svalue) { printf("%.8s: ", sp->sname); error(1, "Multiply defined"); return; } sp->stype = type; sp->svalue = val;}setupout(){ tcreat(&toutb, 0); mktemp(tfname); tcreat(&doutb, 1); if (sflag==0 || xflag==0) tcreat(&soutb, 1); if (rflag) { tcreat(&troutb, 1); tcreat(&droutb, 1); } filhdr.fmagic = (Oflag ? OMAGIC :( iflag ? IMAGIC : ( nflag ? NMAGIC : FMAGIC ))); filhdr.tsize = tsize; filhdr.dsize = dsize; filhdr.bsize = bsize; filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*symindex); if (entrypt) { if (entrypt->stype!=EXTERN+TEXT) error(1, "Entry point not in text"); else filhdr.entry = entrypt->svalue | 01; } else filhdr.entry=0; filhdr.pad = 0; filhdr.relflg = (rflag==0); mput(&toutb, (int *)&filhdr, sizeof filhdr);}tcreat(buf, tempflg)struct buf *buf;{ register int ufd; char *nam; nam = (tempflg ? tfname : ofilename); if ((ufd = creat(nam, 0666)) < 0) error(2, tempflg?"cannot create temp":"cannot create output"); close(ufd); buf->fildes = open(nam, 2); if (tempflg) unlink(tfname); buf->nleft = sizeof(buf->iobuf)/sizeof(int); buf->xnext = buf->iobuf;}load2arg(acp)char *acp;{ register char *cp; register struct liblist *lp; cp = acp; if (getfile(cp) == 0) { while (*cp) cp++; while (cp >= acp && *--cp != '/'); mkfsym(++cp); load2(0L); } else { /* scan archive members referenced */ for (lp = libp; lp->loc != -1; lp++) { dseek(&text, lp->loc, sizeof archdr); mget((int *)&archdr, sizeof archdr); mkfsym(archdr.aname); load2(lp->loc + (sizeof archdr) / 2); } libp = ++lp; } close(infil);}load2(loc)long loc;{ register struct symbol *sp; register struct local *lp; register int symno; int type, mtype; readhdr(loc); ctrel = torigin; cdrel += dorigin; cbrel += borigin; /* * Reread the symbol table, recording the numbering * of symbols for fixing external references. */ lp = local; symno = -1; loc += (sizeof filhdr)/2; dseek(&text, loc + filhdr.tsize + filhdr.dsize, filhdr.ssize); while (text.size > 0) { symno++; mget((int *)&cursym, sizeof cursym); symreloc(); type = cursym.stype; if (Sflag) { mtype = type&037; if (mtype==1 || mtype>4) continue; } if ((type&EXTERN) == 0) { if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L')) mput(&soutb, (int *)&cursym, sizeof cursym); continue; } if ((sp = *lookup()) == 0) error(2, "internal error: symbol not found"); if (cursym.stype == EXTERN+UNDEF) { if (lp >= &local[NSYMPR]) error(2, "Local symbol overflow"); lp->locindex = symno; lp++->locsymbol = sp; continue; } if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { printf("%.8s: ", cursym.sname); error(1, "Multiply defined"); } } dseek(&text, loc, filhdr.tsize); dseek(&reloc, loc + half(filhdr.tsize + filhdr.dsize), filhdr.tsize); load2td(lp, ctrel, &toutb, &troutb); dseek(&text, loc+half(filhdr.tsize), filhdr.dsize); dseek(&reloc, loc+filhdr.tsize+half(filhdr.dsize), filhdr.dsize); load2td(lp, cdrel, &doutb, &droutb); torigin += filhdr.tsize; dorigin += filhdr.dsize; borigin += filhdr.bsize;}load2td(lp, creloc, b1, b2)struct local *lp;struct buf *b1, *b2;{ register r, t; register struct symbol *sp; for (;;) { /* * The pickup code is copied from "get" for speed. */ /* next text or data word */ if (--text.size <= 0) { if (text.size < 0) break; text.size++; t = get(&text); } else if (--text.nibuf < 0) { text.nibuf++; text.size++; t = get(&text); } else t = *text.ptr++; /* next relocation word */ if (--reloc.size <= 0) { if (reloc.size < 0) error(2, "Relocation error"); reloc.size++; r = get(&reloc); } else if (--reloc.nibuf < 0) { reloc.nibuf++; reloc.size++; r = get(&reloc); } else r = *reloc.ptr++; switch (r&016) { case RTEXT: t += ctrel; break; case RDATA: t += cdrel; break; case RBSS: t += cbrel; break; case REXT: sp = lookloc(lp, r); if (sp->stype==EXTERN+UNDEF) { r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT; break; } t += sp->svalue; r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1); break; } if (r&01) t -= creloc; putw(t, b1); if (rflag) putw(r, b2); }}finishout(){ register n, *p; if (nflag||iflag) { n = torigin; while (n&077) { n += 2; putw(0, &toutb); if (rflag) putw(0, &troutb); } } copy(&doutb); if (rflag) { copy(&troutb); copy(&droutb); } if (sflag==0) { if (xflag==0) copy(&soutb); for (p = (int *)symtab; p < (int *)&symtab[symindex];) putw(*p++, &toutb); } flush(&toutb); close(toutb.fildes); if (!ofilfnd) { unlink("a.out"); link("l.out", "a.out"); ofilename = "a.out"; } delarg = errlev; delexit();}copy(buf)struct buf *buf;{ register f, *p, n; flush(buf); lseek(f = buf->fildes, (long)0, 0); while ((n = read(f, (char *)doutb.iobuf, sizeof(doutb.iobuf))) > 1) { n >>= 1; p = (int *)doutb.iobuf; do putw(*p++, &toutb); while (--n); } close(f);}mkfsym(s)char *s;{ if (sflag || xflag) return; cp8c(s, cursym.sname); cursym.stype = 037; cursym.svalue = torigin; mput(&soutb, (int *)&cursym, sizeof cursym);}mget(aloc, an)int *aloc;{ register *loc, n; register *p; n = an; n >>= 1; loc = aloc; if ((text.nibuf -= n) >= 0) { if ((text.size -= n) > 0) { p = text.ptr; do *loc++ = *p++; while (--n); text.ptr = p; return; } else text.size += n; } text.nibuf += n; do { *loc++ = get(&text); } while (--n);}mput(buf, aloc, an)struct buf *buf; int *aloc;{ register *loc; register n; loc = aloc; n = an>>1; do { putw(*loc++, buf); } while (--n);}dseek(asp, aloc, s)long aloc;struct stream *asp;{ register struct stream *sp; register struct page *p; /* register */ long b, o; int n; b = aloc >> 8; o = aloc & 0377; sp = asp; --sp->pno->nuser; if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) if (p->nuser==0 || (p = &page[0])->nuser==0) { if (page[0].nuser==0 && page[1].nuser==0) if (page[0].bno < page[1].bno) p = &page[0]; p->bno = b; lseek(infil, (aloc & ~0377L) << 1, 0); if ((n = read(infil, (char *)p->buff, 512)>>1) < 0) n = 0; p->nibuf = n; } else error(2, "No pages"); ++p->nuser; sp->bno = b; sp->pno = p; sp->ptr = p->buff + o; if (s != -1) sp->size = half(s); if ((sp->nibuf = p->nibuf-o) <= 0) sp->size = 0;}half(i){ return((i>>1)&077777);}get(asp)struct stream *asp;{ register struct stream *sp; sp = asp; if (--sp->nibuf < 0) { dseek(sp, (long)(sp->bno + 1) << 8, -1); --sp->nibuf; } if (--sp->size <= 0) { if (sp->size < 0) error(2, premeof); ++fpage.nuser; --sp->pno->nuser; sp->pno = (struct page *)&fpage; } return(*sp->ptr++);}getfile(acp)char *acp;{ register char *cp; register int c; struct stat x; cp = acp; infil = -1; archdr.aname[0] = '\0'; filname = cp; if (cp[0]=='-' && cp[1]=='l') { if(cp[2] == '\0') cp = "-la"; filname = "/usr/lib/libxxxxxxxxxxxxxxx"; for(c=0; cp[c+2]; c++) filname[c+12] = cp[c+2]; filname[c+12] = '.'; filname[c+13] = 'a'; filname[c+14] = '\0'; if ((infil = open(filname+4, 0)) >= 0) { filname += 4; } } if (infil == -1 && (infil = open(filname, 0)) < 0) error(2, "cannot open"); page[0].bno = page[1].bno = -1; page[0].nuser = page[1].nuser = 0; text.pno = reloc.pno = (struct page *)&fpage; fpage.nuser = 2; dseek(&text, 0L, 2); if (text.size <= 0) error(2, premeof); if(get(&text) != ARCMAGIC) return(0); /* regualr file */ dseek(&text, 1L, sizeof archdr); /* word addressing */ if(text.size <= 0) return(1); /* regular archive */ mget((int *)&archdr, sizeof archdr); if(strncmp(archdr.aname, goodnm, 14) != 0) return(1); /* regular archive */ else { fstat(infil, &x); if(x.st_mtime > archdr.atime) { return(3); } else return(2); }}struct symbol **lookup(){ int i; int clash; register struct symbol **hp; register char *cp, *cp1; i = 0; for (cp = cursym.sname; cp < &cursym.sname[8];) i = (i<<1) + *cp++; for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { cp1 = (*hp)->sname; clash=FALSE; for (cp = cursym.sname; cp < &cursym.sname[8];) if (*cp++ != *cp1++) { clash=TRUE; break; } if (clash) { if (++hp >= &hshtab[NSYM+2]) hp = hshtab; } else break; } return(hp);}struct symbol **slookup(s)char *s;{ cp8c(s, cursym.sname); cursym.stype = EXTERN+UNDEF; cursym.svalue = 0; return(lookup());}enter(hp)struct symbol **hp;{ register struct symbol *sp; if (*hp==0) { if (symindex>=NSYM) error(2, "Symbol table overflow"); symhash[symindex] = hp; *hp = lastsym = sp = &symtab[symindex++]; cp8c(cursym.sname, sp->sname); sp->stype = cursym.stype; sp->svalue = cursym.svalue; return(1); } else { lastsym = *hp; return(0); }}symreloc(){ switch (cursym.stype) { case TEXT: case EXTERN+TEXT: cursym.svalue += ctrel; return; case DATA: case EXTERN+DATA: cursym.svalue += cdrel; return; case BSS: case EXTERN+BSS: cursym.svalue += cbrel; return; case EXTERN+UNDEF: return; } if (cursym.stype&EXTERN) cursym.stype = EXTERN+ABS;}error(n, s)char *s;{ if (errlev==0) printf("ld:"); if (filname) { printf("%s", filname); if (archdr.aname[0]) printf("(%.14s)", archdr.aname); printf(": "); } printf("%s\n", s); if (n > 1) delexit(); errlev = n;}struct symbol *lookloc(alp, r)struct local *alp;{ register struct local *clp, *lp; register sn; lp = alp; sn = (r>>4) & 07777; for (clp = local; clp<lp; clp++) if (clp->locindex == sn) return(clp->locsymbol); error(2, "Local symbol botch");}readhdr(loc)long loc;{ register st, sd; dseek(&text, loc, sizeof filhdr); mget((int *)&filhdr, sizeof filhdr); if (filhdr.fmagic != FMAGIC) error(2, "Bad format"); st = (filhdr.tsize+01) & ~01; filhdr.tsize = st; cdrel = -st; sd = (filhdr.dsize+01) & ~01; cbrel = - (st+sd); filhdr.bsize = (filhdr.bsize+01) & ~01;}cp8c(from, to)char *from, *to;{ register char *f, *t, *te; f = from; t = to; te = t+8; while ((*t++ = *f++) && t<te); while (t<te) *t++ = 0;}eq(s1, s2)char *s1; char *s2;{ while (*s1==*s2++) if ((*s1++)==0) return(TRUE); return(FALSE);}putw(w, b)register struct buf *b;{ *(b->xnext)++ = w; if (--b->nleft <= 0) flush(b);}flush(b)register struct buf *b;{ register n; if ((n = (char *)b->xnext - (char *)b->iobuf) > 0) if (write(b->fildes, (char *)b->iobuf, n) != n) error(2, "output error"); b->xnext = b->iobuf; b->nleft = sizeof(b->iobuf)/sizeof(int);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -