github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/link/internal/s390x/asm.go (about)

     1  // Inferno utils/5l/asm.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/5l/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  package s390x
    32  
    33  import (
    34  	"cmd/internal/objabi"
    35  	"cmd/internal/sys"
    36  	"cmd/link/internal/ld"
    37  	"cmd/link/internal/sym"
    38  	"debug/elf"
    39  	"fmt"
    40  )
    41  
    42  // gentext generates assembly to append the local moduledata to the global
    43  // moduledata linked list at initialization time. This is only done if the runtime
    44  // is in a different module.
    45  //
    46  // <go.link.addmoduledata>:
    47  // 	larl  %r2, <local.moduledata>
    48  // 	jg    <runtime.addmoduledata@plt>
    49  //	undef
    50  //
    51  // The job of appending the moduledata is delegated to runtime.addmoduledata.
    52  func gentext(ctxt *ld.Link) {
    53  	if !ctxt.DynlinkingGo() {
    54  		return
    55  	}
    56  	addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
    57  	if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
    58  		// we're linking a module containing the runtime -> no need for
    59  		// an init function
    60  		return
    61  	}
    62  	addmoduledata.Attr |= sym.AttrReachable
    63  	initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
    64  	initfunc.Type = sym.STEXT
    65  	initfunc.Attr |= sym.AttrLocal
    66  	initfunc.Attr |= sym.AttrReachable
    67  
    68  	// larl %r2, <local.moduledata>
    69  	initfunc.AddUint8(0xc0)
    70  	initfunc.AddUint8(0x20)
    71  	lmd := initfunc.AddRel()
    72  	lmd.Off = int32(initfunc.Size)
    73  	lmd.Siz = 4
    74  	lmd.Sym = ctxt.Moduledata
    75  	lmd.Type = objabi.R_PCREL
    76  	lmd.Variant = sym.RV_390_DBL
    77  	lmd.Add = 2 + int64(lmd.Siz)
    78  	initfunc.AddUint32(ctxt.Arch, 0)
    79  
    80  	// jg <runtime.addmoduledata[@plt]>
    81  	initfunc.AddUint8(0xc0)
    82  	initfunc.AddUint8(0xf4)
    83  	rel := initfunc.AddRel()
    84  	rel.Off = int32(initfunc.Size)
    85  	rel.Siz = 4
    86  	rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
    87  	rel.Type = objabi.R_CALL
    88  	rel.Variant = sym.RV_390_DBL
    89  	rel.Add = 2 + int64(rel.Siz)
    90  	initfunc.AddUint32(ctxt.Arch, 0)
    91  
    92  	// undef (for debugging)
    93  	initfunc.AddUint32(ctxt.Arch, 0)
    94  	if ctxt.BuildMode == ld.BuildModePlugin {
    95  		ctxt.Textp = append(ctxt.Textp, addmoduledata)
    96  	}
    97  	ctxt.Textp = append(ctxt.Textp, initfunc)
    98  	initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
    99  	initarray_entry.Attr |= sym.AttrLocal
   100  	initarray_entry.Attr |= sym.AttrReachable
   101  	initarray_entry.Type = sym.SINITARR
   102  	initarray_entry.AddAddr(ctxt.Arch, initfunc)
   103  }
   104  
   105  func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
   106  	targ := r.Sym
   107  
   108  	switch r.Type {
   109  	default:
   110  		if r.Type >= 256 {
   111  			ld.Errorf(s, "unexpected relocation type %d", r.Type)
   112  			return false
   113  		}
   114  
   115  		// Handle relocations found in ELF object files.
   116  	case 256 + objabi.RelocType(elf.R_390_12),
   117  		256 + objabi.RelocType(elf.R_390_GOT12):
   118  		ld.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-256)
   119  		return false
   120  
   121  	case 256 + objabi.RelocType(elf.R_390_8),
   122  		256 + objabi.RelocType(elf.R_390_16),
   123  		256 + objabi.RelocType(elf.R_390_32),
   124  		256 + objabi.RelocType(elf.R_390_64):
   125  		if targ.Type == sym.SDYNIMPORT {
   126  			ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
   127  		}
   128  		r.Type = objabi.R_ADDR
   129  		return true
   130  
   131  	case 256 + objabi.RelocType(elf.R_390_PC16),
   132  		256 + objabi.RelocType(elf.R_390_PC32),
   133  		256 + objabi.RelocType(elf.R_390_PC64):
   134  		if targ.Type == sym.SDYNIMPORT {
   135  			ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name)
   136  		}
   137  		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
   138  		// sense and should be removed when someone has thought about it properly.
   139  		if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
   140  			ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
   141  		}
   142  		r.Type = objabi.R_PCREL
   143  		r.Add += int64(r.Siz)
   144  		return true
   145  
   146  	case 256 + objabi.RelocType(elf.R_390_GOT16),
   147  		256 + objabi.RelocType(elf.R_390_GOT32),
   148  		256 + objabi.RelocType(elf.R_390_GOT64):
   149  		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
   150  		return true
   151  
   152  	case 256 + objabi.RelocType(elf.R_390_PLT16DBL),
   153  		256 + objabi.RelocType(elf.R_390_PLT32DBL):
   154  		r.Type = objabi.R_PCREL
   155  		r.Variant = sym.RV_390_DBL
   156  		r.Add += int64(r.Siz)
   157  		if targ.Type == sym.SDYNIMPORT {
   158  			addpltsym(ctxt, targ)
   159  			r.Sym = ctxt.Syms.Lookup(".plt", 0)
   160  			r.Add += int64(targ.Plt())
   161  		}
   162  		return true
   163  
   164  	case 256 + objabi.RelocType(elf.R_390_PLT32),
   165  		256 + objabi.RelocType(elf.R_390_PLT64):
   166  		r.Type = objabi.R_PCREL
   167  		r.Add += int64(r.Siz)
   168  		if targ.Type == sym.SDYNIMPORT {
   169  			addpltsym(ctxt, targ)
   170  			r.Sym = ctxt.Syms.Lookup(".plt", 0)
   171  			r.Add += int64(targ.Plt())
   172  		}
   173  		return true
   174  
   175  	case 256 + objabi.RelocType(elf.R_390_COPY):
   176  		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
   177  		return false
   178  
   179  	case 256 + objabi.RelocType(elf.R_390_GLOB_DAT):
   180  		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
   181  		return false
   182  
   183  	case 256 + objabi.RelocType(elf.R_390_JMP_SLOT):
   184  		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
   185  		return false
   186  
   187  	case 256 + objabi.RelocType(elf.R_390_RELATIVE):
   188  		ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
   189  		return false
   190  
   191  	case 256 + objabi.RelocType(elf.R_390_GOTOFF):
   192  		if targ.Type == sym.SDYNIMPORT {
   193  			ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
   194  		}
   195  		r.Type = objabi.R_GOTOFF
   196  		return true
   197  
   198  	case 256 + objabi.RelocType(elf.R_390_GOTPC):
   199  		r.Type = objabi.R_PCREL
   200  		r.Sym = ctxt.Syms.Lookup(".got", 0)
   201  		r.Add += int64(r.Siz)
   202  		return true
   203  
   204  	case 256 + objabi.RelocType(elf.R_390_PC16DBL),
   205  		256 + objabi.RelocType(elf.R_390_PC32DBL):
   206  		r.Type = objabi.R_PCREL
   207  		r.Variant = sym.RV_390_DBL
   208  		r.Add += int64(r.Siz)
   209  		if targ.Type == sym.SDYNIMPORT {
   210  			ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name)
   211  		}
   212  		return true
   213  
   214  	case 256 + objabi.RelocType(elf.R_390_GOTPCDBL):
   215  		r.Type = objabi.R_PCREL
   216  		r.Variant = sym.RV_390_DBL
   217  		r.Sym = ctxt.Syms.Lookup(".got", 0)
   218  		r.Add += int64(r.Siz)
   219  		return true
   220  
   221  	case 256 + objabi.RelocType(elf.R_390_GOTENT):
   222  		addgotsym(ctxt, targ)
   223  
   224  		r.Type = objabi.R_PCREL
   225  		r.Variant = sym.RV_390_DBL
   226  		r.Sym = ctxt.Syms.Lookup(".got", 0)
   227  		r.Add += int64(targ.Got())
   228  		r.Add += int64(r.Siz)
   229  		return true
   230  	}
   231  	// Handle references to ELF symbols from our own object files.
   232  	if targ.Type != sym.SDYNIMPORT {
   233  		return true
   234  	}
   235  
   236  	return false
   237  }
   238  
   239  func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
   240  	ctxt.Out.Write64(uint64(sectoff))
   241  
   242  	elfsym := r.Xsym.ElfsymForReloc()
   243  	switch r.Type {
   244  	default:
   245  		return false
   246  	case objabi.R_TLS_LE:
   247  		switch r.Siz {
   248  		default:
   249  			return false
   250  		case 4:
   251  			// WARNING - silently ignored by linker in ELF64
   252  			ctxt.Out.Write64(uint64(elf.R_390_TLS_LE32) | uint64(elfsym)<<32)
   253  		case 8:
   254  			// WARNING - silently ignored by linker in ELF32
   255  			ctxt.Out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32)
   256  		}
   257  	case objabi.R_TLS_IE:
   258  		switch r.Siz {
   259  		default:
   260  			return false
   261  		case 4:
   262  			ctxt.Out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32)
   263  		}
   264  	case objabi.R_ADDR:
   265  		switch r.Siz {
   266  		default:
   267  			return false
   268  		case 4:
   269  			ctxt.Out.Write64(uint64(elf.R_390_32) | uint64(elfsym)<<32)
   270  		case 8:
   271  			ctxt.Out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32)
   272  		}
   273  	case objabi.R_GOTPCREL:
   274  		if r.Siz == 4 {
   275  			ctxt.Out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32)
   276  		} else {
   277  			return false
   278  		}
   279  	case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
   280  		elfrel := elf.R_390_NONE
   281  		isdbl := r.Variant&sym.RV_TYPE_MASK == sym.RV_390_DBL
   282  		// TODO(mundaym): all DBL style relocations should be
   283  		// signalled using the variant - see issue 14218.
   284  		switch r.Type {
   285  		case objabi.R_PCRELDBL, objabi.R_CALL:
   286  			isdbl = true
   287  		}
   288  		if r.Xsym.Type == sym.SDYNIMPORT && (r.Xsym.ElfType() == elf.STT_FUNC || r.Type == objabi.R_CALL) {
   289  			if isdbl {
   290  				switch r.Siz {
   291  				case 2:
   292  					elfrel = elf.R_390_PLT16DBL
   293  				case 4:
   294  					elfrel = elf.R_390_PLT32DBL
   295  				}
   296  			} else {
   297  				switch r.Siz {
   298  				case 4:
   299  					elfrel = elf.R_390_PLT32
   300  				case 8:
   301  					elfrel = elf.R_390_PLT64
   302  				}
   303  			}
   304  		} else {
   305  			if isdbl {
   306  				switch r.Siz {
   307  				case 2:
   308  					elfrel = elf.R_390_PC16DBL
   309  				case 4:
   310  					elfrel = elf.R_390_PC32DBL
   311  				}
   312  			} else {
   313  				switch r.Siz {
   314  				case 2:
   315  					elfrel = elf.R_390_PC16
   316  				case 4:
   317  					elfrel = elf.R_390_PC32
   318  				case 8:
   319  					elfrel = elf.R_390_PC64
   320  				}
   321  			}
   322  		}
   323  		if elfrel == elf.R_390_NONE {
   324  			return false // unsupported size/dbl combination
   325  		}
   326  		ctxt.Out.Write64(uint64(elfrel) | uint64(elfsym)<<32)
   327  	}
   328  
   329  	ctxt.Out.Write64(uint64(r.Xadd))
   330  	return true
   331  }
   332  
   333  func elfsetupplt(ctxt *ld.Link) {
   334  	plt := ctxt.Syms.Lookup(".plt", 0)
   335  	got := ctxt.Syms.Lookup(".got", 0)
   336  	if plt.Size == 0 {
   337  		// stg     %r1,56(%r15)
   338  		plt.AddUint8(0xe3)
   339  		plt.AddUint8(0x10)
   340  		plt.AddUint8(0xf0)
   341  		plt.AddUint8(0x38)
   342  		plt.AddUint8(0x00)
   343  		plt.AddUint8(0x24)
   344  		// larl    %r1,_GLOBAL_OFFSET_TABLE_
   345  		plt.AddUint8(0xc0)
   346  		plt.AddUint8(0x10)
   347  		plt.AddPCRelPlus(ctxt.Arch, got, 6)
   348  		// mvc     48(8,%r15),8(%r1)
   349  		plt.AddUint8(0xd2)
   350  		plt.AddUint8(0x07)
   351  		plt.AddUint8(0xf0)
   352  		plt.AddUint8(0x30)
   353  		plt.AddUint8(0x10)
   354  		plt.AddUint8(0x08)
   355  		// lg      %r1,16(%r1)
   356  		plt.AddUint8(0xe3)
   357  		plt.AddUint8(0x10)
   358  		plt.AddUint8(0x10)
   359  		plt.AddUint8(0x10)
   360  		plt.AddUint8(0x00)
   361  		plt.AddUint8(0x04)
   362  		// br      %r1
   363  		plt.AddUint8(0x07)
   364  		plt.AddUint8(0xf1)
   365  		// nopr    %r0
   366  		plt.AddUint8(0x07)
   367  		plt.AddUint8(0x00)
   368  		// nopr    %r0
   369  		plt.AddUint8(0x07)
   370  		plt.AddUint8(0x00)
   371  		// nopr    %r0
   372  		plt.AddUint8(0x07)
   373  		plt.AddUint8(0x00)
   374  
   375  		// assume got->size == 0 too
   376  		got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
   377  
   378  		got.AddUint64(ctxt.Arch, 0)
   379  		got.AddUint64(ctxt.Arch, 0)
   380  	}
   381  }
   382  
   383  func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
   384  	return false
   385  }
   386  
   387  func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
   388  	if ctxt.LinkMode == ld.LinkExternal {
   389  		return val, false
   390  	}
   391  
   392  	switch r.Type {
   393  	case objabi.R_CONST:
   394  		return r.Add, true
   395  	case objabi.R_GOTOFF:
   396  		return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
   397  	}
   398  
   399  	return val, false
   400  }
   401  
   402  func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
   403  	switch r.Variant & sym.RV_TYPE_MASK {
   404  	default:
   405  		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
   406  		return t
   407  
   408  	case sym.RV_NONE:
   409  		return t
   410  
   411  	case sym.RV_390_DBL:
   412  		if (t & 1) != 0 {
   413  			ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
   414  		}
   415  		return t >> 1
   416  	}
   417  }
   418  
   419  func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
   420  	if s.Plt() >= 0 {
   421  		return
   422  	}
   423  
   424  	ld.Adddynsym(ctxt, s)
   425  
   426  	if ctxt.IsELF {
   427  		plt := ctxt.Syms.Lookup(".plt", 0)
   428  		got := ctxt.Syms.Lookup(".got", 0)
   429  		rela := ctxt.Syms.Lookup(".rela.plt", 0)
   430  		if plt.Size == 0 {
   431  			elfsetupplt(ctxt)
   432  		}
   433  		// larl    %r1,_GLOBAL_OFFSET_TABLE_+index
   434  
   435  		plt.AddUint8(0xc0)
   436  		plt.AddUint8(0x10)
   437  		plt.AddPCRelPlus(ctxt.Arch, got, got.Size+6) // need variant?
   438  
   439  		// add to got: pointer to current pos in plt
   440  		got.AddAddrPlus(ctxt.Arch, plt, plt.Size+8) // weird but correct
   441  		// lg      %r1,0(%r1)
   442  		plt.AddUint8(0xe3)
   443  		plt.AddUint8(0x10)
   444  		plt.AddUint8(0x10)
   445  		plt.AddUint8(0x00)
   446  		plt.AddUint8(0x00)
   447  		plt.AddUint8(0x04)
   448  		// br      %r1
   449  		plt.AddUint8(0x07)
   450  		plt.AddUint8(0xf1)
   451  		// basr    %r1,%r0
   452  		plt.AddUint8(0x0d)
   453  		plt.AddUint8(0x10)
   454  		// lgf     %r1,12(%r1)
   455  		plt.AddUint8(0xe3)
   456  		plt.AddUint8(0x10)
   457  		plt.AddUint8(0x10)
   458  		plt.AddUint8(0x0c)
   459  		plt.AddUint8(0x00)
   460  		plt.AddUint8(0x14)
   461  		// jg .plt
   462  		plt.AddUint8(0xc0)
   463  		plt.AddUint8(0xf4)
   464  
   465  		plt.AddUint32(ctxt.Arch, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
   466  		//.plt index
   467  		plt.AddUint32(ctxt.Arch, uint32(rela.Size)) // rela size before current entry
   468  
   469  		// rela
   470  		rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
   471  
   472  		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_JMP_SLOT)))
   473  		rela.AddUint64(ctxt.Arch, 0)
   474  
   475  		s.SetPlt(int32(plt.Size - 32))
   476  
   477  	} else {
   478  		ld.Errorf(s, "addpltsym: unsupported binary format")
   479  	}
   480  }
   481  
   482  func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
   483  	if s.Got() >= 0 {
   484  		return
   485  	}
   486  
   487  	ld.Adddynsym(ctxt, s)
   488  	got := ctxt.Syms.Lookup(".got", 0)
   489  	s.SetGot(int32(got.Size))
   490  	got.AddUint64(ctxt.Arch, 0)
   491  
   492  	if ctxt.IsELF {
   493  		rela := ctxt.Syms.Lookup(".rela", 0)
   494  		rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
   495  		rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_GLOB_DAT)))
   496  		rela.AddUint64(ctxt.Arch, 0)
   497  	} else {
   498  		ld.Errorf(s, "addgotsym: unsupported binary format")
   499  	}
   500  }
   501  
   502  func asmb(ctxt *ld.Link) {
   503  	if ctxt.Debugvlog != 0 {
   504  		ctxt.Logf("%5.2f asmb\n", ld.Cputime())
   505  	}
   506  
   507  	if ctxt.IsELF {
   508  		ld.Asmbelfsetup()
   509  	}
   510  
   511  	sect := ld.Segtext.Sections[0]
   512  	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   513  	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   514  	for _, sect = range ld.Segtext.Sections[1:] {
   515  		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   516  		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   517  	}
   518  
   519  	if ld.Segrodata.Filelen > 0 {
   520  		if ctxt.Debugvlog != 0 {
   521  			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   522  		}
   523  		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
   524  		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
   525  	}
   526  	if ld.Segrelrodata.Filelen > 0 {
   527  		if ctxt.Debugvlog != 0 {
   528  			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   529  		}
   530  		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
   531  		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
   532  	}
   533  
   534  	if ctxt.Debugvlog != 0 {
   535  		ctxt.Logf("%5.2f datblk\n", ld.Cputime())
   536  	}
   537  
   538  	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
   539  	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
   540  
   541  	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
   542  	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
   543  
   544  	/* output symbol table */
   545  	ld.Symsize = 0
   546  
   547  	ld.Lcsize = 0
   548  	symo := uint32(0)
   549  	if !*ld.FlagS {
   550  		if !ctxt.IsELF {
   551  			ld.Errorf(nil, "unsupported executable format")
   552  		}
   553  		if ctxt.Debugvlog != 0 {
   554  			ctxt.Logf("%5.2f sym\n", ld.Cputime())
   555  		}
   556  		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
   557  		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
   558  
   559  		ctxt.Out.SeekSet(int64(symo))
   560  		if ctxt.Debugvlog != 0 {
   561  			ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
   562  		}
   563  		ld.Asmelfsym(ctxt)
   564  		ctxt.Out.Flush()
   565  		ctxt.Out.Write(ld.Elfstrdat)
   566  
   567  		if ctxt.Debugvlog != 0 {
   568  			ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
   569  		}
   570  
   571  		if ctxt.LinkMode == ld.LinkExternal {
   572  			ld.Elfemitreloc(ctxt)
   573  		}
   574  	}
   575  
   576  	if ctxt.Debugvlog != 0 {
   577  		ctxt.Logf("%5.2f header\n", ld.Cputime())
   578  	}
   579  	ctxt.Out.SeekSet(0)
   580  	switch ctxt.HeadType {
   581  	default:
   582  		ld.Errorf(nil, "unsupported operating system")
   583  	case objabi.Hlinux:
   584  		ld.Asmbelf(ctxt, int64(symo))
   585  	}
   586  
   587  	ctxt.Out.Flush()
   588  	if *ld.FlagC {
   589  		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
   590  		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
   591  		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
   592  		fmt.Printf("symsize=%d\n", ld.Symsize)
   593  		fmt.Printf("lcsize=%d\n", ld.Lcsize)
   594  		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
   595  	}
   596  }