mirror of
https://github.com/golang/go
synced 2024-11-21 19:54:41 -07:00
cmd/{ld,5l,6l,8l}: add support for OpenBSD ELF signatures
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
This commit is contained in:
parent
9773ac1d08
commit
31758b2c1a
@ -77,6 +77,7 @@ enum {
|
|||||||
ElfStrGnuVersion,
|
ElfStrGnuVersion,
|
||||||
ElfStrGnuVersionR,
|
ElfStrGnuVersionR,
|
||||||
ElfStrNoteNetbsdIdent,
|
ElfStrNoteNetbsdIdent,
|
||||||
|
ElfStrNoteOpenbsdIdent,
|
||||||
ElfStrNoPtrData,
|
ElfStrNoPtrData,
|
||||||
ElfStrNoPtrBss,
|
ElfStrNoPtrBss,
|
||||||
NElfStr
|
NElfStr
|
||||||
@ -504,6 +505,8 @@ doelf(void)
|
|||||||
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
|
||||||
addstring(shstrtab, ".rodata");
|
addstring(shstrtab, ".rodata");
|
||||||
addstring(shstrtab, ".gcdata");
|
addstring(shstrtab, ".gcdata");
|
||||||
addstring(shstrtab, ".gcbss");
|
addstring(shstrtab, ".gcbss");
|
||||||
@ -685,7 +688,7 @@ asmb(void)
|
|||||||
if(elfverneed)
|
if(elfverneed)
|
||||||
elftextsh += 2;
|
elftextsh += 2;
|
||||||
}
|
}
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
|
||||||
elftextsh += 1;
|
elftextsh += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,12 +849,18 @@ asmb(void)
|
|||||||
phsh(ph, sh);
|
phsh(ph, sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HEADTYPE == Hnetbsd) {
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
|
||||||
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
sh = nil;
|
||||||
sh->type = SHT_NOTE;
|
switch(HEADTYPE) {
|
||||||
sh->flags = SHF_ALLOC;
|
case Hnetbsd:
|
||||||
sh->addralign = 4;
|
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
resoff -= elfnetbsdsig(sh, startva, resoff);
|
resoff -= elfnetbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
case Hopenbsd:
|
||||||
|
sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
|
resoff -= elfopenbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
ph->type = PT_NOTE;
|
ph->type = PT_NOTE;
|
||||||
@ -1027,6 +1036,8 @@ asmb(void)
|
|||||||
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
if(a > ELFRESERVE)
|
if(a > ELFRESERVE)
|
||||||
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
||||||
break;
|
break;
|
||||||
|
@ -95,6 +95,7 @@ enum {
|
|||||||
ElfStrGnuVersion,
|
ElfStrGnuVersion,
|
||||||
ElfStrGnuVersionR,
|
ElfStrGnuVersionR,
|
||||||
ElfStrNoteNetbsdIdent,
|
ElfStrNoteNetbsdIdent,
|
||||||
|
ElfStrNoteOpenbsdIdent,
|
||||||
ElfStrNoPtrData,
|
ElfStrNoPtrData,
|
||||||
ElfStrNoPtrBss,
|
ElfStrNoPtrBss,
|
||||||
NElfStr
|
NElfStr
|
||||||
@ -577,6 +578,8 @@ doelf(void)
|
|||||||
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
|
||||||
addstring(shstrtab, ".elfdata");
|
addstring(shstrtab, ".elfdata");
|
||||||
addstring(shstrtab, ".rodata");
|
addstring(shstrtab, ".rodata");
|
||||||
addstring(shstrtab, ".gcdata");
|
addstring(shstrtab, ".gcdata");
|
||||||
@ -785,7 +788,7 @@ asmb(void)
|
|||||||
if(elfverneed)
|
if(elfverneed)
|
||||||
elftextsh += 2;
|
elftextsh += 2;
|
||||||
}
|
}
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
|
||||||
elftextsh += 1;
|
elftextsh += 1;
|
||||||
break;
|
break;
|
||||||
case Hwindows:
|
case Hwindows:
|
||||||
@ -956,12 +959,18 @@ asmb(void)
|
|||||||
phsh(ph, sh);
|
phsh(ph, sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HEADTYPE == Hnetbsd) {
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
|
||||||
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
sh = nil;
|
||||||
sh->type = SHT_NOTE;
|
switch(HEADTYPE) {
|
||||||
sh->flags = SHF_ALLOC;
|
case Hnetbsd:
|
||||||
sh->addralign = 4;
|
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
resoff -= elfnetbsdsig(sh, startva, resoff);
|
resoff -= elfnetbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
case Hopenbsd:
|
||||||
|
sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
|
resoff -= elfopenbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
ph->type = PT_NOTE;
|
ph->type = PT_NOTE;
|
||||||
@ -1151,6 +1160,8 @@ asmb(void)
|
|||||||
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
if(a > ELFRESERVE)
|
if(a > ELFRESERVE)
|
||||||
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
||||||
break;
|
break;
|
||||||
|
@ -91,6 +91,7 @@ enum {
|
|||||||
ElfStrGnuVersion,
|
ElfStrGnuVersion,
|
||||||
ElfStrGnuVersionR,
|
ElfStrGnuVersionR,
|
||||||
ElfStrNoteNetbsdIdent,
|
ElfStrNoteNetbsdIdent,
|
||||||
|
ElfStrNoteOpenbsdIdent,
|
||||||
ElfStrNoPtrData,
|
ElfStrNoPtrData,
|
||||||
ElfStrNoPtrBss,
|
ElfStrNoPtrBss,
|
||||||
NElfStr
|
NElfStr
|
||||||
@ -534,6 +535,8 @@ doelf(void)
|
|||||||
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
|
||||||
addstring(shstrtab, ".elfdata");
|
addstring(shstrtab, ".elfdata");
|
||||||
addstring(shstrtab, ".rodata");
|
addstring(shstrtab, ".rodata");
|
||||||
addstring(shstrtab, ".gcdata");
|
addstring(shstrtab, ".gcdata");
|
||||||
@ -723,7 +726,7 @@ asmb(void)
|
|||||||
if(elfverneed)
|
if(elfverneed)
|
||||||
elftextsh += 2;
|
elftextsh += 2;
|
||||||
}
|
}
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd)
|
||||||
elftextsh += 1;
|
elftextsh += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,12 +1000,18 @@ asmb(void)
|
|||||||
phsh(ph, sh);
|
phsh(ph, sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HEADTYPE == Hnetbsd) {
|
if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
|
||||||
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
sh = nil;
|
||||||
sh->type = SHT_NOTE;
|
switch(HEADTYPE) {
|
||||||
sh->flags = SHF_ALLOC;
|
case Hnetbsd:
|
||||||
sh->addralign = 4;
|
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
resoff -= elfnetbsdsig(sh, startva, resoff);
|
resoff -= elfnetbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
case Hopenbsd:
|
||||||
|
sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
|
resoff -= elfopenbsdsig(sh, startva, resoff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
ph->type = PT_NOTE;
|
ph->type = PT_NOTE;
|
||||||
@ -1202,6 +1211,8 @@ asmb(void)
|
|||||||
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
a += elfwriteinterp(elfstr[ElfStrInterp]);
|
||||||
if(HEADTYPE == Hnetbsd)
|
if(HEADTYPE == Hnetbsd)
|
||||||
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
|
||||||
|
if(HEADTYPE == Hopenbsd)
|
||||||
|
a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]);
|
||||||
if(a > ELFRESERVE)
|
if(a > ELFRESERVE)
|
||||||
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
||||||
break;
|
break;
|
||||||
|
103
src/cmd/ld/elf.c
103
src/cmd/ld/elf.c
@ -351,10 +351,48 @@ elfwriteinterp(vlong stridx)
|
|||||||
return sh->size;
|
return sh->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined in NetBSD's sys/exec_elf.h
|
int
|
||||||
#define ELF_NOTE_TYPE_NETBSD_TAG 1
|
elfnote(ElfShdr *sh, uint64 startva, uint64 resoff, int sz)
|
||||||
|
{
|
||||||
|
uint64 n;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfShdr *
|
||||||
|
elfwritenotehdr(vlong stridx, uint32 namesz, uint32 descsz, uint32 tag)
|
||||||
|
{
|
||||||
|
ElfShdr *sh = nil;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < hdr.shnum; i++)
|
||||||
|
if(shdr[i]->name == stridx)
|
||||||
|
sh = shdr[i];
|
||||||
|
if(sh == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
// Write Elf_Note header.
|
||||||
|
cseek(sh->off);
|
||||||
|
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_NAMESZ 7
|
||||||
#define ELF_NOTE_NETBSD_DESCSZ 4
|
#define ELF_NOTE_NETBSD_DESCSZ 4
|
||||||
|
#define ELF_NOTE_NETBSD_TAG 1
|
||||||
#define ELF_NOTE_NETBSD_NAME "NetBSD\0\0"
|
#define ELF_NOTE_NETBSD_NAME "NetBSD\0\0"
|
||||||
#define ELF_NOTE_NETBSD_VERSION 599000000 /* NetBSD 5.99 */
|
#define ELF_NOTE_NETBSD_VERSION 599000000 /* NetBSD 5.99 */
|
||||||
|
|
||||||
@ -363,37 +401,60 @@ elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
|
n = ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
|
||||||
n += resoff % 4;
|
return elfnote(sh, startva, resoff, n);
|
||||||
sh->addr = startva + resoff - n;
|
|
||||||
sh->off = resoff - n;
|
|
||||||
sh->size = n;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
elfwritenetbsdsig(vlong stridx) {
|
elfwritenetbsdsig(vlong stridx)
|
||||||
ElfShdr *sh = nil;
|
{
|
||||||
int i;
|
ElfShdr *sh;
|
||||||
|
|
||||||
for(i = 0; i < hdr.shnum; i++)
|
// Write Elf_Note header.
|
||||||
if(shdr[i]->name == stridx)
|
sh = elfwritenotehdr(stridx, ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG);
|
||||||
sh = shdr[i];
|
|
||||||
if(sh == nil)
|
if(sh == nil)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Write Elf_Note header followed by NetBSD string.
|
// Followed by NetBSD string and version.
|
||||||
cseek(sh->off);
|
cwrite(ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ + 1);
|
||||||
LPUT(ELF_NOTE_NETBSD_NAMESZ);
|
|
||||||
LPUT(ELF_NOTE_NETBSD_DESCSZ);
|
|
||||||
LPUT(ELF_NOTE_TYPE_NETBSD_TAG);
|
|
||||||
cwrite(ELF_NOTE_NETBSD_NAME, 8);
|
|
||||||
LPUT(ELF_NOTE_NETBSD_VERSION);
|
LPUT(ELF_NOTE_NETBSD_VERSION);
|
||||||
|
|
||||||
return sh->size;
|
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;
|
extern int nelfsym;
|
||||||
int elfverneed;
|
int elfverneed;
|
||||||
|
|
||||||
|
@ -976,6 +976,8 @@ int elfinterp(ElfShdr*, uint64, uint64, char*);
|
|||||||
int elfwriteinterp(vlong);
|
int elfwriteinterp(vlong);
|
||||||
int elfnetbsdsig(ElfShdr*, uint64, uint64);
|
int elfnetbsdsig(ElfShdr*, uint64, uint64);
|
||||||
int elfwritenetbsdsig(vlong);
|
int elfwritenetbsdsig(vlong);
|
||||||
|
int elfopenbsdsig(ElfShdr*, uint64, uint64);
|
||||||
|
int elfwriteopenbsdsig(vlong);
|
||||||
void elfdynhash(void);
|
void elfdynhash(void);
|
||||||
ElfPhdr* elfphload(Segment*);
|
ElfPhdr* elfphload(Segment*);
|
||||||
ElfShdr* elfshbits(Section*);
|
ElfShdr* elfshbits(Section*);
|
||||||
|
Loading…
Reference in New Issue
Block a user