tools/perf/tests/dwarf-unwind.c

Source file repositories/reference/linux-study-clean/tools/perf/tests/dwarf-unwind.c

File Facts

System
Linux kernel
Corpus path
tools/perf/tests/dwarf-unwind.c
Extension
.c
Size
5822 bytes
Lines
224
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

else if (cnt != MAX_STACK) {
		pr_debug("got wrong number of stack entries %lu != %d\n",
			 cnt, MAX_STACK);
		err = -1;
	}

 out:
	zfree(&sample.user_stack.data);
	zfree(&sample.user_regs->regs);
	perf_sample__exit(&sample);
	return err;
}

static int global_unwind_retval = -INT_MAX;

NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p2)
{
	/* Any possible value should be 'thread' */
	struct thread *thread = *(struct thread **)p1;

	if (global_unwind_retval == -INT_MAX) {
		/* Call unwinder twice for both callchain orders. */
		callchain_param.order = ORDER_CALLER;

		global_unwind_retval = test_dwarf_unwind__thread(thread);
		if (!global_unwind_retval) {
			callchain_param.order = ORDER_CALLEE;
			global_unwind_retval = test_dwarf_unwind__thread(thread);
		}
	}

	return p1 - p2;
}

NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *thread)
{
	struct thread *array[2] = {thread, thread};
	void *fp = &bsearch;
	/*
	 * make _bsearch a volatile function pointer to
	 * prevent potential optimization, which may expand
	 * bsearch and call compare directly from this function,
	 * instead of libc shared object.
	 */
	void *(*volatile _bsearch)(void *, void *, size_t,
			size_t, int (*)(void *, void *));

	_bsearch = fp;
	_bsearch(array, &thread, 2, sizeof(struct thread **),
		 test_dwarf_unwind__compare);
	return global_unwind_retval;
}

NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *thread)
{
	int ret;

	ret =  test_dwarf_unwind__krava_3(thread);
	NO_TAIL_CALL_BARRIER;
	return ret;
}

NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *thread)
{
	int ret;

	ret =  test_dwarf_unwind__krava_2(thread);
	NO_TAIL_CALL_BARRIER;
	return ret;
}

noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
				int subtest __maybe_unused)
{
	struct perf_env host_env;
	struct machine *machine;
	struct thread *thread;
	int err = -1;
	pid_t pid = getpid();

	callchain_param.record_mode = CALLCHAIN_DWARF;
	dwarf_callchain_users = true;

	perf_env__init(&host_env);
	machine = machine__new_live(&host_env, /*kernel_maps=*/true, pid);
	if (!machine) {
		pr_err("Could not get machine\n");
		goto out;
	}

Annotation

Implementation Notes