read 128 bytes not 2
[unix-history] / usr / src / old / ld / ld.c
index c06b5e3..5461967 100644 (file)
@@ -1,14 +1,14 @@
-static char sccsid[] = "@(#)ld.c 3.1 %G%";
+static char sccsid[] = "@(#)ld.c 4.1 %G%";
 /*
 /*
- * VAX VM/UNIX ld - string table version
+ * ld - string table version for VAX
  */
 
 #include <sys/types.h>
 #include <signal.h>
 #include <stdio.h>
 #include <ctype.h>
  */
 
 #include <sys/types.h>
 #include <signal.h>
 #include <stdio.h>
 #include <ctype.h>
-#include <newar.h>
-#include <newa.out.h>
+#include <ar.h>
+#include <a.out.h>
 #include <ranlib.h>
 #include <stat.h>
 #include <pagsiz.h>
 #include <ranlib.h>
 #include <stat.h>
 #include <pagsiz.h>
@@ -107,7 +107,7 @@ int nsym;                   /* pass2: number of local symbols in a.out */
 /* nsym + symx(nextsym) is the symbol table size during pass2 */
 
 struct nlist **lookup(), **slookup();
 /* nsym + symx(nextsym) is the symbol table size during pass2 */
 
 struct nlist **lookup(), **slookup();
-struct nlist *p_data, *p_etext, *p_edata, *p_end, *entrypt;
+struct nlist *p_etext, *p_edata, *p_end, *entrypt;
 
 /*
  * Definitions of segmentation for library member table.
 
 /*
  * Definitions of segmentation for library member table.
@@ -134,8 +134,6 @@ struct      libseg {
  * 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.
  * 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.
- *
- * COULD JUST KEEP WHOLE SYMBOL TABLE AROUND.
  */
 #define        LHSIZ   31
 struct local {
  */
 #define        LHSIZ   31
 struct local {
@@ -171,7 +169,7 @@ 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,
  * 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''... soon to be gone...
+ * and now serve only to catch ``Premature EOF''.
  */
 typedef struct {
        short   *fakeptr;
  */
 typedef struct {
        short   *fakeptr;
@@ -219,12 +217,16 @@ 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    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    nflag;          /* pure procedure */
 int    dflag;          /* define common even with rflag */
-int    zflag = 1;      /* demand paged  */
+int    zflag;          /* demand paged  */
 long   hsize;          /* size of hole at beginning of data to be squashed */
 int    Aflag;          /* doing incremental load */
 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    funding;        /* reading fundamental file for incremental load */
+int    yflag;          /* number of symbols to be traced */
+char   **ytab;         /* the symbols */
 
 /*
  * These are the cumulative sizes, set in pass 1, which
 
 /*
  * These are the cumulative sizes, set in pass 1, which
@@ -236,16 +238,22 @@ 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.
  * 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;
 
 /*
  */
 long   ctrel, cdrel, cbrel;
 
 /*
- * Textbase is the starting text address, 0 unless given by -H.
+ * 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.
  * 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.
  */
  * The base addresses for the loaded text, data and bss from the
  * current module during pass2 are given by torigin, dorigin and borigin.
  */
-long   textbase, database;
 long   torigin, dorigin, borigin;
 
 /*
 long   torigin, dorigin, borigin;
 
 /*
@@ -310,13 +318,17 @@ char **argv;
        register char *ap, **p;
        char save;
 
        register char *ap, **p;
        char save;
 
-       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
                signal(SIGINT, delexit);
                signal(SIGINT, delexit);
+               signal(SIGTERM, delexit);
+       }
        if (argc == 1)
                exit(4);
        p = argv+1;
 
        if (argc == 1)
                exit(4);
        p = argv+1;
 
-       /* scan files once to find symdefs */
+       /*
+        * Scan files once to find where symbols are defined.
+        */
        for (c=1; c<argc; c++) {
                if (trace)
                        printf("%s:\n", *p);
        for (c=1; c<argc; c++) {
                if (trace)
                        printf("%s:\n", *p);
@@ -384,6 +396,9 @@ char **argv;
                        load1arg(&ap[i]); 
                        ap[i]=save;
                        goto next;
                        load1arg(&ap[i]); 
                        ap[i]=save;
                        goto next;
+               case 'M':
+                       Mflag++;
+                       continue;
                case 'x':
                        xflag++;
                        continue;
                case 'x':
                        xflag++;
                        continue;
@@ -396,8 +411,6 @@ char **argv;
                case 'r':
                        rflag++;
                        arflag++;
                case 'r':
                        rflag++;
                        arflag++;
-                       zflag = 0;
-                       nflag = 1;
                        continue;
                case 's':
                        sflag++;
                        continue;
                case 's':
                        sflag++;
@@ -405,11 +418,11 @@ char **argv;
                        continue;
                case 'n':
                        nflag++;
                        continue;
                case 'n':
                        nflag++;
-                       zflag = 0;
+                       Nflag = zflag = 0;
                        continue;
                case 'N':
                        continue;
                case 'N':
-                       nflag = 0;
-                       zflag = 0;
+                       Nflag++;
+                       nflag = zflag = 0;
                        continue;
                case 'd':
                        dflag++;
                        continue;
                case 'd':
                        dflag++;
@@ -420,9 +433,19 @@ char **argv;
                case 't':
                        trace++;
                        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++;
                case 'z':
                        zflag++;
-                       nflag = 0;
+                       Nflag = nflag = 0;
                        continue;
                default:
                        filname = savestr("-x");        /* kludge */
                        continue;
                default:
                        filname = savestr("-x");        /* kludge */
@@ -433,6 +456,8 @@ char **argv;
 next:
                ;
        }
 next:
                ;
        }
+       if (rflag == 0 && Nflag == 0 && nflag == 0)
+               zflag++;
        endload(argc, argv);
        exit(0);
 }
        endload(argc, argv);
        exit(0);
 }
@@ -516,6 +541,8 @@ endload(argc, argv)
                        funding = 0;
                        c++;
                        continue;
                        funding = 0;
                        c++;
                        continue;
+               case 'y':
+                       goto next;
                case 'l':
                        ap[--i]='-'; 
                        load2arg(&ap[i]);
                case 'l':
                        ap[--i]='-'; 
                        load2arg(&ap[i]);
@@ -535,8 +562,12 @@ load1arg(cp)
 {
        register struct ranlib *tp;
        off_t nloc;
 {
        register struct ranlib *tp;
        off_t nloc;
+       int kind;
 
 
-       switch (getfile(cp)) {
+       kind = getfile(cp);
+       if (Mflag)
+               printf("%s\n", filname);
+       switch (kind) {
 
        /*
         * Plain file.
 
        /*
         * Plain file.
@@ -550,7 +581,8 @@ load1arg(cp)
         * (Slowly) process each member.
         */
        case 1:
         * (Slowly) process each member.
         */
        case 1:
-               error(-1, "warning: archive has no table of contents");
+               error(-1,
+"warning: archive has no table of contents; add one using ranlib(1)");
                nloc = SARMAG;
                while (step(nloc))
                        nloc += sizeof(archdr) +
                nloc = SARMAG;
                while (step(nloc))
                        nloc += sizeof(archdr) +
@@ -602,7 +634,8 @@ load1arg(cp)
         * as a normal library (but skip the __.SYMDEF file).
         */
        case 3:
         * as a normal library (but skip the __.SYMDEF file).
         */
        case 3:
-               error(-1, "warning: table of contents is out of date");
+               error(-1,
+"warning: table of contents for archive is out of date; rerun ranlib(1)");
                nloc = SARMAG;
                do
                        nloc += sizeof(archdr) +
                nloc = SARMAG;
                do
                        nloc += sizeof(archdr) +
@@ -651,6 +684,8 @@ nextlibp(val)
                        error(1, "ran out of memory (nextlibp)");
        }
        clibseg->li_first[clibseg->li_used++] = val;
                        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);
 }
 
 /*
 }
 
 /*
@@ -792,7 +827,6 @@ middle()
        dorigin = 0; 
        borigin = 0;
 
        dorigin = 0; 
        borigin = 0;
 
-       p_data = *slookup("_data");
        p_etext = *slookup("_etext");
        p_edata = *slookup("_edata");
        p_end = *slookup("_end");
        p_etext = *slookup("_etext");
        p_edata = *slookup("_edata");
        p_end = *slookup("_end");
@@ -804,8 +838,7 @@ middle()
                for (i = 0; i < nsymt; i++) {
                        sp = xsym(i);
                        if (sp->n_type==N_EXT+N_UNDF && sp->n_value==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 && sp!=p_data) {
+                           sp!=p_end && sp!=p_edata && sp!=p_etext) {
                                rflag++;
                                dflag = 0;
                                break;
                                rflag++;
                                dflag = 0;
                                break;
@@ -824,7 +857,6 @@ middle()
            (nflag||zflag? PAGSIZ : sizeof (long)));
        database += hsize;
        if (dflag || rflag==0) {
            (nflag||zflag? PAGSIZ : sizeof (long)));
        database += hsize;
        if (dflag || rflag==0) {
-               ldrsym(p_data, (long)0 , N_EXT+N_DATA);
                ldrsym(p_etext, tsize, N_EXT+N_TEXT);
                ldrsym(p_edata, dsize, N_EXT+N_DATA);
                ldrsym(p_end, bsize, N_EXT+N_BSS);
                ldrsym(p_etext, tsize, N_EXT+N_TEXT);
                ldrsym(p_edata, dsize, N_EXT+N_DATA);
                ldrsym(p_end, bsize, N_EXT+N_BSS);
@@ -867,6 +899,8 @@ middle()
                case N_EXT+N_UNDF:
                        errlev |= 01;
                        if ((arflag==0 || dflag) && sp->n_value==0) {
                case N_EXT+N_UNDF:
                        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++;
                                if (nund==0)
                                        printf("Undefined:\n");
                                nund++;
@@ -896,7 +930,6 @@ middle()
        bsize += csize;
        nsym = ssize / (sizeof cursym);
        if (Aflag) {
        bsize += csize;
        nsym = ssize / (sizeof cursym);
        if (Aflag) {
-               fixspec(p_data,dorigin);
                fixspec(p_etext,torigin);
                fixspec(p_edata,dorigin);
                fixspec(p_end,borigin);
                fixspec(p_etext,torigin);
                fixspec(p_edata,dorigin);
                fixspec(p_end,borigin);
@@ -934,10 +967,15 @@ struct    biobuf toutb;
 setupout()
 {
        int bss;
 setupout()
 {
        int bss;
+       extern char *sys_errlist[];
+       extern int errno;
 
        biofd = creat(ofilename, 0666);
 
        biofd = creat(ofilename, 0666);
-       if (biofd < 0)
-               error(1, "cannot create output");
+       if (biofd < 0) {
+               filname = ofilename;            /* kludge */
+               archdr.ar_name[0] = 0;          /* kludge */
+               error(1, sys_errlist[errno]);   /* kludge */
+       }
        tout = &toutb;
        bopen(tout, 0);
        filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
        tout = &toutb;
        bopen(tout, 0);
        filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
@@ -1032,7 +1070,7 @@ long loc;
        int type;
 
        readhdr(loc);
        int type;
 
        readhdr(loc);
-       if(!funding) {
+       if (!funding) {
                ctrel = torigin;
                cdrel += dorigin;
                cbrel += borigin;
                ctrel = torigin;
                cdrel += dorigin;
                cbrel += borigin;
@@ -1091,6 +1129,14 @@ long loc;
                }
 /* end inline expansion of symreloc() */
                type = cursym.n_type;
                }
 /* 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))
                if ((type&N_EXT) == 0) {
                        if (!sflag&&!xflag&&
                            (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB))
@@ -1131,11 +1177,11 @@ long loc;
                return;
        dseek(&text, loc, filhdr.a_text);
        dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
                return;
        dseek(&text, loc, filhdr.a_text);
        dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
-       load2td(ctrel, tout, trout);
+       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);
        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, dout, drout);
+       load2td(cdrel, dorigin - database, dout, drout);
        while (filhdr.a_data & (sizeof(long)-1)) {
                bputc(0, dout);
                filhdr.a_data++;
        while (filhdr.a_data & (sizeof(long)-1)) {
                bputc(0, dout);
                filhdr.a_data++;
@@ -1146,15 +1192,66 @@ long loc;
        free(curstr);
 }
 
        free(curstr);
 }
 
-load2td(creloc, b1, b2)
-       long creloc;
+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,
+};
+
+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.
+ */
+load2td(creloc, position, b1, b2)
+       long creloc, offset;
        struct biobuf *b1, *b2;
 {
        register struct nlist *sp;
        register struct local *lp;
        long tw;
        register struct relocation_info *rp, *rpend;
        struct biobuf *b1, *b2;
 {
        register struct nlist *sp;
        register struct local *lp;
        long tw;
        register struct relocation_info *rp, *rpend;
-       long address;
        struct relocation_info *relp;
        char *codep;
        register char *cp;
        struct relocation_info *relp;
        char *codep;
        register char *cp;
@@ -1170,9 +1267,10 @@ load2td(creloc, b1, b2)
        rpend = &relp[relsz / sizeof (struct relocation_info)];
        mget(codep, codesz, &text);
        for (rp = relp; rp < rpend; rp++) {
        rpend = &relp[relsz / sizeof (struct relocation_info)];
        mget(codep, codesz, &text);
        for (rp = relp; rp < rpend; rp++) {
-               if (rflag)
-                       address = rp->r_address + creloc;
                cp = codep + rp->r_address;
                cp = codep + rp->r_address;
+               /*
+                * Pick up previous value at location to be relocated.
+                */
                switch (rp->r_length) {
 
                case 0:         /* byte */
                switch (rp->r_length) {
 
                case 0:         /* byte */
@@ -1190,7 +1288,19 @@ load2td(creloc, b1, b2)
                default:
                        error(1, "load2td botch: bad length");
                }
                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) {
                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;
                        lp = lochash[rp->r_symbolnum % LHSIZ];
                        while (lp->l_index != rp->r_symbolnum) {
                                lp = lp->l_link;
@@ -1206,7 +1316,11 @@ load2td(creloc, b1, b2)
                                rp->r_extern = 0;
                        }
                } else switch (rp->r_symbolnum & N_TYPE) {
                                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_TEXT:
                        tw += ctrel;
                        break;
@@ -1221,9 +1335,21 @@ load2td(creloc, b1, b2)
                default:
                        error(1, "relocation format botch (symbol type))");
                }
                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)
                if (rp->r_pcrel)
-                       /* assembler already subtracted text.pos */
                        tw -= creloc;
                        tw -= creloc;
+               /*
+                * Put the value back in the segment,
+                * while checking for overflow.
+                */
                switch (rp->r_length) {
 
                case 0:         /* byte */
                switch (rp->r_length) {
 
                case 0:         /* byte */
@@ -1240,8 +1366,15 @@ load2td(creloc, b1, b2)
                        *(long *)cp = tw;
                        break;
                }
                        *(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)
                if (rflag)
-                       rp->r_address = address;
+                       rp->r_address += position;
        }
        bwrite(codep, codesz, b1);
        if (rflag)
        }
        bwrite(codep, codesz, b1);
        if (rflag)
@@ -1263,7 +1396,8 @@ finishout()
        }
        if (!ofilfnd) {
                unlink("a.out");
        }
        if (!ofilfnd) {
                unlink("a.out");
-               link("l.out", "a.out");
+               if (link("l.out", "a.out") < 0)
+                       error(1, "cannot move l.out to a.out");
                ofilename = "a.out";
        }
        delarg = errlev;
                ofilename = "a.out";
        }
        delarg = errlev;
@@ -1425,10 +1559,10 @@ char *acp;
        archdr.ar_name[0] = '\0';
        filname = cp;
        if (cp[0]=='-' && cp[1]=='l') {
        archdr.ar_name[0] = '\0';
        filname = cp;
        if (cp[0]=='-' && cp[1]=='l') {
-               char *locfilname = "/usr/local/new/libxxxxxxxxxxxxxxx";
+               char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx";
                if(cp[2] == '\0')
                        cp = "-la";
                if(cp[2] == '\0')
                        cp = "-la";
-               filname = "/usr/new/libxxxxxxxxxxxxxxx";
+               filname = "/usr/lib/libxxxxxxxxxxxxxxx";
                for(c=0; cp[c+2]; c++) {
                        filname[c+12] = cp[c+2];
                        locfilname[c+18] = cp[c+2];
                for(c=0; cp[c+2]; c++) {
                        filname[c+12] = cp[c+2];
                        locfilname[c+18] = cp[c+2];
@@ -1622,6 +1756,7 @@ symreloc()
 error(n, s)
 char *s;
 {
 error(n, s)
 char *s;
 {
+
        if (errlev==0)
                printf("ld:");
        if (filname) {
        if (errlev==0)
                printf("ld:");
        if (filname) {