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

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