162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <string.h>
362306a36Sopenharmony_ci#include "perf_regs.h"
462306a36Sopenharmony_ci#include "thread.h"
562306a36Sopenharmony_ci#include "map.h"
662306a36Sopenharmony_ci#include "maps.h"
762306a36Sopenharmony_ci#include "event.h"
862306a36Sopenharmony_ci#include "debug.h"
962306a36Sopenharmony_ci#include "tests/tests.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define STACK_SIZE 8192
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic int sample_ustack(struct perf_sample *sample,
1462306a36Sopenharmony_ci		struct thread *thread, u64 *regs)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct stack_dump *stack = &sample->user_stack;
1762306a36Sopenharmony_ci	struct map *map;
1862306a36Sopenharmony_ci	unsigned long sp;
1962306a36Sopenharmony_ci	u64 stack_size, *buf;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	buf = malloc(STACK_SIZE);
2262306a36Sopenharmony_ci	if (!buf) {
2362306a36Sopenharmony_ci		pr_debug("failed to allocate sample uregs data\n");
2462306a36Sopenharmony_ci		return -1;
2562306a36Sopenharmony_ci	}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	sp = (unsigned long) regs[PERF_REG_ARM64_SP];
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	map = maps__find(thread__maps(thread), (u64)sp);
3062306a36Sopenharmony_ci	if (!map) {
3162306a36Sopenharmony_ci		pr_debug("failed to get stack map\n");
3262306a36Sopenharmony_ci		free(buf);
3362306a36Sopenharmony_ci		return -1;
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	stack_size = map__end(map) - sp;
3762306a36Sopenharmony_ci	stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	memcpy(buf, (void *) sp, stack_size);
4062306a36Sopenharmony_ci	stack->data = (char *) buf;
4162306a36Sopenharmony_ci	stack->size = stack_size;
4262306a36Sopenharmony_ci	return 0;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ciint test__arch_unwind_sample(struct perf_sample *sample,
4662306a36Sopenharmony_ci		struct thread *thread)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	struct regs_dump *regs = &sample->user_regs;
4962306a36Sopenharmony_ci	u64 *buf;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
5262306a36Sopenharmony_ci	if (!buf) {
5362306a36Sopenharmony_ci		pr_debug("failed to allocate sample uregs data\n");
5462306a36Sopenharmony_ci		return -1;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	perf_regs_load(buf);
5862306a36Sopenharmony_ci	regs->abi  = PERF_SAMPLE_REGS_ABI;
5962306a36Sopenharmony_ci	regs->regs = buf;
6062306a36Sopenharmony_ci	regs->mask = PERF_REGS_MASK;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return sample_ustack(sample, thread, buf);
6362306a36Sopenharmony_ci}
64