1
0
mirror of https://github.com/golang/go synced 2024-11-25 03:57:56 -07:00

arm: fix build on android

R=kaib
CC=golang-dev
https://golang.org/cl/206059
This commit is contained in:
Russ Cox 2010-02-10 15:01:02 -08:00
parent fb94be55dc
commit 66cdc699b2
11 changed files with 743 additions and 274 deletions

View File

@ -244,6 +244,9 @@ enum as
#define D_AUTO (D_NONE+5) #define D_AUTO (D_NONE+5)
#define D_PARAM (D_NONE+6) #define D_PARAM (D_NONE+6)
/* internal only */
#define D_SIZE (D_NONE+40)
/* /*
* this is the ranlib header * this is the ranlib header
*/ */

View File

@ -9,6 +9,7 @@ TARG=\
OFILES=\ OFILES=\
asm.$O\ asm.$O\
elf.$O\
enam.$O\ enam.$O\
lib.$O\ lib.$O\
list.$O\ list.$O\
@ -24,6 +25,7 @@ OFILES=\
HFILES=\ HFILES=\
l.h\ l.h\
../5l/5.out.h\ ../5l/5.out.h\
../ld/elf.h\
$(TARG): $(OFILES) $(TARG): $(OFILES)
$(LD) -o $(TARG) -L"$(GOROOT)"/lib $(OFILES) -lbio -l9 $(LD) -o $(TARG) -L"$(GOROOT)"/lib $(OFILES) -lbio -l9

View File

@ -30,11 +30,14 @@
#include "l.h" #include "l.h"
#include "../ld/lib.h" #include "../ld/lib.h"
#include "../ld/elf.h"
int32 OFFSET; int32 OFFSET;
static Prog *PP; static Prog *PP;
char linuxdynld[] = "/lib/ld-linux.so.2";
int32 int32
entryvalue(void) entryvalue(void)
{ {
@ -60,16 +63,310 @@ entryvalue(void)
return s->value; return s->value;
} }
vlong
addstring(Sym *s, char *str)
{
int n, m;
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
n = strlen(str)+1;
while(n > 0) {
m = n;
if(m > NSNAME)
m = NSNAME;
p = newdata(s, s->value, m, D_EXTERN);
p->to.type = D_SCONST;
p->to.sval = mal(NSNAME);
memmove(p->to.sval, str, m);
s->value += m;
str += m;
n -= m;
}
return r;
}
vlong
adduintxx(Sym *s, uint64 v, int wid)
{
vlong r;
Prog *p;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, wid, D_EXTERN);
s->value += wid;
p->to.type = D_CONST;
p->to.offset = v;
return r;
}
vlong
adduint8(Sym *s, uint8 v)
{
return adduintxx(s, v, 1);
}
vlong
adduint16(Sym *s, uint16 v)
{
return adduintxx(s, v, 2);
}
vlong
adduint32(Sym *s, uint32 v)
{
return adduintxx(s, v, 4);
}
vlong
adduint64(Sym *s, uint64 v)
{
return adduintxx(s, v, 8);
}
vlong
addaddr(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
vlong
addsize(Sym *s, Sym *t)
{
vlong r;
Prog *p;
enum { Ptrsize = 4 };
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
r = s->value;
p = newdata(s, s->value, Ptrsize, D_EXTERN);
s->value += Ptrsize;
p->to.type = D_SIZE;
p->to.index = D_EXTERN;
p->to.offset = 0;
p->to.sym = t;
return r;
}
enum {
ElfStrEmpty,
ElfStrInterp,
ElfStrHash,
ElfStrGot,
ElfStrGotPlt,
ElfStrDynamic,
ElfStrDynsym,
ElfStrDynstr,
ElfStrRel,
ElfStrText,
ElfStrData,
ElfStrBss,
ElfStrGosymtab,
ElfStrGopclntab,
ElfStrShstrtab,
NElfStr
};
vlong elfstr[NElfStr];
void
doelf(void)
{
Sym *s, *shstrtab, *dynamic, *dynstr, *d;
int h, nsym, t;
if(!iself)
return;
/* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0);
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
if(!debug['s']) {
elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
}
elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
if(!debug['d']) { /* -d suppresses dynamic loader format */
elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
elfstr[ElfStrGot] = addstring(shstrtab, ".got");
elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
/* interpreter string */
s = lookup(".interp", 0);
s->reachable = 1;
s->type = SDATA; // TODO: rodata
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
s->type = SDATA;
s->reachable = 1;
s->value += ELF32SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
addstring(s, "");
dynstr = s;
/* relocation table */
s = lookup(".rel", 0);
s->reachable = 1;
s->type = SDATA;
/* global offset table */
s = lookup(".got", 0);
s->reachable = 1;
s->type = SDATA;
/* got.plt - ??? */
s = lookup(".got.plt", 0);
s->reachable = 1;
s->type = SDATA;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
dynamic = s;
/*
* relocation entries for dynld symbols
*/
nsym = 1; // sym 0 is reserved
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) {
if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
continue;
#if 0
d = lookup(".rel", 0);
addaddr(d, s);
adduint32(d, ELF32_R_INFO(nsym, R_386_32));
nsym++;
d = lookup(".dynsym", 0);
adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname));
adduint32(d, 0); /* value */
adduint32(d, 0); /* size of object */
t = STB_GLOBAL << 4;
t |= STT_OBJECT; // works for func too, empirically
adduint8(d, t);
adduint8(d, 0); /* reserved */
adduint16(d, SHN_UNDEF); /* section where symbol is defined */
if(needlib(s->dynldlib))
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib));
#endif
}
}
/*
* hash table.
* only entries that other objects need to find when
* linking us need to be in the table. right now that is
* no entries.
*
* freebsd insists on having chains enough for all
* the local symbols, though. for now, we just lay
* down a trivial hash table with 1 bucket and a long chain,
* because no one is actually looking for our symbols.
*/
s = lookup(".hash", 0);
s->type = SDATA; // TODO: rodata
s->reachable = 1;
adduint32(s, 1); // nbucket
adduint32(s, nsym); // nchain
adduint32(s, nsym-1); // bucket 0
adduint32(s, 0); // chain 0
for(h=1; h<nsym; h++) // chain nsym-1 -> nsym-2 -> ... -> 2 -> 1 -> 0
adduint32(s, h-1);
/*
* .dynamic table
*/
s = dynamic;
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
elfwritedynent(s, DT_NULL, 0);
}
}
vlong
datoff(vlong addr)
{
if(addr >= INITDAT)
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
diag("datoff %#llx", addr);
return 0;
}
void
shsym(Elf64_Shdr *sh, Sym *s)
{
sh->addr = s->value + INITDAT;
sh->off = datoff(sh->addr);
sh->size = s->size;
}
void
phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
{
ph->vaddr = sh->addr;
ph->paddr = ph->vaddr;
ph->off = sh->off;
ph->filesz = sh->size;
ph->memsz = sh->size;
ph->align = sh->addralign;
}
void void
asmb(void) asmb(void)
{ {
Prog *p; Prog *p;
int32 t, etext; int32 t, etext;
int np; int a, dynsym;
vlong va, fo, w, symo; uint32 va, fo, w, symo, startva;
int strtabsize; int strtabsize;
vlong symdatva = SYMDATVA; vlong symdatva = SYMDATVA;
Optab *o; Optab *o;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
strtabsize = 0; strtabsize = 0;
symo = 0; symo = 0;
@ -135,11 +432,8 @@ asmb(void)
seek(cout, OFFSET, 0); seek(cout, OFFSET, 0);
break; break;
case 6: case 6:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); OFFSET = rnd(HEADR+textsize, INITRND);
strtabsize = linuxstrtable(); seek(cout, OFFSET, 0);
cflush();
t = rnd(HEADR+textsize, INITRND);
seek(cout, t, 0);
break; break;
} }
if(dlm){ if(dlm){
@ -275,179 +569,242 @@ asmb(void)
break; break;
case 6: case 6:
/* elf arm */ /* elf arm */
strnput("\177ELF", 4); /* e_ident */ eh = getElfEhdr();
cput(1); /* class = 32 bit */
cput(1); /* data = LSB */
cput(1); /* version = CURRENT */
strnput("", 9);
wputl(2); /* type = EXEC */
wputl(40); /* machine = ARM */
lputl(1L); /* version = CURRENT */
lputl(entryvalue()); /* entry vaddr */
lputl(52L); /* offset to first phdr */
np = 3;
if(!debug['s'])
np++;
lputl(52L+32*np); /* offset to first shdr */
lputl(0L); /* processor specific flags */
wputl(52); /* Ehdr size */
wputl(32); /* Phdr size */
wputl(np); /* # of Phdrs */
wputl(40); /* Shdr size */
if (!debug['s'])
wputl(7); /* # of Shdrs */
else
wputl(5); /* # of Shdrs */
wputl(4); /* Shdr with strings */
fo = HEADR; fo = HEADR;
va = rnd(INITTEXT, INITRND); va = INITTEXT;
startva = INITTEXT - fo; /* va of byte 0 of file */
w = textsize; w = textsize;
linuxphdr(1, /* text - type = PT_LOAD */ /* This null SHdr must appear before all others */
1L+4L, /* text - flags = PF_X+PF_R */ sh = newElfShdr(elfstr[ElfStrEmpty]);
fo, /* file offset */
va, /* vaddr */
va, /* paddr */
w, /* file size */
w, /* memory size */
INITRND); /* alignment */
fo = rnd(fo+w, INITRND); /* program header info */
va = rnd(va+w, INITRND); pph = newElfPhdr();
w = datsize; pph->type = PT_PHDR;
pph->flags = PF_R + PF_X;
pph->off = eh->ehsize;
pph->vaddr = INITTEXT - HEADR + pph->off;
pph->paddr = INITTEXT - HEADR + pph->off;
pph->align = INITRND;
linuxphdr(1, /* data - type = PT_LOAD */ if(!debug['d']) {
2L+4L, /* data - flags = PF_W+PF_R */ /* interpreter for dynamic linking */
fo, /* file offset */ sh = newElfShdr(elfstr[ElfStrInterp]);
va, /* vaddr */ sh->type = SHT_PROGBITS;
va, /* paddr */ sh->flags = SHF_ALLOC;
w, /* file size */ sh->addralign = 1;
w+bsssize, /* memory size */ elfinterp(sh, startva, linuxdynld);
INITRND); /* alignment */
if(!debug['s']) { ph = newElfPhdr();
linuxphdr(1, /* data - type = PT_LOAD */ ph->type = PT_INTERP;
2L+4L, /* data - flags = PF_W+PF_R */ ph->flags = PF_R;
symo, /* file offset */ phsh(ph, sh);
symdatva, /* vaddr */
symdatva, /* paddr */
8+symsize+lcsize, /* file size */
8+symsize+lcsize, /* memory size */
INITRND); /* alignment */
} }
linuxphdr(0x6474e551, /* gok - type = gok */ ph = newElfPhdr();
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ ph->type = PT_LOAD;
0, /* file offset */ ph->flags = PF_X+PF_R;
0, /* vaddr */ ph->vaddr = va;
0, /* paddr */ ph->paddr = va;
0, /* file size */ ph->off = fo;
0, /* memory size */ ph->filesz = w;
8); /* alignment */ ph->memsz = w;
ph->align = INITRND;
linuxshdr(nil, /* name */
0, /* type */
0, /* flags */
0, /* addr */
0, /* off */
0, /* size */
0, /* link */
0, /* info */
0, /* align */
0); /* entsize */
stroffset = 1; /* 0 means no name, so start at 1 */
fo = HEADR;
va = rnd(INITTEXT, INITRND);
w = textsize;
linuxshdr(".text", /* name */
1, /* type */
6, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
fo = rnd(fo+w, INITRND); fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
linuxshdr(".data", /* name */ ph = newElfPhdr();
1, /* type */ ph->type = PT_LOAD;
3, /* flags */ ph->flags = PF_W+PF_R;
va, /* addr */ ph->off = fo;
fo, /* off */ ph->vaddr = va;
w, /* size */ ph->paddr = va;
0, /* link */ ph->filesz = w;
0, /* info */ ph->memsz = w+bsssize;
8, /* align */ ph->align = INITRND;
0); /* entsize */
if(!debug['s']) {
ph = newElfPhdr();
ph->type = PT_LOAD;
ph->flags = PF_W+PF_R;
ph->off = symo;
ph->vaddr = symdatva;
ph->paddr = symdatva;
ph->filesz = 8+symsize+lcsize;
ph->memsz = 8+symsize+lcsize;
ph->align = INITRND;
}
/* Dynamic linking sections */
if (!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 4;
sh->addralign = 4;
shsym(sh, lookup(".got", 0));
sh = newElfShdr(elfstr[ElfStrGotPlt]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 4;
sh->addralign = 4;
shsym(sh, lookup(".got.plt", 0));
dynsym = eh->shnum;
sh = newElfShdr(elfstr[ElfStrDynsym]);
sh->type = SHT_DYNSYM;
sh->flags = SHF_ALLOC;
sh->entsize = ELF32SYMSIZE;
sh->addralign = 4;
sh->link = dynsym+1; // dynstr
// sh->info = index of first non-local symbol (number of local symbols)
shsym(sh, lookup(".dynsym", 0));
sh = newElfShdr(elfstr[ElfStrDynstr]);
sh->type = SHT_STRTAB;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
shsym(sh, lookup(".dynstr", 0));
sh = newElfShdr(elfstr[ElfStrHash]);
sh->type = SHT_HASH;
sh->flags = SHF_ALLOC;
sh->entsize = 4;
sh->addralign = 4;
sh->link = dynsym;
shsym(sh, lookup(".hash", 0));
sh = newElfShdr(elfstr[ElfStrRel]);
sh->type = SHT_REL;
sh->flags = SHF_ALLOC;
sh->entsize = ELF32RELSIZE;
sh->addralign = 4;
sh->link = dynsym;
shsym(sh, lookup(".rel", 0));
/* sh and PT_DYNAMIC for .dynamic section */
sh = newElfShdr(elfstr[ElfStrDynamic]);
sh->type = SHT_DYNAMIC;
sh->flags = SHF_ALLOC+SHF_WRITE;
sh->entsize = 8;
sh->addralign = 4;
sh->link = dynsym+1; // dynstr
shsym(sh, lookup(".dynamic", 0));
ph = newElfPhdr();
ph->type = PT_DYNAMIC;
ph->flags = PF_R + PF_W;
phsh(ph, sh);
/*
* Thread-local storage segment (really just size).
if(tlsoffset != 0) {
ph = newElfPhdr();
ph->type = PT_TLS;
ph->flags = PF_R;
ph->memsz = -tlsoffset;
ph->align = 4;
}
*/
}
ph = newElfPhdr();
ph->type = PT_GNU_STACK;
ph->flags = PF_W+PF_R;
ph->align = 4;
fo = ELFRESERVE;
va = startva + fo;
w = textsize;
sh = newElfShdr(elfstr[ElfStrText]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 4;
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
sh = newElfShdr(elfstr[ElfStrData]);
sh->type = SHT_PROGBITS;
sh->flags = SHF_WRITE+SHF_ALLOC;
sh->addr = va;
sh->off = fo;
sh->size = w;
sh->addralign = 4;
fo += w; fo += w;
va += w; va += w;
w = bsssize; w = bsssize;
linuxshdr(".bss", /* name */ sh = newElfShdr(elfstr[ElfStrBss]);
8, /* type */ sh->type = SHT_NOBITS;
3, /* flags */ sh->flags = SHF_WRITE+SHF_ALLOC;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 4;
0, /* info */
8, /* align */
0); /* entsize */
w = strtabsize;
linuxshdr(".shstrtab", /* name */
3, /* type */
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
0); /* entsize */
if (debug['s'])
break;
if (!debug['s']) {
fo = symo+8; fo = symo+8;
w = symsize; w = symsize;
linuxshdr(".gosymtab", /* name */ sh = newElfShdr(elfstr[ElfStrGosymtab]);
1, /* type 1 = SHT_PROGBITS */ sh->type = SHT_PROGBITS;
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
fo += w; fo += w;
w = lcsize; w = lcsize;
linuxshdr(".gopclntab", /* name */ sh = newElfShdr(elfstr[ElfStrGopclntab]);
1, /* type 1 = SHT_PROGBITS*/ sh->type = SHT_PROGBITS;
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */ }
0, /* link */
0, /* info */ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
1, /* align */ sh->type = SHT_STRTAB;
24); /* entsize */ sh->addralign = 1;
shsym(sh, lookup(".shstrtab", 0));
/* Main header */
eh->ident[EI_MAG0] = '\177';
eh->ident[EI_MAG1] = 'E';
eh->ident[EI_MAG2] = 'L';
eh->ident[EI_MAG3] = 'F';
eh->ident[EI_CLASS] = ELFCLASS32;
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
eh->type = ET_EXEC;
eh->machine = EM_ARM;
eh->version = EV_CURRENT;
eh->entry = entryvalue();
if(pph != nil) {
pph->filesz = eh->phnum * eh->phentsize;
pph->memsz = pph->filesz;
}
seek(cout, 0, 0);
a = 0;
a += elfwritehdr();
a += elfwritephdrs();
a += elfwriteshdrs();
cflush();
if(a+elfwriteinterp() > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break; break;
} }
cflush(); cflush();
@ -920,6 +1277,9 @@ datblk(int32 s, int32 n, int str)
break; break;
case SDATA: case SDATA:
case SBSS: case SBSS:
if(p->to.type == D_SIZE)
d += v->size;
else
d += v->value + INITDAT; d += v->value + INITDAT;
break; break;
} }
@ -2071,90 +2431,3 @@ chipfloat(Ieee *e)
return -1; return -1;
} }
uint32
linuxheadr(void)
{
uint32 a;
a = 64; /* a.out header */
a += 56; /* page zero seg */
a += 56; /* text seg */
a += 56; /* stack seg */
a += 64; /* nil sect */
a += 64; /* .text sect */
a += 64; /* .data seg */
a += 64; /* .bss sect */
a += 64; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 56; /* symdat seg */
a += 64; /* .gosymtab sect */
a += 64; /* .gopclntab sect */
}
return a;
}
void
linuxphdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align)
{
lputl(type); /* text - type = PT_LOAD */
lputl(foff); /* file offset */
lputl(vaddr); /* vaddr */
lputl(paddr); /* paddr */
lputl(filesize); /* file size */
lputl(memsize); /* memory size */
lputl(flags); /* text - flags = PF_X+PF_R */
lputl(align); /* alignment */
}
void
linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
vlong size, uint32 link, uint32 info, vlong align, vlong entsize)
{
lputl(stroffset);
lputl(type);
lputl(flags);
lputl(addr);
lputl(off);
lputl(size);
lputl(link);
lputl(info);
lputl(align);
lputl(entsize);
if(name != nil)
stroffset += strlen(name)+1;
}
int
putstrtab(char* name)
{
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
int
linuxstrtable(void)
{
int size;
size = 0;
size += putstrtab("");
size += putstrtab(".text");
size += putstrtab(".data");
size += putstrtab(".bss");
size += putstrtab(".shstrtab");
if (!debug['s']) {
size += putstrtab(".gosymtab");
size += putstrtab(".gopclntab");
}
return size;
}

View File

@ -127,6 +127,7 @@ struct Sym
uchar reachable; uchar reachable;
int32 value; int32 value;
int32 sig; int32 sig;
int32 size;
uchar used; uchar used;
uchar thumb; // thumb code uchar thumb; // thumb code
uchar foreign; // called by arm if thumb, by thumb if arm uchar foreign; // called by arm if thumb, by thumb if arm
@ -470,13 +471,20 @@ int fninc(Sym *);
void thumbcount(void); void thumbcount(void);
void reachable(void); void reachable(void);
void fnptrs(void); void fnptrs(void);
void doelf(void);
uint32 linuxheadr(void); vlong addaddr(Sym *s, Sym *t);
void linuxphdr(int type, int flags, vlong foff, vlong addsize(Sym *s, Sym *t);
vlong vaddr, vlong paddr, vlong addstring(Sym *s, char *str);
vlong filesize, vlong memsize, vlong align); vlong adduint16(Sym *s, uint16 v);
void linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off, vlong adduint32(Sym *s, uint32 v);
vlong size, uint32 link, uint32 info, vlong align, vlong entsize); vlong adduint64(Sym *s, uint64 v);
int linuxstrtable(void); vlong adduint8(Sym *s, uint8 v);
vlong adduintxx(Sym *s, uint64 v, int wid);
/* Native is little-endian */
#define LPUT(a) lputl(a)
#define WPUT(a) wputl(a)
#define VPUT(a) abort()
#endif #endif

View File

@ -31,6 +31,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/lib.h" #include "../ld/lib.h"
#include "../ld/elf.h"
#include <ar.h> #include <ar.h>
#ifndef DEFAULT #ifndef DEFAULT
@ -223,9 +224,11 @@ main(int argc, char *argv[])
INITRND = 1024; INITRND = 1024;
break; break;
case 6: /* arm elf */ case 6: /* arm elf */
HEADR = linuxheadr(); debug['d'] = 1; // no dynamic linking
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 0x8000; INITTEXT = 0x8000 + HEADR;
if(INITDAT == -1) if(INITDAT == -1)
INITDAT = 0; INITDAT = 0;
if(INITRND == -1) if(INITRND == -1)
@ -300,12 +303,15 @@ main(int argc, char *argv[])
doprof2(); doprof2();
if(debug['u']) if(debug['u'])
reachable(); reachable();
doelf();
dodata(); dodata();
if(seenthumb && debug['f']) if(seenthumb && debug['f'])
fnptrs(); fnptrs();
follow(); follow();
if(firstp == P) if(firstp == P) {
goto out; diag("no code");
errorexit();
}
softfloat(); softfloat();
noops(); noops();
span(); span();

View File

@ -92,6 +92,7 @@ dodata(void)
} }
while(v & 3) while(v & 3)
v++; v++;
s->size = v;
s->value = v; s->value = v;
if(v > MINSIZ) if(v > MINSIZ)
continue; continue;
@ -113,6 +114,7 @@ dodata(void)
continue; continue;
} }
v = s->value; v = s->value;
s->size = v;
s->value = orig; s->value = orig;
orig += v; orig += v;
} }
@ -130,6 +132,7 @@ dodata(void)
if(s->type != SBSS) if(s->type != SBSS)
continue; continue;
v = s->value; v = s->value;
s->size = v;
s->value = orig; s->value = orig;
orig += v; orig += v;
} }

View File

@ -16,6 +16,7 @@
#define SYS_exit (SYS_BASE + 1) #define SYS_exit (SYS_BASE + 1)
#define SYS_write (SYS_BASE + 4) #define SYS_write (SYS_BASE + 4)
#define SYS_gettimeofday (SYS_BASE + 78)
#define SYS_clone (SYS_BASE + 120) #define SYS_clone (SYS_BASE + 120)
#define SYS_mmap2 (SYS_BASE + 192) #define SYS_mmap2 (SYS_BASE + 192)
#define SYS_gettid (SYS_BASE + 224) #define SYS_gettid (SYS_BASE + 224)
@ -60,6 +61,33 @@ TEXT ·mmap(SB),7,$0
SWI $0 SWI $0
RET RET
TEXT gettime(SB),7,$32
/* dummy version - return 0,0 */
MOVW $0, R1
MOVW 0(FP), R0
MOVW R1, 0(R0)
MOVW R1, 4(R0)
MOVW 4(FP), R0
MOVW R1, 0(R0)
/*
attempt at real version - seg faults
MOVW $8(SP), R0
MOVW $0, R1
MOVW $SYS_gettimeofday, R7
SWI $0
MOVW 0(FP), R0 // sec
MOVW 8(SP), R1
MOVW R1, 0(R0)
MOVW 4(FP), R0 // usec
MOVW 12(SP), R1
MOVW R1, 0(R0)
*/
RET
// int32 futex(int32 *uaddr, int32 op, int32 val, // int32 futex(int32 *uaddr, int32 op, int32 val,
// struct timespec *timeout, int32 *uaddr2, int32 val2); // struct timespec *timeout, int32 *uaddr2, int32 val2);
TEXT futex(SB),7,$0 TEXT futex(SB),7,$0

View File

@ -133,7 +133,6 @@ fixedbugs/bug120.go
fixedbugs/bug121.go fixedbugs/bug121.go
fixedbugs/bug122.go fixedbugs/bug122.go
fixedbugs/bug123.go fixedbugs/bug123.go
fixedbugs/bug125.go
fixedbugs/bug126.go fixedbugs/bug126.go
fixedbugs/bug127.go fixedbugs/bug127.go
fixedbugs/bug128.go fixedbugs/bug128.go
@ -171,7 +170,6 @@ fixedbugs/bug161.go
fixedbugs/bug163.go fixedbugs/bug163.go
fixedbugs/bug164.go fixedbugs/bug164.go
fixedbugs/bug165.go fixedbugs/bug165.go
fixedbugs/bug166.go
fixedbugs/bug167.go fixedbugs/bug167.go
fixedbugs/bug168.go fixedbugs/bug168.go
fixedbugs/bug169.go fixedbugs/bug169.go
@ -287,7 +285,6 @@ method3.go
named1.go named1.go
nil.go nil.go
parentype.go parentype.go
peano.go
printbig.go printbig.go
range.go range.go
rename1.go rename1.go
@ -304,4 +301,3 @@ turing.go
utf.go utf.go
varinit.go varinit.go
vectors.go vectors.go
x.go

141
test/golden-arm.out Normal file
View File

@ -0,0 +1,141 @@
=========== 64bit.go
BUG: 64bit
=========== chan/nonblock.go
PASS
=========== cmp2.go
comparing uncomparable type []int
throw: interface compare
panic PC=xxx
[1] Segmentation fault "${@}"
=========== cmp3.go
comparing uncomparable type []int
throw: interface compare
panic PC=xxx
[1] Segmentation fault "${@}"
=========== cmp4.go
hash of unhashable type []int
throw: interface hash
panic PC=xxx
[1] Segmentation fault "${@}"
=========== cmp5.go
hash of unhashable type []int
throw: interface hash
panic PC=xxx
[1] Segmentation fault "${@}"
=========== fixedbugs/bug016.go
fixedbugs/bug016.go:11: constant -3 overflows uint
=========== fixedbugs/bug027.go
hi
0 44444
1 3333
2 222
3 11
4 0
0 44444
1 3333
2 222
3 11
4 0
=========== fixedbugs/bug067.go
ok
=========== fixedbugs/bug070.go
outer loop top k 0
inner loop top i 0
do break
broke
=========== fixedbugs/bug081.go
fixedbugs/bug081.go:9: fatal error: typecheck loop
=========== fixedbugs/bug093.go
M
=========== fixedbugs/bug113.go
interface is int, not int32
throw: interface conversion
panic PC=xxx
[1] Segmentation fault "${@}"
=========== fixedbugs/bug120.go
Bad float64 const: 123.5 want 123.5 got %¤
[1] Segmentation fault "${@}"
BUG: bug120
=========== fixedbugs/bug148.go
2 3
interface is main.T, not main.T
throw: interface conversion
panic PC=xxx
[1] Segmentation fault "${@}"
=========== fixedbugs/bug154.go
??none??: $GOROOT/pkg/linux_arm/strconv.a: failed to load: os.ERANGE
BUG: should not panic
=========== fixedbugs/bug206.go
??none??: $GOROOT/pkg/linux_arm/strconv.a: failed to load: os.ERANGE
BUG: bug206
=========== helloworld.go
hello, world
=========== interface/fail.go
*main.S is not main.I: missing method Foo
throw: interface conversion
panic PC=xxx
[1] Segmentation fault "${@}"
=========== interface/returntype.go
*main.S is not main.I2: missing method Name
throw: interface conversion
panic PC=xxx
[1] Segmentation fault "${@}"
=========== ken/intervar.go
print 1 bio 2 file 3 -- abc
=========== ken/label.go
100
=========== ken/rob1.go
9876543210
=========== ken/rob2.go
(defn foo (add 12 34))
=========== ken/simpprint.go
hello world
=========== ken/simpswitch.go
0out01out12out2aout34out4fiveout56out6aout78out89out9
=========== ken/string.go
abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz
=========== printbig.go
-9223372036854775808
9223372036854775807
=========== sigchld.go
survived SIGCHLD
=========== turing.go
Hello World!

View File

@ -89,10 +89,6 @@ done | # clean up some stack noise
/^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d /^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
/^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out /^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
case $failed in
1)
echo FAIL
esac
rm -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out rm -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
diffmsg="" diffmsg=""
if ! diff run.out golden.out if ! diff run.out golden.out
@ -106,4 +102,8 @@ inbugs=$(sed '1,/^== bugs/d' run.out | grep -c '^BUG')
echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg
if [ "$failed" != "0" ]; then
echo FAILED
fi
exit $failed exit $failed

View File

@ -13,7 +13,7 @@ X386)
;; ;;
Xarm) Xarm)
export A=5 export A=5
export E="qemu-arm -cpu cortex-a8 " export E="${GORUN:-qemu-arm -cpu cortex-a8}"
;; ;;
*) *)
echo 1>&2 run: unsupported '$GOARCH' echo 1>&2 run: unsupported '$GOARCH'
@ -42,20 +42,18 @@ do
dir=$(dirname $i) dir=$(dirname $i)
export D=$dir export D=$dir
sed '/^\/\//!q' $i | sed 's@//@@; $d' |sed 's|./\$A.out|$E &|' >$RUNFILE sed '/^\/\//!q' $i | sed 's@//@@; $d' |sed 's|./\$A.out|$E &|' >$RUNFILE
if ! sh $RUNFILE >$TMP1FILE 2>$TMP2FILE if ! sh $RUNFILE >$TMP1FILE 2>&1
then then
echo echo
echo "===========" $i echo "===========" $i
cat $TMP1FILE cat $TMP1FILE
cat $TMP2FILE
echo >&2 fail: $i echo >&2 fail: $i
touch $FAILEDFILE touch $FAILEDFILE
elif test -s $TMP1FILE || test -s $TMP2FILE elif test -s $TMP1FILE
then then
echo echo
echo "===========" $i echo "===========" $i
cat $TMP1FILE cat $TMP1FILE
cat $TMP2FILE
elif [ $dir = "bugs" ] elif [ $dir = "bugs" ]
then then
echo $i succeeded with no output. echo $i succeeded with no output.
@ -68,16 +66,27 @@ done | # clean up some stack noise
s/^pc: 0x[0-9a-f]*/pc: xxx/ s/^pc: 0x[0-9a-f]*/pc: xxx/
/^Trace\/breakpoint trap/d /^Trace\/breakpoint trap/d
/^Trace\/BPT trap/d /^Trace\/BPT trap/d
s!'$GOROOT'!$GOROOT!g
/RUNFILE/ s/line 1: *[0-9]*/line 1: PID/ /RUNFILE/ s/line 1: *[0-9]*/line 1: PID/
/^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d /^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
/^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out /^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
failed=0 failed=0
if test -f $FAILEDFILE; then rm -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
diffmsg=""
if ! diff run.out golden-arm.out
then
diffmsg="; test output differs"
failed=1 failed=1
rm -f $FAILEDFILE
fi fi
rm -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out notinbugs=$(sed '/^== bugs/q' run.out | grep -c '^BUG')
inbugs=$(sed '1,/^== bugs/d' run.out | grep -c '^BUG')
echo 2>&1 $inbugs known bugs';' $notinbugs unexpected bugs$diffmsg
if [ "$failed" != "0" ]; then
echo FAILED
fi
exit $failed exit $failed