Beispiel #1
0
void slug::slugout(int col)
{
	static int numout = 0;
	if (seen++)
		ERROR "%s slug #%d seen %d times [%s]\n",
			type_name(), serialno(), seen, headstr() WARNING;
	if (type == TM) {
		char *p;
		if ((p = strindex(bufptr(dp), (char *)"x X TM ")))
			p += strlen("x X TM ");		// skip junk
		else
			ERROR "strange TM [%s]\n", headstr() FATAL;
		fprintf(stderr, "%d\t", userpn);	// page # as prefix
		for ( ; p < bufptr((this+1)->dp); p++)
			putc(*p, stderr);
	} else if (type == COORD) {
		for (char *p = bufptr(dp); p < bufptr((this+1)->dp) && *p != '\n'; p++)
			putc(*p, stdout);
		printf(" # P %d X %d", userpn, hpos + col*offset);
		return;
	} else if (type == VBOX) {
		if (numout++ > 0)	// BUG??? might miss something
			printf("s%d\nf%d\n", size, font);
		printf("H%d\n", hpos + col*offset);
	}
	fwrite(bufptr(dp), sizeof(char), (this+1)->dp - dp, stdout);
}
Beispiel #2
0
Datei: obj.c Projekt: ALEXGUOQ/go
void
archinit(void)
{
	// 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;
	}

	switch(HEADTYPE) {
	default:
		diag("unknown -H option");
		errorexit();
	case Hplan9:	/* plan 9 */
		HEADR = 32L;
		if(INITTEXT == -1)
			INITTEXT = 4128;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hlinux:	/* ppc64 elf */
		debug['d'] = 1;	// TODO(minux): dynamic linking is not supported yet.
		elfinit();
		HEADR = ELFRESERVE;
		if(INITTEXT == -1)
			INITTEXT = 0x10000 + HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 0x10000;
		break;
	case Hnacl:
		elfinit();
		HEADR = 0x10000;
		funcalign = 16;
		if(INITTEXT == -1)
			INITTEXT = 0x20000;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 0x10000;
		break;
	}
	if(INITDAT != 0 && INITRND != 0)
		print("warning: -D0x%ux is ignored because of -R0x%ux\n",
			INITDAT, INITRND);
}
Beispiel #3
0
void slug::neutralize()
{
	switch (type) {
	case PAGE:
	case UF:
	case BF:
	case PARM:
		type = NEUTRAL;
		coalesce();
		break;
	default:
		ERROR "neutralized %d (%s) with %s\n",
			type, type_name(), headstr() WARNING;
		break;
	}
}
Beispiel #4
0
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();
}
Beispiel #5
0
void
archinit(void)
{
	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
	// Go was built; see ../../make.bash.
	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
		linkmode = LinkInternal;

	if(flag_shared)
		linkmode = LinkExternal;

	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 Hdarwin:
	case Hdragonfly:
	case Hfreebsd:
	case Hlinux:
	case Hnetbsd:
	case Hopenbsd:
	case Hsolaris:
		break;
	}
	ctxt->linkmode = linkmode;

	switch(HEADTYPE) {
	default:
		diag("unknown -H option");
		errorexit();
	case Hplan9:		/* plan 9 */
		HEADR = 32L + 8L;
		if(INITTEXT == -1)
			INITTEXT = 0x200000+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 0x200000;
		break;
	case Helf:		/* elf32 executable */
		HEADR = rnd(52L+3*32L, 16);
		if(INITTEXT == -1)
			INITTEXT = 0x80110000L;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hdarwin:		/* apple MACH */
		machoinit();
		HEADR = INITIAL_MACHO_HEADR;
		if(INITRND == -1)
			INITRND = 4096;
		if(INITTEXT == -1)
			INITTEXT = 4096+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		break;
	case Hlinux:		/* elf64 executable */
	case Hfreebsd:		/* freebsd */
	case Hnetbsd:		/* netbsd */
	case Hopenbsd:		/* openbsd */
	case Hdragonfly:	/* dragonfly */
	case Hsolaris:		/* solaris */
		elfinit();
		HEADR = ELFRESERVE;
		if(INITTEXT == -1)
			INITTEXT = (1<<22)+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hwindows:		/* PE executable */
		peinit();
		HEADR = PEFILEHEADR;
		if(INITTEXT == -1)
			INITTEXT = PEBASE+PESECTHEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = PESECTALIGN;
		break;
	}
	if(INITDAT != 0 && INITRND != 0)
		print("warning: -D0x%llux is ignored because of -R0x%ux\n",
			INITDAT, INITRND);
}
Beispiel #6
0
void slug::dump()	// print contents of a slug
{
	printf("# %d %-4.4s parm %d dv %d base %d s%d f%d H%d\n#\t\t%s\n",
		serialno(), type_name(), parm, dv, base,
		size, font, hpos, headstr());
}
Beispiel #7
0
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();
}
Beispiel #8
0
void
main(int argc, char *argv[])
{
	Binit(&bso, 1, OWRITE);
	listinit();
	memset(debug, 0, sizeof(debug));
	nerrors = 0;
	outfile = nil;
	HEADTYPE = -1;
	INITTEXT = -1;
	INITDAT = -1;
	INITRND = -1;
	INITENTRY = 0;
	LIBINITENTRY = 0;
	linkmode = LinkInternal; // TODO: LinkAuto once everything works.
	nuxiinit();

	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);
	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("O", "print pc-line tables", &debug['O']);
	flagcount("Q", "debug byte-register code gen", &debug['Q']);
	flagint32("R", "rnd: address rounding", &INITRND);
	flagcount("S", "check type signatures", &debug['S']);
	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']);
	flagcount("f", "ignore version mismatch", &debug['f']);
	flagcount("g", "disable go package data checks", &debug['g']);
	flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
	flagstr("k", "sym: set field tracking symbol", &tracksym);
	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("n", "dump symbol table", &debug['n']);
	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']);
	// TODO: link mode flag
	
	flagparse(&argc, &argv, usage);

	if(argc != 1)
		usage();

	mywhatsys();	// get goos

	if(HEADTYPE == -1)
		HEADTYPE = headtype(goos);

	switch(HEADTYPE) {
	default:
		if(linkmode == LinkAuto)
			linkmode = LinkInternal;
		if(linkmode == LinkExternal)
			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
		break;
	case Hdarwin:
	case Hfreebsd:
	case Hlinux:
	case Hnetbsd:
	case Hopenbsd:
		break;
	}

	if(outfile == nil) {
		if(HEADTYPE == Hwindows)
			outfile = "8.out.exe";
		else
			outfile = "8.out";
	}

	libinit();

	switch(HEADTYPE) {
	default:
		diag("unknown -H option");
		errorexit();

	case Hgarbunix:	/* this is garbage */
		HEADR = 20L+56L;
		if(INITTEXT == -1)
			INITTEXT = 0x40004CL;
		if(INITDAT == -1)
			INITDAT = 0x10000000L;
		if(INITRND == -1)
			INITRND = 0;
		break;
	case Hunixcoff:	/* is unix coff */
		HEADR = 0xd0L;
		if(INITTEXT == -1)
			INITTEXT = 0xd0;
		if(INITDAT == -1)
			INITDAT = 0x400000;
		if(INITRND == -1)
			INITRND = 0;
		break;
	case Hplan9x32:	/* plan 9 */
		tlsoffset = -8;
		HEADR = 32L;
		if(INITTEXT == -1)
			INITTEXT = 4096+32;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hmsdoscom:	/* MS-DOS .COM */
		HEADR = 0;
		if(INITTEXT == -1)
			INITTEXT = 0x0100;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4;
		break;
	case Hmsdosexe:	/* fake MS-DOS .EXE */
		HEADR = 0x200;
		if(INITTEXT == -1)
			INITTEXT = 0x0100;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4;
		HEADR += (INITTEXT & 0xFFFF);
		if(debug['v'])
			Bprint(&bso, "HEADR = 0x%d\n", HEADR);
		break;
	case Hdarwin:	/* apple MACH */
		/*
		 * OS X system constant - offset from %gs to our TLS.
		 * Explained in ../../pkg/runtime/cgo/gcc_darwin_386.c.
		 */
		tlsoffset = 0x468;
		machoinit();
		HEADR = INITIAL_MACHO_HEADR;
		if(INITTEXT == -1)
			INITTEXT = 4096+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hlinux:	/* elf32 executable */
	case Hfreebsd:
	case Hnetbsd:
	case Hopenbsd:
		/*
		 * ELF uses TLS offsets negative from %gs.
		 * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
		 * Also known to ../../pkg/runtime/sys_linux_386.s
		 * and ../../pkg/runtime/cgo/gcc_linux_386.c.
		 */
		tlsoffset = -8;
		elfinit();
		HEADR = ELFRESERVE;
		if(INITTEXT == -1)
			INITTEXT = 0x08048000+HEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = 4096;
		break;
	case Hwindows: /* PE executable */
		peinit();
		HEADR = PEFILEHEADR;
		if(INITTEXT == -1)
			INITTEXT = PEBASE+PESECTHEADR;
		if(INITDAT == -1)
			INITDAT = 0;
		if(INITRND == -1)
			INITRND = PESECTALIGN;
		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);

	instinit();
	zprg.link = P;
	zprg.pcond = P;
	zprg.back = 2;
	zprg.as = AGOK;
	zprg.from.type = D_NONE;
	zprg.from.index = D_NONE;
	zprg.from.scale = 1;
	zprg.to = zprg.from;

	pcstr = "%.6ux ";
	histgen = 0;
	pc = 0;
	dtype = 4;
	version = 0;
	cbp = buf.cbuf;
	cbc = sizeof(buf.cbuf);

	addlibpath("command line", "command line", argv[0], "main");
	loadlib();
	deadcode();
	patch();
	follow();
	doelf();
	if(HEADTYPE == Hdarwin)
		domacho();
	if(HEADTYPE == Hwindows)
		dope();
	dostkoff();
	dostkcheck();
	if(debug['p'])
		if(debug['1'])
			doprof1();
		else
			doprof2();
	span();
	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", nsymbol);
		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
	}
	Bflush(&bso);

	errorexit();
}
Beispiel #9
0
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;
}
Beispiel #10
0
void
relocsym(LSym *s)
{
	Reloc *r;
	LSym *rs;
	int32 i, off, siz, fl;
	vlong o;
	uchar *cast;

	ctxt->cursym = s;
	for(r=s->r; r<s->r+s->nr; r++) {
		r->done = 1;
		off = r->off;
		siz = r->siz;
		if(off < 0 || off+siz > s->np) {
			diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
			continue;
		}
		if(r->sym != S && ((r->sym->type & (SMASK | SHIDDEN)) == 0 || (r->sym->type & SMASK) == SXREF)) {
			diag("%s: not defined", r->sym->name);
			continue;
		}
		if(r->type >= 256)
			continue;
		if(r->siz == 0) // informational relocation - no work to do
			continue;

		// Solaris needs the ability to reference dynimport symbols.
		if(HEADTYPE != Hsolaris && r->sym != S && r->sym->type == SDYNIMPORT)
			diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
		if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
			diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);

		// Android emulates runtime.tlsg as a regular variable.
		if (r->type == R_TLS && strcmp(goos, "android") == 0)
			r->type = R_ADDR;

		switch(r->type) {
		default:
			o = 0;
			if(archreloc(r, s, &o) < 0)
				diag("unknown reloc %d", r->type);
			break;
		case R_TLS:
			if(linkmode == LinkInternal && iself && thechar == '5') {
				// On ELF ARM, the thread pointer is 8 bytes before
				// the start of the thread-local data block, so add 8
				// to the actual TLS offset (r->sym->value).
				// This 8 seems to be a fundamental constant of
				// ELF on ARM (or maybe Glibc on ARM); it is not
				// related to the fact that our own TLS storage happens
				// to take up 8 bytes.
				o = 8 + r->sym->value;
				break;
			}
			r->done = 0;
			o = 0;
			if(thechar != '6')
				o = r->add;
			break;
		case R_TLS_LE:
			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
				r->done = 0;
				r->sym = ctxt->tlsg;
				r->xsym = ctxt->tlsg;
				r->xadd = r->add;
				o = 0;
				if(thechar != '6')
					o = r->add;
				break;
			}
			o = ctxt->tlsoffset + r->add;
			break;

		case R_TLS_IE:
			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
				r->done = 0;
				r->sym = ctxt->tlsg;
				r->xsym = ctxt->tlsg;
				r->xadd = r->add;
				o = 0;
				if(thechar != '6')
					o = r->add;
				break;
			}
			if(iself || ctxt->headtype == Hplan9)
				o = ctxt->tlsoffset + r->add;
			else if(ctxt->headtype == Hwindows)
				o = r->add;
			else
				sysfatal("unexpected R_TLS_IE relocation for %s", headstr(ctxt->headtype));
			break;
		case R_ADDR:
			if(linkmode == LinkExternal && r->sym->type != SCONST) {
				r->done = 0;

				// set up addend for eventual relocation via outer symbol.
				rs = r->sym;
				r->xadd = r->add;
				while(rs->outer != nil) {
					r->xadd += symaddr(rs) - symaddr(rs->outer);
					rs = rs->outer;
				}
				if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil)
					diag("missing section for %s", rs->name);
				r->xsym = rs;

				o = r->xadd;
				if(iself) {
					if(thechar == '6')
						o = 0;
				} else if(HEADTYPE == Hdarwin) {
					if(rs->type != SHOSTOBJ)
						o += symaddr(rs);
				} else {
					diag("unhandled pcrel relocation for %s", headstring);
				}
				break;
			}
			o = symaddr(r->sym) + r->add;

			// On amd64, 4-byte offsets will be sign-extended, so it is impossible to
			// access more than 2GB of static data; fail at link time is better than
			// fail at runtime. See http://golang.org/issue/7980.
			// Instead of special casing only amd64, we treat this as an error on all
			// 64-bit architectures so as to be future-proof.
			if((int32)o < 0 && PtrSize > 4 && siz == 4) {
				diag("non-pc-relative relocation address is too big: %#llux", o);
				errorexit();
			}
			break;
		case R_CALL:
		case R_PCREL:
			// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
			if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != ctxt->cursym->sect) {
				r->done = 0;

				// set up addend for eventual relocation via outer symbol.
				rs = r->sym;
				r->xadd = r->add;
				while(rs->outer != nil) {
					r->xadd += symaddr(rs) - symaddr(rs->outer);
					rs = rs->outer;
				}
				r->xadd -= r->siz; // relative to address after the relocated chunk
				if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil)
					diag("missing section for %s", rs->name);
				r->xsym = rs;

				o = r->xadd;
				if(iself) {
					if(thechar == '6')
						o = 0;
				} else if(HEADTYPE == Hdarwin) {
					if(r->type == R_CALL) {
						if(rs->type != SHOSTOBJ)
							o += symaddr(rs) - rs->sect->vaddr;
						o -= r->off; // relative to section offset, not symbol
					} else {
						o += r->siz;
					}
				} else {
					diag("unhandled pcrel relocation for %s", headstring);
				}
				break;
			}
			o = 0;
			if(r->sym)
				o += symaddr(r->sym);
			// NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c
			// compiler. The expression s->value + r->off + r->siz is int32 + int32 +
			// uchar, and Plan 9 8c incorrectly treats the expression as type uint32
			// instead of int32, causing incorrect values when sign extended for adding
			// to o. The bug only occurs on Plan 9, because this C program is compiled by
			// the standard host compiler (gcc on most other systems).
			o += r->add - (s->value + r->off + (int32)r->siz);
			break;
		case R_SIZE:
			o = r->sym->size + r->add;
			break;
		}
//print("relocate %s %#llux (%#llux+%#llux, size %d) => %s %#llux +%#llx [%llx]\n", s->name, (uvlong)(s->value+off), (uvlong)s->value, (uvlong)r->off, r->siz, r->sym ? r->sym->name : "<nil>", (uvlong)symaddr(r->sym), (vlong)r->add, (vlong)o);
		switch(siz) {
		default:
			ctxt->cursym = s;
			diag("bad reloc size %#ux for %s", siz, r->sym->name);
		case 1:
			// TODO(rsc): Remove.
			s->p[off] = (int8)o;
			break;
		case 4:
			if(r->type == R_PCREL || r->type == R_CALL) {
				if(o != (int32)o)
					diag("pc-relative relocation address is too big: %#llx", o);
			} else {
				if(o != (int32)o && o != (uint32)o)
					diag("non-pc-relative relocation address is too big: %#llux", o);
			}
			fl = o;
			cast = (uchar*)&fl;
			for(i=0; i<4; i++)
				s->p[off+i] = cast[inuxi4[i]];
			break;
		case 8:
			cast = (uchar*)&o;
			for(i=0; i<8; i++)
				s->p[off+i] = cast[inuxi8[i]];
			break;
		}
	}
}