github.com/bir3/gocompiler@v0.9.2202/src/cmd/internal/goobj/objfile.go (about) 1 // Copyright 2019 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 // This package defines the Go object file format, and provide "low-level" functions 6 // for reading and writing object files. 7 8 // The object file is understood by the compiler, assembler, linker, and tools. They 9 // have "high level" code that operates on object files, handling application-specific 10 // logics, and use this package for the actual reading and writing. Specifically, the 11 // code below: 12 // 13 // - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile) 14 // - cmd/internal/objfile/goobj.go (used cmd/nm, cmd/objdump) 15 // - cmd/link/internal/loader package (used by cmd/link) 16 // 17 // If the object file format changes, they may (or may not) need to change. 18 19 package goobj 20 21 import ( 22 "github.com/bir3/gocompiler/src/cmd/internal/bio" 23 "encoding/binary" 24 "errors" 25 "fmt" 26 "unsafe" 27 ) 28 29 // New object file format. 30 // 31 // Header struct { 32 // Magic [...]byte // "\x00go120ld" 33 // Fingerprint [8]byte 34 // Flags uint32 35 // Offsets [...]uint32 // byte offset of each block below 36 // } 37 // 38 // Strings [...]struct { 39 // Data [...]byte 40 // } 41 // 42 // Autolib [...]struct { // imported packages (for file loading) 43 // Pkg string 44 // Fingerprint [8]byte 45 // } 46 // 47 // PkgIndex [...]string // referenced packages by index 48 // 49 // Files [...]string 50 // 51 // SymbolDefs [...]struct { 52 // Name string 53 // ABI uint16 54 // Type uint8 55 // Flag uint8 56 // Flag2 uint8 57 // Size uint32 58 // } 59 // Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions 60 // ... // same as SymbolDefs 61 // } 62 // HashedDefs [...]struct { // hashed (content-addressable) symbol definitions 63 // ... // same as SymbolDefs 64 // } 65 // NonPkgDefs [...]struct { // non-pkg symbol definitions 66 // ... // same as SymbolDefs 67 // } 68 // NonPkgRefs [...]struct { // non-pkg symbol references 69 // ... // same as SymbolDefs 70 // } 71 // 72 // RefFlags [...]struct { // referenced symbol flags 73 // Sym symRef 74 // Flag uint8 75 // Flag2 uint8 76 // } 77 // 78 // Hash64 [...][8]byte 79 // Hash [...][N]byte 80 // 81 // RelocIndex [...]uint32 // index to Relocs 82 // AuxIndex [...]uint32 // index to Aux 83 // DataIndex [...]uint32 // offset to Data 84 // 85 // Relocs [...]struct { 86 // Off int32 87 // Size uint8 88 // Type uint16 89 // Add int64 90 // Sym symRef 91 // } 92 // 93 // Aux [...]struct { 94 // Type uint8 95 // Sym symRef 96 // } 97 // 98 // Data [...]byte 99 // 100 // // blocks only used by tools (objdump, nm) 101 // 102 // RefNames [...]struct { // referenced symbol names 103 // Sym symRef 104 // Name string 105 // // TODO: include ABI version as well? 106 // } 107 // 108 // string is encoded as is a uint32 length followed by a uint32 offset 109 // that points to the corresponding string bytes. 110 // 111 // symRef is struct { PkgIdx, SymIdx uint32 }. 112 // 113 // Slice type (e.g. []symRef) is encoded as a length prefix (uint32) 114 // followed by that number of elements. 115 // 116 // The types below correspond to the encoded data structure in the 117 // object file. 118 119 // Symbol indexing. 120 // 121 // Each symbol is referenced with a pair of indices, { PkgIdx, SymIdx }, 122 // as the symRef struct above. 123 // 124 // PkgIdx is either a predeclared index (see PkgIdxNone below) or 125 // an index of an imported package. For the latter case, PkgIdx is the 126 // index of the package in the PkgIndex array. 0 is an invalid index. 127 // 128 // SymIdx is the index of the symbol in the given package. 129 // - If PkgIdx is PkgIdxSelf, SymIdx is the index of the symbol in the 130 // SymbolDefs array. 131 // - If PkgIdx is PkgIdxHashed64, SymIdx is the index of the symbol in the 132 // Hashed64Defs array. 133 // - If PkgIdx is PkgIdxHashed, SymIdx is the index of the symbol in the 134 // HashedDefs array. 135 // - If PkgIdx is PkgIdxNone, SymIdx is the index of the symbol in the 136 // NonPkgDefs array (could naturally overflow to NonPkgRefs array). 137 // - Otherwise, SymIdx is the index of the symbol in some other package's 138 // SymbolDefs array. 139 // 140 // {0, 0} represents a nil symbol. Otherwise PkgIdx should not be 0. 141 // 142 // Hash contains the content hashes of content-addressable symbols, of 143 // which PkgIdx is PkgIdxHashed, in the same order of HashedDefs array. 144 // Hash64 is similar, for PkgIdxHashed64 symbols. 145 // 146 // RelocIndex, AuxIndex, and DataIndex contains indices/offsets to 147 // Relocs/Aux/Data blocks, one element per symbol, first for all the 148 // defined symbols, then all the defined hashed and non-package symbols, 149 // in the same order of SymbolDefs/Hashed64Defs/HashedDefs/NonPkgDefs 150 // arrays. For N total defined symbols, the array is of length N+1. The 151 // last element is the total number of relocations (aux symbols, data 152 // blocks, etc.). 153 // 154 // They can be accessed by index. For the i-th symbol, its relocations 155 // are the RelocIndex[i]-th (inclusive) to RelocIndex[i+1]-th (exclusive) 156 // elements in the Relocs array. Aux/Data are likewise. (The index is 157 // 0-based.) 158 159 // Auxiliary symbols. 160 // 161 // Each symbol may (or may not) be associated with a number of auxiliary 162 // symbols. They are described in the Aux block. See Aux struct below. 163 // Currently a symbol's Gotype, FuncInfo, and associated DWARF symbols 164 // are auxiliary symbols. 165 166 const stringRefSize = 8 // two uint32s 167 168 type FingerprintType [8]byte 169 170 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} } 171 172 // Package Index. 173 const ( 174 PkgIdxNone = (1<<31 - 1) - iota // Non-package symbols 175 PkgIdxHashed64 // Short hashed (content-addressable) symbols 176 PkgIdxHashed // Hashed (content-addressable) symbols 177 PkgIdxBuiltin // Predefined runtime symbols (ex: runtime.newobject) 178 PkgIdxSelf // Symbols defined in the current package 179 PkgIdxSpecial = PkgIdxSelf // Indices above it has special meanings 180 PkgIdxInvalid = 0 181 // The index of other referenced packages starts from 1. 182 ) 183 184 // Blocks 185 const ( 186 BlkAutolib = iota 187 BlkPkgIdx 188 BlkFile 189 BlkSymdef 190 BlkHashed64def 191 BlkHasheddef 192 BlkNonpkgdef 193 BlkNonpkgref 194 BlkRefFlags 195 BlkHash64 196 BlkHash 197 BlkRelocIdx 198 BlkAuxIdx 199 BlkDataIdx 200 BlkReloc 201 BlkAux 202 BlkData 203 BlkRefName 204 BlkEnd 205 NBlk 206 ) 207 208 // File header. 209 // TODO: probably no need to export this. 210 type Header struct { 211 Magic string 212 Fingerprint FingerprintType 213 Flags uint32 214 Offsets [NBlk]uint32 215 } 216 217 const Magic = "\x00go120ld" 218 219 func (h *Header) Write(w *Writer) { 220 w.RawString(h.Magic) 221 w.Bytes(h.Fingerprint[:]) 222 w.Uint32(h.Flags) 223 for _, x := range h.Offsets { 224 w.Uint32(x) 225 } 226 } 227 228 func (h *Header) Read(r *Reader) error { 229 b := r.BytesAt(0, len(Magic)) 230 h.Magic = string(b) 231 if h.Magic != Magic { 232 return errors.New("wrong magic, not a Go object file") 233 } 234 off := uint32(len(h.Magic)) 235 copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint))) 236 off += 8 237 h.Flags = r.uint32At(off) 238 off += 4 239 for i := range h.Offsets { 240 h.Offsets[i] = r.uint32At(off) 241 off += 4 242 } 243 return nil 244 } 245 246 func (h *Header) Size() int { 247 return len(h.Magic) + len(h.Fingerprint) + 4 + 4*len(h.Offsets) 248 } 249 250 // Autolib 251 type ImportedPkg struct { 252 Pkg string 253 Fingerprint FingerprintType 254 } 255 256 const importedPkgSize = stringRefSize + 8 257 258 func (p *ImportedPkg) Write(w *Writer) { 259 w.StringRef(p.Pkg) 260 w.Bytes(p.Fingerprint[:]) 261 } 262 263 // Symbol definition. 264 // 265 // Serialized format: 266 // 267 // Sym struct { 268 // Name string 269 // ABI uint16 270 // Type uint8 271 // Flag uint8 272 // Flag2 uint8 273 // Siz uint32 274 // Align uint32 275 // } 276 type Sym [SymSize]byte 277 278 const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4 279 280 const SymABIstatic = ^uint16(0) 281 282 const ( 283 ObjFlagShared = 1 << iota // this object is built with -shared 284 _ // was ObjFlagNeedNameExpansion 285 ObjFlagFromAssembly // object is from asm src, not go 286 ObjFlagUnlinkable // unlinkable package (linker will emit an error) 287 ) 288 289 // Sym.Flag 290 const ( 291 SymFlagDupok = 1 << iota 292 SymFlagLocal 293 SymFlagTypelink 294 SymFlagLeaf 295 SymFlagNoSplit 296 SymFlagReflectMethod 297 SymFlagGoType 298 ) 299 300 // Sym.Flag2 301 const ( 302 SymFlagUsedInIface = 1 << iota 303 SymFlagItab 304 SymFlagDict 305 SymFlagPkgInit 306 ) 307 308 // Returns the length of the name of the symbol. 309 func (s *Sym) NameLen(r *Reader) int { 310 return int(binary.LittleEndian.Uint32(s[:])) 311 } 312 313 func (s *Sym) Name(r *Reader) string { 314 len := binary.LittleEndian.Uint32(s[:]) 315 off := binary.LittleEndian.Uint32(s[4:]) 316 return r.StringAt(off, len) 317 } 318 319 func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) } 320 func (s *Sym) Type() uint8 { return s[10] } 321 func (s *Sym) Flag() uint8 { return s[11] } 322 func (s *Sym) Flag2() uint8 { return s[12] } 323 func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) } 324 func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) } 325 326 func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 } 327 func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 } 328 func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 } 329 func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 } 330 func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 } 331 func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 } 332 func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 } 333 func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 } 334 func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 } 335 func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 } 336 func (s *Sym) IsPkgInit() bool { return s.Flag2()&SymFlagPkgInit != 0 } 337 338 func (s *Sym) SetName(x string, w *Writer) { 339 binary.LittleEndian.PutUint32(s[:], uint32(len(x))) 340 binary.LittleEndian.PutUint32(s[4:], w.stringOff(x)) 341 } 342 343 func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) } 344 func (s *Sym) SetType(x uint8) { s[10] = x } 345 func (s *Sym) SetFlag(x uint8) { s[11] = x } 346 func (s *Sym) SetFlag2(x uint8) { s[12] = x } 347 func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) } 348 func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) } 349 350 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) } 351 352 // for testing 353 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) } 354 355 // Symbol reference. 356 type SymRef struct { 357 PkgIdx uint32 358 SymIdx uint32 359 } 360 361 func (s SymRef) IsZero() bool { return s == SymRef{} } 362 363 // Hash64 364 type Hash64Type [Hash64Size]byte 365 366 const Hash64Size = 8 367 368 // Hash 369 type HashType [HashSize]byte 370 371 const HashSize = 16 // truncated SHA256 372 373 // Relocation. 374 // 375 // Serialized format: 376 // 377 // Reloc struct { 378 // Off int32 379 // Siz uint8 380 // Type uint16 381 // Add int64 382 // Sym SymRef 383 // } 384 type Reloc [RelocSize]byte 385 386 const RelocSize = 4 + 1 + 2 + 8 + 8 387 388 func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) } 389 func (r *Reloc) Siz() uint8 { return r[4] } 390 func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) } 391 func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[7:])) } 392 func (r *Reloc) Sym() SymRef { 393 return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])} 394 } 395 396 func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) } 397 func (r *Reloc) SetSiz(x uint8) { r[4] = x } 398 func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) } 399 func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[7:], uint64(x)) } 400 func (r *Reloc) SetSym(x SymRef) { 401 binary.LittleEndian.PutUint32(r[15:], x.PkgIdx) 402 binary.LittleEndian.PutUint32(r[19:], x.SymIdx) 403 } 404 405 func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) { 406 r.SetOff(off) 407 r.SetSiz(size) 408 r.SetType(typ) 409 r.SetAdd(add) 410 r.SetSym(sym) 411 } 412 413 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) } 414 415 // for testing 416 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) } 417 418 // Aux symbol info. 419 // 420 // Serialized format: 421 // 422 // Aux struct { 423 // Type uint8 424 // Sym SymRef 425 // } 426 type Aux [AuxSize]byte 427 428 const AuxSize = 1 + 8 429 430 // Aux Type 431 const ( 432 AuxGotype = iota 433 AuxFuncInfo 434 AuxFuncdata 435 AuxDwarfInfo 436 AuxDwarfLoc 437 AuxDwarfRanges 438 AuxDwarfLines 439 AuxPcsp 440 AuxPcfile 441 AuxPcline 442 AuxPcinline 443 AuxPcdata 444 AuxWasmImport 445 AuxSehUnwindInfo 446 ) 447 448 func (a *Aux) Type() uint8 { return a[0] } 449 func (a *Aux) Sym() SymRef { 450 return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])} 451 } 452 453 func (a *Aux) SetType(x uint8) { a[0] = x } 454 func (a *Aux) SetSym(x SymRef) { 455 binary.LittleEndian.PutUint32(a[1:], x.PkgIdx) 456 binary.LittleEndian.PutUint32(a[5:], x.SymIdx) 457 } 458 459 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) } 460 461 // for testing 462 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) } 463 464 // Referenced symbol flags. 465 // 466 // Serialized format: 467 // 468 // RefFlags struct { 469 // Sym symRef 470 // Flag uint8 471 // Flag2 uint8 472 // } 473 type RefFlags [RefFlagsSize]byte 474 475 const RefFlagsSize = 8 + 1 + 1 476 477 func (r *RefFlags) Sym() SymRef { 478 return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])} 479 } 480 func (r *RefFlags) Flag() uint8 { return r[8] } 481 func (r *RefFlags) Flag2() uint8 { return r[9] } 482 483 func (r *RefFlags) SetSym(x SymRef) { 484 binary.LittleEndian.PutUint32(r[:], x.PkgIdx) 485 binary.LittleEndian.PutUint32(r[4:], x.SymIdx) 486 } 487 func (r *RefFlags) SetFlag(x uint8) { r[8] = x } 488 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x } 489 490 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) } 491 492 // Used to construct an artificially large array type when reading an 493 // item from the object file relocs section or aux sym section (needs 494 // to work on 32-bit as well as 64-bit). See issue 41621. 495 const huge = (1<<31 - 1) / RelocSize 496 497 // Referenced symbol name. 498 // 499 // Serialized format: 500 // 501 // RefName struct { 502 // Sym symRef 503 // Name string 504 // } 505 type RefName [RefNameSize]byte 506 507 const RefNameSize = 8 + stringRefSize 508 509 func (n *RefName) Sym() SymRef { 510 return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])} 511 } 512 func (n *RefName) Name(r *Reader) string { 513 len := binary.LittleEndian.Uint32(n[8:]) 514 off := binary.LittleEndian.Uint32(n[12:]) 515 return r.StringAt(off, len) 516 } 517 518 func (n *RefName) SetSym(x SymRef) { 519 binary.LittleEndian.PutUint32(n[:], x.PkgIdx) 520 binary.LittleEndian.PutUint32(n[4:], x.SymIdx) 521 } 522 func (n *RefName) SetName(x string, w *Writer) { 523 binary.LittleEndian.PutUint32(n[8:], uint32(len(x))) 524 binary.LittleEndian.PutUint32(n[12:], w.stringOff(x)) 525 } 526 527 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) } 528 529 type Writer struct { 530 wr *bio.Writer 531 stringMap map[string]uint32 532 off uint32 // running offset 533 534 b [8]byte // scratch space for writing bytes 535 } 536 537 func NewWriter(wr *bio.Writer) *Writer { 538 return &Writer{wr: wr, stringMap: make(map[string]uint32)} 539 } 540 541 func (w *Writer) AddString(s string) { 542 if _, ok := w.stringMap[s]; ok { 543 return 544 } 545 w.stringMap[s] = w.off 546 w.RawString(s) 547 } 548 549 func (w *Writer) stringOff(s string) uint32 { 550 off, ok := w.stringMap[s] 551 if !ok { 552 panic(fmt.Sprintf("writeStringRef: string not added: %q", s)) 553 } 554 return off 555 } 556 557 func (w *Writer) StringRef(s string) { 558 w.Uint32(uint32(len(s))) 559 w.Uint32(w.stringOff(s)) 560 } 561 562 func (w *Writer) RawString(s string) { 563 w.wr.WriteString(s) 564 w.off += uint32(len(s)) 565 } 566 567 func (w *Writer) Bytes(s []byte) { 568 w.wr.Write(s) 569 w.off += uint32(len(s)) 570 } 571 572 func (w *Writer) Uint64(x uint64) { 573 binary.LittleEndian.PutUint64(w.b[:], x) 574 w.wr.Write(w.b[:]) 575 w.off += 8 576 } 577 578 func (w *Writer) Uint32(x uint32) { 579 binary.LittleEndian.PutUint32(w.b[:4], x) 580 w.wr.Write(w.b[:4]) 581 w.off += 4 582 } 583 584 func (w *Writer) Uint16(x uint16) { 585 binary.LittleEndian.PutUint16(w.b[:2], x) 586 w.wr.Write(w.b[:2]) 587 w.off += 2 588 } 589 590 func (w *Writer) Uint8(x uint8) { 591 w.wr.WriteByte(x) 592 w.off++ 593 } 594 595 func (w *Writer) Offset() uint32 { 596 return w.off 597 } 598 599 type Reader struct { 600 b []byte // mmapped bytes, if not nil 601 readonly bool // whether b is backed with read-only memory 602 603 start uint32 604 h Header // keep block offsets 605 } 606 607 func NewReaderFromBytes(b []byte, readonly bool) *Reader { 608 r := &Reader{b: b, readonly: readonly, start: 0} 609 err := r.h.Read(r) 610 if err != nil { 611 return nil 612 } 613 return r 614 } 615 616 func (r *Reader) BytesAt(off uint32, len int) []byte { 617 if len == 0 { 618 return nil 619 } 620 end := int(off) + len 621 return r.b[int(off):end:end] 622 } 623 624 func (r *Reader) uint64At(off uint32) uint64 { 625 b := r.BytesAt(off, 8) 626 return binary.LittleEndian.Uint64(b) 627 } 628 629 func (r *Reader) int64At(off uint32) int64 { 630 return int64(r.uint64At(off)) 631 } 632 633 func (r *Reader) uint32At(off uint32) uint32 { 634 b := r.BytesAt(off, 4) 635 return binary.LittleEndian.Uint32(b) 636 } 637 638 func (r *Reader) int32At(off uint32) int32 { 639 return int32(r.uint32At(off)) 640 } 641 642 func (r *Reader) uint16At(off uint32) uint16 { 643 b := r.BytesAt(off, 2) 644 return binary.LittleEndian.Uint16(b) 645 } 646 647 func (r *Reader) uint8At(off uint32) uint8 { 648 b := r.BytesAt(off, 1) 649 return b[0] 650 } 651 652 func (r *Reader) StringAt(off uint32, len uint32) string { 653 b := r.b[off : off+len] 654 if r.readonly { 655 return toString(b) // backed by RO memory, ok to make unsafe string 656 } 657 return string(b) 658 } 659 660 func toString(b []byte) string { 661 if len(b) == 0 { 662 return "" 663 } 664 return unsafe.String(&b[0], len(b)) 665 } 666 667 func (r *Reader) StringRef(off uint32) string { 668 l := r.uint32At(off) 669 return r.StringAt(r.uint32At(off+4), l) 670 } 671 672 func (r *Reader) Fingerprint() FingerprintType { 673 return r.h.Fingerprint 674 } 675 676 func (r *Reader) Autolib() []ImportedPkg { 677 n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize 678 s := make([]ImportedPkg, n) 679 off := r.h.Offsets[BlkAutolib] 680 for i := range s { 681 s[i].Pkg = r.StringRef(off) 682 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint))) 683 off += importedPkgSize 684 } 685 return s 686 } 687 688 func (r *Reader) Pkglist() []string { 689 n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize 690 s := make([]string, n) 691 off := r.h.Offsets[BlkPkgIdx] 692 for i := range s { 693 s[i] = r.StringRef(off) 694 off += stringRefSize 695 } 696 return s 697 } 698 699 func (r *Reader) NPkg() int { 700 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize 701 } 702 703 func (r *Reader) Pkg(i int) string { 704 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize 705 return r.StringRef(off) 706 } 707 708 func (r *Reader) NFile() int { 709 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize 710 } 711 712 func (r *Reader) File(i int) string { 713 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize 714 return r.StringRef(off) 715 } 716 717 func (r *Reader) NSym() int { 718 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize 719 } 720 721 func (r *Reader) NHashed64def() int { 722 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize 723 } 724 725 func (r *Reader) NHasheddef() int { 726 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize 727 } 728 729 func (r *Reader) NNonpkgdef() int { 730 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize 731 } 732 733 func (r *Reader) NNonpkgref() int { 734 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize 735 } 736 737 // SymOff returns the offset of the i-th symbol. 738 func (r *Reader) SymOff(i uint32) uint32 { 739 return r.h.Offsets[BlkSymdef] + uint32(i*SymSize) 740 } 741 742 // Sym returns a pointer to the i-th symbol. 743 func (r *Reader) Sym(i uint32) *Sym { 744 off := r.SymOff(i) 745 return (*Sym)(unsafe.Pointer(&r.b[off])) 746 } 747 748 // NRefFlags returns the number of referenced symbol flags. 749 func (r *Reader) NRefFlags() int { 750 return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize 751 } 752 753 // RefFlags returns a pointer to the i-th referenced symbol flags. 754 // Note: here i is not a local symbol index, just a counter. 755 func (r *Reader) RefFlags(i int) *RefFlags { 756 off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize) 757 return (*RefFlags)(unsafe.Pointer(&r.b[off])) 758 } 759 760 // Hash64 returns the i-th short hashed symbol's hash. 761 // Note: here i is the index of short hashed symbols, not all symbols 762 // (unlike other accessors). 763 func (r *Reader) Hash64(i uint32) uint64 { 764 off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size) 765 return r.uint64At(off) 766 } 767 768 // Hash returns a pointer to the i-th hashed symbol's hash. 769 // Note: here i is the index of hashed symbols, not all symbols 770 // (unlike other accessors). 771 func (r *Reader) Hash(i uint32) *HashType { 772 off := r.h.Offsets[BlkHash] + uint32(i*HashSize) 773 return (*HashType)(unsafe.Pointer(&r.b[off])) 774 } 775 776 // NReloc returns the number of relocations of the i-th symbol. 777 func (r *Reader) NReloc(i uint32) int { 778 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4) 779 return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff)) 780 } 781 782 // RelocOff returns the offset of the j-th relocation of the i-th symbol. 783 func (r *Reader) RelocOff(i uint32, j int) uint32 { 784 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4) 785 relocIdx := r.uint32At(relocIdxOff) 786 return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize) 787 } 788 789 // Reloc returns a pointer to the j-th relocation of the i-th symbol. 790 func (r *Reader) Reloc(i uint32, j int) *Reloc { 791 off := r.RelocOff(i, j) 792 return (*Reloc)(unsafe.Pointer(&r.b[off])) 793 } 794 795 // Relocs returns a pointer to the relocations of the i-th symbol. 796 func (r *Reader) Relocs(i uint32) []Reloc { 797 off := r.RelocOff(i, 0) 798 n := r.NReloc(i) 799 return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] 800 } 801 802 // NAux returns the number of aux symbols of the i-th symbol. 803 func (r *Reader) NAux(i uint32) int { 804 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4 805 return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff)) 806 } 807 808 // AuxOff returns the offset of the j-th aux symbol of the i-th symbol. 809 func (r *Reader) AuxOff(i uint32, j int) uint32 { 810 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4 811 auxIdx := r.uint32At(auxIdxOff) 812 return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize) 813 } 814 815 // Aux returns a pointer to the j-th aux symbol of the i-th symbol. 816 func (r *Reader) Aux(i uint32, j int) *Aux { 817 off := r.AuxOff(i, j) 818 return (*Aux)(unsafe.Pointer(&r.b[off])) 819 } 820 821 // Auxs returns the aux symbols of the i-th symbol. 822 func (r *Reader) Auxs(i uint32) []Aux { 823 off := r.AuxOff(i, 0) 824 n := r.NAux(i) 825 return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n] 826 } 827 828 // DataOff returns the offset of the i-th symbol's data. 829 func (r *Reader) DataOff(i uint32) uint32 { 830 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 831 return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff) 832 } 833 834 // DataSize returns the size of the i-th symbol's data. 835 func (r *Reader) DataSize(i uint32) int { 836 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 837 return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff)) 838 } 839 840 // Data returns the i-th symbol's data. 841 func (r *Reader) Data(i uint32) []byte { 842 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 843 base := r.h.Offsets[BlkData] 844 off := r.uint32At(dataIdxOff) 845 end := r.uint32At(dataIdxOff + 4) 846 return r.BytesAt(base+off, int(end-off)) 847 } 848 849 // DataString returns the i-th symbol's data as a string. 850 func (r *Reader) DataString(i uint32) string { 851 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 852 base := r.h.Offsets[BlkData] 853 off := r.uint32At(dataIdxOff) 854 end := r.uint32At(dataIdxOff + 4) 855 return r.StringAt(base+off, end-off) 856 } 857 858 // NRefName returns the number of referenced symbol names. 859 func (r *Reader) NRefName() int { 860 return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize 861 } 862 863 // RefName returns a pointer to the i-th referenced symbol name. 864 // Note: here i is not a local symbol index, just a counter. 865 func (r *Reader) RefName(i int) *RefName { 866 off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize) 867 return (*RefName)(unsafe.Pointer(&r.b[off])) 868 } 869 870 // ReadOnly returns whether r.BytesAt returns read-only bytes. 871 func (r *Reader) ReadOnly() bool { 872 return r.readonly 873 } 874 875 // Flags returns the flag bits read from the object file header. 876 func (r *Reader) Flags() uint32 { 877 return r.h.Flags 878 } 879 880 func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 } 881 func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 } 882 func (r *Reader) Unlinkable() bool { return r.Flags()&ObjFlagUnlinkable != 0 }