1
0
mirror of https://github.com/golang/go synced 2024-11-22 02:04:40 -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:
Joel Sing 2012-09-21 12:51:39 +10:00
parent 9773ac1d08
commit 31758b2c1a
5 changed files with 138 additions and 42 deletions

View File

@ -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 = nil;
switch(HEADTYPE) {
case Hnetbsd:
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
sh->type = SHT_NOTE;
sh->flags = SHF_ALLOC;
sh->addralign = 4;
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;

View File

@ -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 = nil;
switch(HEADTYPE) {
case Hnetbsd:
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
sh->type = SHT_NOTE;
sh->flags = SHF_ALLOC;
sh->addralign = 4;
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;

View File

@ -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 = nil;
switch(HEADTYPE) {
case Hnetbsd:
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
sh->type = SHT_NOTE;
sh->flags = SHF_ALLOC;
sh->addralign = 4;
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;

View File

@ -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;

View File

@ -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*);