* Copyright (c) 2011-2022 Google, Inc. All rights reserved.
* Copyright (c) 2008-2010 VMware, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
* os_private.h - declarations shared among os-specific files, but not
* exported to the rest of the code
*/
#ifndef _OS_PRIVATE_H_
#define _OS_PRIVATE_H_ 1
#include <signal.h>
#include "include/siginfo.h"
#include "module.h"
#include "ksynch.h"
#include "instr.h"
#include <sys/time.h>
#include "dr_config.h"
#include "tls.h"
#include "memquery.h"
#include "../drlibc/drlibc_unix.h"
#ifdef DR_HOST_X86
# ifdef DR_HOST_X64
# define ASM_XAX "rax"
# define ASM_XCX "rcx"
# define ASM_XDX "rdx"
# define ASM_XBP "rbp"
# define ASM_XSP "rsp"
# define ASM_XSP "rsp"
# else
# define ASM_XAX "eax"
# define ASM_XCX "ecx"
# define ASM_XDX "edx"
# define ASM_XBP "ebp"
# define ASM_XSP "esp"
# endif
#elif defined(DR_HOST_AARCH64)
# define ASM_R0 "x0"
# define ASM_R1 "x1"
# define ASM_R2 "x2"
# define ASM_R3 "x3"
# define ASM_XSP "sp"
# define ASM_INDJMP "br"
#elif defined(DR_HOST_ARM)
# define ASM_R0 "r0"
# define ASM_R1 "r1"
# define ASM_R2 "r2"
# define ASM_R3 "r3"
# define ASM_XSP "sp"
# define ASM_INDJMP "bx"
#elif defined(DR_HOST_RISCV64)
# define ASM_R0 "a0"
# define ASM_R1 "a1"
# define ASM_R2 "a2"
# define ASM_R3 "a3"
# define ASM_XSP "sp"
# define ASM_INDJMP "jr"
#endif
#define MACHINE_TLS_IS_DR_TLS IF_X86_ELSE(INTERNAL_OPTION(mangle_app_seg), true)
* It may equal NUDGESIG_SIGNUM.
*/
extern int suspend_signum;
#define SUSPEND_SIGNAL suspend_signum
#ifdef MACOS
* code more easily with Linux.
*/
# define CLONE_VM 0x00000100
# define CLONE_FS 0x00000200
# define CLONE_FILES 0x00000400
# define CLONE_SIGHAND 0x00000800
# define CLONE_VFORK 0x00004000
# define CLONE_PARENT 0x00008000
# define CLONE_THREAD 0x00010000
# define CLONE_SYSVSEM 0x00040000
# define CLONE_SETTLS 0x00080000
# define CLONE_PARENT_SETTID 0x00100000
# define CLONE_CHILD_CLEARTID 0x00200000
#endif
*/
#define PTHREAD_CLONE_FLAGS \
(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | \
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID)
#define SYSCALL_PARAM_CLONE_STACK 1
#define SYSCALL_PARAM_CLONE3_CLONE_ARGS 0
#define SYSCALL_PARAM_CLONE3_CLONE_ARGS_SIZE 1
#define CLONE3_FLAGS_4_BYTE_MASK 0x00000000ffffffffUL
struct _os_local_state_t;
typedef struct _os_thread_data_t {
* /proc/self/maps w/ later mprotects and it can be hard to piece together later
*/
app_pc stack_base;
app_pc stack_top;
#ifdef RETURN_AFTER_CALL
app_pc stack_bottom_pc;
#endif
* access to suspend_count and the bools below in os_thread_suspend
* and suspend_resume. handle_suspend_signal() does not use the
* mutex as it is not safe to do so, but our suspend and resume
* synch avoids any need for it there.
*/
mutex_t suspend_lock;
int suspend_count;
thread_record_t **fork_threads;
int fork_num_threads;
* our signal handler
*/
* thread(s). See i#96/PR 295561.
*/
KSYNCH_TYPE suspended;
KSYNCH_TYPE wakeup;
KSYNCH_TYPE resumed;
sig_full_cxt_t *suspended_sigcxt;
bool terminate;
* thread(s). See i#96/PR 295561.
*/
KSYNCH_TYPE terminated;
KSYNCH_TYPE detached;
volatile bool do_detach;
volatile bool retakeover;
int processing_signal;
* and LIB_SEG_TLS. If -mangle_app_seg is off, the base for LIB_SEG_TLS
* will be NULL, but the base for SEG_TLS will still be present.
*/
void *priv_lib_tls_base;
void *priv_alt_tls_base;
void *dr_tls_base;
#ifdef X86
void *app_thread_areas;
struct _os_local_state_t *clone_tls;
#endif
} os_thread_data_t;
enum { ARGC_PTRACE_SENTINEL = -1 };
typedef struct ptrace_stack_args_t {
ptr_int_t argc;
priv_mcontext_t mc;
char home_dir[MAXIMUM_PATH];
} ptrace_stack_args_t;
byte *
mmap_syscall(byte *addr, size_t len, ulong prot, ulong flags, ulong fd, ulong offs);
long
munmap_syscall(byte *addr, size_t len);
bool
os_thread_take_over(priv_mcontext_t *mc, kernel_sigset_t *sigset);
void *
os_get_priv_tls_base(dcontext_t *dcontext, reg_id_t seg);
void
os_tls_thread_exit(local_state_t *local_state);
#ifdef AARCHXX
bool
os_set_app_tls_base(dcontext_t *dcontext, reg_id_t reg, void *base);
#endif
#ifdef MACOS
# define MACOS_VERSION_MOJAVE 18
# define MACOS_VERSION_HIGH_SIERRA 17
# define MACOS_VERSION_SIERRA 16
# define MACOS_VERSION_EL_CAPITAN 15
# define MACOS_VERSION_YOSEMITE 14
# define MACOS_VERSION_MAVERICKS 13
# define MACOS_VERSION_MOUNTAIN_LION 12
# define MACOS_VERSION_LION 11
int
os_get_version(void);
#endif
void
set_executable_path(const char *);
void
set_app_args(int *, char **);
uint
memprot_to_osprot(uint prot);
bool
mmap_syscall_succeeded(byte *retval);
bool
os_files_same(const char *path1, const char *path2);
extern const reg_id_t syscall_regparms[MAX_SYSCALL_ARGS];
void
set_syscall_param(dcontext_t *dcontext, int param_num, reg_t new_value);
file_t
fd_priv_dup(file_t curfd);
bool
fd_mark_close_on_exec(file_t fd);
void
fd_table_add(file_t fd, uint flags);
uint
permstr_to_memprot(const char *const perm);
* Returns the number of executable regions found in the address space.
*/
int
os_walk_address_space(memquery_iter_t *iter, bool add_modules);
bool
is_sigreturn_syscall_number(int sysnum);
bool
is_sigqueue_supported(void);
struct _kernel_sigaction_t;
typedef struct _kernel_sigaction_t kernel_sigaction_t;
struct _old_sigaction_t;
typedef struct _old_sigaction_t old_sigaction_t;
#ifdef MACOS
struct _prev_sigaction_t;
typedef struct _prev_sigaction_t prev_sigaction_t;
#else
typedef kernel_sigaction_t prev_sigaction_t;
#endif
void
d_r_signal_init(void);
void
d_r_signal_exit(void);
void
signal_thread_init(dcontext_t *dcontext, void *os_data);
void
signal_thread_exit(dcontext_t *dcontext, bool other_thread);
void
block_all_noncrash_signals_except(kernel_sigset_t *oset, int num_signals, ...);
void
block_cleanup_and_terminate(dcontext_t *dcontext, int sysnum, ptr_uint_t sys_arg1,
ptr_uint_t sys_arg2, bool exitproc,
ptr_uint_t sys_arg3, ptr_uint_t sys_arg4);
bool
is_thread_signal_info_initialized(dcontext_t *dcontext);
void
signal_swap_mask(dcontext_t *dcontext, bool to_app);
void
signal_remove_handlers(dcontext_t *dcontext);
void
signal_reinstate_handlers(dcontext_t *dcontext, bool ignore_alarm);
void
signal_reinstate_alarm_handlers(dcontext_t *dcontext);
void
handle_clone(dcontext_t *dcontext, uint64 flags);
bool
handle_sigaction(dcontext_t *dcontext, int sig, const kernel_sigaction_t *act,
prev_sigaction_t *oact, size_t sigsetsize, OUT uint *result);
uint
handle_post_sigaction(dcontext_t *dcontext, bool success, int sig,
const kernel_sigaction_t *act, prev_sigaction_t *oact,
size_t sigsetsize);
#ifdef LINUX
bool
handle_old_sigaction(dcontext_t *dcontext, int sig, const old_sigaction_t *act,
old_sigaction_t *oact, OUT uint *result);
uint
handle_post_old_sigaction(dcontext_t *dcontext, bool success, int sig,
const old_sigaction_t *act, old_sigaction_t *oact);
bool
handle_sigreturn(dcontext_t *dcontext, bool rt);
#else
bool
handle_sigreturn(dcontext_t *dcontext, void *ucxt, int style);
#endif
#ifdef LINUX
bool
handle_pre_extended_syscall_sigmasks(dcontext_t *dcontext, kernel_sigset_t *sigmask,
size_t sizemask, bool *pending);
void
handle_post_extended_syscall_sigmasks(dcontext_t *dcontext, bool success);
#endif
bool
handle_sigaltstack(dcontext_t *dcontext, const stack_t *stack, stack_t *old_stack,
reg_t cur_xsp, OUT uint *result);
bool
handle_sigprocmask(dcontext_t *dcontext, int how, kernel_sigset_t *set,
kernel_sigset_t *oset, size_t sigsetsize, uint *error_code);
int
handle_post_sigprocmask(dcontext_t *dcontext, int how, kernel_sigset_t *set,
kernel_sigset_t *oset, size_t sigsetsize);
void
handle_sigsuspend(dcontext_t *dcontext, kernel_sigset_t *set, size_t sigsetsize);
#ifdef LINUX
ptr_int_t
handle_pre_signalfd(dcontext_t *dcontext, int fd, kernel_sigset_t *mask, size_t sizemask,
int flags);
void
signal_handle_dup(dcontext_t *dcontext, file_t src, file_t dst);
void
signal_handle_close(dcontext_t *dcontext, file_t fd);
#endif
void
sigcontext_to_mcontext(priv_mcontext_t *mc, sig_full_cxt_t *sc_full,
dr_mcontext_flags_t flags);
void
mcontext_to_sigcontext(sig_full_cxt_t *sc_full, priv_mcontext_t *mc,
dr_mcontext_flags_t flags);
bool
set_default_signal_action(int sig);
void
signal_thread_inherit(dcontext_t *dcontext, void *clone_record);
dcontext_t *
init_thread_with_shared_siginfo(priv_mcontext_t *mc, dcontext_t *takeover_dc);
void
signal_set_mask(dcontext_t *dcontext, kernel_sigset_t *sigset);
void
os_terminate_via_signal(dcontext_t *dcontext, terminate_flags_t flags, int sig);
bool
thread_signal(process_id_t pid, thread_id_t tid, int signum);
bool
thread_signal_queue(process_id_t pid, thread_id_t tid, int signum, void *value);
void
start_itimer(dcontext_t *dcontext);
void
stop_itimer(dcontext_t *dcontext);
void
handle_pre_setitimer(dcontext_t *dcontext, int which, const struct itimerval *new_timer,
struct itimerval *prev_timer);
void
handle_post_setitimer(dcontext_t *dcontext, bool success, int which,
const struct itimerval *new_timer, struct itimerval *prev_timer);
void
handle_post_getitimer(dcontext_t *dcontext, bool success, int which,
struct itimerval *cur_timer);
void
handle_pre_alarm(dcontext_t *dcontext, unsigned int sec);
void
handle_post_alarm(dcontext_t *dcontext, bool success, unsigned int sec);
void
set_clone_record_fields(void *record, reg_t app_thread_xsp, app_pc continuation_pc,
uint clone_sysnum, uint clone_flags);
#ifdef ARM
dr_isa_mode_t
get_sigcontext_isa_mode(sig_full_cxt_t *sc_full);
void
set_sigcontext_isa_mode(sig_full_cxt_t *sc_full, dr_isa_mode_t isa_mode);
#endif
void
pcprofile_thread_init(dcontext_t *dcontext, bool shared_itimer, void *parent_info);
void
pcprofile_fork_init(dcontext_t *dcontext);
void
os_request_live_coredump(const char *msg);
#ifdef VMX86_SERVER
# include "vmkuw.h"
#endif
void *
privload_tls_init(void *app_tp);
void
privload_tls_exit(void *dr_tp);
#ifdef ANDROID
bool
get_kernel_args(int *argc OUT, char ***argv OUT, char ***envp OUT);
void
init_android_version(void);
#endif
bool
create_nudge_signal_payload(kernel_siginfo_t *info OUT, uint action_mask, uint flags,
client_id_t client_id, uint64 client_arg);
#ifdef X86
uint
safe_read_tls_magic(void);
void
safe_read_tls_magic_recover(void);
byte *
safe_read_tls_self(void);
void
safe_read_tls_self_recover(void);
byte *
safe_read_tls_app_self(void);
void
safe_read_tls_app_self_recover(void);
#endif
#ifdef LINUX
void
module_locate_rseq_regions(void);
bool
rseq_is_registered_for_current_thread(void);
#endif
#endif