github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/symtab.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/ld/symtab.go 2 3 // Inferno utils/6l/span.c 4 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 5 // 6 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 7 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 8 // Portions Copyright © 1997-1999 Vita Nuova Limited 9 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 10 // Portions Copyright © 2004,2006 Bruce Ellis 11 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 12 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 13 // Portions Copyright © 2009 The Go Authors. All rights reserved. 14 // 15 // Permission is hereby granted, free of charge, to any person obtaining a copy 16 // of this software and associated documentation files (the "Software"), to deal 17 // in the Software without restriction, including without limitation the rights 18 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 // copies of the Software, and to permit persons to whom the Software is 20 // furnished to do so, subject to the following conditions: 21 // 22 // The above copyright notice and this permission notice shall be included in 23 // all copies or substantial portions of the Software. 24 // 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 // THE SOFTWARE. 32 33 package ld 34 35 import ( 36 "rsc.io/tmp/bootstrap/internal/obj" 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 type_ = STT_NOTYPE 112 if x == Ctxt.Tlsg { 113 type_ = STT_TLS 114 } 115 116 case 't': 117 type_ = STT_TLS 118 } 119 120 xo := x 121 for xo.Outer != nil { 122 xo = xo.Outer 123 } 124 125 var elfshnum int 126 if xo.Type == obj.SDYNIMPORT || xo.Type == obj.SHOSTOBJ { 127 elfshnum = SHN_UNDEF 128 } else { 129 if xo.Sect == nil { 130 Ctxt.Cursym = x 131 Diag("missing section in putelfsym") 132 return 133 } 134 if xo.Sect.(*Section).Elfsect == nil { 135 Ctxt.Cursym = x 136 Diag("missing ELF section in putelfsym") 137 return 138 } 139 elfshnum = xo.Sect.(*Section).Elfsect.(*ElfShdr).shnum 140 } 141 142 // One pass for each binding: STB_LOCAL, STB_GLOBAL, 143 // maybe one day STB_WEAK. 144 bind := STB_GLOBAL 145 146 if ver != 0 || (x.Type&obj.SHIDDEN != 0) || x.Local { 147 bind = STB_LOCAL 148 } 149 150 // In external linking mode, we have to invoke gcc with -rdynamic 151 // to get the exported symbols put into the dynamic symbol table. 152 // To avoid filling the dynamic table with lots of unnecessary symbols, 153 // mark all Go symbols local (not global) in the final executable. 154 // But when we're dynamically linking, we need all those global symbols. 155 if !DynlinkingGo() && Linkmode == LinkExternal && x.Cgoexport&CgoExportStatic == 0 && elfshnum != SHN_UNDEF { 156 bind = STB_LOCAL 157 } 158 159 if bind != elfbind { 160 return 161 } 162 163 off := putelfstr(s) 164 if Linkmode == LinkExternal && elfshnum != SHN_UNDEF { 165 addr -= int64(xo.Sect.(*Section).Vaddr) 166 } 167 other := STV_DEFAULT 168 if x.Type&obj.SHIDDEN != 0 { 169 other = STV_HIDDEN 170 } 171 putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other) 172 x.Elfsym = int32(numelfsym) 173 numelfsym++ 174 } 175 176 func putelfsectionsym(s *LSym, shndx int) { 177 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) 178 s.Elfsym = int32(numelfsym) 179 numelfsym++ 180 } 181 182 func putelfsymshndx(sympos int64, shndx int) { 183 here := Cpos() 184 if elf64 { 185 Cseek(sympos + 6) 186 } else { 187 Cseek(sympos + 14) 188 } 189 190 Thearch.Wput(uint16(shndx)) 191 Cseek(here) 192 } 193 194 func Asmelfsym() { 195 // the first symbol entry is reserved 196 putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) 197 198 dwarfaddelfsectionsyms() 199 200 elfbind = STB_LOCAL 201 genasmsym(putelfsym) 202 203 elfbind = STB_GLOBAL 204 elfglobalsymndx = numelfsym 205 genasmsym(putelfsym) 206 } 207 208 func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *LSym) { 209 switch t { 210 case 'T', 'L', 'D', 'B': 211 if ver != 0 { 212 t += 'a' - 'A' 213 } 214 fallthrough 215 216 case 'a', 217 'p', 218 'f', 219 'z', 220 'Z', 221 'm': 222 l := 4 223 if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 { 224 Lputb(uint32(addr >> 32)) 225 l = 8 226 } 227 228 Lputb(uint32(addr)) 229 Cput(uint8(t + 0x80)) /* 0x80 is variable length */ 230 231 var i int 232 if t == 'z' || t == 'Z' { 233 Cput(uint8(s[0])) 234 for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { 235 Cput(uint8(s[i])) 236 Cput(uint8(s[i+1])) 237 } 238 239 Cput(0) 240 Cput(0) 241 i++ 242 } else { 243 /* skip the '<' in filenames */ 244 if t == 'f' { 245 s = s[1:] 246 } 247 for i = 0; i < len(s); i++ { 248 Cput(uint8(s[i])) 249 } 250 Cput(0) 251 } 252 253 Symsize += int32(l) + 1 + int32(i) + 1 254 255 default: 256 return 257 } 258 } 259 260 func Asmplan9sym() { 261 genasmsym(putplan9sym) 262 } 263 264 var symt *LSym 265 266 func Wputl(w uint16) { 267 Cput(uint8(w)) 268 Cput(uint8(w >> 8)) 269 } 270 271 func Wputb(w uint16) { 272 Cput(uint8(w >> 8)) 273 Cput(uint8(w)) 274 } 275 276 func Lputb(l uint32) { 277 Cput(uint8(l >> 24)) 278 Cput(uint8(l >> 16)) 279 Cput(uint8(l >> 8)) 280 Cput(uint8(l)) 281 } 282 283 func Lputl(l uint32) { 284 Cput(uint8(l)) 285 Cput(uint8(l >> 8)) 286 Cput(uint8(l >> 16)) 287 Cput(uint8(l >> 24)) 288 } 289 290 func Vputb(v uint64) { 291 Lputb(uint32(v >> 32)) 292 Lputb(uint32(v)) 293 } 294 295 func Vputl(v uint64) { 296 Lputl(uint32(v)) 297 Lputl(uint32(v >> 32)) 298 } 299 300 func symtab() { 301 dosymtype() 302 303 // Define these so that they'll get put into the symbol table. 304 // data.c:/^address will provide the actual values. 305 xdefine("runtime.text", obj.STEXT, 0) 306 307 xdefine("runtime.etext", obj.STEXT, 0) 308 xdefine("runtime.typelink", obj.SRODATA, 0) 309 xdefine("runtime.etypelink", obj.SRODATA, 0) 310 xdefine("runtime.rodata", obj.SRODATA, 0) 311 xdefine("runtime.erodata", obj.SRODATA, 0) 312 xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) 313 xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) 314 xdefine("runtime.data", obj.SDATA, 0) 315 xdefine("runtime.edata", obj.SDATA, 0) 316 xdefine("runtime.bss", obj.SBSS, 0) 317 xdefine("runtime.ebss", obj.SBSS, 0) 318 xdefine("runtime.noptrbss", obj.SNOPTRBSS, 0) 319 xdefine("runtime.enoptrbss", obj.SNOPTRBSS, 0) 320 xdefine("runtime.end", obj.SBSS, 0) 321 xdefine("runtime.epclntab", obj.SRODATA, 0) 322 xdefine("runtime.esymtab", obj.SRODATA, 0) 323 324 // garbage collection symbols 325 s := Linklookup(Ctxt, "runtime.gcdata", 0) 326 327 s.Type = obj.SRODATA 328 s.Size = 0 329 s.Reachable = true 330 xdefine("runtime.egcdata", obj.SRODATA, 0) 331 332 s = Linklookup(Ctxt, "runtime.gcbss", 0) 333 s.Type = obj.SRODATA 334 s.Size = 0 335 s.Reachable = true 336 xdefine("runtime.egcbss", obj.SRODATA, 0) 337 338 // pseudo-symbols to mark locations of type, string, and go string data. 339 var symtype *LSym 340 if !DynlinkingGo() { 341 s = Linklookup(Ctxt, "type.*", 0) 342 343 s.Type = obj.STYPE 344 s.Size = 0 345 s.Reachable = true 346 symtype = s 347 } 348 349 s = Linklookup(Ctxt, "go.string.*", 0) 350 s.Type = obj.SGOSTRING 351 s.Local = true 352 s.Size = 0 353 s.Reachable = true 354 symgostring := s 355 356 s = Linklookup(Ctxt, "go.func.*", 0) 357 s.Type = obj.SGOFUNC 358 s.Local = true 359 s.Size = 0 360 s.Reachable = true 361 symgofunc := s 362 363 symtypelink := Linklookup(Ctxt, "runtime.typelink", 0) 364 365 symt = Linklookup(Ctxt, "runtime.symtab", 0) 366 symt.Local = true 367 symt.Type = obj.SSYMTAB 368 symt.Size = 0 369 symt.Reachable = true 370 371 ntypelinks := 0 372 373 // assign specific types so that they sort together. 374 // within a type they sort by size, so the .* symbols 375 // just defined above will be first. 376 // hide the specific symbols. 377 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 378 if !s.Reachable || s.Special != 0 || s.Type != obj.SRODATA { 379 continue 380 } 381 382 if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() { 383 s.Type = obj.STYPE 384 s.Hide = 1 385 s.Outer = symtype 386 } 387 388 if strings.HasPrefix(s.Name, "go.typelink.") { 389 ntypelinks++ 390 s.Type = obj.STYPELINK 391 s.Hide = 1 392 s.Outer = symtypelink 393 } 394 395 if strings.HasPrefix(s.Name, "go.string.") { 396 s.Type = obj.SGOSTRING 397 s.Hide = 1 398 s.Outer = symgostring 399 } 400 401 if strings.HasPrefix(s.Name, "go.func.") { 402 s.Type = obj.SGOFUNC 403 s.Hide = 1 404 s.Outer = symgofunc 405 } 406 407 if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") { 408 s.Type = obj.SGOFUNC 409 s.Hide = 1 410 s.Outer = symgofunc 411 s.Align = 4 412 liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 413 } 414 } 415 416 // Information about the layout of the executable image for the 417 // runtime to use. Any changes here must be matched by changes to 418 // the definition of moduledata in runtime/symtab.go. 419 // This code uses several global variables that are set by pcln.go:pclntab. 420 moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0) 421 moduledata.Type = obj.SNOPTRDATA 422 moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize 423 moduledata.Reachable = true 424 moduledata.Local = true 425 // The pclntab slice 426 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0)) 427 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 428 adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size)) 429 // The ftab slice 430 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset)) 431 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 432 adduint(Ctxt, moduledata, uint64(pclntabNfunc+1)) 433 // The filetab slice 434 Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset)) 435 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)) 436 adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)) 437 // findfunctab 438 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0)) 439 // minpc, maxpc 440 Addaddr(Ctxt, moduledata, pclntabFirstFunc) 441 Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size) 442 // pointers to specific parts of the module 443 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0)) 444 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0)) 445 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0)) 446 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrdata", 0)) 447 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0)) 448 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0)) 449 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0)) 450 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0)) 451 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0)) 452 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 0)) 453 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) 454 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) 455 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) 456 // The typelinks slice 457 Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) 458 adduint(Ctxt, moduledata, uint64(ntypelinks)) 459 adduint(Ctxt, moduledata, uint64(ntypelinks)) 460 // The rest of moduledata is zero initialized. 461 // When linking an object that does not contain the runtime we are 462 // creating the moduledata from scratch and it does not have a 463 // compiler-provided size, so read it from the type data. 464 moduledatatype := Linkrlookup(Ctxt, "type.runtime.moduledata", 0) 465 moduledata.Size = decodetype_size(moduledatatype) 466 Symgrow(Ctxt, moduledata, moduledata.Size) 467 468 lastmoduledatap := Linklookup(Ctxt, "runtime.lastmoduledatap", 0) 469 if lastmoduledatap.Type != obj.SDYNIMPORT { 470 lastmoduledatap.Type = obj.SNOPTRDATA 471 lastmoduledatap.Size = 0 // overwrite existing value 472 Addaddr(Ctxt, lastmoduledatap, moduledata) 473 } 474 }