github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/safecopy/sighandler_arm64.s (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include "textflag.h"
    16  
    17  // The signals handled by sigHandler.
    18  #define SIGBUS 7
    19  #define SIGSEGV 11
    20  
    21  // Offsets to the registers in context->uc_mcontext.gregs[].
    22  #define REG_R0 0xB8
    23  #define REG_R1 0xC0
    24  #define REG_PC 0x1B8
    25  
    26  // Offset to the si_addr field of siginfo.
    27  #define SI_CODE 0x08
    28  #define SI_ADDR 0x10
    29  
    30  // signalHandler is the signal handler for SIGSEGV and SIGBUS signals. It must
    31  // not be set up as a handler to any other signals.
    32  //
    33  // If the instruction causing the signal is within a safecopy-protected
    34  // function, the signal is handled such that execution resumes in the
    35  // appropriate fault handling stub with R0 containing the faulting address and
    36  // R1 containing the signal number. Otherwise control is transferred to the
    37  // previously configured signal handler (savedSigSegvHandler or
    38  // savedSigBusHandler).
    39  //
    40  // This function cannot be written in go because it runs whenever a signal is
    41  // received by the thread (preempting whatever was running), which includes when
    42  // garbage collector has stopped or isn't expecting any interactions (like
    43  // barriers).
    44  //
    45  // The arguments are the following:
    46  // R0 - The signal number.
    47  // R1 - Pointer to siginfo_t structure.
    48  // R2 - Pointer to ucontext structure.
    49  TEXT ·signalHandler(SB),NOSPLIT,$0
    50  	// Check if the signal is from the kernel, si_code > 0 means a kernel signal.
    51  	MOVD SI_CODE(R1), R7
    52  	CMPW $0x0, R7
    53  	BLE original_handler
    54  
    55  	// Check if PC is within the area we care about.
    56  	MOVD REG_PC(R2), R7
    57  	MOVD ·memcpyBegin(SB), R8
    58  	CMP R8, R7
    59  	BLO not_memcpy
    60  	MOVD ·memcpyEnd(SB), R8
    61  	CMP R8, R7
    62  	BHS not_memcpy
    63  
    64  	// Modify the context such that execution will resume in the fault handler.
    65  	MOVD $handleMemcpyFault(SB), R7
    66  	B handle_fault
    67  
    68  not_memcpy:
    69  	MOVD ·memclrBegin(SB), R8
    70  	CMP R8, R7
    71  	BLO not_memclr
    72  	MOVD ·memclrEnd(SB), R8
    73  	CMP R8, R7
    74  	BHS not_memclr
    75  
    76  	MOVD $handleMemclrFault(SB), R7
    77  	B handle_fault
    78  
    79  not_memclr:
    80  	MOVD ·swapUint32Begin(SB), R8
    81  	CMP R8, R7
    82  	BLO not_swapuint32
    83  	MOVD ·swapUint32End(SB), R8
    84  	CMP R8, R7
    85  	BHS not_swapuint32
    86  
    87  	MOVD $handleSwapUint32Fault(SB), R7
    88  	B handle_fault
    89  
    90  not_swapuint32:
    91  	MOVD ·swapUint64Begin(SB), R8
    92  	CMP R8, R7
    93  	BLO not_swapuint64
    94  	MOVD ·swapUint64End(SB), R8
    95  	CMP R8, R7
    96  	BHS not_swapuint64
    97  
    98  	MOVD $handleSwapUint64Fault(SB), R7
    99  	B handle_fault
   100  
   101  not_swapuint64:
   102  	MOVD ·compareAndSwapUint32Begin(SB), R8
   103  	CMP R8, R7
   104  	BLO not_casuint32
   105  	MOVD ·compareAndSwapUint32End(SB), R8
   106  	CMP R8, R7
   107  	BHS not_casuint32
   108  
   109  	MOVD $handleCompareAndSwapUint32Fault(SB), R7
   110  	B handle_fault
   111  
   112  not_casuint32:
   113  	MOVD ·loadUint32Begin(SB), R8
   114  	CMP R8, R7
   115  	BLO not_loaduint32
   116  	MOVD ·loadUint32End(SB), R8
   117  	CMP R8, R7
   118  	BHS not_loaduint32
   119  
   120  	MOVD $handleLoadUint32Fault(SB), R7
   121  	B handle_fault
   122  
   123  not_loaduint32:
   124  original_handler:
   125  	// Jump to the previous signal handler, which is likely the golang one.
   126  	MOVD ·savedSigBusHandler(SB), R7
   127  	MOVD ·savedSigSegVHandler(SB), R8
   128  	CMPW $SIGSEGV, R0
   129  	CSEL EQ, R8, R7, R7
   130  	B (R7)
   131  
   132  handle_fault:
   133  	// Entered with the address of the fault handler in R7; store it in PC.
   134  	MOVD R7, REG_PC(R2)
   135  
   136  	// Store the faulting address in R0.
   137  	MOVD SI_ADDR(R1), R7
   138  	MOVD R7, REG_R0(R2)
   139  
   140  	// Store the signal number in R1.
   141  	MOVW R0, REG_R1(R2)
   142  
   143  	RET
   144  
   145  // func addrOfSignalHandler() uintptr
   146  TEXT ·addrOfSignalHandler(SB), $0-8
   147  	MOVD	$·signalHandler(SB), R0
   148  	MOVD	R0, ret+0(FP)
   149  	RET