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