data.go 42.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
//
//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package ld

import (
35
	"cmd/internal/gcprog"
36 37 38
	"cmd/internal/obj"
	"fmt"
	"log"
39
	"os"
40
	"strconv"
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
	"strings"
)

func Symgrow(ctxt *Link, s *LSym, siz int64) {
	if int64(int(siz)) != siz {
		log.Fatalf("symgrow size %d too long", siz)
	}
	if int64(len(s.P)) >= siz {
		return
	}
	for cap(s.P) < int(siz) {
		s.P = append(s.P[:len(s.P)], 0)
	}
	s.P = s.P[:siz]
}

func Addrel(s *LSym) *Reloc {
	s.R = append(s.R, Reloc{})
	return &s.R[len(s.R)-1]
}

func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
	if s.Type == 0 {
64
		s.Type = obj.SDATA
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
	}
	s.Reachable = true
	if s.Size < off+wid {
		s.Size = off + wid
		Symgrow(ctxt, s, s.Size)
	}

	switch wid {
	case 1:
		s.P[off] = uint8(v)
	case 2:
		ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
	case 4:
		ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
	case 8:
		ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v))
	}

	return off + wid
}

func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
Russ Cox's avatar
Russ Cox committed
87
	off := s.Size
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	setuintxx(ctxt, s, off, v, int64(wid))
	return off
}

func Adduint8(ctxt *Link, s *LSym, v uint8) int64 {
	return adduintxx(ctxt, s, uint64(v), 1)
}

func Adduint16(ctxt *Link, s *LSym, v uint16) int64 {
	return adduintxx(ctxt, s, uint64(v), 2)
}

func Adduint32(ctxt *Link, s *LSym, v uint32) int64 {
	return adduintxx(ctxt, s, uint64(v), 4)
}

func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
	return adduintxx(ctxt, s, v, 8)
}

108 109 110 111
func adduint(ctxt *Link, s *LSym, v uint64) int64 {
	return adduintxx(ctxt, s, v, Thearch.Intsize)
}

112 113 114 115 116 117 118 119 120 121
func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
	return setuintxx(ctxt, s, r, uint64(v), 1)
}

func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 {
	return setuintxx(ctxt, s, r, uint64(v), 4)
}

func Addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
	if s.Type == 0 {
122
		s.Type = obj.SDATA
123 124
	}
	s.Reachable = true
Russ Cox's avatar
Russ Cox committed
125
	i := s.Size
126 127
	s.Size += int64(ctxt.Arch.Ptrsize)
	Symgrow(ctxt, s, s.Size)
Russ Cox's avatar
Russ Cox committed
128
	r := Addrel(s)
129 130 131
	r.Sym = t
	r.Off = int32(i)
	r.Siz = uint8(ctxt.Arch.Ptrsize)
132
	r.Type = obj.R_ADDR
133 134 135 136 137 138
	r.Add = add
	return i + int64(r.Siz)
}

func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
	if s.Type == 0 {
139
		s.Type = obj.SDATA
140 141
	}
	s.Reachable = true
Russ Cox's avatar
Russ Cox committed
142
	i := s.Size
143 144
	s.Size += 4
	Symgrow(ctxt, s, s.Size)
Russ Cox's avatar
Russ Cox committed
145
	r := Addrel(s)
146 147 148
	r.Sym = t
	r.Off = int32(i)
	r.Add = add
149
	r.Type = obj.R_PCREL
150 151 152 153 154 155 156 157 158 159
	r.Siz = 4
	return i + int64(r.Siz)
}

func Addaddr(ctxt *Link, s *LSym, t *LSym) int64 {
	return Addaddrplus(ctxt, s, t, 0)
}

func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
	if s.Type == 0 {
160
		s.Type = obj.SDATA
161 162 163 164 165 166 167
	}
	s.Reachable = true
	if off+int64(ctxt.Arch.Ptrsize) > s.Size {
		s.Size = off + int64(ctxt.Arch.Ptrsize)
		Symgrow(ctxt, s, s.Size)
	}

Russ Cox's avatar
Russ Cox committed
168
	r := Addrel(s)
169 170 171
	r.Sym = t
	r.Off = int32(off)
	r.Siz = uint8(ctxt.Arch.Ptrsize)
172
	r.Type = obj.R_ADDR
173 174 175 176 177 178 179 180 181 182
	r.Add = add
	return off + int64(r.Siz)
}

func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 {
	return setaddrplus(ctxt, s, off, t, 0)
}

func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
	if s.Type == 0 {
183
		s.Type = obj.SDATA
184 185
	}
	s.Reachable = true
Russ Cox's avatar
Russ Cox committed
186
	i := s.Size
187 188
	s.Size += int64(ctxt.Arch.Ptrsize)
	Symgrow(ctxt, s, s.Size)
Russ Cox's avatar
Russ Cox committed
189
	r := Addrel(s)
190 191 192
	r.Sym = t
	r.Off = int32(i)
	r.Siz = uint8(ctxt.Arch.Ptrsize)
193
	r.Type = obj.R_SIZE
194 195 196 197 198
	return i + int64(r.Siz)
}

func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
	if s.Type == 0 {
199
		s.Type = obj.SDATA
200 201
	}
	s.Reachable = true
Russ Cox's avatar
Russ Cox committed
202
	i := s.Size
203 204
	s.Size += 4
	Symgrow(ctxt, s, s.Size)
Russ Cox's avatar
Russ Cox committed
205
	r := Addrel(s)
206 207 208
	r.Sym = t
	r.Off = int32(i)
	r.Siz = 4
209
	r.Type = obj.R_ADDR
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	r.Add = add
	return i + int64(r.Siz)
}

/*
 * divide-and-conquer list-link
 * sort of LSym* structures.
 * Used for the data block.
 */
func datcmp(s1 *LSym, s2 *LSym) int {
	if s1.Type != s2.Type {
		return int(s1.Type) - int(s2.Type)
	}

	// For ppc64, we want to interleave the .got and .toc sections
	// from input files.  Both are type SELFGOT, so in that case
	// fall through to the name comparison (conveniently, .got
	// sorts before .toc).
228
	if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
		if s1.Size < s2.Size {
			return -1
		}
		return +1
	}

	return stringsCompare(s1.Name, s2.Name)
}

func listnextp(s *LSym) **LSym {
	return &s.Next
}

func listsubp(s *LSym) **LSym {
	return &s.Sub
}

func listsort(l *LSym, cmp func(*LSym, *LSym) int, nextp func(*LSym) **LSym) *LSym {
	if l == nil || *nextp(l) == nil {
		return l
	}

Russ Cox's avatar
Russ Cox committed
251 252
	l1 := l
	l2 := l
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	for {
		l2 = *nextp(l2)
		if l2 == nil {
			break
		}
		l2 = *nextp(l2)
		if l2 == nil {
			break
		}
		l1 = *nextp(l1)
	}

	l2 = *nextp(l1)
	*nextp(l1) = nil
	l1 = listsort(l, cmp, nextp)
	l2 = listsort(l2, cmp, nextp)

	/* set up lead element */
	if cmp(l1, l2) < 0 {
		l = l1
		l1 = *nextp(l1)
	} else {
		l = l2
		l2 = *nextp(l2)
	}

Russ Cox's avatar
Russ Cox committed
279
	le := l
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327

	for {
		if l1 == nil {
			for l2 != nil {
				*nextp(le) = l2
				le = l2
				l2 = *nextp(l2)
			}

			*nextp(le) = nil
			break
		}

		if l2 == nil {
			for l1 != nil {
				*nextp(le) = l1
				le = l1
				l1 = *nextp(l1)
			}

			break
		}

		if cmp(l1, l2) < 0 {
			*nextp(le) = l1
			le = l1
			l1 = *nextp(l1)
		} else {
			*nextp(le) = l2
			le = l2
			l2 = *nextp(l2)
		}
	}

	*nextp(le) = nil
	return l
}

func relocsym(s *LSym) {
	var r *Reloc
	var rs *LSym
	var i16 int16
	var off int32
	var siz int32
	var fl int32
	var o int64

	Ctxt.Cursym = s
Russ Cox's avatar
Russ Cox committed
328
	for ri := int32(0); ri < int32(len(s.R)); ri++ {
329 330 331 332 333 334 335 336 337
		r = &s.R[ri]
		r.Done = 1
		off = r.Off
		siz = int32(r.Siz)
		if off < 0 || off+siz > int32(len(s.P)) {
			Diag("%s: invalid relocation %d+%d not in [%d,%d)", s.Name, off, siz, 0, len(s.P))
			continue
		}

338
		if r.Sym != nil && (r.Sym.Type&(obj.SMASK|obj.SHIDDEN) == 0 || r.Sym.Type&obj.SMASK == obj.SXREF) {
339 340 341
			// When putting the runtime but not main into a shared library
			// these symbols are undefined and that's OK.
			if Buildmode == BuildmodeShared && (r.Sym.Name == "main.main" || r.Sym.Name == "main.init") {
342
				r.Sym.Type = obj.SDYNIMPORT
343 344 345 346
			} else {
				Diag("%s: not defined", r.Sym.Name)
				continue
			}
347 348 349 350 351 352 353 354 355
		}

		if r.Type >= 256 {
			continue
		}
		if r.Siz == 0 { // informational relocation - no work to do
			continue
		}

356 357
		// We need to be able to reference dynimport symbols when linking against
		// shared libraries, and Solaris needs it always
358
		if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() {
359 360
			Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
		}
361
		if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Reachable {
362 363 364 365
			Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name)
		}

		// Android emulates runtime.tlsg as a regular variable.
366 367
		if r.Type == obj.R_TLS && goos == "android" {
			r.Type = obj.R_ADDR
368 369 370 371 372 373 374 375 376
		}

		switch r.Type {
		default:
			o = 0
			if Thearch.Archreloc(r, s, &o) < 0 {
				Diag("unknown reloc %d", r.Type)
			}

377
		case obj.R_TLS:
378 379 380 381 382 383 384 385
			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
				r.Done = 0
				r.Sym = Ctxt.Tlsg
				r.Xsym = Ctxt.Tlsg
				r.Xadd = r.Add
				o = r.Add
				break
			}
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
			if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' {
				// On ELF ARM, the thread pointer is 8 bytes before
				// the start of the thread-local data block, so add 8
				// to the actual TLS offset (r->sym->value).
				// This 8 seems to be a fundamental constant of
				// ELF on ARM (or maybe Glibc on ARM); it is not
				// related to the fact that our own TLS storage happens
				// to take up 8 bytes.
				o = 8 + r.Sym.Value

				break
			}

			r.Done = 0
			o = 0
			if Thearch.Thechar != '6' {
				o = r.Add
			}

405 406
		case obj.R_TLS_LE:
			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
407 408 409 410 411 412 413 414 415 416 417
				r.Done = 0
				r.Sym = Ctxt.Tlsg
				r.Xsym = Ctxt.Tlsg
				r.Xadd = r.Add
				o = 0
				if Thearch.Thechar != '6' {
					o = r.Add
				}
				break
			}

418
			if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
419 420 421 422 423 424
				o = int64(Ctxt.Tlsoffset) + r.Add
			} else if Ctxt.Headtype == obj.Hwindows {
				o = r.Add
			} else {
				log.Fatalf("unexpected R_TLS_LE relocation for %s", Headstr(Ctxt.Headtype))
			}
425

426 427
		case obj.R_TLS_IE:
			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
428 429 430 431 432 433 434 435 436 437
				r.Done = 0
				r.Sym = Ctxt.Tlsg
				r.Xsym = Ctxt.Tlsg
				r.Xadd = r.Add
				o = 0
				if Thearch.Thechar != '6' {
					o = r.Add
				}
				break
			}
438
			log.Fatalf("cannot handle R_TLS_IE when linking internally")
439

440 441
		case obj.R_ADDR:
			if Linkmode == LinkExternal && r.Sym.Type != obj.SCONST {
442 443 444 445 446 447 448 449 450 451 452
				r.Done = 0

				// set up addend for eventual relocation via outer symbol.
				rs = r.Sym

				r.Xadd = r.Add
				for rs.Outer != nil {
					r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
					rs = rs.Outer
				}

453
				if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
454 455 456 457 458 459 460 461 462
					Diag("missing section for %s", rs.Name)
				}
				r.Xsym = rs

				o = r.Xadd
				if Iself {
					if Thearch.Thechar == '6' {
						o = 0
					}
463
				} else if HEADTYPE == obj.Hdarwin {
464 465 466 467 468
					// ld64 for arm64 has a bug where if the address pointed to by o exists in the
					// symbol table (dynid >= 0), or is inside a symbol that exists in the symbol
					// table, then it will add o twice into the relocated value.
					// The workaround is that on arm64 don't ever add symaddr to o and always use
					// extern relocation by requiring rs->dynid >= 0.
469
					if rs.Type != obj.SHOSTOBJ {
470 471 472 473 474 475
						if Thearch.Thechar == '7' && rs.Dynid < 0 {
							Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o)
						}
						if Thearch.Thechar != '7' {
							o += Symaddr(rs)
						}
476
					}
477
				} else if HEADTYPE == obj.Hwindows {
478
					// nothing to do
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
				} else {
					Diag("unhandled pcrel relocation for %s", headstring)
				}

				break
			}

			o = Symaddr(r.Sym) + r.Add

			// On amd64, 4-byte offsets will be sign-extended, so it is impossible to
			// access more than 2GB of static data; fail at link time is better than
			// fail at runtime. See http://golang.org/issue/7980.
			// Instead of special casing only amd64, we treat this as an error on all
			// 64-bit architectures so as to be future-proof.
			if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 {
Russ Cox's avatar
Russ Cox committed
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 500
		case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL:
			if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) {
501 502 503 504 505 506 507 508 509 510 511 512
				r.Done = 0

				// set up addend for eventual relocation via outer symbol.
				rs = r.Sym

				r.Xadd = r.Add
				for rs.Outer != nil {
					r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
					rs = rs.Outer
				}

				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 515 516 517 518 519 520 521 522
					Diag("missing section for %s", rs.Name)
				}
				r.Xsym = rs

				o = r.Xadd
				if Iself {
					if Thearch.Thechar == '6' {
						o = 0
					}
523 524 525
				} else if HEADTYPE == obj.Hdarwin {
					if r.Type == obj.R_CALL {
						if rs.Type != obj.SHOSTOBJ {
526
							o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
527 528 529 530 531
						}
						o -= int64(r.Off) // relative to section offset, not symbol
					} else {
						o += int64(r.Siz)
					}
532
				} else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL
533 534 535 536 537
					// PE/COFF's PC32 relocation uses the address after the relocated
					// bytes as the base. Compensate by skewing the addend.
					o += int64(r.Siz)
					// GNU ld always add VirtualAddress of the .text section to the
					// relocated address, compensate that.
538
					o -= int64(s.Sect.Vaddr - PEBASE)
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
				} else {
					Diag("unhandled pcrel relocation for %s", headstring)
				}

				break
			}

			o = 0
			if r.Sym != nil {
				o += Symaddr(r.Sym)
			}

			// NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c
			// compiler. The expression s->value + r->off + r->siz is int32 + int32 +
			// uchar, and Plan 9 8c incorrectly treats the expression as type uint32
			// instead of int32, causing incorrect values when sign extended for adding
			// to o. The bug only occurs on Plan 9, because this C program is compiled by
			// the standard host compiler (gcc on most other systems).
			o += r.Add - (s.Value + int64(r.Off) + int64(int32(r.Siz)))

559
		case obj.R_SIZE:
560 561 562 563 564 565 566
			o = r.Sym.Size + r.Add
		}

		if r.Variant != RV_NONE {
			o = Thearch.Archrelocvariant(r, s, o)
		}

Russ Cox's avatar
Russ Cox committed
567 568 569 570 571 572 573
		if false {
			nam := "<nil>"
			if r.Sym != nil {
				nam = r.Sym.Name
			}
			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)
		}
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
		switch siz {
		default:
			Ctxt.Cursym = s
			Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
			fallthrough

			// TODO(rsc): Remove.
		case 1:
			s.P[off] = byte(int8(o))

		case 2:
			if o != int64(int16(o)) {
				Diag("relocation address is too big: %#x", o)
			}
			i16 = int16(o)
			Ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))

		case 4:
592
			if r.Type == obj.R_PCREL || r.Type == obj.R_CALL {
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
				if o != int64(int32(o)) {
					Diag("pc-relative relocation address is too big: %#x", o)
				}
			} else {
				if o != int64(int32(o)) && o != int64(uint32(o)) {
					Diag("non-pc-relative relocation address is too big: %#x", uint64(o))
				}
			}

			fl = int32(o)
			Ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))

		case 8:
			Ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
		}
	}
}

func reloc() {
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
	}
615
	Bso.Flush()
616

Russ Cox's avatar
Russ Cox committed
617
	for s := Ctxt.Textp; s != nil; s = s.Next {
618 619
		relocsym(s)
	}
Russ Cox's avatar
Russ Cox committed
620
	for s := datap; s != nil; s = s.Next {
621 622 623 624 625
		relocsym(s)
	}
}

func dynrelocsym(s *LSym) {
626
	if HEADTYPE == obj.Hwindows && Linkmode != LinkExternal {
Russ Cox's avatar
Russ Cox committed
627
		rel := Linklookup(Ctxt, ".rel", 0)
628 629 630
		if s == rel {
			return
		}
Russ Cox's avatar
Russ Cox committed
631 632 633
		var r *Reloc
		var targ *LSym
		for ri := 0; ri < len(s.R); ri++ {
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
			r = &s.R[ri]
			targ = r.Sym
			if targ == nil {
				continue
			}
			if !targ.Reachable {
				Diag("internal inconsistency: dynamic symbol %s is not reachable.", targ.Name)
			}
			if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files.
				targ.Plt = int32(rel.Size)
				r.Sym = rel
				r.Add = int64(targ.Plt)

				// jmp *addr
				if Thearch.Thechar == '8' {
					Adduint8(Ctxt, rel, 0xff)
					Adduint8(Ctxt, rel, 0x25)
					Addaddr(Ctxt, rel, targ)
					Adduint8(Ctxt, rel, 0x90)
					Adduint8(Ctxt, rel, 0x90)
				} else {
					Adduint8(Ctxt, rel, 0xff)
					Adduint8(Ctxt, rel, 0x24)
					Adduint8(Ctxt, rel, 0x25)
					addaddrplus4(Ctxt, rel, targ, 0)
					Adduint8(Ctxt, rel, 0x90)
				}
			} else if r.Sym.Plt >= 0 {
				r.Sym = rel
				r.Add = int64(targ.Plt)
			}
		}

		return
	}

Russ Cox's avatar
Russ Cox committed
670 671
	var r *Reloc
	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 675 676 677 678 679 680 681 682 683 684
			if r.Sym != nil && !r.Sym.Reachable {
				Diag("internal inconsistency: dynamic symbol %s is not reachable.", r.Sym.Name)
			}
			Thearch.Adddynrel(s, r)
		}
	}
}

func dynreloc() {
	// -d suppresses dynamic loader format, so we may as well not
	// compute these sections or mark their symbols as reachable.
685
	if Debug['d'] != 0 && HEADTYPE != obj.Hwindows {
686 687 688 689 690
		return
	}
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
	}
691
	Bso.Flush()
692

Russ Cox's avatar
Russ Cox committed
693
	for s := Ctxt.Textp; s != nil; s = s.Next {
694 695
		dynrelocsym(s)
	}
Russ Cox's avatar
Russ Cox committed
696
	for s := datap; s != nil; s = s.Next {
697 698 699 700 701 702 703 704 705 706 707
		dynrelocsym(s)
	}
	if Iself {
		elfdynhash()
	}
}

func blk(start *LSym, addr int64, size int64) {
	var sym *LSym

	for sym = start; sym != nil; sym = sym.Next {
708
		if sym.Type&obj.SSUB == 0 && sym.Value >= addr {
709 710 711 712
			break
		}
	}

Russ Cox's avatar
Russ Cox committed
713 714 715
	eaddr := addr + size
	var ep []byte
	var p []byte
716
	for ; sym != nil; sym = sym.Next {
717
		if sym.Type&obj.SSUB != 0 {
718 719 720 721 722 723 724 725
			continue
		}
		if sym.Value >= eaddr {
			break
		}
		Ctxt.Cursym = sym
		if sym.Value < addr {
			Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type)
726
			errorexit()
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
		}

		for ; addr < sym.Value; addr++ {
			Cput(0)
		}
		p = sym.P
		ep = p[len(sym.P):]
		for -cap(p) < -cap(ep) {
			Cput(uint8(p[0]))
			p = p[1:]
		}
		addr += int64(len(sym.P))
		for ; addr < sym.Value+sym.Size; addr++ {
			Cput(0)
		}
		if addr != sym.Value+sym.Size {
			Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size)
744
			errorexit()
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
		}

		if sym.Value+sym.Size >= eaddr {
			break
		}
	}

	for ; addr < eaddr; addr++ {
		Cput(0)
	}
	Cflush()
}

func Codeblk(addr int64, size int64) {
	if Debug['a'] != 0 {
		fmt.Fprintf(&Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
	}

	blk(Ctxt.Textp, addr, size)

	/* again for printing */
	if Debug['a'] == 0 {
		return
	}

Russ Cox's avatar
Russ Cox committed
770
	var sym *LSym
771 772 773 774 775 776 777 778 779
	for sym = Ctxt.Textp; sym != nil; sym = sym.Next {
		if !sym.Reachable {
			continue
		}
		if sym.Value >= addr {
			break
		}
	}

Russ Cox's avatar
Russ Cox committed
780 781 782
	eaddr := addr + size
	var n int64
	var q []byte
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
	for ; sym != nil; sym = sym.Next {
		if !sym.Reachable {
			continue
		}
		if sym.Value >= eaddr {
			break
		}

		if addr < sym.Value {
			fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
			for ; addr < sym.Value; addr++ {
				fmt.Fprintf(&Bso, " %.2x", 0)
			}
			fmt.Fprintf(&Bso, "\n")
		}

		fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name)
		n = sym.Size
		q = sym.P

		for n >= 16 {
804
			fmt.Fprintf(&Bso, "%.6x\t%-20.16I\n", uint64(addr), q)
805 806 807 808 809 810
			addr += 16
			q = q[16:]
			n -= 16
		}

		if n > 0 {
811
			fmt.Fprintf(&Bso, "%.6x\t%-20.*I\n", uint64(addr), int(n), q)
812 813 814 815 816 817 818 819 820 821 822
		}
		addr += n
	}

	if addr < eaddr {
		fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
		for ; addr < eaddr; addr++ {
			fmt.Fprintf(&Bso, " %.2x", 0)
		}
	}

823
	Bso.Flush()
824 825 826 827 828 829 830 831 832 833 834 835 836 837
}

func Datblk(addr int64, size int64) {
	if Debug['a'] != 0 {
		fmt.Fprintf(&Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
	}

	blk(datap, addr, size)

	/* again for printing */
	if Debug['a'] == 0 {
		return
	}

Russ Cox's avatar
Russ Cox committed
838
	var sym *LSym
839 840 841 842 843 844
	for sym = datap; sym != nil; sym = sym.Next {
		if sym.Value >= addr {
			break
		}
	}

Russ Cox's avatar
Russ Cox committed
845 846 847 848 849 850 851
	eaddr := addr + size
	var ep []byte
	var i int64
	var p []byte
	var r *Reloc
	var rsname string
	var typ string
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
	for ; sym != nil; sym = sym.Next {
		if sym.Value >= eaddr {
			break
		}
		if addr < sym.Value {
			fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint64(addr))
			addr = sym.Value
		}

		fmt.Fprintf(&Bso, "%s\n\t%.8x|", sym.Name, uint(addr))
		p = sym.P
		ep = p[len(sym.P):]
		for -cap(p) < -cap(ep) {
			if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 {
				fmt.Fprintf(&Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P))))
			}
			fmt.Fprintf(&Bso, " %.2x", p[0])
			p = p[1:]
		}

		addr += int64(len(sym.P))
		for ; addr < sym.Value+sym.Size; addr++ {
			fmt.Fprintf(&Bso, " %.2x", 0)
		}
		fmt.Fprintf(&Bso, "\n")

		if Linkmode == LinkExternal {
			for i = 0; i < int64(len(sym.R)); i++ {
				r = &sym.R[i]
				rsname = ""
				if r.Sym != nil {
					rsname = r.Sym.Name
				}
				typ = "?"
				switch r.Type {
887
				case obj.R_ADDR:
888 889
					typ = "addr"

890
				case obj.R_PCREL:
891 892
					typ = "pcrel"

893
				case obj.R_CALL:
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
					typ = "call"
				}

				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))
			}
		}
	}

	if addr < eaddr {
		fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint(addr))
	}
	fmt.Fprintf(&Bso, "\t%.8x|\n", uint(eaddr))
}

func strnput(s string, n int) {
	for ; n > 0 && s != ""; s = s[1:] {
		Cput(uint8(s[0]))
		n--
	}

	for n > 0 {
		Cput(0)
		n--
	}
}

920 921
var strdata []*LSym

922
func addstrdata1(arg string) {
923 924 925
	i := strings.Index(arg, "=")
	if i < 0 {
		Exitf("-X flag requires argument of the form importpath.name=value")
926
	}
927
	addstrdata(arg[:i], arg[i+1:])
928 929 930
}

func addstrdata(name string, value string) {
Russ Cox's avatar
Russ Cox committed
931 932
	p := fmt.Sprintf("%s.str", name)
	sp := Linklookup(Ctxt, p, 0)
933 934

	Addstring(sp, value)
935
	sp.Type = obj.SRODATA
936

Russ Cox's avatar
Russ Cox committed
937
	s := Linklookup(Ctxt, name, 0)
938 939
	s.Size = 0
	s.Dupok = 1
Russ Cox's avatar
Russ Cox committed
940
	reachable := s.Reachable
941 942 943 944 945 946 947 948
	Addaddr(Ctxt, s, sp)
	adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize)

	// addstring, addaddr, etc., mark the symbols as reachable.
	// In this case that is not necessarily true, so stick to what
	// we know before entering this function.
	s.Reachable = reachable

949 950
	strdata = append(strdata, s)

951 952 953
	sp.Reachable = reachable
}

954 955 956 957 958 959 960 961 962 963
func checkstrdata() {
	for _, s := range strdata {
		if s.Type == obj.STEXT {
			Diag("cannot use -X with text symbol %s", s.Name)
		} else if s.Gotype != nil && s.Gotype.Name != "type.string" {
			Diag("cannot use -X with non-string symbol %s", s.Name)
		}
	}
}

964 965
func Addstring(s *LSym, str string) int64 {
	if s.Type == 0 {
966
		s.Type = obj.SNOPTRDATA
967 968
	}
	s.Reachable = true
Russ Cox's avatar
Russ Cox committed
969 970
	r := int32(s.Size)
	n := len(str) + 1
971 972 973 974 975 976 977 978 979 980
	if s.Name == ".shstrtab" {
		elfsetstring(str, int(r))
	}
	Symgrow(Ctxt, s, int64(r)+int64(n))
	copy(s.P[r:], str)
	s.P[int(r)+len(str)] = 0
	s.Size += int64(n)
	return int64(r)
}

981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
// addgostring adds str, as a Go string value, to s. symname is the name of the
// symbol used to define the string data and must be unique per linked object.
func addgostring(s *LSym, symname, str string) {
	sym := Linklookup(Ctxt, symname, 0)
	if sym.Type != obj.Sxxx {
		Diag("duplicate symname in addgostring: %s", symname)
	}
	sym.Reachable = true
	sym.Local = true
	sym.Type = obj.SRODATA
	sym.Size = int64(len(str))
	sym.P = []byte(str)
	Addaddr(Ctxt, s, sym)
	adduint(Ctxt, s, uint64(len(str)))
}

997 998 999
func addinitarrdata(s *LSym) {
	p := s.Name + ".ptr"
	sp := Linklookup(Ctxt, p, 0)
1000
	sp.Type = obj.SINITARR
1001 1002 1003 1004 1005
	sp.Size = 0
	sp.Dupok = 1
	Addaddr(Ctxt, sp, s)
}

1006
func dosymtype() {
Russ Cox's avatar
Russ Cox committed
1007
	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
1008
		if len(s.P) > 0 {
1009 1010
			if s.Type == obj.SBSS {
				s.Type = obj.SDATA
1011
			}
1012 1013
			if s.Type == obj.SNOPTRBSS {
				s.Type = obj.SNOPTRDATA
1014 1015
			}
		}
1016 1017
		// Create a new entry in the .init_array section that points to the
		// library initializer function.
1018 1019 1020 1021 1022
		switch Buildmode {
		case BuildmodeCArchive, BuildmodeCShared:
			if s.Name == INITENTRY {
				addinitarrdata(s)
			}
1023
		}
1024 1025 1026 1027 1028 1029 1030 1031
	}
}

func symalign(s *LSym) int32 {
	if s.Align != 0 {
		return s.Align
	}

Russ Cox's avatar
Russ Cox committed
1032
	align := int32(Thearch.Maxalign)
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
	for int64(align) > s.Size && align > 1 {
		align >>= 1
	}
	if align < s.Align {
		align = s.Align
	}
	return align
}

func aligndatsize(datsize int64, s *LSym) int64 {
	return Rnd(datsize, int64(symalign(s)))
}

// maxalign returns the maximum required alignment for
// the list of symbols s; the list stops when s->type exceeds type.
func maxalign(s *LSym, type_ int) int32 {
	var align int32

Russ Cox's avatar
Russ Cox committed
1051
	max := int32(0)
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
	for ; s != nil && int(s.Type) <= type_; s = s.Next {
		align = symalign(s)
		if max < align {
			max = align
		}
	}

	return max
}

1062
const debugGCProg = false
1063

1064 1065 1066
type GCProg struct {
	sym *LSym
	w   gcprog.Writer
1067 1068
}

1069 1070 1071 1072 1073 1074
func (p *GCProg) Init(name string) {
	p.sym = Linklookup(Ctxt, name, 0)
	p.w.Init(p.writeByte)
	if debugGCProg {
		fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
		p.w.Debug(os.Stderr)
1075 1076 1077
	}
}

1078 1079
func (p *GCProg) writeByte(x byte) {
	Adduint8(Ctxt, p.sym, x)
1080 1081
}

1082 1083 1084 1085 1086
func (p *GCProg) End(size int64) {
	p.w.ZeroUntil(size / int64(Thearch.Ptrsize))
	p.w.End()
	if debugGCProg {
		fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
1087 1088 1089
	}
}

1090 1091 1092 1093 1094 1095
func (p *GCProg) AddSym(s *LSym) {
	typ := s.Gotype
	// Things without pointers should be in SNOPTRDATA or SNOPTRBSS;
	// everything we see should have pointers and should therefore have a type.
	if typ == nil {
		Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size))
1096 1097 1098
		return
	}

1099 1100
	ptrsize := int64(Thearch.Ptrsize)
	nptr := decodetype_ptrdata(typ) / ptrsize
1101

1102 1103
	if debugGCProg {
		fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr)
1104
	}
1105

1106 1107 1108 1109 1110 1111
	if decodetype_usegcprog(typ) == 0 {
		// Copy pointers from mask into program.
		mask := decodetype_gcmask(typ)
		for i := int64(0); i < nptr; i++ {
			if (mask[i/8]>>uint(i%8))&1 != 0 {
				p.w.Ptr(s.Value/ptrsize + i)
1112 1113
			}
		}
1114
		return
1115
	}
1116 1117 1118 1119

	// Copy program.
	prog := decodetype_gcprog(typ)
	p.w.ZeroUntil(s.Value / ptrsize)
1120
	p.w.Append(prog[4:], nptr)
1121 1122 1123
}

func growdatsize(datsizep *int64, s *LSym) {
Russ Cox's avatar
Russ Cox committed
1124
	datsize := *datsizep
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
	if s.Size < 0 {
		Diag("negative size (datsize = %d, s->size = %d)", datsize, s.Size)
	}
	if datsize+s.Size < datsize {
		Diag("symbol too large (datsize = %d, s->size = %d)", datsize, s.Size)
	}
	*datsizep = datsize + s.Size
}

func dodata() {
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
	}
1138
	Bso.Flush()
1139

Russ Cox's avatar
Russ Cox committed
1140
	var last *LSym
1141 1142
	datap = nil

Russ Cox's avatar
Russ Cox committed
1143
	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
1144 1145 1146
		if !s.Reachable || s.Special != 0 {
			continue
		}
1147
		if obj.STEXT < s.Type && s.Type < obj.SXREF {
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
			if s.Onlist != 0 {
				log.Fatalf("symbol %s listed multiple times", s.Name)
			}
			s.Onlist = 1
			if last == nil {
				datap = s
			} else {
				last.Next = s
			}
			s.Next = nil
			last = s
		}
	}

Russ Cox's avatar
Russ Cox committed
1162
	for s := datap; s != nil; s = s.Next {
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
		if int64(len(s.P)) > s.Size {
			Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P))
		}
	}

	/*
	 * now that we have the datap list, but before we start
	 * to assign addresses, record all the necessary
	 * dynamic relocations.  these will grow the relocation
	 * symbol, which is itself data.
	 *
	 * on darwin, we need the symbol table numbers for dynreloc.
	 */
1176
	if HEADTYPE == obj.Hdarwin {
1177 1178 1179 1180 1181
		machosymorder()
	}
	dynreloc()

	/* some symbols may no longer belong in datap (Mach-O) */
Russ Cox's avatar
Russ Cox committed
1182 1183
	var l **LSym
	var s *LSym
1184 1185 1186 1187 1188 1189
	for l = &datap; ; {
		s = *l
		if s == nil {
			break
		}

1190
		if s.Type <= obj.STEXT || obj.SXREF <= s.Type {
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
			*l = s.Next
		} else {
			l = &s.Next
		}
	}

	*l = nil

	datap = listsort(datap, datcmp, listnextp)

1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
	if Iself {
		// Make .rela and .rela.plt contiguous, the ELF ABI requires this
		// and Solaris actually cares.
		var relplt *LSym
		for l = &datap; *l != nil; l = &(*l).Next {
			if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" {
				relplt = (*l)
				*l = (*l).Next
				break
			}
		}
		if relplt != nil {
			for s = datap; s != nil; s = s.Next {
				if s.Name == ".rel" || s.Name == ".rela" {
					relplt.Next = s.Next
					s.Next = relplt
				}
			}
		}
	}

1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
	/*
	 * allocate sections.  list is sorted by type,
	 * so we can just walk it for each piece we want to emit.
	 * segdata is processed before segtext, because we need
	 * to see all symbols in the .data and .bss sections in order
	 * to generate garbage collection information.
	 */

	/* begin segdata */

	/* skip symbols belonging to segtext */
	s = datap

1235
	for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
1236 1237 1238
	}

	/* writable ELF sections */
Russ Cox's avatar
Russ Cox committed
1239
	datsize := int64(0)
1240

Russ Cox's avatar
Russ Cox committed
1241
	var sect *Section
1242
	for ; s != nil && s.Type < obj.SELFGOT; s = s.Next {
1243 1244 1245 1246 1247
		sect = addsection(&Segdata, s.Name, 06)
		sect.Align = symalign(s)
		datsize = Rnd(datsize, int64(sect.Align))
		sect.Vaddr = uint64(datsize)
		s.Sect = sect
1248
		s.Type = obj.SDATA
1249 1250 1251 1252 1253 1254
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
		sect.Length = uint64(datsize) - sect.Vaddr
	}

	/* .got (and .toc on ppc64) */
1255
	if s.Type == obj.SELFGOT {
Russ Cox's avatar
Russ Cox committed
1256
		sect := addsection(&Segdata, ".got", 06)
1257
		sect.Align = maxalign(s, obj.SELFGOT)
1258 1259
		datsize = Rnd(datsize, int64(sect.Align))
		sect.Vaddr = uint64(datsize)
Russ Cox's avatar
Russ Cox committed
1260
		var toc *LSym
1261
		for ; s != nil && s.Type == obj.SELFGOT; s = s.Next {
1262 1263
			datsize = aligndatsize(datsize, s)
			s.Sect = sect
1264
			s.Type = obj.SDATA
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
			s.Value = int64(uint64(datsize) - sect.Vaddr)

			// Resolve .TOC. symbol for this object file (ppc64)
			toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version))

			if toc != nil {
				toc.Sect = sect
				toc.Outer = s
				toc.Sub = s.Sub
				s.Sub = toc

				toc.Value = 0x8000
			}

			growdatsize(&datsize, s)
		}

		sect.Length = uint64(datsize) - sect.Vaddr
	}

	/* pointer-free data */
	sect = addsection(&Segdata, ".noptrdata", 06)

1288
	sect.Align = maxalign(s, obj.SINITARR-1)
1289 1290 1291 1292
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect
	Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect
1293
	for ; s != nil && s.Type < obj.SINITARR; s = s.Next {
1294 1295
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
1296
		s.Type = obj.SDATA
1297 1298 1299 1300 1301 1302
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr

1303 1304
	hasinitarr := Linkshared

1305
	/* shared library initializer */
1306 1307
	switch Buildmode {
	case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
1308 1309 1310 1311
		hasinitarr = true
	}

	if hasinitarr {
Russ Cox's avatar
Russ Cox committed
1312
		sect := addsection(&Segdata, ".init_array", 06)
1313
		sect.Align = maxalign(s, obj.SINITARR)
1314 1315
		datsize = Rnd(datsize, int64(sect.Align))
		sect.Vaddr = uint64(datsize)
1316
		for ; s != nil && s.Type == obj.SINITARR; s = s.Next {
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
			datsize = aligndatsize(datsize, s)
			s.Sect = sect
			s.Value = int64(uint64(datsize) - sect.Vaddr)
			growdatsize(&datsize, s)
		}

		sect.Length = uint64(datsize) - sect.Vaddr
	}

	/* data */
	sect = addsection(&Segdata, ".data", 06)
1328
	sect.Align = maxalign(s, obj.SBSS-1)
1329 1330 1331 1332
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.data", 0).Sect = sect
	Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
1333 1334
	var gc GCProg
	gc.Init("runtime.gcdata")
1335 1336
	for ; s != nil && s.Type < obj.SBSS; s = s.Next {
		if s.Type == obj.SINITARR {
1337 1338 1339 1340 1341
			Ctxt.Cursym = s
			Diag("unexpected symbol type %d", s.Type)
		}

		s.Sect = sect
1342
		s.Type = obj.SDATA
1343 1344
		datsize = aligndatsize(datsize, s)
		s.Value = int64(uint64(datsize) - sect.Vaddr)
1345
		gc.AddSym(s)
1346 1347 1348
		growdatsize(&datsize, s)
	}
	sect.Length = uint64(datsize) - sect.Vaddr
1349
	gc.End(int64(sect.Length))
1350 1351 1352

	/* bss */
	sect = addsection(&Segdata, ".bss", 06)
1353
	sect.Align = maxalign(s, obj.SNOPTRBSS-1)
1354 1355 1356 1357
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
	Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
1358 1359
	gc = GCProg{}
	gc.Init("runtime.gcbss")
1360
	for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next {
1361 1362 1363
		s.Sect = sect
		datsize = aligndatsize(datsize, s)
		s.Value = int64(uint64(datsize) - sect.Vaddr)
1364
		gc.AddSym(s)
1365 1366 1367
		growdatsize(&datsize, s)
	}
	sect.Length = uint64(datsize) - sect.Vaddr
1368
	gc.End(int64(sect.Length))
1369 1370 1371 1372

	/* pointer-free bss */
	sect = addsection(&Segdata, ".noptrbss", 06)

1373
	sect.Align = maxalign(s, obj.SNOPTRBSS)
1374 1375 1376 1377
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect
	Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect
1378
	for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next {
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr
	Linklookup(Ctxt, "runtime.end", 0).Sect = sect

	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
	if datsize != int64(uint32(datsize)) {
		Diag("data or bss segment too large")
	}

1393
	if Iself && Linkmode == LinkExternal && s != nil && s.Type == obj.STLSBSS && HEADTYPE != obj.Hopenbsd {
Russ Cox's avatar
Russ Cox committed
1394
		sect := addsection(&Segdata, ".tbss", 06)
1395 1396 1397
		sect.Align = int32(Thearch.Ptrsize)
		sect.Vaddr = 0
		datsize = 0
1398
		for ; s != nil && s.Type == obj.STLSBSS; s = s.Next {
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
			datsize = aligndatsize(datsize, s)
			s.Sect = sect
			s.Value = int64(uint64(datsize) - sect.Vaddr)
			growdatsize(&datsize, s)
		}

		sect.Length = uint64(datsize)
	} else {
		// Might be internal linking but still using cgo.
		// In that case, the only possible STLSBSS symbol is runtime.tlsg.
		// Give it offset 0, because it's the only thing here.
1410
		if s != nil && s.Type == obj.STLSBSS && s.Name == "runtime.tlsg" {
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
			s.Value = 0
			s = s.Next
		}
	}

	if s != nil {
		Ctxt.Cursym = nil
		Diag("unexpected symbol type %d for %s", s.Type, s.Name)
	}

	/*
	 * We finished data, begin read-only data.
	 * Not all systems support a separate read-only non-executable data section.
	 * ELF systems do.
	 * OS X and Plan 9 do not.
	 * Windows PE may, but if so we have not implemented it.
	 * And if we're using external linking mode, the point is moot,
	 * since it's not our decision; that code expects the sections in
	 * segtext.
	 */
Russ Cox's avatar
Russ Cox committed
1431
	var segro *Segment
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
	if Iself && Linkmode == LinkInternal {
		segro = &Segrodata
	} else {
		segro = &Segtext
	}

	s = datap

	datsize = 0

	/* read-only executable ELF, Mach-O sections */
1443
	for ; s != nil && s.Type < obj.STYPE; s = s.Next {
1444 1445 1446 1447 1448
		sect = addsection(&Segtext, s.Name, 04)
		sect.Align = symalign(s)
		datsize = Rnd(datsize, int64(sect.Align))
		sect.Vaddr = uint64(datsize)
		s.Sect = sect
1449
		s.Type = obj.SRODATA
1450 1451 1452 1453 1454 1455 1456 1457
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
		sect.Length = uint64(datsize) - sect.Vaddr
	}

	/* read-only data */
	sect = addsection(segro, ".rodata", 04)

1458
	sect.Align = maxalign(s, obj.STYPELINK-1)
1459 1460 1461 1462
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = 0
	Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
	Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
1463
	for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
1464 1465
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
1466
		s.Type = obj.SRODATA
1467 1468 1469 1470 1471 1472 1473 1474 1475
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr

	/* typelink */
	sect = addsection(segro, ".typelink", 04)

1476
	sect.Align = maxalign(s, obj.STYPELINK)
1477 1478 1479 1480
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect
	Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect
1481
	for ; s != nil && s.Type == obj.STYPELINK; s = s.Next {
1482 1483
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
1484
		s.Type = obj.SRODATA
1485 1486 1487 1488 1489 1490 1491 1492 1493
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr

	/* gosymtab */
	sect = addsection(segro, ".gosymtab", 04)

1494
	sect.Align = maxalign(s, obj.SPCLNTAB-1)
1495 1496 1497 1498
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect
	Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect
1499
	for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next {
1500 1501
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
1502
		s.Type = obj.SRODATA
1503 1504 1505 1506 1507 1508 1509 1510 1511
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr

	/* gopclntab */
	sect = addsection(segro, ".gopclntab", 04)

1512
	sect.Align = maxalign(s, obj.SELFROSECT-1)
1513 1514 1515 1516
	datsize = Rnd(datsize, int64(sect.Align))
	sect.Vaddr = uint64(datsize)
	Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect
	Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect
1517
	for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next {
1518 1519
		datsize = aligndatsize(datsize, s)
		s.Sect = sect
1520
		s.Type = obj.SRODATA
1521 1522 1523 1524 1525 1526 1527
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
	}

	sect.Length = uint64(datsize) - sect.Vaddr

	/* read-only ELF, Mach-O sections */
1528
	for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
1529 1530 1531 1532 1533
		sect = addsection(segro, s.Name, 04)
		sect.Align = symalign(s)
		datsize = Rnd(datsize, int64(sect.Align))
		sect.Vaddr = uint64(datsize)
		s.Sect = sect
1534
		s.Type = obj.SRODATA
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
		s.Value = int64(uint64(datsize) - sect.Vaddr)
		growdatsize(&datsize, s)
		sect.Length = uint64(datsize) - sect.Vaddr
	}

	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
	if datsize != int64(uint32(datsize)) {
		Diag("read-only data segment too large")
	}

	/* number the sections */
Russ Cox's avatar
Russ Cox committed
1546
	n := int32(1)
1547

Russ Cox's avatar
Russ Cox committed
1548
	for sect := Segtext.Sect; sect != nil; sect = sect.Next {
1549 1550 1551
		sect.Extnum = int16(n)
		n++
	}
Russ Cox's avatar
Russ Cox committed
1552
	for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
1553 1554 1555
		sect.Extnum = int16(n)
		n++
	}
Russ Cox's avatar
Russ Cox committed
1556
	for sect := Segdata.Sect; sect != nil; sect = sect.Next {
1557 1558 1559 1560
		sect.Extnum = int16(n)
		n++
	}
}
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583

// Add buildid to beginning of text segment, on non-ELF systems.
// Non-ELF binary formats are not always flexible enough to
// give us a place to put the Go build ID. On those systems, we put it
// at the very beginning of the text segment.
// This ``header'' is read by cmd/go.
func textbuildid() {
	if Iself || buildid == "" {
		return
	}

	sym := Linklookup(Ctxt, "go.buildid", 0)
	sym.Reachable = true
	// The \xff is invalid UTF-8, meant to make it less likely
	// to find one of these accidentally.
	data := "\xff Go build ID: " + strconv.Quote(buildid) + "\n \xff"
	sym.Type = obj.STEXT
	sym.P = []byte(data)
	sym.Size = int64(len(sym.P))

	sym.Next = Ctxt.Textp
	Ctxt.Textp = sym
}
1584 1585 1586 1587 1588 1589 1590 1591 1592 1593

// assign addresses to text
func textaddress() {
	var sub *LSym

	addsection(&Segtext, ".text", 05)

	// Assign PCs in text segment.
	// Could parallelize, by assigning to text
	// and then letting threads copy down, but probably not worth it.
Russ Cox's avatar
Russ Cox committed
1594
	sect := Segtext.Sect
1595 1596 1597 1598

	sect.Align = int32(Funcalign)
	Linklookup(Ctxt, "runtime.text", 0).Sect = sect
	Linklookup(Ctxt, "runtime.etext", 0).Sect = sect
Russ Cox's avatar
Russ Cox committed
1599
	va := uint64(INITTEXT)
1600
	sect.Vaddr = va
Russ Cox's avatar
Russ Cox committed
1601
	for sym := Ctxt.Textp; sym != nil; sym = sym.Next {
1602
		sym.Sect = sect
1603
		if sym.Type&obj.SSUB != 0 {
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
			continue
		}
		if sym.Align != 0 {
			va = uint64(Rnd(int64(va), int64(sym.Align)))
		} else {
			va = uint64(Rnd(int64(va), int64(Funcalign)))
		}
		sym.Value = 0
		for sub = sym; sub != nil; sub = sub.Sub {
			sub.Value += int64(va)
		}
		if sym.Size == 0 && sym.Sub != nil {
			Ctxt.Cursym = sym
		}
		if sym.Size < MINFUNC {
			va += MINFUNC // spacing required for findfunctab
		} else {
			va += uint64(sym.Size)
		}
	}

	sect.Length = va - sect.Vaddr
}

// assign addresses
func address() {
Russ Cox's avatar
Russ Cox committed
1630
	va := uint64(INITTEXT)
1631 1632 1633
	Segtext.Rwx = 05
	Segtext.Vaddr = va
	Segtext.Fileoff = uint64(HEADR)
Russ Cox's avatar
Russ Cox committed
1634
	for s := Segtext.Sect; s != nil; s = s.Next {
1635 1636 1637 1638 1639 1640 1641
		va = uint64(Rnd(int64(va), int64(s.Align)))
		s.Vaddr = va
		va += s.Length
	}

	Segtext.Length = va - uint64(INITTEXT)
	Segtext.Filelen = Segtext.Length
1642
	if HEADTYPE == obj.Hnacl {
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
		va += 32 // room for the "halt sled"
	}

	if Segrodata.Sect != nil {
		// align to page boundary so as not to mix
		// rodata and executable text.
		va = uint64(Rnd(int64(va), int64(INITRND)))

		Segrodata.Rwx = 04
		Segrodata.Vaddr = va
		Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
		Segrodata.Filelen = 0
Russ Cox's avatar
Russ Cox committed
1655
		for s := Segrodata.Sect; s != nil; s = s.Next {
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
			va = uint64(Rnd(int64(va), int64(s.Align)))
			s.Vaddr = va
			va += s.Length
		}

		Segrodata.Length = va - Segrodata.Vaddr
		Segrodata.Filelen = Segrodata.Length
	}

	va = uint64(Rnd(int64(va), int64(INITRND)))
	Segdata.Rwx = 06
	Segdata.Vaddr = va
	Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
	Segdata.Filelen = 0
1670
	if HEADTYPE == obj.Hwindows {
1671 1672
		Segdata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
	}
1673
	if HEADTYPE == obj.Hplan9 {
1674 1675
		Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen
	}
Russ Cox's avatar
Russ Cox committed
1676 1677 1678 1679
	var data *Section
	var noptr *Section
	var bss *Section
	var noptrbss *Section
Russ Cox's avatar
Russ Cox committed
1680 1681
	var vlen int64
	for s := Segdata.Sect; s != nil; s = s.Next {
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
		vlen = int64(s.Length)
		if s.Next != nil {
			vlen = int64(s.Next.Vaddr - s.Vaddr)
		}
		s.Vaddr = va
		va += uint64(vlen)
		Segdata.Length = va - Segdata.Vaddr
		if s.Name == ".data" {
			data = s
		}
		if s.Name == ".noptrdata" {
			noptr = s
		}
		if s.Name == ".bss" {
			bss = s
		}
		if s.Name == ".noptrbss" {
			noptrbss = s
		}
	}

	Segdata.Filelen = bss.Vaddr - Segdata.Vaddr

Russ Cox's avatar
Russ Cox committed
1705 1706
	text := Segtext.Sect
	var rodata *Section
1707 1708 1709 1710 1711
	if Segrodata.Sect != nil {
		rodata = Segrodata.Sect
	} else {
		rodata = text.Next
	}
Russ Cox's avatar
Russ Cox committed
1712 1713 1714
	typelink := rodata.Next
	symtab := typelink.Next
	pclntab := symtab.Next
1715

Russ Cox's avatar
Russ Cox committed
1716 1717
	var sub *LSym
	for sym := datap; sym != nil; sym = sym.Next {
1718 1719
		Ctxt.Cursym = sym
		if sym.Sect != nil {
1720
			sym.Value += int64(sym.Sect.Vaddr)
1721 1722 1723 1724 1725 1726
		}
		for sub = sym.Sub; sub != nil; sub = sub.Sub {
			sub.Value += sym.Value
		}
	}

1727 1728 1729 1730 1731 1732 1733
	if Buildmode == BuildmodeShared {
		s := Linklookup(Ctxt, "go.link.abihashbytes", 0)
		sectSym := Linklookup(Ctxt, ".note.go.abihash", 0)
		s.Sect = sectSym.Sect
		s.Value = int64(sectSym.Sect.Vaddr + 16)
	}

1734 1735 1736 1737 1738 1739
	xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
	xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
	xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr))
	xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length))
	xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr))
	xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length))
1740

Russ Cox's avatar
Russ Cox committed
1741
	sym := Linklookup(Ctxt, "runtime.gcdata", 0)
1742
	sym.Local = true
1743
	xdefine("runtime.egcdata", obj.SRODATA, Symaddr(sym)+sym.Size)
1744 1745 1746
	Linklookup(Ctxt, "runtime.egcdata", 0).Sect = sym.Sect

	sym = Linklookup(Ctxt, "runtime.gcbss", 0)
1747
	sym.Local = true
1748
	xdefine("runtime.egcbss", obj.SRODATA, Symaddr(sym)+sym.Size)
1749 1750
	Linklookup(Ctxt, "runtime.egcbss", 0).Sect = sym.Sect

1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
	xdefine("runtime.symtab", obj.SRODATA, int64(symtab.Vaddr))
	xdefine("runtime.esymtab", obj.SRODATA, int64(symtab.Vaddr+symtab.Length))
	xdefine("runtime.pclntab", obj.SRODATA, int64(pclntab.Vaddr))
	xdefine("runtime.epclntab", obj.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
	xdefine("runtime.noptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr))
	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
	xdefine("runtime.bss", obj.SBSS, int64(bss.Vaddr))
	xdefine("runtime.ebss", obj.SBSS, int64(bss.Vaddr+bss.Length))
	xdefine("runtime.data", obj.SDATA, int64(data.Vaddr))
	xdefine("runtime.edata", obj.SDATA, int64(data.Vaddr+data.Length))
	xdefine("runtime.noptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr))
	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
	xdefine("runtime.end", obj.SBSS, int64(Segdata.Vaddr+Segdata.Length))
1764
}