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