changed "pc - 1" to "pc" in getsrcpos, the source module has no business
[unix-history] / usr / src / old / ld / ld.c
index 5461967..18a17d0 100644 (file)
@@ -1,4 +1,5 @@
-static char sccsid[] = "@(#)ld.c 4.1 %G%";
+static char sccsid[] = "@(#)ld.c 4.7 %G%";
+
 /*
  * ld - string table version for VAX
  */
 /*
  * ld - string table version for VAX
  */
@@ -170,13 +171,19 @@ char      *tabstr;        /* string table for table of contents */
  * (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''.
  * (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
+ * work in hardware page sizes. The associated constants are defined 
+ * as BLKSIZE, BLKSHIFT, and BLKMASK.
  */
  */
+#define BLKSIZE 1024
+#define BLKSHIFT 10
+#define BLKMASK (BLKSIZE - 1)
 typedef struct {
        short   *fakeptr;
        int     bno;
        int     nibuf;
        int     nuser;
 typedef struct {
        short   *fakeptr;
        int     bno;
        int     nibuf;
        int     nuser;
-       char    buff[BSIZE];
+       char    buff[BLKSIZE];
 } PAGE;
 
 PAGE   page[2];
 } PAGE;
 
 PAGE   page[2];
@@ -298,6 +305,7 @@ off_t       offset = sizeof (off_t);
 
 int    ofilfnd;                /* -o given; otherwise move l.out to a.out */
 char   *ofilename = "l.out";
 
 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 */
 
 int    infil;                  /* current input file descriptor */
 char   *filname;               /* and its name */
 
@@ -488,11 +496,28 @@ htoi(p)
 
 delexit()
 {
 
 delexit()
 {
+       struct stat stbuf;
+       long size;
+       char c = 0;
 
        bflush();
        unlink("l.out");
        if (delarg==0 && Aflag==0)
 
        bflush();
        unlink("l.out");
        if (delarg==0 && Aflag==0)
-               chmod(ofilename, 0777 &~ umask(0));
+               chmod(ofilename, ofilemode);
+       /*
+        * We have to insure that the last block of the data segment
+        * is allocated a full BLKSIZE block. If the underlying
+        * file system allocates frags that are smaller than BLKSIZE,
+        * a full zero filled BLKSIZE 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, BLKSIZE);
+       if (!rflag && size > stbuf.st_size) {
+               lseek(biofd, size - 1, 0);
+               write(biofd, &c, 1);
+       }
        exit (delarg);
 }
 
        exit (delarg);
 }
 
@@ -897,7 +922,8 @@ middle()
                switch (sp->n_type & (N_TYPE+N_EXT)) {
 
                case N_EXT+N_UNDF:
                switch (sp->n_type & (N_TYPE+N_EXT)) {
 
                case N_EXT+N_UNDF:
-                       errlev |= 01;
+                       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 ((arflag==0 || dflag) && sp->n_value==0) {
                                if (sp==p_end || sp==p_etext || sp==p_edata)
                                        continue;
@@ -970,11 +996,19 @@ setupout()
        extern char *sys_errlist[];
        extern int errno;
 
        extern char *sys_errlist[];
        extern int errno;
 
-       biofd = creat(ofilename, 0666);
+       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 */
        if (biofd < 0) {
                filname = ofilename;            /* kludge */
                archdr.ar_name[0] = 0;          /* kludge */
                error(1, sys_errlist[errno]);   /* kludge */
+       } else {
+               struct stat mybuf;              /* kls kludge */
+               fstat(biofd, &mybuf);           /* suppose file exists, wrong*/
+               if(mybuf.st_mode & 0111) {      /* mode, ld fails? */
+                       chmod(ofilename, mybuf.st_mode & 0666);
+                       ofilemode = mybuf.st_mode;
+               }
        }
        tout = &toutb;
        bopen(tout, 0);
        }
        tout = &toutb;
        bopen(tout, 0);
@@ -1187,8 +1221,8 @@ long loc;
                filhdr.a_data++;
        }
        torigin += filhdr.a_text;
                filhdr.a_data++;
        }
        torigin += filhdr.a_text;
-       dorigin += filhdr.a_data;
-       borigin += filhdr.a_bss;
+       dorigin += round(filhdr.a_data, sizeof (long));
+       borigin += round(filhdr.a_bss, sizeof (long));
        free(curstr);
 }
 
        free(curstr);
 }
 
@@ -1456,15 +1490,15 @@ top:
                goto top;
        }
        if (n > BUFSIZ) {
                goto top;
        }
        if (n > BUFSIZ) {
-               take = n - n % BSIZE;
-               lseek(infil, (sp->bno+1)*BSIZE, 0);
+               take = n - n % BLKSIZE;
+               lseek(infil, (sp->bno+1)*BLKSIZE, 0);
                if (take > sp->size || read(infil, loc, take) != take)
                        error(1, "premature EOF");
                loc += take;
                n -= take;
                sp->size -= take;
                sp->pos += take;
                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/BSIZE)*BSIZE, -1);
+               dseek(sp, (sp->bno+1+take/BLKSIZE)*BLKSIZE, -1);
                goto top;
        }
        *loc++ = get(sp);
                goto top;
        }
        *loc++ = get(sp);
@@ -1498,8 +1532,8 @@ long loc, s;
        register b, o;
        int n;
 
        register b, o;
        int n;
 
-       b = loc>>BSHIFT;
-       o = loc&BMASK;
+       b = loc>>BLKSHIFT;
+       o = loc&BLKMASK;
        if (o&01)
                error(1, "loader error; odd offset");
        --sp->pno->nuser;
        if (o&01)
                error(1, "loader error; odd offset");
        --sp->pno->nuser;
@@ -1509,7 +1543,7 @@ long loc, s;
                                if (page[0].bno < page[1].bno)
                                        p = &page[0];
                        p->bno = b;
                                if (page[0].bno < page[1].bno)
                                        p = &page[0];
                        p->bno = b;
-                       lseek(infil, loc & ~(long)BMASK, 0);
+                       lseek(infil, loc & ~(long)BLKMASK, 0);
                        if ((n = read(infil, p->buff, sizeof(p->buff))) < 0)
                                n = 0;
                        p->nibuf = n;
                        if ((n = read(infil, p->buff, sizeof(p->buff))) < 0)
                                n = 0;
                        p->nibuf = n;
@@ -1532,7 +1566,7 @@ STREAM *asp;
 
        sp = asp;
        if ((sp->nibuf -= sizeof(char)) < 0) {
 
        sp = asp;
        if ((sp->nibuf -= sizeof(char)) < 0) {
-               dseek(sp, ((long)(sp->bno+1)<<BSHIFT), (long)-1);
+               dseek(sp, ((long)(sp->bno+1)<<BLKSHIFT), (long)-1);
                sp->nibuf -= sizeof(char);
        }
        if ((sp->size -= sizeof(char)) <= 0) {
                sp->nibuf -= sizeof(char);
        }
        if ((sp->size -= sizeof(char)) <= 0) {