1570af302Sopenharmony_ci#include <stdlib.h>
2570af302Sopenharmony_ci#include <signal.h>
3570af302Sopenharmony_ci#include "syscall.h"
4570af302Sopenharmony_ci#include "pthread_impl.h"
5570af302Sopenharmony_ci#include "atomic.h"
6570af302Sopenharmony_ci#include "lock.h"
7570af302Sopenharmony_ci#include "ksigaction.h"
8570af302Sopenharmony_ci#if defined(MUSL_AARCH64_ARCH)
9570af302Sopenharmony_ci#include <stdint.h>
10570af302Sopenharmony_ci#include <stdio.h>
11570af302Sopenharmony_ci#include <inttypes.h>
12570af302Sopenharmony_ci#include <info/fatal_message.h>
13570af302Sopenharmony_ci
14570af302Sopenharmony_ci#define MESSAGE_BUFFER_SIZE 512
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci/**
17570af302Sopenharmony_ci * @brief Retrieves the current value of the x1 register on AArch64.
18570af302Sopenharmony_ci *
19570af302Sopenharmony_ci * This function is used in CFI checks to obtain the function address
20570af302Sopenharmony_ci * stored in the x1 register during calls involving function pointers,
21570af302Sopenharmony_ci * virtual calls (vcall), and non-virtual calls (nvcall) using vtable addresses.
22570af302Sopenharmony_ci *
23570af302Sopenharmony_ci * @return Value of the x1 register.
24570af302Sopenharmony_ci */
25570af302Sopenharmony_ciuint64_t fetch_function_address()
26570af302Sopenharmony_ci{
27570af302Sopenharmony_ci	uint64_t val;
28570af302Sopenharmony_ci	__asm__ __volatile__(
29570af302Sopenharmony_ci		"mov %0, x1"
30570af302Sopenharmony_ci		: "=r" (val)
31570af302Sopenharmony_ci		:
32570af302Sopenharmony_ci		: "memory"
33570af302Sopenharmony_ci	);
34570af302Sopenharmony_ci	return val;
35570af302Sopenharmony_ci}
36570af302Sopenharmony_ci#endif
37570af302Sopenharmony_ci
38570af302Sopenharmony_ci_Noreturn void __cfi_fail_report(void)
39570af302Sopenharmony_ci{
40570af302Sopenharmony_ci#if defined(MUSL_AARCH64_ARCH)
41570af302Sopenharmony_ci	uint64_t function_address = fetch_function_address();
42570af302Sopenharmony_ci	char message[MESSAGE_BUFFER_SIZE];
43570af302Sopenharmony_ci	snprintf(message, sizeof(message),
44570af302Sopenharmony_ci			" CFI check failed. Function Address: 0x%" PRIx64, function_address);
45570af302Sopenharmony_ci	set_fatal_message(message);
46570af302Sopenharmony_ci#endif
47570af302Sopenharmony_ci	abort();
48570af302Sopenharmony_ci}
49570af302Sopenharmony_ci
50570af302Sopenharmony_ci_Noreturn void abort(void)
51570af302Sopenharmony_ci{
52570af302Sopenharmony_ci#ifdef __LITEOS_A__
53570af302Sopenharmony_ci	sigset_t set, pending;
54570af302Sopenharmony_ci	sigemptyset(&set);
55570af302Sopenharmony_ci	sigaddset(&set, SIGABRT);
56570af302Sopenharmony_ci
57570af302Sopenharmony_ci	sigpending(&pending);
58570af302Sopenharmony_ci	__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, &set, 0, _NSIG / 8);
59570af302Sopenharmony_ci	if (!sigismember(&pending, SIGABRT)) {
60570af302Sopenharmony_ci		raise(SIGABRT);
61570af302Sopenharmony_ci	}
62570af302Sopenharmony_ci#else
63570af302Sopenharmony_ci	raise(SIGABRT);
64570af302Sopenharmony_ci#endif
65570af302Sopenharmony_ci
66570af302Sopenharmony_ci	/* If there was a SIGABRT handler installed and it returned, or if
67570af302Sopenharmony_ci	 * SIGABRT was blocked or ignored, take an AS-safe lock to prevent
68570af302Sopenharmony_ci	 * sigaction from installing a new SIGABRT handler, uninstall any
69570af302Sopenharmony_ci	 * handler that may be present, and re-raise the signal to generate
70570af302Sopenharmony_ci	 * the default action of abnormal termination. */
71570af302Sopenharmony_ci	__block_all_sigs(0);
72570af302Sopenharmony_ci	LOCK(__abort_lock);
73570af302Sopenharmony_ci#ifdef __LITEOS_A__
74570af302Sopenharmony_ci	signal(SIGABRT, SIG_DFL);
75570af302Sopenharmony_ci#else
76570af302Sopenharmony_ci	__syscall(SYS_rt_sigaction, SIGABRT,
77570af302Sopenharmony_ci		&(struct k_sigaction){.handler = SIG_DFL}, 0, _NSIG/8);
78570af302Sopenharmony_ci#endif
79570af302Sopenharmony_ci	__syscall(SYS_tkill, __pthread_self()->tid, SIGABRT);
80570af302Sopenharmony_ci	__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
81570af302Sopenharmony_ci		&(long[_NSIG/(8*sizeof(long))]){1UL<<(SIGABRT-1)}, 0, _NSIG/8);
82570af302Sopenharmony_ci
83570af302Sopenharmony_ci	/* Beyond this point should be unreachable. */
84570af302Sopenharmony_ci	a_crash();
85570af302Sopenharmony_ci	raise(SIGKILL);
86570af302Sopenharmony_ci	_Exit(127);
87570af302Sopenharmony_ci}
88