mirror of https://github.com/golang/go.git
918 lines
18 KiB
C
918 lines
18 KiB
C
// Inferno utils/6l/asm.c
|
|
// http://code.google.com/p/inferno-os/source/browse/utils/6l/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
|
|
|
|
#define PADDR(a) ((uint32)(a) & ~0x80000000)
|
|
|
|
vlong
|
|
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
|
|
llput(vlong v)
|
|
{
|
|
lput(v>>32);
|
|
lput(v);
|
|
}
|
|
|
|
void
|
|
lputl(int32 l)
|
|
{
|
|
cput(l);
|
|
cput(l>>8);
|
|
cput(l>>16);
|
|
cput(l>>24);
|
|
}
|
|
|
|
void
|
|
llputl(vlong v)
|
|
{
|
|
lputl(v);
|
|
lputl(v>>32);
|
|
}
|
|
|
|
void
|
|
strnput(char *s, int n)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<n; i++) {
|
|
cput(*s);
|
|
if(*s != 0)
|
|
s++;
|
|
}
|
|
}
|
|
|
|
void
|
|
asmb(void)
|
|
{
|
|
Prog *p;
|
|
int32 v, magic;
|
|
int a;
|
|
uchar *op1;
|
|
vlong vl, va, fo, w;
|
|
int strtabsize;
|
|
|
|
strtabsize = 0;
|
|
|
|
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 %llux sb %llux in %s", p->pc, pc, TNAME);
|
|
pc = p->pc;
|
|
}
|
|
curp = p;
|
|
asmins(p);
|
|
a = (andptr - and);
|
|
if(cbc < a)
|
|
cflush();
|
|
if(debug['a']) {
|
|
Bprint(&bso, pcstr, pc);
|
|
for(op1 = and; op1 < andptr; op1++)
|
|
Bprint(&bso, "%.2ux", *op1);
|
|
for(; op1 < and+Maxand; op1++)
|
|
Bprint(&bso, " ");
|
|
Bprint(&bso, "%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 %ld", HEADTYPE);
|
|
case 2:
|
|
case 5:
|
|
seek(cout, HEADR+textsize, 0);
|
|
break;
|
|
case 6:
|
|
debug['8'] = 1; /* 64-bit addresses */
|
|
v = HEADR+textsize;
|
|
myseek(cout, v);
|
|
v = rnd(v, 4096) - v;
|
|
while(v > 0) {
|
|
cput(0);
|
|
v--;
|
|
}
|
|
cflush();
|
|
break;
|
|
|
|
case 7:
|
|
debug['8'] = 1; /* 64-bit addresses */
|
|
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
|
|
strtabsize = linuxstrtable();
|
|
cflush();
|
|
v = rnd(HEADR+textsize, INITRND);
|
|
myseek(cout, v);
|
|
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;
|
|
if(!debug['s']) {
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f sym\n", cputime());
|
|
Bflush(&bso);
|
|
switch(HEADTYPE) {
|
|
default:
|
|
case 2:
|
|
case 5:
|
|
debug['s'] = 1;
|
|
seek(cout, HEADR+textsize+datsize, 0);
|
|
break;
|
|
case 6:
|
|
seek(cout, rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND), 0);
|
|
break;
|
|
case 7:
|
|
seek(cout, rnd(HEADR+textsize, INITRND)+datsize+strtabsize, 0);
|
|
break;
|
|
}
|
|
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();
|
|
} 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 2: /* plan9 */
|
|
magic = 4*26*26+7;
|
|
magic |= 0x00008000; /* fat header */
|
|
if(dlm)
|
|
magic |= 0x80000000; /* dlm */
|
|
lput(magic); /* magic */
|
|
lput(textsize); /* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(symsize); /* nsyms */
|
|
vl = entryvalue();
|
|
lput(PADDR(vl)); /* va of entry */
|
|
lput(spsize); /* sp offsets */
|
|
lput(lcsize); /* line offsets */
|
|
llput(vl); /* va of entry */
|
|
break;
|
|
case 3: /* plan9 */
|
|
magic = 4*26*26+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 5:
|
|
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(62); /* machine = AMD64 */
|
|
lputl(1L); /* version = CURRENT */
|
|
lputl(PADDR(entryvalue())); /* entry vaddr */
|
|
lputl(52L); /* offset to first phdr */
|
|
lputl(0L); /* offset to first shdr */
|
|
lputl(0L); /* processor specific flags */
|
|
wputl(52); /* Ehdr size */
|
|
wputl(32); /* Phdr size */
|
|
wputl(3); /* # of Phdrs */
|
|
wputl(40); /* Shdr size */
|
|
wputl(0); /* # of Shdrs */
|
|
wputl(0); /* Shdr string size */
|
|
|
|
lputl(1L); /* text - type = PT_LOAD */
|
|
lputl(HEADR); /* file offset */
|
|
lputl(INITTEXT); /* vaddr */
|
|
lputl(PADDR(INITTEXT)); /* paddr */
|
|
lputl(textsize); /* file size */
|
|
lputl(textsize); /* memory size */
|
|
lputl(0x05L); /* protections = RX */
|
|
lputl(INITRND); /* alignment */
|
|
|
|
lputl(1L); /* data - type = PT_LOAD */
|
|
lputl(HEADR+textsize); /* file offset */
|
|
lputl(INITDAT); /* vaddr */
|
|
lputl(PADDR(INITDAT)); /* paddr */
|
|
lputl(datsize); /* file size */
|
|
lputl(datsize+bsssize); /* memory size */
|
|
lputl(0x06L); /* protections = RW */
|
|
lputl(INITRND); /* alignment */
|
|
|
|
lputl(0L); /* data - type = PT_NULL */
|
|
lputl(HEADR+textsize+datsize); /* file offset */
|
|
lputl(0L);
|
|
lputl(0L);
|
|
lputl(symsize); /* symbol table size */
|
|
lputl(lcsize); /* line number size */
|
|
lputl(0x04L); /* protections = R */
|
|
lputl(0x04L); /* alignment */
|
|
break;
|
|
case 6:
|
|
/* apple MACH */
|
|
va = 4096;
|
|
|
|
lputl(0xfeedfacf); /* 64-bit */
|
|
lputl((1<<24)|7); /* cputype - x86/ABI64 */
|
|
lputl(3); /* subtype - x86 */
|
|
lputl(2); /* file type - mach executable */
|
|
if (debug['s'])
|
|
lputl(4); /* number of loads */
|
|
else
|
|
lputl(6); /* number of loads */
|
|
lputl(machheadr()-32); /* size of loads */
|
|
lputl(1); /* flags - no undefines */
|
|
lputl(0); /* reserved */
|
|
|
|
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 */
|
|
|
|
machstack(va+HEADR);
|
|
|
|
if (!debug['s']) {
|
|
v += rnd(datsize, INITRND);
|
|
machsymseg(v,symsize); /* fileoffset,filesize */
|
|
v += symsize;
|
|
machsymseg(v,lcsize); /* fileoffset,filesize */
|
|
}
|
|
break;
|
|
case 7:
|
|
/* elf amd-64 */
|
|
strnput("\177ELF", 4); /* e_ident */
|
|
cput(2); /* class = 64 bit */
|
|
cput(1); /* data = LSB */
|
|
cput(1); /* version = CURRENT */
|
|
strnput("", 9);
|
|
|
|
wputl(2); /* type = EXEC */
|
|
wputl(62); /* machine = AMD64 */
|
|
lputl(1L); /* version = CURRENT */
|
|
llputl(entryvalue()); /* entry vaddr */
|
|
llputl(64L); /* offset to first phdr */
|
|
llputl(64L+56*3); /* offset to first shdr */
|
|
lputl(0L); /* processor specific flags */
|
|
wputl(64); /* Ehdr size */
|
|
wputl(56); /* Phdr size */
|
|
wputl(3); /* # of Phdrs */
|
|
wputl(64); /* 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 */
|
|
|
|
linuxphdr(0x6474e551, /* gok - type = gok */
|
|
1L+2L+4L, /* gok - flags = PF_X+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 = 0;
|
|
va = INITRND;
|
|
w = HEADR+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 */
|
|
8, /* align */
|
|
0); /* entsize */
|
|
|
|
if (debug['s'])
|
|
break;
|
|
|
|
fo += w;
|
|
w = symsize;
|
|
|
|
linuxshdr(".gosymtab", /* name */
|
|
7, /* type */
|
|
0, /* flags */
|
|
0, /* addr */
|
|
fo, /* off */
|
|
w, /* size */
|
|
0, /* link */
|
|
0, /* info */
|
|
8, /* align */
|
|
24); /* entsize */
|
|
|
|
fo += w;
|
|
w = lcsize;
|
|
|
|
linuxshdr(".gopclntab", /* name */
|
|
7, /* type */
|
|
0, /* flags */
|
|
0, /* addr */
|
|
fo, /* off */
|
|
w, /* size */
|
|
0, /* link */
|
|
0, /* info */
|
|
8, /* align */
|
|
24); /* entsize */
|
|
break;
|
|
}
|
|
cflush();
|
|
}
|
|
|
|
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
|
|
outa(int n, uchar *cast, uchar *map, vlong l)
|
|
{
|
|
int i, j;
|
|
|
|
Bprint(&bso, pcstr, l);
|
|
for(i=0; i<n; i++) {
|
|
j = i;
|
|
if(map != nil)
|
|
j = map[j];
|
|
Bprint(&bso, "%.2ux", cast[j]);
|
|
}
|
|
for(; i<Maxand; i++)
|
|
Bprint(&bso, " ");
|
|
Bprint(&bso, "%P\n", curp);
|
|
}
|
|
|
|
void
|
|
datblk(int32 s, int32 n)
|
|
{
|
|
Prog *p;
|
|
uchar *cast;
|
|
int32 l, fl, j;
|
|
vlong o;
|
|
int i, c;
|
|
|
|
memset(buf.dbuf, 0, n+Dbufslop);
|
|
for(p = datap; p != P; p = p->link) {
|
|
curp = p;
|
|
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 = (uchar*)&fl;
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, fnuxi4, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi4[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 8:
|
|
cast = (uchar*)&p->to.ieee;
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, fnuxi8, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi8[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case D_SCONST:
|
|
if(debug['a'] && i == 0)
|
|
outa(c, (uchar*)p->to.scon, nil, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = p->to.scon[i];
|
|
l++;
|
|
}
|
|
break;
|
|
default:
|
|
o = 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, o);
|
|
o += p->to.sym->value;
|
|
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
|
|
o += INITDAT;
|
|
if(dlm)
|
|
dynreloc(p->to.sym, l+s+INITDAT, 1);
|
|
}
|
|
}
|
|
fl = o;
|
|
cast = (uchar*)&fl;
|
|
switch(c) {
|
|
default:
|
|
diag("bad nuxi %d %d\n%P", c, i, curp);
|
|
break;
|
|
case 1:
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, inuxi1, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi1[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 2:
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, inuxi2, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi2[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 4:
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, inuxi4, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi4[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 8:
|
|
cast = (uchar*)&o;
|
|
if(debug['a'] && i == 0)
|
|
outa(c, cast, inuxi8, l+s+INITDAT);
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi8[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
write(cout, buf.dbuf, n);
|
|
}
|
|
|
|
vlong
|
|
rnd(vlong v, vlong r)
|
|
{
|
|
vlong c;
|
|
|
|
if(r <= 0)
|
|
return v;
|
|
v += r - 1;
|
|
c = v % r;
|
|
if(c < 0)
|
|
c += r;
|
|
v -= c;
|
|
return v;
|
|
}
|
|
|
|
void
|
|
vputl(vlong v)
|
|
{
|
|
lputl(v);
|
|
lputl(v>>32);
|
|
}
|
|
|
|
void
|
|
machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
|
|
uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag)
|
|
{
|
|
lputl(25); /* segment 64 */
|
|
lputl(72 + 80*nsect);
|
|
strnput(name, 16);
|
|
vputl(vaddr);
|
|
vputl(vsize);
|
|
vputl(foff);
|
|
vputl(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);
|
|
vputl(addr);
|
|
vputl(size);
|
|
lputl(off);
|
|
lputl(align);
|
|
lputl(reloc);
|
|
lputl(nreloc);
|
|
lputl(flag);
|
|
lputl(0); /* reserved */
|
|
lputl(0); /* reserved */
|
|
lputl(0); /* reserved */
|
|
}
|
|
|
|
void
|
|
machstack(vlong e)
|
|
{
|
|
int i;
|
|
|
|
lputl(5); /* unix thread */
|
|
lputl((42+4)*4); /* total byte count */
|
|
|
|
lputl(4); /* thread type */
|
|
lputl(42); /* word count */
|
|
|
|
for(i=0; i<32; i++)
|
|
lputl(0);
|
|
vputl(e);
|
|
for(i=0; i<8; i++)
|
|
lputl(0);
|
|
}
|
|
|
|
uint32
|
|
machheadr(void)
|
|
{
|
|
uint32 a;
|
|
|
|
a = 8; /* a.out header */
|
|
a += 18; /* page zero seg */
|
|
a += 18; /* text seg */
|
|
a += 20; /* text sect */
|
|
a += 18; /* data seg */
|
|
a += 20; /* data sect */
|
|
a += 20; /* bss sect */
|
|
a += 46; /* stack sect */
|
|
if (!debug['s']) {
|
|
a += 4; /* symtab seg */
|
|
a += 4; /* lctab seg */
|
|
}
|
|
|
|
return a*4;
|
|
}
|
|
|
|
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 += 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(flags); /* text - flags = PF_X+PF_R */
|
|
llputl(foff); /* file offset */
|
|
llputl(vaddr); /* vaddr */
|
|
llputl(paddr); /* paddr */
|
|
llputl(filesize); /* file size */
|
|
llputl(memsize); /* memory size */
|
|
llputl(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);
|
|
llputl(flags);
|
|
llputl(addr);
|
|
llputl(off);
|
|
llputl(size);
|
|
lputl(link);
|
|
lputl(info);
|
|
llputl(align);
|
|
llputl(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)
|
|
{
|
|
char *name;
|
|
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;
|
|
}
|