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