void elfsetupplt(void) { Sym *plt, *got; plt = lookup(".plt", 0); got = lookup(".got.plt", 0); if(plt->size == 0) { // pushl got+4 adduint8(plt, 0xff); adduint8(plt, 0x35); addaddrplus(plt, got, 4); // jmp *got+8 adduint8(plt, 0xff); adduint8(plt, 0x25); addaddrplus(plt, got, 8); // zero pad adduint32(plt, 0); // assume got->size == 0 too addaddrplus(got, lookup(".dynamic", 0), 0); adduint32(got, 0); adduint32(got, 0); } }
void elfsetupplt(void) { Sym *plt, *got; plt = lookup(".plt", 0); got = lookup(".got.plt", 0); if(plt->size == 0) { // pushq got+8(IP) adduint8(plt, 0xff); adduint8(plt, 0x35); addpcrelplus(plt, got, 8); // jmpq got+16(IP) adduint8(plt, 0xff); adduint8(plt, 0x25); addpcrelplus(plt, got, 16); // nopl 0(AX) adduint32(plt, 0x00401f0f); // assume got->size == 0 too addaddrplus(got, lookup(".dynamic", 0), 0); adduint64(got, 0); adduint64(got, 0); } }
void adddynsym(Link *ctxt, LSym *s) { LSym *d; int t; char *name; if(s->dynid >= 0) return; if(iself) { s->dynid = nelfsym++; d = linklookup(ctxt, ".dynsym", 0); name = s->extname; adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(ctxt, d, t); /* reserved */ adduint8(ctxt, d, 0); /* section where symbol is defined */ if(s->type == SDYNIMPORT) adduint16(ctxt, d, SHN_UNDEF); else adduint16(ctxt, d, 1); /* value */ if(s->type == SDYNIMPORT) adduint64(ctxt, d, 0); else addaddr(ctxt, d, s); /* size of object */ adduint64(ctxt, d, s->size); if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(linklookup(ctxt, ".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); } else if(HEADTYPE == Hwindows) { // already taken care of } else { diag("adddynsym: unsupported binary format"); } }
void dynrelocsym(Sym *s) { Reloc *r; Sym *rel; Sym *got; if(HEADTYPE == Hwindows) { Sym *rel, *targ; rel = lookup(".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(rel, 0xff); adduint8(rel, 0x25); addaddr(rel, targ); adduint8(rel, 0x90); adduint8(rel, 0x90); } else { adduint8(rel, 0xff); adduint8(rel, 0x24); adduint8(rel, 0x25); addaddrplus4(rel, targ, 0); adduint8(rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } got = rel = nil; if(flag_shared) { rel = lookuprel(); got = lookup(".got", 0); } s->rel_ro = 0; for(r=s->r; r<s->r+s->nr; r++) { if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) adddynrel(s, r); if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR && (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) { // Create address based RELATIVE relocation adddynrela(rel, s, r); if(s->type < SNOPTRDATA) s->rel_ro = 1; } } }
void dynrelocsym(LSym *s) { Reloc *r; if(HEADTYPE == Hwindows) { LSym *rel, *targ; rel = linklookup(ctxt, ".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(targ == nil) continue; if(!targ->reachable) diag("internal inconsistency: dynamic symbol %s is not reachable.", targ->name); if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(ctxt, rel, 0xff); adduint8(ctxt, rel, 0x25); addaddr(ctxt, rel, targ); adduint8(ctxt, rel, 0x90); adduint8(ctxt, rel, 0x90); } else { adduint8(ctxt, rel, 0xff); adduint8(ctxt, rel, 0x24); adduint8(ctxt, rel, 0x25); addaddrplus4(ctxt, rel, targ, 0); adduint8(ctxt, rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } for(r=s->r; r<s->r+s->nr; r++) { if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) { if(r->sym != S && !r->sym->reachable) diag("internal inconsistency: dynamic symbol %s is not reachable.", r->sym->name); adddynrel(s, r); } } }
static void addpltsym(Sym *s) { Sym *plt, *got, *rel; if(s->plt >= 0) return; adddynsym(s); if(iself) { plt = lookup(".plt", 0); got = lookup(".got.plt", 0); rel = lookup(".rel.plt", 0); if(plt->size == 0) elfsetupplt(); // jmpq *got+size adduint8(plt, 0xff); adduint8(plt, 0x25); addaddrplus(plt, got, got->size); // add to got: pointer to current pos in plt addaddrplus(got, plt, plt->size); // pushl $x adduint8(plt, 0x68); adduint32(plt, rel->size); // jmp .plt adduint8(plt, 0xe9); adduint32(plt, -(plt->size+4)); // rel addaddrplus(rel, got, got->size-4); adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT)); s->plt = plt->size - 16; } else if(HEADTYPE == Hdarwin) { // Same laziness as in 6l. Sym *plt; plt = lookup(".plt", 0); addgotsym(s); adduint32(lookup(".linkedit.plt", 0), s->dynid); // jmpq *got+size(IP) s->plt = plt->size; adduint8(plt, 0xff); adduint8(plt, 0x25); addaddrplus(plt, lookup(".got", 0), s->got); } else { diag("addpltsym: unsupported binary format"); } }
void dynrelocsym(Sym *s) { Reloc *r; if(HEADTYPE == Hwindows) { Sym *rel, *targ; rel = lookup(".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(rel, 0xff); adduint8(rel, 0x25); addaddr(rel, targ); adduint8(rel, 0x90); adduint8(rel, 0x90); } else { adduint8(rel, 0xff); adduint8(rel, 0x24); adduint8(rel, 0x25); addaddrplus4(rel, targ, 0); adduint8(rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } for(r=s->r; r<s->r+s->nr; r++) if(r->sym->type == SDYNIMPORT || r->type >= 256) adddynrel(s, r); }
void adddynsym(Sym *s) { Sym *d; int t; char *name; if(s->dynid >= 0) return; if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->extname; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(s->type == SDYNIMPORT) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); } else if(HEADTYPE == Hwindows) { // already taken care of } else { diag("adddynsym: unsupported binary format"); } }
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 adddynsym(Sym *s) { Sym *d, *str; int t; char *name; vlong off; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { // Mach-O symbol nlist32 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps symgrow(d, ndynexp*12); } if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp() s->dynid = -s->dynid-100; off = s->dynid*12; } else { off = d->size; s->dynid = off/12; } // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); setuint32(d, off, str->size); off += 4; adduint8(str, '_'); addstring(str, name); if(s->type == SDYNIMPORT) { setuint8(d, off, 0x01); // type - N_EXT - external symbol off++; setuint8(d, off, 0); // section off++; } else { setuint8(d, off, 0x0f); off++; switch(s->type) { default: case STEXT: setuint8(d, off, 1); break; case SDATA: setuint8(d, off, 2); break; case SBSS: setuint8(d, off, 4); break; } off++; } setuint16(d, off, 0); // desc off += 2; if(s->type == SDYNIMPORT) setuint32(d, off, 0); // value else setaddr(d, off, s); off += 4; } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
static void addpltsym(Sym *s) { if(s->plt >= 0) return; adddynsym(s); if(iself) { Sym *plt, *got, *rela; plt = lookup(".plt", 0); got = lookup(".got.plt", 0); rela = lookup(".rela.plt", 0); if(plt->size == 0) elfsetupplt(); // jmpq *got+size(IP) adduint8(plt, 0xff); adduint8(plt, 0x25); addpcrelplus(plt, got, got->size); // add to got: pointer to current pos in plt addaddrplus(got, plt, plt->size); // pushq $x adduint8(plt, 0x68); adduint32(plt, (got->size-24-8)/8); // jmpq .plt adduint8(plt, 0xe9); adduint32(plt, -(plt->size+4)); // rela addaddrplus(rela, got, got->size-8); adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT)); adduint64(rela, 0); s->plt = plt->size - 16; } else if(HEADTYPE == Hdarwin) { // To do lazy symbol lookup right, we're supposed // to tell the dynamic loader which library each // symbol comes from and format the link info // section just so. I'm too lazy (ha!) to do that // so for now we'll just use non-lazy pointers, // which don't need to be told which library to use. // // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html // has details about what we're avoiding. Sym *plt; addgotsym(s); plt = lookup(".plt", 0); adduint32(lookup(".linkedit.plt", 0), s->dynid); // jmpq *got+size(IP) s->plt = plt->size; adduint8(plt, 0xff); adduint8(plt, 0x25); addpcrelplus(plt, lookup(".got", 0), s->got); } else { diag("addpltsym: unsupported binary format"); } }
void adddynsym(Sym *s) { Sym *d, *str; int t; char *name; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && s->type == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { // Mach-O symbol nlist32 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; s->dynid = d->size/12; // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); adduint32(d, str->size); adduint8(str, '_'); addstring(str, name); adduint8(d, 0x01); // type - N_EXT - external symbol adduint8(d, 0); // section adduint16(d, 0); // desc adduint32(d, 0); // value } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
void adddynsym(Sym *s) { Sym *d, *str; int t; char *name; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && s->type == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); /* reserved */ adduint8(d, 0); /* section where symbol is defined */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } /* value */ if(s->type == SDYNIMPORT) adduint64(d, 0); else addaddr(d, s); /* size of object */ adduint64(d, 0); if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) { elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(lookup(".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { // Mach-o symbol nlist64 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; s->dynid = d->size/16; // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); adduint32(d, str->size); adduint8(str, '_'); addstring(str, name); if(s->type == SDYNIMPORT) { adduint8(d, 0x01); // type - N_EXT - external symbol adduint8(d, 0); // section } else { adduint8(d, 0x0f); switch(s->type) { default: case STEXT: adduint8(d, 1); break; case SDATA: adduint8(d, 2); break; case SBSS: adduint8(d, 4); break; } } adduint16(d, 0); // desc if(s->type == SDYNIMPORT) adduint64(d, 0); // value else addaddr(d, s); } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
void main(int argc, char *argv[]) { char *p; Sym *s; Binit(&bso, 1, OWRITE); listinit(); nerrors = 0; outfile = "5.out"; HEADTYPE = -1; INITTEXT = -1; INITDAT = -1; INITRND = -1; INITENTRY = 0; linkmode = LinkAuto; nuxiinit(); p = getgoarm(); if(p != nil) goarm = atoi(p); else goarm = 6; if(goarm == 5) debug['F'] = 1; flagcount("1", "use alternate profiling code", &debug['1']); flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); flagstr("E", "sym: entry symbol", &INITENTRY); flagint32("D", "addr: data address", &INITDAT); 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']); flagcount("M", "disable software div/mod", &debug['M']); flagcount("O", "print pc-line tables", &debug['O']); flagcount("P", "debug code generation", &debug['P']); flagint32("R", "rnd: address rounding", &INITRND); flagint32("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("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); flagcount("p", "insert profiling code", &debug['p']); 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']); 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); if(argc != 1) usage(); if(flag_shared) linkmode = LinkExternal; mywhatsys(); if(HEADTYPE == -1) HEADTYPE = headtype(goos); // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when // Go was built; see ../../make.bash. if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) linkmode = LinkInternal; switch(HEADTYPE) { default: if(linkmode == LinkAuto) linkmode = LinkInternal; if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0) sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); break; case Hlinux: break; } libinit(); switch(HEADTYPE) { default: diag("unknown -H option"); errorexit(); case Hnoheader: /* no header */ HEADR = 0L; if(INITTEXT == -1) INITTEXT = 0; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 4; break; case Hrisc: /* aif for risc os */ HEADR = 128L; if(INITTEXT == -1) INITTEXT = 0x10005000 + HEADR; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 4; break; case Hplan9x32: /* plan 9 */ HEADR = 32L; if(INITTEXT == -1) INITTEXT = 4128; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 4096; break; case Hixp1200: /* boot for IXP1200 */ HEADR = 0L; if(INITTEXT == -1) INITTEXT = 0x0; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 4; break; case Hipaq: /* boot for ipaq */ HEADR = 16L; if(INITTEXT == -1) INITTEXT = 0xC0008010; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 1024; break; case Hlinux: /* arm elf */ case Hfreebsd: case Hnetbsd: debug['d'] = 0; // with dynamic linking tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m // this number is known to ../../pkg/runtime/rt0_*_arm.s elfinit(); HEADR = ELFRESERVE; if(INITTEXT == -1) INITTEXT = 0x10000 + HEADR; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) INITRND = 4096; break; } if(INITDAT != 0 && INITRND != 0) print("warning: -D0x%ux is ignored because of -R0x%ux\n", INITDAT, INITRND); if(debug['v']) Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -R0x%ux\n", HEADTYPE, INITTEXT, INITDAT, INITRND); Bflush(&bso); zprg.as = AGOK; zprg.scond = 14; zprg.reg = NREG; zprg.from.name = D_NONE; zprg.from.type = D_NONE; zprg.from.reg = NREG; zprg.to = zprg.from; buildop(); histgen = 0; pc = 0; dtype = 4; version = 0; cbp = buf.cbuf; cbc = sizeof(buf.cbuf); // embed goarm to runtime.goarm s = lookup("runtime.goarm", 0); s->dupok = 1; adduint8(s, goarm); addlibpath("command line", "command line", argv[0], "main"); loadlib(); // mark some functions that are only referenced after linker code editing if(debug['F']) mark(rlookup("_sfloat", 0)); mark(lookup("runtime.read_tls_fallback", 0)); deadcode(); if(textp == nil) { diag("no code"); errorexit(); } patch(); if(debug['p']) if(debug['1']) doprof1(); else doprof2(); doelf(); follow(); softfloat(); // 5l -Z means zero the stack frame on entry. // This slows down function calls but can help avoid // false positives in garbage collection. if(debug['Z']) dozerostk(); noops(); // generate stack split prolog, handle div/mod, etc. dostkcheck(); span(); addexport(); // textaddress() functionality is handled in span() pclntab(); symtab(); dodata(); address(); doweak(); reloc(); asmb(); undef(); hostlink(); if(debug['c']) print("ARM size = %d\n", armsize); if(debug['v']) { Bprint(&bso, "%5.2f cpu time\n", cputime()); Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); } Bflush(&bso); errorexit(); }
static void proggenemit(ProgGen *g, uint8 v) { adduint8(ctxt, g->s, v); }