debug_go117.go raw
1 //go:build go1.17 && !go1.25
2 // +build go1.17,!go1.25
3
4 /*
5 * Copyright 2021 ByteDance Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 package x86
21
22 import (
23 "fmt"
24 "runtime"
25 "strings"
26 "unsafe"
27
28 "github.com/bytedance/sonic/internal/encoder/ir"
29 "github.com/bytedance/sonic/internal/encoder/vars"
30 "github.com/bytedance/sonic/internal/jit"
31 "github.com/twitchyliquid64/golang-asm/obj"
32 )
33
34 const _FP_debug = 128
35
36 var (
37 _Instr_End = ir.NewInsOp(ir.OP_is_nil)
38
39 _F_gc = jit.Func(gc)
40 _F_println = jit.Func(println_wrapper)
41 _F_print = jit.Func(print)
42 )
43
44 func (self *Assembler) dsave(r ...obj.Addr) {
45 for i, v := range r {
46 if i > _FP_debug/8-1 {
47 panic("too many registers to save")
48 } else {
49 self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8))
50 }
51 }
52 }
53
54 func (self *Assembler) dload(r ...obj.Addr) {
55 for i, v := range r {
56 if i > _FP_debug/8-1 {
57 panic("too many registers to load")
58 } else {
59 self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs+_FP_saves+_FP_locals+int64(i)*8), v)
60 }
61 }
62 }
63
64 func println_wrapper(i int, op1 int, op2 int) {
65 println(i, " Intrs ", op1, ir.OpNames[op1], "next: ", op2, ir.OpNames[op2])
66 }
67
68 func print(i int) {
69 println(i)
70 }
71
72 func gc() {
73 if !vars.DebugSyncGC {
74 return
75 }
76 runtime.GC()
77 // debug.FreeOSMemory()
78 }
79
80 func (self *Assembler) dcall(fn obj.Addr) {
81 self.Emit("MOVQ", fn, _R10) // MOVQ ${fn}, R10
82 self.Rjmp("CALL", _R10) // CALL R10
83 }
84
85 func (self *Assembler) debug_gc() {
86 if !vars.DebugSyncGC {
87 return
88 }
89 self.dsave(_REG_debug...)
90 self.dcall(_F_gc)
91 self.dload(_REG_debug...)
92 }
93
94 func (self *Assembler) debug_instr(i int, v *ir.Instr) {
95 if vars.DebugSyncGC {
96 if i+1 == len(self.p) {
97 self.print_gc(i, v, &_Instr_End)
98 } else {
99 next := &(self.p[i+1])
100 self.print_gc(i, v, next)
101 name := ir.OpNames[next.Op()]
102 if strings.Contains(name, "save") {
103 return
104 }
105 }
106 // self.debug_gc()
107 }
108 }
109
110 //go:noescape
111 //go:linkname checkptrBase runtime.checkptrBase
112 func checkptrBase(p unsafe.Pointer) uintptr
113
114 //go:noescape
115 //go:linkname findObject runtime.findObject
116 func findObject(p, refBase, refOff uintptr) (base uintptr, s unsafe.Pointer, objIndex uintptr)
117
118 var (
119 _F_checkptr = jit.Func(checkptr)
120 _F_printptr = jit.Func(printptr)
121 )
122
123 var (
124 _R10 = jit.Reg("R10")
125 )
126 var _REG_debug = []obj.Addr{
127 jit.Reg("AX"),
128 jit.Reg("BX"),
129 jit.Reg("CX"),
130 jit.Reg("DX"),
131 jit.Reg("DI"),
132 jit.Reg("SI"),
133 jit.Reg("BP"),
134 jit.Reg("SP"),
135 jit.Reg("R8"),
136 jit.Reg("R9"),
137 jit.Reg("R10"),
138 jit.Reg("R11"),
139 jit.Reg("R12"),
140 jit.Reg("R13"),
141 jit.Reg("R14"),
142 jit.Reg("R15"),
143 }
144
145 func checkptr(ptr uintptr) {
146 if ptr == 0 {
147 return
148 }
149 fmt.Printf("pointer: %x\n", ptr)
150 f := checkptrBase(unsafe.Pointer(uintptr(ptr)))
151 if f == 0 {
152 fmt.Printf("! unknown-based pointer: %x\n", ptr)
153 } else if f == 1 {
154 fmt.Printf("! stack pointer: %x\n", ptr)
155 } else {
156 fmt.Printf("base: %x\n", f)
157 }
158 findobj(ptr)
159 }
160
161 func findobj(ptr uintptr) {
162 base, s, objIndex := findObject(ptr, 0, 0)
163 if s != nil && base == 0 {
164 fmt.Printf("! invalid pointer: %x\n", ptr)
165 }
166 fmt.Printf("objIndex: %d\n", objIndex)
167 }
168
169 func (self *Assembler) check_ptr(ptr obj.Addr, lea bool) {
170 if !vars.DebugCheckPtr {
171 return
172 }
173
174 self.dsave(_REG_debug...)
175 if lea {
176 self.Emit("LEAQ", ptr, _R10)
177 } else {
178 self.Emit("MOVQ", ptr, _R10)
179 }
180 self.Emit("MOVQ", _R10, jit.Ptr(_SP, 0))
181 self.dcall(_F_checkptr)
182 self.dload(_REG_debug...)
183 }
184
185 func printptr(i int, ptr uintptr) {
186 fmt.Printf("[%d] ptr: %x\n", i, ptr)
187 }
188
189 func (self *Assembler) print_ptr(i int, ptr obj.Addr, lea bool) {
190 self.dsave(_REG_debug...)
191 if lea {
192 self.Emit("LEAQ", ptr, _R10)
193 } else {
194 self.Emit("MOVQ", ptr, _R10)
195 }
196
197 self.Emit("MOVQ", jit.Imm(int64(i)), _AX)
198 self.Emit("MOVQ", _R10, _BX)
199 self.dcall(_F_printptr)
200 self.dload(_REG_debug...)
201 }
202