void outcode(void) { int f; Biobuf b; f = open(outfile, OWRITE); if(f < 0) { diag(Z, "cannot open %s", outfile); return; } Binit(&b, f, OWRITE); Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); if(pragcgobuf.to > pragcgobuf.start) { Bprint(&b, "\n"); Bprint(&b, "$$ // exports\n\n"); Bprint(&b, "$$ // local types\n\n"); Bprint(&b, "$$ // cgo\n"); Bprint(&b, "%s", fmtstrflush(&pragcgobuf)); Bprint(&b, "\n$$\n\n"); } Bprint(&b, "!\n"); linkwriteobj(ctxt, &b); Bterm(&b); close(f); lastp = P; }
void linkarchinit(void) { thestring = getgoarch(); if(strcmp(thestring, "ppc64le") == 0) thelinkarch = &linkppc64le; else thelinkarch = &linkppc64; }
int assemble(char *file) { char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); Bprint(&obuf, "!\n"); for(pass = 1; pass <= 2; pass++) { pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); if(nerrors) return nerrors; } linkwriteobj(ctxt, &obuf); Bflush(&obuf); return 0; }
void main(int argc, char *argv[]) { char *p; thechar = '6'; thestring = "amd64"; // Allow GOARCH=thestring or GOARCH=thestringsuffix, // but not other values. p = getgoarch(); if(strncmp(p, thestring, strlen(thestring)) != 0) sysfatal("cannot use %cc with GOARCH=%s", thechar, p); if(strcmp(p, "amd64p32") == 0) thelinkarch = &linkamd64p32; ctxt = linknew(thelinkarch); ctxt->diag = yyerror; ctxt->bso = &bstdout; ctxt->enforce_data_order = 1; Binit(&bstdout, 1, OWRITE); listinit6(); fmtinstall('L', Lconv); ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; setinclude("."); flagfn1("D", "name[=value]: add #define", dodef); flagfn1("I", "dir: add dir to include path", setinclude); flagcount("S", "print assembly and machine code", &debug['S']); flagcount("m", "debug preprocessor macros", &debug['m']); flagstr("o", "file: set output file", &outfile); flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath); flagparse(&argc, &argv, usage); ctxt->debugasm = debug['S']; if(argc < 1) usage(); if(argc > 1){ print("can't assemble multiple files\n"); errorexit(); } if(assemble(argv[0])) errorexit(); Bflush(&bstdout); exits(0); }
void dumpobj(void) { NodeList *externs, *tmp; char arhdr[ArhdrSize]; vlong startobj, size; Sym *zero; bout = Bopen(outfile, OWRITE); if(bout == nil) { flusherrors(); print("can't create %s: %r\n", outfile); errorexit(); } startobj = 0; if(writearchive) { Bwrite(bout, "!<arch>\n", 8); memset(arhdr, 0, sizeof arhdr); Bwrite(bout, arhdr, sizeof arhdr); startobj = Boffset(bout); } Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); dumpexport(); if(writearchive) { Bflush(bout); size = Boffset(bout) - startobj; if(size&1) Bputc(bout, 0); Bseek(bout, startobj - ArhdrSize, 0); formathdr(arhdr, "__.PKGDEF", size); Bwrite(bout, arhdr, ArhdrSize); Bflush(bout); Bseek(bout, startobj + size + (size&1), 0); memset(arhdr, 0, ArhdrSize); Bwrite(bout, arhdr, ArhdrSize); startobj = Boffset(bout); Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); } Bprint(bout, "\n!\n"); externs = nil; if(externdcl != nil) externs = externdcl->end; dumpglobls(); dumptypestructs(); // Dump extra globals. tmp = externdcl; if(externs != nil) externdcl = externs->next; dumpglobls(); externdcl = tmp; zero = pkglookup("zerovalue", runtimepkg); ggloblsym(zero, zerosize, 1, 1); dumpdata(); writeobj(ctxt, bout); if(writearchive) { Bflush(bout); size = Boffset(bout) - startobj; if(size&1) Bputc(bout, 0); Bseek(bout, startobj - ArhdrSize, 0); snprint(namebuf, sizeof namebuf, "_go_.%c", thechar); formathdr(arhdr, namebuf, size); Bwrite(bout, arhdr, ArhdrSize); } Bterm(bout); }
Link* linknew(LinkArch *arch) { Link *ctxt; char *p; char buf[1024]; nuxiinit(); ctxt = emallocz(sizeof *ctxt); ctxt->arch = arch; ctxt->version = HistVersion; ctxt->goroot = getgoroot(); ctxt->goroot_final = getenv("GOROOT_FINAL"); if(ctxt->goroot_final != nil && ctxt->goroot_final[0] == '\0') ctxt->goroot_final = nil; p = getgoarch(); if(strcmp(p, arch->name) != 0) sysfatal("invalid goarch %s (want %s)", p, arch->name); if(getwd(buf, sizeof buf) == 0) strcpy(buf, "/???"); if(yy_isalpha(buf[0]) && buf[1] == ':') { // On Windows. ctxt->windows = 1; // Canonicalize path by converting \ to / (Windows accepts both). for(p=buf; *p; p++) if(*p == '\\') *p = '/'; } ctxt->pathname = strdup(buf); ctxt->headtype = headtype(getgoos()); if(ctxt->headtype < 0) sysfatal("unknown goos %s", getgoos()); // Record thread-local storage offset. // TODO(rsc): Move tlsoffset back into the linker. switch(ctxt->headtype) { default: sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype)); case Hplan9: ctxt->tlsoffset = -2*ctxt->arch->ptrsize; break; case Hwindows: break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: case Hdragonfly: case Hsolaris: /* * ELF uses TLS offset negative from FS. * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). * Known to low-level assembly in package runtime and runtime/cgo. */ ctxt->tlsoffset = -2*ctxt->arch->ptrsize; break; case Hnacl: switch(ctxt->arch->thechar) { default: sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name); case '6': ctxt->tlsoffset = 0; break; case '8': ctxt->tlsoffset = -8; break; } break; case Hdarwin: /* * OS X system constants - offset from 0(GS) to our TLS. * Explained in ../../pkg/runtime/cgo/gcc_darwin_*.c. */ switch(ctxt->arch->thechar) { default: sysfatal("unknown thread-local storage offset for darwin/%s", ctxt->arch->name); case '6': ctxt->tlsoffset = 0x8a0; break; case '8': ctxt->tlsoffset = 0x468; break; } break; } // On arm, record goarm. if(ctxt->arch->thechar == '5') { p = getgoarm(); if(p != nil) ctxt->goarm = atoi(p); else ctxt->goarm = 6; } return ctxt; }
void main(int argc, char *argv[]) { char *p; int c; thechar = '8'; thestring = "386"; ctxt = linknew(&link386); ctxt->diag = yyerror; ctxt->bso = &bstdout; Binit(&bstdout, 1, OWRITE); listinit8(); fmtinstall('L', Lconv); // Allow GOARCH=thestring or GOARCH=thestringsuffix, // but not other values. p = getgoarch(); if(strncmp(p, thestring, strlen(thestring)) != 0) sysfatal("cannot use %cc with GOARCH=%s", thechar, p); ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; setinclude("."); ARGBEGIN { default: c = ARGC(); if(c >= 0 && c < sizeof(debug)) debug[c] = 1; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) { if (nDlist%8 == 0) Dlist = allocn(Dlist, nDlist*sizeof(char *), 8*sizeof(char *)); Dlist[nDlist++] = p; } break; case 'I': p = ARGF(); setinclude(p); break; case 'S': ctxt->debugasm++; break; } ARGEND if(*argv == 0) { print("usage: %ca [-options] file.s\n", thechar); errorexit(); } if(argc > 1){ print("can't assemble multiple files\n"); errorexit(); } if(assemble(argv[0])) errorexit(); Bflush(&bstdout); exits(0); }