blob: e0cd43529037669746b3e019f64959b4e15b71bd [file] [log] [blame]
// Inferno utils/8l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "l.h"
#define Dbufslop 100
uint32 symdatva = 0x99<<24;
uint32 stroffset;
uint32 strtabsize;
uint32 machheadr(void);
uint32 elfheadr(void);
void elfphdr(int type, int flags, uint32 foff, uint32 vaddr, uint32 paddr, uint32 filesize, uint32 memsize, uint32 align);
void elfshdr(char *name, uint32 type, uint32 flags, uint32 addr, uint32 off, uint32 size, uint32 link, uint32 info, uint32 align, uint32 entsize);
int elfstrtable(void);
void machdylink(void);
uint32 machheadr(void);
void machsect(char *name, char *seg, vlong addr, vlong size, uint32 off, uint32 align, uint32 reloc, uint32 nreloc, uint32 flag);
void machseg(char *name, uint32 vaddr, uint32 vsize, uint32 foff, uint32 fsize, uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag);
void machstack(vlong e);
void machsymseg(uint32 foffset, uint32 fsize);
int32
entryvalue(void)
{
char *a;
Sym *s;
a = INITENTRY;
if(*a >= '0' && *a <= '9')
return atolwhex(a);
s = lookup(a, 0);
if(s->type == 0)
return INITTEXT;
switch(s->type) {
case STEXT:
break;
case SDATA:
if(dlm)
return s->value+INITDAT;
default:
diag("entry not text: %s", s->name);
}
return s->value;
}
void
wputl(ushort w)
{
cput(w);
cput(w>>8);
}
void
wput(ushort w)
{
cput(w>>8);
cput(w);
}
void
lput(int32 l)
{
cput(l>>24);
cput(l>>16);
cput(l>>8);
cput(l);
}
void
lputl(int32 l)
{
cput(l);
cput(l>>8);
cput(l>>16);
cput(l>>24);
}
void
vputl(uvlong l)
{
lputl(l >> 32);
lputl(l);
}
void
strnput(char *s, int n)
{
for(; *s && n > 0; s++) {
cput(*s);
n--;
}
while(n > 0) {
cput(0);
n--;
}
}
void
asmb(void)
{
Prog *p;
int32 v, magic;
int a, np, nl, ns;
uint32 va, fo, w, symo;
uchar *op1;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
seek(cout, HEADR, 0);
pc = INITTEXT;
curp = firstp;
for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT)
curtext = p;
if(p->pc != pc) {
if(!debug['a'])
print("%P\n", curp);
diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
pc = p->pc;
}
curp = p;
asmins(p);
if(cbc < sizeof(and))
cflush();
a = (andptr - and);
if(debug['a']) {
Bprint(&bso, pcstr, pc);
for(op1 = and; op1 < andptr; op1++)
Bprint(&bso, "%.2ux", *op1 & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
if(dlm) {
if(p->as == ATEXT)
reloca = nil;
else if(reloca != nil)
diag("reloc failure: %P", curp);
}
memmove(cbp, and, a);
cbp += a;
pc += a;
cbc -= a;
}
cflush();
switch(HEADTYPE) {
default:
diag("unknown header type %d", HEADTYPE);
case 0:
seek(cout, rnd(HEADR+textsize, 8192), 0);
break;
case 1:
textsize = rnd(HEADR+textsize, 4096)-HEADR;
seek(cout, textsize+HEADR, 0);
break;
case 2:
seek(cout, HEADR+textsize, 0);
break;
case 3:
case 4:
seek(cout, HEADR+rnd(textsize, INITRND), 0);
break;
case 6:
v = HEADR+textsize;
seek(cout, v, 0);
v = rnd(v, 4096) - v;
while(v > 0) {
cput(0);
v--;
}
cflush();
break;
case 7:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = elfstrtable();
cflush();
v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0);
break;
}
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
Bflush(&bso);
if(dlm){
char buf[8];
write(cout, buf, INITDAT-textsize);
textsize = INITDAT;
}
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
if(datsize-v > sizeof(buf)-Dbufslop)
datblk(v, sizeof(buf)-Dbufslop);
else
datblk(v, datsize-v);
}
symsize = 0;
spsize = 0;
lcsize = 0;
symo = 0;
if(!debug['s']) {
if(debug['v'])
Bprint(&bso, "%5.2f sym\n", cputime());
Bflush(&bso);
switch(HEADTYPE) {
default:
case 0:
seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
break;
case 1:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
break;
case 2:
seek(cout, HEADR+textsize+datsize, 0);
break;
case 3:
case 4:
debug['s'] = 1;
symo = HEADR+textsize+datsize;
break;
case 6:
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
break;
case 7:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
symo = rnd(symo, INITRND);
break;
}
seek(cout, symo+8, 0);
if(!debug['s'])
asmsym();
if(debug['v'])
Bprint(&bso, "%5.2f sp\n", cputime());
Bflush(&bso);
if(debug['v'])
Bprint(&bso, "%5.2f pc\n", cputime());
Bflush(&bso);
if(!debug['s'])
asmlc();
if(dlm)
asmdyn();
cflush();
seek(cout, symo, 0);
lputl(symsize);
lputl(lcsize);
cflush();
}
else if(dlm){
seek(cout, HEADR+textsize+datsize, 0);
asmdyn();
cflush();
}
if(debug['v'])
Bprint(&bso, "%5.2f headr\n", cputime());
Bflush(&bso);
seek(cout, 0L, 0);
switch(HEADTYPE) {
default:
case 0: /* garbage */
lput(0x160L<<16); /* magic and sections */
lput(0L); /* time and date */
lput(rnd(HEADR+textsize, 4096)+datsize);
lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0413<<16)|0437L); /* magic and version */
lput(rnd(HEADR+textsize, 4096)); /* sizes */
lput(datsize);
lput(bsssize);
lput(entryvalue()); /* va of entry */
lput(INITTEXT-HEADR); /* va of base of text */
lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(0L);
lput(0L);
lput(0L);
lput(0L);
lput(~0L); /* gp value ?? */
break;
lputl(0); /* x */
case 1: /* unix coff */
/*
* file header
*/
lputl(0x0004014c); /* 4 sections, magic */
lputl(0); /* unix time stamp */
lputl(0); /* symbol table */
lputl(0); /* nsyms */
lputl(0x0003001c); /* flags, sizeof a.out header */
/*
* a.out header
*/
lputl(0x10b); /* magic, version stamp */
lputl(rnd(textsize, INITRND)); /* text sizes */
lputl(datsize); /* data sizes */
lputl(bsssize); /* bss sizes */
lput(entryvalue()); /* va of entry */
lputl(INITTEXT); /* text start */
lputl(INITDAT); /* data start */
/*
* text section header
*/
s8put(".text");
lputl(HEADR); /* pa */
lputl(HEADR); /* va */
lputl(textsize); /* text size */
lputl(HEADR); /* file offset */
lputl(0); /* relocation */
lputl(0); /* line numbers */
lputl(0); /* relocation, line numbers */
lputl(0x20); /* flags text only */
/*
* data section header
*/
s8put(".data");
lputl(INITDAT); /* pa */
lputl(INITDAT); /* va */
lputl(datsize); /* data size */
lputl(HEADR+textsize); /* file offset */
lputl(0); /* relocation */
lputl(0); /* line numbers */
lputl(0); /* relocation, line numbers */
lputl(0x40); /* flags data only */
/*
* bss section header
*/
s8put(".bss");
lputl(INITDAT+datsize); /* pa */
lputl(INITDAT+datsize); /* va */
lputl(bsssize); /* bss size */
lputl(0); /* file offset */
lputl(0); /* relocation */
lputl(0); /* line numbers */
lputl(0); /* relocation, line numbers */
lputl(0x80); /* flags bss only */
/*
* comment section header
*/
s8put(".comment");
lputl(0); /* pa */
lputl(0); /* va */
lputl(symsize+lcsize); /* comment size */
lputl(HEADR+textsize+datsize); /* file offset */
lputl(HEADR+textsize+datsize); /* offset of syms */
lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
lputl(0); /* relocation, line numbers */
lputl(0x200); /* flags comment only */
break;
case 2: /* plan9 */
magic = 4*11*11+7;
if(dlm)
magic |= 0x80000000;
lput(magic); /* magic */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
lput(symsize); /* nsyms */
lput(entryvalue()); /* va of entry */
lput(spsize); /* sp offsets */
lput(lcsize); /* line offsets */
break;
case 3:
/* MS-DOS .COM */
break;
case 4:
/* fake MS-DOS .EXE */
v = rnd(HEADR+textsize, INITRND)+datsize;
wputl(0x5A4D); /* 'MZ' */
wputl(v % 512); /* bytes in last page */
wputl(rnd(v, 512)/512); /* total number of pages */
wputl(0x0000); /* number of reloc items */
v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
wputl(v/16); /* size of header */
wputl(0x0000); /* minimum allocation */
wputl(0xFFFF); /* maximum allocation */
wputl(0x0000); /* initial ss value */
wputl(0x0100); /* initial sp value */
wputl(0x0000); /* complemented checksum */
v = entryvalue();
wputl(v); /* initial ip value (!) */
wputl(0x0000); /* initial cs value */
wputl(0x0000);
wputl(0x0000);
wputl(0x003E); /* reloc table offset */
wputl(0x0000); /* overlay number */
break;
case 6:
/* apple MACH */
va = 4096;
lputl(0xfeedface); /* 32-bit */
lputl(7); /* cputype - x86 */
lputl(3); /* subtype - x86 */
lputl(2); /* file type - mach executable */
nl = 4;
if (!debug['s'])
nl += 3;
if (!debug['d']) // -d = turn off "dynamic loader"
nl += 3;
lputl(nl); /* number of loads */
lputl(machheadr()-28); /* size of loads */
lputl(1); /* flags - no undefines */
machseg("__PAGEZERO",
0,va, /* vaddr vsize */
0,0, /* fileoffset filesize */
0,0, /* protects */
0,0); /* sections flags */
v = rnd(HEADR+textsize, INITRND);
machseg("__TEXT",
va, /* vaddr */
v, /* vsize */
0,v, /* fileoffset filesize */
7,5, /* protects */
1,0); /* sections flags */
machsect("__text", "__TEXT",
va+HEADR,v-HEADR, /* addr size */
HEADR,0,0,0, /* offset align reloc nreloc */
0|0x400); /* flag - some instructions */
w = datsize+bsssize;
machseg("__DATA",
va+v, /* vaddr */
w, /* vsize */
v,datsize, /* fileoffset filesize */
7,3, /* protects */
2,0); /* sections flags */
machsect("__data", "__DATA",
va+v,datsize, /* addr size */
v,0,0,0, /* offset align reloc nreloc */
0); /* flag */
machsect("__bss", "__DATA",
va+v+datsize,bsssize, /* addr size */
0,0,0,0, /* offset align reloc nreloc */
1); /* flag - zero fill */
machdylink();
machstack(entryvalue());
if (!debug['s']) {
machseg("__SYMDAT",
symdatva, /* vaddr */
8+symsize+lcsize, /* vsize */
symo, 8+symsize+lcsize, /* fileoffset filesize */
7, 5, /* protects */
0, 0); /* sections flags */
machsymseg(symo+8,symsize); /* fileoffset,filesize */
machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */
}
break;
case 7:
np = 3;
ns = 5;
if(!debug['s']) {
np++;
ns += 2;
}
/* ELF header */
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(3); /* machine = AMD64 */
lputl(1L); /* version = CURRENT */
lputl(entryvalue()); /* entry vaddr */
lputl(52L); /* offset to first phdr */
lputl(52L+32L*np); /* offset to first shdr */
lputl(0L); /* processor specific flags */
wputl(52L); /* Ehdr size */
wputl(32L); /* Phdr size */
wputl(np); /* # of Phdrs */
wputl(40L); /* Shdr size */
wputl(ns); /* # of Shdrs */
wputl(4); /* Shdr with strings */
/* prog headers */
fo = 0;
va = INITTEXT & ~((vlong)INITRND - 1);
w = HEADR+textsize;
elfphdr(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;
elfphdr(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']) {
elfphdr(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 */
}
elfphdr(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 */
/* segment headers */
elfshdr(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;
elfshdr(".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;
elfshdr(".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;
elfshdr(".bss", /* name */
8, /* type */
3, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
w = strtabsize;
elfshdr(".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;
elfshdr(".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;
elfshdr(".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();
}
void
s8put(char *n)
{
char name[8];
int i;
strncpy(name, n, sizeof(name));
for(i=0; i<sizeof(name); i++)
cput(name[i]);
}
void
cflush(void)
{
int n;
n = sizeof(buf.cbuf) - cbc;
if(n)
write(cout, buf.cbuf, n);
cbp = buf.cbuf;
cbc = sizeof(buf.cbuf);
}
void
datblk(int32 s, int32 n)
{
Prog *p;
char *cast;
int32 l, fl, j;
int i, c;
memset(buf.dbuf, 0, n+Dbufslop);
for(p = datap; p != P; p = p->link) {
curp = p;
if(!p->from.sym->reachable)
diag("unreachable symbol in datblk - %s", p->from.sym->name);
l = p->from.sym->value + p->from.offset - s;
c = p->from.scale;
i = 0;
if(l < 0) {
if(l+c <= 0)
continue;
while(l < 0) {
l++;
i++;
}
}
if(l >= n)
continue;
if(p->as != AINIT && p->as != ADYNT) {
for(j=l+(c-i)-1; j>=l; j--)
if(buf.dbuf[j]) {
print("%P\n", p);
diag("multiple initialization");
break;
}
}
switch(p->to.type) {
case D_FCONST:
switch(c) {
default:
case 4:
fl = ieeedtof(&p->to.ieee);
cast = (char*)&fl;
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi4[i]];
l++;
}
break;
case 8:
cast = (char*)&p->to.ieee;
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = cast[fnuxi8[i]];
l++;
}
break;
}
break;
case D_SCONST:
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = p->to.scon[i];
l++;
}
break;
default:
fl = p->to.offset;
if(p->to.type == D_ADDR) {
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
diag("DADDR type%P", p);
if(p->to.sym) {
if(p->to.sym->type == SUNDEF)
ckoff(p->to.sym, fl);
fl += p->to.sym->value;
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
fl += INITDAT;
if(dlm)
dynreloc(p->to.sym, l+s+INITDAT, 1);
}
}
cast = (char*)&fl;
switch(c) {
default:
diag("bad nuxi %d %d\n%P", c, i, curp);
break;
case 1:
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi1[i]];
l++;
}
break;
case 2:
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi2[i]];
l++;
}
break;
case 4:
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = cast[inuxi4[i]];
l++;
}
break;
}
break;
}
}
write(cout, buf.dbuf, n);
}
int32
rnd(int32 v, int32 r)
{
int32 c;
if(r <= 0)
return v;
v += r - 1;
c = v % r;
if(c < 0)
c += r;
v -= c;
return v;
}
void
machseg(char *name, uint32 vaddr, uint32 vsize, uint32 foff, uint32 fsize,
uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag)
{
lputl(1); /* segment 32 */
lputl(56 + 68*nsect);
strnput(name, 16);
lputl(vaddr);
lputl(vsize);
lputl(foff);
lputl(fsize);
lputl(prot1);
lputl(prot2);
lputl(nsect);
lputl(flag);
}
void
machsymseg(uint32 foffset, uint32 fsize)
{
lputl(3); /* obsolete gdb debug info */
lputl(16); /* size of symseg command */
lputl(foffset);
lputl(fsize);
}
void
machsect(char *name, char *seg, vlong addr, vlong size, uint32 off,
uint32 align, uint32 reloc, uint32 nreloc, uint32 flag)
{
strnput(name, 16);
strnput(seg, 16);
lputl(addr);
lputl(size);
lputl(off);
lputl(align);
lputl(reloc);
lputl(nreloc);
lputl(flag);
lputl(0); /* reserved */
lputl(0); /* reserved */
}
// Emit a section requesting the dynamic loader
// but giving it no work to do (an empty dynamic symbol table).
// This is enough to make the Apple tracing programs (like dtrace)
// accept the binary, so that one can run dtruss on an 8.out.
void
machdylink(void)
{
int i;
if(debug['d'])
return;
lputl(2); /* LC_SYMTAB */
lputl(24); /* byte count - 6 words*/
for(i=0; i<4; i++)
lputl(0);
lputl(11); /* LC_DYSYMTAB */
lputl(80); /* byte count - 20 words */
for(i=0; i<18; i++)
lputl(0);
lputl(14); /* LC_LOAD_DYLINKER */
lputl(32); /* byte count */
lputl(12); /* offset to string */
strnput("/usr/lib/dyld", 32-12);
}
void
machstack(vlong e)
{
int i;
lputl(5); /* unix thread */
lputl((16+4)*4); /* total byte count */
lputl(1); /* thread type - x86_THREAD_STATE32 */
lputl(16); /* word count */
for(i=0; i<16; i++) /* initial register set */
if(i == 10)
lputl(e);
else
lputl(0);
}
uint32
machheadr(void)
{
uint32 a;
enum {
Header = 28,
Seg = 56,
Sect = 68,
Symtab = 24,
Dysymtab = 80,
LoadDylinker = 32,
Stack = 80,
Symseg = 16,
};
a = Header; /* a.out header */
a += Seg; /* page zero seg */
a += Seg; /* text seg */
a += Sect; /* text sect */
a += Seg; /* data seg */
a += Sect; /* data sect */
a += Sect; /* bss sect */
if (!debug['d']) {
a += Symtab; /* symtab */
a += Dysymtab; /* dysymtab */
a += LoadDylinker; /* load dylinker */
}
a += Stack; /* stack sect */
if (!debug['s']) {
a += Seg; /* symdat seg */
a += Symseg; /* symtab seg */
a += Symseg; /* lctab seg */
}
return a;
}
uint32
elfheadr(void)
{
uint32 a;
a = 52; /* elf header */
a += 32; /* page zero seg */
a += 32; /* text seg */
a += 32; /* stack seg */
a += 40; /* nil sect */
a += 40; /* .text sect */
a += 40; /* .data seg */
a += 40; /* .bss sect */
a += 40; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 32; /* symdat seg */
a += 40; /* .gosymtab sect */
a += 40; /* .gopclntab sect */
}
return a;
}
void
elfphdr(int type, int flags, uint32 foff,
uint32 vaddr, uint32 paddr,
uint32 filesize, uint32 memsize, uint32 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
elfshdr(char *name, uint32 type, uint32 flags, uint32 addr, uint32 off,
uint32 size, uint32 link, uint32 info, uint32 align, uint32 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
elfstrtable(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;
}