...

Text file src/runtime/libfuzzer_arm64.s

Documentation: runtime

     1// Copyright 2019 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_arm64.s; see commentary there.
    11
    12#define RARG0 R0
    13#define RARG1 R1
    14#define RARG2 R2
    15#define RARG3 R3
    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·libfuzzerCallTraceIntCmp(fn, arg0, arg1, fakePC uintptr)
    22// Calls C function fn from libFuzzer and passes 2 arguments to it after
    23// manipulating the return address so that libfuzzer's integer compare hooks
    24// work.
    25// The problem statement and solution are documented in detail in libfuzzer_amd64.s.
    26// See commentary there.
    27TEXT	runtime·libfuzzerCallTraceIntCmp(SB), NOSPLIT, $8-32
    28	MOVD	fn+0(FP), R9
    29	MOVD	arg0+8(FP), RARG0
    30	MOVD	arg1+16(FP), RARG1
    31	MOVD	fakePC+24(FP), R8
    32	// Save the original return address in a local variable
    33	MOVD	R30, savedRetAddr-8(SP)
    34
    35	MOVD	g_m(g), R10
    36
    37	// Switch to g0 stack.
    38	MOVD	RSP, R19	// callee-saved, preserved across the CALL
    39	MOVD	m_g0(R10), R11
    40	CMP	R11, g
    41	BEQ	call	// already on g0
    42	MOVD	(g_sched+gobuf_sp)(R11), R12
    43	MOVD	R12, RSP
    44call:
    45	// Load address of the ret sled into the default register for the return
    46	// address.
    47	ADR	ret_sled, R30
    48	// Clear the lowest 2 bits of fakePC. All ARM64 instructions are four
    49	// bytes long, so we cannot get better return address granularity than
    50	// multiples of 4.
    51	AND	$-4, R8, R8
    52	// Add the offset of the fake_pc-th ret.
    53	ADD	R8, R30, R30
    54	// Call the function by jumping to it and reusing all registers except
    55	// for the modified return address register R30.
    56	JMP	(R9)
    57
    58// The ret sled for ARM64 consists of 128 br instructions jumping to the
    59// end of the function. Each instruction is 4 bytes long. The sled thus
    60// has the same byte length of 4 * 128 = 512 as the x86_64 sled, but
    61// coarser granularity.
    62#define RET_SLED \
    63	JMP	end_of_function;
    64
    65ret_sled:
    66	REPEAT_128(RET_SLED);
    67
    68end_of_function:
    69	MOVD	R19, RSP
    70	MOVD	savedRetAddr-8(SP), R30
    71	RET
    72
    73// void runtime·libfuzzerCall4(fn, hookId int, s1, s2 unsafe.Pointer, result uintptr)
    74// Calls C function fn from libFuzzer and passes 4 arguments to it.
    75TEXT	runtime·libfuzzerCall4(SB), NOSPLIT, $0-40
    76	MOVD	fn+0(FP), R9
    77	MOVD	hookId+8(FP), RARG0
    78	MOVD	s1+16(FP), RARG1
    79	MOVD	s2+24(FP), RARG2
    80	MOVD	result+32(FP), RARG3
    81
    82	MOVD	g_m(g), R10
    83
    84	// Switch to g0 stack.
    85	MOVD	RSP, R19	// callee-saved, preserved across the CALL
    86	MOVD	m_g0(R10), R11
    87	CMP	R11, g
    88	BEQ	call	// already on g0
    89	MOVD	(g_sched+gobuf_sp)(R11), R12
    90	MOVD	R12, RSP
    91call:
    92	BL	R9
    93	MOVD	R19, RSP
    94	RET
    95
    96// void runtime·libfuzzerCallWithTwoByteBuffers(fn, start, end *byte)
    97// Calls C function fn from libFuzzer and passes 2 arguments of type *byte to it.
    98TEXT	runtime·libfuzzerCallWithTwoByteBuffers(SB), NOSPLIT, $0-24
    99	MOVD	fn+0(FP), R9
   100	MOVD	start+8(FP), R0
   101	MOVD	end+16(FP), R1
   102
   103	MOVD	g_m(g), R10
   104
   105	// Switch to g0 stack.
   106	MOVD	RSP, R19	// callee-saved, preserved across the CALL
   107	MOVD	m_g0(R10), R11
   108	CMP	R11, g
   109	BEQ	call	// already on g0
   110	MOVD	(g_sched+gobuf_sp)(R11), R12
   111	MOVD	R12, RSP
   112call:
   113	BL	R9
   114	MOVD	R19, RSP
   115	RET

View as plain text