Home | History | Annotate | Download | only in ld
      1 // Inferno utils/6l/span.c
      2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
      3 //
      4 //	Copyright  1994-1999 Lucent Technologies Inc.  All rights reserved.
      5 //	Portions Copyright  1995-1997 C H Forsyth (forsyth (a] terzarima.net)
      6 //	Portions Copyright  1997-1999 Vita Nuova Limited
      7 //	Portions Copyright  2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
      8 //	Portions Copyright  2004,2006 Bruce Ellis
      9 //	Portions Copyright  2005-2007 C H Forsyth (forsyth (a] terzarima.net)
     10 //	Revisions Copyright  2000-2007 Lucent Technologies Inc. and others
     11 //	Portions Copyright  2009 The Go Authors.  All rights reserved.
     12 //
     13 // Permission is hereby granted, free of charge, to any person obtaining a copy
     14 // of this software and associated documentation files (the "Software"), to deal
     15 // in the Software without restriction, including without limitation the rights
     16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17 // copies of the Software, and to permit persons to whom the Software is
     18 // furnished to do so, subject to the following conditions:
     19 //
     20 // The above copyright notice and this permission notice shall be included in
     21 // all copies or substantial portions of the Software.
     22 //
     23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     29 // THE SOFTWARE.
     30 
     31 package ld
     32 
     33 import (
     34 	"cmd/internal/obj"
     35 	"fmt"
     36 	"path/filepath"
     37 	"strings"
     38 )
     39 
     40 // Symbol table.
     41 
     42 func putelfstr(s string) int {
     43 	if len(Elfstrdat) == 0 && s != "" {
     44 		// first entry must be empty string
     45 		putelfstr("")
     46 	}
     47 
     48 	// When dynamically linking, we create LSym's by reading the names from
     49 	// the symbol tables of the shared libraries and so the names need to
     50 	// match exactly.  Tools like DTrace will have to wait for now.
     51 	if !DynlinkingGo() {
     52 		// Rewrite  to . for ASCII-only tools like DTrace (sigh)
     53 		s = strings.Replace(s, "", ".", -1)
     54 	}
     55 
     56 	n := len(s) + 1
     57 	for len(Elfstrdat)+n > cap(Elfstrdat) {
     58 		Elfstrdat = append(Elfstrdat[:cap(Elfstrdat)], 0)[:len(Elfstrdat)]
     59 	}
     60 
     61 	off := len(Elfstrdat)
     62 	Elfstrdat = Elfstrdat[:off+n]
     63 	copy(Elfstrdat[off:], s)
     64 
     65 	return off
     66 }
     67 
     68 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
     69 	switch Thearch.Thechar {
     70 	case '6', '7', '9':
     71 		Thearch.Lput(uint32(off))
     72 		Cput(uint8(info))
     73 		Cput(uint8(other))
     74 		Thearch.Wput(uint16(shndx))
     75 		Thearch.Vput(uint64(addr))
     76 		Thearch.Vput(uint64(size))
     77 		Symsize += ELF64SYMSIZE
     78 
     79 	default:
     80 		Thearch.Lput(uint32(off))
     81 		Thearch.Lput(uint32(addr))
     82 		Thearch.Lput(uint32(size))
     83 		Cput(uint8(info))
     84 		Cput(uint8(other))
     85 		Thearch.Wput(uint16(shndx))
     86 		Symsize += ELF32SYMSIZE
     87 	}
     88 }
     89 
     90 var numelfsym int = 1 // 0 is reserved
     91 
     92 var elfbind int
     93 
     94 func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
     95 	var type_ int
     96 
     97 	switch t {
     98 	default:
     99 		return
    100 
    101 	case 'T':
    102 		type_ = STT_FUNC
    103 
    104 	case 'D':
    105 		type_ = STT_OBJECT
    106 
    107 	case 'B':
    108 		type_ = STT_OBJECT
    109 
    110 	case 'U':
    111 		// ElfType is only set for symbols read from Go shared libraries, but
    112 		// for other symbols it is left as STT_NOTYPE which is fine.
    113 		type_ = int(x.ElfType)
    114 
    115 	case 't':
    116 		type_ = STT_TLS
    117 	}
    118 
    119 	xo := x
    120 	for xo.Outer != nil {
    121 		xo = xo.Outer
    122 	}
    123 
    124 	var elfshnum int
    125 	if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ {
    126 		elfshnum = SHN_UNDEF
    127 	} else {
    128 		if xo.Sect == nil {
    129 			Ctxt.Cursym = x
    130 			Diag("missing section in putelfsym")
    131 			return
    132 		}
    133 		if xo.Sect.Elfsect == nil {
    134 			Ctxt.Cursym = x
    135 			Diag("missing ELF section in putelfsym")
    136 			return
    137 		}
    138 		elfshnum = xo.Sect.Elfsect.shnum
    139 	}
    140 
    141 	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
    142 	// maybe one day STB_WEAK.
    143 	bind := STB_GLOBAL
    144 
    145 	if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Local {
    146 		bind = STB_LOCAL
    147 	}
    148 
    149 	// In external linking mode, we have to invoke gcc with -rdynamic
    150 	// to get the exported symbols put into the dynamic symbol table.
    151 	// To avoid filling the dynamic table with lots of unnecessary symbols,
    152 	// mark all Go symbols local (not global) in the final executable.
    153 	// But when we're dynamically linking, we need all those global symbols.
    154 	if !DynlinkingGo() && Linkmode == LinkExternal && x.Cgoexport&CgoExportStatic == 0 && elfshnum != SHN_UNDEF {
    155 		bind = STB_LOCAL
    156 	}
    157 
    158 	if bind != elfbind {
    159 		return
    160 	}
    161 
    162 	off := putelfstr(s)
    163 	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
    164 		addr -= int64(xo.Sect.Vaddr)
    165 	}
    166 	other := STV_DEFAULT
    167 	if x.Type&obj.SHIDDEN != 0 {
    168 		other = STV_HIDDEN
    169 	}
    170 	putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
    171 	x.Elfsym = int32(numelfsym)
    172 	numelfsym++
    173 }
    174 
    175 func putelfsectionsym(s *LSym, shndx int) {
    176 	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
    177 	s.Elfsym = int32(numelfsym)
    178 	numelfsym++
    179 }
    180 
    181 func putelfsymshndx(sympos int64, shndx int) {
    182 	here := Cpos()
    183 	if elf64 {
    184 		Cseek(sympos + 6)
    185 	} else {
    186 		Cseek(sympos + 14)
    187 	}
    188 
    189 	Thearch.Wput(uint16(shndx))
    190 	Cseek(here)
    191 }
    192 
    193 func Asmelfsym() {
    194 	// the first symbol entry is reserved
    195 	putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
    196 
    197 	dwarfaddelfsectionsyms()
    198 
    199 	elfbind = STB_LOCAL
    200 	genasmsym(putelfsym)
    201 
    202 	elfbind = STB_GLOBAL
    203 	elfglobalsymndx = numelfsym
    204 	genasmsym(putelfsym)
    205 }
    206 
    207 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) {
    208 	switch t {
    209 	case 'T', 'L', 'D', 'B':
    210 		if ver != 0 {
    211 			t += 'a' - 'A'
    212 		}
    213 		fallthrough
    214 
    215 	case 'a',
    216 		'p',
    217 		'f',
    218 		'z',
    219 		'Z',
    220 		'm':
    221 		l := 4
    222 		if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 {
    223 			Lputb(uint32(addr >> 32))
    224 			l = 8
    225 		}
    226 
    227 		Lputb(uint32(addr))
    228 		Cput(uint8(t + 0x80)) /* 0x80 is variable length */
    229 
    230 		var i int
    231 		if t == 'z' || t == 'Z' {
    232 			Cput(uint8(s[0]))
    233 			for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
    234 				Cput(uint8(s[i]))
    235 				Cput(uint8(s[i+1]))
    236 			}
    237 
    238 			Cput(0)
    239 			Cput(0)
    240 			i++
    241 		} else {
    242 			/* skip the '<' in filenames */
    243 			if t == 'f' {
    244 				s = s[1:]
    245 			}
    246 			for i = 0; i < len(s); i++ {
    247 				Cput(uint8(s[i]))
    248 			}
    249 			Cput(0)
    250 		}
    251 
    252 		Symsize += int32(l) + 1 + int32(i) + 1
    253 
    254 	default:
    255 		return
    256 	}
    257 }
    258 
    259 func Asmplan9sym() {
    260 	genasmsym(putplan9sym)
    261 }
    262 
    263 var symt *LSym
    264 
    265 func Wputl(w uint16) {
    266 	Cput(uint8(w))
    267 	Cput(uint8(w >> 8))
    268 }
    269 
    270 func Wputb(w uint16) {
    271 	Cput(uint8(w >> 8))
    272 	Cput(uint8(w))
    273 }
    274 
    275 func Lputb(l uint32) {
    276 	Cput(uint8(l >> 24))
    277 	Cput(uint8(l >> 16))
    278 	Cput(uint8(l >> 8))
    279 	Cput(uint8(l))
    280 }
    281 
    282 func Lputl(l uint32) {
    283 	Cput(uint8(l))
    284 	Cput(uint8(l >> 8))
    285 	Cput(uint8(l >> 16))
    286 	Cput(uint8(l >> 24))
    287 }
    288 
    289 func Vputb(v uint64) {
    290 	Lputb(uint32(v >> 32))
    291 	Lputb(uint32(v))
    292 }
    293 
    294 func Vputl(v uint64) {
    295 	Lputl(uint32(v))
    296 	Lputl(uint32(v >> 32))
    297 }
    298 
    299 type byPkg []*Library
    300 
    301 func (libs byPkg) Len() int {
    302 	return len(libs)
    303 }
    304 
    305 func (libs byPkg) Less(a, b int) bool {
    306 	return libs[a].Pkg < libs[b].Pkg
    307 }
    308 
    309 func (libs byPkg) Swap(a, b int) {
    310 	libs[a], libs[b] = libs[b], libs[a]
    311 }
    312 
    313 func symtab() {
    314 	dosymtype()
    315 
    316 	// Define these so that they'll get put into the symbol table.
    317 	// data.c:/^address will provide the actual values.
    318 	xdefine("runtime.text", obj.STEXT, 0)
    319 
    320 	xdefine("runtime.etext", obj.STEXT, 0)
    321 	xdefine("runtime.typelink", obj.SRODATA, 0)
    322 	xdefine("runtime.etypelink", obj.SRODATA, 0)
    323 	xdefine("runtime.rodata", obj.SRODATA, 0)
    324 	xdefine("runtime.erodata", obj.SRODATA, 0)
    325 	xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
    326 	xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
    327 	xdefine("runtime.data", obj.SDATA, 0)
    328 	xdefine("runtime.edata", obj.SDATA, 0)
    329 	xdefine("runtime.bss", obj.SBSS, 0)
    330 	xdefine("runtime.ebss", obj.SBSS, 0)
    331 	xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0)
    332 	xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0)
    333 	xdefine("runtime.end", obj.SBSS, 0)
    334 	xdefine("runtime.epclntab", obj.SRODATA, 0)
    335 	xdefine("runtime.esymtab", obj.SRODATA, 0)
    336 
    337 	// garbage collection symbols
    338 	s := Linklookup(Ctxt, "runtime.gcdata", 0)
    339 
    340 	s.Type = obj.SRODATA
    341 	s.Size = 0
    342 	s.Reachable = true
    343 	xdefine("runtime.egcdata", obj.SRODATA, 0)
    344 
    345 	s = Linklookup(Ctxt, "runtime.gcbss", 0)
    346 	s.Type = obj.SRODATA
    347 	s.Size = 0
    348 	s.Reachable = true
    349 	xdefine("runtime.egcbss", obj.SRODATA, 0)
    350 
    351 	// pseudo-symbols to mark locations of type, string, and go string data.
    352 	var symtype *LSym
    353 	if !DynlinkingGo() {
    354 		s = Linklookup(Ctxt, "type.*", 0)
    355 
    356 		s.Type = obj.STYPE
    357 		s.Size = 0
    358 		s.Reachable = true
    359 		symtype = s
    360 	}
    361 
    362 	s = Linklookup(Ctxt, "go.string.*", 0)
    363 	s.Type = obj.SGOSTRING
    364 	s.Local = true
    365 	s.Size = 0
    366 	s.Reachable = true
    367 	symgostring := s
    368 
    369 	s = Linklookup(Ctxt, "go.func.*", 0)
    370 	s.Type = obj.SGOFUNC
    371 	s.Local = true
    372 	s.Size = 0
    373 	s.Reachable = true
    374 	symgofunc := s
    375 
    376 	s = Linklookup(Ctxt, "runtime.gcbits.*", 0)
    377 	s.Type = obj.SGCBITS
    378 	s.Local = true
    379 	s.Size = 0
    380 	s.Reachable = true
    381 	symgcbits := s
    382 
    383 	symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
    384 
    385 	symt = Linklookup(Ctxt, "runtime.symtab", 0)
    386 	symt.Local = true
    387 	symt.Type = obj.SSYMTAB
    388 	symt.Size = 0
    389 	symt.Reachable = true
    390 
    391 	ntypelinks := 0
    392 
    393 	// assign specific types so that they sort together.
    394 	// within a type they sort by size, so the .* symbols
    395 	// just defined above will be first.
    396 	// hide the specific symbols.
    397 	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
    398 		if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA {
    399 			continue
    400 		}
    401 
    402 		if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() {
    403 			s.Type = obj.STYPE
    404 			s.Hide = 1
    405 			s.Outer = symtype
    406 		}
    407 
    408 		if strings.HasPrefix(s.Name, "go.typelink.") {
    409 			ntypelinks++
    410 			s.Type = obj.STYPELINK
    411 			s.Hide = 1
    412 			s.Outer = symtypelink
    413 		}
    414 
    415 		if strings.HasPrefix(s.Name, "go.string.") {
    416 			s.Type = obj.SGOSTRING
    417 			s.Hide = 1
    418 			s.Outer = symgostring
    419 		}
    420 
    421 		if strings.HasPrefix(s.Name, "runtime.gcbits.") {
    422 			s.Type = obj.SGCBITS
    423 			s.Hide = 1
    424 			s.Outer = symgcbits
    425 		}
    426 
    427 		if strings.HasPrefix(s.Name, "go.func.") {
    428 			s.Type = obj.SGOFUNC
    429 			s.Hide = 1
    430 			s.Outer = symgofunc
    431 		}
    432 
    433 		if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals") {
    434 			s.Type = obj.SGOFUNC
    435 			s.Hide = 1
    436 			s.Outer = symgofunc
    437 			s.Align = 4
    438 			liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
    439 		}
    440 	}
    441 
    442 	if Buildmode == BuildmodeShared {
    443 		abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0)
    444 		abihashgostr.Reachable = true
    445 		abihashgostr.Type = obj.SRODATA
    446 		hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0)
    447 		Addaddr(Ctxt, abihashgostr, hashsym)
    448 		adduint(Ctxt, abihashgostr, uint64(hashsym.Size))
    449 	}
    450 
    451 	// Information about the layout of the executable image for the
    452 	// runtime to use. Any changes here must be matched by changes to
    453 	// the definition of moduledata in runtime/symtab.go.
    454 	// This code uses several global variables that are set by pcln.go:pclntab.
    455 	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
    456 	moduledata.Type = obj.SNOPTRDATA
    457 	moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize
    458 	moduledata.Reachable = true
    459 	moduledata.Local = true
    460 	// The pclntab slice
    461 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
    462 	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
    463 	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
    464 	// The ftab slice
    465 	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset))
    466 	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
    467 	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
    468 	// The filetab slice
    469 	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
    470 	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
    471 	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
    472 	// findfunctab
    473 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
    474 	// minpc, maxpc
    475 	Addaddr(Ctxt, moduledata, pclntabFirstFunc)
    476 	Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
    477 	// pointers to specific parts of the module
    478 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0))
    479 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0))
    480 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0))
    481 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0))
    482 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0))
    483 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0))
    484 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0))
    485 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0))
    486 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0))
    487 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0))
    488 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0))
    489 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0))
    490 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
    491 	// The typelinks slice
    492 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
    493 	adduint(Ctxt, moduledata, uint64(ntypelinks))
    494 	adduint(Ctxt, moduledata, uint64(ntypelinks))
    495 	if len(Ctxt.Shlibs) > 0 {
    496 		thismodulename := filepath.Base(outfile)
    497 		if Buildmode == BuildmodeExe {
    498 			// When linking an executable, outfile is just "a.out". Make
    499 			// it something slightly more comprehensible.
    500 			thismodulename = "the executable"
    501 		}
    502 		addgostring(moduledata, "go.link.thismodulename", thismodulename)
    503 
    504 		modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0)
    505 		modulehashes.Reachable = true
    506 		modulehashes.Local = true
    507 		modulehashes.Type = obj.SRODATA
    508 
    509 		for i, shlib := range Ctxt.Shlibs {
    510 			// modulehashes[i].modulename
    511 			modulename := filepath.Base(shlib.Path)
    512 			addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
    513 
    514 			// modulehashes[i].linktimehash
    515 			addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
    516 
    517 			// modulehashes[i].runtimehash
    518 			abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0)
    519 			abihash.Reachable = true
    520 			Addaddr(Ctxt, modulehashes, abihash)
    521 		}
    522 
    523 		Addaddr(Ctxt, moduledata, modulehashes)
    524 		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
    525 		adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
    526 	}
    527 	// The rest of moduledata is zero initialized.
    528 	// When linking an object that does not contain the runtime we are
    529 	// creating the moduledata from scratch and it does not have a
    530 	// compiler-provided size, so read it from the type data.
    531 	moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0)
    532 	moduledata.Size = decodetype_size(moduledatatype)
    533 	Symgrow(Ctxt, moduledata, moduledata.Size)
    534 
    535 	lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0)
    536 	if lastmoduledatap.Type != obj.SDYNIMPORT {
    537 		lastmoduledatap.Type = obj.SNOPTRDATA
    538 		lastmoduledatap.Size = 0 // overwrite existing value
    539 		Addaddr(Ctxt, lastmoduledatap, moduledata)
    540 	}
    541 }
    542