github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/6l/obj.c (about)

     1  // Inferno utils/6l/obj.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  // Reading object files.
    32  
    33  #define	EXTERN
    34  #include	"l.h"
    35  #include	"../ld/lib.h"
    36  #include	"../ld/elf.h"
    37  #include	"../ld/macho.h"
    38  #include	"../ld/dwarf.h"
    39  #include	"../ld/pe.h"
    40  #include	<ar.h>
    41  
    42  char	*noname		= "<none>";
    43  char*	thestring 	= "amd64";
    44  char*	paramspace	= "FP";
    45  
    46  Header headers[] = {
    47  	"plan9x32", Hplan9x32,
    48  	"plan9", Hplan9x64,
    49  	"elf", Helf,
    50  	"darwin", Hdarwin,
    51  	"dragonfly", Hdragonfly,
    52  	"linux", Hlinux,
    53  	"freebsd", Hfreebsd,
    54  	"netbsd", Hnetbsd,
    55  	"openbsd", Hopenbsd,
    56  	"windows", Hwindows,
    57  	"windowsgui", Hwindows,
    58  	0, 0
    59  };
    60  
    61  /*
    62   *	-Hplan9x32 -T4128 -R4096	is plan9 32-bit format
    63   *	-Hplan9 -T0x200028 -R0x200000	is plan9 64-bit format
    64   *	-Helf -T0x80110000 -R4096	is ELF32
    65   *	-Hdarwin -Tx -Rx		is apple MH-exec
    66   *	-Hdragonfly -Tx -Rx		is DragonFly elf-exec
    67   *	-Hlinux -Tx -Rx			is linux elf-exec
    68   *	-Hfreebsd -Tx -Rx		is FreeBSD elf-exec
    69   *	-Hnetbsd -Tx -Rx		is NetBSD elf-exec
    70   *	-Hopenbsd -Tx -Rx		is OpenBSD elf-exec
    71   *	-Hwindows -Tx -Rx		is MS Windows PE32+
    72   */
    73  
    74  void
    75  main(int argc, char *argv[])
    76  {
    77  	Binit(&bso, 1, OWRITE);
    78  	listinit();
    79  	memset(debug, 0, sizeof(debug));
    80  	nerrors = 0;
    81  	outfile = nil;
    82  	HEADTYPE = -1;
    83  	INITTEXT = -1;
    84  	INITDAT = -1;
    85  	INITRND = -1;
    86  	INITENTRY = 0;
    87  	linkmode = LinkAuto;
    88  	nuxiinit();
    89  
    90  	flagcount("1", "use alternate profiling code", &debug['1']);
    91  	flagcount("8", "assume 64-bit addresses", &debug['8']);
    92  	flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
    93  	flagint64("D", "addr: data address", &INITDAT);
    94  	flagstr("E", "sym: entry symbol", &INITENTRY);
    95  	flagfn1("I", "interp: set ELF interp", setinterp);
    96  	flagfn1("L", "dir: add dir to library path", Lflag);
    97  	flagfn1("H", "head: header type", setheadtype);
    98  	flagcount("K", "add stack underflow checks", &debug['K']);
    99  	flagcount("O", "print pc-line tables", &debug['O']);
   100  	flagcount("Q", "debug byte-register code gen", &debug['Q']);
   101  	flagint32("R", "rnd: address rounding", &INITRND);
   102  	flagcount("S", "check type signatures", &debug['S']);
   103  	flagint64("T", "addr: text address", &INITTEXT);
   104  	flagfn0("V", "print version and exit", doversion);
   105  	flagcount("W", "disassemble input", &debug['W']);
   106  	flagfn2("X", "name value: define string data", addstrdata);
   107  	flagcount("Z", "clear stack frame on entry", &debug['Z']);
   108  	flagcount("a", "disassemble output", &debug['a']);
   109  	flagcount("c", "dump call graph", &debug['c']);
   110  	flagcount("d", "disable dynamic executable", &debug['d']);
   111  	flagstr("extld", "linker to run in external mode", &extld);
   112  	flagstr("extldflags", "flags for external linker", &extldflags);
   113  	flagcount("f", "ignore version mismatch", &debug['f']);
   114  	flagcount("g", "disable go package data checks", &debug['g']);
   115  	flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix);
   116  	flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
   117  	flagstr("k", "sym: set field tracking symbol", &tracksym);
   118  	flagcount("n", "dump symbol table", &debug['n']);
   119  	flagstr("o", "outfile: set output file", &outfile);
   120  	flagcount("p", "insert profiling code", &debug['p']);
   121  	flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
   122  	flagcount("race", "enable race detector", &flag_race);
   123  	flagcount("s", "disable symbol table", &debug['s']);
   124  	flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared);
   125  	flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
   126  	flagcount("u", "reject unsafe packages", &debug['u']);
   127  	flagcount("v", "print link trace", &debug['v']);
   128  	flagcount("w", "disable DWARF generation", &debug['w']);
   129  	
   130  	flagparse(&argc, &argv, usage);
   131  
   132  	if(argc != 1)
   133  		usage();
   134  
   135  	mywhatsys();	// get goos
   136  
   137  	if(HEADTYPE == -1)
   138  		HEADTYPE = headtype(goos);
   139  
   140  	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
   141  	// Go was built; see ../../make.bash.
   142  	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
   143  		linkmode = LinkInternal;
   144  
   145  	if(flag_shared)
   146  		linkmode = LinkExternal;
   147  
   148  	switch(HEADTYPE) {
   149  	default:
   150  		if(linkmode == LinkAuto)
   151  			linkmode = LinkInternal;
   152  		if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
   153  			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
   154  		break;
   155  	case Hdarwin:
   156  	case Hdragonfly:
   157  	case Hfreebsd:
   158  	case Hlinux:
   159  	case Hnetbsd:
   160  	case Hopenbsd:
   161  		break;
   162  	}
   163  
   164  	if(outfile == nil) {
   165  		if(HEADTYPE == Hwindows)
   166  			outfile = "6.out.exe";
   167  		else
   168  			outfile = "6.out";
   169  	}
   170  
   171  	libinit();
   172  
   173  	switch(HEADTYPE) {
   174  	default:
   175  		diag("unknown -H option");
   176  		errorexit();
   177  	case Hplan9x32:		/* plan 9 */
   178  		HEADR = 32L;
   179  		if(INITTEXT == -1)
   180  			INITTEXT = 4096+HEADR;
   181  		if(INITDAT == -1)
   182  			INITDAT = 0;
   183  		if(INITRND == -1)
   184  			INITRND = 4096;
   185  		break;
   186  	case Hplan9x64:		/* plan 9 */
   187  		HEADR = 32L + 8L;
   188  		if(INITTEXT == -1)
   189  			INITTEXT = 0x200000+HEADR;
   190  		if(INITDAT == -1)
   191  			INITDAT = 0;
   192  		if(INITRND == -1)
   193  			INITRND = 0x200000;
   194  		break;
   195  	case Helf:		/* elf32 executable */
   196  		HEADR = rnd(52L+3*32L, 16);
   197  		if(INITTEXT == -1)
   198  			INITTEXT = 0x80110000L;
   199  		if(INITDAT == -1)
   200  			INITDAT = 0;
   201  		if(INITRND == -1)
   202  			INITRND = 4096;
   203  		break;
   204  	case Hdarwin:		/* apple MACH */
   205  		/*
   206  		 * OS X system constant - offset from 0(GS) to our TLS.
   207  		 * Explained in ../../pkg/runtime/cgo/gcc_darwin_amd64.c.
   208  		 */
   209  		tlsoffset = 0x8a0;
   210  		machoinit();
   211  		HEADR = INITIAL_MACHO_HEADR;
   212  		if(INITRND == -1)
   213  			INITRND = 4096;
   214  		if(INITTEXT == -1)
   215  			INITTEXT = 4096+HEADR;
   216  		if(INITDAT == -1)
   217  			INITDAT = 0;
   218  		break;
   219  	case Hlinux:		/* elf64 executable */
   220  	case Hfreebsd:		/* freebsd */
   221  	case Hnetbsd:		/* netbsd */
   222  	case Hopenbsd:		/* openbsd */
   223  	case Hdragonfly:	/* dragonfly */
   224  		/*
   225  		 * ELF uses TLS offset negative from FS.
   226  		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
   227  		 * Also known to ../../pkg/runtime/sys_linux_amd64.s
   228  		 * and ../../pkg/runtime/cgo/gcc_linux_amd64.c.
   229  		 */
   230  		tlsoffset = -16;
   231  		elfinit();
   232  		HEADR = ELFRESERVE;
   233  		if(INITTEXT == -1)
   234  			INITTEXT = (1<<22)+HEADR;
   235  		if(INITDAT == -1)
   236  			INITDAT = 0;
   237  		if(INITRND == -1)
   238  			INITRND = 4096;
   239  		break;
   240  	case Hwindows:		/* PE executable */
   241  		peinit();
   242  		HEADR = PEFILEHEADR;
   243  		if(INITTEXT == -1)
   244  			INITTEXT = PEBASE+PESECTHEADR;
   245  		if(INITDAT == -1)
   246  			INITDAT = 0;
   247  		if(INITRND == -1)
   248  			INITRND = PESECTALIGN;
   249  		break;
   250  	}
   251  	if(INITDAT != 0 && INITRND != 0)
   252  		print("warning: -D0x%llux is ignored because of -R0x%ux\n",
   253  			INITDAT, INITRND);
   254  	if(debug['v'])
   255  		Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n",
   256  			HEADTYPE, INITTEXT, INITDAT, INITRND);
   257  	Bflush(&bso);
   258  	instinit();
   259  
   260  	zprg.link = P;
   261  	zprg.pcond = P;
   262  	zprg.back = 2;
   263  	zprg.as = AGOK;
   264  	zprg.from.type = D_NONE;
   265  	zprg.from.index = D_NONE;
   266  	zprg.from.scale = 1;
   267  	zprg.to = zprg.from;
   268  	zprg.mode = 64;
   269  
   270  	pcstr = "%.6llux ";
   271  	histgen = 0;
   272  	pc = 0;
   273  	dtype = 4;
   274  	version = 0;
   275  	cbp = buf.cbuf;
   276  	cbc = sizeof(buf.cbuf);
   277  
   278  	addlibpath("command line", "command line", argv[0], "main");
   279  	loadlib();
   280  	deadcode();
   281  	patch();
   282  	follow();
   283  	doelf();
   284  	if(HEADTYPE == Hdarwin)
   285  		domacho();
   286  	dostkoff();
   287  	dostkcheck();
   288  	paramspace = "SP";	/* (FP) now (SP) on output */
   289  	if(debug['p'])
   290  		if(debug['1'])
   291  			doprof1();
   292  		else
   293  			doprof2();
   294  	span();
   295  	if(HEADTYPE == Hwindows)
   296  		dope();
   297  	addexport();
   298  	textaddress();
   299  	pclntab();
   300  	symtab();
   301  	dodata();
   302  	address();
   303  	doweak();
   304  	reloc();
   305  	asmb();
   306  	undef();
   307  	hostlink();
   308  	if(debug['v']) {
   309  		Bprint(&bso, "%5.2f cpu time\n", cputime());
   310  		Bprint(&bso, "%d symbols\n", nsymbol);
   311  		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
   312  		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
   313  	}
   314  	Bflush(&bso);
   315  
   316  	errorexit();
   317  }
   318  
   319  static Sym*
   320  zsym(char *pn, Biobuf *f, Sym *h[])
   321  {	
   322  	int o;
   323  	
   324  	o = BGETC(f);
   325  	if(o < 0 || o >= NSYM || h[o] == nil)
   326  		mangle(pn);
   327  	return h[o];
   328  }
   329  
   330  static void
   331  zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
   332  {
   333  	int t;
   334  	int32 l;
   335  	Sym *s;
   336  	Auto *u;
   337  
   338  	t = BGETC(f);
   339  	a->index = D_NONE;
   340  	a->scale = 0;
   341  	if(t & T_INDEX) {
   342  		a->index = BGETC(f);
   343  		a->scale = BGETC(f);
   344  	}
   345  	a->offset = 0;
   346  	if(t & T_OFFSET) {
   347  		a->offset = BGETLE4(f);
   348  		if(t & T_64) {
   349  			a->offset &= 0xFFFFFFFFULL;
   350  			a->offset |= (uvlong)BGETLE4(f) << 32;
   351  		}
   352  	}
   353  	a->sym = S;
   354  	if(t & T_SYM)
   355  		a->sym = zsym(pn, f, h);
   356  	a->type = D_NONE;
   357  	if(t & T_FCONST) {
   358  		a->ieee.l = BGETLE4(f);
   359  		a->ieee.h = BGETLE4(f);
   360  		a->type = D_FCONST;
   361  	} else
   362  	if(t & T_SCONST) {
   363  		Bread(f, a->scon, NSNAME);
   364  		a->type = D_SCONST;
   365  	}
   366  	if(t & T_TYPE)
   367  		a->type = BGETC(f);
   368  	if(a->type < 0 || a->type >= D_SIZE)
   369  		mangle(pn);
   370  	adrgotype = S;
   371  	if(t & T_GOTYPE)
   372  		adrgotype = zsym(pn, f, h);
   373  	s = a->sym;
   374  	t = a->type;
   375  	if(t == D_INDIR+D_GS || a->index == D_GS)
   376  		a->offset += tlsoffset;
   377  	if(t != D_AUTO && t != D_PARAM) {
   378  		if(s && adrgotype)
   379  			s->gotype = adrgotype;
   380  		return;
   381  	}
   382  	l = a->offset;
   383  	for(u=curauto; u; u=u->link) {
   384  		if(u->asym == s)
   385  		if(u->type == t) {
   386  			if(u->aoffset > l)
   387  				u->aoffset = l;
   388  			if(adrgotype)
   389  				u->gotype = adrgotype;
   390  			return;
   391  		}
   392  	}
   393  	
   394  	switch(t) {
   395  	case D_FILE:
   396  	case D_FILE1:
   397  	case D_AUTO:
   398  	case D_PARAM:
   399  		if(s == S)
   400  			mangle(pn);
   401  	}
   402  
   403  	u = mal(sizeof(*u));
   404  	u->link = curauto;
   405  	curauto = u;
   406  	u->asym = s;
   407  	u->aoffset = l;
   408  	u->type = t;
   409  	u->gotype = adrgotype;
   410  }
   411  
   412  void
   413  nopout(Prog *p)
   414  {
   415  	p->as = ANOP;
   416  	p->from.type = D_NONE;
   417  	p->to.type = D_NONE;
   418  }
   419  
   420  void
   421  ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
   422  {
   423  	vlong ipc;
   424  	Prog *p;
   425  	int v, o, r, skip, mode;
   426  	Sym *h[NSYM], *s;
   427  	uint32 sig;
   428  	char *name, *x;
   429  	int ntext;
   430  	vlong eof;
   431  	char src[1024];
   432  	Prog *lastp;
   433  
   434  	lastp = nil;
   435  	ntext = 0;
   436  	eof = Boffset(f) + len;
   437  	src[0] = 0;
   438  	pn = estrdup(pn); // we keep it in Sym* references
   439  
   440  newloop:
   441  	memset(h, 0, sizeof(h));
   442  	version++;
   443  	histfrogp = 0;
   444  	ipc = pc;
   445  	skip = 0;
   446  	mode = 64;
   447  
   448  loop:
   449  	if(f->state == Bracteof || Boffset(f) >= eof)
   450  		goto eof;
   451  	o = BGETC(f);
   452  	if(o == Beof)
   453  		goto eof;
   454  	o |= BGETC(f) << 8;
   455  	if(o <= AXXX || o >= ALAST) {
   456  		if(o < 0)
   457  			goto eof;
   458  		diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o);
   459  		print("	probably not a .6 file\n");
   460  		errorexit();
   461  	}
   462  
   463  	if(o == ANAME || o == ASIGNAME) {
   464  		sig = 0;
   465  		if(o == ASIGNAME)
   466  			sig = BGETLE4(f);
   467  		v = BGETC(f);	/* type */
   468  		o = BGETC(f);	/* sym */
   469  		r = 0;
   470  		if(v == D_STATIC)
   471  			r = version;
   472  		name = Brdline(f, '\0');
   473  		if(name == nil) {
   474  			if(Blinelen(f) > 0) {
   475  				fprint(2, "%s: name too long\n", pn);
   476  				errorexit();
   477  			}
   478  			goto eof;
   479  		}
   480  		x = expandpkg(name, pkg);
   481  		s = lookup(x, r);
   482  		if(x != name)
   483  			free(x);
   484  
   485  		if(debug['S'] && r == 0)
   486  			sig = 1729;
   487  		if(sig != 0){
   488  			if(s->sig != 0 && s->sig != sig)
   489  				diag("incompatible type signatures "
   490  					"%ux(%s) and %ux(%s) for %s",
   491  					s->sig, s->file, sig, pn, s->name);
   492  			s->sig = sig;
   493  			s->file = pn;
   494  		}
   495  
   496  		if(debug['W'])
   497  			print("	ANAME	%s\n", s->name);
   498  		if(o < 0 || o >= nelem(h))
   499  			mangle(pn);
   500  		h[o] = s;
   501  		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
   502  			s->type = SXREF;
   503  		if(v == D_FILE) {
   504  			if(s->type != SFILE) {
   505  				histgen++;
   506  				s->type = SFILE;
   507  				s->value = histgen;
   508  			}
   509  			if(histfrogp < MAXHIST) {
   510  				histfrog[histfrogp] = s;
   511  				histfrogp++;
   512  			} else
   513  				collapsefrog(s);
   514  			dwarfaddfrag(s->value, s->name);
   515  		}
   516  		goto loop;
   517  	}
   518  
   519  	p = mal(sizeof(*p));
   520  	p->as = o;
   521  	p->line = BGETLE4(f);
   522  	p->back = 2;
   523  	p->mode = mode;
   524  	zaddr(pn, f, &p->from, h);
   525  	fromgotype = adrgotype;
   526  	zaddr(pn, f, &p->to, h);
   527  	
   528  	switch(p->as) {
   529  	case ATEXT:
   530  	case ADATA:
   531  	case AGLOBL:
   532  		if(p->from.sym == S)
   533  			mangle(pn);
   534  		break;
   535  	}
   536  
   537  	if(debug['W'])
   538  		print("%P\n", p);
   539  
   540  	switch(p->as) {
   541  	case AHISTORY:
   542  		if(p->to.offset == -1) {
   543  			addlib(src, pn);
   544  			histfrogp = 0;
   545  			goto loop;
   546  		}
   547  		if(src[0] == '\0')
   548  			copyhistfrog(src, sizeof src);
   549  		addhist(p->line, D_FILE);		/* 'z' */
   550  		if(p->to.offset)
   551  			addhist(p->to.offset, D_FILE1);	/* 'Z' */
   552  		savehist(p->line, p->to.offset);
   553  		histfrogp = 0;
   554  		goto loop;
   555  
   556  	case AEND:
   557  		histtoauto();
   558  		if(cursym != nil && cursym->text)
   559  			cursym->autom = curauto;
   560  		curauto = 0;
   561  		cursym = nil;
   562  		if(Boffset(f) == eof)
   563  			return;
   564  		goto newloop;
   565  
   566  	case AGLOBL:
   567  		s = p->from.sym;
   568  		if(s->type == 0 || s->type == SXREF) {
   569  			s->type = SBSS;
   570  			s->size = 0;
   571  		}
   572  		if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) {
   573  			diag("%s: redefinition: %s in %s",
   574  				pn, s->name, TNAME);
   575  			s->type = SBSS;
   576  			s->size = 0;
   577  		}
   578  		if(p->to.offset > s->size)
   579  			s->size = p->to.offset;
   580  		if(p->from.scale & DUPOK)
   581  			s->dupok = 1;
   582  		if(p->from.scale & RODATA)
   583  			s->type = SRODATA;
   584  		else if(p->from.scale & NOPTR)
   585  			s->type = SNOPTRBSS;
   586  		goto loop;
   587  
   588  	case ADATA:
   589  		// Assume that AGLOBL comes after ADATA.
   590  		// If we've seen an AGLOBL that said this sym was DUPOK,
   591  		// ignore any more ADATA we see, which must be
   592  		// redefinitions.
   593  		s = p->from.sym;
   594  		if(s->dupok) {
   595  //			if(debug['v'])
   596  //				Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
   597  			goto loop;
   598  		}
   599  		if(s->file == nil)
   600  			s->file = pn;
   601  		else if(s->file != pn) {
   602  			diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
   603  			errorexit();
   604  		}
   605  		savedata(s, p, pn);
   606  		unmal(p, sizeof *p);
   607  		goto loop;
   608  
   609  	case AGOK:
   610  		diag("%s: GOK opcode in %s", pn, TNAME);
   611  		pc++;
   612  		goto loop;
   613  
   614  	case ATYPE:
   615  		if(skip)
   616  			goto casdef;
   617  		pc++;
   618  		goto loop;
   619  
   620  	case ATEXT:
   621  		s = p->from.sym;
   622  		if(s->text != nil) {
   623  			if(p->from.scale & DUPOK) {
   624  				skip = 1;
   625  				goto casdef;
   626  			}
   627  			diag("%s: %s: redefinition", pn, s->name);
   628  			return;
   629  		}
   630  		if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
   631  			/* redefinition, so file has probably been seen before */
   632  			if(debug['v'])
   633  				Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name);
   634  			return;
   635  		}
   636  		if(cursym != nil && cursym->text) {
   637  			histtoauto();
   638  			cursym->autom = curauto;
   639  			curauto = 0;
   640  		}
   641  		skip = 0;
   642  		if(etextp)
   643  			etextp->next = s;
   644  		else
   645  			textp = s;
   646  		etextp = s;
   647  		s->text = p;
   648  		cursym = s;
   649  		if(s->type != 0 && s->type != SXREF) {
   650  			if(p->from.scale & DUPOK) {
   651  				skip = 1;
   652  				goto casdef;
   653  			}
   654  			diag("%s: redefinition: %s\n%P", pn, s->name, p);
   655  		}
   656  		if(fromgotype) {
   657  			if(s->gotype && s->gotype != fromgotype)
   658  				diag("%s: type mismatch for %s", pn, s->name);
   659  			s->gotype = fromgotype;
   660  		}
   661  		s->type = STEXT;
   662  		s->hist = gethist();
   663  		s->value = pc;
   664  		s->args = p->to.offset >> 32;
   665  		lastp = p;
   666  		p->pc = pc++;
   667  		goto loop;
   668  
   669  	case AMODE:
   670  		if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){
   671  			switch((int)p->from.offset){
   672  			case 16: case 32: case 64:
   673  				mode = p->from.offset;
   674  				break;
   675  			}
   676  		}
   677  		goto loop;
   678  
   679  	case AFMOVF:
   680  	case AFADDF:
   681  	case AFSUBF:
   682  	case AFSUBRF:
   683  	case AFMULF:
   684  	case AFDIVF:
   685  	case AFDIVRF:
   686  	case AFCOMF:
   687  	case AFCOMFP:
   688  	case AMOVSS:
   689  	case AADDSS:
   690  	case ASUBSS:
   691  	case AMULSS:
   692  	case ADIVSS:
   693  	case ACOMISS:
   694  	case AUCOMISS:
   695  		if(skip)
   696  			goto casdef;
   697  		if(p->from.type == D_FCONST) {
   698  			/* size sb 9 max */
   699  			sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
   700  			s = lookup(literal, 0);
   701  			if(s->type == 0) {
   702  				s->type = SRODATA;
   703  				adduint32(s, ieeedtof(&p->from.ieee));
   704  				s->reachable = 0;
   705  			}
   706  			p->from.type = D_EXTERN;
   707  			p->from.sym = s;
   708  			p->from.offset = 0;
   709  		}
   710  		goto casdef;
   711  
   712  	case AFMOVD:
   713  	case AFADDD:
   714  	case AFSUBD:
   715  	case AFSUBRD:
   716  	case AFMULD:
   717  	case AFDIVD:
   718  	case AFDIVRD:
   719  	case AFCOMD:
   720  	case AFCOMDP:
   721  	case AMOVSD:
   722  	case AADDSD:
   723  	case ASUBSD:
   724  	case AMULSD:
   725  	case ADIVSD:
   726  	case ACOMISD:
   727  	case AUCOMISD:
   728  		if(skip)
   729  			goto casdef;
   730  		if(p->from.type == D_FCONST) {
   731  			/* size sb 18 max */
   732  			sprint(literal, "$%ux.%ux",
   733  				p->from.ieee.l, p->from.ieee.h);
   734  			s = lookup(literal, 0);
   735  			if(s->type == 0) {
   736  				s->type = SRODATA;
   737  				adduint32(s, p->from.ieee.l);
   738  				adduint32(s, p->from.ieee.h);
   739  				s->reachable = 0;
   740  			}
   741  			p->from.type = D_EXTERN;
   742  			p->from.sym = s;
   743  			p->from.offset = 0;
   744  		}
   745  		goto casdef;
   746  
   747  	casdef:
   748  	default:
   749  		if(skip)
   750  			nopout(p);
   751  		p->pc = pc;
   752  		pc++;
   753  
   754  		if(p->to.type == D_BRANCH)
   755  			p->to.offset += ipc;
   756  		if(lastp == nil) {
   757  			if(p->as != ANOP)
   758  				diag("unexpected instruction: %P", p);
   759  			goto loop;
   760  		}
   761  		lastp->link = p;
   762  		lastp = p;
   763  		goto loop;
   764  	}
   765  
   766  eof:
   767  	diag("truncated object file: %s", pn);
   768  }
   769  
   770  Prog*
   771  prg(void)
   772  {
   773  	Prog *p;
   774  
   775  	p = mal(sizeof(*p));
   776  
   777  	*p = zprg;
   778  	return p;
   779  }
   780  
   781  Prog*
   782  copyp(Prog *q)
   783  {
   784  	Prog *p;
   785  
   786  	p = prg();
   787  	*p = *q;
   788  	return p;
   789  }
   790  
   791  Prog*
   792  appendp(Prog *q)
   793  {
   794  	Prog *p;
   795  
   796  	p = prg();
   797  	p->link = q->link;
   798  	q->link = p;
   799  	p->line = q->line;
   800  	p->mode = q->mode;
   801  	return p;
   802  }