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