Home | History | Annotate | Download | only in ld
      1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c
      2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
      3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
      4 //
      5 //	Copyright  1994-1999 Lucent Technologies Inc.  All rights reserved.
      6 //	Portions Copyright  1995-1997 C H Forsyth (forsyth (a] terzarima.net)
      7 //	Portions Copyright  1997-1999 Vita Nuova Limited
      8 //	Portions Copyright  2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
      9 //	Portions Copyright  2004,2006 Bruce Ellis
     10 //	Portions Copyright  2005-2007 C H Forsyth (forsyth (a] terzarima.net)
     11 //	Revisions Copyright  2000-2007 Lucent Technologies Inc. and others
     12 //	Portions Copyright  2009 The Go Authors.  All rights reserved.
     13 //
     14 // Permission is hereby granted, free of charge, to any person obtaining a copy
     15 // of this software and associated documentation files (the "Software"), to deal
     16 // in the Software without restriction, including without limitation the rights
     17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     18 // copies of the Software, and to permit persons to whom the Software is
     19 // furnished to do so, subject to the following conditions:
     20 //
     21 // The above copyright notice and this permission notice shall be included in
     22 // all copies or substantial portions of the Software.
     23 //
     24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     30 // THE SOFTWARE.
     31 
     32 package ld
     33 
     34 import (
     35 	"cmd/internal/gcprog"
     36 	"cmd/internal/obj"
     37 	"fmt"
     38 	"log"
     39 	"os"
     40 	"strconv"
     41 	"strings"
     42 )
     43 
     44 func Symgrow(ctxt *Link, s *LSym, siz int64) {
     45 	if int64(int(siz)) != siz {
     46 		log.Fatalf("symgrow size %d too long", siz)
     47 	}
     48 	if int64(len(s.P)) >= siz {
     49 		return
     50 	}
     51 	for cap(s.P) < int(siz) {
     52 		s.P = append(s.P[:len(s.P)], 0)
     53 	}
     54 	s.P = s.P[:siz]
     55 }
     56 
     57 func Addrel(s *LSym) *Reloc {
     58 	s.R = append(s.R, Reloc{})
     59 	return &s.R[len(s.R)-1]
     60 }
     61 
     62 func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
     63 	if s.Type == 0 {
     64 		s.Type = obj.SDATA
     65 	}
     66 	s.Reachable = true
     67 	if s.Size < off+wid {
     68 		s.Size = off + wid
     69 		Symgrow(ctxt, s, s.Size)
     70 	}
     71 
     72 	switch wid {
     73 	case 1:
     74 		s.P[off] = uint8(v)
     75 	case 2:
     76 		ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
     77 	case 4:
     78 		ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
     79 	case 8:
     80 		ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v))
     81 	}
     82 
     83 	return off + wid
     84 }
     85 
     86 func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
     87 	off := s.Size
     88 	setuintxx(ctxt, s, off, v, int64(wid))
     89 	return off
     90 }
     91 
     92 func Adduint8(ctxt *Link, s *LSym, v uint8) int64 {
     93 	return adduintxx(ctxt, s, uint64(v), 1)
     94 }
     95 
     96 func Adduint16(ctxt *Link, s *LSym, v uint16) int64 {
     97 	return adduintxx(ctxt, s, uint64(v), 2)
     98 }
     99 
    100 func Adduint32(ctxt *Link, s *LSym, v uint32) int64 {
    101 	return adduintxx(ctxt, s, uint64(v), 4)
    102 }
    103 
    104 func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
    105 	return adduintxx(ctxt, s, v, 8)
    106 }
    107 
    108 func adduint(ctxt *Link, s *LSym, v uint64) int64 {
    109 	return adduintxx(ctxt, s, v, Thearch.Intsize)
    110 }
    111 
    112 func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
    113 	return setuintxx(ctxt, s, r, uint64(v), 1)
    114 }
    115 
    116 func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 {
    117 	return setuintxx(ctxt, s, r, uint64(v), 4)
    118 }
    119 
    120 func Addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
    121 	if s.Type == 0 {
    122 		s.Type = obj.SDATA
    123 	}
    124 	s.Reachable = true
    125 	i := s.Size
    126 	s.Size += int64(ctxt.Arch.Ptrsize)
    127 	Symgrow(ctxt, s, s.Size)
    128 	r := Addrel(s)
    129 	r.Sym = t
    130 	r.Off = int32(i)
    131 	r.Siz = uint8(ctxt.Arch.Ptrsize)
    132 	r.Type = obj.R_ADDR
    133 	r.Add = add
    134 	return i + int64(r.Siz)
    135 }
    136 
    137 func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
    138 	if s.Type == 0 {
    139 		s.Type = obj.SDATA
    140 	}
    141 	s.Reachable = true
    142 	i := s.Size
    143 	s.Size += 4
    144 	Symgrow(ctxt, s, s.Size)
    145 	r := Addrel(s)
    146 	r.Sym = t
    147 	r.Off = int32(i)
    148 	r.Add = add
    149 	r.Type = obj.R_PCREL
    150 	r.Siz = 4
    151 	return i + int64(r.Siz)
    152 }
    153 
    154 func Addaddr(ctxt *Link, s *LSym, t *LSym) int64 {
    155 	return Addaddrplus(ctxt, s, t, 0)
    156 }
    157 
    158 func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
    159 	if s.Type == 0 {
    160 		s.Type = obj.SDATA
    161 	}
    162 	s.Reachable = true
    163 	if off+int64(ctxt.Arch.Ptrsize) > s.Size {
    164 		s.Size = off + int64(ctxt.Arch.Ptrsize)
    165 		Symgrow(ctxt, s, s.Size)
    166 	}
    167 
    168 	r := Addrel(s)
    169 	r.Sym = t
    170 	r.Off = int32(off)
    171 	r.Siz = uint8(ctxt.Arch.Ptrsize)
    172 	r.Type = obj.R_ADDR
    173 	r.Add = add
    174 	return off + int64(r.Siz)
    175 }
    176 
    177 func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 {
    178 	return setaddrplus(ctxt, s, off, t, 0)
    179 }
    180 
    181 func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
    182 	if s.Type == 0 {
    183 		s.Type = obj.SDATA
    184 	}
    185 	s.Reachable = true
    186 	i := s.Size
    187 	s.Size += int64(ctxt.Arch.Ptrsize)
    188 	Symgrow(ctxt, s, s.Size)
    189 	r := Addrel(s)
    190 	r.Sym = t
    191 	r.Off = int32(i)
    192 	r.Siz = uint8(ctxt.Arch.Ptrsize)
    193 	r.Type = obj.R_SIZE
    194 	return i + int64(r.Siz)
    195 }
    196 
    197 func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
    198 	if s.Type == 0 {
    199 		s.Type = obj.SDATA
    200 	}
    201 	s.Reachable = true
    202 	i := s.Size
    203 	s.Size += 4
    204 	Symgrow(ctxt, s, s.Size)
    205 	r := Addrel(s)
    206 	r.Sym = t
    207 	r.Off = int32(i)
    208 	r.Siz = 4
    209 	r.Type = obj.R_ADDR
    210 	r.Add = add
    211 	return i + int64(r.Siz)
    212 }
    213 
    214 /*
    215  * divide-and-conquer list-link
    216  * sort of LSym* structures.
    217  * Used for the data block.
    218  */
    219 func datcmp(s1 *LSym, s2 *LSym) int {
    220 	if s1.Type != s2.Type {
    221 		return int(s1.Type) - int(s2.Type)
    222 	}
    223 
    224 	// For ppc64, we want to interleave the .got and .toc sections
    225 	// from input files.  Both are type SELFGOT, so in that case
    226 	// fall through to the name comparison (conveniently, .got
    227 	// sorts before .toc).
    228 	if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
    229 		if s1.Size < s2.Size {
    230 			return -1
    231 		}
    232 		return +1
    233 	}
    234 
    235 	return stringsCompare(s1.Name, s2.Name)
    236 }
    237 
    238 func listnextp(s *LSym) **LSym {
    239 	return &s.Next
    240 }
    241 
    242 func listsubp(s *LSym) **LSym {
    243 	return &s.Sub
    244 }
    245 
    246 func listsort(l *LSym, cmp func(*LSym, *LSym) int, nextp func(*LSym) **LSym) *LSym {
    247 	if l == nil || *nextp(l) == nil {
    248 		return l
    249 	}
    250 
    251 	l1 := l
    252 	l2 := l
    253 	for {
    254 		l2 = *nextp(l2)
    255 		if l2 == nil {
    256 			break
    257 		}
    258 		l2 = *nextp(l2)
    259 		if l2 == nil {
    260 			break
    261 		}
    262 		l1 = *nextp(l1)
    263 	}
    264 
    265 	l2 = *nextp(l1)
    266 	*nextp(l1) = nil
    267 	l1 = listsort(l, cmp, nextp)
    268 	l2 = listsort(l2, cmp, nextp)
    269 
    270 	/* set up lead element */
    271 	if cmp(l1, l2) < 0 {
    272 		l = l1
    273 		l1 = *nextp(l1)
    274 	} else {
    275 		l = l2
    276 		l2 = *nextp(l2)
    277 	}
    278 
    279 	le := l
    280 
    281 	for {
    282 		if l1 == nil {
    283 			for l2 != nil {
    284 				*nextp(le) = l2
    285 				le = l2
    286 				l2 = *nextp(l2)
    287 			}
    288 
    289 			*nextp(le) = nil
    290 			break
    291 		}
    292 
    293 		if l2 == nil {
    294 			for l1 != nil {
    295 				*nextp(le) = l1
    296 				le = l1
    297 				l1 = *nextp(l1)
    298 			}
    299 
    300 			break
    301 		}
    302 
    303 		if cmp(l1, l2) < 0 {
    304 			*nextp(le) = l1
    305 			le = l1
    306 			l1 = *nextp(l1)
    307 		} else {
    308 			*nextp(le) = l2
    309 			le = l2
    310 			l2 = *nextp(l2)
    311 		}
    312 	}
    313 
    314 	*nextp(le) = nil
    315 	return l
    316 }
    317 
    318 func relocsym(s *LSym) {
    319 	var r *Reloc
    320 	var rs *LSym
    321 	var i16 int16
    322 	var off int32
    323 	var siz int32
    324 	var fl int32
    325 	var o int64
    326 
    327 	Ctxt.Cursym = s
    328 	for ri := int32(0); ri < int32(len(s.R)); ri++ {
    329 		r = &s.R[ri]
    330 		r.Done = 1
    331 		off = r.Off
    332 		siz = int32(r.Siz)
    333 		if off < 0 || off+siz > int32(len(s.P)) {
    334 			Diag("%s: invalid relocation %d+%d not in [%d,%d)", s.Name, off, siz, 0, len(s.P))
    335 			continue
    336 		}
    337 
    338 		if r.Sym != nil && (r.Sym.Type&(obj.SMASK|obj.SHIDDEN) == 0 || r.Sym.Type&obj.SMASK == obj.SXREF) {
    339 			// When putting the runtime but not main into a shared library
    340 			// these symbols are undefined and that's OK.
    341 			if Buildmode == BuildmodeShared && (r.Sym.Name == "main.main" || r.Sym.Name == "main.init") {
    342 				r.Sym.Type = obj.SDYNIMPORT
    343 			} else {
    344 				Diag("%s: not defined", r.Sym.Name)
    345 				continue
    346 			}
    347 		}
    348 
    349 		if r.Type >= 256 {
    350 			continue
    351 		}
    352 		if r.Siz == 0 { // informational relocation - no work to do
    353 			continue
    354 		}
    355 
    356 		// We need to be able to reference dynimport symbols when linking against
    357 		// shared libraries, and Solaris needs it always
    358 		if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() {
    359 			Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
    360 		}
    361 		if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Reachable {
    362 			Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name)
    363 		}
    364 
    365 		// Android emulates runtime.tlsg as a regular variable.
    366 		if r.Type == obj.R_TLS && goos == "android" {
    367 			r.Type = obj.R_ADDR
    368 		}
    369 
    370 		switch r.Type {
    371 		default:
    372 			o = 0
    373 			if Thearch.Archreloc(r, s, &o) < 0 {
    374 				Diag("unknown reloc %d", r.Type)
    375 			}
    376 
    377 		case obj.R_TLS:
    378 			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
    379 				r.Done = 0
    380 				r.Sym = Ctxt.Tlsg
    381 				r.Xsym = Ctxt.Tlsg
    382 				r.Xadd = r.Add
    383 				o = r.Add
    384 				break
    385 			}
    386 			if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' {
    387 				// On ELF ARM, the thread pointer is 8 bytes before
    388 				// the start of the thread-local data block, so add 8
    389 				// to the actual TLS offset (r->sym->value).
    390 				// This 8 seems to be a fundamental constant of
    391 				// ELF on ARM (or maybe Glibc on ARM); it is not
    392 				// related to the fact that our own TLS storage happens
    393 				// to take up 8 bytes.
    394 				o = 8 + r.Sym.Value
    395 
    396 				break
    397 			}
    398 
    399 			r.Done = 0
    400 			o = 0
    401 			if Thearch.Thechar != '6' {
    402 				o = r.Add
    403 			}
    404 
    405 		case obj.R_TLS_LE:
    406 			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
    407 				r.Done = 0
    408 				r.Sym = Ctxt.Tlsg
    409 				r.Xsym = Ctxt.Tlsg
    410 				r.Xadd = r.Add
    411 				o = 0
    412 				if Thearch.Thechar != '6' {
    413 					o = r.Add
    414 				}
    415 				break
    416 			}
    417 
    418 			if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
    419 				o = int64(Ctxt.Tlsoffset) + r.Add
    420 			} else if Ctxt.Headtype == obj.Hwindows {
    421 				o = r.Add
    422 			} else {
    423 				log.Fatalf("unexpected R_TLS_LE relocation for %s", Headstr(Ctxt.Headtype))
    424 			}
    425 
    426 		case obj.R_TLS_IE:
    427 			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
    428 				r.Done = 0
    429 				r.Sym = Ctxt.Tlsg
    430 				r.Xsym = Ctxt.Tlsg
    431 				r.Xadd = r.Add
    432 				o = 0
    433 				if Thearch.Thechar != '6' {
    434 					o = r.Add
    435 				}
    436 				break
    437 			}
    438 			log.Fatalf("cannot handle R_TLS_IE when linking internally")
    439 
    440 		case obj.R_ADDR:
    441 			if Linkmode == LinkExternal && r.Sym.Type != obj.SCONST {
    442 				r.Done = 0
    443 
    444 				// set up addend for eventual relocation via outer symbol.
    445 				rs = r.Sym
    446 
    447 				r.Xadd = r.Add
    448 				for rs.Outer != nil {
    449 					r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
    450 					rs = rs.Outer
    451 				}
    452 
    453 				if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
    454 					Diag("missing section for %s", rs.Name)
    455 				}
    456 				r.Xsym = rs
    457 
    458 				o = r.Xadd
    459 				if Iself {
    460 					if Thearch.Thechar == '6' {
    461 						o = 0
    462 					}
    463 				} else if HEADTYPE == obj.Hdarwin {
    464 					// ld64 for arm64 has a bug where if the address pointed to by o exists in the
    465 					// symbol table (dynid >= 0), or is inside a symbol that exists in the symbol
    466 					// table, then it will add o twice into the relocated value.
    467 					// The workaround is that on arm64 don't ever add symaddr to o and always use
    468 					// extern relocation by requiring rs->dynid >= 0.
    469 					if rs.Type != obj.SHOSTOBJ {
    470 						if Thearch.Thechar == '7' && rs.Dynid < 0 {
    471 							Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o)
    472 						}
    473 						if Thearch.Thechar != '7' {
    474 							o += Symaddr(rs)
    475 						}
    476 					}
    477 				} else if HEADTYPE == obj.Hwindows {
    478 					// nothing to do
    479 				} else {
    480 					Diag("unhandled pcrel relocation for %s", headstring)
    481 				}
    482 
    483 				break
    484 			}
    485 
    486 			o = Symaddr(r.Sym) + r.Add
    487 
    488 			// On amd64, 4-byte offsets will be sign-extended, so it is impossible to
    489 			// access more than 2GB of static data; fail at link time is better than
    490 			// fail at runtime. See https://golang.org/issue/7980.
    491 			// Instead of special casing only amd64, we treat this as an error on all
    492 			// 64-bit architectures so as to be future-proof.
    493 			if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 {
    494 				Diag("non-pc-relative relocation address is too big: %#x (%#x + %#x)", uint64(o), Symaddr(r.Sym), r.Add)
    495 				errorexit()
    496 			}
    497 
    498 			// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
    499 		case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL:
    500 			if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) {
    501 				r.Done = 0
    502 
    503 				// set up addend for eventual relocation via outer symbol.
    504 				rs = r.Sym
    505 
    506 				r.Xadd = r.Add
    507 				for rs.Outer != nil {
    508 					r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
    509 					rs = rs.Outer
    510 				}
    511 
    512 				r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
    513 				if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
    514 					Diag("missing section for %s", rs.Name)
    515 				}
    516 				r.Xsym = rs
    517 
    518 				o = r.Xadd
    519 				if Iself {
    520 					if Thearch.Thechar == '6' {
    521 						o = 0
    522 					}
    523 				} else if HEADTYPE == obj.Hdarwin {
    524 					if r.Type == obj.R_CALL {
    525 						if rs.Type != obj.SHOSTOBJ {
    526 							o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
    527 						}
    528 						o -= int64(r.Off) // relative to section offset, not symbol
    529 					} else {
    530 						o += int64(r.Siz)
    531 					}
    532 				} else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL
    533 					// PE/COFF's PC32 relocation uses the address after the relocated
    534 					// bytes as the base. Compensate by skewing the addend.
    535 					o += int64(r.Siz)
    536 					// GNU ld always add VirtualAddress of the .text section to the
    537 					// relocated address, compensate that.
    538 					o -= int64(s.Sect.Vaddr - PEBASE)
    539 				} else {
    540 					Diag("unhandled pcrel relocation for %s", headstring)
    541 				}
    542 
    543 				break
    544 			}
    545 
    546 			o = 0
    547 			if r.Sym != nil {
    548 				o += Symaddr(r.Sym)
    549 			}
    550 
    551 			// NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c
    552 			// compiler. The expression s->value + r->off + r->siz is int32 + int32 +
    553 			// uchar, and Plan 9 8c incorrectly treats the expression as type uint32
    554 			// instead of int32, causing incorrect values when sign extended for adding
    555 			// to o. The bug only occurs on Plan 9, because this C program is compiled by
    556 			// the standard host compiler (gcc on most other systems).
    557 			o += r.Add - (s.Value + int64(r.Off) + int64(int32(r.Siz)))
    558 
    559 		case obj.R_SIZE:
    560 			o = r.Sym.Size + r.Add
    561 		}
    562 
    563 		if r.Variant != RV_NONE {
    564 			o = Thearch.Archrelocvariant(r, s, o)
    565 		}
    566 
    567 		if false {
    568 			nam := "<nil>"
    569 			if r.Sym != nil {
    570 				nam = r.Sym.Name
    571 			}
    572 			fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x [type %d/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, Symaddr(r.Sym), r.Add, r.Type, r.Variant, o)
    573 		}
    574 		switch siz {
    575 		default:
    576 			Ctxt.Cursym = s
    577 			Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
    578 			fallthrough
    579 
    580 			// TODO(rsc): Remove.
    581 		case 1:
    582 			s.P[off] = byte(int8(o))
    583 
    584 		case 2:
    585 			if o != int64(int16(o)) {
    586 				Diag("relocation address is too big: %#x", o)
    587 			}
    588 			i16 = int16(o)
    589 			Ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))
    590 
    591 		case 4:
    592 			if r.Type == obj.R_PCREL || r.Type == obj.R_CALL {
    593 				if o != int64(int32(o)) {
    594 					Diag("pc-relative relocation address is too big: %#x", o)
    595 				}
    596 			} else {
    597 				if o != int64(int32(o)) && o != int64(uint32(o)) {
    598 					Diag("non-pc-relative relocation address is too big: %#x", uint64(o))
    599 				}
    600 			}
    601 
    602 			fl = int32(o)
    603 			Ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
    604 
    605 		case 8:
    606 			Ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
    607 		}
    608 	}
    609 }
    610 
    611 func reloc() {
    612 	if Debug['v'] != 0 {
    613 		fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
    614 	}
    615 	Bso.Flush()
    616 
    617 	for s := Ctxt.Textp; s != nil; s = s.Next {
    618 		relocsym(s)
    619 	}
    620 	for s := datap; s != nil; s = s.Next {
    621 		relocsym(s)
    622 	}
    623 }
    624 
    625 func dynrelocsym(s *LSym) {
    626 	if HEADTYPE == obj.Hwindows && Linkmode != LinkExternal {
    627 		rel := Linklookup(Ctxt, ".rel", 0)
    628 		if s == rel {
    629 			return
    630 		}
    631 		var r *Reloc
    632 		var targ *LSym
    633 		for ri := 0; ri < len(s.R); ri++ {
    634 			r = &s.R[ri]
    635 			targ = r.Sym
    636 			if targ == nil {
    637 				continue
    638 			}
    639 			if !targ.Reachable {
    640 				Diag("internal inconsistency: dynamic symbol %s is not reachable.", targ.Name)
    641 			}
    642 			if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files.
    643 				targ.Plt = int32(rel.Size)
    644 				r.Sym = rel
    645 				r.Add = int64(targ.Plt)
    646 
    647 				// jmp *addr
    648 				if Thearch.Thechar == '8' {
    649 					Adduint8(Ctxt, rel, 0xff)
    650 					Adduint8(Ctxt, rel, 0x25)
    651 					Addaddr(Ctxt, rel, targ)
    652 					Adduint8(Ctxt, rel, 0x90)
    653 					Adduint8(Ctxt, rel, 0x90)
    654 				} else {
    655 					Adduint8(Ctxt, rel, 0xff)
    656 					Adduint8(Ctxt, rel, 0x24)
    657 					Adduint8(Ctxt, rel, 0x25)
    658 					addaddrplus4(Ctxt, rel, targ, 0)
    659 					Adduint8(Ctxt, rel, 0x90)
    660 				}
    661 			} else if r.Sym.Plt >= 0 {
    662 				r.Sym = rel
    663 				r.Add = int64(targ.Plt)
    664 			}
    665 		}
    666 
    667 		return
    668 	}
    669 
    670 	var r *Reloc
    671 	for ri := 0; ri < len(s.R); ri++ {
    672 		r = &s.R[ri]
    673 		if r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT || r.Type >= 256 {
    674 			if r.Sym != nil && !r.Sym.Reachable {
    675 				Diag("internal inconsistency: dynamic symbol %s is not reachable.", r.Sym.Name)
    676 			}
    677 			Thearch.Adddynrel(s, r)
    678 		}
    679 	}
    680 }
    681 
    682 func dynreloc() {
    683 	// -d suppresses dynamic loader format, so we may as well not
    684 	// compute these sections or mark their symbols as reachable.
    685 	if Debug['d'] != 0 && HEADTYPE != obj.Hwindows {
    686 		return
    687 	}
    688 	if Debug['v'] != 0 {
    689 		fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
    690 	}
    691 	Bso.Flush()
    692 
    693 	for s := Ctxt.Textp; s != nil; s = s.Next {
    694 		dynrelocsym(s)
    695 	}
    696 	for s := datap; s != nil; s = s.Next {
    697 		dynrelocsym(s)
    698 	}
    699 	if Iself {
    700 		elfdynhash()
    701 	}
    702 }
    703 
    704 func blk(start *LSym, addr int64, size int64) {
    705 	var sym *LSym
    706 
    707 	for sym = start; sym != nil; sym = sym.Next {
    708 		if sym.Type&obj.SSUB == 0 && sym.Value >= addr {
    709 			break
    710 		}
    711 	}
    712 
    713 	eaddr := addr + size
    714 	var ep []byte
    715 	var p []byte
    716 	for ; sym != nil; sym = sym.Next {
    717 		if sym.Type&obj.SSUB != 0 {
    718 			continue
    719 		}
    720 		if sym.Value >= eaddr {
    721 			break
    722 		}
    723 		Ctxt.Cursym = sym
    724 		if sym.Value < addr {
    725 			Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type)
    726 			errorexit()
    727 		}
    728 
    729 		for ; addr < sym.Value; addr++ {
    730 			Cput(0)
    731 		}
    732 		p = sym.P
    733 		ep = p[len(sym.P):]
    734 		for -cap(p) < -cap(ep) {
    735 			Cput(uint8(p[0]))
    736 			p = p[1:]
    737 		}
    738 		addr += int64(len(sym.P))
    739 		for ; addr < sym.Value+sym.Size; addr++ {
    740 			Cput(0)
    741 		}
    742 		if addr != sym.Value+sym.Size {
    743 			Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size)
    744 			errorexit()
    745 		}
    746 
    747 		if sym.Value+sym.Size >= eaddr {
    748 			break
    749 		}
    750 	}
    751 
    752 	for ; addr < eaddr; addr++ {
    753 		Cput(0)
    754 	}
    755 	Cflush()
    756 }
    757 
    758 func Codeblk(addr int64, size int64) {
    759 	if Debug['a'] != 0 {
    760 		fmt.Fprintf(&Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
    761 	}
    762 
    763 	blk(Ctxt.Textp, addr, size)
    764 
    765 	/* again for printing */
    766 	if Debug['a'] == 0 {
    767 		return
    768 	}
    769 
    770 	var sym *LSym
    771 	for sym = Ctxt.Textp; sym != nil; sym = sym.Next {
    772 		if !sym.Reachable {
    773 			continue
    774 		}
    775 		if sym.Value >= addr {
    776 			break
    777 		}
    778 	}
    779 
    780 	eaddr := addr + size
    781 	var q []byte
    782 	for ; sym != nil; sym = sym.Next {
    783 		if !sym.Reachable {
    784 			continue
    785 		}
    786 		if sym.Value >= eaddr {
    787 			break
    788 		}
    789 
    790 		if addr < sym.Value {
    791 			fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
    792 			for ; addr < sym.Value; addr++ {
    793 				fmt.Fprintf(&Bso, " %.2x", 0)
    794 			}
    795 			fmt.Fprintf(&Bso, "\n")
    796 		}
    797 
    798 		fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name)
    799 		q = sym.P
    800 
    801 		for len(q) >= 16 {
    802 			fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q[:16])
    803 			addr += 16
    804 			q = q[16:]
    805 		}
    806 
    807 		if len(q) > 0 {
    808 			fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q)
    809 			addr += int64(len(q))
    810 		}
    811 	}
    812 
    813 	if addr < eaddr {
    814 		fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
    815 		for ; addr < eaddr; addr++ {
    816 			fmt.Fprintf(&Bso, " %.2x", 0)
    817 		}
    818 	}
    819 
    820 	Bso.Flush()
    821 }
    822 
    823 func Datblk(addr int64, size int64) {
    824 	if Debug['a'] != 0 {
    825 		fmt.Fprintf(&Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
    826 	}
    827 
    828 	blk(datap, addr, size)
    829 
    830 	/* again for printing */
    831 	if Debug['a'] == 0 {
    832 		return
    833 	}
    834 
    835 	var sym *LSym
    836 	for sym = datap; sym != nil; sym = sym.Next {
    837 		if sym.Value >= addr {
    838 			break
    839 		}
    840 	}
    841 
    842 	eaddr := addr + size
    843 	var ep []byte
    844 	var i int64
    845 	var p []byte
    846 	var r *Reloc
    847 	var rsname string
    848 	var typ string
    849 	for ; sym != nil; sym = sym.Next {
    850 		if sym.Value >= eaddr {
    851 			break
    852 		}
    853 		if addr < sym.Value {
    854 			fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint64(addr))
    855 			addr = sym.Value
    856 		}
    857 
    858 		fmt.Fprintf(&Bso, "%s\n\t%.8x|", sym.Name, uint(addr))
    859 		p = sym.P
    860 		ep = p[len(sym.P):]
    861 		for -cap(p) < -cap(ep) {
    862 			if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 {
    863 				fmt.Fprintf(&Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P))))
    864 			}
    865 			fmt.Fprintf(&Bso, " %.2x", p[0])
    866 			p = p[1:]
    867 		}
    868 
    869 		addr += int64(len(sym.P))
    870 		for ; addr < sym.Value+sym.Size; addr++ {
    871 			fmt.Fprintf(&Bso, " %.2x", 0)
    872 		}
    873 		fmt.Fprintf(&Bso, "\n")
    874 
    875 		if Linkmode == LinkExternal {
    876 			for i = 0; i < int64(len(sym.R)); i++ {
    877 				r = &sym.R[i]
    878 				rsname = ""
    879 				if r.Sym != nil {
    880 					rsname = r.Sym.Name
    881 				}
    882 				typ = "?"
    883 				switch r.Type {
    884 				case obj.R_ADDR:
    885 					typ = "addr"
    886 
    887 				case obj.R_PCREL:
    888 					typ = "pcrel"
    889 
    890 				case obj.R_CALL:
    891 					typ = "call"
    892 				}
    893 
    894 				fmt.Fprintf(&Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, int64(r.Add), int64(r.Sym.Value+r.Add))
    895 			}
    896 		}
    897 	}
    898 
    899 	if addr < eaddr {
    900 		fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint(addr))
    901 	}
    902 	fmt.Fprintf(&Bso, "\t%.8x|\n", uint(eaddr))
    903 }
    904 
    905 func strnput(s string, n int) {
    906 	for ; n > 0 && s != ""; s = s[1:] {
    907 		Cput(uint8(s[0]))
    908 		n--
    909 	}
    910 
    911 	for n > 0 {
    912 		Cput(0)
    913 		n--
    914 	}
    915 }
    916 
    917 var strdata []*LSym
    918 
    919 func addstrdata1(arg string) {
    920 	i := strings.Index(arg, "=")
    921 	if i < 0 {
    922 		Exitf("-X flag requires argument of the form importpath.name=value")
    923 	}
    924 	addstrdata(arg[:i], arg[i+1:])
    925 }
    926 
    927 func addstrdata(name string, value string) {
    928 	p := fmt.Sprintf("%s.str", name)
    929 	sp := Linklookup(Ctxt, p, 0)
    930 
    931 	Addstring(sp, value)
    932 	sp.Type = obj.SRODATA
    933 
    934 	s := Linklookup(Ctxt, name, 0)
    935 	s.Size = 0
    936 	s.Dupok = 1
    937 	reachable := s.Reachable
    938 	Addaddr(Ctxt, s, sp)
    939 	adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize)
    940 
    941 	// addstring, addaddr, etc., mark the symbols as reachable.
    942 	// In this case that is not necessarily true, so stick to what
    943 	// we know before entering this function.
    944 	s.Reachable = reachable
    945 
    946 	strdata = append(strdata, s)
    947 
    948 	sp.Reachable = reachable
    949 }
    950 
    951 func checkstrdata() {
    952 	for _, s := range strdata {
    953 		if s.Type == obj.STEXT {
    954 			Diag("cannot use -X with text symbol %s", s.Name)
    955 		} else if s.Gotype != nil && s.Gotype.Name != "type.string" {
    956 			Diag("cannot use -X with non-string symbol %s", s.Name)
    957 		}
    958 	}
    959 }
    960 
    961 func Addstring(s *LSym, str string) int64 {
    962 	if s.Type == 0 {
    963 		s.Type = obj.SNOPTRDATA
    964 	}
    965 	s.Reachable = true
    966 	r := int32(s.Size)
    967 	n := len(str) + 1
    968 	if s.Name == ".shstrtab" {
    969 		elfsetstring(str, int(r))
    970 	}
    971 	Symgrow(Ctxt, s, int64(r)+int64(n))
    972 	copy(s.P[r:], str)
    973 	s.P[int(r)+len(str)] = 0
    974 	s.Size += int64(n)
    975 	return int64(r)
    976 }
    977 
    978 // addgostring adds str, as a Go string value, to s. symname is the name of the
    979 // symbol used to define the string data and must be unique per linked object.
    980 func addgostring(s *LSym, symname, str string) {
    981 	sym := Linklookup(Ctxt, symname, 0)
    982 	if sym.Type != obj.Sxxx {
    983 		Diag("duplicate symname in addgostring: %s", symname)
    984 	}
    985 	sym.Reachable = true
    986 	sym.Local = true
    987 	sym.Type = obj.SRODATA
    988 	sym.Size = int64(len(str))
    989 	sym.P = []byte(str)
    990 	Addaddr(Ctxt, s, sym)
    991 	adduint(Ctxt, s, uint64(len(str)))
    992 }
    993 
    994 func addinitarrdata(s *LSym) {
    995 	p := s.Name + ".ptr"
    996 	sp := Linklookup(Ctxt, p, 0)
    997 	sp.Type = obj.SINITARR
    998 	sp.Size = 0
    999 	sp.Dupok = 1
   1000 	Addaddr(Ctxt, sp, s)
   1001 }
   1002 
   1003 func dosymtype() {
   1004 	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   1005 		if len(s.P) > 0 {
   1006 			if s.Type == obj.SBSS {
   1007 				s.Type = obj.SDATA
   1008 			}
   1009 			if s.Type == obj.SNOPTRBSS {
   1010 				s.Type = obj.SNOPTRDATA
   1011 			}
   1012 		}
   1013 		// Create a new entry in the .init_array section that points to the
   1014 		// library initializer function.
   1015 		switch Buildmode {
   1016 		case BuildmodeCArchive, BuildmodeCShared:
   1017 			if s.Name == INITENTRY {
   1018 				addinitarrdata(s)
   1019 			}
   1020 		}
   1021 	}
   1022 }
   1023 
   1024 func symalign(s *LSym) int32 {
   1025 	if s.Align != 0 {
   1026 		return s.Align
   1027 	}
   1028 
   1029 	align := int32(Thearch.Maxalign)
   1030 	for int64(align) > s.Size && align > 1 {
   1031 		align >>= 1
   1032 	}
   1033 	if align < s.Align {
   1034 		align = s.Align
   1035 	}
   1036 	return align
   1037 }
   1038 
   1039 func aligndatsize(datsize int64, s *LSym) int64 {
   1040 	return Rnd(datsize, int64(symalign(s)))
   1041 }
   1042 
   1043 // maxalign returns the maximum required alignment for
   1044 // the list of symbols s; the list stops when s->type exceeds type.
   1045 func maxalign(s *LSym, type_ int) int32 {
   1046 	var align int32
   1047 
   1048 	max := int32(0)
   1049 	for ; s != nil && int(s.Type) <= type_; s = s.Next {
   1050 		align = symalign(s)
   1051 		if max < align {
   1052 			max = align
   1053 		}
   1054 	}
   1055 
   1056 	return max
   1057 }
   1058 
   1059 const debugGCProg = false
   1060 
   1061 type GCProg struct {
   1062 	sym *LSym
   1063 	w   gcprog.Writer
   1064 }
   1065 
   1066 func (p *GCProg) Init(name string) {
   1067 	p.sym = Linklookup(Ctxt, name, 0)
   1068 	p.w.Init(p.writeByte)
   1069 	if debugGCProg {
   1070 		fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
   1071 		p.w.Debug(os.Stderr)
   1072 	}
   1073 }
   1074 
   1075 func (p *GCProg) writeByte(x byte) {
   1076 	Adduint8(Ctxt, p.sym, x)
   1077 }
   1078 
   1079 func (p *GCProg) End(size int64) {
   1080 	p.w.ZeroUntil(size / int64(Thearch.Ptrsize))
   1081 	p.w.End()
   1082 	if debugGCProg {
   1083 		fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
   1084 	}
   1085 }
   1086 
   1087 func (p *GCProg) AddSym(s *LSym) {
   1088 	typ := s.Gotype
   1089 	// Things without pointers should be in SNOPTRDATA or SNOPTRBSS;
   1090 	// everything we see should have pointers and should therefore have a type.
   1091 	if typ == nil {
   1092 		Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size))
   1093 		return
   1094 	}
   1095 
   1096 	ptrsize := int64(Thearch.Ptrsize)
   1097 	nptr := decodetype_ptrdata(typ) / ptrsize
   1098 
   1099 	if debugGCProg {
   1100 		fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr)
   1101 	}
   1102 
   1103 	if decodetype_usegcprog(typ) == 0 {
   1104 		// Copy pointers from mask into program.
   1105 		mask := decodetype_gcmask(typ)
   1106 		for i := int64(0); i < nptr; i++ {
   1107 			if (mask[i/8]>>uint(i%8))&1 != 0 {
   1108 				p.w.Ptr(s.Value/ptrsize + i)
   1109 			}
   1110 		}
   1111 		return
   1112 	}
   1113 
   1114 	// Copy program.
   1115 	prog := decodetype_gcprog(typ)
   1116 	p.w.ZeroUntil(s.Value / ptrsize)
   1117 	p.w.Append(prog[4:], nptr)
   1118 }
   1119 
   1120 func growdatsize(datsizep *int64, s *LSym) {
   1121 	datsize := *datsizep
   1122 	const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
   1123 	switch {
   1124 	case s.Size < 0:
   1125 		Diag("%s: negative size (%d bytes)", s.Name, s.Size)
   1126 	case s.Size > cutoff:
   1127 		Diag("%s: symbol too large (%d bytes)", s.Name, s.Size)
   1128 	case datsize <= cutoff && datsize+s.Size > cutoff:
   1129 		Diag("%s: too much data (over %d bytes)", s.Name, cutoff)
   1130 	}
   1131 	*datsizep = datsize + s.Size
   1132 }
   1133 
   1134 func dodata() {
   1135 	if Debug['v'] != 0 {
   1136 		fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
   1137 	}
   1138 	Bso.Flush()
   1139 
   1140 	var last *LSym
   1141 	datap = nil
   1142 
   1143 	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   1144 		if !s.Reachable || s.Special != 0 {
   1145 			continue
   1146 		}
   1147 		if obj.STEXT < s.Type && s.Type < obj.SXREF {
   1148 			if s.Onlist != 0 {
   1149 				log.Fatalf("symbol %s listed multiple times", s.Name)
   1150 			}
   1151 			s.Onlist = 1
   1152 			if last == nil {
   1153 				datap = s
   1154 			} else {
   1155 				last.Next = s
   1156 			}
   1157 			s.Next = nil
   1158 			last = s
   1159 		}
   1160 	}
   1161 
   1162 	for s := datap; s != nil; s = s.Next {
   1163 		if int64(len(s.P)) > s.Size {
   1164 			Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P))
   1165 		}
   1166 	}
   1167 
   1168 	/*
   1169 	 * now that we have the datap list, but before we start
   1170 	 * to assign addresses, record all the necessary
   1171 	 * dynamic relocations.  these will grow the relocation
   1172 	 * symbol, which is itself data.
   1173 	 *
   1174 	 * on darwin, we need the symbol table numbers for dynreloc.
   1175 	 */
   1176 	if HEADTYPE == obj.Hdarwin {
   1177 		machosymorder()
   1178 	}
   1179 	dynreloc()
   1180 
   1181 	/* some symbols may no longer belong in datap (Mach-O) */
   1182 	var l **LSym
   1183 	var s *LSym
   1184 	for l = &datap; ; {
   1185 		s = *l
   1186 		if s == nil {
   1187 			break
   1188 		}
   1189 
   1190 		if s.Type <= obj.STEXT || obj.SXREF <= s.Type {
   1191 			*l = s.Next
   1192 		} else {
   1193 			l = &s.Next
   1194 		}
   1195 	}
   1196 
   1197 	*l = nil
   1198 
   1199 	datap = listsort(datap, datcmp, listnextp)
   1200 
   1201 	if Iself {
   1202 		// Make .rela and .rela.plt contiguous, the ELF ABI requires this
   1203 		// and Solaris actually cares.
   1204 		var relplt *LSym
   1205 		for l = &datap; *l != nil; l = &(*l).Next {
   1206 			if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" {
   1207 				relplt = (*l)
   1208 				*l = (*l).Next
   1209 				break
   1210 			}
   1211 		}
   1212 		if relplt != nil {
   1213 			for s = datap; s != nil; s = s.Next {
   1214 				if s.Name == ".rel" || s.Name == ".rela" {
   1215 					relplt.Next = s.Next
   1216 					s.Next = relplt
   1217 				}
   1218 			}
   1219 		}
   1220 	}
   1221 
   1222 	/*
   1223 	 * allocate sections.  list is sorted by type,
   1224 	 * so we can just walk it for each piece we want to emit.
   1225 	 * segdata is processed before segtext, because we need
   1226 	 * to see all symbols in the .data and .bss sections in order
   1227 	 * to generate garbage collection information.
   1228 	 */
   1229 
   1230 	/* begin segdata */
   1231 
   1232 	/* skip symbols belonging to segtext */
   1233 	s = datap
   1234 
   1235 	for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
   1236 	}
   1237 
   1238 	/* writable ELF sections */
   1239 	datsize := int64(0)
   1240 
   1241 	var sect *Section
   1242 	for ; s != nil && s.Type < obj.SELFGOT; s = s.Next {
   1243 		sect = addsection(&Segdata, s.Name, 06)
   1244 		sect.Align = symalign(s)
   1245 		datsize = Rnd(datsize, int64(sect.Align))
   1246 		sect.Vaddr = uint64(datsize)
   1247 		s.Sect = sect
   1248 		s.Type = obj.SDATA
   1249 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1250 		growdatsize(&datsize, s)
   1251 		sect.Length = uint64(datsize) - sect.Vaddr
   1252 	}
   1253 
   1254 	/* .got (and .toc on ppc64) */
   1255 	if s.Type == obj.SELFGOT {
   1256 		sect := addsection(&Segdata, ".got", 06)
   1257 		sect.Align = maxalign(s, obj.SELFGOT)
   1258 		datsize = Rnd(datsize, int64(sect.Align))
   1259 		sect.Vaddr = uint64(datsize)
   1260 		var toc *LSym
   1261 		for ; s != nil && s.Type == obj.SELFGOT; s = s.Next {
   1262 			datsize = aligndatsize(datsize, s)
   1263 			s.Sect = sect
   1264 			s.Type = obj.SDATA
   1265 			s.Value = int64(uint64(datsize) - sect.Vaddr)
   1266 
   1267 			// Resolve .TOC. symbol for this object file (ppc64)
   1268 			toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version))
   1269 
   1270 			if toc != nil {
   1271 				toc.Sect = sect
   1272 				toc.Outer = s
   1273 				toc.Sub = s.Sub
   1274 				s.Sub = toc
   1275 
   1276 				toc.Value = 0x8000
   1277 			}
   1278 
   1279 			growdatsize(&datsize, s)
   1280 		}
   1281 
   1282 		sect.Length = uint64(datsize) - sect.Vaddr
   1283 	}
   1284 
   1285 	/* pointer-free data */
   1286 	sect = addsection(&Segdata, ".noptrdata", 06)
   1287 
   1288 	sect.Align = maxalign(s, obj.SINITARR-1)
   1289 	datsize = Rnd(datsize, int64(sect.Align))
   1290 	sect.Vaddr = uint64(datsize)
   1291 	Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect
   1292 	Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect
   1293 	for ; s != nil && s.Type < obj.SINITARR; s = s.Next {
   1294 		datsize = aligndatsize(datsize, s)
   1295 		s.Sect = sect
   1296 		s.Type = obj.SDATA
   1297 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1298 		growdatsize(&datsize, s)
   1299 	}
   1300 
   1301 	sect.Length = uint64(datsize) - sect.Vaddr
   1302 
   1303 	hasinitarr := Linkshared
   1304 
   1305 	/* shared library initializer */
   1306 	switch Buildmode {
   1307 	case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
   1308 		hasinitarr = true
   1309 	}
   1310 
   1311 	if hasinitarr {
   1312 		sect := addsection(&Segdata, ".init_array", 06)
   1313 		sect.Align = maxalign(s, obj.SINITARR)
   1314 		datsize = Rnd(datsize, int64(sect.Align))
   1315 		sect.Vaddr = uint64(datsize)
   1316 		for ; s != nil && s.Type == obj.SINITARR; s = s.Next {
   1317 			datsize = aligndatsize(datsize, s)
   1318 			s.Sect = sect
   1319 			s.Value = int64(uint64(datsize) - sect.Vaddr)
   1320 			growdatsize(&datsize, s)
   1321 		}
   1322 
   1323 		sect.Length = uint64(datsize) - sect.Vaddr
   1324 	}
   1325 
   1326 	/* data */
   1327 	sect = addsection(&Segdata, ".data", 06)
   1328 	sect.Align = maxalign(s, obj.SBSS-1)
   1329 	datsize = Rnd(datsize, int64(sect.Align))
   1330 	sect.Vaddr = uint64(datsize)
   1331 	Linklookup(Ctxt, "runtime.data", 0).Sect = sect
   1332 	Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
   1333 	var gc GCProg
   1334 	gc.Init("runtime.gcdata")
   1335 	for ; s != nil && s.Type < obj.SBSS; s = s.Next {
   1336 		if s.Type == obj.SINITARR {
   1337 			Ctxt.Cursym = s
   1338 			Diag("unexpected symbol type %d", s.Type)
   1339 		}
   1340 
   1341 		s.Sect = sect
   1342 		s.Type = obj.SDATA
   1343 		datsize = aligndatsize(datsize, s)
   1344 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1345 		gc.AddSym(s)
   1346 		growdatsize(&datsize, s)
   1347 	}
   1348 	sect.Length = uint64(datsize) - sect.Vaddr
   1349 	gc.End(int64(sect.Length))
   1350 
   1351 	/* bss */
   1352 	sect = addsection(&Segdata, ".bss", 06)
   1353 	sect.Align = maxalign(s, obj.SNOPTRBSS-1)
   1354 	datsize = Rnd(datsize, int64(sect.Align))
   1355 	sect.Vaddr = uint64(datsize)
   1356 	Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
   1357 	Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
   1358 	gc = GCProg{}
   1359 	gc.Init("runtime.gcbss")
   1360 	for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next {
   1361 		s.Sect = sect
   1362 		datsize = aligndatsize(datsize, s)
   1363 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1364 		gc.AddSym(s)
   1365 		growdatsize(&datsize, s)
   1366 	}
   1367 	sect.Length = uint64(datsize) - sect.Vaddr
   1368 	gc.End(int64(sect.Length))
   1369 
   1370 	/* pointer-free bss */
   1371 	sect = addsection(&Segdata, ".noptrbss", 06)
   1372 
   1373 	sect.Align = maxalign(s, obj.SNOPTRBSS)
   1374 	datsize = Rnd(datsize, int64(sect.Align))
   1375 	sect.Vaddr = uint64(datsize)
   1376 	Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect
   1377 	Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect
   1378 	for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next {
   1379 		datsize = aligndatsize(datsize, s)
   1380 		s.Sect = sect
   1381 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1382 		growdatsize(&datsize, s)
   1383 	}
   1384 
   1385 	sect.Length = uint64(datsize) - sect.Vaddr
   1386 	Linklookup(Ctxt, "runtime.end", 0).Sect = sect
   1387 
   1388 	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
   1389 	if datsize != int64(uint32(datsize)) {
   1390 		Diag("data or bss segment too large")
   1391 	}
   1392 
   1393 	if Iself && Linkmode == LinkExternal && s != nil && s.Type == obj.STLSBSS && HEADTYPE != obj.Hopenbsd {
   1394 		sect := addsection(&Segdata, ".tbss", 06)
   1395 		sect.Align = int32(Thearch.Ptrsize)
   1396 		sect.Vaddr = 0
   1397 		datsize = 0
   1398 		for ; s != nil && s.Type == obj.STLSBSS; s = s.Next {
   1399 			datsize = aligndatsize(datsize, s)
   1400 			s.Sect = sect
   1401 			s.Value = int64(uint64(datsize) - sect.Vaddr)
   1402 			growdatsize(&datsize, s)
   1403 		}
   1404 
   1405 		sect.Length = uint64(datsize)
   1406 	} else {
   1407 		// Might be internal linking but still using cgo.
   1408 		// In that case, the only possible STLSBSS symbol is runtime.tlsg.
   1409 		// Give it offset 0, because it's the only thing here.
   1410 		if s != nil && s.Type == obj.STLSBSS && s.Name == "runtime.tlsg" {
   1411 			s.Value = 0
   1412 			s = s.Next
   1413 		}
   1414 	}
   1415 
   1416 	if s != nil {
   1417 		Ctxt.Cursym = nil
   1418 		Diag("unexpected symbol type %d for %s", s.Type, s.Name)
   1419 	}
   1420 
   1421 	/*
   1422 	 * We finished data, begin read-only data.
   1423 	 * Not all systems support a separate read-only non-executable data section.
   1424 	 * ELF systems do.
   1425 	 * OS X and Plan 9 do not.
   1426 	 * Windows PE may, but if so we have not implemented it.
   1427 	 * And if we're using external linking mode, the point is moot,
   1428 	 * since it's not our decision; that code expects the sections in
   1429 	 * segtext.
   1430 	 */
   1431 	var segro *Segment
   1432 	if Iself && Linkmode == LinkInternal {
   1433 		segro = &Segrodata
   1434 	} else {
   1435 		segro = &Segtext
   1436 	}
   1437 
   1438 	s = datap
   1439 
   1440 	datsize = 0
   1441 
   1442 	/* read-only executable ELF, Mach-O sections */
   1443 	for ; s != nil && s.Type < obj.STYPE; s = s.Next {
   1444 		sect = addsection(&Segtext, s.Name, 04)
   1445 		sect.Align = symalign(s)
   1446 		datsize = Rnd(datsize, int64(sect.Align))
   1447 		sect.Vaddr = uint64(datsize)
   1448 		s.Sect = sect
   1449 		s.Type = obj.SRODATA
   1450 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1451 		growdatsize(&datsize, s)
   1452 		sect.Length = uint64(datsize) - sect.Vaddr
   1453 	}
   1454 
   1455 	/* read-only data */
   1456 	sect = addsection(segro, ".rodata", 04)
   1457 
   1458 	sect.Align = maxalign(s, obj.STYPELINK-1)
   1459 	datsize = Rnd(datsize, int64(sect.Align))
   1460 	sect.Vaddr = 0
   1461 	Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
   1462 	Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
   1463 	for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
   1464 		datsize = aligndatsize(datsize, s)
   1465 		s.Sect = sect
   1466 		s.Type = obj.SRODATA
   1467 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1468 		growdatsize(&datsize, s)
   1469 	}
   1470 
   1471 	sect.Length = uint64(datsize) - sect.Vaddr
   1472 
   1473 	/* typelink */
   1474 	sect = addsection(segro, ".typelink", 04)
   1475 
   1476 	sect.Align = maxalign(s, obj.STYPELINK)
   1477 	datsize = Rnd(datsize, int64(sect.Align))
   1478 	sect.Vaddr = uint64(datsize)
   1479 	Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect
   1480 	Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect
   1481 	for ; s != nil && s.Type == obj.STYPELINK; s = s.Next {
   1482 		datsize = aligndatsize(datsize, s)
   1483 		s.Sect = sect
   1484 		s.Type = obj.SRODATA
   1485 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1486 		growdatsize(&datsize, s)
   1487 	}
   1488 
   1489 	sect.Length = uint64(datsize) - sect.Vaddr
   1490 
   1491 	/* gosymtab */
   1492 	sect = addsection(segro, ".gosymtab", 04)
   1493 
   1494 	sect.Align = maxalign(s, obj.SPCLNTAB-1)
   1495 	datsize = Rnd(datsize, int64(sect.Align))
   1496 	sect.Vaddr = uint64(datsize)
   1497 	Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect
   1498 	Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect
   1499 	for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next {
   1500 		datsize = aligndatsize(datsize, s)
   1501 		s.Sect = sect
   1502 		s.Type = obj.SRODATA
   1503 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1504 		growdatsize(&datsize, s)
   1505 	}
   1506 
   1507 	sect.Length = uint64(datsize) - sect.Vaddr
   1508 
   1509 	/* gopclntab */
   1510 	sect = addsection(segro, ".gopclntab", 04)
   1511 
   1512 	sect.Align = maxalign(s, obj.SELFROSECT-1)
   1513 	datsize = Rnd(datsize, int64(sect.Align))
   1514 	sect.Vaddr = uint64(datsize)
   1515 	Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect
   1516 	Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect
   1517 	for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next {
   1518 		datsize = aligndatsize(datsize, s)
   1519 		s.Sect = sect
   1520 		s.Type = obj.SRODATA
   1521 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1522 		growdatsize(&datsize, s)
   1523 	}
   1524 
   1525 	sect.Length = uint64(datsize) - sect.Vaddr
   1526 
   1527 	/* read-only ELF, Mach-O sections */
   1528 	for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
   1529 		sect = addsection(segro, s.Name, 04)
   1530 		sect.Align = symalign(s)
   1531 		datsize = Rnd(datsize, int64(sect.Align))
   1532 		sect.Vaddr = uint64(datsize)
   1533 		s.Sect = sect
   1534 		s.Type = obj.SRODATA
   1535 		s.Value = int64(uint64(datsize) - sect.Vaddr)
   1536 		growdatsize(&datsize, s)
   1537 		sect.Length = uint64(datsize) - sect.Vaddr
   1538 	}
   1539 
   1540 	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
   1541 	if datsize != int64(uint32(datsize)) {
   1542 		Diag("read-only data segment too large")
   1543 	}
   1544 
   1545 	/* number the sections */
   1546 	n := int32(1)
   1547 
   1548 	for sect := Segtext.Sect; sect != nil; sect = sect.Next {
   1549 		sect.Extnum = int16(n)
   1550 		n++
   1551 	}
   1552 	for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
   1553 		sect.Extnum = int16(n)
   1554 		n++
   1555 	}
   1556 	for sect := Segdata.Sect; sect != nil; sect = sect.Next {
   1557 		sect.Extnum = int16(n)
   1558 		n++
   1559 	}
   1560 }
   1561 
   1562 // Add buildid to beginning of text segment, on non-ELF systems.
   1563 // Non-ELF binary formats are not always flexible enough to
   1564 // give us a place to put the Go build ID. On those systems, we put it
   1565 // at the very beginning of the text segment.
   1566 // This ``header'' is read by cmd/go.
   1567 func textbuildid() {
   1568 	if Iself || buildid == "" {
   1569 		return
   1570 	}
   1571 
   1572 	sym := Linklookup(Ctxt, "go.buildid", 0)
   1573 	sym.Reachable = true
   1574 	// The \xff is invalid UTF-8, meant to make it less likely
   1575 	// to find one of these accidentally.
   1576 	data := "\xff Go build ID: " + strconv.Quote(buildid) + "\n \xff"
   1577 	sym.Type = obj.STEXT
   1578 	sym.P = []byte(data)
   1579 	sym.Size = int64(len(sym.P))
   1580 
   1581 	sym.Next = Ctxt.Textp
   1582 	Ctxt.Textp = sym
   1583 }
   1584 
   1585 // assign addresses to text
   1586 func textaddress() {
   1587 	var sub *LSym
   1588 
   1589 	addsection(&Segtext, ".text", 05)
   1590 
   1591 	// Assign PCs in text segment.
   1592 	// Could parallelize, by assigning to text
   1593 	// and then letting threads copy down, but probably not worth it.
   1594 	sect := Segtext.Sect
   1595 
   1596 	sect.Align = int32(Funcalign)
   1597 	Linklookup(Ctxt, "runtime.text", 0).Sect = sect
   1598 	Linklookup(Ctxt, "runtime.etext", 0).Sect = sect
   1599 	va := uint64(INITTEXT)
   1600 	sect.Vaddr = va
   1601 	for sym := Ctxt.Textp; sym != nil; sym = sym.Next {
   1602 		sym.Sect = sect
   1603 		if sym.Type&obj.SSUB != 0 {
   1604 			continue
   1605 		}
   1606 		if sym.Align != 0 {
   1607 			va = uint64(Rnd(int64(va), int64(sym.Align)))
   1608 		} else {
   1609 			va = uint64(Rnd(int64(va), int64(Funcalign)))
   1610 		}
   1611 		sym.Value = 0
   1612 		for sub = sym; sub != nil; sub = sub.Sub {
   1613 			sub.Value += int64(va)
   1614 		}
   1615 		if sym.Size == 0 && sym.Sub != nil {
   1616 			Ctxt.Cursym = sym
   1617 		}
   1618 		if sym.Size < MINFUNC {
   1619 			va += MINFUNC // spacing required for findfunctab
   1620 		} else {
   1621 			va += uint64(sym.Size)
   1622 		}
   1623 	}
   1624 
   1625 	sect.Length = va - sect.Vaddr
   1626 }
   1627 
   1628 // assign addresses
   1629 func address() {
   1630 	va := uint64(INITTEXT)
   1631 	Segtext.Rwx = 05
   1632 	Segtext.Vaddr = va
   1633 	Segtext.Fileoff = uint64(HEADR)
   1634 	for s := Segtext.Sect; s != nil; s = s.Next {
   1635 		va = uint64(Rnd(int64(va), int64(s.Align)))
   1636 		s.Vaddr = va
   1637 		va += s.Length
   1638 	}
   1639 
   1640 	Segtext.Length = va - uint64(INITTEXT)
   1641 	Segtext.Filelen = Segtext.Length
   1642 	if HEADTYPE == obj.Hnacl {
   1643 		va += 32 // room for the "halt sled"
   1644 	}
   1645 
   1646 	if Segrodata.Sect != nil {
   1647 		// align to page boundary so as not to mix
   1648 		// rodata and executable text.
   1649 		va = uint64(Rnd(int64(va), int64(INITRND)))
   1650 
   1651 		Segrodata.Rwx = 04
   1652 		Segrodata.Vaddr = va
   1653 		Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
   1654 		Segrodata.Filelen = 0
   1655 		for s := Segrodata.Sect; s != nil; s = s.Next {
   1656 			va = uint64(Rnd(int64(va), int64(s.Align)))
   1657 			s.Vaddr = va
   1658 			va += s.Length
   1659 		}
   1660 
   1661 		Segrodata.Length = va - Segrodata.Vaddr
   1662 		Segrodata.Filelen = Segrodata.Length
   1663 	}
   1664 
   1665 	va = uint64(Rnd(int64(va), int64(INITRND)))
   1666 	Segdata.Rwx = 06
   1667 	Segdata.Vaddr = va
   1668 	Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
   1669 	Segdata.Filelen = 0
   1670 	if HEADTYPE == obj.Hwindows {
   1671 		Segdata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
   1672 	}
   1673 	if HEADTYPE == obj.Hplan9 {
   1674 		Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen
   1675 	}
   1676 	var data *Section
   1677 	var noptr *Section
   1678 	var bss *Section
   1679 	var noptrbss *Section
   1680 	var vlen int64
   1681 	for s := Segdata.Sect; s != nil; s = s.Next {
   1682 		vlen = int64(s.Length)
   1683 		if s.Next != nil {
   1684 			vlen = int64(s.Next.Vaddr - s.Vaddr)
   1685 		}
   1686 		s.Vaddr = va
   1687 		va += uint64(vlen)
   1688 		Segdata.Length = va - Segdata.Vaddr
   1689 		if s.Name == ".data" {
   1690 			data = s
   1691 		}
   1692 		if s.Name == ".noptrdata" {
   1693 			noptr = s
   1694 		}
   1695 		if s.Name == ".bss" {
   1696 			bss = s
   1697 		}
   1698 		if s.Name == ".noptrbss" {
   1699 			noptrbss = s
   1700 		}
   1701 	}
   1702 
   1703 	Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
   1704 
   1705 	text := Segtext.Sect
   1706 	var rodata *Section
   1707 	if Segrodata.Sect != nil {
   1708 		rodata = Segrodata.Sect
   1709 	} else {
   1710 		rodata = text.Next
   1711 	}
   1712 	typelink := rodata.Next
   1713 	symtab := typelink.Next
   1714 	pclntab := symtab.Next
   1715 
   1716 	var sub *LSym
   1717 	for sym := datap; sym != nil; sym = sym.Next {
   1718 		Ctxt.Cursym = sym
   1719 		if sym.Sect != nil {
   1720 			sym.Value += int64(sym.Sect.Vaddr)
   1721 		}
   1722 		for sub = sym.Sub; sub != nil; sub = sub.Sub {
   1723 			sub.Value += sym.Value
   1724 		}
   1725 	}
   1726 
   1727 	if Buildmode == BuildmodeShared {
   1728 		s := Linklookup(Ctxt, "go.link.abihashbytes", 0)
   1729 		sectSym := Linklookup(Ctxt, ".note.go.abihash", 0)
   1730 		s.Sect = sectSym.Sect
   1731 		s.Value = int64(sectSym.Sect.Vaddr + 16)
   1732 	}
   1733 
   1734 	xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
   1735 	xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
   1736 	xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr))
   1737 	xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length))
   1738 	xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr))
   1739 	xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length))
   1740 
   1741 	sym := Linklookup(Ctxt, "runtime.gcdata", 0)
   1742 	sym.Local = true
   1743 	xdefine("runtime.egcdata", obj.SRODATA, Symaddr(sym)+sym.Size)
   1744 	Linklookup(Ctxt, "runtime.egcdata", 0).Sect = sym.Sect
   1745 
   1746 	sym = Linklookup(Ctxt, "runtime.gcbss", 0)
   1747 	sym.Local = true
   1748 	xdefine("runtime.egcbss", obj.SRODATA, Symaddr(sym)+sym.Size)
   1749 	Linklookup(Ctxt, "runtime.egcbss", 0).Sect = sym.Sect
   1750 
   1751 	xdefine("runtime.symtab", obj.SRODATA, int64(symtab.Vaddr))
   1752 	xdefine("runtime.esymtab", obj.SRODATA, int64(symtab.Vaddr+symtab.Length))
   1753 	xdefine("runtime.pclntab", obj.SRODATA, int64(pclntab.Vaddr))
   1754 	xdefine("runtime.epclntab", obj.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
   1755 	xdefine("runtime.noptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr))
   1756 	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
   1757 	xdefine("runtime.bss", obj.SBSS, int64(bss.Vaddr))
   1758 	xdefine("runtime.ebss", obj.SBSS, int64(bss.Vaddr+bss.Length))
   1759 	xdefine("runtime.data", obj.SDATA, int64(data.Vaddr))
   1760 	xdefine("runtime.edata", obj.SDATA, int64(data.Vaddr+data.Length))
   1761 	xdefine("runtime.noptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr))
   1762 	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
   1763 	xdefine("runtime.end", obj.SBSS, int64(Segdata.Vaddr+Segdata.Length))
   1764 }
   1765