Commit 5842f7e4 authored by Joel Sing's avatar Joel Sing

5l/6l/8l: add support for netbsd signature note section

R=m4dh4tt3r, jsing, rsc
CC=golang-dev
https://golang.org/cl/5493068
parent b7e9d225
...@@ -73,6 +73,7 @@ enum { ...@@ -73,6 +73,7 @@ enum {
ElfStrShstrtab, ElfStrShstrtab,
ElfStrRelPlt, ElfStrRelPlt,
ElfStrPlt, ElfStrPlt,
ElfStrNoteNetbsdIdent,
NElfStr NElfStr
}; };
...@@ -164,6 +165,8 @@ doelf(void) ...@@ -164,6 +165,8 @@ doelf(void)
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
if(HEADTYPE == Hnetbsd)
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".rodata"); addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab"); addstring(shstrtab, ".gopclntab");
...@@ -294,7 +297,7 @@ asmb(void) ...@@ -294,7 +297,7 @@ asmb(void)
{ {
int32 t; int32 t;
int a, dynsym; int a, dynsym;
uint32 fo, symo, startva; uint32 fo, symo, startva, resoff;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
...@@ -336,6 +339,8 @@ asmb(void) ...@@ -336,6 +339,8 @@ asmb(void)
if(elfverneed) if(elfverneed)
elftextsh += 2; elftextsh += 2;
} }
if(HEADTYPE == Hnetbsd)
elftextsh += 1;
} }
/* output symbol table */ /* output symbol table */
...@@ -371,7 +376,7 @@ asmb(void) ...@@ -371,7 +376,7 @@ asmb(void)
cseek(symo); cseek(symo);
if(iself) { if(iself) {
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f elfsym\n", cputime()); Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym(); asmelfsym();
cflush(); cflush();
cwrite(elfstrdat, elfstrsize); cwrite(elfstrdat, elfstrsize);
...@@ -455,6 +460,7 @@ asmb(void) ...@@ -455,6 +460,7 @@ asmb(void)
eh = getElfEhdr(); eh = getElfEhdr();
fo = HEADR; fo = HEADR;
startva = INITTEXT - fo; /* va of byte 0 of file */ startva = INITTEXT - fo; /* va of byte 0 of file */
resoff = ELFRESERVE;
/* This null SHdr must appear before all others */ /* This null SHdr must appear before all others */
newElfShdr(elfstr[ElfStrEmpty]); newElfShdr(elfstr[ElfStrEmpty]);
...@@ -487,7 +493,7 @@ asmb(void) ...@@ -487,7 +493,7 @@ asmb(void)
sh->addralign = 1; sh->addralign = 1;
if(interpreter == nil) if(interpreter == nil)
interpreter = linuxdynld; interpreter = linuxdynld;
elfinterp(sh, startva, interpreter); resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr(); ph = newElfPhdr();
ph->type = PT_INTERP; ph->type = PT_INTERP;
...@@ -495,11 +501,24 @@ asmb(void) ...@@ -495,11 +501,24 @@ asmb(void)
phsh(ph, sh); 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);
ph = newElfPhdr();
ph->type = PT_NOTE;
ph->flags = PF_R;
phsh(ph, sh);
}
elfphload(&segtext); elfphload(&segtext);
elfphload(&segdata); elfphload(&segdata);
/* Dynamic linking sections */ /* Dynamic linking sections */
if (!debug['d']) { /* -d suppresses dynamic loader format */ if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */ /* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]); sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
...@@ -590,7 +609,7 @@ asmb(void) ...@@ -590,7 +609,7 @@ asmb(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect); elfshbits(sect);
if (!debug['s']) { if(!debug['s']) {
sh = newElfShdr(elfstr[ElfStrSymtab]); sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB; sh->type = SHT_SYMTAB;
sh->off = symo; sh->off = symo;
...@@ -632,7 +651,9 @@ asmb(void) ...@@ -632,7 +651,9 @@ asmb(void)
a += elfwritehdr(); a += elfwritehdr();
a += elfwritephdrs(); a += elfwritephdrs();
a += elfwriteshdrs(); a += elfwriteshdrs();
a += elfwriteinterp(); a += elfwriteinterp(elfstr[ElfStrInterp]);
if(HEADTYPE == Hnetbsd)
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
if(a > ELFRESERVE) if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break; break;
......
...@@ -707,7 +707,7 @@ asmb(void) ...@@ -707,7 +707,7 @@ asmb(void)
{ {
int32 magic; int32 magic;
int a, dynsym; int a, dynsym;
vlong vl, startva, symo, dwarfoff, machlink; vlong vl, startva, symo, dwarfoff, machlink, resoff;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
...@@ -778,6 +778,8 @@ asmb(void) ...@@ -778,6 +778,8 @@ asmb(void)
if(elfverneed) if(elfverneed)
elftextsh += 2; elftextsh += 2;
} }
if(HEADTYPE == Hnetbsd)
elftextsh += 1;
break; break;
case Hwindows: case Hwindows:
break; break;
...@@ -879,6 +881,7 @@ asmb(void) ...@@ -879,6 +881,7 @@ asmb(void)
eh = getElfEhdr(); eh = getElfEhdr();
startva = INITTEXT - HEADR; startva = INITTEXT - HEADR;
resoff = ELFRESERVE;
/* This null SHdr must appear before all others */ /* This null SHdr must appear before all others */
newElfShdr(elfstr[ElfStrEmpty]); newElfShdr(elfstr[ElfStrEmpty]);
...@@ -925,7 +928,7 @@ asmb(void) ...@@ -925,7 +928,7 @@ asmb(void)
break; break;
} }
} }
elfinterp(sh, startva, interpreter); resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr(); ph = newElfPhdr();
ph->type = PT_INTERP; ph->type = PT_INTERP;
...@@ -933,11 +936,24 @@ asmb(void) ...@@ -933,11 +936,24 @@ asmb(void)
phsh(ph, sh); 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);
ph = newElfPhdr();
ph->type = PT_NOTE;
ph->flags = PF_R;
phsh(ph, sh);
}
elfphload(&segtext); elfphload(&segtext);
elfphload(&segdata); elfphload(&segdata);
/* Dynamic linking sections */ /* Dynamic linking sections */
if (!debug['d']) { /* -d suppresses dynamic loader format */ if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */ /* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]); sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
...@@ -1061,7 +1077,7 @@ asmb(void) ...@@ -1061,7 +1077,7 @@ asmb(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect); elfshbits(sect);
if (!debug['s']) { if(!debug['s']) {
sh = newElfShdr(elfstr[ElfStrSymtab]); sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB; sh->type = SHT_SYMTAB;
sh->off = symo; sh->off = symo;
...@@ -1107,7 +1123,9 @@ asmb(void) ...@@ -1107,7 +1123,9 @@ asmb(void)
a += elfwritehdr(); a += elfwritehdr();
a += elfwritephdrs(); a += elfwritephdrs();
a += elfwriteshdrs(); a += elfwriteshdrs();
a += elfwriteinterp(); a += elfwriteinterp(elfstr[ElfStrInterp]);
if(HEADTYPE == Hnetbsd)
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
if(a > ELFRESERVE) if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break; break;
......
...@@ -92,6 +92,7 @@ enum { ...@@ -92,6 +92,7 @@ enum {
ElfStrPlt, ElfStrPlt,
ElfStrGnuVersion, ElfStrGnuVersion,
ElfStrGnuVersionR, ElfStrGnuVersionR,
ElfStrNoteNetbsdIdent,
NElfStr NElfStr
}; };
...@@ -528,6 +529,8 @@ doelf(void) ...@@ -528,6 +529,8 @@ doelf(void)
elfstr[ElfStrText] = addstring(shstrtab, ".text"); elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
if(HEADTYPE == Hnetbsd)
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata"); addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gosymtab");
...@@ -661,7 +664,7 @@ asmb(void) ...@@ -661,7 +664,7 @@ asmb(void)
{ {
int32 v, magic; int32 v, magic;
int a, dynsym; int a, dynsym;
uint32 symo, startva, dwarfoff, machlink; uint32 symo, startva, dwarfoff, machlink, resoff;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
...@@ -715,6 +718,8 @@ asmb(void) ...@@ -715,6 +718,8 @@ asmb(void)
if(elfverneed) if(elfverneed)
elftextsh += 2; elftextsh += 2;
} }
if(HEADTYPE == Hnetbsd)
elftextsh += 1;
} }
symsize = 0; symsize = 0;
...@@ -761,7 +766,7 @@ asmb(void) ...@@ -761,7 +766,7 @@ asmb(void)
default: default:
if(iself) { if(iself) {
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f elfsym\n", cputime()); Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym(); asmelfsym();
cflush(); cflush();
cwrite(elfstrdat, elfstrsize); cwrite(elfstrdat, elfstrsize);
...@@ -932,6 +937,7 @@ asmb(void) ...@@ -932,6 +937,7 @@ asmb(void)
Elfput: Elfput:
eh = getElfEhdr(); eh = getElfEhdr();
startva = INITTEXT - HEADR; startva = INITTEXT - HEADR;
resoff = ELFRESERVE;
/* This null SHdr must appear before all others */ /* This null SHdr must appear before all others */
newElfShdr(elfstr[ElfStrEmpty]); newElfShdr(elfstr[ElfStrEmpty]);
...@@ -978,7 +984,7 @@ asmb(void) ...@@ -978,7 +984,7 @@ asmb(void)
break; break;
} }
} }
elfinterp(sh, startva, interpreter); resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr(); ph = newElfPhdr();
ph->type = PT_INTERP; ph->type = PT_INTERP;
...@@ -986,11 +992,24 @@ asmb(void) ...@@ -986,11 +992,24 @@ asmb(void)
phsh(ph, sh); 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);
ph = newElfPhdr();
ph->type = PT_NOTE;
ph->flags = PF_R;
phsh(ph, sh);
}
elfphload(&segtext); elfphload(&segtext);
elfphload(&segdata); elfphload(&segdata);
/* Dynamic linking sections */ /* Dynamic linking sections */
if (!debug['d']) { /* -d suppresses dynamic loader format */ if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */ /* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]); sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
...@@ -1114,7 +1133,7 @@ asmb(void) ...@@ -1114,7 +1133,7 @@ asmb(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next) for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect); elfshbits(sect);
if (!debug['s']) { if(!debug['s']) {
sh = newElfShdr(elfstr[ElfStrSymtab]); sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB; sh->type = SHT_SYMTAB;
sh->off = symo; sh->off = symo;
...@@ -1167,7 +1186,9 @@ asmb(void) ...@@ -1167,7 +1186,9 @@ asmb(void)
a += elfwritehdr(); a += elfwritehdr();
a += elfwritephdrs(); a += elfwritephdrs();
a += elfwriteshdrs(); a += elfwriteshdrs();
a += elfwriteinterp(); a += elfwriteinterp(elfstr[ElfStrInterp]);
if(HEADTYPE == Hnetbsd)
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
if(a > ELFRESERVE) if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break; break;
......
...@@ -318,29 +318,77 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t) ...@@ -318,29 +318,77 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t)
} }
int int
elfwriteinterp(void) elfinterp(ElfShdr *sh, uint64 startva, uint64 resoff, char *p)
{ {
int n; int n;
if(interp == nil) interp = p;
return 0;
n = strlen(interp)+1; n = strlen(interp)+1;
cseek(ELFRESERVE-n); sh->addr = startva + resoff - n;
cwrite(interp, n); sh->off = resoff - n;
sh->size = n;
return n; return n;
} }
void int
elfinterp(ElfShdr *sh, uint64 startva, char *p) elfwriteinterp(vlong stridx)
{
ElfShdr *sh = nil;
int i;
for(i = 0; i < hdr.shnum; i++)
if(shdr[i]->name == stridx)
sh = shdr[i];
if(sh == nil || interp == nil)
return 0;
cseek(sh->off);
cwrite(interp, sh->size);
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)
{ {
int n; int n;
interp = p; n = sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
n = strlen(interp)+1; n += resoff % 4;
sh->addr = startva + ELFRESERVE - n; sh->addr = startva + resoff - n;
sh->off = ELFRESERVE - n; sh->off = resoff - n;
sh->size = n; sh->size = n;
return n;
}
int
elfwritenetbsdsig(vlong stridx) {
ElfShdr *sh = nil;
int i;
for(i = 0; i < hdr.shnum; i++)
if(shdr[i]->name == stridx)
sh = shdr[i];
if(sh == nil)
return 0;
// Write Elf_Note header followed by NetBSD string.
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(ELF_NOTE_NETBSD_VERSION);
return sh->size;
} }
extern int nelfsym; extern int nelfsym;
......
...@@ -968,8 +968,10 @@ extern int numelfphdr; ...@@ -968,8 +968,10 @@ extern int numelfphdr;
extern int numelfshdr; extern int numelfshdr;
extern int iself; extern int iself;
extern int elfverneed; extern int elfverneed;
int elfwriteinterp(void); int elfinterp(ElfShdr*, uint64, uint64, char*);
void elfinterp(ElfShdr*, uint64, char*); int elfwriteinterp(vlong);
int elfnetbsdsig(ElfShdr*, uint64, uint64);
int elfwritenetbsdsig(vlong);
void elfdynhash(void); void elfdynhash(void);
ElfPhdr* elfphload(Segment*); ElfPhdr* elfphload(Segment*);
ElfShdr* elfshbits(Section*); ElfShdr* elfshbits(Section*);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment