github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/objfile/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 objfile reads Go object files for the Go linker, cmd/link. 6 // 7 // This package is similar to cmd/internal/objfile which also reads 8 // Go object files. 9 package objfile 10 11 import ( 12 "bufio" 13 "bytes" 14 "github.com/gagliardetto/golang-go/cmd/internal/bio" 15 "github.com/gagliardetto/golang-go/cmd/internal/dwarf" 16 "github.com/gagliardetto/golang-go/cmd/internal/obj" 17 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 18 "github.com/gagliardetto/golang-go/cmd/internal/sys" 19 "github.com/gagliardetto/golang-go/cmd/link/internal/sym" 20 "fmt" 21 "io" 22 "log" 23 "os" 24 "strconv" 25 "strings" 26 "unsafe" 27 ) 28 29 const ( 30 startmagic = "\x00go114ld" 31 endmagic = "\xffgo114ld" 32 ) 33 34 var emptyPkg = []byte(`"".`) 35 36 // objReader reads Go object files. 37 type objReader struct { 38 rd *bio.Reader 39 arch *sys.Arch 40 syms *sym.Symbols 41 lib *sym.Library 42 unit *sym.CompilationUnit 43 pn string 44 dupSym *sym.Symbol 45 localSymVersion int 46 flags int 47 strictDupMsgs int 48 dataSize int 49 50 // rdBuf is used by readString and readSymName as scratch for reading strings. 51 rdBuf []byte 52 53 // List of symbol references for the file being read. 54 refs []*sym.Symbol 55 data []byte 56 reloc []sym.Reloc 57 pcdata []sym.Pcdata 58 funcdata []*sym.Symbol 59 funcdataoff []int64 60 file []*sym.Symbol 61 pkgpref string // objabi.PathToPrefix(r.lib.Pkg) + "." 62 63 roObject []byte // from read-only mmap of object file (may be nil) 64 roOffset int64 // offset into readonly object data examined so far 65 66 dataReadOnly bool // whether data is backed by read-only memory 67 } 68 69 // Flags to enable optional behavior during object loading/reading. 70 71 const ( 72 NoFlag int = iota 73 74 // Sanity-check duplicate symbol contents, issuing warning 75 // when duplicates have different lengths or contents. 76 StrictDupsWarnFlag 77 78 // Similar to StrictDupsWarnFlag, but issue fatal error. 79 StrictDupsErrFlag 80 ) 81 82 // Load loads an object file f into library lib. 83 // The symbols loaded are added to syms. 84 func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) int { 85 start := f.Offset() 86 roObject := f.SliceRO(uint64(length)) 87 if roObject != nil { 88 f.MustSeek(int64(-length), os.SEEK_CUR) 89 } 90 r := &objReader{ 91 rd: f, 92 lib: lib, 93 unit: unit, 94 arch: arch, 95 syms: syms, 96 pn: pn, 97 dupSym: &sym.Symbol{Name: ".dup"}, 98 localSymVersion: syms.IncVersion(), 99 flags: flags, 100 roObject: roObject, 101 pkgpref: objabi.PathToPrefix(lib.Pkg) + ".", 102 } 103 r.loadObjFile() 104 if roObject != nil { 105 if r.roOffset != length { 106 log.Fatalf("%s: unexpected end at %d, want %d", pn, r.roOffset, start+length) 107 } 108 r.rd.MustSeek(int64(length), os.SEEK_CUR) 109 } else if f.Offset() != start+length { 110 log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length) 111 } 112 return r.strictDupMsgs 113 } 114 115 func (r *objReader) loadObjFile() { 116 // Magic header 117 var buf [8]uint8 118 r.readFull(buf[:]) 119 if string(buf[:]) != startmagic { 120 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]) 121 } 122 123 // Version 124 c, err := r.readByte() 125 if err != nil || c != 1 { 126 log.Fatalf("%s: invalid file version number %d", r.pn, c) 127 } 128 129 // Autolib 130 for { 131 lib := r.readString() 132 if lib == "" { 133 break 134 } 135 r.lib.ImportStrings = append(r.lib.ImportStrings, lib) 136 } 137 138 // DWARF strings 139 count := r.readInt() 140 r.unit.DWARFFileTable = make([]string, count) 141 for i := 0; i < count; i++ { 142 // TODO: This should probably be a call to mkROString. 143 r.unit.DWARFFileTable[i] = r.readString() 144 } 145 146 // Symbol references 147 r.refs = []*sym.Symbol{nil} // zeroth ref is nil 148 for { 149 c, err := r.peek(1) 150 if err != nil { 151 log.Fatalf("%s: peeking: %v", r.pn, err) 152 } 153 if c[0] == 0xff { 154 r.readByte() 155 break 156 } 157 r.readRef() 158 } 159 160 // Lengths 161 r.readSlices() 162 163 // Data section 164 err = r.readDataSection() 165 if err != nil { 166 log.Fatalf("%s: error reading %s", r.pn, err) 167 } 168 169 // Defined symbols 170 for { 171 c, err := r.peek(1) 172 if err != nil { 173 log.Fatalf("%s: peeking: %v", r.pn, err) 174 } 175 if c[0] == 0xff { 176 break 177 } 178 r.readSym() 179 } 180 181 // Magic footer 182 buf = [8]uint8{} 183 r.readFull(buf[:]) 184 if string(buf[:]) != endmagic { 185 log.Fatalf("%s: invalid file end", r.pn) 186 } 187 } 188 189 func (r *objReader) readSlices() { 190 r.dataSize = r.readInt() 191 n := r.readInt() 192 r.reloc = make([]sym.Reloc, n) 193 n = r.readInt() 194 r.pcdata = make([]sym.Pcdata, n) 195 _ = r.readInt() // TODO: remove on next object file rev (autom count) 196 n = r.readInt() 197 r.funcdata = make([]*sym.Symbol, n) 198 r.funcdataoff = make([]int64, n) 199 n = r.readInt() 200 r.file = make([]*sym.Symbol, n) 201 } 202 203 func (r *objReader) readDataSection() (err error) { 204 if r.roObject != nil { 205 r.data, r.dataReadOnly, err = 206 r.roObject[r.roOffset:r.roOffset+int64(r.dataSize)], true, nil 207 r.roOffset += int64(r.dataSize) 208 return 209 } 210 r.data, r.dataReadOnly, err = r.rd.Slice(uint64(r.dataSize)) 211 return 212 } 213 214 // Symbols are prefixed so their content doesn't get confused with the magic footer. 215 const symPrefix = 0xfe 216 217 func (r *objReader) readSym() { 218 var c byte 219 var err error 220 if c, err = r.readByte(); c != symPrefix || err != nil { 221 log.Fatalln("readSym out of sync") 222 } 223 if c, err = r.readByte(); err != nil { 224 log.Fatalln("error reading input: ", err) 225 } 226 t := sym.AbiSymKindToSymKind[c] 227 s := r.readSymIndex() 228 flags := r.readInt() 229 dupok := flags&1 != 0 230 local := flags&2 != 0 231 makeTypelink := flags&4 != 0 232 size := r.readInt() 233 typ := r.readSymIndex() 234 data := r.readData() 235 nreloc := r.readInt() 236 isdup := false 237 238 var dup *sym.Symbol 239 if s.Type != 0 && s.Type != sym.SXREF { 240 if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 { 241 if s.Size < int64(size) { 242 s.Size = int64(size) 243 } 244 if typ != nil && s.Gotype == nil { 245 s.Gotype = typ 246 } 247 return 248 } 249 250 if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 { 251 goto overwrite 252 } 253 if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() { 254 log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn) 255 } 256 if len(s.P) > 0 { 257 dup = s 258 s = r.dupSym 259 isdup = true 260 } 261 } 262 263 overwrite: 264 s.File = r.pkgpref[:len(r.pkgpref)-1] 265 s.Unit = r.unit 266 if dupok { 267 s.Attr |= sym.AttrDuplicateOK 268 } 269 if t == sym.SXREF { 270 log.Fatalf("bad sxref") 271 } 272 if t == 0 { 273 log.Fatalf("missing type for %s in %s", s.Name, r.pn) 274 } 275 if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) { 276 t = s.Type 277 } 278 s.Type = t 279 if s.Size < int64(size) { 280 s.Size = int64(size) 281 } 282 s.Attr.Set(sym.AttrLocal, local) 283 s.Attr.Set(sym.AttrMakeTypelink, makeTypelink) 284 if typ != nil { 285 s.Gotype = typ 286 } 287 if isdup && typ != nil { // if bss sym defined multiple times, take type from any one def 288 dup.Gotype = typ 289 } 290 s.P = data 291 s.Attr.Set(sym.AttrReadOnly, r.dataReadOnly) 292 if nreloc > 0 { 293 s.R = r.reloc[:nreloc:nreloc] 294 if !isdup { 295 r.reloc = r.reloc[nreloc:] 296 } 297 298 for i := 0; i < nreloc; i++ { 299 s.R[i] = sym.Reloc{ 300 Off: r.readInt32(), 301 Siz: r.readUint8(), 302 Type: objabi.RelocType(r.readInt32()), 303 Add: r.readInt64(), 304 Sym: r.readSymIndex(), 305 } 306 } 307 } 308 309 if s.Type == sym.STEXT { 310 s.FuncInfo = new(sym.FuncInfo) 311 pc := s.FuncInfo 312 313 pc.Args = r.readInt32() 314 pc.Locals = r.readInt32() 315 if r.readUint8() != 0 { 316 s.Attr |= sym.AttrNoSplit 317 } 318 flags := r.readInt() 319 if flags&(1<<2) != 0 { 320 s.Attr |= sym.AttrReflectMethod 321 } 322 if flags&(1<<3) != 0 { 323 s.Attr |= sym.AttrShared 324 } 325 if flags&(1<<4) != 0 { 326 s.Attr |= sym.AttrTopFrame 327 } 328 n := r.readInt() 329 if n != 0 { 330 log.Fatalf("stale object file: autom count nonzero") 331 } 332 333 pc.Pcsp.P = r.readData() 334 pc.Pcfile.P = r.readData() 335 pc.Pcline.P = r.readData() 336 pc.Pcinline.P = r.readData() 337 n = r.readInt() 338 pc.Pcdata = r.pcdata[:n:n] 339 if !isdup { 340 r.pcdata = r.pcdata[n:] 341 } 342 for i := 0; i < n; i++ { 343 pc.Pcdata[i].P = r.readData() 344 } 345 n = r.readInt() 346 pc.Funcdata = r.funcdata[:n:n] 347 pc.Funcdataoff = r.funcdataoff[:n:n] 348 if !isdup { 349 r.funcdata = r.funcdata[n:] 350 r.funcdataoff = r.funcdataoff[n:] 351 } 352 for i := 0; i < n; i++ { 353 pc.Funcdata[i] = r.readSymIndex() 354 } 355 for i := 0; i < n; i++ { 356 pc.Funcdataoff[i] = r.readInt64() 357 } 358 n = r.readInt() 359 pc.File = r.file[:n:n] 360 if !isdup { 361 r.file = r.file[n:] 362 } 363 for i := 0; i < n; i++ { 364 pc.File[i] = r.readSymIndex() 365 } 366 n = r.readInt() 367 pc.InlTree = make([]sym.InlinedCall, n) 368 for i := 0; i < n; i++ { 369 pc.InlTree[i].Parent = r.readInt32() 370 pc.InlTree[i].File = r.readSymIndex() 371 pc.InlTree[i].Line = r.readInt32() 372 pc.InlTree[i].Func = r.readSymIndex().Name 373 pc.InlTree[i].ParentPC = r.readInt32() 374 } 375 376 if !dupok { 377 if s.Attr.OnList() { 378 log.Fatalf("symbol %s listed multiple times", s.Name) 379 } 380 s.Attr |= sym.AttrOnList 381 r.lib.Textp = append(r.lib.Textp, s) 382 } else { 383 // there may ba a dup in another package 384 // put into a temp list and add to text later 385 if !isdup { 386 r.lib.DupTextSyms = append(r.lib.DupTextSyms, s) 387 } else { 388 r.lib.DupTextSyms = append(r.lib.DupTextSyms, dup) 389 } 390 } 391 } 392 if s.Type == sym.SDWARFINFO { 393 r.patchDWARFName(s) 394 } 395 396 if isdup && r.flags&(StrictDupsWarnFlag|StrictDupsErrFlag) != 0 { 397 // Compare the just-read symbol with the previously read 398 // symbol of the same name, verifying that they have the same 399 // payload. If not, issue a warning and possibly an error. 400 if !bytes.Equal(s.P, dup.P) { 401 reason := "same length but different contents" 402 if len(s.P) != len(dup.P) { 403 reason = fmt.Sprintf("new length %d != old length %d", 404 len(data), len(dup.P)) 405 } 406 fmt.Fprintf(os.Stderr, "github.com/gagliardetto/golang-go/cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Unit.Lib, reason) 407 408 // For the moment, whitelist DWARF subprogram DIEs for 409 // auto-generated wrapper functions. What seems to happen 410 // here is that we get different line numbers on formal 411 // params; I am guessing that the pos is being inherited 412 // from the spot where the wrapper is needed. 413 whitelist := (strings.HasPrefix(dup.Name, "go.info.go.interface") || 414 strings.HasPrefix(dup.Name, "go.info.go.builtin") || 415 strings.HasPrefix(dup.Name, "go.isstmt.go.builtin") || 416 strings.HasPrefix(dup.Name, "go.debuglines")) 417 if !whitelist { 418 r.strictDupMsgs++ 419 } 420 } 421 } 422 } 423 424 func (r *objReader) patchDWARFName(s *sym.Symbol) { 425 // This is kind of ugly. Really the package name should not 426 // even be included here. 427 if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION { 428 return 429 } 430 e := bytes.IndexByte(s.P, 0) 431 if e == -1 { 432 return 433 } 434 p := bytes.Index(s.P[:e], emptyPkg) 435 if p == -1 { 436 return 437 } 438 pkgprefix := []byte(r.pkgpref) 439 patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1) 440 441 s.P = append(patched, s.P[e:]...) 442 delta := int64(len(s.P)) - s.Size 443 s.Size = int64(len(s.P)) 444 for i := range s.R { 445 r := &s.R[i] 446 if r.Off > int32(e) { 447 r.Off += int32(delta) 448 } 449 } 450 } 451 452 func (r *objReader) readFull(b []byte) { 453 if r.roObject != nil { 454 copy(b, r.roObject[r.roOffset:]) 455 r.roOffset += int64(len(b)) 456 return 457 } 458 _, err := io.ReadFull(r.rd, b) 459 if err != nil { 460 log.Fatalf("%s: error reading %s", r.pn, err) 461 } 462 } 463 464 func (r *objReader) readByte() (byte, error) { 465 if r.roObject != nil { 466 b := r.roObject[r.roOffset] 467 r.roOffset++ 468 return b, nil 469 } 470 return r.rd.ReadByte() 471 } 472 473 func (r *objReader) peek(n int) ([]byte, error) { 474 if r.roObject != nil { 475 return r.roObject[r.roOffset : r.roOffset+int64(n)], nil 476 } 477 return r.rd.Peek(n) 478 } 479 480 func (r *objReader) readRef() { 481 if c, err := r.readByte(); c != symPrefix || err != nil { 482 log.Fatalf("readSym out of sync") 483 } 484 name := r.readSymName() 485 var v int 486 if abi := r.readInt(); abi == -1 { 487 // Static 488 v = r.localSymVersion 489 } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 { 490 // Note that data symbols are "ABI0", which maps to version 0. 491 v = abiver 492 } else { 493 log.Fatalf("invalid symbol ABI for %q: %d", name, abi) 494 } 495 s := r.syms.Lookup(name, v) 496 r.refs = append(r.refs, s) 497 498 if s == nil || v == r.localSymVersion { 499 return 500 } 501 if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 { 502 x, err := strconv.ParseUint(s.Name[5:], 16, 64) 503 if err != nil { 504 log.Panicf("failed to parse $-symbol %s: %v", s.Name, err) 505 } 506 s.Type = sym.SRODATA 507 s.Attr |= sym.AttrLocal 508 switch s.Name[:5] { 509 case "$f32.": 510 if uint64(uint32(x)) != x { 511 log.Panicf("$-symbol %s too large: %d", s.Name, x) 512 } 513 s.AddUint32(r.arch, uint32(x)) 514 case "$f64.", "$i64.": 515 s.AddUint64(r.arch, x) 516 default: 517 log.Panicf("unrecognized $-symbol: %s", s.Name) 518 } 519 s.Attr.Set(sym.AttrReachable, false) 520 } 521 if strings.HasPrefix(s.Name, "runtime.gcbits.") { 522 s.Attr |= sym.AttrLocal 523 } 524 } 525 526 func (r *objReader) readInt64() int64 { 527 uv := uint64(0) 528 for shift := uint(0); ; shift += 7 { 529 if shift >= 64 { 530 log.Fatalf("corrupt input") 531 } 532 c, err := r.readByte() 533 if err != nil { 534 log.Fatalln("error reading input: ", err) 535 } 536 uv |= uint64(c&0x7F) << shift 537 if c&0x80 == 0 { 538 break 539 } 540 } 541 542 return int64(uv>>1) ^ (int64(uv<<63) >> 63) 543 } 544 545 func (r *objReader) readInt() int { 546 n := r.readInt64() 547 if int64(int(n)) != n { 548 log.Panicf("%v out of range for int", n) 549 } 550 return int(n) 551 } 552 553 func (r *objReader) readInt32() int32 { 554 n := r.readInt64() 555 if int64(int32(n)) != n { 556 log.Panicf("%v out of range for int32", n) 557 } 558 return int32(n) 559 } 560 561 func (r *objReader) readInt16() int16 { 562 n := r.readInt64() 563 if int64(int16(n)) != n { 564 log.Panicf("%v out of range for int16", n) 565 } 566 return int16(n) 567 } 568 569 func (r *objReader) readUint8() uint8 { 570 n := r.readInt64() 571 if int64(uint8(n)) != n { 572 log.Panicf("%v out of range for uint8", n) 573 } 574 return uint8(n) 575 } 576 577 func (r *objReader) readString() string { 578 n := r.readInt() 579 if cap(r.rdBuf) < n { 580 r.rdBuf = make([]byte, 2*n) 581 } 582 r.readFull(r.rdBuf[:n]) 583 return string(r.rdBuf[:n]) 584 } 585 586 func (r *objReader) readData() []byte { 587 n := r.readInt() 588 p := r.data[:n:n] 589 r.data = r.data[n:] 590 return p 591 } 592 593 type stringHeader struct { 594 str unsafe.Pointer 595 len int 596 } 597 598 func mkROString(rodata []byte) string { 599 if len(rodata) == 0 { 600 return "" 601 } 602 ss := stringHeader{str: unsafe.Pointer(&rodata[0]), len: len(rodata)} 603 s := *(*string)(unsafe.Pointer(&ss)) 604 return s 605 } 606 607 // readSymName reads a symbol name, replacing all "". with pkg. 608 func (r *objReader) readSymName() string { 609 n := r.readInt() 610 if n == 0 { 611 r.readInt64() 612 return "" 613 } 614 if cap(r.rdBuf) < n { 615 r.rdBuf = make([]byte, 2*n) 616 } 617 sOffset := r.roOffset 618 origName, err := r.peek(n) 619 if err == bufio.ErrBufferFull { 620 // Long symbol names are rare but exist. One source is type 621 // symbols for types with long string forms. See #15104. 622 origName = make([]byte, n) 623 r.readFull(origName) 624 } else if err != nil { 625 log.Fatalf("%s: error reading symbol: %v", r.pn, err) 626 } 627 adjName := r.rdBuf[:0] 628 nPkgRefs := 0 629 for { 630 i := bytes.Index(origName, emptyPkg) 631 if i == -1 { 632 var s string 633 if r.roObject != nil && nPkgRefs == 0 { 634 s = mkROString(r.roObject[sOffset : sOffset+int64(n)]) 635 } else { 636 s = string(append(adjName, origName...)) 637 } 638 // Read past the peeked origName, now that we're done with it, 639 // using the rfBuf (also no longer used) as the scratch space. 640 // TODO: use bufio.Reader.Discard if available instead? 641 if err == nil { 642 r.readFull(r.rdBuf[:n]) 643 } 644 r.rdBuf = adjName[:0] // in case 2*n wasn't enough 645 return s 646 } 647 nPkgRefs++ 648 adjName = append(adjName, origName[:i]...) 649 adjName = append(adjName, r.pkgpref[:len(r.pkgpref)-1]...) 650 adjName = append(adjName, '.') 651 origName = origName[i+len(emptyPkg):] 652 } 653 } 654 655 // Reads the index of a symbol reference and resolves it to a symbol 656 func (r *objReader) readSymIndex() *sym.Symbol { 657 i := r.readInt() 658 return r.refs[i] 659 }