in probes/kprobes/test-core.c [1316:1429]
static uintptr_t __used kprobes_test_case_start(const char **title, void *stack)
{
struct test_arg *args;
struct test_arg_end *end_arg;
unsigned long test_code;
current_title = *title++;
args = (struct test_arg *)title;
current_args = args;
current_stack = stack;
++test_try_count;
while (args->type != ARG_TYPE_END)
++args;
end_arg = (struct test_arg_end *)args;
test_code = (unsigned long)(args + 1); /* Code starts after args */
test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
if (test_case_is_thumb)
test_code |= 1;
current_code_start = test_code;
current_branch_target = 0;
if (end_arg->branch_offset != end_arg->end_offset)
current_branch_target = test_code + end_arg->branch_offset;
test_code += end_arg->code_offset;
test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
test_code = next_instruction(test_code);
test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
if (test_case_is_thumb) {
u16 *p = (u16 *)(test_code & ~1);
current_instruction = __mem_to_opcode_thumb16(p[0]);
if (is_wide_instruction(current_instruction)) {
u16 instr2 = __mem_to_opcode_thumb16(p[1]);
current_instruction = __opcode_thumb32_compose(current_instruction, instr2);
}
} else {
current_instruction = __mem_to_opcode_arm(*(u32 *)test_code);
}
if (current_title[0] == '.')
verbose("%s\n", current_title);
else
verbose("%s\t@ %0*x\n", current_title,
test_case_is_thumb ? 4 : 8,
current_instruction);
test_code = next_instruction(test_code);
test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
if (!test_case_is_thumb ||
is_wide_instruction(current_instruction)) {
test_case_failed("expected 16-bit instruction");
goto fail;
}
} else {
if (test_case_is_thumb &&
!is_wide_instruction(current_instruction)) {
test_case_failed("expected 32-bit instruction");
goto fail;
}
}
coverage_add(current_instruction);
if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
if (register_test_probe(&test_case_probe) < 0)
goto pass;
test_case_failed("registered probe for unsupported instruction");
goto fail;
}
if (end_arg->flags & ARG_FLAG_SUPPORTED) {
if (register_test_probe(&test_case_probe) >= 0)
goto pass;
test_case_failed("couldn't register probe for supported instruction");
goto fail;
}
if (register_test_probe(&test_before_probe) < 0) {
test_case_failed("register test_before_probe failed");
goto fail;
}
if (register_test_probe(&test_after_probe) < 0) {
test_case_failed("register test_after_probe failed");
goto fail;
}
if (current_branch_target) {
test_after2_probe.kprobe.addr =
(kprobe_opcode_t *)current_branch_target;
if (register_test_probe(&test_after2_probe) < 0) {
test_case_failed("register test_after2_probe failed");
goto fail;
}
}
/* Start first run of test case */
test_case_run_count = 0;
++test_instance;
return current_code_start;
pass:
test_case_run_count = TEST_CASE_PASSED;
return (uintptr_t)test_after_probe.kprobe.addr;
fail:
test_case_run_count = TEST_CASE_FAILED;
return (uintptr_t)test_after_probe.kprobe.addr;
}