NAME list uprobe args - basic type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test:main'
EXPECT int argc
REQUIRES_FEATURE dwarf

NAME list uprobe args - pointer type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test:uprobeFunction1'
EXPECT int * n
REQUIRES_FEATURE dwarf

NAME list uprobe args - struct pointer type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test:uprobeFunction2'
EXPECT struct Foo * foo1
REQUIRES_FEATURE dwarf

NAME list uprobe args - anonymous param type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test:uprobeFunction3'
EXPECT enum { A, B, C } e
       union { int a; char b; } u
REQUIRES bash -c "exit 1" # SKIP: anonymous parameter type not supported #3083
REQUIRES_FEATURE dwarf

NAME list uprobe args - class reference type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeFunction1'
EXPECT     int & x
           Foo & foo
           Bar & bar
REQUIRES_FEATURE dwarf

NAME list uprobe args - array reference type
RUN {{BPFTRACE}} -lv 'uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeArray'
EXPECT int (&)[10] array
REQUIRES_FEATURE dwarf

NAME uprobe arg by name - char
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { printf("c = %c\n", args.c); exit(); }
EXPECT c = x
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME uprobe arg by name - pointer
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { printf("n = %d\n", *(args.n)); exit(); }
EXPECT n = 13
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME uprobe arg by name - struct
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 { printf("foo1->a = %d\n", args.foo1->a); exit(); }
EXPECT foo1->a = 123
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

# NAME uprobe arg by index - 128-bits integer
# PROG uprobe:./testprogs/uprobe_test:uprobeFunctionUint128 { printf("x = %x\ny = %x\nz = %x\nw = %x\n", arg0, arg1, arg2, arg3); exit(); }
# EXPECT x = 9abcdef0
#        y = efefefef
#        z = cdcdcdcd
#        w = abababab
# REQUIRES_FEATURE dwarf
# AFTER ./testprogs/uprobe_test

# NAME uprobe arg by name - 128-bits integer
# PROG uprobe:./testprogs/uprobe_test:uprobeFunctionUint128 { printf("x = %x\ny = %x\nz = %x\nw = %x\n", args.x, args.y, args.z, args.w); exit(); }
# EXPECT x = 9abcdef0
#        y = efefefef
#        z = cdcdcdcd
#        w = abababab
# REQUIRES_FEATURE dwarf
# AFTER ./testprogs/uprobe_test

NAME uprobe arg by name - struct with 128-bits integer
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 { printf("foo1->d = %x\n", args.foo1->d); exit(); }
EXPECT foo1->d = 9abcdef0
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME uprobe without dwarf
PROG config = { symbol_source = "symbol_table"; cache_user_symbols = "PER_PROGRAM"; }
     uprobe:./testprogs/uprobe_test:uprobeFunction1 { print(ustack); exit(); }
EXPECT uprobeFunction1+0
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME uprobe inline without dwarf
PROG config = { symbol_source = "symbol_table"; probe_inline = 1; }
     uprobe:./testprogs/inline_function:square { @count++ }
     uretprobe:./testprogs/inline_function:main { exit() }
EXPECT @count: 1
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME uprobe skip inlined function
PROG config = { probe_inline = 0 }
     uprobe:./testprogs/inline_function:square { @count++ }
     uretprobe:./testprogs/inline_function:main { exit() }
EXPECT @count: 1
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME uprobe inlined function
PROG config = { probe_inline = 1 }
     uprobe:./testprogs/inline_function:square { @count++ }
     uretprobe:./testprogs/inline_function:main { exit() }
EXPECT @count: 3
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME uprobe inlined function - probe
PROG config = { probe_inline = 1; cache_user_symbols = "PER_PROGRAM"; }
     uprobe:./testprogs/inline_function:square {
       printf("%s\n", probe);
       if (++@count == 3) { exit(); }
     }
EXPECT uprobe:./testprogs/inline_function:square
       uprobe:./testprogs/inline_function:square
       uprobe:./testprogs/inline_function:square
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME uprobe inlined function - func
PROG config = { probe_inline = 1; cache_user_symbols = "PER_PROGRAM"; }
     uprobe:./testprogs/inline_function:square {
       printf("%s\n", func);
       if (++@count == 3) { exit(); }
     }
EXPECT main
       main
       square
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME uprobe inlined function - ustack
PROG config = { probe_inline = 1; cache_user_symbols = "PER_PROGRAM"; }
     uprobe:./testprogs/inline_function:square {
       printf("%s\n", ustack);
       if (++@count == 3) { exit(); }
     }
EXPECT_REGEX ^\n[ ]+main\+\d+$
EXPECT_REGEX ^\n[ ]+square\+\d+\n[ ]+main\+\d+$
REQUIRES_FEATURE dwarf
AFTER ./testprogs/inline_function

NAME print uprobe arg as deref pointer - struct
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 {
       print(*args.foo1);
       exit();
     }
EXPECT { .a = 123, .b = hello, .c = [1,2,3], .d = 1311768467463790320 }
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME uprobe arg as reference - int
PROG uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeFunction1 {
       printf("x = %d\n", args.x);
       exit();
     }
EXPECT x = 42
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test_cxx

NAME print uprobe arg as reference - struct
PROG uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeFunction1 {
       print(args.foo);
       exit();
     }
EXPECT_REGEX ^\{ \.a = 1, \.b = 2, \.c = 3, \.x = 0x[0-9a-f]{1,16} \}$
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test_cxx

NAME uprobe arg as reference - struct member
PROG uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeFunction1 {
       printf("foo.a = %d\nfoo.b = %d\nfoo.c = %d\nfoo.x = %d\n",
         args.foo.a, args.foo.b, args.foo.c, args.foo.x);
       exit();
     }
EXPECT foo.a = 1
       foo.b = 2
       foo.c = 3
       foo.x = 42
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test_cxx

NAME uprobe arg as reference - array
PROG uprobe:./testprogs/uprobe_test_cxx:cpp:uprobeArray {
       printf("arr[0] = %d, arr[1] = %d, arr[9] = %d\n",
         args.array[0], args.array[1], args.array[9]);
       exit();
     }
EXPECT arr[0] = 1, arr[1] = 2, arr[9] = 10
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test_cxx

# Checking backwards compatibility
NAME uprobe args as pointer
PROG uprobe:./testprogs/uprobe_test:uprobeFunction1 { printf("c = %c\n", args->c); exit(); }
EXPECT c = x
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME struct field string
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 { printf("foo1->b = %s\n", args.foo1->b); exit(); }
EXPECT foo1->b = hello
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME struct field array
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 { print(args.foo1->c); exit(); }
EXPECT [1,2,3]
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME cast to struct
PROG uprobe:./testprogs/uprobe_test:uprobeFunction2 { printf("foo1->a = %d\n", ((struct Foo *)arg0)->a); exit(); }
EXPECT foo1->a = 123
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

NAME struct override
PROG struct Foo { int b; } uprobe:./testprogs/uprobe_test:uprobeFunction2 { printf("foo1->b = %d\n", ((struct Foo *)arg0)->b); exit(); }
EXPECT foo1->b = 123
REQUIRES_FEATURE dwarf
AFTER ./testprogs/uprobe_test

# The function `str_has_prefix` is marked to be always inlined, so we'll get
# more than one occurrence for it.
# We first check that bpftrace attaches to more probes than the two defined in the script.
# We also check that the offsets bpftrace attaches to are different from 0,
# since they should be inline instances part of another function/symbol.
NAME kprobe inlined function
RUN {{BPFTRACE}} -ve \ 'config = { probe_inline = 1 } BEGIN { exit() } kprobe:str_has_prefix { }'
EXPECT_NONE Attaching 1 probe...
EXPECT_NONE Attaching 2 probes...
EXPECT_REGEX_NONE ^bpf_attach_kprobe\(.*, 0, 0\)$
REQUIRES_FEATURE dwarf kernel_dwarf
