github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/cmd/8l/asm.c (about)

     1  // Inferno utils/8l/asm.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.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  // Writing object files.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  #include	"../ld/elf.h"
    36  #include	"../ld/dwarf.h"
    37  #include	"../ld/macho.h"
    38  #include	"../ld/pe.h"
    39  
    40  char linuxdynld[] = "/lib/ld-linux.so.2";
    41  char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
    42  char haikudynld[] = "/system/runtime_loader";
    43  char openbsddynld[] = "/usr/libexec/ld.so";
    44  char netbsddynld[] = "/usr/libexec/ld.elf_so";
    45  char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
    46  char solarisdynld[] = "/lib/ld.so.1";
    47  
    48  static int
    49  needlib(char *name)
    50  {
    51  	char *p;
    52  	LSym *s;
    53  
    54  	if(*name == '\0')
    55  		return 0;
    56  
    57  	/* reuse hash code in symbol table */
    58  	p = smprint(".dynlib.%s", name);
    59  	s = linklookup(ctxt, p, 0);
    60  	free(p);
    61  	if(s->type == 0) {
    62  		s->type = 100;	// avoid SDATA, etc.
    63  		return 1;
    64  	}
    65  	return 0;
    66  }
    67  
    68  int	nelfsym = 1;
    69  
    70  static void	addpltsym(Link*, LSym*);
    71  static void	addgotsym(Link*, LSym*);
    72  
    73  void
    74  adddynrela(LSym *rela, LSym *s, Reloc *r)
    75  {
    76  	USED(rela);
    77  	USED(s);
    78  	USED(r);
    79  	sysfatal("adddynrela not implemented");
    80  }
    81  
    82  void
    83  adddynrel(LSym *s, Reloc *r)
    84  {
    85  	LSym *targ, *rel, *got;
    86  
    87  	targ = r->sym;
    88  	ctxt->cursym = s;
    89  
    90  	switch(r->type) {
    91  	default:
    92  		if(r->type >= 256) {
    93  			diag("unexpected relocation type %d", r->type);
    94  			return;
    95  		}
    96  		break;
    97  
    98  	// Handle relocations found in ELF object files.
    99  	case 256 + R_386_PC32:
   100  		if(targ->type == SDYNIMPORT)
   101  			diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
   102  		if(targ->type == 0 || targ->type == SXREF)
   103  			diag("unknown symbol %s in pcrel", targ->name);
   104  		r->type = R_PCREL;
   105  		r->add += 4;
   106  		return;
   107  
   108  	case 256 + R_386_PLT32:
   109  		r->type = R_PCREL;
   110  		r->add += 4;
   111  		if(targ->type == SDYNIMPORT) {
   112  			addpltsym(ctxt, targ);
   113  			r->sym = linklookup(ctxt, ".plt", 0);
   114  			r->add += targ->plt;
   115  		}
   116  		return;		
   117  	
   118  	case 256 + R_386_GOT32:
   119  	case 256 + R_386_GOT32X:
   120  		if(targ->type != SDYNIMPORT) {
   121  			// have symbol
   122  			if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
   123  				// turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
   124  				s->p[r->off-2] = 0x8d;
   125  				r->type = R_GOTOFF;
   126  				return;
   127  			}
   128  			if(r->off >= 2 && s->p[r->off-2] == 0xff && s->p[r->off-1] == 0xb3) {
   129  				// turn PUSHL of GOT entry into PUSHL of symbol itself.
   130  				// use unnecessary SS prefix to keep instruction same length.
   131  				s->p[r->off-2] = 0x36;
   132  				s->p[r->off-1] = 0x68;
   133  				r->type = R_ADDR;
   134  				return;
   135  			}
   136  			diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
   137  			return;
   138  		}
   139  		addgotsym(ctxt, targ);
   140  		r->type = R_CONST;	// write r->add during relocsym
   141  		r->sym = S;
   142  		r->add += targ->got;
   143  		return;
   144  	
   145  	case 256 + R_386_GOTOFF:
   146  		r->type = R_GOTOFF;
   147  		return;
   148  	
   149  	case 256 + R_386_GOTPC:
   150  		r->type = R_PCREL;
   151  		r->sym = linklookup(ctxt, ".got", 0);
   152  		r->add += 4;
   153  		return;
   154  
   155  	case 256 + R_386_32:
   156  		if(targ->type == SDYNIMPORT)
   157  			diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
   158  		r->type = R_ADDR;
   159  		return;
   160  	
   161  	case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
   162  		r->type = R_ADDR;
   163  		if(targ->type == SDYNIMPORT)
   164  			diag("unexpected reloc for dynamic symbol %s", targ->name);
   165  		return;
   166  	
   167  	case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
   168  		if(targ->type == SDYNIMPORT) {
   169  			addpltsym(ctxt, targ);
   170  			r->sym = linklookup(ctxt, ".plt", 0);
   171  			r->add = targ->plt;
   172  			r->type = R_PCREL;
   173  			return;
   174  		}
   175  		r->type = R_PCREL;
   176  		return;
   177  	
   178  	case 512 + MACHO_FAKE_GOTPCREL:
   179  		if(targ->type != SDYNIMPORT) {
   180  			// have symbol
   181  			// turn MOVL of GOT entry into LEAL of symbol itself
   182  			if(r->off < 2 || s->p[r->off-2] != 0x8b) {
   183  				diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
   184  				return;
   185  			}
   186  			s->p[r->off-2] = 0x8d;
   187  			r->type = R_PCREL;
   188  			return;
   189  		}
   190  		addgotsym(ctxt, targ);
   191  		r->sym = linklookup(ctxt, ".got", 0);
   192  		r->add += targ->got;
   193  		r->type = R_PCREL;
   194  		return;
   195  	}
   196  	
   197  	// Handle references to ELF symbols from our own object files.
   198  	if(targ->type != SDYNIMPORT)
   199  		return;
   200  
   201  	switch(r->type) {
   202  	case R_CALL:
   203  	case R_PCREL:
   204  		addpltsym(ctxt, targ);
   205  		r->sym = linklookup(ctxt, ".plt", 0);
   206  		r->add = targ->plt;
   207  		return;
   208  	
   209  	case R_ADDR:
   210  		if(s->type != SDATA)
   211  			break;
   212  		if(iself) {
   213  			adddynsym(ctxt, targ);
   214  			rel = linklookup(ctxt, ".rel", 0);
   215  			addaddrplus(ctxt, rel, s, r->off);
   216  			adduint32(ctxt, rel, ELF32_R_INFO(targ->dynid, R_386_32));
   217  			r->type = R_CONST;	// write r->add during relocsym
   218  			r->sym = S;
   219  			return;
   220  		}
   221  		if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) {
   222  			// Mach-O relocations are a royal pain to lay out.
   223  			// They use a compact stateful bytecode representation
   224  			// that is too much bother to deal with.
   225  			// Instead, interpret the C declaration
   226  			//	void *_Cvar_stderr = &stderr;
   227  			// as making _Cvar_stderr the name of a GOT entry
   228  			// for stderr.  This is separate from the usual GOT entry,
   229  			// just in case the C code assigns to the variable,
   230  			// and of course it only works for single pointers,
   231  			// but we only need to support cgo and that's all it needs.
   232  			adddynsym(ctxt, targ);
   233  			got = linklookup(ctxt, ".got", 0);
   234  			s->type = got->type | SSUB;
   235  			s->outer = got;
   236  			s->sub = got->sub;
   237  			got->sub = s;
   238  			s->value = got->size;
   239  			adduint32(ctxt, got, 0);
   240  			adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), targ->dynid);
   241  			r->type = 256;	// ignore during relocsym
   242  			return;
   243  		}
   244  		break;
   245  	}
   246  	
   247  	ctxt->cursym = s;
   248  	diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
   249  }
   250  
   251  int
   252  elfreloc1(Reloc *r, vlong sectoff)
   253  {
   254  	int32 elfsym;
   255  
   256  	LPUT(sectoff);
   257  
   258  	elfsym = r->xsym->elfsym;
   259  	switch(r->type) {
   260  	default:
   261  		return -1;
   262  
   263  	case R_ADDR:
   264  		if(r->siz == 4)
   265  			LPUT(R_386_32 | elfsym<<8);
   266  		else
   267  			return -1;
   268  		break;
   269  
   270  	case R_CALL:
   271  	case R_PCREL:
   272  		if(r->siz == 4)
   273  			LPUT(R_386_PC32 | elfsym<<8);
   274  		else
   275  			return -1;
   276  		break;
   277  	
   278  	case R_TLS_LE:
   279  	case R_TLS_IE:
   280  		if(r->siz == 4)
   281  			LPUT(R_386_TLS_LE | elfsym<<8);
   282  		else
   283  			return -1;
   284  	}
   285  
   286  	return 0;
   287  }
   288  
   289  int
   290  machoreloc1(Reloc *r, vlong sectoff)
   291  {
   292  	uint32 v;
   293  	LSym *rs;
   294  	
   295  	rs = r->xsym;
   296  
   297  	if(rs->type == SHOSTOBJ) {
   298  		if(rs->dynid < 0) {
   299  			diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
   300  			return -1;
   301  		}
   302  		v = rs->dynid;			
   303  		v |= 1<<27; // external relocation
   304  	} else {
   305  		v = rs->sect->extnum;
   306  		if(v == 0) {
   307  			diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
   308  			return -1;
   309  		}
   310  	}
   311  
   312  	switch(r->type) {
   313  	default:
   314  		return -1;
   315  	case R_ADDR:
   316  		v |= MACHO_GENERIC_RELOC_VANILLA<<28;
   317  		break;
   318  	case R_CALL:
   319  	case R_PCREL:
   320  		v |= 1<<24; // pc-relative bit
   321  		v |= MACHO_GENERIC_RELOC_VANILLA<<28;
   322  		break;
   323  	}
   324  	
   325  	switch(r->siz) {
   326  	default:
   327  		return -1;
   328  	case 1:
   329  		v |= 0<<25;
   330  		break;
   331  	case 2:
   332  		v |= 1<<25;
   333  		break;
   334  	case 4:
   335  		v |= 2<<25;
   336  		break;
   337  	case 8:
   338  		v |= 3<<25;
   339  		break;
   340  	}
   341  
   342  	LPUT(sectoff);
   343  	LPUT(v);
   344  	return 0;
   345  }
   346  
   347  int
   348  archreloc(Reloc *r, LSym *s, vlong *val)
   349  {
   350  	USED(s);
   351  	if(linkmode == LinkExternal)
   352  		return -1;
   353  	switch(r->type) {
   354  	case R_CONST:
   355  		*val = r->add;
   356  		return 0;
   357  	case R_GOTOFF:
   358  		*val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
   359  		return 0;
   360  	}
   361  	return -1;
   362  }
   363  
   364  void
   365  elfsetupplt(void)
   366  {
   367  	LSym *plt, *got;
   368  	
   369  	plt = linklookup(ctxt, ".plt", 0);
   370  	got = linklookup(ctxt, ".got.plt", 0);
   371  	if(plt->size == 0) {
   372  		// pushl got+4
   373  		adduint8(ctxt, plt, 0xff);
   374  		adduint8(ctxt, plt, 0x35);
   375  		addaddrplus(ctxt, plt, got, 4);
   376  		
   377  		// jmp *got+8
   378  		adduint8(ctxt, plt, 0xff);
   379  		adduint8(ctxt, plt, 0x25);
   380  		addaddrplus(ctxt, plt, got, 8);
   381  
   382  		// zero pad
   383  		adduint32(ctxt, plt, 0);
   384  		
   385  		// assume got->size == 0 too
   386  		addaddrplus(ctxt, got, linklookup(ctxt, ".dynamic", 0), 0);
   387  		adduint32(ctxt, got, 0);
   388  		adduint32(ctxt, got, 0);
   389  	}
   390  }
   391  
   392  static void
   393  addpltsym(Link *ctxt, LSym *s)
   394  {
   395  	LSym *plt, *got, *rel;
   396  	
   397  	if(s->plt >= 0)
   398  		return;
   399  
   400  	adddynsym(ctxt, s);
   401  	
   402  	if(iself) {
   403  		plt = linklookup(ctxt, ".plt", 0);
   404  		got = linklookup(ctxt, ".got.plt", 0);
   405  		rel = linklookup(ctxt, ".rel.plt", 0);
   406  		if(plt->size == 0)
   407  			elfsetupplt();
   408  		
   409  		// jmpq *got+size
   410  		adduint8(ctxt, plt, 0xff);
   411  		adduint8(ctxt, plt, 0x25);
   412  		addaddrplus(ctxt, plt, got, got->size);
   413  		
   414  		// add to got: pointer to current pos in plt
   415  		addaddrplus(ctxt, got, plt, plt->size);
   416  		
   417  		// pushl $x
   418  		adduint8(ctxt, plt, 0x68);
   419  		adduint32(ctxt, plt, rel->size);
   420  		
   421  		// jmp .plt
   422  		adduint8(ctxt, plt, 0xe9);
   423  		adduint32(ctxt, plt, -(plt->size+4));
   424  		
   425  		// rel
   426  		addaddrplus(ctxt, rel, got, got->size-4);
   427  		adduint32(ctxt, rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT));
   428  		
   429  		s->plt = plt->size - 16;
   430  	} else if(HEADTYPE == Hdarwin) {
   431  		// Same laziness as in 6l.
   432  		
   433  		LSym *plt;
   434  
   435  		plt = linklookup(ctxt, ".plt", 0);
   436  
   437  		addgotsym(ctxt, s);
   438  
   439  		adduint32(ctxt, linklookup(ctxt, ".linkedit.plt", 0), s->dynid);
   440  
   441  		// jmpq *got+size(IP)
   442  		s->plt = plt->size;
   443  
   444  		adduint8(ctxt, plt, 0xff);
   445  		adduint8(ctxt, plt, 0x25);
   446  		addaddrplus(ctxt, plt, linklookup(ctxt, ".got", 0), s->got);
   447  	} else {
   448  		diag("addpltsym: unsupported binary format");
   449  	}
   450  }
   451  
   452  static void
   453  addgotsym(Link *ctxt, LSym *s)
   454  {
   455  	LSym *got, *rel;
   456  	
   457  	if(s->got >= 0)
   458  		return;
   459  	
   460  	adddynsym(ctxt, s);
   461  	got = linklookup(ctxt, ".got", 0);
   462  	s->got = got->size;
   463  	adduint32(ctxt, got, 0);
   464  	
   465  	if(iself) {
   466  		rel = linklookup(ctxt, ".rel", 0);
   467  		addaddrplus(ctxt, rel, got, s->got);
   468  		adduint32(ctxt, rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT));
   469  	} else if(HEADTYPE == Hdarwin) {
   470  		adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), s->dynid);
   471  	} else {
   472  		diag("addgotsym: unsupported binary format");
   473  	}
   474  }
   475  
   476  void
   477  adddynsym(Link *ctxt, LSym *s)
   478  {
   479  	LSym *d;
   480  	int t;
   481  	char *name;
   482  	
   483  	if(s->dynid >= 0)
   484  		return;
   485  	
   486  	if(iself) {
   487  		s->dynid = nelfsym++;
   488  		
   489  		d = linklookup(ctxt, ".dynsym", 0);
   490  
   491  		/* name */
   492  		name = s->extname;
   493  		adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name));
   494  		
   495  		/* value */
   496  		if(s->type == SDYNIMPORT)
   497  			adduint32(ctxt, d, 0);
   498  		else
   499  			addaddr(ctxt, d, s);
   500  		
   501  		/* size */
   502  		adduint32(ctxt, d, s->size);
   503  	
   504  		/* type */
   505  		t = STB_GLOBAL << 4;
   506  		if(s->cgoexport && (s->type&SMASK) == STEXT)
   507  			t |= STT_FUNC;
   508  		else
   509  			t |= STT_OBJECT;
   510  		adduint8(ctxt, d, t);
   511  		adduint8(ctxt, d, 0);
   512  	
   513  		/* shndx */
   514  		if(s->type == SDYNIMPORT)
   515  			adduint16(ctxt, d, SHN_UNDEF);
   516  		else {
   517  			switch(s->type) {
   518  			default:
   519  			case STEXT:
   520  				t = 11;
   521  				break;
   522  			case SRODATA:
   523  				t = 12;
   524  				break;
   525  			case SDATA:
   526  				t = 13;
   527  				break;
   528  			case SBSS:
   529  				t = 14;
   530  				break;
   531  			}
   532  			adduint16(ctxt, d, t);
   533  		}
   534  	} else if(HEADTYPE == Hdarwin) {
   535  		diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
   536  	} else if(HEADTYPE == Hwindows) {
   537  		// already taken care of
   538  	} else {
   539  		diag("adddynsym: unsupported binary format");
   540  	}
   541  }
   542  
   543  void
   544  adddynlib(char *lib)
   545  {
   546  	LSym *s;
   547  	
   548  	if(!needlib(lib))
   549  		return;
   550  	
   551  	if(iself) {
   552  		s = linklookup(ctxt, ".dynstr", 0);
   553  		if(s->size == 0)
   554  			addstring(s, "");
   555  		elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
   556  	} else if(HEADTYPE == Hdarwin) {
   557  		machoadddynlib(lib);
   558  	} else if(HEADTYPE != Hwindows) {
   559  		diag("adddynlib: unsupported binary format");
   560  	}
   561  }
   562  
   563  void
   564  asmb(void)
   565  {
   566  	int32 magic;
   567  	uint32 symo, dwarfoff, machlink;
   568  	Section *sect;
   569  	LSym *sym;
   570  	int i;
   571  
   572  	if(debug['v'])
   573  		Bprint(&bso, "%5.2f asmb\n", cputime());
   574  	Bflush(&bso);
   575  
   576  	if(iself)
   577  		asmbelfsetup();
   578  
   579  	sect = segtext.sect;
   580  	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
   581  	codeblk(sect->vaddr, sect->len);
   582  	for(sect = sect->next; sect != nil; sect = sect->next) {
   583  		cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
   584  		datblk(sect->vaddr, sect->len);
   585  	}
   586  	
   587  	if(segrodata.filelen > 0) {
   588  		if(debug['v'])
   589  			Bprint(&bso, "%5.2f rodatblk\n", cputime());
   590  		Bflush(&bso);
   591  
   592  		cseek(segrodata.fileoff);
   593  		datblk(segrodata.vaddr, segrodata.filelen);
   594  	}
   595  
   596  	if(debug['v'])
   597  		Bprint(&bso, "%5.2f datblk\n", cputime());
   598  	Bflush(&bso);
   599  
   600  	cseek(segdata.fileoff);
   601  	datblk(segdata.vaddr, segdata.filelen);
   602  
   603  	machlink = 0;
   604  	if(HEADTYPE == Hdarwin) {
   605  		if(debug['v'])
   606  			Bprint(&bso, "%5.2f dwarf\n", cputime());
   607  
   608  		dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
   609  		cseek(dwarfoff);
   610  
   611  		segdwarf.fileoff = cpos();
   612  		dwarfemitdebugsections();
   613  		segdwarf.filelen = cpos() - segdwarf.fileoff;
   614  
   615  		machlink = domacholink();
   616  	}
   617  
   618  	symsize = 0;
   619  	spsize = 0;
   620  	lcsize = 0;
   621  	symo = 0;
   622  	if(!debug['s']) {
   623  		// TODO: rationalize
   624  		if(debug['v'])
   625  			Bprint(&bso, "%5.2f sym\n", cputime());
   626  		Bflush(&bso);
   627  		switch(HEADTYPE) {
   628  		default:
   629  			if(iself)
   630  				goto Elfsym;
   631  		case Hplan9:
   632  			symo = segdata.fileoff+segdata.filelen;
   633  			break;
   634  		case Hdarwin:
   635  			symo = segdata.fileoff+rnd(segdata.filelen, INITRND)+machlink;
   636  			break;
   637  		Elfsym:
   638  			symo = segdata.fileoff+segdata.filelen;
   639  			symo = rnd(symo, INITRND);
   640  			break;
   641  		case Hwindows:
   642  			symo = segdata.fileoff+segdata.filelen;
   643  			symo = rnd(symo, PEFILEALIGN);
   644  			break;
   645  		}
   646  		cseek(symo);
   647  		switch(HEADTYPE) {
   648  		default:
   649  			if(iself) {
   650  				if(debug['v'])
   651  					Bprint(&bso, "%5.2f elfsym\n", cputime());
   652  				asmelfsym();
   653  				cflush();
   654  				cwrite(elfstrdat, elfstrsize);
   655  
   656  				if(debug['v'])
   657  					Bprint(&bso, "%5.2f dwarf\n", cputime());
   658  				dwarfemitdebugsections();
   659  				
   660  				if(linkmode == LinkExternal)
   661  					elfemitreloc();
   662  			}
   663  			break;
   664  		case Hplan9:
   665  			asmplan9sym();
   666  			cflush();
   667  
   668  			sym = linklookup(ctxt, "pclntab", 0);
   669  			if(sym != nil) {
   670  				lcsize = sym->np;
   671  				for(i=0; i < lcsize; i++)
   672  					cput(sym->p[i]);
   673  				
   674  				cflush();
   675  			}
   676  			break;
   677  		case Hwindows:
   678  			if(debug['v'])
   679  				Bprint(&bso, "%5.2f dwarf\n", cputime());
   680  			dwarfemitdebugsections();
   681  			break;
   682  		case Hdarwin:
   683  			if(linkmode == LinkExternal)
   684  				machoemitreloc();
   685  			break;
   686  		}
   687  	}
   688  	if(debug['v'])
   689  		Bprint(&bso, "%5.2f headr\n", cputime());
   690  	Bflush(&bso);
   691  	cseek(0L);
   692  	switch(HEADTYPE) {
   693  	default:
   694  	case Hplan9:	/* plan9 */
   695  		magic = 4*11*11+7;
   696  		lputb(magic);		/* magic */
   697  		lputb(segtext.filelen);			/* sizes */
   698  		lputb(segdata.filelen);
   699  		lputb(segdata.len - segdata.filelen);
   700  		lputb(symsize);			/* nsyms */
   701  		lputb(entryvalue());		/* va of entry */
   702  		lputb(spsize);			/* sp offsets */
   703  		lputb(lcsize);			/* line offsets */
   704  		break;
   705  	case Hdarwin:
   706  		asmbmacho();
   707  		break;
   708  	case Hlinux:
   709  	case Hfreebsd:
   710  	case Hnetbsd:
   711  	case Hopenbsd:
   712  	case Hdragonfly:
   713  	case Hnacl:
   714  		asmbelf(symo);
   715  		break;
   716  	case Hwindows:
   717  		asmbpe();
   718  		break;
   719  	}
   720  	cflush();
   721  }
   722  
   723  void
   724  s8put(char *n)
   725  {
   726  	char name[8];
   727  	int i;
   728  
   729  	strncpy(name, n, sizeof(name));
   730  	for(i=0; i<sizeof(name); i++)
   731  		cput(name[i]);
   732  }
   733  
   734  int32
   735  rnd(int32 v, int32 r)
   736  {
   737  	int32 c;
   738  
   739  	if(r <= 0)
   740  		return v;
   741  	v += r - 1;
   742  	c = v % r;
   743  	if(c < 0)
   744  		c += r;
   745  	v -= c;
   746  	return v;
   747  }