[DTrace-devel] [PATCH v2 3/3] String args to dt_strcmp() need to be copied if not DPTR
Eugene Loh
eugene.loh at oracle.com
Sat Oct 8 04:31:37 UTC 2022
Actually, wait a minute. Does this patch pass testing? The new tests
check against BPF verifier failures, but are the comparisons being
performed correctly? Do older tests like
operators/tst.str_comparison*.d pass? (str_comparison-basic.d has been
failing for a while due to NULL-pointer support, but that's a different
issue.) Comments below:
On 10/6/22 20:48, Kris Van Hees via DTrace-devel wrote:
> diff --git a/bpf/strcmp.S b/bpf/strcmp.S
> @@ -86,8 +87,14 @@ dt_strcmp_not :
> * // based on this location, judge if the strings are >, <, or ==
> * if (r0 > r6) goto Lsame;
> * if (r0 > r7) goto Lsame;
> - * if (s[r0] > t[r0]) return +1;
> - * if (s[r0] < t[r0]) return +1;
> +
> + * s += r0;
> + * t += r0;
> +
> + * if (flags & 1) { } else { bpf_probe_read(tmp1, 1, s); s = tmp1; }
> + * if (flags & 2) { } else { bpf_probe_read(tmp2, 1, t); t = tmp2; }
> + * if (s[0] > t[0]) return +1;
> + * if (s[0] < t[0]) return +1;
> *
> * // if all chars are the same, break tie on string length
> * Lsame:
> @@ -158,20 +166,37 @@ dt_strcmp :
> jgt %r0, %r6, .Lsame /* if (r0 > r6) goto Lsame */
> jgt %r0, %r8, .Lsame /* if (r0 > r8) goto Lsame */
Hmm. The above two lines predate this patch, but presumably the second
line is wrong. Earlier comments claim we should be checking r0>r7, not
r0>r8.
> - ldxdw %r4, [%fp+-8]
> - add %r4, %r0
> - ldxb %r4, [%r4+0] /* s[r0] */
> - and %r4, 0xff
> + ldxdw %r6, [%fp+-8]
> + add %r6, %r8 /* s += r0 */
> + ldxdw %r7, [%fp+-16]
> + add %r7, %r8 /* t += r0 */
The code is doing +=%r8 but the comments claim +=r0. I think the
comments are right. The code is wrong. Presumably the problem is the
v1 patch stashed r0 in r8, but that is no longer the case in the v2 patch.
By the way, this patch's fancy handling of t (identification of !DPTR
via flags and special code to handle that case) is unnecessary. We
already copied t into tmp2 anyhow, and there it still sits. So, there
is no need for this patch's new code in the t case. Instead of loading
t (%fp+-16) just load tmp2 (%fp+-32). Simple fix.
> + jset %r9, 1, .Ls_is_dptr
> + ldxdw %r1, [%fp+-24]
> + mov %r2, 1
> + mov %r3, %r6
> + mov %r6, %r1 /* s = tmp1 (after the helper call) */
> + call BPF_FUNC_probe_read /* bpf_probe_read(tmp1, r8, s) */
> +.Ls_is_dptr:
> +
> + jset %r9, 2, .Lt_is_dptr
> + ldxdw %r1, [%fp+-32]
> + mov %r2, 1
> + mov %r3, %r7
> + mov %r7, %r1 /* t = tmp2 (after the helper call) */
> + call BPF_FUNC_probe_read /* bpf_probe_read(tmp2, r8, t) */
> +.Lt_is_dptr:
> +
> + ldxb %r6, [%r6+0] /* s[0] */
> + and %r6, 0xff
>
> - ldxdw %r5, [%fp+-16]
> - add %r5, %r0
> - ldxb %r5, [%r5+0] /* t[r0] */
> - and %r5, 0xff
> + ldxb %r7, [%r7+0] /* t[0] */
> + and %r7, 0xff
>
> - jle %r4, %r5, 2 /* if (s[r0] > t[r0]) return +1 */
> + jle %r6, %r7, 2 /* if (s[0] > t[0]) return +1 */
> mov %r0, 1
> exit
> - jge %r4, %r5, 2 /* if (s[r0] < t[r0]) return +1 */
> + jge %r6, %r7, 2 /* if (s[0] < t[0]) return +1 */
> mov %r0, -1
> exit
This is also a little weird -- in part due to pre-existing oddities and
now even more peculiar due to the patch. If that last branch (jge)
jumps, we end up at .Lsame. (That code doesn't show up here since the
patch doesn't change it.) In .Lsame, we compare %r6 and %r7, but this
patch has just overwritten them. So that suggests this patch is wrong.
But, the overwriting might not matter. (Presumably, r0 is the first
byte that does not match. So one we test s[r0]>t[r0] and fall through,
there is no further need for testing. We presumably know s[r0]!=t[r0].
So the pre-existing code could just have returned +1 at this point,
without further branching.)
More information about the DTrace-devel
mailing list