Skip to content

Commit

Permalink
Add support for strjoin() subroutine
Browse files Browse the repository at this point in the history
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Sep 9, 2021
1 parent d78ee59 commit 0dbbc74
Show file tree
Hide file tree
Showing 21 changed files with 376 additions and 8 deletions.
1 change: 1 addition & 0 deletions bpf/Build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bpf_dlib_SOURCES = \
get_bvar.c \
get_tvar.c set_tvar.c \
probe_error.c \
strjoin.S \
strlen.c

bpf-check: $(objdir)/include/.dir.stamp
Expand Down
58 changes: 58 additions & 0 deletions bpf/strjoin.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
*/

#define DT_STRLEN_BYTES 2

#define BPF_FUNC_probe_read_str 45

/*
* void dt_strjoin(char *dst, const char *s1, const char *s2)
*/
.text
.align 4
.global dt_strjoin
.type dt_strjoin, @function
dt_strjoin:
mov %r9, %r1 /* %r9 = dst */
mov %r7, %r2 /* %r7 = s1 */
mov %r8, %r3 /* %r8 = s2 */

mov %r1, %r7
call dt_strlen
mov %r6, %r0 /* len = dt_strlen(s1) */
add %r7, DT_STRLEN_BYTES /* s1 += 2 */

mov %r1, %r8
call dt_strlen
add %r6, %r0 /* len += dt_strlen(s2) */
add %r8, DT_STRLEN_BYTES /* s2 += 2 */

mov %r1, %r6
mov %r2, %r9
call dt_strlen_store /* dt_strlen_store(len, dst) */
add %r9, DT_STRLEN_BYTES /* dst += 2 */

lddw %r6, STRSZ
add %r6, 1
and %r6, 0xffffffff /* len = (STRSZ + 1) & 0xffffffff */

mov %r1, %r9
mov %r2, %r6
mov %r3, %r7
call BPF_FUNC_probe_read_str /* cnt = bpf_probe_read_str(dst, len s1) */
jslt %r0, 0, .L1 /* if (cnt < 0) goto .L1 */
jslt %r0, 1, .L2 /* if (cnt < 1) goto .L2 */
sub %r0, 1 /* cnt-- */
add %r9, %r0 /* dst += cnt */
sub %r6, %r0 /* len -= cnt */
add %r6, 1 /* len++ */
.L2:
mov %r1, %r9
mov %r2, %r6
mov %r3, %r8
call BPF_FUNC_probe_read_str /* bpf_probe_read_str(dst, len, s2 */
.L1:
exit
.size dt_strjoin, .-dt_strjoin
68 changes: 63 additions & 5 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,20 +753,30 @@ dt_cg_strlen(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src)
size_t size = yypcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE];
uint_t lbl_ok = dt_irlist_label(dlp);

TRACE_REGSET(" strlen:Begin");

assert(idp != NULL);
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emit(dlp, BPF_MOV_REG(BPF_REG_1, src));
dt_regset_xalloc(drp, BPF_REG_0);
if (src != BPF_REG_1)
emit(dlp, BPF_MOV_REG(BPF_REG_1, src));
if (dst != BPF_REG_0)
dt_regset_xalloc(drp, BPF_REG_0);

emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
dt_regset_free_args(drp);
emit(dlp, BPF_BRANCH_IMM(BPF_JLE, BPF_REG_0, size, lbl_ok));
emit(dlp, BPF_MOV_IMM(BPF_REG_0, size));
emitl(dlp, lbl_ok,
BPF_MOV_REG(dst, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);
BPF_NOP());

if (dst != BPF_REG_0) {
emit(dlp, BPF_MOV_REG(dst, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);
}

TRACE_REGSET(" strlen:End ");
}

static void
Expand Down Expand Up @@ -3123,6 +3133,54 @@ dt_cg_subr_strlen(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-strlen:End ");
}

static void
dt_cg_subr_strjoin(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
dt_node_t *s1 = dnp->dn_args;
dt_node_t *s2 = s1->dn_list;
dt_ident_t *idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_strjoin");

assert(idp != NULL);

TRACE_REGSET(" subr-strjoin:Begin");

dt_cg_node(s1, dlp, drp);
dt_cg_check_notnull(dlp, drp, s1->dn_reg);
dt_cg_node(s2, dlp, drp);
dt_cg_check_notnull(dlp, drp, s2->dn_reg);

/*
* The result needs be be a temporary string, so we request one.
*/
dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_reg == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_cg_tstring_alloc(yypcb, dnp);

emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_DCTX));
emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, DCTX_MEM));
emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));

if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_reg));
emit(dlp, BPF_MOV_REG(BPF_REG_2, s1->dn_reg));
dt_regset_free(drp, s1->dn_reg);
if (s1->dn_tstring)
dt_cg_tstring_free(yypcb, s1);
emit(dlp, BPF_MOV_REG(BPF_REG_3, s2->dn_reg));
dt_regset_free(drp, s2->dn_reg);
if (s2->dn_tstring)
dt_cg_tstring_free(yypcb, s2);
dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
dt_regset_free_args(drp);
dt_regset_free(drp, BPF_REG_0);

TRACE_REGSET(" subr-strjoin:End ");
}

typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);

static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
Expand All @@ -3149,7 +3207,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_GETMAJOR] = NULL,
[DIF_SUBR_GETMINOR] = NULL,
[DIF_SUBR_DDI_PATHNAME] = NULL,
[DIF_SUBR_STRJOIN] = NULL,
[DIF_SUBR_STRJOIN] = dt_cg_subr_strjoin,
[DIF_SUBR_LLTOSTR] = NULL,
[DIF_SUBR_BASENAME] = NULL,
[DIF_SUBR_DIRNAME] = NULL,
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_dlibs.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_set_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strjoin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strnlen, DT_IDENT_SYMBOL),
/* BPF maps */
DT_BPF_SYMBOL(aggs, DT_IDENT_PTR),
Expand Down
36 changes: 36 additions & 0 deletions test/unittest/codegen/tst.dfunc_reg_leak.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

/*
* Ensure that we do not leak registers with void expressions.
*/

#pragma D option quiet

BEGIN {
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
strlen("a");
exit(0);
}

ERROR {
exit(1);
}
1 change: 1 addition & 0 deletions test/unittest/codegen/tst.dfunc_reg_leak.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

36 changes: 36 additions & 0 deletions test/unittest/codegen/tst.tstring_leak.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

/*
* Ensure that we do not leak tstrings with void expressions.
*/

#pragma D option quiet

BEGIN {
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
strjoin("a", "b");
exit(0);
}

ERROR {
exit(1);
}
1 change: 1 addition & 0 deletions test/unittest/codegen/tst.tstring_leak.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

36 changes: 36 additions & 0 deletions test/unittest/codegen/tst.tstring_leak2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

/*
* Ensure that we do not leak tstrings with variable assignments.
*/

#pragma D option quiet

BEGIN {
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
x = strjoin("a", "b");
exit(0);
}

ERROR {
exit(1);
}
1 change: 1 addition & 0 deletions test/unittest/codegen/tst.tstring_leak2.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

6 changes: 5 additions & 1 deletion test/unittest/dif/strjoin.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* @@xfail: dtv2 */
BEGIN
{
trace(strjoin(probeprov, probename));
exit(0);
}

ERROR
{
exit(1);
}
28 changes: 28 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-capped-size-2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

#pragma D option rawbytes
#pragma D option strsize=6
#pragma D option quiet

BEGIN
{
x = probeprov;
y = probename;
z = strjoin(x, y);

trace(x);
trace(y);
trace(z);

exit(0);
}

ERROR
{
exit(1);
}
10 changes: 10 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-capped-size-2.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 06 64 74 72 61 63 65 00 ..dtrace.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 05 42 45 47 49 4e 00 00 ..BEGIN..

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 06 64 74 72 61 63 65 00 ..dtrace.

28 changes: 28 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-capped-size-3.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

#pragma D option rawbytes
#pragma D option strsize=6
#pragma D option quiet

BEGIN
{
x = probeprov;
y = probeprov;
z = strjoin(x, y);

trace(x);
trace(y);
trace(z);

exit(0);
}

ERROR
{
exit(1);
}
10 changes: 10 additions & 0 deletions test/unittest/funcs/strjoin/tst.strjoin-capped-size-3.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 06 64 74 72 61 63 65 00 ..dtrace.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 06 64 74 72 61 63 65 00 ..dtrace.

0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 06 64 74 72 61 63 65 00 ..dtrace.

0 comments on commit 0dbbc74

Please sign in to comment.