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  }