📄 ld.c
字号:
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++; Nflag = zflag = 0; continue; case 'N': Nflag++; nflag = zflag = 0; continue; case 'd': dflag++; continue; case 'i': printf("ld: -i ignored\n"); continue; case 't': trace++; continue; case 'y': if (ap[i+1] == 0) error(1, "-y: symbol name missing"); if (yflag == 0) { ytab = (char **)calloc(argc, sizeof (char **)); if (ytab == 0) error(1, "ran out of memory (-y)"); } ytab[yflag++] = &ap[i+1]; goto next; case 'z': zflag++; Nflag = nflag = 0; continue; case 'Y': if (ap[++i] == '\0') ex_mode = sys_v; /* For pre-V2.4 compatibility */ else if (strcmp("SYSTEM_FIVE", &ap[i]) == 0) ex_mode = sys_v; else if (strcmp("POSIX", &ap[i]) == 0) ex_mode = posix; else if (strcmp("BSD", &ap[i]) == 0) ex_mode = bsd; else error(-1, "warning: bad -Y argument"); goto next; case 'L': goto next; default: filname = savestr("-x"); /* kludge */ filname[1] = ap[i]; /* kludge */ archdr.ar_name[0] = 0; /* kludge */ error(1, "bad flag"); }next: ; } if (rflag == 0 && Nflag == 0 && nflag == 0) zflag++; endload(argc, argv); exit(0);}/* * Convert a ascii string which is a hex number. * Used by -T and -D options. */htoi(p) register char *p;{ register int c, n; n = 0; while (c = *p++) { n <<= 4; if (isdigit(c)) n += c - '0'; else if (c >= 'a' && c <= 'f') n += 10 + (c - 'a'); else if (c >= 'A' && c <= 'F') n += 10 + (c - 'A'); else error(1, "badly formed hex number"); } return (n);}voiddelexit(){ struct stat stbuf; long size; char c = 0; bflush(); unlink("l.out"); /* * We have to insure that the last block of the data segment * is allocated a full pagesize block. If the underlying * file system allocates frags that are smaller than pagesize, * a full zero filled pagesize block needs to be allocated so * that when it is demand paged, the paged in block will be * appropriately filled with zeros. */ fstat(biofd, &stbuf); size = round(stbuf.st_size, pagesize); if (!rflag && size > stbuf.st_size) { lseek(biofd, size - 1, 0); if (write(biofd, &c, 1) != 1) delarg |= 4; } if (delarg==0 && (arflag==0 || dflag) && Aflag==0) /*009*/ (void) chmod(ofilename, ofilemode); exit (delarg);}endload(argc, argv) int argc; char **argv;{ register int c, i; long dnum; register char *ap, **p; clibseg = libseg; filname = 0; middle(); setupout(); p = argv+1; for (c=1; c<argc; c++) { ap = *p++; if (trace) printf("%s:\n", ap); if (*ap != '-') { load2arg(ap); continue; } for (i=1; ap[i]; i++) switch (ap[i]) { case 'D': dnum = htoi(*p); if (dorigin < dnum) while (dorigin < dnum) bputc(0, dout), dorigin++; /* fall into ... */ case 'T': case 'u': case 'e': case 'o': case 'H': ++c; ++p; /* fall into ... */ default: continue; case 'A': funding = 1; load2arg(*p++); funding = 0; c++; continue; case 'Y': case 'y': case 'L': goto next; case 'l': ap[--i]='-'; load2arg(&ap[i]); goto next; }next: ; } finishout();}/* * Scan file to find defined symbols. */load1arg(cp) register char *cp;{ register struct ranlib *tp; off_t nloc; int kind; kind = getfile(cp); if (Mflag) printf("%s\n", filname); switch (kind) { /* * Plain file. */ case 0: load1(0, 0L); break; /* * Archive without table of contents. * (Slowly) process each member. */ case 1: error(-1,"warning: archive has no table of contents; add one using ranlib(1)"); nloc = SARMAG; while (step(nloc)) nloc += sizeof(archdr) + round(atol(archdr.ar_size), sizeof (short)); break; /* * Archive with table of contents. * Read the table of contents and its associated string table. * Pass through the library resolving symbols until nothing changes * for an entire pass (i.e. you can get away with backward references * when there is a table of contents!) */ case 2: nloc = SARMAG + sizeof (archdr); dseek(&text, nloc, sizeof (tnum)); mget((char *)&tnum, sizeof (tnum), &text); nloc += sizeof (tnum); tab = (struct ranlib *)malloc(tnum); if (tab == 0) error(1, "ran out of memory (toc)"); dseek(&text, nloc, tnum); mget((char *)tab, tnum, &text); nloc += tnum; tnum /= sizeof (struct ranlib); dseek(&text, nloc, sizeof (ssiz)); mget((char *)&ssiz, sizeof (ssiz), &text); nloc += sizeof (ssiz); tabstr = (char *)malloc(ssiz); if (tabstr == 0) error(1, "ran out of memory (tocstr)"); dseek(&text, nloc, ssiz); mget((char *)tabstr, ssiz, &text); for (tp = &tab[tnum]; --tp >= tab;) { if (tp->ran_un.ran_strx < 0 || tp->ran_un.ran_strx >= ssiz) error(1, "mangled archive table of contents"); tp->ran_un.ran_name = tabstr + tp->ran_un.ran_strx; } while (ldrand()) continue; free((char *)tab); free(tabstr); nextlibp(-1); break; /* * Table of contents is out of date, so search * as a normal library (but skip the __.SYMDEF file). */ case 3: error(-1,"warning: table of contents for archive is out of date; rerun ranlib(1)"); nloc = SARMAG; do nloc += sizeof(archdr) + round(atol(archdr.ar_size), sizeof(short)); while (step(nloc)); break; } close(infil);}/* * Advance to the next archive member, which * is at offset nloc in the archive. If the member * is useful, record its location in the liblist structure * for use in pass2. Mark the end of the archive in libilst with a -1. */step(nloc) off_t nloc;{ dseek(&text, nloc, (long) sizeof archdr); if (text.size <= 0) { nextlibp(-1); return (0); } getarhdr(); if (load1(1, nloc + (sizeof archdr))) nextlibp(nloc); return (1);}/* * Record the location of a useful archive member. * Recording -1 marks the end of files from an archive. * The liblist data structure is dynamically extended here. */nextlibp(val) off_t val;{ if (clibseg->li_used == NROUT) { if (++clibseg == &libseg[NSEG]) error(1, "too many files loaded from libraries"); clibseg->li_first = (off_t *)malloc(NROUT * sizeof (off_t)); if (clibseg->li_first == 0) error(1, "ran out of memory (nextlibp)"); } clibseg->li_first[clibseg->li_used++] = val; if (val != -1 && Mflag) printf("\t%s\n", archdr.ar_name);}/* * One pass over an archive with a table of contents. * Remember the number of symbols currently defined, * then call step on members which look promising (i.e. * that define a symbol which is currently externally undefined). * Indicate to our caller whether this process netted any more symbols. */ldrand(){ register struct nlist *sp, **hp; register struct ranlib *tp, *tplast; off_t loc; int nsymt = symx(nextsym); tplast = &tab[tnum-1]; for (tp = tab; tp <= tplast; tp++) { if ((hp = slookup(tp->ran_un.ran_name)) == 0 || *hp == 0) continue; sp = *hp; if (sp->n_type != N_EXT+N_UNDF) continue; step(tp->ran_off); loc = tp->ran_off; while (tp < tplast && (tp+1)->ran_off == loc) tp++; } return (symx(nextsym) != nsymt);}/* * Examine a single file or archive member on pass 1. */load1(libflg, loc) off_t loc;{ register struct nlist *sp; struct nlist *savnext; int ndef, nlocal, type, size, nsymt; register int i; off_t maxoff; struct stat stb; readhdr(loc); if (filhdr.a_syms == 0) { if (filhdr.a_text+filhdr.a_data == 0) {/* Even though there's nothing here, we still mkfsym the name. 011 */ if (libflg == 0) /* 011 */ ssize += sizeof cursym; /* 011 */ return (0); } error(1, "no namelist"); } if (libflg) maxoff = atol(archdr.ar_size); else { fstat(infil, &stb); maxoff = stb.st_size; } if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff) error(1, "too small (old format .o?)"); ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; nlocal = sizeof cursym; savnext = nextsym; loc += N_SYMOFF(filhdr); dseek(&text, loc, filhdr.a_syms); dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t)); mget(&size, sizeof (size), &reloc); dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t)); curstr = (char *)malloc(size); if (curstr == NULL) error(1, "no space for string table"); mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc); while (text.size > 0) { mget((char *)&cursym, sizeof(struct nlist), &text); if (cursym.n_un.n_strx) { if (cursym.n_un.n_strx<sizeof(size) || cursym.n_un.n_strx>=size) error(1, "bad string table index (pass 1)"); cursym.n_un.n_name = curstr + cursym.n_un.n_strx; } type = cursym.n_type; /* Count the number of source lines and source files * found in the symbol table. This information is used by * dbx. Unnamed blocks are counted as functions, but * real procedures are counted from the loader namelist * (N_TEXT+N_EXT, and N_TEXT symbols). */ if (type & N_STAB) { switch (type) { case N_LBRAC: case N_RBRAC: /* unnamed blocks go in the functab */ nfun++; break; case N_SLINE: /* source lines */ nsline++; break; case N_SO: /* source files with stab info */ case N_SOL: /* textual include files */ nsol++; break; default: break; } } if ((type&N_EXT)==0) { if (Xflag==0 || type & N_STAB || cursym.n_un.n_name[0]!='L' ) /* SLR001 */ nlocal += sizeof cursym; if (type == N_TEXT) nfun++; /* vjh007 */ continue; } symreloc(); if (enter(lookup())) continue; if ((sp = lastsym)->n_type != N_EXT+N_UNDF) continue; if (cursym.n_type == N_EXT+N_UNDF) { if (cursym.n_value > sp->n_value) sp->n_value = cursym.n_value; continue; } if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) continue; ndef++; sp->n_type = cursym.n_type; sp->n_value = cursym.n_value; } if (libflg==0 || ndef) { tsize += filhdr.a_text; dsize += round(filhdr.a_data, sizeof (long)); bsize += round(filhdr.a_bss, sizeof (long)); ssize += nlocal; trsize += filhdr.a_trsize; drsize += filhdr.a_drsize; if (funding) textbase = (*slookup("_end"))->n_value; nsymt = symx(nextsym); for (i = symx(savnext); i < nsymt; i++) { sp = xsym(i); sp->n_un.n_name = savestr(sp->n_un.n_name); } free(curstr); return (1); } /* * No symbols defined by this library member. * Rip out the hash table entries and reset the symbol table. */ symfree(savnext); free(curstr); return(0);}middle(){ register struct nlist *sp; long csize, t, corigin, ocsize; int nund, rnd; char s; register int i; int nsymt; 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. */ nsymt = symx(nextsym); if (rflag==0) { for (i = 0; i < nsymt; i++) { sp = xsym(i); if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 && sp!=p_end && sp!=p_edata && sp!=p_etext) { rflag++; dflag = 0; break; } } } if (rflag) sflag = zflag = 0; /* * Assign common locations. */ csize = 0; if (!Aflag) addsym = symseg[0].sy_first; tsize += hsize ; /* Increase by size given with -H option */ database = round(tsize+textbase, (nflag||zflag? pagesize : sizeof (long))); /* * If requested, start BSS on a 512 byte hardware page boundary * (the 'pagesize' used in the rest of ld is the software page size). * This code causes the data size to be padded out to a 512 byte * interval. BSS is started directly after data, and may still be * included in data (not bss) since data (later in ld) is rounded * up to a 'pagesize' boundary. */ if (Bflag) dsize = round(dsize, 512); if (dflag || rflag==0) { ldrsym(p_etext, tsize, N_EXT+N_TEXT); ldrsym(p_edata, dsize, N_EXT+N_DATA); ldrsym(p_end, bsize, N_EXT+N_BSS); for (i = symx(addsym); i < nsymt; i++) { sp = xsym(i); if ((s=sp->n_type)==N_EXT+N_UNDF && (t = sp->n_value)!=0) { if (t >= sizeof (double)) rnd = sizeof (double); else if (t >= sizeof (long)) rnd = sizeof (long); else rnd = sizeof (short); csize = round(csize, rnd); sp->n_value = csize; sp->n_type = N_EXT+N_COMM; ocsize = csize; csize += t; } if (s&N_EXT && (s&N_TYPE)==N_UNDF && s&N_STAB) { sp->n_value = ocsize; sp->n_type = (s&N_STAB) | (N_EXT+N_COMM); } } } /* * Now set symbols to their final value */ csize = round(csize, sizeof (long)); torigin = textbase; dorigin = database; corigin = dorigin + dsize; borigin = corigin + csize; nund = 0; nsymt = symx(nextsym); for (i = symx(addsym); i<nsymt; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -