]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: add -B option to set build ID
authorIan Lance Taylor <iant@golang.org>
Tue, 9 Oct 2012 22:29:43 +0000 (15:29 -0700)
committerIan Lance Taylor <iant@golang.org>
Tue, 9 Oct 2012 22:29:43 +0000 (15:29 -0700)
Background on build ID:
http://fedoraproject.org/wiki/RolandMcGrath/BuildID

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

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

index 463e3bfa33c04993855d8e9036c67a538a21e11e..b114309d45c05d97fb46e4d7b45456e8742a63fc 100644 (file)
@@ -79,6 +79,7 @@ enum {
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
        ElfStrNoteOpenbsdIdent,
+       ElfStrNoteBuildInfo,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -523,6 +524,8 @@ doelf(void)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        if(HEADTYPE == Hopenbsd)
                elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
+       if(buildinfolen > 0)
+               elfstr[ElfStrNoteBuildInfo] = addstring(shstrtab, ".note.gnu.build-id");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
        addstring(shstrtab, ".gcbss");
@@ -669,7 +672,7 @@ asmb(void)
        int a, dynsym;
        uint32 fo, symo, startva, resoff;
        ElfEhdr *eh;
-       ElfPhdr *ph, *pph;
+       ElfPhdr *ph, *pph, *pnote;
        ElfShdr *sh;
        Section *sect;
        int o;
@@ -706,6 +709,8 @@ asmb(void)
                }
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
+               if(buildinfolen > 0)
+                       elftextsh += 1;
        }
 
        /* output symbol table */
@@ -876,6 +881,7 @@ asmb(void)
                        phsh(ph, sh);
                }
 
+               pnote = nil;
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
                        sh = nil;
                        switch(HEADTYPE) {
@@ -889,10 +895,22 @@ asmb(void)
                                break;
                        }
 
-                       ph = newElfPhdr();
-                       ph->type = PT_NOTE;
-                       ph->flags = PF_R;
-                       phsh(ph, sh);
+                       pnote = newElfPhdr();
+                       pnote->type = PT_NOTE;
+                       pnote->flags = PF_R;
+                       phsh(pnote, sh);
+               }
+
+               if(buildinfolen > 0) {
+                       sh = newElfShdr(elfstr[ElfStrNoteBuildInfo]);
+                       resoff -= elfbuildinfo(sh, startva, resoff);
+
+                       if(pnote == nil) {
+                               pnote = newElfPhdr();
+                               pnote->type = PT_NOTE;
+                               pnote->flags = PF_R;
+                       }
+                       phsh(pnote, sh);
                }
 
                elfphload(&segtext);
@@ -1079,6 +1097,8 @@ asmb(void)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
                if(HEADTYPE == Hopenbsd)
                        a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
+               if(buildinfolen > 0)
+                       a += elfwritebuildinfo(elfstr[ElfStrNoteBuildInfo]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index 7e229ac17ea6cb043fd218b66116ca5c6abf016f..4a7ccc63f78724f6025a97ba782537be4e483aeb 100644 (file)
@@ -143,6 +143,10 @@ main(int argc, char *argv[])
                val = EARGF(usage());
                addstrdata(name, val);
                break;
+       case 'B':
+               val = EARGF(usage());
+               addbuildinfo(val);
+               break;
        } ARGEND
 
        USED(argc);
index 8af86066036b74138579fdf63df84c2926dfc5b6..67ab63b3e2a3f331dfa01787584e6105837da691 100644 (file)
@@ -96,6 +96,7 @@ enum {
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
        ElfStrNoteOpenbsdIdent,
+       ElfStrNoteBuildInfo,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -597,6 +598,8 @@ doelf(void)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        if(HEADTYPE == Hopenbsd)
                elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
+       if(buildinfolen > 0)
+               elfstr[ElfStrNoteBuildInfo] = addstring(shstrtab, ".note.gnu.build-id");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
@@ -734,7 +737,7 @@ asmb(void)
        int a, dynsym;
        vlong vl, startva, symo, dwarfoff, machlink, resoff;
        ElfEhdr *eh;
-       ElfPhdr *ph, *pph;
+       ElfPhdr *ph, *pph, *pnote;
        ElfShdr *sh;
        Section *sect;
        Sym *sym;
@@ -807,6 +810,8 @@ asmb(void)
                }
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
+               if(buildinfolen > 0)
+                       elftextsh += 1;
                break;
        case Hwindows:
                break;
@@ -976,6 +981,7 @@ asmb(void)
                        phsh(ph, sh);
                }
 
+               pnote = nil;
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
                        sh = nil;
                        switch(HEADTYPE) {
@@ -989,10 +995,22 @@ asmb(void)
                                break;
                        }
 
-                       ph = newElfPhdr();
-                       ph->type = PT_NOTE;
-                       ph->flags = PF_R;
-                       phsh(ph, sh);
+                       pnote = newElfPhdr();
+                       pnote->type = PT_NOTE;
+                       pnote->flags = PF_R;
+                       phsh(pnote, sh);
+               }
+
+               if(buildinfolen > 0) {
+                       sh = newElfShdr(elfstr[ElfStrNoteBuildInfo]);
+                       resoff -= elfbuildinfo(sh, startva, resoff);
+
+                       if(pnote == nil) {
+                               pnote = newElfPhdr();
+                               pnote->type = PT_NOTE;
+                               pnote->flags = PF_R;
+                       }
+                       phsh(pnote, sh);
                }
 
                elfphload(&segtext);
@@ -1179,6 +1197,8 @@ asmb(void)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
                if(HEADTYPE == Hopenbsd)
                        a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
+               if(buildinfolen > 0)
+                       a += elfwritebuildinfo(elfstr[ElfStrNoteBuildInfo]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index cfce2111b824a3c573f6c5ba9251d8f0911d60f0..5987310f9514ef21df448167a80ecdce7a0fe260 100644 (file)
@@ -140,6 +140,10 @@ main(int argc, char *argv[])
                val = EARGF(usage());
                addstrdata(name, val);
                break;
+       case 'B':
+               val = EARGF(usage());
+               addbuildinfo(val);
+               break;
        } ARGEND
 
        if(argc != 1)
index 44cd77cbac4793431ebf61e3bf70e16dbaf1831e..06f974a757f59aae9dd865be2370da67a95efbe0 100644 (file)
@@ -92,6 +92,7 @@ enum {
        ElfStrGnuVersionR,
        ElfStrNoteNetbsdIdent,
        ElfStrNoteOpenbsdIdent,
+       ElfStrNoteBuildInfo,
        ElfStrNoPtrData,
        ElfStrNoPtrBss,
        NElfStr
@@ -573,6 +574,8 @@ doelf(void)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        if(HEADTYPE == Hopenbsd)
                elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
+       if(buildinfolen > 0)
+               elfstr[ElfStrNoteBuildInfo] = addstring(shstrtab, ".note.gnu.build-id");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
        addstring(shstrtab, ".gcdata");
@@ -710,7 +713,7 @@ asmb(void)
        int a, dynsym;
        uint32 symo, startva, dwarfoff, machlink, resoff;
        ElfEhdr *eh;
-       ElfPhdr *ph, *pph;
+       ElfPhdr *ph, *pph, *pnote;
        ElfShdr *sh;
        Section *sect;
        Sym *sym;
@@ -764,6 +767,8 @@ asmb(void)
                }
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
                        elftextsh += 1;
+               if(buildinfolen > 0)
+                       elftextsh += 1;
        }
 
        symsize = 0;
@@ -1036,6 +1041,7 @@ asmb(void)
                        phsh(ph, sh);
                }
 
+               pnote = nil;
                if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
                        sh = nil;
                        switch(HEADTYPE) {
@@ -1049,10 +1055,22 @@ asmb(void)
                                break;
                        }
 
-                       ph = newElfPhdr();
-                       ph->type = PT_NOTE;
-                       ph->flags = PF_R;
-                       phsh(ph, sh);
+                       pnote = newElfPhdr();
+                       pnote->type = PT_NOTE;
+                       pnote->flags = PF_R;
+                       phsh(pnote, sh);
+               }
+
+               if(buildinfolen > 0) {
+                       sh = newElfShdr(elfstr[ElfStrNoteBuildInfo]);
+                       resoff -= elfbuildinfo(sh, startva, resoff);
+
+                       if(pnote == nil) {
+                               pnote = newElfPhdr();
+                               pnote->type = PT_NOTE;
+                               pnote->flags = PF_R;
+                       }
+                       phsh(pnote, sh);
                }
 
                // Additions to the reserved area must be above this line.
@@ -1249,6 +1267,8 @@ asmb(void)
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
                if(HEADTYPE == Hopenbsd)
                        a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
+               if(buildinfolen > 0)
+                       a += elfwritebuildinfo(elfstr[ElfStrNoteBuildInfo]);
                if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
index 648fef1ab0bcefae585cde3236acc84d787fb821..773a6ddfb16ab7934c24d9378c529aa8e48ca641 100644 (file)
@@ -145,6 +145,10 @@ main(int argc, char *argv[])
                val = EARGF(usage());
                addstrdata(name, val);
                break;
+       case 'B':
+               val = EARGF(usage());
+               addbuildinfo(val);
+               break;
        } ARGEND
 
        if(argc != 1)
index 539448d27645d08fb79d306ee51e54eb249143f1..a4977d581c773a222b3fbf6d755fad70d88a75d8 100644 (file)
@@ -58,5 +58,8 @@ Options new in this version:
                as displayed in the symbol table printed by "go tool nm".
        -b
                Link with race detection libraries.
+       -B value
+               Add a NT_GNU_BUILD_ID note when using ELF.  The value
+               should start with 0x and be an even number of hex digits.
 */
 package documentation
index 7e46c2767cd0b2ddb3d0f4b3c7ccb80a154cc2de..7fa41e237235bba80b7bc042901430d205a4789a 100644 (file)
@@ -31,6 +31,8 @@ struct Elfstring
 static Elfstring elfstr[100];
 static int nelfstr;
 
+static char buildinfo[32];
+
 /*
  Initialize the global variable that describes the ELF header. It will be updated as
  we write section and prog headers.
@@ -455,6 +457,77 @@ elfwriteopenbsdsig(vlong stridx)
        return sh->size;
 }
 
+void
+addbuildinfo(char *val)
+{
+       char *ov;
+       int i, b, j;
+
+       if(val[0] != '0' || val[1] != 'x') {
+               fprint(2, "%s: -B argument must start with 0x: %s\n", argv0, val);
+               exits("usage");
+       }
+       ov = val;
+       val += 2;
+       i = 0;
+       while(*val != '\0') {
+               if(val[1] == '\0') {
+                       fprint(2, "%s: -B argument must have even number of digits: %s\n", argv0, ov);
+                       exits("usage");
+               }
+               b = 0;
+               for(j = 0; j < 2; j++, val++) {
+                       b *= 16;
+                       if(*val >= '0' && *val <= '9')
+                               b += *val - '0';
+                       else if(*val >= 'a' && *val <= 'f')
+                               b += *val - 'a' + 10;
+                       else if(*val >= 'A' && *val <= 'F')
+                               b += *val - 'A' + 10;
+                       else {
+                               fprint(2, "%s: -B argument contains invalid hex digit %c: %s\n", argv0, *val, ov);
+                               exits("usage");
+                       }
+               }
+               if(i >= nelem(buildinfo)) {
+                       fprint(2, "%s: -B option too long (max %d digits): %s\n", argv0, (int)nelem(buildinfo), ov);
+                       exits("usage");
+               }
+               buildinfo[i++] = b;
+       }
+       buildinfolen = i;
+}
+
+// Build info note
+#define ELF_NOTE_BUILDINFO_NAMESZ      4
+#define ELF_NOTE_BUILDINFO_TAG         3
+#define ELF_NOTE_BUILDINFO_NAME                "GNU\0"
+
+int
+elfbuildinfo(ElfShdr *sh, uint64 startva, uint64 resoff)
+{
+       int n;
+
+       n = ELF_NOTE_BUILDINFO_NAMESZ + rnd(buildinfolen, 4);
+       return elfnote(sh, startva, resoff, n);
+}
+
+int
+elfwritebuildinfo(vlong stridx)
+{
+       ElfShdr *sh;
+
+       sh = elfwritenotehdr(stridx, ELF_NOTE_BUILDINFO_NAMESZ, buildinfolen, ELF_NOTE_BUILDINFO_TAG);
+       if(sh == nil)
+               return 0;
+
+       cwrite(ELF_NOTE_BUILDINFO_NAME, ELF_NOTE_BUILDINFO_NAMESZ);
+       cwrite(buildinfo, buildinfolen);
+       cwrite("\0\0\0", rnd(buildinfolen, 4) - buildinfolen);
+
+       return sh->size;
+}
+
 extern int nelfsym;
 int elfverneed;
 
index f5d0713e48c2577519ed1859d1b0a87a20e242ce..3eb13ae398d71f460ee4850a5c722059f2440c67 100644 (file)
@@ -979,6 +979,9 @@ int elfnetbsdsig(ElfShdr*, uint64, uint64);
 int    elfwritenetbsdsig(vlong);
 int    elfopenbsdsig(ElfShdr*, uint64, uint64);
 int    elfwriteopenbsdsig(vlong);
+void   addbuildinfo(char*);
+int    elfbuildinfo(ElfShdr*, uint64, uint64);
+int    elfwritebuildinfo(vlong);
 void   elfdynhash(void);
 ElfPhdr* elfphload(Segment*);
 ElfShdr* elfshbits(Section*);
@@ -988,6 +991,7 @@ void        elfaddverneed(Sym*);
 EXTERN int     elfstrsize;
 EXTERN char*   elfstrdat;
 EXTERN int     elftextsh;
+EXTERN int     buildinfolen;
 
 /*
  * Total amount of space to reserve at the start of the file