]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/{ld,5l,6l,8l}: add support for OpenBSD ELF signatures
authorJoel Sing <jsing@google.com>
Fri, 21 Sep 2012 02:51:39 +0000 (12:51 +1000)
committerJoel Sing <jsing@google.com>
Fri, 21 Sep 2012 02:51:39 +0000 (12:51 +1000)
OpenBSD now requires ELF binaries to have a PT_NOTE that identifies
it as an OpenBSD binary. Refactor the existing NetBSD ELF signature
code and implement support for OpenBSD ELF signatures.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6489131

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

index f31c2f734fe94b28124bd1498aa8377202a6606d..b265a15cdb440c21e5700c95515dcfeb1db5ce96 100644 (file)
@@ -77,6 +77,7 @@ enum {
        ElfStrGnuVersion,
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
+       ElfStrNoteOpenbsdIdent,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -504,6 +505,8 @@ doelf(void)
        elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
        if(HEADTYPE == Hnetbsd)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
+       if(HEADTYPE == Hopenbsd)
+               elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
        addstring(shstrtab, ".gcbss");
@@ -685,7 +688,7 @@ asmb(void)
                        if(elfverneed)
                                elftextsh += 2;
                }
-               if(HEADTYPE == Hnetbsd)
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
        }
 
@@ -846,12 +849,18 @@ asmb(void)
                        phsh(ph, sh);
                }
 
-               if(HEADTYPE == Hnetbsd) {
-                       sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-                       sh->type = SHT_NOTE;
-                       sh->flags = SHF_ALLOC;
-                       sh->addralign = 4;
-                       resoff -= elfnetbsdsig(sh, startva, resoff);
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
+                       sh = nil;
+                       switch(HEADTYPE) {
+                       case Hnetbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+                               resoff -= elfnetbsdsig(sh, startva, resoff);
+                               break;
+                       case Hopenbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
+                               resoff -= elfopenbsdsig(sh, startva, resoff);
+                               break;
+                       }
 
                        ph = newElfPhdr();
                        ph->type = PT_NOTE;
@@ -1027,6 +1036,8 @@ asmb(void)
                a += elfwriteinterp(elfstr[ElfStrInterp]);
                if(HEADTYPE == Hnetbsd)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+               if(HEADTYPE == Hopenbsd)
+                       a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index 3b7feeca431000b5aa9c77c5c98b548976f24980..05732d081d8ea3782e635e9a0e3bcdf18612d914 100644 (file)
@@ -95,6 +95,7 @@ enum {
        ElfStrGnuVersion,
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
+       ElfStrNoteOpenbsdIdent,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -577,6 +578,8 @@ doelf(void)
        elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
        if(HEADTYPE == Hnetbsd)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
+       if(HEADTYPE == Hopenbsd)
+               elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
@@ -785,7 +788,7 @@ asmb(void)
                        if(elfverneed)
                                elftextsh += 2;
                }
-               if(HEADTYPE == Hnetbsd)
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
                break;
        case Hwindows:
@@ -956,12 +959,18 @@ asmb(void)
                        phsh(ph, sh);
                }
 
-               if(HEADTYPE == Hnetbsd) {
-                       sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-                       sh->type = SHT_NOTE;
-                       sh->flags = SHF_ALLOC;
-                       sh->addralign = 4;
-                       resoff -= elfnetbsdsig(sh, startva, resoff);
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
+                       sh = nil;
+                       switch(HEADTYPE) {
+                       case Hnetbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+                               resoff -= elfnetbsdsig(sh, startva, resoff);
+                               break;
+                       case Hopenbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
+                               resoff -= elfopenbsdsig(sh, startva, resoff);
+                               break;
+                       }
 
                        ph = newElfPhdr();
                        ph->type = PT_NOTE;
@@ -1151,6 +1160,8 @@ asmb(void)
                a += elfwriteinterp(elfstr[ElfStrInterp]);
                if(HEADTYPE == Hnetbsd)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+               if(HEADTYPE == Hopenbsd)
+                       a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index 87888d2bb249470caae8eb3267a20fc7af0016de..4d7734f046c35e3c6abe4b9cf0a62850ea7abcfa 100644 (file)
@@ -91,6 +91,7 @@ enum {
        ElfStrGnuVersion,
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
+       ElfStrNoteOpenbsdIdent,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -534,6 +535,8 @@ doelf(void)
        elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
        if(HEADTYPE == Hnetbsd)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
+       if(HEADTYPE == Hopenbsd)
+               elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
@@ -723,7 +726,7 @@ asmb(void)
                        if(elfverneed)
                                elftextsh += 2;
                }
-               if(HEADTYPE == Hnetbsd)
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
        }
 
@@ -997,12 +1000,18 @@ asmb(void)
                        phsh(ph, sh);
                }
 
-               if(HEADTYPE == Hnetbsd) {
-                       sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-                       sh->type = SHT_NOTE;
-                       sh->flags = SHF_ALLOC;
-                       sh->addralign = 4;
-                       resoff -= elfnetbsdsig(sh, startva, resoff);
+               if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
+                       sh = nil;
+                       switch(HEADTYPE) {
+                       case Hnetbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+                               resoff -= elfnetbsdsig(sh, startva, resoff);
+                               break;
+                       case Hopenbsd:
+                               sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
+                               resoff -= elfopenbsdsig(sh, startva, resoff);
+                               break;
+                       }
 
                        ph = newElfPhdr();
                        ph->type = PT_NOTE;
@@ -1202,6 +1211,8 @@ asmb(void)
                a += elfwriteinterp(elfstr[ElfStrInterp]);
                if(HEADTYPE == Hnetbsd)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+               if(HEADTYPE == Hopenbsd)
+                       a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index a4829da4e885c4d300ab9970fcbb6f2401a78682..7e46c2767cd0b2ddb3d0f4b3c7ccb80a154cc2de 100644 (file)
@@ -351,20 +351,16 @@ elfwriteinterp(vlong stridx)
        return sh->size;
 }
 
-// Defined in NetBSD's sys/exec_elf.h
-#define ELF_NOTE_TYPE_NETBSD_TAG       1
-#define ELF_NOTE_NETBSD_NAMESZ         7
-#define ELF_NOTE_NETBSD_DESCSZ         4
-#define ELF_NOTE_NETBSD_NAME           "NetBSD\0\0"
-#define ELF_NOTE_NETBSD_VERSION                599000000       /* NetBSD 5.99 */
-
 int
-elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
+elfnote(ElfShdr *sh, uint64 startva, uint64 resoff, int sz)
 {
-       int n;
+       uint64 n;
 
-       n = sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
-       n += resoff % 4;
+       n = sizeof(Elf_Note) + sz + resoff % 4;
+
+       sh->type = SHT_NOTE;
+       sh->flags = SHF_ALLOC;
+       sh->addralign = 4;
        sh->addr = startva + resoff - n;
        sh->off = resoff - n;
        sh->size = n;
@@ -372,8 +368,9 @@ elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
        return n;
 }
 
-int
-elfwritenetbsdsig(vlong stridx) {
+ElfShdr *
+elfwritenotehdr(vlong stridx, uint32 namesz, uint32 descsz, uint32 tag)
+{
        ElfShdr *sh = nil;
        int i;
 
@@ -381,19 +378,83 @@ elfwritenetbsdsig(vlong stridx) {
                if(shdr[i]->name == stridx)
                        sh = shdr[i];
        if(sh == nil)
-               return 0;
+               return nil;
 
-       // Write Elf_Note header followed by NetBSD string.
+       // Write Elf_Note header.
        cseek(sh->off);
-       LPUT(ELF_NOTE_NETBSD_NAMESZ);
-       LPUT(ELF_NOTE_NETBSD_DESCSZ);
-       LPUT(ELF_NOTE_TYPE_NETBSD_TAG);
-       cwrite(ELF_NOTE_NETBSD_NAME, 8);
+       LPUT(namesz);
+       LPUT(descsz);
+       LPUT(tag);
+
+       return sh;
+}
+
+// NetBSD Signature (as per sys/exec_elf.h)
+#define ELF_NOTE_NETBSD_NAMESZ         7
+#define ELF_NOTE_NETBSD_DESCSZ         4
+#define ELF_NOTE_NETBSD_TAG            1
+#define ELF_NOTE_NETBSD_NAME           "NetBSD\0\0"
+#define ELF_NOTE_NETBSD_VERSION                599000000       /* NetBSD 5.99 */
+
+int
+elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
+{
+       int n;
+
+       n = ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
+       return elfnote(sh, startva, resoff, n);
+}
+
+int
+elfwritenetbsdsig(vlong stridx)
+{
+       ElfShdr *sh;
+
+       // Write Elf_Note header.
+       sh = elfwritenotehdr(stridx, ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG);
+       if(sh == nil)
+               return 0;
+
+       // Followed by NetBSD string and version.
+       cwrite(ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ + 1);
        LPUT(ELF_NOTE_NETBSD_VERSION);
 
        return sh->size;
 }
 
+// OpenBSD Signature
+#define ELF_NOTE_OPENBSD_NAMESZ                8
+#define ELF_NOTE_OPENBSD_DESCSZ                4
+#define ELF_NOTE_OPENBSD_TAG           1
+#define ELF_NOTE_OPENBSD_NAME          "OpenBSD\0"
+#define ELF_NOTE_OPENBSD_VERSION       0
+
+int
+elfopenbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
+{
+       int n;
+
+       n = ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ;
+       return elfnote(sh, startva, resoff, n);
+}
+
+int
+elfwriteopenbsdsig(vlong stridx)
+{
+       ElfShdr *sh;
+
+       // Write Elf_Note header.
+       sh = elfwritenotehdr(stridx, ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG);
+       if(sh == nil)
+               return 0;
+
+       // Followed by OpenBSD string and version.
+       cwrite(ELF_NOTE_OPENBSD_NAME, ELF_NOTE_OPENBSD_NAMESZ);
+       LPUT(ELF_NOTE_OPENBSD_VERSION);
+
+       return sh->size;
+}
+
 extern int nelfsym;
 int elfverneed;
 
index 13c3d4da1f599550efb8f2e0a6d530941d16d26f..8568548a91b3492704f32fe20e01a4090a48bcf2 100644 (file)
@@ -976,6 +976,8 @@ int elfinterp(ElfShdr*, uint64, uint64, char*);
 int    elfwriteinterp(vlong);
 int    elfnetbsdsig(ElfShdr*, uint64, uint64);
 int    elfwritenetbsdsig(vlong);
+int    elfopenbsdsig(ElfShdr*, uint64, uint64);
+int    elfwriteopenbsdsig(vlong);
 void   elfdynhash(void);
 ElfPhdr* elfphload(Segment*);
 ElfShdr* elfshbits(Section*);