blob: 406019312d0ffd7fc5872a63eff27837d3f2c61c [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Writing of internal program representation to a serialized form
// so that the Go translation of these routines can do the actual
// program layout.
// The serialized form and this code support the piecewise transition
// from C to Go and will be removed along with the rest of the C code
// when it is no longer needed.
// There has been no attempt to make it particularly efficient, nor will there be.
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
/*c2go
char *mktempdir(void);
int runcmd(char**);
void removeall(char*);
*/
static void printtype(Link*, Biobuf*, int);
static void printsym(Link*, Biobuf*, LSym*);
static void printprog(Link*, Biobuf*, Prog*);
static void printaddr(Link*, Biobuf*, Addr*);
static void printhist(Link*, Biobuf*, Hist*);
static void printint(Link*, Biobuf*, int64);
static void printstr(Link*, Biobuf*, char*);
static void printptr(Link*, Biobuf*, void*);
#undef waitpid
enum
{
TypeEnd = 0,
TypeCtxt,
TypePlist,
TypeSym,
TypeProg,
TypeAddr,
TypeHist,
};
void
writeobjgo1(Link *ctxt, char *outfile)
{
int i;
char *p;
Biobuf *bw;
Plist *pl;
p = smprint("%s.goliblink.in", outfile);
bw = Bopen(p, OWRITE);
if(bw == nil)
sysfatal("writing liblinktest input: %r");
printtype(ctxt, bw, TypeCtxt);
printstr(ctxt, bw, ctxt->arch->name);
printint(ctxt, bw, ctxt->goarm);
printint(ctxt, bw, ctxt->debugasm);
printstr(ctxt, bw, ctxt->trimpath);
printptr(ctxt, bw, ctxt->plist);
printptr(ctxt, bw, ctxt->plast);
printptr(ctxt, bw, ctxt->hist);
printptr(ctxt, bw, ctxt->ehist);
for(i = 0; i < LINKHASH; i++) {
if(ctxt->hash[i] != nil) {
printint(ctxt, bw, i);
printptr(ctxt, bw, ctxt->hash[i]);
}
}
printint(ctxt, bw, -1);
printhist(ctxt, bw, ctxt->hist);
printhist(ctxt, bw, ctxt->ehist);
for(pl=ctxt->plist; pl != nil; pl = pl->link) {
printtype(ctxt, bw, TypePlist);
printptr(ctxt, bw, pl);
printint(ctxt, bw, pl->recur);
printptr(ctxt, bw, pl->name);
printptr(ctxt, bw, pl->firstpc);
printptr(ctxt, bw, pl->link);
printsym(ctxt, bw, pl->name);
printprog(ctxt, bw, pl->firstpc);
}
for(i = 0; i < LINKHASH; i++)
printsym(ctxt, bw, ctxt->hash[i]);
printtype(ctxt, bw, TypeEnd);
Bterm(bw);
}
void
writeobjgo2(Link *ctxt, char *outfile, int64 offset)
{
char *p, *env, *prog, *cmd[10];
char offsetbuf[20];
USED(ctxt);
env = getenv("GOOBJWRITER");
if(env != nil && env[0] != '\0')
prog = env;
else
prog = smprint("%s/pkg/tool/%s_%s/objwriter", getgoroot(), getgohostos(), getgohostarch());
p = smprint("%s.goliblink.in", outfile);
snprint(offsetbuf, sizeof offsetbuf, "%lld", offset);
cmd[0] = prog;
cmd[1] = p;
cmd[2] = outfile;
cmd[3] = offsetbuf;
cmd[4] = ctxt->arch->name;
cmd[5] = nil;
if(runcmd(cmd) < 0)
sysfatal("running %s: %r", prog);
env = getenv("GOOBJ");
if(env == nil || atoi(env) <= 2)
remove(p);
}
static void
printtype(Link *ctxt, Biobuf *bw, int t)
{
printint(ctxt, bw, t);
}
static void
printint(Link *ctxt, Biobuf *bw, int64 v)
{
uint64 u;
USED(ctxt);
u = (uint64)(v<<1) ^ (uint64)(v>>63);
while(u >= 0x80) {
Bputc(bw, u&0x7F | 0x80);
u >>= 7;
}
Bputc(bw, u);
}
static void
printstr(Link *ctxt, Biobuf *bw, char *s)
{
if(s == nil)
s = "";
printint(ctxt, bw, strlen(s));
Bwrite(bw, s, strlen(s));
}
static void
printptr(Link *ctxt, Biobuf *bw, void *v)
{
printint(ctxt, bw, (int64)(uintptr)v);
}
static void
printsym(Link *ctxt, Biobuf *bw, LSym *s)
{
int i;
Reloc *r;
if(s == nil || s->printed)
return;
s->printed = 1;
printtype(ctxt, bw, TypeSym);
printptr(ctxt, bw, s);
printstr(ctxt, bw, s->name);
printstr(ctxt, bw, s->extname);
printint(ctxt, bw, s->type);
printint(ctxt, bw, s->version);
printint(ctxt, bw, s->dupok);
printint(ctxt, bw, s->external);
printint(ctxt, bw, s->nosplit);
printint(ctxt, bw, s->reachable);
printint(ctxt, bw, s->cgoexport);
printint(ctxt, bw, s->special);
printint(ctxt, bw, s->stkcheck);
printint(ctxt, bw, s->hide);
printint(ctxt, bw, s->leaf);
printint(ctxt, bw, s->fnptr);
printint(ctxt, bw, s->seenglobl);
printint(ctxt, bw, s->onlist);
printint(ctxt, bw, s->symid);
printint(ctxt, bw, s->dynid);
printint(ctxt, bw, s->sig);
printint(ctxt, bw, s->plt);
printint(ctxt, bw, s->got);
printint(ctxt, bw, s->align);
printint(ctxt, bw, s->elfsym);
printint(ctxt, bw, s->args);
printint(ctxt, bw, s->locals);
printint(ctxt, bw, s->value);
printint(ctxt, bw, s->size);
printptr(ctxt, bw, s->hash);
printptr(ctxt, bw, s->allsym);
printptr(ctxt, bw, s->next);
printptr(ctxt, bw, s->sub);
printptr(ctxt, bw, s->outer);
printptr(ctxt, bw, s->gotype);
printptr(ctxt, bw, s->reachparent);
printptr(ctxt, bw, s->queue);
printstr(ctxt, bw, s->file);
printstr(ctxt, bw, s->dynimplib);
printstr(ctxt, bw, s->dynimpvers);
printptr(ctxt, bw, s->text);
printptr(ctxt, bw, s->etext);
printint(ctxt, bw, s->np);
Bwrite(bw, s->p, s->np);
printint(ctxt, bw, s->nr);
for(i=0; i<s->nr; i++) {
r = s->r+i;
printint(ctxt, bw, r->off);
printint(ctxt, bw, r->siz);
printint(ctxt, bw, r->done);
printint(ctxt, bw, r->type);
printint(ctxt, bw, r->add);
printint(ctxt, bw, r->xadd);
printptr(ctxt, bw, r->sym);
printptr(ctxt, bw, r->xsym);
}
printsym(ctxt, bw, s->hash);
printsym(ctxt, bw, s->allsym);
printsym(ctxt, bw, s->next);
printsym(ctxt, bw, s->sub);
printsym(ctxt, bw, s->outer);
printsym(ctxt, bw, s->gotype);
printsym(ctxt, bw, s->reachparent);
printsym(ctxt, bw, s->queue);
printprog(ctxt, bw, s->text);
printprog(ctxt, bw, s->etext);
for(i=0; i<s->nr; i++) {
r = s->r+i;
printsym(ctxt, bw, r->sym);
printsym(ctxt, bw, r->xsym);
}
}
static void
printprog(Link *ctxt, Biobuf *bw, Prog *p0)
{
Prog *p, *q;
for(p = p0; p != nil && !p->printed; p=p->link) {
p->printed = 1;
printtype(ctxt, bw, TypeProg);
printptr(ctxt, bw, p);
printint(ctxt, bw, p->pc);
printint(ctxt, bw, p->lineno);
printptr(ctxt, bw, p->link);
printint(ctxt, bw, p->as);
printint(ctxt, bw, p->reg);
printint(ctxt, bw, p->scond);
printint(ctxt, bw, p->width);
printaddr(ctxt, bw, &p->from);
printaddr(ctxt, bw, &p->from3);
printaddr(ctxt, bw, &p->to);
printsym(ctxt, bw, p->from.sym);
printsym(ctxt, bw, p->from.gotype);
printsym(ctxt, bw, p->to.sym);
printsym(ctxt, bw, p->to.gotype);
}
q = p;
for(p=p0; p!=q; p=p->link) {
if(p->from.type == TYPE_BRANCH)
printprog(ctxt, bw, p->from.u.branch);
if(p->to.type == TYPE_BRANCH)
printprog(ctxt, bw, p->to.u.branch);
}
}
static void
printaddr(Link *ctxt, Biobuf *bw, Addr *a)
{
static char zero[8];
printtype(ctxt, bw, TypeAddr);
printint(ctxt, bw, a->offset);
if(a->type == TYPE_FCONST) {
uint64 u;
float64 f;
f = a->u.dval;
memmove(&u, &f, 8);
printint(ctxt, bw, u);
} else
printint(ctxt, bw, 0);
if(a->type == TYPE_SCONST)
Bwrite(bw, a->u.sval, 8);
else
Bwrite(bw, zero, 8);
if(a->type == TYPE_BRANCH)
printptr(ctxt, bw, a->u.branch);
else
printptr(ctxt, bw, nil);
printptr(ctxt, bw, a->sym);
printptr(ctxt, bw, a->gotype);
printint(ctxt, bw, a->type);
printint(ctxt, bw, a->index);
printint(ctxt, bw, a->scale);
printint(ctxt, bw, a->reg);
printint(ctxt, bw, a->name);
printint(ctxt, bw, a->class);
printint(ctxt, bw, a->etype);
if(a->type == TYPE_TEXTSIZE)
printint(ctxt, bw, a->u.argsize);
else
printint(ctxt, bw, 0);
printint(ctxt, bw, a->width);
}
static void
printhist(Link *ctxt, Biobuf *bw, Hist *h)
{
if(h == nil || h->printed)
return;
h->printed = 1;
printtype(ctxt, bw, TypeHist);
printptr(ctxt, bw, h);
printptr(ctxt, bw, h->link);
if(h->name == nil)
printstr(ctxt, bw, "<pop>");
else
printstr(ctxt, bw, h->name);
printint(ctxt, bw, h->line);
printint(ctxt, bw, h->offset);
printhist(ctxt, bw, h->link);
}