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