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