github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-unwind.c (about) 1 /* 2 * jit-unwind.c - Routines for performing stack unwinding. 3 * 4 * Copyright (C) 2008 Southern Storm Software, Pty Ltd. 5 * 6 * This file is part of the libjit library. 7 * 8 * The libjit library is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation, either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * The libjit library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with the libjit library. If not, see 20 * <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "jit-internal.h" 24 #include "jit-rules.h" 25 #include "jit-apply-rules.h" 26 #include <jit/jit-unwind.h> 27 #include <jit/jit-walk.h> 28 29 int 30 jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context) 31 { 32 #if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 33 jit_thread_control_t control; 34 35 control = _jit_thread_get_control(); 36 if(!control) 37 { 38 return 0; 39 } 40 41 unwind->frame = control->backtrace_head; 42 #elif JIT_FAST_GET_CURRENT_FRAME != 0 43 unwind->frame = jit_get_next_frame_address(jit_get_current_frame()); 44 #else 45 unwind->frame = jit_get_frame_address(1); 46 #endif 47 48 unwind->context = context; 49 unwind->cache = 0; 50 51 #ifdef _JIT_ARCH_UNWIND_INIT 52 _JIT_ARCH_UNWIND_INIT(unwind); 53 #endif 54 55 return (unwind->frame != 0); 56 } 57 58 void 59 jit_unwind_free(jit_unwind_context_t *unwind) 60 { 61 #ifdef _JIT_ARCH_UNWIND_FREE 62 _JIT_ARCH_UNWIND_FREE(unwind); 63 #endif 64 } 65 66 int 67 jit_unwind_next(jit_unwind_context_t *unwind) 68 { 69 #if defined(_JIT_ARCH_UNWIND_NEXT) || defined(_JIT_ARCH_UNWIND_NEXT_PRE) 70 jit_function_t func; 71 #endif 72 73 if(!unwind || !unwind->frame) 74 { 75 return 0; 76 } 77 78 unwind->cache = 0; 79 80 #if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 81 unwind->frame = ((jit_backtrace_t) unwind->frame)->parent; 82 return (unwind->frame != 0); 83 #else 84 85 #ifdef _JIT_ARCH_UNWIND_NEXT_PRE 86 func = jit_unwind_get_function(unwind); 87 if(func) 88 { 89 _JIT_ARCH_UNWIND_NEXT_PRE(unwind, func); 90 } 91 #endif 92 93 unwind->frame = jit_get_next_frame_address(unwind->frame); 94 if(!unwind->frame) 95 { 96 return 0; 97 } 98 99 #ifdef _JIT_ARCH_UNWIND_NEXT 100 func = jit_unwind_get_function(unwind); 101 if(func) 102 { 103 _JIT_ARCH_UNWIND_NEXT(unwind, func); 104 } 105 #endif 106 107 return 1; 108 #endif 109 } 110 111 int 112 jit_unwind_next_pc(jit_unwind_context_t *unwind) 113 { 114 void *next; 115 116 if(!unwind || !unwind->frame) 117 { 118 return 0; 119 } 120 121 unwind->cache = 0; 122 123 #if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 124 next = ((jit_backtrace_t) unwind->frame)->parent; 125 #else 126 next = jit_get_next_frame_address(unwind->frame); 127 #endif 128 129 if(next <= unwind->frame) 130 { 131 unwind->frame = 0; 132 } 133 else 134 { 135 unwind->frame = next; 136 } 137 return (unwind->frame != 0); 138 } 139 140 void * 141 jit_unwind_get_pc(jit_unwind_context_t *unwind) 142 { 143 if(!unwind || !unwind->frame) 144 { 145 return 0; 146 } 147 148 #if defined(JIT_BACKEND_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 149 return ((jit_backtrace_t) unwind->frame)->pc; 150 #else 151 return jit_get_return_address(unwind->frame); 152 #endif 153 } 154 155 int 156 jit_unwind_jump(jit_unwind_context_t *unwind, void *pc) 157 { 158 #ifdef _JIT_ARCH_UNWIND_JUMP 159 if(!unwind || !unwind->frame || !pc) 160 { 161 return 0; 162 } 163 164 return _JIT_ARCH_UNWIND_JUMP(unwind, pc); 165 #else 166 return 0; 167 #endif 168 } 169 170 jit_function_t 171 jit_unwind_get_function(jit_unwind_context_t *unwind) 172 { 173 if(!unwind || !unwind->frame || !unwind->context) 174 { 175 return 0; 176 } 177 178 if(!unwind->cache) 179 { 180 void *pc = jit_unwind_get_pc(unwind); 181 unwind->cache = _jit_memory_find_function_info(unwind->context, pc); 182 } 183 184 return _jit_memory_get_function(unwind->context, unwind->cache); 185 } 186 187 unsigned int 188 jit_unwind_get_offset(jit_unwind_context_t *unwind) 189 { 190 void *pc; 191 jit_function_t func; 192 193 if(!unwind || !unwind->frame || !unwind->context) 194 { 195 return JIT_NO_OFFSET; 196 } 197 198 pc = jit_unwind_get_pc(unwind); 199 if(!pc) 200 { 201 return JIT_NO_OFFSET; 202 } 203 204 if(!unwind->cache) 205 { 206 unwind->cache = _jit_memory_find_function_info(unwind->context, pc); 207 } 208 func = _jit_memory_get_function(unwind->context, unwind->cache); 209 if(!func) 210 { 211 return JIT_NO_OFFSET; 212 } 213 214 return _jit_function_get_bytecode(func, unwind->cache, pc, 0); 215 }