6l -e: emit external ELF symbol table.

enough to make nm and oprofile work.

R=r
http://go/go-review/1017016
This commit is contained in:
Russ Cox 2009-11-03 14:20:37 -08:00
parent c56b366c28
commit 96ea081c04
4 changed files with 140 additions and 16 deletions

View File

@ -255,6 +255,8 @@ enum {
ElfStrGosymtab, ElfStrGosymtab,
ElfStrGopclntab, ElfStrGopclntab,
ElfStrShstrtab, ElfStrShstrtab,
ElfStrSymtab,
ElfStrStrtab,
NElfStr NElfStr
}; };
@ -294,6 +296,10 @@ doelf(void)
if(!debug['s']) { if(!debug['s']) {
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
if(debug['e']) {
elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
}
} }
elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab"); elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
@ -426,7 +432,7 @@ asmb(void)
int32 v, magic; int32 v, magic;
int a, dynsym; int a, dynsym;
uchar *op1; uchar *op1;
vlong vl, va, startva, fo, w, symo, machlink; vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink;
vlong symdatva = 0x99LL<<32; vlong symdatva = 0x99LL<<32;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
@ -436,6 +442,10 @@ asmb(void)
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso); Bflush(&bso);
elftextsh = 0;
elfsymsize = 0;
elfstro = 0;
elfsymo = 0;
seek(cout, HEADR, 0); seek(cout, HEADR, 0);
pc = INITTEXT; pc = INITTEXT;
curp = firstp; curp = firstp;
@ -498,6 +508,12 @@ asmb(void)
debug['8'] = 1; /* 64-bit addresses */ debug['8'] = 1; /* 64-bit addresses */
v = rnd(HEADR+textsize, INITRND); v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0); seek(cout, v, 0);
/* index of elf text section; needed by asmelfsym, double-checked below */
/* debug['d'] causes 8 extra sections before the .text section */
elftextsh = 1;
if(!debug['d'])
elftextsh += 8;
break; break;
} }
@ -546,6 +562,13 @@ asmb(void)
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
} }
/*
* the symbol information is stored as
* 32-bit symbol table size
* 32-bit line number table size
* symbol table
* line number table
*/
seek(cout, symo+8, 0); seek(cout, symo+8, 0);
if(!debug['s']) if(!debug['s'])
asmsym(); asmsym();
@ -564,6 +587,15 @@ asmb(void)
lputl(symsize); lputl(symsize);
lputl(lcsize); lputl(lcsize);
cflush(); cflush();
if(!debug['s'] && debug['e']) {
elfsymo = symo+8+symsize+lcsize;
seek(cout, elfsymo, 0);
asmelfsym();
cflush();
elfstro = seek(cout, 0, 1);
elfsymsize = elfstro - elfsymo;
write(cout, elfstrdat, elfstrsize);
}
} else } else
if(dlm){ if(dlm){
seek(cout, HEADR+textsize+datsize, 0); seek(cout, HEADR+textsize+datsize, 0);
@ -752,6 +784,8 @@ asmb(void)
va = startva + fo; va = startva + fo;
w = textsize; w = textsize;
if(elftextsh != eh->shnum)
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
sh = newElfShdr(elfstr[ElfStrText]); sh = newElfShdr(elfstr[ElfStrText]);
sh->type = SHT_PROGBITS; sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_EXECINSTR; sh->flags = SHF_ALLOC+SHF_EXECINSTR;
@ -802,6 +836,22 @@ asmb(void)
sh->off = fo; sh->off = fo;
sh->size = w; sh->size = w;
sh->addralign = 1; sh->addralign = 1;
if(debug['e']) {
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = elfsymo;
sh->size = elfsymsize;
sh->addralign = 8;
sh->entsize = 24;
sh->link = eh->shnum; // link to strtab
sh = newElfShdr(elfstr[ElfStrStrtab]);
sh->type = SHT_STRTAB;
sh->off = elfstro;
sh->size = elfstrsize;
sh->addralign = 1;
}
} }
sh = newElfShstrtab(elfstr[ElfStrShstrtab]); sh = newElfShstrtab(elfstr[ElfStrShstrtab]);

View File

@ -350,6 +350,9 @@ EXTERN vlong textstksiz;
EXTERN vlong textarg; EXTERN vlong textarg;
extern char thechar; extern char thechar;
EXTERN int dynptrsize; EXTERN int dynptrsize;
EXTERN int elfstrsize;
EXTERN char* elfstrdat;
EXTERN int elftextsh;
#define UP (&undefp) #define UP (&undefp)
@ -376,6 +379,7 @@ void asmins(Prog*);
void asmlc(void); void asmlc(void);
void asmsp(void); void asmsp(void);
void asmsym(void); void asmsym(void);
void asmelfsym(void);
vlong atolwhex(char*); vlong atolwhex(char*);
Prog* brchain(Prog*); Prog* brchain(Prog*);
Prog* brloop(Prog*); Prog* brloop(Prog*);

View File

@ -30,6 +30,7 @@
#include "l.h" #include "l.h"
#include "../ld/lib.h" #include "../ld/lib.h"
#include "../ld/elf.h"
static int rexflag; static int rexflag;
static int asmode; static int asmode;
@ -151,7 +152,7 @@ xdefine(char *p, int t, vlong v)
} }
void void
putsymb(char *s, int t, vlong v, int ver, Sym *go) putsymb(char *s, int t, vlong v, vlong size, int ver, Sym *go)
{ {
int i, f, l; int i, f, l;
vlong gv; vlong gv;
@ -212,7 +213,7 @@ putsymb(char *s, int t, vlong v, int ver, Sym *go)
} }
void void
asmsym(void) genasmsym(void (*put)(char*, int, vlong, vlong, int, Sym*))
{ {
Prog *p; Prog *p;
Auto *a; Auto *a;
@ -221,7 +222,7 @@ asmsym(void)
s = lookup("etext", 0); s = lookup("etext", 0);
if(s->type == STEXT) if(s->type == STEXT)
putsymb(s->name, 'T', s->value, s->version, 0); put(s->name, 'T', s->value, s->size, s->version, 0);
for(h=0; h<NHASH; h++) { for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) { for(s=hash[h]; s!=S; s=s->link) {
@ -229,29 +230,29 @@ asmsym(void)
case SCONST: case SCONST:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'D', s->value, s->version, s->gotype); put(s->name, 'D', s->value, s->size, s->version, s->gotype);
continue; continue;
case SDATA: case SDATA:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype); put(s->name, 'D', s->value+INITDAT, s->size, s->version, s->gotype);
continue; continue;
case SMACHO: case SMACHO:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->version, s->gotype); put(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->size, s->version, s->gotype);
continue; continue;
case SBSS: case SBSS:
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'B', s->value+INITDAT, s->version, s->gotype); put(s->name, 'B', s->value+INITDAT, s->size, s->version, s->gotype);
continue; continue;
case SFILE: case SFILE:
putsymb(s->name, 'f', s->value, s->version, 0); put(s->name, 'f', s->value, 0, s->version, 0);
continue; continue;
} }
} }
@ -265,30 +266,99 @@ asmsym(void)
/* filenames first */ /* filenames first */
for(a=p->to.autom; a; a=a->link) for(a=p->to.autom; a; a=a->link)
if(a->type == D_FILE) if(a->type == D_FILE)
putsymb(a->asym->name, 'z', a->aoffset, 0, 0); put(a->asym->name, 'z', a->aoffset, 0, 0, 0);
else else
if(a->type == D_FILE1) if(a->type == D_FILE1)
putsymb(a->asym->name, 'Z', a->aoffset, 0, 0); put(a->asym->name, 'Z', a->aoffset, 0, 0, 0);
if(!s->reachable) if(!s->reachable)
continue; continue;
putsymb(s->name, 'T', s->value, s->version, s->gotype); put(s->name, 'T', s->value, s->size, s->version, s->gotype);
/* frame, auto and param after */ /* frame, auto and param after */
putsymb(".frame", 'm', p->to.offset+8, 0, 0); put(".frame", 'm', p->to.offset+8, 0, 0, 0);
for(a=p->to.autom; a; a=a->link) for(a=p->to.autom; a; a=a->link)
if(a->type == D_AUTO) if(a->type == D_AUTO)
putsymb(a->asym->name, 'a', -a->aoffset, 0, a->gotype); put(a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
else else
if(a->type == D_PARAM) if(a->type == D_PARAM)
putsymb(a->asym->name, 'p', a->aoffset, 0, a->gotype); put(a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
} }
if(debug['v'] || debug['n']) if(debug['v'] || debug['n'])
Bprint(&bso, "symsize = %lud\n", symsize); Bprint(&bso, "symsize = %lud\n", symsize);
Bflush(&bso); Bflush(&bso);
} }
void
asmsym(void)
{
genasmsym(putsymb);
}
char *elfstrdat;
int elfstrsize;
int maxelfstr;
int
putelfstr(char *s)
{
int off, n;
if(elfstrsize == 0 && s[0] != 0) {
// first entry must be empty string
putelfstr("");
}
n = strlen(s)+1;
if(elfstrsize+n > maxelfstr) {
maxelfstr = 2*(elfstrsize+n+(1<<20));
elfstrdat = realloc(elfstrdat, maxelfstr);
}
off = elfstrsize;
elfstrsize += n;
memmove(elfstrdat+off, s, n);
return off;
}
void
putelfsymb(char *s, int t, vlong addr, vlong size, int ver, Sym *go)
{
int bind, type, shndx, stroff;
bind = STB_GLOBAL;
switch(t) {
default:
return;
case 'T':
type = STT_FUNC;
shndx = elftextsh + 0;
break;
case 'D':
type = STT_OBJECT;
shndx = elftextsh + 1;
break;
case 'B':
type = STT_OBJECT;
shndx = elftextsh + 2;
break;
}
stroff = putelfstr(s);
lputl(stroff); // string
cput((bind<<4)|(type&0xF));
cput(0);
wputl(shndx);
vputl(addr);
vputl(size);
}
void
asmelfsym(void)
{
genasmsym(putelfsymb);
}
void void
asmlc(void) asmlc(void)
{ {

View File

@ -11,7 +11,7 @@
* in order to write the code just once. The 64-bit data structure is * in order to write the code just once. The 64-bit data structure is
* written in the 32-bit format on the 32-bit machines. * written in the 32-bit format on the 32-bit machines.
*/ */
#define NSECT 16 #define NSECT 32
static int elf64; static int elf64;
static ElfEhdr hdr; static ElfEhdr hdr;