Text file src/runtime/libfuzzer_loong64.s

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build libfuzzer
     6  
     7  #include "go_asm.h"
     8  #include "textflag.h"
     9  
    10  // Based on race_loong64.s; see commentary there.
    11  
    12  #define RARG0 R4
    13  #define RARG1 R5
    14  #define RARG2 R6
    15  #define RARG3 R7
    16  
    17  #define REPEAT_2(a) a a
    18  #define REPEAT_8(a) REPEAT_2(REPEAT_2(REPEAT_2(a)))
    19  #define REPEAT_128(a) REPEAT_2(REPEAT_8(REPEAT_8(a)))
    20  
    21  // void runtime·libfuzzerCall4(fn, hookId int, s1, s2 unsafe.Pointer, result uintptr)
    22  // Calls C function fn from libFuzzer and passes 4 arguments to it.
    23  TEXT	runtime·libfuzzerCall4<ABIInternal>(SB), NOSPLIT, $0-0
    24  	MOVV	R4, R12	// fn
    25  	MOVV	R5, RARG0	// hookId
    26  	MOVV	R6, RARG1	// s1
    27  	MOVV	R7, RARG2	// s2
    28  	MOVV	R8, RARG3	// result
    29  
    30  	MOVV	g_m(g), R13
    31  
    32  	// Switch to g0 stack.
    33  	MOVV	R3, R23	// callee-saved, preserved across the CALL
    34  	MOVV	m_g0(R13), R14
    35  	BEQ	R14, g, call	// already on g0
    36  	MOVV	(g_sched+gobuf_sp)(R14), R3
    37  
    38  call:
    39  	JAL	(R12)
    40  	MOVV	R23, R3
    41  	RET
    42  
    43  // void runtime·libfuzzerCallWithTwoByteBuffers(fn, start, end *byte)
    44  // Calls C function fn from libFuzzer and passes 2 arguments of type *byte to it.
    45  TEXT    runtime·libfuzzerCallWithTwoByteBuffers<ABIInternal>(SB), NOSPLIT, $0-0
    46  	MOVV    R4, R12	// fn
    47  	MOVV    R5, RARG0	// start
    48  	MOVV    R6, RARG1	// end
    49  
    50  	MOVV    g_m(g), R13
    51  
    52  	// Switch to g0 stack.
    53  	MOVV    R3, R23	// callee-saved, preserved across the CALL
    54  	MOVV    m_g0(R13), R14
    55  	BEQ	R14, g, call	// already on g0
    56  	MOVV    (g_sched+gobuf_sp)(R14), R3
    57  
    58  call:
    59  	JAL	(R12)
    60  	MOVV    R23, R3
    61  	RET
    62  
    63  // void runtime·libfuzzerCallTraceIntCmp(fn, arg0, arg1, fakePC uintptr)
    64  // Calls C function fn from libFuzzer and passes 2 arguments to it after
    65  // manipulating the return address so that libfuzzer's integer compare hooks
    66  // work.
    67  // The problem statement and solution are documented in detail in libfuzzer_amd64.s.
    68  // See commentary there.
    69  TEXT	runtime·libfuzzerCallTraceIntCmp<ABIInternal>(SB), NOSPLIT, $0-0
    70  	MOVV	R4, R12	// fn
    71  	MOVV	R5, RARG0	// arg0
    72  	MOVV	R6, RARG1	// arg1
    73  	// Save the original return address in a local variable
    74  	MOVV	R1, savedRetAddr-8(SP)
    75  
    76  	MOVV	g_m(g), R13
    77  
    78  	// Switch to g0 stack.
    79  	MOVV	R3, R23	// callee-saved, preserved across the CALL
    80  	MOVV	m_g0(R13), R14
    81  	BEQ	R14, g, call	// already on g0
    82  	MOVV	(g_sched+gobuf_sp)(R14), R3
    83  
    84  call:
    85  	// Load address of the ret sled into the default register for the return
    86  	// address.
    87  	MOVV	$ret_sled(SB), R1
    88  	// Clear the lowest 2 bits of fakePC. All Loong64 instructions are four
    89  	// bytes long, so we cannot get better return address granularity than
    90  	// multiples of 4.
    91  	AND	$-4, R7
    92  	// Load the address of the i'th return instruction from the return sled.
    93  	// The index is given in the fakePC argument.
    94  	ADDV	R7, R1
    95  	// Call the function by jumping to it and reusing all registers except
    96  	// for the modified return address register R1.
    97  	JMP	(R12)
    98  
    99  // The ret sled for Loong64 consists of 128 br instructions jumping to the
   100  // end of the function. Each instruction is 4 bytes long. The sled thus has
   101  // the same byte length of 4 * 128 = 512 as the x86_64 sled, but coarser
   102  // granularity.
   103  #define RET_SLED \
   104  	JMP	end_of_function;
   105  
   106  TEXT	ret_sled(SB), NOSPLIT, $0-0
   107  	REPEAT_128(RET_SLED);
   108  
   109  end_of_function:
   110  	MOVV	R23, R3
   111  	MOVV	savedRetAddr-8(SP), R1
   112  	RET
   113  

View as plain text