1351282Sdim//===-- safestack_platform.h ----------------------------------------------===//
2351282Sdim//
3351282Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4351282Sdim// See https://llvm.org/LICENSE.txt for license information.
5351282Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6351282Sdim//
7351282Sdim//===----------------------------------------------------------------------===//
8351282Sdim//
9351282Sdim// This file implements platform specific parts of SafeStack runtime.
10351282Sdim//
11351282Sdim//===----------------------------------------------------------------------===//
12351282Sdim
13351282Sdim#ifndef SAFESTACK_PLATFORM_H
14351282Sdim#define SAFESTACK_PLATFORM_H
15351282Sdim
16351282Sdim#include "safestack_util.h"
17351282Sdim#include "sanitizer_common/sanitizer_platform.h"
18351282Sdim
19351282Sdim#include <dlfcn.h>
20351282Sdim#include <stdint.h>
21351282Sdim#include <stdio.h>
22351282Sdim#include <stdlib.h>
23351282Sdim#include <sys/mman.h>
24351282Sdim#include <sys/syscall.h>
25351282Sdim#include <sys/types.h>
26351282Sdim#include <unistd.h>
27351282Sdim
28351282Sdim#if !(SANITIZER_NETBSD || SANITIZER_FREEBSD || SANITIZER_LINUX)
29351282Sdim#error "Support for your platform has not been implemented"
30351282Sdim#endif
31351282Sdim
32351282Sdim#if SANITIZER_NETBSD
33351282Sdim#include <lwp.h>
34351282Sdim
35351282Sdimextern "C" void *__mmap(void *, size_t, int, int, int, int, off_t);
36351282Sdim#endif
37351282Sdim
38351282Sdim#if SANITIZER_FREEBSD
39351282Sdim#include <sys/thr.h>
40351282Sdim#endif
41351282Sdim
42351282Sdimnamespace safestack {
43351282Sdim
44351282Sdim#if SANITIZER_NETBSD
45351282Sdimstatic void *GetRealLibcAddress(const char *symbol) {
46351282Sdim  void *real = dlsym(RTLD_NEXT, symbol);
47351282Sdim  if (!real)
48351282Sdim    real = dlsym(RTLD_DEFAULT, symbol);
49351282Sdim  if (!real) {
50351282Sdim    fprintf(stderr, "safestack GetRealLibcAddress failed for symbol=%s",
51351282Sdim            symbol);
52351282Sdim    abort();
53351282Sdim  }
54351282Sdim  return real;
55351282Sdim}
56351282Sdim
57351282Sdim#define _REAL(func, ...) real##_##func(__VA_ARGS__)
58351282Sdim#define DEFINE__REAL(ret_type, func, ...)                              \
59351282Sdim  static ret_type (*real_##func)(__VA_ARGS__) = NULL;                  \
60351282Sdim  if (!real_##func) {                                                  \
61351282Sdim    real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
62351282Sdim  }                                                                    \
63351282Sdim  SFS_CHECK(real_##func);
64351282Sdim#endif
65351282Sdim
66351282Sdimusing ThreadId = uint64_t;
67351282Sdim
68351282Sdiminline ThreadId GetTid() {
69351282Sdim#if SANITIZER_NETBSD
70351282Sdim  DEFINE__REAL(int, _lwp_self);
71351282Sdim  return _REAL(_lwp_self);
72351282Sdim#elif SANITIZER_FREEBSD
73351282Sdim  long Tid;
74351282Sdim  thr_self(&Tid);
75351282Sdim  return Tid;
76351282Sdim#else
77351282Sdim  return syscall(SYS_gettid);
78351282Sdim#endif
79351282Sdim}
80351282Sdim
81351282Sdiminline int TgKill(pid_t pid, ThreadId tid, int sig) {
82351282Sdim#if SANITIZER_NETBSD
83351282Sdim  DEFINE__REAL(int, _lwp_kill, int a, int b);
84351282Sdim  (void)pid;
85351282Sdim  return _REAL(_lwp_kill, tid, sig);
86351282Sdim#elif SANITIZER_FREEBSD
87351282Sdim  return syscall(SYS_thr_kill2, pid, tid, sig);
88351282Sdim#else
89351282Sdim  return syscall(SYS_tgkill, pid, tid, sig);
90351282Sdim#endif
91351282Sdim}
92351282Sdim
93351282Sdiminline void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
94351282Sdim                  off_t offset) {
95351282Sdim#if SANITIZER_NETBSD
96351282Sdim  return __mmap(addr, length, prot, flags, fd, 0, offset);
97351282Sdim#elif defined(__x86_64__) && (SANITIZER_FREEBSD)
98351282Sdim  return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
99351282Sdim#else
100351282Sdim  return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
101351282Sdim#endif
102351282Sdim}
103351282Sdim
104351282Sdiminline int Munmap(void *addr, size_t length) {
105351282Sdim#if SANITIZER_NETBSD
106351282Sdim  DEFINE__REAL(int, munmap, void *a, size_t b);
107351282Sdim  return _REAL(munmap, addr, length);
108351282Sdim#else
109351282Sdim  return syscall(SYS_munmap, addr, length);
110351282Sdim#endif
111351282Sdim}
112351282Sdim
113351282Sdiminline int Mprotect(void *addr, size_t length, int prot) {
114351282Sdim#if SANITIZER_NETBSD
115351282Sdim  DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
116351282Sdim  return _REAL(mprotect, addr, length, prot);
117351282Sdim#else
118351282Sdim  return syscall(SYS_mprotect, addr, length, prot);
119351282Sdim#endif
120351282Sdim}
121351282Sdim
122351282Sdim}  // namespace safestack
123351282Sdim
124351282Sdim#endif  // SAFESTACK_PLATFORM_H
125