github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/link/internal/ld/objfile.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 // Reading of Go object files. 8 9 import ( 10 "bufio" 11 "bytes" 12 "cmd/internal/bio" 13 "cmd/internal/dwarf" 14 "cmd/internal/objabi" 15 "crypto/sha1" 16 "encoding/base64" 17 "io" 18 "log" 19 "strconv" 20 "strings" 21 ) 22 23 const ( 24 startmagic = "\x00\x00go19ld" 25 endmagic = "\xff\xffgo19ld" 26 ) 27 28 var emptyPkg = []byte(`"".`) 29 30 // objReader reads Go object files. 31 type objReader struct { 32 rd *bufio.Reader 33 ctxt *Link 34 lib *Library 35 pn string 36 dupSym *Symbol 37 localSymVersion int 38 39 // rdBuf is used by readString and readSymName as scratch for reading strings. 40 rdBuf []byte 41 42 // List of symbol references for the file being read. 43 refs []*Symbol 44 data []byte 45 reloc []Reloc 46 pcdata []Pcdata 47 autom []Auto 48 funcdata []*Symbol 49 funcdataoff []int64 50 file []*Symbol 51 } 52 53 func LoadObjFile(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn string) { 54 55 start := f.Offset() 56 r := &objReader{ 57 rd: f.Reader, 58 lib: lib, 59 ctxt: ctxt, 60 pn: pn, 61 dupSym: &Symbol{Name: ".dup"}, 62 localSymVersion: ctxt.Syms.IncVersion(), 63 } 64 r.loadObjFile() 65 if f.Offset() != start+length { 66 log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length) 67 } 68 } 69 70 func (r *objReader) loadObjFile() { 71 pkg := objabi.PathToPrefix(r.lib.Pkg) 72 73 // Magic header 74 var buf [8]uint8 75 r.readFull(buf[:]) 76 if string(buf[:]) != startmagic { 77 log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", r.pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]) 78 } 79 80 // Version 81 c, err := r.rd.ReadByte() 82 if err != nil || c != 1 { 83 log.Fatalf("%s: invalid file version number %d", r.pn, c) 84 } 85 86 // Autolib 87 for { 88 lib := r.readString() 89 if lib == "" { 90 break 91 } 92 l := addlib(r.ctxt, pkg, r.pn, lib) 93 if l != nil { 94 r.lib.imports = append(r.lib.imports, l) 95 } 96 } 97 98 // Symbol references 99 r.refs = []*Symbol{nil} // zeroth ref is nil 100 for { 101 c, err := r.rd.Peek(1) 102 if err != nil { 103 log.Fatalf("%s: peeking: %v", r.pn, err) 104 } 105 if c[0] == 0xff { 106 r.rd.ReadByte() 107 break 108 } 109 r.readRef() 110 } 111 112 // Lengths 113 r.readSlices() 114 115 // Data section 116 r.readFull(r.data) 117 118 // Defined symbols 119 for { 120 c, err := r.rd.Peek(1) 121 if err != nil { 122 log.Fatalf("%s: peeking: %v", r.pn, err) 123 } 124 if c[0] == 0xff { 125 break 126 } 127 r.readSym() 128 } 129 130 // Magic footer 131 buf = [8]uint8{} 132 r.readFull(buf[:]) 133 if string(buf[:]) != endmagic { 134 log.Fatalf("%s: invalid file end", r.pn) 135 } 136 } 137 138 func (r *objReader) readSlices() { 139 n := r.readInt() 140 r.data = make([]byte, n) 141 n = r.readInt() 142 r.reloc = make([]Reloc, n) 143 n = r.readInt() 144 r.pcdata = make([]Pcdata, n) 145 n = r.readInt() 146 r.autom = make([]Auto, n) 147 n = r.readInt() 148 r.funcdata = make([]*Symbol, n) 149 r.funcdataoff = make([]int64, n) 150 n = r.readInt() 151 r.file = make([]*Symbol, n) 152 } 153 154 // Symbols are prefixed so their content doesn't get confused with the magic footer. 155 const symPrefix = 0xfe 156 157 func (r *objReader) readSym() { 158 if c, err := r.rd.ReadByte(); c != symPrefix || err != nil { 159 log.Fatalln("readSym out of sync") 160 } 161 t := abiSymKindToSymKind[r.readInt()] 162 s := r.readSymIndex() 163 flags := r.readInt() 164 dupok := flags&1 != 0 165 local := flags&2 != 0 166 makeTypelink := flags&4 != 0 167 size := r.readInt() 168 typ := r.readSymIndex() 169 data := r.readData() 170 nreloc := r.readInt() 171 pkg := objabi.PathToPrefix(r.lib.Pkg) 172 isdup := false 173 174 var dup *Symbol 175 if s.Type != 0 && s.Type != SXREF { 176 if (t == SDATA || t == SBSS || t == SNOPTRBSS) && len(data) == 0 && nreloc == 0 { 177 if s.Size < int64(size) { 178 s.Size = int64(size) 179 } 180 if typ != nil && s.Gotype == nil { 181 s.Gotype = typ 182 } 183 return 184 } 185 186 if (s.Type == SDATA || s.Type == SBSS || s.Type == SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 { 187 goto overwrite 188 } 189 if s.Type != SBSS && s.Type != SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() { 190 log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn) 191 } 192 if len(s.P) > 0 { 193 dup = s 194 s = r.dupSym 195 isdup = true 196 } 197 } 198 199 overwrite: 200 s.File = pkg 201 if dupok { 202 s.Attr |= AttrDuplicateOK 203 } 204 if t == SXREF { 205 log.Fatalf("bad sxref") 206 } 207 if t == 0 { 208 log.Fatalf("missing type for %s in %s", s.Name, r.pn) 209 } 210 if t == SBSS && (s.Type == SRODATA || s.Type == SNOPTRBSS) { 211 t = s.Type 212 } 213 s.Type = t 214 if s.Size < int64(size) { 215 s.Size = int64(size) 216 } 217 s.Attr.Set(AttrLocal, local) 218 s.Attr.Set(AttrMakeTypelink, makeTypelink) 219 if typ != nil { 220 s.Gotype = typ 221 } 222 if isdup && typ != nil { // if bss sym defined multiple times, take type from any one def 223 dup.Gotype = typ 224 } 225 s.P = data 226 if nreloc > 0 { 227 s.R = r.reloc[:nreloc:nreloc] 228 if !isdup { 229 r.reloc = r.reloc[nreloc:] 230 } 231 232 for i := 0; i < nreloc; i++ { 233 s.R[i] = Reloc{ 234 Off: r.readInt32(), 235 Siz: r.readUint8(), 236 Type: objabi.RelocType(r.readInt32()), 237 Add: r.readInt64(), 238 Sym: r.readSymIndex(), 239 } 240 } 241 } 242 243 if s.Type == STEXT { 244 s.FuncInfo = new(FuncInfo) 245 pc := s.FuncInfo 246 247 pc.Args = r.readInt32() 248 pc.Locals = r.readInt32() 249 if r.readUint8() != 0 { 250 s.Attr |= AttrNoSplit 251 } 252 flags := r.readInt() 253 if flags&(1<<2) != 0 { 254 s.Attr |= AttrReflectMethod 255 } 256 n := r.readInt() 257 pc.Autom = r.autom[:n:n] 258 if !isdup { 259 r.autom = r.autom[n:] 260 } 261 262 for i := 0; i < n; i++ { 263 pc.Autom[i] = Auto{ 264 Asym: r.readSymIndex(), 265 Aoffset: r.readInt32(), 266 Name: r.readInt16(), 267 Gotype: r.readSymIndex(), 268 } 269 } 270 271 pc.Pcsp.P = r.readData() 272 pc.Pcfile.P = r.readData() 273 pc.Pcline.P = r.readData() 274 pc.Pcinline.P = r.readData() 275 n = r.readInt() 276 pc.Pcdata = r.pcdata[:n:n] 277 if !isdup { 278 r.pcdata = r.pcdata[n:] 279 } 280 for i := 0; i < n; i++ { 281 pc.Pcdata[i].P = r.readData() 282 } 283 n = r.readInt() 284 pc.Funcdata = r.funcdata[:n:n] 285 pc.Funcdataoff = r.funcdataoff[:n:n] 286 if !isdup { 287 r.funcdata = r.funcdata[n:] 288 r.funcdataoff = r.funcdataoff[n:] 289 } 290 for i := 0; i < n; i++ { 291 pc.Funcdata[i] = r.readSymIndex() 292 } 293 for i := 0; i < n; i++ { 294 pc.Funcdataoff[i] = r.readInt64() 295 } 296 n = r.readInt() 297 pc.File = r.file[:n:n] 298 if !isdup { 299 r.file = r.file[n:] 300 } 301 for i := 0; i < n; i++ { 302 pc.File[i] = r.readSymIndex() 303 } 304 n = r.readInt() 305 pc.InlTree = make([]InlinedCall, n) 306 for i := 0; i < n; i++ { 307 pc.InlTree[i].Parent = r.readInt32() 308 pc.InlTree[i].File = r.readSymIndex() 309 pc.InlTree[i].Line = r.readInt32() 310 pc.InlTree[i].Func = r.readSymIndex() 311 } 312 313 if !dupok { 314 if s.Attr.OnList() { 315 log.Fatalf("symbol %s listed multiple times", s.Name) 316 } 317 s.Attr |= AttrOnList 318 r.lib.textp = append(r.lib.textp, s) 319 } else { 320 // there may ba a dup in another package 321 // put into a temp list and add to text later 322 if !isdup { 323 r.lib.dupTextSyms = append(r.lib.dupTextSyms, s) 324 } else { 325 r.lib.dupTextSyms = append(r.lib.dupTextSyms, dup) 326 } 327 } 328 } 329 if s.Type == SDWARFINFO { 330 r.patchDWARFName(s) 331 } 332 } 333 334 func (r *objReader) patchDWARFName(s *Symbol) { 335 // This is kind of ugly. Really the package name should not 336 // even be included here. 337 if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION { 338 return 339 } 340 e := bytes.IndexByte(s.P, 0) 341 if e == -1 { 342 return 343 } 344 p := bytes.Index(s.P[:e], emptyPkg) 345 if p == -1 { 346 return 347 } 348 pkgprefix := []byte(objabi.PathToPrefix(r.lib.Pkg) + ".") 349 patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1) 350 351 s.P = append(patched, s.P[e:]...) 352 delta := int64(len(s.P)) - s.Size 353 s.Size = int64(len(s.P)) 354 for i := range s.R { 355 r := &s.R[i] 356 if r.Off > int32(e) { 357 r.Off += int32(delta) 358 } 359 } 360 } 361 362 func (r *objReader) readFull(b []byte) { 363 _, err := io.ReadFull(r.rd, b) 364 if err != nil { 365 log.Fatalf("%s: error reading %s", r.pn, err) 366 } 367 } 368 369 func (r *objReader) readRef() { 370 if c, err := r.rd.ReadByte(); c != symPrefix || err != nil { 371 log.Fatalf("readSym out of sync") 372 } 373 name := r.readSymName() 374 v := r.readInt() 375 if v != 0 && v != 1 { 376 log.Fatalf("invalid symbol version for %q: %d", name, v) 377 } 378 if v == 1 { 379 v = r.localSymVersion 380 } 381 s := r.ctxt.Syms.Lookup(name, v) 382 r.refs = append(r.refs, s) 383 384 if s == nil || v != 0 { 385 return 386 } 387 if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 { 388 x, err := strconv.ParseUint(s.Name[5:], 16, 64) 389 if err != nil { 390 log.Panicf("failed to parse $-symbol %s: %v", s.Name, err) 391 } 392 s.Type = SRODATA 393 s.Attr |= AttrLocal 394 switch s.Name[:5] { 395 case "$f32.": 396 if uint64(uint32(x)) != x { 397 log.Panicf("$-symbol %s too large: %d", s.Name, x) 398 } 399 Adduint32(r.ctxt, s, uint32(x)) 400 case "$f64.", "$i64.": 401 Adduint64(r.ctxt, s, x) 402 default: 403 log.Panicf("unrecognized $-symbol: %s", s.Name) 404 } 405 s.Attr.Set(AttrReachable, false) 406 } 407 if strings.HasPrefix(s.Name, "runtime.gcbits.") { 408 s.Attr |= AttrLocal 409 } 410 } 411 412 func (r *objReader) readInt64() int64 { 413 uv := uint64(0) 414 for shift := uint(0); ; shift += 7 { 415 if shift >= 64 { 416 log.Fatalf("corrupt input") 417 } 418 c, err := r.rd.ReadByte() 419 if err != nil { 420 log.Fatalln("error reading input: ", err) 421 } 422 uv |= uint64(c&0x7F) << shift 423 if c&0x80 == 0 { 424 break 425 } 426 } 427 428 return int64(uv>>1) ^ (int64(uv<<63) >> 63) 429 } 430 431 func (r *objReader) readInt() int { 432 n := r.readInt64() 433 if int64(int(n)) != n { 434 log.Panicf("%v out of range for int", n) 435 } 436 return int(n) 437 } 438 439 func (r *objReader) readInt32() int32 { 440 n := r.readInt64() 441 if int64(int32(n)) != n { 442 log.Panicf("%v out of range for int32", n) 443 } 444 return int32(n) 445 } 446 447 func (r *objReader) readInt16() int16 { 448 n := r.readInt64() 449 if int64(int16(n)) != n { 450 log.Panicf("%v out of range for int16", n) 451 } 452 return int16(n) 453 } 454 455 func (r *objReader) readUint8() uint8 { 456 n := r.readInt64() 457 if int64(uint8(n)) != n { 458 log.Panicf("%v out of range for uint8", n) 459 } 460 return uint8(n) 461 } 462 463 func (r *objReader) readString() string { 464 n := r.readInt() 465 if cap(r.rdBuf) < n { 466 r.rdBuf = make([]byte, 2*n) 467 } 468 r.readFull(r.rdBuf[:n]) 469 return string(r.rdBuf[:n]) 470 } 471 472 func (r *objReader) readData() []byte { 473 n := r.readInt() 474 p := r.data[:n:n] 475 r.data = r.data[n:] 476 return p 477 } 478 479 // readSymName reads a symbol name, replacing all "". with pkg. 480 func (r *objReader) readSymName() string { 481 pkg := objabi.PathToPrefix(r.lib.Pkg) 482 n := r.readInt() 483 if n == 0 { 484 r.readInt64() 485 return "" 486 } 487 if cap(r.rdBuf) < n { 488 r.rdBuf = make([]byte, 2*n) 489 } 490 origName, err := r.rd.Peek(n) 491 if err == bufio.ErrBufferFull { 492 // Long symbol names are rare but exist. One source is type 493 // symbols for types with long string forms. See #15104. 494 origName = make([]byte, n) 495 r.readFull(origName) 496 } else if err != nil { 497 log.Fatalf("%s: error reading symbol: %v", r.pn, err) 498 } 499 adjName := r.rdBuf[:0] 500 for { 501 i := bytes.Index(origName, emptyPkg) 502 if i == -1 { 503 s := string(append(adjName, origName...)) 504 // Read past the peeked origName, now that we're done with it, 505 // using the rfBuf (also no longer used) as the scratch space. 506 // TODO: use bufio.Reader.Discard if available instead? 507 if err == nil { 508 r.readFull(r.rdBuf[:n]) 509 } 510 r.rdBuf = adjName[:0] // in case 2*n wasn't enough 511 512 if Buildmode == BuildmodeShared || *FlagLinkshared { 513 // These types are included in the symbol 514 // table when dynamically linking. To keep 515 // binary size down, we replace the names 516 // with SHA-1 prefixes. 517 // 518 // Keep the type.. prefix, which parts of the 519 // linker (like the DWARF generator) know means 520 // the symbol is not decodable. 521 // 522 // Leave type.runtime. symbols alone, because 523 // other parts of the linker manipulates them, 524 // and also symbols whose names would not be 525 // shortened by this process. 526 if len(s) > 14 && strings.HasPrefix(s, "type.") && !strings.HasPrefix(s, "type.runtime.") { 527 hash := sha1.Sum([]byte(s)) 528 prefix := "type." 529 if s[5] == '.' { 530 prefix = "type.." 531 } 532 s = prefix + base64.StdEncoding.EncodeToString(hash[:6]) 533 } 534 } 535 return s 536 } 537 adjName = append(adjName, origName[:i]...) 538 adjName = append(adjName, pkg...) 539 adjName = append(adjName, '.') 540 origName = origName[i+len(emptyPkg):] 541 } 542 } 543 544 // Reads the index of a symbol reference and resolves it to a symbol 545 func (r *objReader) readSymIndex() *Symbol { 546 i := r.readInt() 547 return r.refs[i] 548 }