1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package goobj
20
21 import (
22 "cmd/internal/bio"
23 "encoding/binary"
24 "errors"
25 "fmt"
26 "unsafe"
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 const stringRefSize = 8
168
169 type FingerprintType [8]byte
170
171 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
172
173
174 const (
175 PkgIdxNone = (1<<31 - 1) - iota
176 PkgIdxHashed64
177 PkgIdxHashed
178 PkgIdxBuiltin
179 PkgIdxSelf
180 PkgIdxSpecial = PkgIdxSelf
181 PkgIdxInvalid = 0
182
183 )
184
185
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
210
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) + len(h.Fingerprint) + 4 + 4*len(h.Offsets)
249 }
250
251
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
265
266
267
268
269
270
271
272
273
274
275
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
285 _
286 ObjFlagFromAssembly
287 ObjFlagUnlinkable
288 ObjFlagStd
289 )
290
291
292 const (
293 SymFlagDupok = 1 << iota
294 SymFlagLocal
295 SymFlagTypelink
296 SymFlagLeaf
297 SymFlagNoSplit
298 SymFlagReflectMethod
299 SymFlagGoType
300 )
301
302
303 const (
304 SymFlagUsedInIface = 1 << iota
305 SymFlagItab
306 SymFlagDict
307 SymFlagPkgInit
308 SymFlagLinkname
309 SymFlagABIWrapper
310 SymFlagWasmExport
311 )
312
313
314 func (s *Sym) NameLen(r *Reader) int {
315 return int(binary.LittleEndian.Uint32(s[:]))
316 }
317
318 func (s *Sym) Name(r *Reader) string {
319 len := binary.LittleEndian.Uint32(s[:])
320 off := binary.LittleEndian.Uint32(s[4:])
321 return r.StringAt(off, len)
322 }
323
324 func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
325 func (s *Sym) Type() uint8 { return s[10] }
326 func (s *Sym) Flag() uint8 { return s[11] }
327 func (s *Sym) Flag2() uint8 { return s[12] }
328 func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) }
329 func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }
330
331 func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 }
332 func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 }
333 func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 }
334 func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 }
335 func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 }
336 func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
337 func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
338 func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
339 func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
340 func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 }
341 func (s *Sym) IsPkgInit() bool { return s.Flag2()&SymFlagPkgInit != 0 }
342 func (s *Sym) IsLinkname() bool { return s.Flag2()&SymFlagLinkname != 0 }
343 func (s *Sym) ABIWrapper() bool { return s.Flag2()&SymFlagABIWrapper != 0 }
344 func (s *Sym) WasmExport() bool { return s.Flag2()&SymFlagWasmExport != 0 }
345
346 func (s *Sym) SetName(x string, w *Writer) {
347 binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
348 binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
349 }
350
351 func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) }
352 func (s *Sym) SetType(x uint8) { s[10] = x }
353 func (s *Sym) SetFlag(x uint8) { s[11] = x }
354 func (s *Sym) SetFlag2(x uint8) { s[12] = x }
355 func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) }
356 func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }
357
358 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
359
360
361 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
362
363
364 type SymRef struct {
365 PkgIdx uint32
366 SymIdx uint32
367 }
368
369 func (s SymRef) IsZero() bool { return s == SymRef{} }
370
371
372 type Hash64Type [Hash64Size]byte
373
374 const Hash64Size = 8
375
376
377 type HashType [HashSize]byte
378
379 const HashSize = 16
380
381
382
383
384
385
386
387
388
389
390
391
392 type Reloc [RelocSize]byte
393
394 const RelocSize = 4 + 1 + 2 + 8 + 8
395
396 func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) }
397 func (r *Reloc) Siz() uint8 { return r[4] }
398 func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
399 func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[7:])) }
400 func (r *Reloc) Sym() SymRef {
401 return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])}
402 }
403
404 func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
405 func (r *Reloc) SetSiz(x uint8) { r[4] = x }
406 func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
407 func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
408 func (r *Reloc) SetSym(x SymRef) {
409 binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
410 binary.LittleEndian.PutUint32(r[19:], x.SymIdx)
411 }
412
413 func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
414 r.SetOff(off)
415 r.SetSiz(size)
416 r.SetType(typ)
417 r.SetAdd(add)
418 r.SetSym(sym)
419 }
420
421 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
422
423
424 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
425
426
427
428
429
430
431
432
433
434 type Aux [AuxSize]byte
435
436 const AuxSize = 1 + 8
437
438
439 const (
440 AuxGotype = iota
441 AuxFuncInfo
442 AuxFuncdata
443 AuxDwarfInfo
444 AuxDwarfLoc
445 AuxDwarfRanges
446 AuxDwarfLines
447 AuxPcsp
448 AuxPcfile
449 AuxPcline
450 AuxPcinline
451 AuxPcdata
452 AuxWasmImport
453 AuxWasmType
454 AuxSehUnwindInfo
455 )
456
457 func (a *Aux) Type() uint8 { return a[0] }
458 func (a *Aux) Sym() SymRef {
459 return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
460 }
461
462 func (a *Aux) SetType(x uint8) { a[0] = x }
463 func (a *Aux) SetSym(x SymRef) {
464 binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
465 binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
466 }
467
468 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
469
470
471 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
472
473
474
475
476
477
478
479
480
481
482 type RefFlags [RefFlagsSize]byte
483
484 const RefFlagsSize = 8 + 1 + 1
485
486 func (r *RefFlags) Sym() SymRef {
487 return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
488 }
489 func (r *RefFlags) Flag() uint8 { return r[8] }
490 func (r *RefFlags) Flag2() uint8 { return r[9] }
491
492 func (r *RefFlags) SetSym(x SymRef) {
493 binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
494 binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
495 }
496 func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
497 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
498
499 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
500
501
502
503
504 const huge = (1<<31 - 1) / RelocSize
505
506
507
508
509
510
511
512
513
514 type RefName [RefNameSize]byte
515
516 const RefNameSize = 8 + stringRefSize
517
518 func (n *RefName) Sym() SymRef {
519 return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
520 }
521 func (n *RefName) Name(r *Reader) string {
522 len := binary.LittleEndian.Uint32(n[8:])
523 off := binary.LittleEndian.Uint32(n[12:])
524 return r.StringAt(off, len)
525 }
526
527 func (n *RefName) SetSym(x SymRef) {
528 binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
529 binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
530 }
531 func (n *RefName) SetName(x string, w *Writer) {
532 binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
533 binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
534 }
535
536 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
537
538 type Writer struct {
539 wr *bio.Writer
540 stringMap map[string]uint32
541 off uint32
542
543 b [8]byte
544 }
545
546 func NewWriter(wr *bio.Writer) *Writer {
547 return &Writer{wr: wr, stringMap: make(map[string]uint32)}
548 }
549
550 func (w *Writer) AddString(s string) {
551 if _, ok := w.stringMap[s]; ok {
552 return
553 }
554 w.stringMap[s] = w.off
555 w.RawString(s)
556 }
557
558 func (w *Writer) stringOff(s string) uint32 {
559 off, ok := w.stringMap[s]
560 if !ok {
561 panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
562 }
563 return off
564 }
565
566 func (w *Writer) StringRef(s string) {
567 w.Uint32(uint32(len(s)))
568 w.Uint32(w.stringOff(s))
569 }
570
571 func (w *Writer) RawString(s string) {
572 w.wr.WriteString(s)
573 w.off += uint32(len(s))
574 }
575
576 func (w *Writer) Bytes(s []byte) {
577 w.wr.Write(s)
578 w.off += uint32(len(s))
579 }
580
581 func (w *Writer) Uint64(x uint64) {
582 binary.LittleEndian.PutUint64(w.b[:], x)
583 w.wr.Write(w.b[:])
584 w.off += 8
585 }
586
587 func (w *Writer) Uint32(x uint32) {
588 binary.LittleEndian.PutUint32(w.b[:4], x)
589 w.wr.Write(w.b[:4])
590 w.off += 4
591 }
592
593 func (w *Writer) Uint16(x uint16) {
594 binary.LittleEndian.PutUint16(w.b[:2], x)
595 w.wr.Write(w.b[:2])
596 w.off += 2
597 }
598
599 func (w *Writer) Uint8(x uint8) {
600 w.wr.WriteByte(x)
601 w.off++
602 }
603
604 func (w *Writer) Offset() uint32 {
605 return w.off
606 }
607
608 type Reader struct {
609 b []byte
610 readonly bool
611
612 start uint32
613 h Header
614 }
615
616 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
617 r := &Reader{b: b, readonly: readonly, start: 0}
618 err := r.h.Read(r)
619 if err != nil {
620 return nil
621 }
622 return r
623 }
624
625 func (r *Reader) BytesAt(off uint32, len int) []byte {
626 if len == 0 {
627 return nil
628 }
629 end := int(off) + len
630 return r.b[int(off):end:end]
631 }
632
633 func (r *Reader) uint64At(off uint32) uint64 {
634 b := r.BytesAt(off, 8)
635 return binary.LittleEndian.Uint64(b)
636 }
637
638 func (r *Reader) uint32At(off uint32) uint32 {
639 b := r.BytesAt(off, 4)
640 return binary.LittleEndian.Uint32(b)
641 }
642
643 func (r *Reader) StringAt(off uint32, len uint32) string {
644 b := r.b[off : off+len]
645 if r.readonly {
646 return toString(b)
647 }
648 return string(b)
649 }
650
651 func toString(b []byte) string {
652 if len(b) == 0 {
653 return ""
654 }
655 return unsafe.String(&b[0], len(b))
656 }
657
658 func (r *Reader) StringRef(off uint32) string {
659 l := r.uint32At(off)
660 return r.StringAt(r.uint32At(off+4), l)
661 }
662
663 func (r *Reader) Fingerprint() FingerprintType {
664 return r.h.Fingerprint
665 }
666
667 func (r *Reader) Autolib() []ImportedPkg {
668 n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
669 s := make([]ImportedPkg, n)
670 off := r.h.Offsets[BlkAutolib]
671 for i := range s {
672 s[i].Pkg = r.StringRef(off)
673 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
674 off += importedPkgSize
675 }
676 return s
677 }
678
679 func (r *Reader) Pkglist() []string {
680 n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
681 s := make([]string, n)
682 off := r.h.Offsets[BlkPkgIdx]
683 for i := range s {
684 s[i] = r.StringRef(off)
685 off += stringRefSize
686 }
687 return s
688 }
689
690 func (r *Reader) NPkg() int {
691 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
692 }
693
694 func (r *Reader) Pkg(i int) string {
695 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
696 return r.StringRef(off)
697 }
698
699 func (r *Reader) NFile() int {
700 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
701 }
702
703 func (r *Reader) File(i int) string {
704 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
705 return r.StringRef(off)
706 }
707
708 func (r *Reader) NSym() int {
709 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
710 }
711
712 func (r *Reader) NHashed64def() int {
713 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
714 }
715
716 func (r *Reader) NHasheddef() int {
717 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
718 }
719
720 func (r *Reader) NNonpkgdef() int {
721 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
722 }
723
724 func (r *Reader) NNonpkgref() int {
725 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
726 }
727
728
729 func (r *Reader) SymOff(i uint32) uint32 {
730 return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
731 }
732
733
734 func (r *Reader) Sym(i uint32) *Sym {
735 off := r.SymOff(i)
736 return (*Sym)(unsafe.Pointer(&r.b[off]))
737 }
738
739
740 func (r *Reader) NRefFlags() int {
741 return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
742 }
743
744
745
746 func (r *Reader) RefFlags(i int) *RefFlags {
747 off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
748 return (*RefFlags)(unsafe.Pointer(&r.b[off]))
749 }
750
751
752
753
754 func (r *Reader) Hash64(i uint32) uint64 {
755 off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
756 return r.uint64At(off)
757 }
758
759
760
761
762 func (r *Reader) Hash(i uint32) *HashType {
763 off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
764 return (*HashType)(unsafe.Pointer(&r.b[off]))
765 }
766
767
768 func (r *Reader) NReloc(i uint32) int {
769 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
770 return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
771 }
772
773
774 func (r *Reader) RelocOff(i uint32, j int) uint32 {
775 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
776 relocIdx := r.uint32At(relocIdxOff)
777 return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
778 }
779
780
781 func (r *Reader) Reloc(i uint32, j int) *Reloc {
782 off := r.RelocOff(i, j)
783 return (*Reloc)(unsafe.Pointer(&r.b[off]))
784 }
785
786
787 func (r *Reader) Relocs(i uint32) []Reloc {
788 off := r.RelocOff(i, 0)
789 n := r.NReloc(i)
790 return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
791 }
792
793
794 func (r *Reader) NAux(i uint32) int {
795 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
796 return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
797 }
798
799
800 func (r *Reader) AuxOff(i uint32, j int) uint32 {
801 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
802 auxIdx := r.uint32At(auxIdxOff)
803 return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
804 }
805
806
807 func (r *Reader) Aux(i uint32, j int) *Aux {
808 off := r.AuxOff(i, j)
809 return (*Aux)(unsafe.Pointer(&r.b[off]))
810 }
811
812
813 func (r *Reader) Auxs(i uint32) []Aux {
814 off := r.AuxOff(i, 0)
815 n := r.NAux(i)
816 return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
817 }
818
819
820 func (r *Reader) DataOff(i uint32) uint32 {
821 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
822 return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
823 }
824
825
826 func (r *Reader) DataSize(i uint32) int {
827 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
828 return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
829 }
830
831
832 func (r *Reader) Data(i uint32) []byte {
833 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
834 base := r.h.Offsets[BlkData]
835 off := r.uint32At(dataIdxOff)
836 end := r.uint32At(dataIdxOff + 4)
837 return r.BytesAt(base+off, int(end-off))
838 }
839
840
841 func (r *Reader) DataString(i uint32) string {
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.StringAt(base+off, end-off)
847 }
848
849
850 func (r *Reader) NRefName() int {
851 return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
852 }
853
854
855
856 func (r *Reader) RefName(i int) *RefName {
857 off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
858 return (*RefName)(unsafe.Pointer(&r.b[off]))
859 }
860
861
862 func (r *Reader) ReadOnly() bool {
863 return r.readonly
864 }
865
866
867 func (r *Reader) Flags() uint32 {
868 return r.h.Flags
869 }
870
871 func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 }
872 func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
873 func (r *Reader) Unlinkable() bool { return r.Flags()&ObjFlagUnlinkable != 0 }
874 func (r *Reader) Std() bool { return r.Flags()&ObjFlagStd != 0 }
875
View as plain text