blob: 2792a817611c3ac35b46c79817d4a5777378c3b2 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 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> /* for stack_t */
#include "module.h" /* for os_module_data_t */
#include "ksynch.h" /* for KSYNCH_TYPE */
#include "instr.h" /* for reg_id_t */
#include <sys/time.h> /* struct itimerval */
#include "dr_config.h" /* for dr_platform_t */
/* for inline asm */
#ifdef X86
# ifdef X64
# define ASM_XAX "rax"
# define ASM_XDX "rdx"
# define ASM_XBP "rbp"
# define ASM_XSP "rsp"
# else
# define ASM_XAX "eax"
# define ASM_XDX "edx"
# define ASM_XBP "ebp"
# define ASM_XSP "esp"
# endif /* 64/32-bit */
#elif defined(ARM)
# define ASM_XSP "sp"
#endif /* X86/ARM */
/* PR 212090: the signal we use to suspend threads */
#define SUSPEND_SIGNAL SIGUSR2
#ifdef MACOS
/* While there is no clone system call, we use the same clone flags to share
* 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
/* Clone flags use by pthreads on Linux 2.6.38. May need updating over time.
*/
#define PTHREAD_CLONE_FLAGS (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| \
CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS| \
CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID)
/* On Mac, we use the _nocancel variant to defer app-initiated thread termination */
#ifdef MACOS
# define SYSNUM_NO_CANCEL(num) num##_nocancel
#else
# define SYSNUM_NO_CANCEL(num) num
#endif
/* Maximum number of arguments to Linux syscalls. */
enum { MAX_SYSCALL_ARGS = 6 };
/* thread-local data that's os-private, for modularity */
typedef struct _os_thread_data_t {
/* store stack info at thread startup, since stack can get fragmented in
* /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; /* return target in the loader at program startup */
#endif
/* PR 2120990: for thread suspension */
/* This lock synchronizes suspension and resumption and controls
* 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 synchronization data held across a fork. */
thread_record_t **fork_threads;
int fork_num_threads;
/* We would use event_t's here except we can't use mutexes in
* our signal handler
*/
/* Any function that sets these flags must also notify possibly waiting
* thread(s). See i#96/PR 295561.
*/
KSYNCH_TYPE suspended;
KSYNCH_TYPE wakeup;
KSYNCH_TYPE resumed;
sigcontext_t *suspended_sigcxt;
/* PR 297902: for thread termination */
bool terminate;
/* Any function that sets this flag must also notify possibly waiting
* thread(s). See i#96/PR 295561.
*/
KSYNCH_TYPE terminated;
volatile bool retakeover; /* for re-attach */
/* PR 450670: for re-entrant suspend signals */
int processing_signal;
/* i#107: If -mangle_app_seg is on, these hold the bases for both SEG_TLS
* 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 *dr_fs_base;
void *dr_gs_base;
void *app_thread_areas; /* data structure for app's thread area info */
} os_thread_data_t;
enum { ARGC_PTRACE_SENTINEL = -1 };
/* This data is pushed on the stack by the ptrace injection code. */
typedef struct ptrace_stack_args_t {
ptr_int_t argc; /* Set to ARGC_PTRACE_SENTINEL */
priv_mcontext_t mc; /* Registers at attach time */
char home_dir[MAXIMUM_PATH]; /* In case the user of the injectee is not us. */
} ptrace_stack_args_t;
/* in os.c */
void os_thread_take_over(priv_mcontext_t *mc);
void
set_executable_path(const 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];
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);
/* in signal.c */
struct _kernel_sigaction_t;
typedef struct _kernel_sigaction_t kernel_sigaction_t;
void signal_init(void);
void signal_exit(void);
void signal_thread_init(dcontext_t *dcontext);
void signal_thread_exit(dcontext_t *dcontext, bool other_thread);
void handle_clone(dcontext_t *dcontext, uint flags);
bool handle_sigaction(dcontext_t *dcontext, int sig,
const kernel_sigaction_t *act,
kernel_sigaction_t *oact, size_t sigsetsize);
void handle_post_sigaction(dcontext_t *dcontext, int sig,
const kernel_sigaction_t *act,
kernel_sigaction_t *oact, size_t sigsetsize);
#ifdef LINUX
bool handle_sigreturn(dcontext_t *dcontext, bool rt);
#else
bool handle_sigreturn(dcontext_t *dcontext, void *ucxt, int style);
#endif
bool handle_sigaltstack(dcontext_t *dcontext, const stack_t *stack,
stack_t *old_stack);
bool handle_sigprocmask(dcontext_t *dcontext, int how, kernel_sigset_t *set,
kernel_sigset_t *oset, size_t sigsetsize);
void 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, sigcontext_t *sc);
void
mcontext_to_sigcontext(sigcontext_t *sc, priv_mcontext_t *mc);
bool
set_default_signal_action(int sig);
void
share_siginfo_after_take_over(dcontext_t *dcontext, dcontext_t *takeover_dc);
void
os_terminate_via_signal(dcontext_t *dcontext, terminate_flags_t flags, int sig);
void start_itimer(dcontext_t *dcontext);
void stop_itimer(dcontext_t *dcontext);
/* handle app itimer syscalls */
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);
/* not exported beyond unix/ unlike rest of clone record routines */
void
set_clone_record_fields(void *record, reg_t app_thread_xsp, app_pc continuation_pc,
uint clone_sysnum, uint clone_flags);
/* in pcprofile.c */
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
/* in loader.c */
void *privload_tls_init(void *app_tp);
void privload_tls_exit(void *dr_tp);
/* in nudgesig.c */
bool
create_nudge_signal_payload(siginfo_t *info OUT, uint action_mask,
client_id_t client_id, uint64 client_arg);
#endif /* _OS_PRIVATE_H_ */