github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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) bool {
   236  	ld.Thearch.Vput(uint64(sectoff))
   237  
   238  	elfsym := r.Xsym.ElfsymForReloc()
   239  	switch r.Type {
   240  	default:
   241  		return false
   242  	case objabi.R_TLS_LE:
   243  		switch r.Siz {
   244  		default:
   245  			return false
   246  		case 4:
   247  			// WARNING - silently ignored by linker in ELF64
   248  			ld.Thearch.Vput(ld.R_390_TLS_LE32 | uint64(elfsym)<<32)
   249  		case 8:
   250  			// WARNING - silently ignored by linker in ELF32
   251  			ld.Thearch.Vput(ld.R_390_TLS_LE64 | uint64(elfsym)<<32)
   252  		}
   253  	case objabi.R_TLS_IE:
   254  		switch r.Siz {
   255  		default:
   256  			return false
   257  		case 4:
   258  			ld.Thearch.Vput(ld.R_390_TLS_IEENT | uint64(elfsym)<<32)
   259  		}
   260  	case objabi.R_ADDR:
   261  		switch r.Siz {
   262  		default:
   263  			return false
   264  		case 4:
   265  			ld.Thearch.Vput(ld.R_390_32 | uint64(elfsym)<<32)
   266  		case 8:
   267  			ld.Thearch.Vput(ld.R_390_64 | uint64(elfsym)<<32)
   268  		}
   269  	case objabi.R_GOTPCREL:
   270  		if r.Siz == 4 {
   271  			ld.Thearch.Vput(ld.R_390_GOTENT | uint64(elfsym)<<32)
   272  		} else {
   273  			return false
   274  		}
   275  	case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
   276  		elfrel := ld.R_390_NONE
   277  		isdbl := r.Variant&ld.RV_TYPE_MASK == ld.RV_390_DBL
   278  		// TODO(mundaym): all DBL style relocations should be
   279  		// signalled using the variant - see issue 14218.
   280  		switch r.Type {
   281  		case objabi.R_PCRELDBL, objabi.R_CALL:
   282  			isdbl = true
   283  		}
   284  		if r.Xsym.Type == ld.SDYNIMPORT && (r.Xsym.ElfType == elf.STT_FUNC || r.Type == objabi.R_CALL) {
   285  			if isdbl {
   286  				switch r.Siz {
   287  				case 2:
   288  					elfrel = ld.R_390_PLT16DBL
   289  				case 4:
   290  					elfrel = ld.R_390_PLT32DBL
   291  				}
   292  			} else {
   293  				switch r.Siz {
   294  				case 4:
   295  					elfrel = ld.R_390_PLT32
   296  				case 8:
   297  					elfrel = ld.R_390_PLT64
   298  				}
   299  			}
   300  		} else {
   301  			if isdbl {
   302  				switch r.Siz {
   303  				case 2:
   304  					elfrel = ld.R_390_PC16DBL
   305  				case 4:
   306  					elfrel = ld.R_390_PC32DBL
   307  				}
   308  			} else {
   309  				switch r.Siz {
   310  				case 2:
   311  					elfrel = ld.R_390_PC16
   312  				case 4:
   313  					elfrel = ld.R_390_PC32
   314  				case 8:
   315  					elfrel = ld.R_390_PC64
   316  				}
   317  			}
   318  		}
   319  		if elfrel == ld.R_390_NONE {
   320  			return false // unsupported size/dbl combination
   321  		}
   322  		ld.Thearch.Vput(uint64(elfrel) | uint64(elfsym)<<32)
   323  	}
   324  
   325  	ld.Thearch.Vput(uint64(r.Xadd))
   326  	return true
   327  }
   328  
   329  func elfsetupplt(ctxt *ld.Link) {
   330  	plt := ctxt.Syms.Lookup(".plt", 0)
   331  	got := ctxt.Syms.Lookup(".got", 0)
   332  	if plt.Size == 0 {
   333  		// stg     %r1,56(%r15)
   334  		ld.Adduint8(ctxt, plt, 0xe3)
   335  		ld.Adduint8(ctxt, plt, 0x10)
   336  		ld.Adduint8(ctxt, plt, 0xf0)
   337  		ld.Adduint8(ctxt, plt, 0x38)
   338  		ld.Adduint8(ctxt, plt, 0x00)
   339  		ld.Adduint8(ctxt, plt, 0x24)
   340  		// larl    %r1,_GLOBAL_OFFSET_TABLE_
   341  		ld.Adduint8(ctxt, plt, 0xc0)
   342  		ld.Adduint8(ctxt, plt, 0x10)
   343  		ld.Addpcrelplus(ctxt, plt, got, 6)
   344  		// mvc     48(8,%r15),8(%r1)
   345  		ld.Adduint8(ctxt, plt, 0xd2)
   346  		ld.Adduint8(ctxt, plt, 0x07)
   347  		ld.Adduint8(ctxt, plt, 0xf0)
   348  		ld.Adduint8(ctxt, plt, 0x30)
   349  		ld.Adduint8(ctxt, plt, 0x10)
   350  		ld.Adduint8(ctxt, plt, 0x08)
   351  		// lg      %r1,16(%r1)
   352  		ld.Adduint8(ctxt, plt, 0xe3)
   353  		ld.Adduint8(ctxt, plt, 0x10)
   354  		ld.Adduint8(ctxt, plt, 0x10)
   355  		ld.Adduint8(ctxt, plt, 0x10)
   356  		ld.Adduint8(ctxt, plt, 0x00)
   357  		ld.Adduint8(ctxt, plt, 0x04)
   358  		// br      %r1
   359  		ld.Adduint8(ctxt, plt, 0x07)
   360  		ld.Adduint8(ctxt, plt, 0xf1)
   361  		// nopr    %r0
   362  		ld.Adduint8(ctxt, plt, 0x07)
   363  		ld.Adduint8(ctxt, plt, 0x00)
   364  		// nopr    %r0
   365  		ld.Adduint8(ctxt, plt, 0x07)
   366  		ld.Adduint8(ctxt, plt, 0x00)
   367  		// nopr    %r0
   368  		ld.Adduint8(ctxt, plt, 0x07)
   369  		ld.Adduint8(ctxt, plt, 0x00)
   370  
   371  		// assume got->size == 0 too
   372  		ld.Addaddrplus(ctxt, got, ctxt.Syms.Lookup(".dynamic", 0), 0)
   373  
   374  		ld.Adduint64(ctxt, got, 0)
   375  		ld.Adduint64(ctxt, got, 0)
   376  	}
   377  }
   378  
   379  func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) bool {
   380  	return false
   381  }
   382  
   383  func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
   384  	if ld.Linkmode == ld.LinkExternal {
   385  		return false
   386  	}
   387  
   388  	switch r.Type {
   389  	case objabi.R_CONST:
   390  		*val = r.Add
   391  		return true
   392  	case objabi.R_GOTOFF:
   393  		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
   394  		return true
   395  	}
   396  
   397  	return false
   398  }
   399  
   400  func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
   401  	switch r.Variant & ld.RV_TYPE_MASK {
   402  	default:
   403  		ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
   404  		return t
   405  
   406  	case ld.RV_NONE:
   407  		return t
   408  
   409  	case ld.RV_390_DBL:
   410  		if (t & 1) != 0 {
   411  			ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
   412  		}
   413  		return t >> 1
   414  	}
   415  }
   416  
   417  func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
   418  	if s.Plt >= 0 {
   419  		return
   420  	}
   421  
   422  	ld.Adddynsym(ctxt, s)
   423  
   424  	if ld.Iself {
   425  		plt := ctxt.Syms.Lookup(".plt", 0)
   426  		got := ctxt.Syms.Lookup(".got", 0)
   427  		rela := ctxt.Syms.Lookup(".rela.plt", 0)
   428  		if plt.Size == 0 {
   429  			elfsetupplt(ctxt)
   430  		}
   431  		// larl    %r1,_GLOBAL_OFFSET_TABLE_+index
   432  
   433  		ld.Adduint8(ctxt, plt, 0xc0)
   434  		ld.Adduint8(ctxt, plt, 0x10)
   435  		ld.Addpcrelplus(ctxt, plt, got, got.Size+6) // need variant?
   436  
   437  		// add to got: pointer to current pos in plt
   438  		ld.Addaddrplus(ctxt, got, plt, plt.Size+8) // weird but correct
   439  		// lg      %r1,0(%r1)
   440  		ld.Adduint8(ctxt, plt, 0xe3)
   441  		ld.Adduint8(ctxt, plt, 0x10)
   442  		ld.Adduint8(ctxt, plt, 0x10)
   443  		ld.Adduint8(ctxt, plt, 0x00)
   444  		ld.Adduint8(ctxt, plt, 0x00)
   445  		ld.Adduint8(ctxt, plt, 0x04)
   446  		// br      %r1
   447  		ld.Adduint8(ctxt, plt, 0x07)
   448  		ld.Adduint8(ctxt, plt, 0xf1)
   449  		// basr    %r1,%r0
   450  		ld.Adduint8(ctxt, plt, 0x0d)
   451  		ld.Adduint8(ctxt, plt, 0x10)
   452  		// lgf     %r1,12(%r1)
   453  		ld.Adduint8(ctxt, plt, 0xe3)
   454  		ld.Adduint8(ctxt, plt, 0x10)
   455  		ld.Adduint8(ctxt, plt, 0x10)
   456  		ld.Adduint8(ctxt, plt, 0x0c)
   457  		ld.Adduint8(ctxt, plt, 0x00)
   458  		ld.Adduint8(ctxt, plt, 0x14)
   459  		// jg .plt
   460  		ld.Adduint8(ctxt, plt, 0xc0)
   461  		ld.Adduint8(ctxt, plt, 0xf4)
   462  
   463  		ld.Adduint32(ctxt, plt, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
   464  		//.plt index
   465  		ld.Adduint32(ctxt, plt, uint32(rela.Size)) // rela size before current entry
   466  
   467  		// rela
   468  		ld.Addaddrplus(ctxt, rela, got, got.Size-8)
   469  
   470  		ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_390_JMP_SLOT))
   471  		ld.Adduint64(ctxt, rela, 0)
   472  
   473  		s.Plt = int32(plt.Size - 32)
   474  
   475  	} else {
   476  		ld.Errorf(s, "addpltsym: unsupported binary format")
   477  	}
   478  }
   479  
   480  func addgotsym(ctxt *ld.Link, s *ld.Symbol) {
   481  	if s.Got >= 0 {
   482  		return
   483  	}
   484  
   485  	ld.Adddynsym(ctxt, s)
   486  	got := ctxt.Syms.Lookup(".got", 0)
   487  	s.Got = int32(got.Size)
   488  	ld.Adduint64(ctxt, got, 0)
   489  
   490  	if ld.Iself {
   491  		rela := ctxt.Syms.Lookup(".rela", 0)
   492  		ld.Addaddrplus(ctxt, rela, got, int64(s.Got))
   493  		ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_390_GLOB_DAT))
   494  		ld.Adduint64(ctxt, rela, 0)
   495  	} else {
   496  		ld.Errorf(s, "addgotsym: unsupported binary format")
   497  	}
   498  }
   499  
   500  func asmb(ctxt *ld.Link) {
   501  	if ctxt.Debugvlog != 0 {
   502  		ctxt.Logf("%5.2f asmb\n", ld.Cputime())
   503  	}
   504  
   505  	if ld.Iself {
   506  		ld.Asmbelfsetup()
   507  	}
   508  
   509  	sect := ld.Segtext.Sections[0]
   510  	ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   511  	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   512  	for _, sect = range ld.Segtext.Sections[1:] {
   513  		ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   514  		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   515  	}
   516  
   517  	if ld.Segrodata.Filelen > 0 {
   518  		if ctxt.Debugvlog != 0 {
   519  			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   520  		}
   521  		ld.Cseek(int64(ld.Segrodata.Fileoff))
   522  		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
   523  	}
   524  	if ld.Segrelrodata.Filelen > 0 {
   525  		if ctxt.Debugvlog != 0 {
   526  			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   527  		}
   528  		ld.Cseek(int64(ld.Segrelrodata.Fileoff))
   529  		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
   530  	}
   531  
   532  	if ctxt.Debugvlog != 0 {
   533  		ctxt.Logf("%5.2f datblk\n", ld.Cputime())
   534  	}
   535  
   536  	ld.Cseek(int64(ld.Segdata.Fileoff))
   537  	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
   538  
   539  	ld.Cseek(int64(ld.Segdwarf.Fileoff))
   540  	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
   541  
   542  	/* output symbol table */
   543  	ld.Symsize = 0
   544  
   545  	ld.Lcsize = 0
   546  	symo := uint32(0)
   547  	if !*ld.FlagS {
   548  		if !ld.Iself {
   549  			ld.Errorf(nil, "unsupported executable format")
   550  		}
   551  		if ctxt.Debugvlog != 0 {
   552  			ctxt.Logf("%5.2f sym\n", ld.Cputime())
   553  		}
   554  		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
   555  		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
   556  
   557  		ld.Cseek(int64(symo))
   558  		if ctxt.Debugvlog != 0 {
   559  			ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
   560  		}
   561  		ld.Asmelfsym(ctxt)
   562  		ld.Cflush()
   563  		ld.Cwrite(ld.Elfstrdat)
   564  
   565  		if ctxt.Debugvlog != 0 {
   566  			ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
   567  		}
   568  
   569  		if ld.Linkmode == ld.LinkExternal {
   570  			ld.Elfemitreloc(ctxt)
   571  		}
   572  	}
   573  
   574  	if ctxt.Debugvlog != 0 {
   575  		ctxt.Logf("%5.2f header\n", ld.Cputime())
   576  	}
   577  	ld.Cseek(0)
   578  	switch ld.Headtype {
   579  	default:
   580  		ld.Errorf(nil, "unsupported operating system")
   581  	case objabi.Hlinux:
   582  		ld.Asmbelf(ctxt, int64(symo))
   583  	}
   584  
   585  	ld.Cflush()
   586  	if *ld.FlagC {
   587  		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
   588  		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
   589  		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
   590  		fmt.Printf("symsize=%d\n", ld.Symsize)
   591  		fmt.Printf("lcsize=%d\n", ld.Lcsize)
   592  		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
   593  	}
   594  }