static uintptr_t __used kprobes_test_case_start()

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;
}