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