Source file
src/runtime/symtab.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/atomic"
9 "runtime/internal/sys"
10 "unsafe"
11 )
12
13
14
15 type Frames struct {
16
17 callers []uintptr
18
19
20 frames []Frame
21 frameStore [2]Frame
22 }
23
24
25 type Frame struct {
26
27
28
29
30
31 PC uintptr
32
33
34
35 Func *Func
36
37
38
39
40
41
42 Function string
43
44
45
46
47
48 File string
49 Line int
50
51
52
53
54 Entry uintptr
55
56
57
58
59 funcInfo funcInfo
60 }
61
62
63
64
65 func CallersFrames(callers []uintptr) *Frames {
66 f := &Frames{callers: callers}
67 f.frames = f.frameStore[:0]
68 return f
69 }
70
71
72
73 func (ci *Frames) Next() (frame Frame, more bool) {
74 for len(ci.frames) < 2 {
75
76
77
78 if len(ci.callers) == 0 {
79 break
80 }
81 pc := ci.callers[0]
82 ci.callers = ci.callers[1:]
83 funcInfo := findfunc(pc)
84 if !funcInfo.valid() {
85 if cgoSymbolizer != nil {
86
87
88
89 ci.frames = append(ci.frames, expandCgoFrames(pc)...)
90 }
91 continue
92 }
93 f := funcInfo._Func()
94 entry := f.Entry()
95 if pc > entry {
96
97
98
99
100 pc--
101 }
102 name := funcname(funcInfo)
103 if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {
104 inltree := (*[1 << 20]inlinedCall)(inldata)
105 ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil)
106 if ix >= 0 {
107
108 f = nil
109 name = funcnameFromNameoff(funcInfo, inltree[ix].func_)
110
111
112 }
113 }
114 ci.frames = append(ci.frames, Frame{
115 PC: pc,
116 Func: f,
117 Function: name,
118 Entry: entry,
119 funcInfo: funcInfo,
120
121 })
122 }
123
124
125
126 switch len(ci.frames) {
127 case 0:
128 return
129 case 1:
130 frame = ci.frames[0]
131 ci.frames = ci.frameStore[:0]
132 case 2:
133 frame = ci.frames[0]
134 ci.frameStore[0] = ci.frames[1]
135 ci.frames = ci.frameStore[:1]
136 default:
137 frame = ci.frames[0]
138 ci.frames = ci.frames[1:]
139 }
140 more = len(ci.frames) > 0
141 if frame.funcInfo.valid() {
142
143
144
145 file, line := funcline1(frame.funcInfo, frame.PC, false)
146 frame.File, frame.Line = file, int(line)
147 }
148 return
149 }
150
151
152
153
154
155 func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
156 if len(stk) == 0 {
157 return stk
158 }
159 pc := stk[len(stk)-1]
160 tracepc := pc - 1
161
162 f := findfunc(tracepc)
163 if !f.valid() {
164
165 return stk
166 }
167
168 inldata := funcdata(f, _FUNCDATA_InlTree)
169 if inldata == nil {
170
171 return stk
172 }
173
174
175
176
177 lastFuncID := funcID_normal
178
179
180 stk = stk[:len(stk)-1]
181
182
183 var cache pcvalueCache
184 inltree := (*[1 << 20]inlinedCall)(inldata)
185 for {
186 ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache)
187 if ix < 0 {
188 break
189 }
190 if inltree[ix].funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) {
191
192 } else {
193 stk = append(stk, pc)
194 }
195 lastFuncID = inltree[ix].funcID
196
197 tracepc = f.entry + uintptr(inltree[ix].parentPc)
198 pc = tracepc + 1
199 }
200
201
202 stk = append(stk, pc)
203
204 return stk
205 }
206
207
208
209
210 func expandCgoFrames(pc uintptr) []Frame {
211 arg := cgoSymbolizerArg{pc: pc}
212 callCgoSymbolizer(&arg)
213
214 if arg.file == nil && arg.funcName == nil {
215
216 return nil
217 }
218
219 var frames []Frame
220 for {
221 frames = append(frames, Frame{
222 PC: pc,
223 Func: nil,
224 Function: gostring(arg.funcName),
225 File: gostring(arg.file),
226 Line: int(arg.lineno),
227 Entry: arg.entry,
228
229
230 })
231 if arg.more == 0 {
232 break
233 }
234 callCgoSymbolizer(&arg)
235 }
236
237
238
239
240
241 arg.pc = 0
242 callCgoSymbolizer(&arg)
243
244 return frames
245 }
246
247
248
249
250
251
252
253
254 type Func struct {
255 opaque struct{}
256 }
257
258 func (f *Func) raw() *_func {
259 return (*_func)(unsafe.Pointer(f))
260 }
261
262 func (f *Func) funcInfo() funcInfo {
263 fn := f.raw()
264 return funcInfo{fn, findmoduledatap(fn.entry)}
265 }
266
267
268
269
270 const (
271 _PCDATA_UnsafePoint = 0
272 _PCDATA_StackMapIndex = 1
273 _PCDATA_InlTreeIndex = 2
274
275 _FUNCDATA_ArgsPointerMaps = 0
276 _FUNCDATA_LocalsPointerMaps = 1
277 _FUNCDATA_StackObjects = 2
278 _FUNCDATA_InlTree = 3
279 _FUNCDATA_OpenCodedDeferInfo = 4
280
281 _ArgsSizeUnknown = -0x80000000
282 )
283
284 const (
285
286 _PCDATA_UnsafePointSafe = -1
287 _PCDATA_UnsafePointUnsafe = -2
288
289
290
291
292
293
294 _PCDATA_Restart1 = -3
295 _PCDATA_Restart2 = -4
296
297
298
299 _PCDATA_RestartAtEntry = -5
300 )
301
302
303
304
305
306
307 type funcID uint8
308
309 const (
310 funcID_normal funcID = iota
311 funcID_runtime_main
312 funcID_goexit
313 funcID_jmpdefer
314 funcID_mcall
315 funcID_morestack
316 funcID_mstart
317 funcID_rt0_go
318 funcID_asmcgocall
319 funcID_sigpanic
320 funcID_runfinq
321 funcID_gcBgMarkWorker
322 funcID_systemstack_switch
323 funcID_systemstack
324 funcID_cgocallback
325 funcID_gogo
326 funcID_externalthreadhandler
327 funcID_debugCallV1
328 funcID_gopanic
329 funcID_panicwrap
330 funcID_handleAsyncEvent
331 funcID_asyncPreempt
332 funcID_wrapper
333 )
334
335
336 type pcHeader struct {
337 magic uint32
338 pad1, pad2 uint8
339 minLC uint8
340 ptrSize uint8
341 nfunc int
342 nfiles uint
343 funcnameOffset uintptr
344 cuOffset uintptr
345 filetabOffset uintptr
346 pctabOffset uintptr
347 pclnOffset uintptr
348 }
349
350
351
352
353
354
355 type moduledata struct {
356 pcHeader *pcHeader
357 funcnametab []byte
358 cutab []uint32
359 filetab []byte
360 pctab []byte
361 pclntable []byte
362 ftab []functab
363 findfunctab uintptr
364 minpc, maxpc uintptr
365
366 text, etext uintptr
367 noptrdata, enoptrdata uintptr
368 data, edata uintptr
369 bss, ebss uintptr
370 noptrbss, enoptrbss uintptr
371 end, gcdata, gcbss uintptr
372 types, etypes uintptr
373
374 textsectmap []textsect
375 typelinks []int32
376 itablinks []*itab
377
378 ptab []ptabEntry
379
380 pluginpath string
381 pkghashes []modulehash
382
383 modulename string
384 modulehashes []modulehash
385
386 hasmain uint8
387
388 gcdatamask, gcbssmask bitvector
389
390 typemap map[typeOff]*_type
391
392 bad bool
393
394 next *moduledata
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408
409 type modulehash struct {
410 modulename string
411 linktimehash string
412 runtimehash *string
413 }
414
415
416
417
418
419
420
421
422 var pinnedTypemaps []map[typeOff]*_type
423
424 var firstmoduledata moduledata
425 var lastmoduledatap *moduledata
426 var modulesSlice *[]*moduledata
427
428
429
430
431
432
433
434
435
436
437 func activeModules() []*moduledata {
438 p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
439 if p == nil {
440 return nil
441 }
442 return *p
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 func modulesinit() {
464 modules := new([]*moduledata)
465 for md := &firstmoduledata; md != nil; md = md.next {
466 if md.bad {
467 continue
468 }
469 *modules = append(*modules, md)
470 if md.gcdatamask == (bitvector{}) {
471 md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data)
472 md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss)
473 }
474 }
475
476
477
478
479
480
481
482
483
484
485 for i, md := range *modules {
486 if md.hasmain != 0 {
487 (*modules)[0] = md
488 (*modules)[i] = &firstmoduledata
489 break
490 }
491 }
492
493 atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules))
494 }
495
496 type functab struct {
497 entry uintptr
498 funcoff uintptr
499 }
500
501
502
503 type textsect struct {
504 vaddr uintptr
505 length uintptr
506 baseaddr uintptr
507 }
508
509 const minfunc = 16
510 const pcbucketsize = 256 * minfunc
511
512
513
514
515
516
517
518
519
520 type findfuncbucket struct {
521 idx uint32
522 subbuckets [16]byte
523 }
524
525 func moduledataverify() {
526 for datap := &firstmoduledata; datap != nil; datap = datap.next {
527 moduledataverify1(datap)
528 }
529 }
530
531 const debugPcln = false
532
533 func moduledataverify1(datap *moduledata) {
534
535 hdr := datap.pcHeader
536 if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || hdr.minLC != sys.PCQuantum || hdr.ptrSize != sys.PtrSize {
537 println("runtime: function symbol table header:", hex(hdr.magic), hex(hdr.pad1), hex(hdr.pad2), hex(hdr.minLC), hex(hdr.ptrSize))
538 throw("invalid function symbol table\n")
539 }
540
541
542 nftab := len(datap.ftab) - 1
543 for i := 0; i < nftab; i++ {
544
545 if datap.ftab[i].entry > datap.ftab[i+1].entry {
546 f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap}
547 f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap}
548 f2name := "end"
549 if i+1 < nftab {
550 f2name = funcname(f2)
551 }
552 println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name)
553 for j := 0; j <= i; j++ {
554 print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n")
555 }
556 if GOOS == "aix" && isarchive {
557 println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
558 }
559 throw("invalid runtime symbol table")
560 }
561 }
562
563 if datap.minpc != datap.ftab[0].entry ||
564 datap.maxpc != datap.ftab[nftab].entry {
565 throw("minpc or maxpc invalid")
566 }
567
568 for _, modulehash := range datap.modulehashes {
569 if modulehash.linktimehash != *modulehash.runtimehash {
570 println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
571 throw("abi mismatch")
572 }
573 }
574 }
575
576
577
578
579
580
581
582 func FuncForPC(pc uintptr) *Func {
583 f := findfunc(pc)
584 if !f.valid() {
585 return nil
586 }
587 if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil {
588
589
590
591
592 if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 {
593 inltree := (*[1 << 20]inlinedCall)(inldata)
594 name := funcnameFromNameoff(f, inltree[ix].func_)
595 file, line := funcline(f, pc)
596 fi := &funcinl{
597 entry: f.entry,
598 name: name,
599 file: file,
600 line: int(line),
601 }
602 return (*Func)(unsafe.Pointer(fi))
603 }
604 }
605 return f._Func()
606 }
607
608
609 func (f *Func) Name() string {
610 if f == nil {
611 return ""
612 }
613 fn := f.raw()
614 if fn.entry == 0 {
615 fi := (*funcinl)(unsafe.Pointer(fn))
616 return fi.name
617 }
618 return funcname(f.funcInfo())
619 }
620
621
622 func (f *Func) Entry() uintptr {
623 fn := f.raw()
624 if fn.entry == 0 {
625 fi := (*funcinl)(unsafe.Pointer(fn))
626 return fi.entry
627 }
628 return fn.entry
629 }
630
631
632
633
634
635 func (f *Func) FileLine(pc uintptr) (file string, line int) {
636 fn := f.raw()
637 if fn.entry == 0 {
638 fi := (*funcinl)(unsafe.Pointer(fn))
639 return fi.file, fi.line
640 }
641
642
643 file, line32 := funcline1(f.funcInfo(), pc, false)
644 return file, int(line32)
645 }
646
647 func findmoduledatap(pc uintptr) *moduledata {
648 for datap := &firstmoduledata; datap != nil; datap = datap.next {
649 if datap.minpc <= pc && pc < datap.maxpc {
650 return datap
651 }
652 }
653 return nil
654 }
655
656 type funcInfo struct {
657 *_func
658 datap *moduledata
659 }
660
661 func (f funcInfo) valid() bool {
662 return f._func != nil
663 }
664
665 func (f funcInfo) _Func() *Func {
666 return (*Func)(unsafe.Pointer(f._func))
667 }
668
669 func findfunc(pc uintptr) funcInfo {
670 datap := findmoduledatap(pc)
671 if datap == nil {
672 return funcInfo{}
673 }
674 const nsub = uintptr(len(findfuncbucket{}.subbuckets))
675
676 x := pc - datap.minpc
677 b := x / pcbucketsize
678 i := x % pcbucketsize / (pcbucketsize / nsub)
679
680 ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
681 idx := ffb.idx + uint32(ffb.subbuckets[i])
682
683
684
685
686
687 if idx >= uint32(len(datap.ftab)) {
688 idx = uint32(len(datap.ftab) - 1)
689 }
690 if pc < datap.ftab[idx].entry {
691
692
693
694 for datap.ftab[idx].entry > pc && idx > 0 {
695 idx--
696 }
697 if idx == 0 {
698 throw("findfunc: bad findfunctab entry idx")
699 }
700 } else {
701
702 for datap.ftab[idx+1].entry <= pc {
703 idx++
704 }
705 }
706 funcoff := datap.ftab[idx].funcoff
707 if funcoff == ^uintptr(0) {
708
709
710
711
712 return funcInfo{}
713 }
714 return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[funcoff])), datap}
715 }
716
717 type pcvalueCache struct {
718 entries [2][8]pcvalueCacheEnt
719 }
720
721 type pcvalueCacheEnt struct {
722
723 targetpc uintptr
724 off uint32
725
726 val int32
727 }
728
729
730
731
732
733 func pcvalueCacheKey(targetpc uintptr) uintptr {
734 return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries))
735 }
736
737
738
739 func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, strict bool) (int32, uintptr) {
740 if off == 0 {
741 return -1, 0
742 }
743
744
745
746
747
748
749
750 if cache != nil {
751 x := pcvalueCacheKey(targetpc)
752 for i := range cache.entries[x] {
753
754
755
756
757
758 ent := &cache.entries[x][i]
759 if ent.off == off && ent.targetpc == targetpc {
760 return ent.val, 0
761 }
762 }
763 }
764
765 if !f.valid() {
766 if strict && panicking == 0 {
767 print("runtime: no module data for ", hex(f.entry), "\n")
768 throw("no module data")
769 }
770 return -1, 0
771 }
772 datap := f.datap
773 p := datap.pctab[off:]
774 pc := f.entry
775 prevpc := pc
776 val := int32(-1)
777 for {
778 var ok bool
779 p, ok = step(p, &pc, &val, pc == f.entry)
780 if !ok {
781 break
782 }
783 if targetpc < pc {
784
785
786
787
788
789
790 if cache != nil {
791 x := pcvalueCacheKey(targetpc)
792 e := &cache.entries[x]
793 ci := fastrand() % uint32(len(cache.entries[x]))
794 e[ci] = e[0]
795 e[0] = pcvalueCacheEnt{
796 targetpc: targetpc,
797 off: off,
798 val: val,
799 }
800 }
801
802 return val, prevpc
803 }
804 prevpc = pc
805 }
806
807
808
809 if panicking != 0 || !strict {
810 return -1, 0
811 }
812
813 print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
814
815 p = datap.pctab[off:]
816 pc = f.entry
817 val = -1
818 for {
819 var ok bool
820 p, ok = step(p, &pc, &val, pc == f.entry)
821 if !ok {
822 break
823 }
824 print("\tvalue=", val, " until pc=", hex(pc), "\n")
825 }
826
827 throw("invalid runtime symbol table")
828 return -1, 0
829 }
830
831 func cfuncname(f funcInfo) *byte {
832 if !f.valid() || f.nameoff == 0 {
833 return nil
834 }
835 return &f.datap.funcnametab[f.nameoff]
836 }
837
838 func funcname(f funcInfo) string {
839 return gostringnocopy(cfuncname(f))
840 }
841
842 func funcpkgpath(f funcInfo) string {
843 name := funcname(f)
844 i := len(name) - 1
845 for ; i > 0; i-- {
846 if name[i] == '/' {
847 break
848 }
849 }
850 for ; i < len(name); i++ {
851 if name[i] == '.' {
852 break
853 }
854 }
855 return name[:i]
856 }
857
858 func cfuncnameFromNameoff(f funcInfo, nameoff int32) *byte {
859 if !f.valid() {
860 return nil
861 }
862 return &f.datap.funcnametab[nameoff]
863 }
864
865 func funcnameFromNameoff(f funcInfo, nameoff int32) string {
866 return gostringnocopy(cfuncnameFromNameoff(f, nameoff))
867 }
868
869 func funcfile(f funcInfo, fileno int32) string {
870 datap := f.datap
871 if !f.valid() {
872 return "?"
873 }
874
875 if fileoff := datap.cutab[f.cuOffset+uint32(fileno)]; fileoff != ^uint32(0) {
876 return gostringnocopy(&datap.filetab[fileoff])
877 }
878
879 return "?"
880 }
881
882 func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) {
883 datap := f.datap
884 if !f.valid() {
885 return "?", 0
886 }
887 fileno, _ := pcvalue(f, f.pcfile, targetpc, nil, strict)
888 line, _ = pcvalue(f, f.pcln, targetpc, nil, strict)
889 if fileno == -1 || line == -1 || int(fileno) >= len(datap.filetab) {
890
891 return "?", 0
892 }
893 file = funcfile(f, fileno)
894 return
895 }
896
897 func funcline(f funcInfo, targetpc uintptr) (file string, line int32) {
898 return funcline1(f, targetpc, true)
899 }
900
901 func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 {
902 x, _ := pcvalue(f, f.pcsp, targetpc, cache, true)
903 if x&(sys.PtrSize-1) != 0 {
904 print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
905 }
906 return x
907 }
908
909
910 func funcMaxSPDelta(f funcInfo) int32 {
911 datap := f.datap
912 p := datap.pctab[f.pcsp:]
913 pc := f.entry
914 val := int32(-1)
915 max := int32(0)
916 for {
917 var ok bool
918 p, ok = step(p, &pc, &val, pc == f.entry)
919 if !ok {
920 return max
921 }
922 if val > max {
923 max = val
924 }
925 }
926 }
927
928 func pcdatastart(f funcInfo, table uint32) uint32 {
929 return *(*uint32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
930 }
931
932 func pcdatavalue(f funcInfo, table uint32, targetpc uintptr, cache *pcvalueCache) int32 {
933 if table >= f.npcdata {
934 return -1
935 }
936 r, _ := pcvalue(f, pcdatastart(f, table), targetpc, cache, true)
937 return r
938 }
939
940 func pcdatavalue1(f funcInfo, table uint32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
941 if table >= f.npcdata {
942 return -1
943 }
944 r, _ := pcvalue(f, pcdatastart(f, table), targetpc, cache, strict)
945 return r
946 }
947
948
949
950 func pcdatavalue2(f funcInfo, table uint32, targetpc uintptr) (int32, uintptr) {
951 if table >= f.npcdata {
952 return -1, 0
953 }
954 return pcvalue(f, pcdatastart(f, table), targetpc, nil, true)
955 }
956
957 func funcdata(f funcInfo, i uint8) unsafe.Pointer {
958 if i < 0 || i >= f.nfuncdata {
959 return nil
960 }
961 p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
962 if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
963 if uintptr(unsafe.Pointer(f._func))&4 != 0 {
964 println("runtime: misaligned func", f._func)
965 }
966 p = add(p, 4)
967 }
968 return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
969 }
970
971
972 func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
973
974
975 uvdelta := uint32(p[0])
976 if uvdelta == 0 && !first {
977 return nil, false
978 }
979 n := uint32(1)
980 if uvdelta&0x80 != 0 {
981 n, uvdelta = readvarint(p)
982 }
983 *val += int32(-(uvdelta & 1) ^ (uvdelta >> 1))
984 p = p[n:]
985
986 pcdelta := uint32(p[0])
987 n = 1
988 if pcdelta&0x80 != 0 {
989 n, pcdelta = readvarint(p)
990 }
991 p = p[n:]
992 *pc += uintptr(pcdelta * sys.PCQuantum)
993 return p, true
994 }
995
996
997 func readvarint(p []byte) (read uint32, val uint32) {
998 var v, shift, n uint32
999 for {
1000 b := p[n]
1001 n++
1002 v |= uint32(b&0x7F) << (shift & 31)
1003 if b&0x80 == 0 {
1004 break
1005 }
1006 shift += 7
1007 }
1008 return n, v
1009 }
1010
1011 type stackmap struct {
1012 n int32
1013 nbit int32
1014 bytedata [1]byte
1015 }
1016
1017
1018 func stackmapdata(stkmap *stackmap, n int32) bitvector {
1019
1020
1021
1022 if stackDebug > 0 && (n < 0 || n >= stkmap.n) {
1023 throw("stackmapdata: index out of range")
1024 }
1025 return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))}
1026 }
1027
1028
1029 type inlinedCall struct {
1030 parent int16
1031 funcID funcID
1032 _ byte
1033 file int32
1034 line int32
1035 func_ int32
1036 parentPc int32
1037 }
1038
View as plain text