]> Cypherpunks repositories - gostls13.git/commitdiff
ld: move interpreter string into first block of ELF file
authorRuss Cox <rsc@golang.org>
Wed, 18 Nov 2009 21:51:05 +0000 (13:51 -0800)
committerRuss Cox <rsc@golang.org>
Wed, 18 Nov 2009 21:51:05 +0000 (13:51 -0800)
necessary on freebsd.

R=r, dho
CC=golang-dev
https://golang.org/cl/157069

src/cmd/6l/asm.c
src/cmd/8l/asm.c
src/cmd/ld/elf.c
src/cmd/ld/elf.h

index 3679e5cf4054d73555d2d85f35090c8ffc444c4a..4f7f6e22fe5b509fe9d08915f3426e56fbd89026 100644 (file)
@@ -315,19 +315,6 @@ doelf(void)
                elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
                elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
 
-               /* interpreter string */
-               s = lookup(".interp", 0);
-               s->reachable = 1;
-               s->type = SDATA;        // TODO: rodata
-               switch(HEADTYPE) {
-               case 7:
-                       addstring(lookup(".interp", 0), linuxdynld);
-                       break;
-               case 9:
-                       addstring(lookup(".interp", 0), freebsddynld);
-                       break;
-               }
-
                /*
                 * hash table.
                 * only entries that other objects need to find when
@@ -688,7 +675,14 @@ asmb(void)
                        sh->type = SHT_PROGBITS;
                        sh->flags = SHF_ALLOC;
                        sh->addralign = 1;
-                       shsym(sh, lookup(".interp", 0));
+                       switch(HEADTYPE) {
+                       case 7:
+                               elfinterp(sh, startva, linuxdynld);
+                               break;
+                       case 9:
+                               elfinterp(sh, startva, freebsddynld);
+                               break;
+                       }
 
                        ph = newElfPhdr();
                        ph->type = PT_INTERP;
@@ -903,7 +897,8 @@ asmb(void)
                a += elfwritehdr();
                a += elfwritephdrs();
                a += elfwriteshdrs();
-               if (a > ELFRESERVE)
+               cflush();
+               if(a+elfwriteinterp() > ELFRESERVE)
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
        }
index e496672e56653eeb95cf1826fe272b3daf5536fc..689ba12d92610b8ddf5e3ac4c988abe9c70e2b19 100644 (file)
@@ -304,14 +304,6 @@ doelf(void)
                s = lookup(".interp", 0);
                s->reachable = 1;
                s->type = SDATA;        // TODO: rodata
-               switch(HEADTYPE) {
-               case 7:
-                       addstring(lookup(".interp", 0), linuxdynld);
-                       break;
-               case 9:
-                       addstring(lookup(".interp", 0), freebsddynld);
-                       break;
-               }
 
                /*
                 * hash table - empty for now.
@@ -794,7 +786,14 @@ asmb(void)
                        sh->type = SHT_PROGBITS;
                        sh->flags = SHF_ALLOC;
                        sh->addralign = 1;
-                       shsym(sh, lookup(".interp", 0));
+                       switch(HEADTYPE) {
+                       case 7:
+                               elfinterp(sh, startva, linuxdynld);
+                               break;
+                       case 9:
+                               elfinterp(sh, startva, freebsddynld);
+                               break;
+                       }
 
                        ph = newElfPhdr();
                        ph->type = PT_INTERP;
@@ -1012,10 +1011,9 @@ asmb(void)
                a += elfwritehdr();
                a += elfwritephdrs();
                a += elfwriteshdrs();
-               if (a > ELFRESERVE) {
-                       diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
-               }
                cflush();
+               if(a+elfwriteinterp() > ELFRESERVE)
+                       diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
        }
        cflush();
index f4809e07cf70a579195a2413eff4060b8809215e..c57630e8081b75d1466fddf5820f99563d6db2dc 100644 (file)
@@ -17,6 +17,7 @@ static        int     elf64;
 static ElfEhdr hdr;
 static ElfPhdr *phdr[NSECT];
 static ElfShdr *shdr[NSECT];
+static char    *interp;
 
 /*
  Initialize the global variable that describes the ELF header. It will be updated as
@@ -278,3 +279,29 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t)
                adduint32(s, tag);
        addsize(s, t);
 }
+
+int
+elfwriteinterp(void)
+{
+       int n;
+       
+       if(interp == nil)
+               return 0;
+
+       n = strlen(interp)+1;
+       seek(cout, ELFRESERVE-n, 0);
+       write(cout, interp, n);
+       return n;
+}
+
+void
+elfinterp(ElfShdr *sh, uint64 startva, char *p)
+{
+       int n;
+       
+       interp = p;
+       n = strlen(interp)+1;
+       sh->addr = startva + ELFRESERVE - n;
+       sh->off = ELFRESERVE - n;
+       sh->size = n;
+}
index e0c2bd1b6ce9c5f1425c36165e4c9d9d93d0d221..9f18ec3ddc47309a78ce59dff9e018616979727c 100644 (file)
@@ -961,11 +961,14 @@ uint64    startelf(void);
 uint64 endelf(void);
 extern int     numelfphdr;
 extern int     numelfshdr;
+int    elfwriteinterp(void);
+void   elfinterp(ElfShdr*, uint64, char*);
 
 /*
  * Total amount of space to reserve at the start of the file
- * for Header, PHeaders, and SHeaders.
+ * for Header, PHeaders, SHeaders, and interp.
  * May waste some.
+ * On FreeBSD, cannot be larger than a page.
  */
 #define        ELFRESERVE      2048