+++ /dev/null
-#if defined(DOSCCS) && !defined(lint)
-static char sccsid[] = "@(#)cc.c 4.13 9/18/85";
-#endif
-/*
- * cc - front end for C compiler
- */
-#include <sys/param.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/dir.h>
-#include <sys/wait.h>
-#ifdef XIFY
-#include <errno.h>
-#include <sys/stat.h>
-#endif
-
-#ifdef __STDC__
-#include <stdlib.h>
-#include <unistd.h>
-#endif
-
-#ifdef XIFY
-char *gcc = "/usr/bin/gcc";
-char *ld;
-char *xify;
-char *include;
-char *crt0;
-#else
-char *cpp = "/lib/cpp";
-char *ccom = "/lib/ccom";
-char *sccom = "/lib/sccom";
-char *c2 = "/lib/c2";
-char *as = "/bin/as";
-char *ld = "/bin/ld";
-char *crt0 = "/lib/crt0.o";
-#endif
-
-#ifndef XIFY
-char tmp0[30]; /* big enough for /tmp/ctm%05.5d */
-char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5;
-#endif
-char *outfile;
-/*char *savestr(), *strspl(), *setsuf();*/
-/*void idexit();*/
-char **av, **clist, **llist, **plist;
-int cflag, eflag, oflag, pflag, sflag, wflag, Rflag, exflag, proflag;
-int fflag, gflag, Gflag, Mflag, debug;
-char *dflag;
-int exfail;
-char *chpass;
-char *npassname;
-
-int nc, nl, np, nxo, na;
-
-#ifdef XIFY
-/* When we run "xify" as a child process, it will output to us on stderr a */
-/* list of dependencies as it encounters them. We receive this list via a */
-/* pipe, and as each dependency is received, we search the include path for */
-/* it, using special rules for "file.h" vs <file.h>, and then check if the */
-/* resolved path is already encountered (xified, or queued for xification). */
-/* If so, we ignore it. Otherwise we queue it. When we queue it, we save two */
-/* further pieces of information. If the path stem came from the include */
-/* path (other than being a relative path from a current file), and the */
-/* remaining path contained at least one directory, we have to "mkdir" the */
-/* path stem plus "/.xify". This is because the "-Idirectory" passed to to */
-/* gcc must exist, even if it is empty. This can occur if the remaining path */
-/* contains ".." elements. So, the first piece of information is which path */
-/* stem was used, or -1 if no extra "mkdir" is necessary (noting that we */
-/* will also "mkdir" the directory containing the xified source). It'd be */
-/* fine to "mkdir" the path stem at the time of queueing, or to "mkdir" all */
-/* path stems whether anything is found through them or not, but this way is */
-/* more consistent if we get an error and abort with things still enqueued. */
-/* The second piece of information is the mtime, so that we do not have to */
-/* "stat" it again when it comes to the head of the queue. When it comes to */
-/* the head of the queue we check for a previous xification of the same file */
-/* left in ".xify" underneath the directory containing the file, since this */
-/* will occur a lot for system includes and if not stale it saves much work. */
-
-#define IN_QUEUE_SIZE 0x100 /* fix this later and make it dynamic */
-
-struct {
- char *path;
- struct timespec mtime;
- int mkdir;
-} in_queue[IN_QUEUE_SIZE];
-int in_queue_head;
-int in_queue_tail;
-
-char in_path[BUFSIZ];
-char out_path[BUFSIZ];
-char err_path[BUFSIZ];
-
-extern char **environ;
-#endif
-
-#define cunlink(s) if (s) unlink(s)
-
-#ifndef __P
-#ifdef __STDC__
-#define __P(args) args
-#else
-#define __P(args) ()
-#endif
-#endif
-
-int main __P((int argc, char **argv));
-void idexit __P((void));
-int dexit __P((void));
-void error __P((char *s, char *x));
-int getsuf __P((char as[]));
-char *setsuf __P((char *as, int ch));
-#ifdef XIFY
-int xify_enqueue __P((char *in_name, char *prev_name));
-int xify_file __P((char *in_name, struct timespec *in_mtime));
-#endif
-int callsys __P((/*char *f,*/ char **v));
-int nodup __P((char **l, char *os));
-char *savestr __P((register char *cp));
-char *strspl __P((char *left, char *right));
-
-int main(argc, argv) int argc; char **argv; {
- char *t;
-#ifndef XIFY
- char *assource;
-#endif
- int i, j, c;
-#ifdef XIFY
- struct stat statbuf;
-#endif
-
- /* ld currently adds upto 5 args; 10 is room to spare */
- av = (char **)calloc(argc+/*10*/20, sizeof (char **));
- clist = (char **)calloc(argc, sizeof (char **));
- llist = (char **)calloc(argc, sizeof (char **));
- plist = (char **)calloc(argc, sizeof (char **));
-#ifdef XIFY
- t = argv[0];
- j = strlen(t);
- for (i = j; i > 0 && t[i - 1] != '/'; --i)
- ;
- j = (j >= 2 && t[j - 2] == 'c' && t[j - 1] == 'c') ? j - 2 : i;
- bcopy(t, in_path, j);
- strcpy(in_path + j, "ld");
- ld = savestr(in_path);
- strcpy(in_path + i, "../lib/xify");
- xify = savestr(in_path);
- strcpy(in_path + i, "../usr/include/.xify");
- include = savestr(in_path);
- strcpy(in_path + i, "../lib/crt0.o");
- crt0 = savestr(in_path);
-#endif
- for (i = 1; i < argc; i++) {
- if (*argv[i] == '-') switch (argv[i][1]) {
-
- case 'S':
- sflag++;
- cflag++;
- continue;
- case 'o':
- if (++i < argc) {
- outfile = argv[i];
- switch (getsuf(outfile)) {
-
- case 'c':
- error("-o would overwrite %s",
- outfile);
- exit(8);
- }
- }
- continue;
- case 'R':
- Rflag++;
- continue;
- case 'O':
- oflag++;
- continue;
- case 'p':
- proflag++;
- crt0 = "/lib/mcrt0.o";
- if (argv[i][2] == 'g')
- crt0 = "/usr/lib/gcrt0.o";
- continue;
- case 'f':
- fflag++;
- continue;
- case 'g':
- if (argv[i][2] == 'o') {
- Gflag++; /* old format for -go */
- } else {
- gflag++; /* new format for -g */
- }
- continue;
- case 'w':
- wflag++;
- continue;
- case 'E':
- exflag++;
- case 'P':
- pflag++;
- if (argv[i][1]=='P')
- fprintf(stderr,
- "cc: warning: -P option obsolete; you should use -E instead\n");
- plist[np++] = argv[i];
- case 'c':
- cflag++;
- continue;
- case 'M':
- exflag++;
- pflag++;
- Mflag++;
- /* and fall through */
-#ifdef XIFY
- plist[np++] = argv[i];
- continue;
- case 'D':
- if (strncmp(argv[i] + 2, "nox_", 4) == 0) {
- plist[np++] = strspl("-D", argv[i] + 6);
- continue;
- }
- t = strspl("-D", argv[i]);
- goto define;
- case 'U':
- if (strncmp(argv[i] + 2, "nox_", 4) == 0) {
- plist[np++] = strspl("-U", argv[i] + 6);
- continue;
- }
- t = strspl("-U", argv[i]);
- define:
- t[2] = 'x';
- t[3] = '_';
- plist[np++] = t;
- continue;
- case 'I':
- plist[np++] = strspl(argv[i], "/.xify");
- continue;
- case 'C':
- error("-C not implemented", 0);
- exit(1);
-#else
- case 'D':
- case 'I':
- case 'U':
- case 'C':
- plist[np++] = argv[i];
- continue;
-#endif
- case 'L':
- llist[nl++] = argv[i];
- continue;
- case 't':
- if (chpass)
- error("-t overwrites earlier option", 0);
- chpass = argv[i]+2;
- if (chpass[0]==0)
- chpass = "012p";
- continue;
- case 'B':
- if (npassname)
- error("-B overwrites earlier option", 0);
- npassname = argv[i]+2;
- if (npassname[0]==0)
- npassname = "/usr/c/o";
- continue;
- case 'd':
- if (argv[i][2] == '\0') {
- debug++;
- continue;
- }
- dflag = argv[i];
- continue;
- }
- t = argv[i];
- c = getsuf(t);
- if (c=='c' || c=='s' || exflag) {
- clist[nc++] = t;
- t = setsuf(t, 'o');
- }
- if (nodup(llist, t)) {
- llist[nl++] = t;
- if (getsuf(t)=='o')
- nxo++;
- }
- }
- if (gflag || Gflag) {
- if (oflag)
- fprintf(stderr, "cc: warning: -g disables -O\n");
- oflag = 0;
- }
- if (npassname && chpass ==0)
- chpass = "012p";
- if (chpass && npassname==0)
- npassname = "/usr/new";
- if (chpass)
-#ifdef XIFY
- gcc = strspl(npassname, "gcc");
-#else
- for (t=chpass; *t; t++) {
- switch (*t) {
-
- case '0':
- if (fflag)
- sccom = strspl(npassname, "sccom");
- else
- ccom = strspl(npassname, "ccom");
- continue;
- case '2':
- c2 = strspl(npassname, "c2");
- continue;
- case 'p':
- cpp = strspl(npassname, "cpp");
- continue;
- }
- }
-#endif
- if (nc==0)
- goto nocom;
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- signal(SIGINT, (void (*) __P((int sig)))idexit);
- if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
- signal(SIGTERM, (void (*) __P((int sig)))idexit);
- if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
- signal(SIGHUP, (void (*) __P((int sig)))idexit);
-#ifdef XIFY
- plist[np++] = strspl("-I", include);
-#else
- if (pflag==0)
- sprintf(tmp0, "/tmp/ctm%05.5d", getpid());
- tmp1 = strspl(tmp0, "1");
- tmp2 = strspl(tmp0, "2");
- tmp3 = strspl(tmp0, "3");
- if (pflag==0)
- tmp4 = strspl(tmp0, "4");
- if (oflag)
- tmp5 = strspl(tmp0, "5");
-#endif
- for (i=0; i<nc; i++) {
- if (nc > 1 && !Mflag) {
- printf("%s:\n", clist[i]);
- fflush(stdout);
- }
-#ifdef XIFY
- c = getsuf(clist[i]);
- if (c == 'c') {
- if (stat(clist[i], &statbuf)) {
- error("not found: %s", clist[i]);
- goto nogood;
- }
- if (xify_file(clist[i], &statbuf.st_mtim))
- goto nogood;
- clist[i] = savestr(out_path);
-
- while (in_queue_head < in_queue_tail) {
- if (
- xify_file(
- in_queue[in_queue_head].path,
- &in_queue[in_queue_head].mtime
- )
- )
- goto nogood;
- if (in_queue[in_queue_head].mkdir >= 0) {
- if (debug)
- fprintf(stderr, "mkdir %s\n", plist[in_queue[in_queue_head].mkdir] + 2);
- if (mkdir(plist[in_queue[in_queue_head].mkdir] + 2, 0777) && errno != EEXIST)
- goto nogood;
- }
- ++in_queue_head;
- }
- }
- av[0] = /*"gcc"*/gcc; av[1] = "-o";
- na = 2;
- if (cflag && nc==1 && outfile)
- av[na++] = outfile;
- else if (c == 'c' && !exflag)
- av[na++] = setsuf(clist[i] + 8, sflag ? 's' : 'o');
- else
- --na;
- for (j = 0; j < np; ++j)
- av[na++] = plist[j];
- av[na++] = "-fno-strict-aliasing";
- if (proflag)
- av[na++] = "-pg";
- if (gflag || Gflag)
- av[na++] = "-g";
- if (!wflag) {
- av[na++] = "-Wall";
- av[na++] = "-Wno-char-subscripts";
- av[na++] = "-Wno-deprecated-declarations";
- av[na++] = "-Wno-maybe-uninitialized";
- av[na++] = "-Wno-parentheses";
- av[na++] = "-Wno-strict-aliasing";
- av[na++] = "-Wno-unused-result";
- }
- if (oflag)
- av[na++] = "-O3";
- if (exflag)
- av[na++] = "-E";
- else if (sflag)
- av[na++] = "-S";
- else
- av[na++] = "-c";
- av[na++] = clist[i];
- av[na] = 0;
- if (callsys(/*gcc,*/ av)) {
- nogood:
- cflag++;
- eflag++;
- continue;
- }
-#else
- if (!Mflag && getsuf(clist[i]) == 's') {
- assource = clist[i];
- goto assemble;
- } else
- assource = tmp3;
- if (pflag)
- tmp4 = setsuf(clist[i], 'i');
- av[0] = /*"cpp"*/cpp; av[1] = clist[i];
- na = 2;
- if (!exflag)
- av[na++] = tmp4;
- for (j = 0; j < np; j++)
- av[na++] = plist[j];
- av[na++] = 0;
- if (callsys(/*cpp,*/ av)) {
- exfail++;
- eflag++;
- }
- if (pflag || exfail) {
- cflag++;
- continue;
- }
- if (sflag) {
- if (nc==1 && outfile)
- tmp3 = outfile;
- else
- tmp3 = setsuf(clist[i], 's');
- assource = tmp3;
- }
- av[0] = fflag ? /*"sccom"*/sccom : /*"ccom"*/ccom;
- av[1] = tmp4; av[2] = oflag?tmp5:tmp3; na = 3;
- if (proflag)
- av[na++] = "-XP";
- if (gflag) {
- av[na++] = "-Xg";
- } else if (Gflag) {
- av[na++] = "-XG";
- }
- if (wflag)
- av[na++] = "-w";
- av[na] = 0;
- if (callsys(/*fflag ? sccom : ccom,*/ av)) {
- cflag++;
- eflag++;
- continue;
- }
- if (oflag) {
- av[0] = /*"c2"*/c2; av[1] = tmp5; av[2] = tmp3; av[3] = 0;
- if (callsys(/*c2,*/ av)) {
- unlink(tmp3);
- tmp3 = assource = tmp5;
- } else
- unlink(tmp5);
- }
- if (sflag)
- continue;
- assemble:
- cunlink(tmp1); cunlink(tmp2); cunlink(tmp4);
- av[0] = /*"as"*/as; av[1] = "-o";
- if (cflag && nc==1 && outfile)
- av[2] = outfile;
- else
- av[2] = setsuf(clist[i], 'o');
- na = 3;
- if (Rflag)
- av[na++] = "-R";
- if (dflag)
- av[na++] = dflag;
- av[na++] = assource;
- av[na] = 0;
- if (callsys(/*as,*/ av) > 1) {
- cflag++;
- eflag++;
- continue;
- }
-#endif
- }
-nocom:
- if (cflag==0 && nl!=0) {
- i = 0;
- av[0] = /*"ld"*/ld; av[1] = "-X"; av[2] = crt0; na = 3;
- if (outfile) {
- av[na++] = "-o";
- av[na++] = outfile;
- }
-#ifdef XIFY
- if (debug)
- av[na++] = "-t";
-#endif
- while (i < nl)
- av[na++] = llist[i++];
-#ifndef XIFY
- if (gflag || Gflag)
- av[na++] = "-lg";
-#endif
- if (proflag)
- av[na++] = "-lc_p";
- else
- av[na++] = "-lc";
- av[na++] = 0;
- eflag |= callsys(/*ld,*/ av);
- if (nc==1 && nxo==1 && eflag==0)
- unlink(setsuf(clist[0], 'o'));
- }
- dexit();
-}
-
-void idexit() {
-
- eflag = 100;
- dexit();
-}
-
-int dexit() {
-
-#ifndef XIFY
- if (!pflag) {
- cunlink(tmp1);
- cunlink(tmp2);
- if (sflag==0)
- cunlink(tmp3);
- cunlink(tmp4);
- cunlink(tmp5);
- }
-#endif
- exit(eflag);
-}
-
-void error(s, x) char *s; char *x; {
- FILE *diag = exflag ? stderr : stdout;
-
- fprintf(diag, "cc: ");
- fprintf(diag, s, x);
- putc('\n', diag);
- exfail++;
- cflag++;
- eflag++;
-}
-
-int getsuf(as) char as[]; {
- register int c;
- register char *s;
- register int t;
-
- s = as;
- c = 0;
- while (t = *s++)
- if (t=='/')
- c = 0;
- else
- c++;
- s -= 3;
- if (c <= MAXNAMLEN && c > 2 && *s++ == '.')
- return (*s);
- return (0);
-}
-
-char *setsuf(as, ch) char *as; int ch; {
- register char *s, *s1;
-
- s = s1 = savestr(as);
- while (*s)
- if (*s++ == '/')
- s1 = s;
- s[-1] = ch;
- return (s1);
-}
-
-#ifdef XIFY
-int xify_file(in_name, in_mtime) char *in_name; struct timespec *in_mtime; {
- int i;
- struct stat out_statbuf;
- FILE *err_fp;
- char err_line[BUFSIZ];
- int e;
- /* note: out_path is an output parameter on success */
-
- for (i = strlen(in_name); i > 0 && in_name[i - 1] != '/'; --i)
- ;
- bcopy(in_name, out_path, i);
- strcpy(out_path + i, ".xify/x_");
- strcat(out_path + i, in_name + i);
-
- strcpy(err_path, out_path);
- strcat(err_path, ".deps");
-
- if (
- stat(out_path, &out_statbuf) ||
- out_statbuf.st_mtim.tv_sec < in_mtime->tv_sec || (
- out_statbuf.st_mtim.tv_sec == in_mtime->tv_sec &&
- out_statbuf.st_mtim.tv_nsec < in_mtime->tv_nsec
- )
-
- ) {
- out_path[i + 5] = 0;
- if (debug)
- fprintf(stderr, "mkdir %s\n", out_path);
- if (mkdir(out_path, 0777) == -1 && errno != EEXIST) {
- error("can't mkdir: %s\n", out_path);
- return 1;
- }
- out_path[i + 5] = '/';
-
- av[0] = /*"xify"*/xify; av[1] = in_name; av[2] = out_path; av[3] = err_path; av[4] = 0;
- if (callsys(/*xify,*/ av))
- return 1;
- }
-
- /*fprintf(stderr, "reading deps: %s\n", err_path);*/
- err_fp = fopen(err_path, "r");
- if (err_fp == 0) {
- error("can't find deps: %s", err_path);
- return 1;
- }
- while (fgets(err_line, BUFSIZ, err_fp))
- if (err_line[0] == '"') {
- e = '"';
- goto include;
- }
- else if (err_line[0] == '<') {
- e = '>';
- include:
- for (i = 1; err_line[i] != e; ++i) {
- if (err_line[i] == 0)
- goto garbage;
- }
- err_line[i] = 0;
- /*fprintf(stderr, "found dep: %s\n", err_line);*/
- if (xify_enqueue(err_line + 1, err_line[0] == '"' ? in_name : 0))
- break;
- }
- else {
- garbage:
- error("garbage in deps: %s\n", err_path);
- break;
- }
- fclose(err_fp);
- return 0;
-}
-
-int xify_enqueue(in_name, prev_name) char *in_name; char *prev_name; {
- int i, j, k;
- struct stat statbuf;
-
- for (i = strlen(in_name); i > 0 && in_name[i - 1] != '/'; --i)
- ;
- if (prev_name) {
- for (j = strlen(prev_name); j > 0 && prev_name[j - 1] != '/'; --j)
- ;
- bcopy(prev_name, in_path, j);
- strcpy(in_path + j, in_name);
- if (stat(in_path, &statbuf) == 0) {
- j = -1; /* does not require extra mkdir */
- goto found;
- }
-
- strcpy(in_path + j + i, ".xify/x_");
- strcat(in_path + j + i, in_name + i);
- if (debug)
- fprintf(stderr, "unlink %s\n", in_path);
- if (unlink(in_path)) {
- if (errno != ENOENT)
- goto cant_unlink;
- }
- else {
- strcat(in_path, ".deps");
- if (debug)
- fprintf(stderr, "unlink %s\n", in_path);
- if (unlink(in_path) && errno != ENOENT)
- goto cant_unlink;
- }
- }
- for (j = 0; j < np; ++j)
- if (/*plist[j][0] == '-' &&*/ plist[j][1] == 'I') {
- k = strlen(plist[j] + 2) - 5; /* remove ".xify" */
- bcopy(plist[j] + 2, in_path, k);
- strcpy(in_path + k, in_name);
- if (stat(in_path, &statbuf) == 0)
- goto found;
-
- strcpy(in_path + k + i, ".xify/x_");
- strcat(in_path + k + i, in_name + i);
- if (debug)
- fprintf(stderr, "unlink %s\n", in_path);
- if (unlink(in_path)) {
- if (errno != ENOENT)
- goto cant_unlink;
- }
- else {
- strcat(in_path, ".deps");
- if (debug)
- fprintf(stderr, "unlink %s\n", in_path);
- if (unlink(in_path) && errno != ENOENT) {
- cant_unlink:
- error("can't unlink: %s\n", in_path);
- return 1;
- }
- }
- }
- /* If we do not find a dependency, we just silently don't xify it, */
- /* then gcc will complain that it cannot find the xified dependency. */
- /* This is because the dependency might be #if'd out and not needed. */
- /*error("not found: %s\n", in_name);*/
- /*return 1;*/
- return 0;
-
-found:
- for (k = 0; k < in_queue_tail; ++k)
- if (strcmp(in_queue[k].path, in_path) == 0)
- return 0;
-
- if (in_queue_tail >= IN_QUEUE_SIZE) {
- error("in queue full: %s\n", in_path);
- return 1;
- }
-
- in_queue[in_queue_tail].path = savestr(in_path);
- in_queue[in_queue_tail].mtime = statbuf.st_mtim;
- in_queue[in_queue_tail].mkdir = i ? j : -1;
- ++in_queue_tail;
- return 0;
-}
-#endif
-
-int callsys(/*f,*/ v) /*char *f;*/ char **v; {
- int t, status;
-#if 1
- int i;
-
- if (debug) {
- fprintf(stderr, "%s", v[0]);
- for (i = 1; v[i]; ++i)
- fprintf(stderr, " %s", v[i]);
- fprintf(stderr, "\n");
- }
-#else
- char **cpp;
-
- if (debug) {
- fprintf(stderr, "%s:", /*f*/v[0]);
- for (cpp = v; *cpp != 0; cpp++)
- fprintf(stderr, " %s", *cpp);
- fprintf(stderr, "\n");
- }
-#endif
- t = vfork();
- if (t == -1) {
- printf("No more processes\n");
- return (100);
- }
- if (t == 0) {
- execv(/*f*/v[0], v);
- printf("Can't find %s\n", /*f*/v[0]);
- fflush(stdout);
- _exit(100);
- }
- while (t != wait(&status))
- ;
-#if 1
- if (WIFSIGNALED(status) /*&& WTERMSIG(status) != SIGALRM*/) {
- if (WTERMSIG(status) != SIGINT) {
- printf("Fatal error in %s\n", /*f*/v[0]);
- eflag = 8;
- }
- dexit();
- }
- return (WEXITSTATUS(status));
-#else
- if ((t=(status&0377)) != 0 && t!=14) {
- if (t!=2) {
- printf("Fatal error in %s\n", /*f*/v[0]);
- eflag = 8;
- }
- dexit();
- }
- return ((status>>8) & 0377);
-#endif
-}
-
-int nodup(l, os) char **l; char *os; {
- register char *t, *s;
- register int c;
-
- s = os;
- if (getsuf(s) != 'o')
- return (1);
- while (t = *l++) {
- while (c = *s++)
- if (c != *t++)
- break;
- if (*t==0 && c==0)
- return (0);
- s = os;
- }
- return (1);
-}
-
-#define NSAVETAB 1024
-char *savetab;
-int saveleft;
-
-char *savestr(cp) register char *cp; {
- register int len;
-
- len = strlen(cp) + 1;
- if (len > saveleft) {
- saveleft = NSAVETAB;
- if (len > saveleft)
- saveleft = len;
- savetab = (char *)malloc(saveleft);
- if (savetab == 0) {
- fprintf(stderr, "ran out of memory (savestr)\n");
- exit(1);
- }
- }
- strncpy(savetab, cp, len);
- cp = savetab;
- savetab += len;
- saveleft -= len;
- return (cp);
-}
-
-char *strspl(left, right) char *left; char *right; {
- char buf[BUFSIZ];
-
- strcpy(buf, left);
- strcat(buf, right);
- return (savestr(buf));
-}
+++ /dev/null
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
-#if defined(DOCOPYRIGHT) && !defined(lint)
-char copyright[] =
-"@(#) Copyright (c) 1980 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif
-
-#if defined(DOSCCS) && !defined(lint)
-static char sccsid[] = "@(#)ld.c 5.4 (Berkeley) 11/26/85";
-#endif
-
-/*
- * ld - string table version for VAX
- */
-
-#include <sys/param.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#ifdef XIFY
-#include <errno.h>
-#else
-#include <ar.h>
-#include <a.out.h>
-#include <ranlib.h>
-#endif
-#include <sys/stat.h>
-#include <sys/file.h>
-#ifdef XIFY
-#include <sys/wait.h>
-#endif
-
-#if defined(__STDC__) && !defined(X_)
-#include <stdlib.h>
-#include <unistd.h>
-#else
-#include <sys.h>
-#endif
-
-/*
- * Basic strategy:
- *
- * The loader takes a number of files and libraries as arguments.
- * A first pass examines each file in turn. Normal files are
- * unconditionally loaded, and the (external) symbols they define and require
- * are noted in the symbol table. Libraries are searched, and the
- * library members which define needed symbols are remembered
- * in a special data structure so they can be selected on the second
- * pass. Symbols defined and required by library members are also
- * recorded.
- *
- * After the first pass, the loader knows the size of the basic text
- * data, and bss segments from the sum of the sizes of the modules which
- * were required. It has computed, for each ``common'' symbol, the
- * maximum size of any reference to it, and these symbols are then assigned
- * storage locations after their sizes are appropriately rounded.
- * The loader now knows all sizes for the eventual output file, and
- * can determine the final locations of external symbols before it
- * begins a second pass.
- *
- * On the second pass each normal file and required library member
- * is processed again. The symbol table for each such file is
- * reread and relevant parts of it are placed in the output. The offsets
- * in the local symbol table for externally defined symbols are recorded
- * since relocation information refers to symbols in this way.
- * Armed with all necessary information, the text and data segments
- * are relocated and the result is placed in the output file, which
- * is pasted together, ``in place'', by writing to it in several
- * different places concurrently.
- */
-
-#ifndef XIFY
-/*
- * Internal data structures
- *
- * All internal data structures are segmented and dynamically extended.
- * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT)
- * referenced library members, and 100 (NSYMPR) private (local) symbols
- * per object module. For large programs and/or modules, these structures
- * expand to be up to 40 (NSEG) times as large as this as necessary.
- */
-#define NSEG 40 /* Number of segments, each data structure */
-#define NSYM 1103 /* Number of symbols per segment */
-#define NROUT 250 /* Number of library references per segment */
-#define NSYMPR 100 /* Number of private symbols per segment */
-
-/*
- * Structure describing each symbol table segment.
- * Each segment has its own hash table. We record the first
- * address in and first address beyond both the symbol and hash
- * tables, for use in the routine symx and the lookup routine respectively.
- * The symfree routine also understands this structure well as it used
- * to back out symbols from modules we decide that we don't need in pass 1.
- *
- * Csymseg points to the current symbol table segment;
- * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated,
- * (unless csymseg->sy_used == NSYM in which case we will allocate another
- * symbol table segment first.)
- */
-struct symseg {
- struct nlist *sy_first; /* base of this alloc'ed segment */
- struct nlist *sy_last; /* end of this segment, for n_strx */
- int sy_used; /* symbols used in this seg */
- struct nlist **sy_hfirst; /* base of hash table, this seg */
- struct nlist **sy_hlast; /* end of hash table, this seg */
-} symseg[NSEG], *csymseg;
-
-/*
- * The lookup routine uses quadratic rehash. Since a quadratic rehash
- * only probes 1/2 of the buckets in the table, and since the hash
- * table is segmented the same way the symbol table is, we make the
- * hash table have twice as many buckets as there are symbol table slots
- * in the segment. This guarantees that the quadratic rehash will never
- * fail to find an empty bucket if the segment is not full and the
- * symbol is not there.
- */
-#define HSIZE (NSYM*2)
-
-/*
- * Xsym converts symbol table indices (ala x) into symbol table pointers.
- * Symx (harder, but never used in loops) inverts pointers into the symbol
- * table into indices using the symseg[] structure.
- */
-#define xsym(x) (symseg[(x)/NSYM].sy_first+((x)%NSYM))
-/* symx() is a function, defined below */
-
-struct nlist cursym; /* current symbol */
-struct nlist *lastsym; /* last symbol entered */
-struct nlist *nextsym; /* next available symbol table entry */
-struct nlist *addsym; /* first sym defined during incr load */
-int nsym; /* pass2: number of local symbols in a.out */
-/* nsym + symx(nextsym) is the symbol table size during pass2 */
-
-struct nlist **lookup(), **slookup();
-struct nlist *p_etext, *p_edata, *p_end, *entrypt;
-
-/*
- * Definitions of segmentation for library member table.
- * For each library we encounter on pass 1 we record pointers to all
- * members which we will load on pass 2. These are recorded as offsets
- * into the archive in the library member table. Libraries are
- * separated in the table by the special offset value -1.
- */
-off_t li_init[NROUT];
-struct libseg {
- off_t *li_first;
- int li_used;
- int li_used2;
-} libseg[NSEG] = {
- li_init, 0, 0,
-}, *clibseg = libseg;
-
-/*
- * In processing each module on pass 2 we must relocate references
- * relative to external symbols. These references are recorded
- * in the relocation information as relative to local symbol numbers
- * assigned to the external symbols when the module was created.
- * Thus before relocating the module in pass 2 we create a table
- * which maps these internal numbers to symbol table entries.
- * A hash table is constructed, based on the local symbol table indices,
- * for quick lookup of these symbols.
- */
-#define LHSIZ 31
-struct local {
- int l_index; /* index to symbol in file */
- struct nlist *l_symbol; /* ptr to symbol table */
- struct local *l_link; /* hash link */
-} *lochash[LHSIZ], lhinit[NSYMPR];
-struct locseg {
- struct local *lo_first;
- int lo_used;
-} locseg[NSEG] = {
- lhinit, 0
-}, *clocseg;
-
-/*
- * Libraries are typically built with a table of contents,
- * which is the first member of a library with special file
- * name __.SYMDEF and contains a list of symbol names
- * and with each symbol the offset of the library member which defines
- * it. The loader uses this table to quickly tell which library members
- * are (potentially) useful. The alternative, examining the symbol
- * table of each library member, is painfully slow for large archives.
- *
- * See <ranlib.h> for the definition of the ranlib structure and an
- * explanation of the __.SYMDEF file format.
- */
-int tnum; /* number of symbols in table of contents */
-int ssiz; /* size of string table for table of contents */
-struct ranlib *tab; /* the table of contents (dynamically allocated) */
-char *tabstr; /* string table for table of contents */
-
-/*
- * We open each input file or library only once, but in pass2 we
- * (historically) read from such a file at 2 different places at the
- * same time. These structures are remnants from those days,
- * and now serve only to catch ``Premature EOF''.
- * In order to make I/O more efficient, we provide routines which
- * use the optimal block size returned by stat().
- */
-#define BLKSIZE 1024
-typedef struct {
- short *fakeptr;
- int bno;
- int nibuf;
- int nuser;
- char *buff;
- int bufsize;
-} PAGE;
-
-PAGE page[2];
-int p_blksize;
-int p_blkshift;
-int p_blkmask;
-
-struct {
- short *fakeptr;
- int bno;
- int nibuf;
- int nuser;
-} fpage;
-
-typedef struct {
- char *ptr;
- int bno;
- int nibuf;
- long size;
- long pos;
- PAGE *pno;
-} STREAM;
-
-STREAM text;
-STREAM reloc;
-
-/*
- * Header from the a.out and the archive it is from (if any).
- */
-struct exec filhdr;
-struct ar_hdr archdr;
-#define OARMAG 0177545
-#endif
-
-/*
- * Options.
- */
-int trace;
-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 Mflag; /* print rudimentary load map */
-int nflag; /* pure procedure */
-int dflag; /* define common even with rflag */
-int zflag; /* demand paged */
-long hsize; /* size of hole at beginning of data to be squashed */
-int Aflag; /* doing incremental load */
-int Nflag; /* want impure a.out */
-int funding; /* reading fundamental file for incremental load */
-int yflag; /* number of symbols to be traced */
-char **ytab; /* the symbols */
-
-#ifndef XIFY
-/*
- * These are the cumulative sizes, set in pass 1, which
- * appear in the a.out header when the loader is finished.
- */
-off_t tsize, dsize, bsize, trsize, drsize, ssize;
-
-/*
- * Symbol relocation: c?rel is a scale factor which is
- * added to an old relocation to convert it to new units;
- * i.e. it is the difference between segment origins.
- * (Thus if we are loading from a data segment which began at location
- * 4 in a .o file into an a.out where it will be loaded starting at
- * 1024, cdrel will be 1020.)
- */
-long ctrel, cdrel, cbrel;
-
-/*
- * Textbase is the start address of all text, 0 unless given by -T.
- * Database is the base of all data, computed before and used during pass2.
- */
-long textbase, database;
-
-/*
- * The base addresses for the loaded text, data and bss from the
- * current module during pass2 are given by torigin, dorigin and borigin.
- */
-long torigin, dorigin, borigin;
-#endif
-
-/*
- * Errlev is nonzero when errors have occured.
- * Delarg is an implicit argument to the routine delexit
- * which is called on error. We do ``delarg = errlev'' before normal
- * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the
- * result file executable.
- */
-int errlev;
-int delarg = 4;
-
-#ifndef XIFY
-/*
- * The biobuf structure and associated routines are used to write
- * into one file at several places concurrently. Calling bopen
- * with a biobuf structure sets it up to write ``biofd'' starting
- * at the specified offset. You can then use ``bwrite'' and/or ``bputc''
- * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
- * Calling bflush drains all the buffers and MUST be done before exit.
- */
-struct biobuf {
- short b_nleft; /* Number free spaces left in b_buf */
-/* Initialize to be less than b_bufsize initially, to boundary align in file */
- char *b_ptr; /* Next place to stuff characters */
- char *b_buf; /* Pointer to the buffer */
- int b_bufsize; /* Size of the buffer */
- off_t b_off; /* Current file offset */
- struct biobuf *b_link; /* Link in chain for bflush() */
-} *biobufs;
-#define bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
- : bflushc(b, c))
-int biofd;
-off_t boffset;
-struct biobuf *tout, *dout, *trout, *drout, *sout, *strout;
-
-/*
- * Offset is the current offset in the string file.
- * Its initial value reflects the fact that we will
- * eventually stuff the size of the string table at the
- * beginning of the string table (i.e. offset itself!).
- */
-off_t offset = sizeof (off_t);
-#endif
-
-int ofilfnd; /* -o given; otherwise move l.out to a.out */
-char *ofilename = "l.out";
-int ofilemode; /* respect umask even for unsucessful ld's */
-int infil; /* current input file descriptor */
-char *filname; /* and its name */
-
-#define NDIRS 25
-#define NDEFDIRS 3 /* number of default directories in dirs[] */
-char *dirs[NDIRS]; /* directories for library search */
-int ndir; /* number of directories */
-
-#ifdef XIFY
-char *gcc = "/usr/bin/gcc";
-char *ld = "/usr/bin/ld";
-
-char **av;
-int na;
-
-char in_path[BUFSIZ];
-char out_path[BUFSIZ];
-
-extern char **environ;
-#else
-/*
- * Base of the string table of the current module (pass1 and pass2).
- */
-char *curstr;
-
-/*
- * System software page size, as returned by getpagesize.
- */
-int pagesize;
-#endif
-
-/*char get();*/
-/*int delexit();*/
-/*char *savestr();*/
-/*char *malloc();*/
-
-#ifndef __P
-#ifdef __STDC__
-#define __P(args) args
-#else
-#define __P(args) ()
-#endif
-#endif
-
-int main __P((int argc, char **argv));
-#ifndef XIFY
-int htoi __P((register char *p));
-#endif
-void delexit __P((void));
-void endload __P((int argc, char **argv));
-#ifdef XIFY
-void xify_library __P((char *in_name));
-int callsys __P((/*char *f,*/ char **v));
-#else
-void load1arg __P((register char *cp));
-int step __P((off_t nloc));
-void nextlibp __P((off_t val));
-int ldrand __P((void));
-int load1 __P((int libflg, off_t loc));
-void middle __P((void));
-void fixspec __P((struct nlist *sym, long offset));
-void ldrsym __P((register struct nlist *sp, long val, int type));
-void setupout __P((void));
-void outb __P((register struct biobuf **bp, int inc, int bufsize));
-void load2arg __P((char *acp));
-void load2 __P((long loc));
-void tracesym __P((void));
-void load2td __P((long creloc, int position, struct biobuf *b1, struct biobuf *b2));
-#endif
-void finishout __P((void));
-#ifndef XIFY
-void mkfsym __P((char *s));
-void getarhdr __P((void));
-void mget __P((void *_loc, int n, register STREAM *sp));
-void symwrite __P((struct nlist *sp, struct biobuf *bp));
-void dseek __P((register STREAM *sp, long loc, long s));
-char get __P((STREAM *asp));
-int getfile __P((char *acp));
-int libopen __P((char *name, int oflags));
-struct nlist **lookup __P((void));
-void symfree __P((struct nlist *saved));
-struct nlist **slookup __P((char *s));
-int enter __P((register struct nlist **hp));
-int symx __P((struct nlist *sp));
-void symreloc __P((void));
-#endif
-void error __P((int n, char *s));
-#ifndef XIFY
-void readhdr __P((off_t loc));
-int _round __P((int v, u_long r));
-#endif
-char *savestr __P((register char *cp));
-#ifdef XIFY
-char *strspl __P((char *left, char *right));
-#else
-void bopen __P((register struct biobuf *bp, int off, int bufsize));
-void bwrite __P((void *_p, register int cnt, register struct biobuf *bp));
-void bflush __P((void));
-void bflush1 __P((register struct biobuf *bp));
-void bflushc __P((register struct biobuf *bp, int c));
-void bseek __P((register struct biobuf *bp, register off_t off));
-#endif
-
-int main(argc, argv) int argc; char **argv; {
- register int c, i;
-#ifndef XIFY
- int num;
-#endif
- register char *ap, **p;
-#ifndef XIFY
- char save;
-#endif
-
- if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
- signal(SIGINT, (void (*) __P((int sig)))delexit);
- signal(SIGTERM, (void (*) __P((int sig)))delexit);
- }
- if (argc == 1)
- exit(4);
-#ifndef XIFY
- pagesize = getpagesize();
-#endif
-
- /*
- * Pull out search directories.
- */
- for (c = 1; c < argc; c++) {
- ap = argv[c];
- if (ap[0] == '-' && ap[1] == 'L') {
- if (ap[2] == 0)
- error(1, "-L: pathname missing");
- if (ndir >= NDIRS - NDEFDIRS)
- error(1, "-L: too many directories");
-#ifdef XIFY
- dirs[ndir++] = strspl(&ap[2], "/.xify");
-#else
- dirs[ndir++] = &ap[2];
-#endif
- }
- }
- /* add default search directories */
-#ifdef XIFY
- ap = argv[0];
- for (i = strlen(ap); i > 0 && ap[i - 1] != '/'; --i)
- ;
- bcopy(ap, in_path, i);
- strcpy(in_path + i, "../lib/.xify");
- dirs[ndir++] = savestr(in_path);
- strcpy(in_path + i, "../usr/lib/.xify");
- dirs[ndir++] = savestr(in_path);
- strcpy(in_path + i, "../usr/local/lib/.xify");
- dirs[ndir++] = savestr(in_path);
-#else
- dirs[ndir++] = "/lib";
- dirs[ndir++] = "/usr/lib";
- dirs[ndir++] = "/usr/local/lib";
-#endif
-
- p = argv+1;
- /*
- * Scan files once to find where symbols are defined.
- */
- for (c=1; c<argc; c++) {
-#ifndef XIFY
- if (trace)
- printf("%s:\n", *p);
-#endif
- filname = 0;
- ap = *p++;
- if (*ap != '-') {
-#ifndef XIFY
- load1arg(ap);
-#endif
- continue;
- }
- for (i=1; ap[i]; i++) switch (ap[i]) {
-
- case 'o':
- if (++c >= argc)
- error(1, "-o where?");
- ofilename = *p++;
- ofilfnd++;
- continue;
- case 'u':
- case 'e':
- if (++c >= argc)
- error(1, "-u or -c: arg missing");
-#ifdef XIFY
- error(1, "-u or -c: not implemented");
-#else
- enter(slookup(*p++));
- if (ap[i]=='e')
- entrypt = lastsym;
-#endif
- continue;
- case 'H':
- if (++c >= argc)
- error(1, "-H: arg missing");
-#ifdef XIFY
- error(1, "-H: not implemented");
-#else
- if (tsize!=0)
- error(1, "-H: too late, some text already loaded");
- hsize = atoi(*p++);
-#endif
- continue;
- case 'A':
- if (++c >= argc)
- error(1, "-A: arg missing");
-#ifdef XIFY
- error(1, "-A: not implemented");
-#else
- if (Aflag)
- error(1, "-A: only one base file allowed");
- Aflag = 1;
- nflag = 0;
- funding = 1;
- load1arg(*p++);
- trsize = drsize = tsize = dsize = bsize = 0;
- ctrel = cdrel = cbrel = 0;
- funding = 0;
- addsym = nextsym;
-#endif
- continue;
- case 'D':
- if (++c >= argc)
- error(1, "-D: arg missing");
-#ifdef XIFY
- error(1, "-D: not implemented");
-#else
- num = htoi(*p++);
- if (dsize > num)
- error(1, "-D: too small");
- dsize = num;
-#endif
- continue;
- case 'T':
- if (++c >= argc)
- error(1, "-T: arg missing");
-#ifdef XIFY
- error(1, "-T: not implemented");
-#else
- if (tsize!=0)
- error(1, "-T: too late, some text already loaded");
- textbase = htoi(*p++);
-#endif
- continue;
- case 'l':
-#ifndef XIFY
- save = ap[--i];
- ap[i]='-';
- load1arg(&ap[i]);
- ap[i]=save;
-#endif
- goto next;
- case 'M':
- Mflag++;
- continue;
- 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 'L':
- goto next;
- default:
- filname = savestr("-x"); /* kludge */
- filname[1] = ap[i]; /* kludge */
-#ifndef XIFY
- archdr.ar_name[0] = 0; /* kludge */
-#endif
- error(1, "bad flag");
- }
-next:
- ;
- }
- if (rflag == 0 && Nflag == 0 && nflag == 0)
- zflag++;
- endload(argc, argv);
- exit(0);
-}
-
-#ifndef XIFY
-/*
- * Convert a ascii string which is a hex number.
- * Used by -T and -D options.
- */
-int 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);
-}
-#endif
-
-void delexit() {
-#ifndef XIFY
- struct stat stbuf;
- long size;
- char c = 0;
-
- bflush();
-#endif
- unlink("l.out");
-#ifndef XIFY
- /*
- * 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 && Aflag==0)
- (void) chmod(ofilename, ofilemode);
-#endif
- exit (delarg);
-}
-
-void endload(argc, argv) int argc; char **argv; {
- register int c, i;
-#ifndef XIFY
- long dnum;
-#endif
- register char *ap, **p;
-
-#ifdef XIFY
- /* ld currently adds upto 5 args; 10 is room to spare */
- av = (char **)calloc(argc+10, sizeof (char **));
- av[0] = rflag ? /*"ld"*/ld : /*"gcc"*/gcc; av[1] = "-o"; av[2] = ofilename;
- na = 3;
- for (i = 0; i < ndir; ++i)
- av[na++] = strspl("-L", dirs[i]);
- if (rflag)
- av[na++] = "-r";
-#else
- clibseg = libseg;
- filname = 0;
- middle();
- setupout();
-#endif
- p = argv+1;
- for (c=1; c<argc; c++) {
- ap = *p++;
-#ifndef XIFY
- if (trace)
- printf("%s:\n", ap);
-#endif
- if (*ap != '-') {
-#ifdef XIFY
- av[na++] = ap;
-#else
- load2arg(ap);
-#endif
- continue;
- }
- for (i=1; ap[i]; i++) switch (ap[i]) {
-
-#ifndef XIFY
- case 'D':
- dnum = htoi(*p);
- if (dorigin < dnum)
- while (dorigin < dnum)
- bputc(0, dout), dorigin++;
- /* fall into ... */
- case 'T':
- case 'u':
- case 'e':
-#endif
- case 'o':
-#ifndef XIFY
- case 'H':
-#endif
- ++c;
- ++p;
- /* fall into ... */
- default:
- continue;
-#ifndef XIFY
- case 'A':
- funding = 1;
- load2arg(*p++);
- funding = 0;
- c++;
- continue;
-#endif
- case 'y':
- case 'L':
- goto next;
- case 'l':
- ap[--i]='-';
-#ifdef XIFY
- filname = ap + i;
- if (strncmp(filname + 2, "nox_", 4) == 0)
- av[na++] = strspl("-l", filname + 6);
- else {
- xify_library(filname + 2);
- av[na++] = strspl("-lx_", filname + 2);
- }
-#else
-
- load2arg(&ap[i]);
-#endif
- goto next;
- }
-next:
- ;
- }
-#ifdef XIFY
- if (callsys(/*rflag ? ld : gcc,*/ av))
- delexit();
-#endif
- finishout();
-}
-
-#ifdef XIFY
-void xify_library(in_name) char *in_name; {
- int i, j;
- struct stat statbuf;
-
- for (i = 0; i < ndir; ++i) {
- j = strlen(dirs[i]) - 5; /* remove ".xify" */
- bcopy(dirs[i], in_path, j);
- strcpy(in_path + j, "lib");
- strcat(in_path + j, in_name);
- strcat(in_path + j, ".a");
- if (stat(in_path, &statbuf) == 0)
- goto found;
-
- strcpy(in_path + j, ".xify/libx_");
- strcat(in_path + j, in_name);
- strcat(in_path + j, ".a");
- if (trace)
- fprintf(stderr, "unlink %s\n", in_path);
- if (unlink(in_path) && errno != ENOENT) {
- filname=in_path;
- error(1, "can't unlink\n");
- }
- }
- error(1, "not found\n");
- exit(1);
-
-found:
- j += 5; /* j = strlen(dirs[i]); */
- bcopy(dirs[i], out_path, j);
- strcpy(out_path + j, "/libx_");
- strcat(out_path + j, in_name);
- strcat(out_path + j, ".a");
- if (stat(out_path, &statbuf) == 0)
- return;
- if (trace)
- fprintf(stderr, "mkdir %s\n", dirs[i]);
- if (mkdir(dirs[i], 0777) == -1 && errno != EEXIST) {
- filname = dirs[i];
- error(1, "can't mkdir\n");
- }
- strcpy(in_path, "../lib");
- strcat(in_path, in_name);
- strcat(in_path, ".a");
- if (trace)
- fprintf(stderr, "symlink %s %s\n", in_path, out_path);
- if (symlink(in_path, out_path) == -1) {
- filname = out_path;
- error(1, "can't symlink\n");
- }
-}
-
-int callsys(/*f,*/ v) /*char *f;*/ char **v; {
- int t, status;
-#if 1
- int i;
-
- if (/*debug*/trace) {
- fprintf(stderr, "%s", v[0]);
- for (i = 1; v[i]; ++i)
- fprintf(stderr, " %s", v[i]);
- fprintf(stderr, "\n");
- }
-#else
- char **cpp;
-
- if (/*debug*/trace) {
- fprintf(stderr, "%s:", /*f*/v[0]);
- for (cpp = v; *cpp != 0; cpp++)
- fprintf(stderr, " %s", *cpp);
- fprintf(stderr, "\n");
- }
-#endif
- t = vfork();
- if (t == -1) {
- printf("No more processes\n");
- return (100);
- }
- if (t == 0) {
- execv(/*f*/v[0], v);
- printf("Can't find %s\n", /*f*/v[0]);
- fflush(stdout);
- _exit(100);
- }
- while (t != wait(&status))
- ;
-#if 1
- if (WIFSIGNALED(status) /*&& WTERMSIG(status) != SIGALRM*/) {
- if (WTERMSIG(status) != SIGINT) {
- printf("Fatal error in %s\n", /*f*/v[0]);
- /*eflag*/delarg = 8;
- }
- /*dexit*/delexit();
- }
- return (WEXITSTATUS(status));
-#else
- if ((t=(status&0377)) != 0 && t!=14) {
- if (t!=2) {
- printf("Fatal error in %s\n", /*f*/v[0]);
- /*eflag*/delarg = 8;
- }
- /*dexit*/delexit();
- }
- return ((status>>8) & 0377);
-#endif
-}
-#else
-/*
- * Scan file to find defined symbols.
- */
-void 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(&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(tab, tnum, &text);
- nloc += tnum;
- tnum /= sizeof (struct ranlib);
- dseek(&text, nloc, sizeof (ssiz));
- mget(&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(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.
- */
-int 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.
- */
-void 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.
- */
-int 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.
- */
-int load1(libflg, loc) int libflg; 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)
- 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(&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;
- if ((type&N_EXT)==0) {
- if (Xflag==0 || cursym.n_un.n_name[0]!='L' ||
- type & N_STAB)
- nlocal += sizeof cursym;
- 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);
-}
-
-void 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;
- database = _round(tsize+textbase,
- (nflag||zflag? pagesize : sizeof (long)));
- database += hsize;
- 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++) {
- sp = xsym(i);
- switch (sp->n_type & (N_TYPE+N_EXT)) {
-
- case N_EXT+N_UNDF:
- if (arflag == 0)
- errlev |= 01;
- if ((arflag==0 || dflag) && sp->n_value==0) {
- if (sp==p_end || sp==p_etext || sp==p_edata)
- continue;
- if (nund==0)
- printf("Undefined:\n");
- nund++;
- printf("%s\n", sp->n_un.n_name);
- }
- continue;
- case N_EXT+N_ABS:
- default:
- continue;
- case N_EXT+N_TEXT:
- sp->n_value += torigin;
- continue;
- case N_EXT+N_DATA:
- sp->n_value += dorigin;
- continue;
- case N_EXT+N_BSS:
- sp->n_value += borigin;
- continue;
- case N_EXT+N_COMM:
- sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS);
- sp->n_value += corigin;
- continue;
- }
- }
- if (sflag || xflag)
- ssize = 0;
- bsize += csize;
- nsym = ssize / (sizeof cursym);
- if (Aflag) {
- fixspec(p_etext,torigin);
- fixspec(p_edata,dorigin);
- fixspec(p_end,borigin);
- }
-}
-
-void fixspec(sym, offset) struct nlist *sym; long offset; {
-
- if(symx(sym) < symx(addsym) && sym!=0)
- sym->n_value += offset;
-}
-
-void ldrsym(sp, val, type) register struct nlist *sp; long val; int type; {
-
- if (sp == 0)
- return;
- if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) {
- printf("%s: ", sp->n_un.n_name);
- error(0, "user attempt to redfine loader-defined symbol");
- return;
- }
- sp->n_type = type;
- sp->n_value = val;
-}
-
-off_t wroff;
-struct biobuf toutb;
-
-void setupout() {
- int bss;
- struct stat stbuf;
- extern char *sys_errlist[];
- extern int errno;
-
- ofilemode = 0777 & ~umask(0);
- biofd = creat(ofilename, 0666 & ofilemode);
- if (biofd < 0) {
- filname = ofilename; /* kludge */
- archdr.ar_name[0] = 0; /* kludge */
- error(1, sys_errlist[errno]); /* kludge */
- }
- fstat(biofd, &stbuf); /* suppose file exists, wrong*/
- if (stbuf.st_mode & 0111) { /* mode, ld fails? */
- chmod(ofilename, stbuf.st_mode & 0666);
- ofilemode = stbuf.st_mode;
- }
- filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
- filhdr.a_text = nflag ? tsize :
- _round(tsize, zflag ? pagesize : sizeof (long));
- filhdr.a_data = zflag ? _round(dsize, pagesize) : dsize;
- bss = bsize - (filhdr.a_data - dsize);
- if (bss < 0)
- bss = 0;
- filhdr.a_bss = bss;
- filhdr.a_trsize = trsize;
- filhdr.a_drsize = drsize;
- filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*symx(nextsym));
- if (entrypt) {
- if (entrypt->n_type!=N_EXT+N_TEXT)
- error(0, "entry point not in text");
- else
- filhdr.a_entry = entrypt->n_value;
- } else
- filhdr.a_entry = 0;
- filhdr.a_trsize = (rflag ? trsize:0);
- filhdr.a_drsize = (rflag ? drsize:0);
- tout = &toutb;
- bopen(tout, 0, stbuf.st_blksize);
- bwrite(&filhdr, sizeof (filhdr), tout);
- if (zflag)
- bseek(tout, pagesize);
- wroff = N_TXTOFF(filhdr) + filhdr.a_text;
- outb(&dout, filhdr.a_data, stbuf.st_blksize);
- if (rflag) {
- outb(&trout, filhdr.a_trsize, stbuf.st_blksize);
- outb(&drout, filhdr.a_drsize, stbuf.st_blksize);
- }
- if (sflag==0 || xflag==0) {
- outb(&sout, filhdr.a_syms, stbuf.st_blksize);
- wroff += sizeof (offset);
- outb(&strout, 0, stbuf.st_blksize);
- }
-}
-
-void outb(bp, inc, bufsize) register struct biobuf **bp; int inc; int bufsize; {
-
- *bp = (struct biobuf *)malloc(sizeof (struct biobuf));
- if (*bp == 0)
- error(1, "ran out of memory (outb)");
- bopen(*bp, wroff, bufsize);
- wroff += inc;
-}
-
-void load2arg(acp) char *acp; {
- register char *cp;
- off_t loc;
-
- cp = acp;
- if (getfile(cp) == 0) {
- while (*cp)
- cp++;
- while (cp >= acp && *--cp != '/');
- mkfsym(++cp);
- load2(0L);
- } else { /* scan archive members referenced */
- for (;;) {
- if (clibseg->li_used2 == clibseg->li_used) {
- if (clibseg->li_used < NROUT)
- error(1, "libseg botch");
- clibseg++;
- }
- loc = clibseg->li_first[clibseg->li_used2++];
- if (loc == -1)
- break;
- dseek(&text, loc, (long)sizeof(archdr));
- getarhdr();
- mkfsym(archdr.ar_name);
- load2(loc + (long)sizeof(archdr));
- }
- }
- close(infil);
-}
-
-void load2(loc) long loc; {
- int size;
- register struct nlist *sp;
- register struct local *lp;
- register int symno, i;
- int type;
-
- readhdr(loc);
- if (!funding) {
- ctrel = torigin;
- cdrel += dorigin;
- cbrel += borigin;
- }
- /*
- * Reread the symbol table, recording the numbering
- * of symbols for fixing external references.
- */
- for (i = 0; i < LHSIZ; i++)
- lochash[i] = 0;
- clocseg = locseg;
- clocseg->lo_used = 0;
- symno = -1;
- loc += N_TXTOFF(filhdr);
- dseek(&text, loc+filhdr.a_text+filhdr.a_data+
- filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t));
- mget(&size, sizeof(size), &text);
- dseek(&text, loc+filhdr.a_text+filhdr.a_data+
- filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t),
- size - sizeof(off_t));
- curstr = (char *)malloc(size);
- if (curstr == NULL)
- error(1, "out of space reading string table (pass 2)");
- mget(curstr+sizeof(off_t), size-sizeof(off_t), &text);
- dseek(&text, loc+filhdr.a_text+filhdr.a_data+
- filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);
- while (text.size > 0) {
- symno++;
- mget(&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 2)");
- cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
- }
-/* inline expansion of symreloc() */
- switch (cursym.n_type & 017) {
-
- case N_TEXT:
- case N_EXT+N_TEXT:
- cursym.n_value += ctrel;
- break;
- case N_DATA:
- case N_EXT+N_DATA:
- cursym.n_value += cdrel;
- break;
- case N_BSS:
- case N_EXT+N_BSS:
- cursym.n_value += cbrel;
- break;
- case N_EXT+N_UNDF:
- break;
- default:
- if (cursym.n_type&N_EXT)
- cursym.n_type = N_EXT+N_ABS;
- }
-/* end inline expansion of symreloc() */
- type = cursym.n_type;
- if (yflag && cursym.n_un.n_name)
- for (i = 0; i < yflag; i++)
- /* fast check for 2d character! */
- if (ytab[i][1] == cursym.n_un.n_name[1] &&
- !strcmp(ytab[i], cursym.n_un.n_name)) {
- tracesym();
- break;
- }
- if ((type&N_EXT) == 0) {
- if (!sflag&&!xflag&&
- (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB))
- symwrite(&cursym, sout);
- continue;
- }
- if (funding)
- continue;
- if ((sp = *lookup()) == 0)
- error(1, "internal error: symbol not found");
- if (cursym.n_type == N_EXT+N_UNDF) {
- if (clocseg->lo_used == NSYMPR) {
- if (++clocseg == &locseg[NSEG])
- error(1, "local symbol overflow");
- clocseg->lo_used = 0;
- }
- if (clocseg->lo_first == 0) {
- clocseg->lo_first = (struct local *)
- malloc(NSYMPR * sizeof (struct local));
- if (clocseg->lo_first == 0)
- error(1, "out of memory (clocseg)");
- }
- lp = &clocseg->lo_first[clocseg->lo_used++];
- lp->l_index = symno;
- lp->l_symbol = sp;
- lp->l_link = lochash[symno % LHSIZ];
- lochash[symno % LHSIZ] = lp;
- continue;
- }
- if (cursym.n_type & N_STAB)
- continue;
- if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) {
- printf("%s: ", cursym.n_un.n_name);
- error(0, "multiply defined");
- }
- }
- if (funding)
- return;
- dseek(&text, loc, filhdr.a_text);
- dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
- load2td(ctrel, torigin - textbase, tout, trout);
- dseek(&text, loc+filhdr.a_text, filhdr.a_data);
- dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize,
- filhdr.a_drsize);
- load2td(cdrel, dorigin - database, dout, drout);
- while (filhdr.a_data & (sizeof(long)-1)) {
- bputc(0, dout);
- filhdr.a_data++;
- }
- torigin += filhdr.a_text;
- dorigin += _round(filhdr.a_data, sizeof (long));
- borigin += _round(filhdr.a_bss, sizeof (long));
- free(curstr);
-}
-
-struct tynames {
- int ty_value;
- char *ty_name;
-} tynames[] = {
- N_UNDF, "undefined",
- N_ABS, "absolute",
- N_TEXT, "text",
- N_DATA, "data",
- N_BSS, "bss",
- N_COMM, "common",
- 0, 0,
-};
-
-void tracesym() {
- register struct tynames *tp;
-
- if (cursym.n_type & N_STAB)
- return;
- printf("%s", filname);
- if (archdr.ar_name[0])
- printf("(%s)", archdr.ar_name);
- printf(": ");
- if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) {
- printf("definition of common %s size %d\n",
- cursym.n_un.n_name, cursym.n_value);
- return;
- }
- for (tp = tynames; tp->ty_name; tp++)
- if (tp->ty_value == (cursym.n_type&N_TYPE))
- break;
- printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to");
- if (cursym.n_type&N_EXT)
- printf(" external");
- if (tp->ty_name)
- printf(" %s", tp->ty_name);
- printf(" %s\n", cursym.n_un.n_name);
-}
-
-/*
- * This routine relocates the single text or data segment argument.
- * Offsets from external symbols are resolved by adding the value
- * of the external symbols. Non-external reference are updated to account
- * for the relative motion of the segments (ctrel, cdrel, ...). If
- * a relocation was pc-relative, then we update it to reflect the
- * change in the positioning of the segments by adding the displacement
- * of the referenced segment and subtracting the displacement of the
- * current segment (creloc).
- *
- * If we are saving the relocation information, then we increase
- * each relocation datum address by our base position in the new segment.
- */
-void load2td(creloc, position, b1, b2) long creloc; int position; struct biobuf *b1; struct biobuf *b2; {
- register struct nlist *sp;
- register struct local *lp;
- long tw;
- register struct relocation_info *rp, *rpend;
- struct relocation_info *relp;
- char *codep;
- register char *cp;
- int relsz, codesz;
-
- relsz = reloc.size;
- relp = (struct relocation_info *)malloc(relsz);
- codesz = text.size;
- codep = (char *)malloc(codesz);
- if (relp == 0 || codep == 0)
- error(1, "out of memory (load2td)");
- mget(relp, relsz, &reloc);
- rpend = &relp[relsz / sizeof (struct relocation_info)];
- mget(codep, codesz, &text);
- for (rp = relp; rp < rpend; rp++) {
- cp = codep + rp->r_address;
- /*
- * Pick up previous value at location to be relocated.
- */
- switch (rp->r_length) {
-
- case 0: /* byte */
- tw = *cp;
- break;
-
- case 1: /* word */
- tw = *(short *)cp;
- break;
-
- case 2: /* long */
- tw = *(long *)cp;
- break;
-
- default:
- error(1, "load2td botch: bad length");
- }
- /*
- * If relative to an external which is defined,
- * resolve to a simpler kind of reference in the
- * result file. If the external is undefined, just
- * convert the symbol number to the number of the
- * symbol in the result file and leave it undefined.
- */
- if (rp->r_extern) {
- /*
- * Search the hash table which maps local
- * symbol numbers to symbol tables entries
- * in the new a.out file.
- */
- lp = lochash[rp->r_symbolnum % LHSIZ];
- while (lp->l_index != rp->r_symbolnum) {
- lp = lp->l_link;
- if (lp == 0)
- error(1, "local symbol botch");
- }
- sp = lp->l_symbol;
- if (sp->n_type == N_EXT+N_UNDF)
- rp->r_symbolnum = nsym+symx(sp);
- else {
- rp->r_symbolnum = sp->n_type & N_TYPE;
- tw += sp->n_value;
- rp->r_extern = 0;
- }
- } else switch (rp->r_symbolnum & N_TYPE) {
- /*
- * Relocation is relative to the loaded position
- * of another segment. Update by the change in position
- * of that segment.
- */
- case N_TEXT:
- tw += ctrel;
- break;
- case N_DATA:
- tw += cdrel;
- break;
- case N_BSS:
- tw += cbrel;
- break;
- case N_ABS:
- break;
- default:
- error(1, "relocation format botch (symbol type))");
- }
- /*
- * Relocation is pc relative, so decrease the relocation
- * by the amount the current segment is displaced.
- * (E.g if we are a relative reference to a text location
- * from data space, we added the increase in the text address
- * above, and subtract the increase in our (data) address
- * here, leaving the net change the relative change in the
- * positioning of our text and data segments.)
- */
- if (rp->r_pcrel)
- tw -= creloc;
- /*
- * Put the value back in the segment,
- * while checking for overflow.
- */
- switch (rp->r_length) {
-
- case 0: /* byte */
- if (tw < -128 || tw > 127)
- error(0, "byte displacement overflow");
- *cp = tw;
- break;
- case 1: /* word */
- if (tw < -32768 || tw > 32767)
- error(0, "word displacement overflow");
- *(short *)cp = tw;
- break;
- case 2: /* long */
- *(long *)cp = tw;
- break;
- }
- /*
- * If we are saving relocation information,
- * we must convert the address in the segment from
- * the old .o file into an address in the segment in
- * the new a.out, by adding the position of our
- * segment in the new larger segment.
- */
- if (rflag)
- rp->r_address += position;
- }
- bwrite(codep, codesz, b1);
- if (rflag)
- bwrite(relp, relsz, b2);
- free((char *)relp);
- free(codep);
-}
-#endif
-
-void finishout() {
-#ifndef XIFY
- register int i;
- int nsymt;
-
- if (sflag==0) {
- nsymt = symx(nextsym);
- for (i = 0; i < nsymt; i++)
- symwrite(xsym(i), sout);
- bwrite(&offset, sizeof offset, sout);
- }
-#endif
- if (!ofilfnd) {
- unlink("a.out");
- if (link("l.out", "a.out") < 0)
- error(1, "cannot move l.out to a.out");
- ofilename = "a.out";
- }
- delarg = errlev;
- delexit();
-}
-
-#ifndef XIFY
-void mkfsym(s) char *s; {
-
- if (sflag || xflag)
- return;
- cursym.n_un.n_name = s;
- cursym.n_type = N_TEXT;
- cursym.n_value = torigin;
- symwrite(&cursym, sout);
-}
-
-void getarhdr() {
- register char *cp;
-
- mget(&archdr, sizeof archdr, &text);
- for (cp=archdr.ar_name; cp<&archdr.ar_name[sizeof(archdr.ar_name)];)
- if (*cp++ == ' ') {
- cp[-1] = 0;
- return;
- }
-}
-
-void mget(_loc, n, sp) void *_loc; int n; register STREAM *sp; {
-#define loc (*(char **)&_loc)
- register char *p;
- register int take;
-
-top:
- if (n == 0)
- return;
- if (sp->size && sp->nibuf) {
- p = sp->ptr;
- take = sp->size;
- if (take > sp->nibuf)
- take = sp->nibuf;
- if (take > n)
- take = n;
- n -= take;
- sp->size -= take;
- sp->nibuf -= take;
- sp->pos += take;
- do
- *loc++ = *p++;
- while (--take > 0);
- sp->ptr = p;
- goto top;
- }
- if (n > p_blksize) {
- take = n - n % p_blksize;
- lseek(infil, (sp->bno+1)<<p_blkshift, 0);
- if (take > sp->size || read(infil, loc, take) != take)
- error(1, "premature EOF");
- loc += take;
- n -= take;
- sp->size -= take;
- sp->pos += take;
- dseek(sp, (sp->bno+1+(take>>p_blkshift))<<p_blkshift, -1);
- goto top;
- }
- *loc++ = get(sp);
- --n;
- goto top;
-#undef loc
-}
-
-void symwrite(sp, bp) struct nlist *sp; struct biobuf *bp; {
- register int len;
- register char *str;
-
- str = sp->n_un.n_name;
- if (str) {
- sp->n_un.n_strx = offset;
- len = strlen(str) + 1;
- bwrite(str, len, strout);
- offset += len;
- }
- bwrite(sp, sizeof (*sp), bp);
- sp->n_un.n_name = str;
-}
-
-void dseek(sp, loc, s) register STREAM *sp; long loc; long s; {
- register PAGE *p;
- register b, o;
- int n;
-
- b = loc>>p_blkshift;
- o = loc&p_blkmask;
- if (o&01)
- error(1, "loader error; odd offset");
- --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, loc & ~(long)p_blkmask, 0);
- if ((n = read(infil, p->buff, p_blksize)) < 0)
- n = 0;
- p->nibuf = n;
- } else
- error(1, "botch: no pages");
- ++p->nuser;
- sp->bno = b;
- sp->pno = p;
- if (s != -1) {sp->size = s; sp->pos = 0;}
- sp->ptr = (char *)(p->buff + o);
- if ((sp->nibuf = p->nibuf-o) <= 0)
- sp->size = 0;
-}
-
-char get(asp) STREAM *asp; {
- register STREAM *sp;
-
- sp = asp;
- if ((sp->nibuf -= sizeof(char)) < 0) {
- dseek(sp, ((long)(sp->bno+1)<<p_blkshift), (long)-1);
- sp->nibuf -= sizeof(char);
- }
- if ((sp->size -= sizeof(char)) <= 0) {
- if (sp->size < 0)
- error(1, "premature EOF");
- ++fpage.nuser;
- --sp->pno->nuser;
- sp->pno = (PAGE *) &fpage;
- }
- sp->pos += sizeof(char);
- return(*sp->ptr++);
-}
-
-int getfile(acp) char *acp; {
- register int c;
- char arcmag[SARMAG+1];
- struct stat stb;
-
- archdr.ar_name[0] = '\0';
- filname = acp;
- if (filname[0] == '-' && filname[1] == 'l')
- infil = libopen(filname + 2, O_RDONLY);
- else
- infil = open(filname, O_RDONLY);
- if (infil < 0)
- error(1, "cannot open");
- fstat(infil, &stb);
- page[0].bno = page[1].bno = -1;
- page[0].nuser = page[1].nuser = 0;
- c = stb.st_blksize;
- if (c == 0 || (c & (c - 1)) != 0) {
- /* use default size if not a power of two */
- c = BLKSIZE;
- }
- if (p_blksize != c) {
- p_blksize = c;
- p_blkmask = c - 1;
- for (p_blkshift = 0; c > 1 ; p_blkshift++)
- c >>= 1;
- if (page[0].buff != NULL)
- free(page[0].buff);
- page[0].buff = (char *)malloc(p_blksize);
- if (page[0].buff == NULL)
- error(1, "ran out of memory (getfile)");
- if (page[1].buff != NULL)
- free(page[1].buff);
- page[1].buff = (char *)malloc(p_blksize);
- if (page[1].buff == NULL)
- error(1, "ran out of memory (getfile)");
- }
- text.pno = reloc.pno = (PAGE *) &fpage;
- fpage.nuser = 2;
- dseek(&text, 0L, SARMAG);
- if (text.size <= 0)
- error(1, "premature EOF");
- mget(arcmag, SARMAG, &text);
- arcmag[SARMAG] = 0;
- if (strcmp(arcmag, ARMAG))
- return (0);
- dseek(&text, SARMAG, sizeof archdr);
- if (text.size <= 0)
- return (1);
- getarhdr();
- if (strncmp(archdr.ar_name, "__.SYMDEF", sizeof(archdr.ar_name)) != 0)
- return (1);
- return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2);
-}
-
-/*
- * Search for a library with given name
- * using the directory search array.
- */
-int libopen(name, oflags) char *name; int oflags; {
- register char *p, *cp;
- register int i;
- static char buf[MAXPATHLEN+1];
- int fd = -1;
-
- if (*name == '\0') /* backwards compat */
- name = "a";
- for (i = 0; i < ndir && fd == -1; i++) {
- p = buf;
- for (cp = dirs[i]; *cp; *p++ = *cp++)
- ;
- *p++ = '/';
- for (cp = "lib"; *cp; *p++ = *cp++)
- ;
- for (cp = name; *cp; *p++ = *cp++)
- ;
- cp = ".a";
- while (*p++ = *cp++)
- ;
- fd = open(buf, oflags);
- }
- if (fd != -1)
- filname = buf;
- return (fd);
-}
-
-struct nlist **lookup() {
- register int sh;
- register struct nlist **hp;
- register char *cp, *cp1;
- register struct symseg *gp;
- register int i;
-
- sh = 0;
- for (cp = cursym.n_un.n_name; *cp;)
- sh = (sh<<1) + *cp++;
- sh = (sh & 0x7fffffff) % HSIZE;
- for (gp = symseg; gp < &symseg[NSEG]; gp++) {
- if (gp->sy_first == 0) {
- gp->sy_first = (struct nlist *)
- calloc(NSYM, sizeof (struct nlist));
- gp->sy_hfirst = (struct nlist **)
- calloc(HSIZE, sizeof (struct nlist *));
- if (gp->sy_first == 0 || gp->sy_hfirst == 0)
- error(1, "ran out of space for symbol table");
- gp->sy_last = gp->sy_first + NSYM;
- gp->sy_hlast = gp->sy_hfirst + HSIZE;
- }
- if (gp > csymseg)
- csymseg = gp;
- hp = gp->sy_hfirst + sh;
- i = 1;
- do {
- if (*hp == 0) {
- if (gp->sy_used == NSYM)
- break;
- return (hp);
- }
- cp1 = (*hp)->n_un.n_name;
- for (cp = cursym.n_un.n_name; *cp == *cp1++;)
- if (*cp++ == 0)
- return (hp);
- hp += i;
- i += 2;
- if (hp >= gp->sy_hlast)
- hp -= HSIZE;
- } while (i < HSIZE);
- if (i > HSIZE)
- error(1, "hash table botch");
- }
- error(1, "symbol table overflow");
- /*NOTREACHED*/
-#ifdef __GNUC__
- return 0;
-#endif
-}
-
-void symfree(saved) struct nlist *saved; {
- register struct symseg *gp;
- register struct nlist *sp;
-
- for (gp = csymseg; gp >= symseg; gp--, csymseg--) {
- sp = gp->sy_first + gp->sy_used;
- if (sp == saved) {
- nextsym = sp;
- return;
- }
- for (sp--; sp >= gp->sy_first; sp--) {
- gp->sy_hfirst[sp->n_hash] = 0;
- gp->sy_used--;
- if (sp == saved) {
- nextsym = sp;
- return;
- }
- }
- }
- if (saved == 0)
- return;
- error(1, "symfree botch");
-}
-
-struct nlist **slookup(s) char *s; {
-
- cursym.n_un.n_name = s;
- cursym.n_type = N_EXT+N_UNDF;
- cursym.n_value = 0;
- return (lookup());
-}
-
-int enter(hp) register struct nlist **hp; {
- register struct nlist *sp;
-
- if (*hp==0) {
- if (hp < csymseg->sy_hfirst || hp >= csymseg->sy_hlast)
- error(1, "enter botch");
- *hp = lastsym = sp = csymseg->sy_first + csymseg->sy_used;
- csymseg->sy_used++;
- sp->n_un.n_name = cursym.n_un.n_name;
- sp->n_type = cursym.n_type;
- sp->n_hash = hp - csymseg->sy_hfirst;
- sp->n_value = cursym.n_value;
- nextsym = lastsym + 1;
- return(1);
- } else {
- lastsym = *hp;
- return(0);
- }
-}
-
-int symx(sp) struct nlist *sp; {
- register struct symseg *gp;
-
- if (sp == 0)
- return (0);
- for (gp = csymseg; gp >= symseg; gp--)
- /* <= is sloppy so nextsym will always work */
- if (sp >= gp->sy_first && sp <= gp->sy_last)
- return ((gp - symseg) * NSYM + sp - gp->sy_first);
- error(1, "symx botch");
- /*NOTREACHED*/
-#ifdef __GNUC__
- return -1;
-#endif
-}
-
-void symreloc() {
- if(funding) return;
- switch (cursym.n_type & 017) {
-
- case N_TEXT:
- case N_EXT+N_TEXT:
- cursym.n_value += ctrel;
- return;
-
- case N_DATA:
- case N_EXT+N_DATA:
- cursym.n_value += cdrel;
- return;
-
- case N_BSS:
- case N_EXT+N_BSS:
- cursym.n_value += cbrel;
- return;
-
- case N_EXT+N_UNDF:
- return;
-
- default:
- if (cursym.n_type&N_EXT)
- cursym.n_type = N_EXT+N_ABS;
- return;
- }
-}
-#endif
-
-void error(n, s) int n; char *s; {
-
- if (errlev==0)
- printf("ld:");
- if (filname) {
- printf("%s", filname);
-#ifndef XIFY
- if (n != -1 && archdr.ar_name[0])
- printf("(%s)", archdr.ar_name);
-#endif
- printf(": ");
- }
- printf("%s\n", s);
- if (n == -1)
- return;
- if (n)
- delexit();
- errlev = 2;
-}
-
-#ifndef XIFY
-void readhdr(loc) off_t loc; {
-
- dseek(&text, loc, (long)sizeof(filhdr));
- mget(&filhdr, sizeof(filhdr), &text);
- if (N_BADMAG(filhdr)) {
- if (filhdr.a_magic == OARMAG)
- error(1, "old archive");
- error(1, "bad magic number");
- }
- if (filhdr.a_text&01 || filhdr.a_data&01)
- error(1, "text/data size odd");
- if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) {
- cdrel = -_round(filhdr.a_text, pagesize);
- cbrel = cdrel - filhdr.a_data;
- } else if (filhdr.a_magic == OMAGIC) {
- cdrel = -filhdr.a_text;
- cbrel = cdrel - filhdr.a_data;
- } else
- error(1, "bad format");
-}
-
-int _round(v, r) int v; u_long r; {
-
- r--;
- v += r;
- v &= ~(long)r;
- return(v);
-}
-#endif
-
-#define NSAVETAB 8192
-char *savetab;
-int saveleft;
-
-char *savestr(cp) register char *cp; {
- register int len;
-
- len = strlen(cp) + 1;
- if (len > saveleft) {
- saveleft = NSAVETAB;
- if (len > saveleft)
- saveleft = len;
- savetab = malloc(saveleft);
- if (savetab == 0)
- error(1, "ran out of memory (savestr)");
- }
- strncpy(savetab, cp, len);
- cp = savetab;
- savetab += len;
- saveleft -= len;
- return (cp);
-}
-
-#ifdef XIFY
-char *strspl(left, right) char *left; char *right; {
- char buf[BUFSIZ];
-
- strcpy(buf, left);
- strcat(buf, right);
- return (savestr(buf));
-}
-#else
-void bopen(bp, off, bufsize) register struct biobuf *bp; int off; int bufsize; {
-
- bp->b_ptr = bp->b_buf = malloc(bufsize);
- if (bp->b_ptr == (char *)0)
- error(1, "ran out of memory (bopen)");
- bp->b_bufsize = bufsize;
- bp->b_nleft = bufsize - (off % bufsize);
- bp->b_off = off;
- bp->b_link = biobufs;
- biobufs = bp;
-}
-
-int bwrerror;
-
-void bwrite(_p, cnt, bp) void *_p; register int cnt; register struct biobuf *bp; {
-#define p (*(char **)&_p)
- register int put;
- register char *to;
-
-top:
- if (cnt == 0)
- return;
- if (bp->b_nleft) {
- put = bp->b_nleft;
- if (put > cnt)
- put = cnt;
- bp->b_nleft -= put;
- to = bp->b_ptr;
- bcopy(p, to, put);
- bp->b_ptr += put;
- p += put;
- cnt -= put;
- goto top;
- }
- if (cnt >= bp->b_bufsize) {
- if (bp->b_ptr != bp->b_buf)
- bflush1(bp);
- put = cnt - cnt % bp->b_bufsize;
- if (boffset != bp->b_off)
- lseek(biofd, bp->b_off, 0);
- if (write(biofd, p, put) != put) {
- bwrerror = 1;
- error(1, "output write error");
- }
- bp->b_off += put;
- boffset = bp->b_off;
- p += put;
- cnt -= put;
- goto top;
- }
- bflush1(bp);
- goto top;
-#undef p
-}
-
-void bflush() {
- register struct biobuf *bp;
-
- if (bwrerror)
- return;
- for (bp = biobufs; bp; bp = bp->b_link)
- bflush1(bp);
-}
-
-void bflush1(bp) register struct biobuf *bp; {
- register int cnt = bp->b_ptr - bp->b_buf;
-
- if (cnt == 0)
- return;
- if (boffset != bp->b_off)
- lseek(biofd, bp->b_off, 0);
- if (write(biofd, bp->b_buf, cnt) != cnt) {
- bwrerror = 1;
- error(1, "output write error");
- }
- bp->b_off += cnt;
- boffset = bp->b_off;
- bp->b_ptr = bp->b_buf;
- bp->b_nleft = bp->b_bufsize;
-}
-
-void bflushc(bp, c) register struct biobuf *bp; int c; {
-
- bflush1(bp);
- bputc(c, bp);
-}
-
-void bseek(bp, off) register struct biobuf *bp; register off_t off; {
- bflush1(bp);
-
- bp->b_nleft = bp->b_bufsize - (off % bp->b_bufsize);
- bp->b_off = off;
-}
-#endif