static void addsymtable(void) { IMAGE_SECTION_HEADER *h; int i, size; LSym *s; fh.NumberOfSymbols = sizeof(symlabels)/sizeof(symlabels[0]); size = nextsymoff + 4 + 18*fh.NumberOfSymbols; h = addpesection(".symtab", size, size); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_DISCARDABLE; chksectoff(h, cpos()); fh.PointerToSymbolTable = cpos(); // put COFF symbol table for (i=0; i<fh.NumberOfSymbols; i++) { s = linkrlookup(ctxt, symlabels[i], 0); strnput(s->name, 8); lputl(datoff(s->value)); wputl(textsect); wputl(0x0308); // "array of structs" cput(2); // storage class: external cput(0); // no aux entries } // put COFF string table lputl(nextsymoff + 4); for (i=0; i<nextsymoff; i++) cput(symnames[i]); strnput("", h->SizeOfRawData - size); }
void loadlib(void) { int i, w, x; LSym *s, *gmsym; char* cgostrsym; if(flag_shared) { s = linklookup(ctxt, "runtime.islibrary", 0); s->dupok = 1; adduint8(ctxt, s, 1); } loadinternal("runtime"); if(thechar == '5') loadinternal("math"); if(flag_race) loadinternal("runtime/race"); for(i=0; i<ctxt->libraryp; i++) { if(debug['v'] > 1) Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), ctxt->library[i].file, ctxt->library[i].objref); iscgo |= strcmp(ctxt->library[i].pkg, "runtime/cgo") == 0; objfile(ctxt->library[i].file, ctxt->library[i].pkg); } if(linkmode == LinkExternal && !iscgo) { // This indicates a user requested -linkmode=external. // The startup code uses an import of runtime/cgo to decide // whether to initialize the TLS. So give it one. This could // be handled differently but it's an unusual case. loadinternal("runtime/cgo"); // Pretend that we really imported the package. s = linklookup(ctxt, "go.importpath.runtime/cgo.", 0); s->type = SDATA; s->dupok = 1; s->reachable = 1; // Provided by the code that imports the package. // Since we are simulating the import, we have to provide this string. cgostrsym = "go.string.\"runtime/cgo\""; if(linkrlookup(ctxt, cgostrsym, 0) == nil) addstrdata(cgostrsym, "runtime/cgo"); } if(linkmode == LinkAuto) { if(iscgo && externalobj) linkmode = LinkExternal; else linkmode = LinkInternal; } if(linkmode == LinkInternal) { // Drop all the cgo_import_static declarations. // Turns out we won't be needing them. for(s = ctxt->allsym; s != S; s = s->allsym) if(s->type == SHOSTOBJ) { // If a symbol was marked both // cgo_import_static and cgo_import_dynamic, // then we want to make it cgo_import_dynamic // now. if(s->extname != nil && s->dynimplib != nil && s->cgoexport == 0) { s->type = SDYNIMPORT; } else s->type = 0; } } gmsym = linklookup(ctxt, "runtime.tlsgm", 0); gmsym->type = STLSBSS; gmsym->size = 2*PtrSize; gmsym->hide = 1; gmsym->reachable = 1; // Now that we know the link mode, trim the dynexp list. x = CgoExportDynamic; if(linkmode == LinkExternal) x = CgoExportStatic; w = 0; for(i=0; i<ndynexp; i++) if(dynexp[i]->cgoexport & x) dynexp[w++] = dynexp[i]; ndynexp = w; // In internal link mode, read the host object files. if(linkmode == LinkInternal) hostobjs(); else hostlinksetup(); // We've loaded all the code now. // If there are no dynamic libraries needed, gcc disables dynamic linking. // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13) // assumes that a dynamic binary always refers to at least one dynamic library. // Rather than be a source of test cases for glibc, disable dynamic linking // the same way that gcc would. // // Exception: on OS X, programs such as Shark only work with dynamic // binaries, so leave it enabled on OS X (Mach-O) binaries. // Also leave it enabled on Solaris which doesn't support // statically linked binaries. if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris) debug['d'] = 1; importcycles(); }
void main(int argc, char *argv[]) { linkarchinit(); ctxt = linknew(thelinkarch); ctxt->thechar = thechar; ctxt->thestring = thestring; ctxt->diag = diag; ctxt->bso = &bso; Binit(&bso, 1, OWRITE); listinit(); memset(debug, 0, sizeof(debug)); nerrors = 0; outfile = nil; HEADTYPE = -1; INITTEXT = -1; INITDAT = -1; INITRND = -1; INITENTRY = 0; linkmode = LinkAuto; nuxiinit(); if(thechar == '5' && ctxt->goarm == 5) debug['F'] = 1; flagcount("1", "use alternate profiling code", &debug['1']); if(thechar == '6') flagcount("8", "assume 64-bit addresses", &debug['8']); flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); flagint64("D", "addr: data address", &INITDAT); flagstr("E", "sym: entry symbol", &INITENTRY); if(thechar == '5') flagcount("G", "debug pseudo-ops", &debug['G']); flagfn1("I", "interp: set ELF interp", setinterp); flagfn1("L", "dir: add dir to library path", Lflag); flagfn1("H", "head: header type", setheadtype); flagcount("K", "add stack underflow checks", &debug['K']); if(thechar == '5') flagcount("M", "disable software div/mod", &debug['M']); flagcount("O", "print pc-line tables", &debug['O']); flagcount("Q", "debug byte-register code gen", &debug['Q']); if(thechar == '5') flagcount("P", "debug code generation", &debug['P']); flagint32("R", "rnd: address rounding", &INITRND); flagcount("S", "check type signatures", &debug['S']); flagint64("T", "addr: text address", &INITTEXT); flagfn0("V", "print version and exit", doversion); flagcount("W", "disassemble input", &debug['W']); flagfn2("X", "name value: define string data", addstrdata); flagcount("Z", "clear stack frame on entry", &debug['Z']); flagcount("a", "disassemble output", &debug['a']); flagcount("c", "dump call graph", &debug['c']); flagcount("d", "disable dynamic executable", &debug['d']); flagstr("extld", "linker to run in external mode", &extld); flagstr("extldflags", "flags for external linker", &extldflags); flagcount("f", "ignore version mismatch", &debug['f']); flagcount("g", "disable go package data checks", &debug['g']); flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix); flagstr("k", "sym: set field tracking symbol", &tracksym); flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); flagcount("n", "dump symbol table", &debug['n']); flagstr("o", "outfile: set output file", &outfile); flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); flagcount("race", "enable race detector", &flag_race); flagcount("s", "disable symbol table", &debug['s']); if(thechar == '5' || thechar == '6') flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared); flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); flagcount("u", "reject unsafe packages", &debug['u']); flagcount("v", "print link trace", &debug['v']); flagcount("w", "disable DWARF generation", &debug['w']); flagparse(&argc, &argv, usage); ctxt->bso = &bso; ctxt->debugdivmod = debug['M']; ctxt->debugfloat = debug['F']; ctxt->debughist = debug['O']; ctxt->debugpcln = debug['O']; ctxt->debugread = debug['W']; ctxt->debugstack = debug['K']; ctxt->debugvlog = debug['v']; if(argc != 1) usage(); if(outfile == nil) { if(HEADTYPE == Hwindows) outfile = smprint("%c.out.exe", thechar); else outfile = smprint("%c.out", thechar); } libinit(); // creates outfile if(HEADTYPE == -1) HEADTYPE = headtype(goos); ctxt->headtype = HEADTYPE; if (headstring == nil) headstring = headstr(HEADTYPE); archinit(); ctxt->debugfloat = debug['F']; if(debug['v']) Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n", HEADTYPE, INITTEXT, INITDAT, INITRND); Bflush(&bso); cbp = buf.cbuf; cbc = sizeof(buf.cbuf); addlibpath(ctxt, "command line", "command line", argv[0], "main"); loadlib(); if(thechar == '5') { // mark some functions that are only referenced after linker code editing if(debug['F']) mark(linkrlookup(ctxt, "_sfloat", 0)); mark(linklookup(ctxt, "runtime.read_tls_fallback", 0)); } deadcode(); callgraph(); paramspace = "SP"; /* (FP) now (SP) on output */ doelf(); if(HEADTYPE == Hdarwin) domacho(); dostkcheck(); if(HEADTYPE == Hwindows) dope(); addexport(); textaddress(); pclntab(); symtab(); dodata(); address(); doweak(); reloc(); asmb(); undef(); hostlink(); if(debug['v']) { Bprint(&bso, "%5.2f cpu time\n", cputime()); Bprint(&bso, "%d symbols\n", ctxt->nsymbol); Bprint(&bso, "%d sizeof adr\n", sizeof(Addr)); Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); Bprint(&bso, "%lld liveness data\n", liveness); } Bflush(&bso); errorexit(); }