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