Commit 4e1896a1 authored by Kai Backman's avatar Kai Backman

Adding ARM elf support to the 5l linker.

R=rsc
APPROVED=rsc
DELTA=312  (312 added, 0 deleted, 0 changed)
OCL=27133
CL=27326
parent cb15bbe7
......@@ -64,8 +64,15 @@ asmb(void)
{
Prog *p;
int32 t, etext;
int np;
vlong va, fo, w, symo;
int strtabsize;
vlong symdatva = 0x99LL<<24;
Optab *o;
strtabsize = 0;
symo = 0;
if(debug['v'])
Bprint(&bso, "%5.2f asm\n", cputime());
Bflush(&bso);
......@@ -112,6 +119,7 @@ asmb(void)
datblk(t, etext-t, 1);
}
/* output section header strings */
curtext = P;
switch(HEADTYPE) {
case 0:
......@@ -125,6 +133,13 @@ asmb(void)
OFFSET = rnd(HEADR+textsize, 4096);
seek(cout, OFFSET, 0);
break;
case 6:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = linuxstrtable();
cflush();
t = rnd(HEADR+textsize, INITRND);
seek(cout, t, 0);
break;
}
if(dlm){
char buf[8];
......@@ -140,6 +155,7 @@ asmb(void)
}
cflush();
/* output symbol table */
symsize = 0;
lcsize = 0;
if(!debug['s']) {
......@@ -161,6 +177,11 @@ asmb(void)
OFFSET += rnd(datsize, 4096);
seek(cout, OFFSET, 0);
break;
case 6:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
symo = rnd(symo, INITRND);
seek(cout, symo + 8, 0);
break;
}
if(!debug['s'])
asmsym();
......@@ -251,6 +272,181 @@ asmb(void)
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
break;
case 6:
/* elf arm */
strnput("\177ELF", 4); /* e_ident */
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 = 0;
va = INITTEXT & ~((vlong)INITRND - 1);
w = HEADR+textsize;
linuxphdr(1, /* text - type = PT_LOAD */
1L+4L, /* text - flags = PF_X+PF_R */
0, /* file offset */
va, /* vaddr */
va, /* paddr */
w, /* file size */
w, /* memory size */
INITRND); /* alignment */
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
linuxphdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */
fo, /* file offset */
va, /* vaddr */
va, /* paddr */
w, /* file size */
w+bsssize, /* memory size */
INITRND); /* alignment */
if(!debug['s']) {
linuxphdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */
symo, /* file offset */
symdatva, /* vaddr */
symdatva, /* paddr */
8+symsize+lcsize, /* file size */
8+symsize+lcsize, /* memory size */
INITRND); /* alignment */
}
linuxphdr(0x6474e551, /* gok - type = gok */
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */
0, /* file offset */
0, /* vaddr */
0, /* paddr */
0, /* file size */
0, /* memory size */
8); /* alignment */
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 = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
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);
va = rnd(va+w, INITRND);
w = datsize;
linuxshdr(".data", /* name */
1, /* type */
3, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
fo += w;
va += w;
w = bsssize;
linuxshdr(".bss", /* name */
8, /* type */
3, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
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;
fo = symo+8;
w = symsize;
linuxshdr(".gosymtab", /* name */
1, /* type 1 = SHT_PROGBITS */
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
fo += w;
w = lcsize;
linuxshdr(".gopclntab", /* name */
1, /* type 1 = SHT_PROGBITS*/
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
break;
}
cflush();
if(debug['c']){
......@@ -306,6 +502,14 @@ wput(int32 l)
cflush();
}
void
wputl(ushort w)
{
cput(w);
cput(w>>8);
}
void
hput(int32 l)
{
......@@ -1829,3 +2033,91 @@ chipfloat(Ieee *e)
}
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;
}
......@@ -323,6 +323,7 @@ EXTERN Oprang thumboprange[ALAST];
EXTERN char* outfile;
EXTERN int32 pc;
EXTERN uchar repop[ALAST];
EXTERN uint32 stroffset;
EXTERN int32 symsize;
EXTERN Prog* textp;
EXTERN int32 textsize;
......@@ -456,6 +457,7 @@ void strnput(char*, int);
void undef(void);
void undefsym(Sym*);
void wput(int32);
void wputl(ushort w);
void xdefine(char*, int, int32);
void xfol(Prog*);
void zerosig(char*);
......@@ -471,4 +473,12 @@ void thumbcount(void);
void reachable(void);
void fnptrs(void);
uint32 linuxheadr(void);
void linuxphdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align);
void linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
vlong size, uint32 link, uint32 info, vlong align, vlong entsize);
int linuxstrtable(void);
#endif
......@@ -153,6 +153,7 @@ main(int argc, char *argv[])
HEADTYPE = 1;
if(debug['9'])
HEADTYPE = 2;
HEADTYPE = 6;
}
switch(HEADTYPE) {
default:
......@@ -212,6 +213,15 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 1024;
break;
case 6: /* arm elf */
HEADR = linuxheadr();
if(INITTEXT == -1)
INITTEXT = 0x8000+HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%lux is ignored because of -R0x%lux\n",
......
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