File: substr.S

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (135 lines) | stat: -rw-r--r-- 3,843 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2021, 2024, Oracle and/or its affiliates.
 */

#include <bpf_asm_helpers.h>

/*
 * char *dt_substr(char *dst, const char *src, int32_t idx, int32_t cnt,
 *		  uint64_t argc)
 *
 * %r1 = dst, %r2 = src, %r3 = idx, %r4 = cnt, %r5 = argc
 */
	.text
	.align	4
	.global	dt_substr
	.type	dt_substr, @function
dt_substr :
	/* Store the arguments (sign-extend idx). */
	mov	%r9, %r1		/* %r9 = dst */
	stxdw	[%fp+-8], %r2		/* Spill src */
	lsh	%r3, 32			/* Sign-extend idx */
	arsh	%r3, 32
	mov	%r6, %r3		/* %r6 = idx */

	/* Initialize the string length with its maximum value.  */
	lddw	%r8, STRSZ		/* %r8 = len = STRSZ */

	/*
	 * If we do not have a cnt, use the maximum value.
	 * Otherwise, sign-extend cnt.
	 */
	jgt	%r5, 2, .Lhave_cnt	/* if (argc > 2) goto Lhave_cnt; */
	mov	%r7, %r8		/* cnt = STRSZ */
	ja	.Lcnt_set
.Lhave_cnt:
	lsh	%r4, 32			/* Sign-extend cnt */
	arsh	%r4, 32
	mov	%r7, %r4		/* %r7 = cnt */
.Lcnt_set:

	/*
	 * Get the source string length and validate it.
	 * If the return value of probe_read_str() is less than 0, an error
	 * occurred, and the result will be the empty string.
	 * If the length is 1, the result is the empty string.
	 * If the length is less than the maximum string length (STRSZ), use
	 * the length we got.  (The length is initialized in %r8 as the default
	 * string length.)
	 */
	mov	%r3, %r2
	mov	%r2, %r8
	add	%r2, 1
	call	BPF_FUNC_probe_read_str	/*
					 * len = probe_read_str(dst, STRSZ + 1,
					 *			src);
					 */
	jsle	%r0, 1, .Lempty		/* if (len <= 1) goto Lempty; */
	sub	%r0, 1			/* len--; */
	mov	%r4, %r8		/* %r4 = STRSZ (previously in %r8) */
	mov	%r8, %r0		/* %r8 = len */

	jsge	%r6, 0, .Lcheck_idx	/* if (idx s>= 0) goto Lcheck_idx; */

	/*
	 * If idx is negative it is a count from the end of the string.  Turn
	 * it into the equivalent character offset (len + idx).
	 * If the offset is not negative, we can use it as the index.
	 * If not, we need to determine whether idx + cnt falls within the
	 * [0, len[ interval.  If it does not, the result is the empty string.
	 * If it does, we will copy cnt + idx characters, starting from idx 0..
	 */
	add	%r6, %r8		/* idx += len */
	jsge	%r6, 0, .Lcheck_idx	/* if (idx s>= 0) goto Lcheck_idx; */
	mov	%r0, 0
	sub	%r0, %r6		/* neg messes up the verifier */
	jsle	%r7, %r0, .Lempty	/* if (cnt s<= -idx) goto Lempty; */
	add	%r7, %r6		/* cnt += idx */
	mov	%r6, 0			/* idx = 0 */

.Lcheck_idx:
	/*
	 * Validate the idx value.  If idx is greater than the string length,
	 * we get the empty string.
	 */
	jsge	%r6, %r8, .Lempty	/* if (idx s>= len) goto Lempty; */

	/* If cnt is positive (or 0), we are ready to copy the slice. */
	jsge	%r7, 0, .Lcopy		/* if (cnt s>= 0) goto Lcopy; */

	/*
	 * If cnt is negative it is a count from the last character in string.
	 * Use the equivalent character offset to calculate the true (positive)
	 * cnt:
	 *	start = idx
	 *	end = (len - 1) - (-cnt)
	 *	new_cnt = end - start + 1
	 *		= (len - 1) - (-cnt) - idx + 1
	 *		= len - 1 + cnt - idx + 1
	 *		= len + cnt - idx
	 * which is equivalent with:
	 *	cnt += len - idx
	 */
	mov	%r0, %r8
	sub	%r0, %r6
	add	%r7, %r0		/* cnt += len - idx */
	jsle	%r7, 0, .Lempty		/* if (cnt s<= 0) goto Lempty; */

.Lcopy:
	/*
	 * Use the probe_read_str() BPF helper to copy (cnt + 1) bytes from
	 * &src[idx] to dst.  We ensure that cnt is capped at STRSZ.
	 */
	mov	%r1, %r9
	mov	%r2, %r7
	jle	%r2, %r4, .Lcnt_ok	/* if (cnt <= STRSZ) goto Lcnt_ok; */
	mov	%r2, %r4		/* cnt = STRSZ */
.Lcnt_ok:
	add	%r2, 1
	ldxdw	%r3, [%fp+-8]
	add	%r3, %r6
	call	BPF_FUNC_probe_read_str	/*
					 * rc = probe_read_str(dst, cnt + 1,
					 *		       &src[idx]);
					 */

	mov	%r0, %r9
	exit

.Lempty:
	/* Store the empty string in the destination. */
	stb	[%r9+0], 0
	mov	%r0, %r9
	exit
	.size	dt_substr, .-dt_substr