#include "exec/gdbstub.h"
#include "qemu/queue.h"
-#define THREAD __thread
+/* This is the size of the host kernel's sigset_t, needed where we make
+ * direct system calls that take a sigset_t pointer and a size.
+ */
+#define SIGSET_T_SIZE (_NSIG / 8)
/* This struct is used to hold certain information about the image.
* Basically, it replicates in user space what would be certain
abi_ulong auxv_len;
abi_ulong arg_start;
abi_ulong arg_end;
+ abi_ulong arg_strings;
+ abi_ulong env_strings;
+ abi_ulong file_string;
uint32_t elf_flags;
int personality;
-#ifdef CONFIG_USE_FDPIC
+
+ /* The fields below are used in FDPIC mode. */
abi_ulong loadmap_addr;
uint16_t nsegs;
void *loadsegs;
abi_ulong pt_dynamic_addr;
+ abi_ulong interpreter_loadmap_addr;
+ abi_ulong interpreter_pt_dynamic_addr;
struct image_info *other_info;
-#endif
};
#ifdef TARGET_I386
#define MAX_SIGQUEUE_SIZE 1024
-struct sigqueue {
- struct sigqueue *next;
- target_siginfo_t info;
-};
-
struct emulated_sigtable {
int pending; /* true if signal is pending */
- struct sigqueue *first;
- struct sigqueue info; /* in order to always have memory for the
- first signal, we put it here */
+ target_siginfo_t info;
};
/* NOTE: we force a big alignment so that the stack stored after is
# endif
int swi_errno;
#endif
-#ifdef TARGET_UNICORE32
- int swi_errno;
-#endif
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
abi_ulong target_v86;
struct vm86_saved_state vm86_saved_regs;
int sim_syscalls;
abi_ulong tp_value;
#endif
-#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
+#if defined(TARGET_ARM) || defined(TARGET_M68K)
/* Extra fields for semihosted binaries. */
- uint32_t heap_base;
- uint32_t heap_limit;
+ abi_ulong heap_base;
+ abi_ulong heap_limit;
#endif
- uint32_t stack_base;
+ abi_ulong stack_base;
int used; /* non zero if used */
- bool sigsegv_blocked; /* SIGSEGV blocked by guest */
struct image_info *info;
struct linux_binprm *bprm;
+ struct emulated_sigtable sync_signal;
struct emulated_sigtable sigtab[TARGET_NSIG];
- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
- struct sigqueue *first_free; /* first free siginfo queue entry */
- int signal_pending; /* non zero if a signal may be pending */
+ /* This thread's signal mask, as requested by the guest program.
+ * The actual signal mask of this thread may differ:
+ * + we don't let SIGSEGV and SIGBUS be blocked while running guest code
+ * + sometimes we block all signals to avoid races
+ */
+ sigset_t signal_mask;
+ /* The signal mask imposed by a guest sigsuspend syscall, if we are
+ * currently in the middle of such a syscall
+ */
+ sigset_t sigsuspend_mask;
+ /* Nonzero if we're leaving a sigsuspend and sigsuspend_mask is valid. */
+ int in_sigsuspend;
+
+ /* Nonzero if process_pending_signals() needs to do something (either
+ * handle a pending signal or unblock signals).
+ * This flag is written from a signal handler so should be accessed via
+ * the atomic_read() and atomic_write() functions. (It is not accessed
+ * from multiple threads.)
+ */
+ int signal_pending;
+
} __attribute__((aligned(16))) TaskState;
extern char *exec_path;
struct target_pt_regs * regs, struct image_info *infop,
struct linux_binprm *);
+/* Returns true if the image uses the FDPIC ABI. If this is the case,
+ * we have to provide some information (loadmap, pt_dynamic_info) such
+ * that the program can be relocated adequately. This is also useful
+ * when handling signals.
+ */
+int info_is_fdpic(struct image_info *info);
+
+uint32_t get_elf_eflags(int fd);
int load_elf_binary(struct linux_binprm *bprm, struct image_info *info);
int load_flt_binary(struct linux_binprm *bprm, struct image_info *info);
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUState *thread_cpu;
+extern __thread CPUState *thread_cpu;
void cpu_loop(CPUArchState *env);
-char *target_strerror(int err);
+const char *target_strerror(int err);
int get_osversion(void);
void init_qemu_uname_release(void);
void fork_start(void);
* It's also OK to implement these with safe_syscall, though it will be
* a little less efficient if a signal is delivered at the 'wrong' moment.
*
+ * Some non-interruptible syscalls need to be handled using block_signals()
+ * to block signals for the duration of the syscall. This mainly applies
+ * to code which needs to modify the data structures used by the
+ * host_signal_handler() function and the functions it calls, including
+ * all syscalls which change the thread's signal mask.
+ *
* (2) Interruptible syscalls
*
* These are guest syscalls that can be interrupted by signals and
* you make in the implementation returns either -TARGET_ERESTARTSYS or
* EINTR though.)
*
+ * block_signals() cannot be used for interruptible syscalls.
+ *
*
* How and why the safe_syscall implementation works:
*
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6);
void print_syscall_ret(int num, abi_long arg1);
+/**
+ * print_taken_signal:
+ * @target_signum: target signal being taken
+ * @tinfo: target_siginfo_t which will be passed to the guest for the signal
+ *
+ * Print strace output indicating that this signal is being taken by the guest,
+ * in a format similar to:
+ * --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+ */
+void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
extern int do_strace;
/* signal.c */
void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void);
-int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
+int queue_signal(CPUArchState *env, int sig, int si_type,
+ target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
int target_to_host_signal(int sig);
long do_rt_sigreturn(CPUArchState *env);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+/**
+ * block_signals: block all signals while handling this guest syscall
+ *
+ * Block all signals, and arrange that the signal mask is returned to
+ * its correct value for the guest before we resume execution of guest code.
+ * If this function returns non-zero, then the caller should immediately
+ * return -TARGET_ERESTARTSYS to the main loop, which will take the pending
+ * signal and restart execution of the syscall.
+ * If block_signals() returns zero, then the caller can continue with
+ * emulation of the system call knowing that no signals can be taken
+ * (and therefore that no race conditions will result).
+ * This should only be called once, because if it is called a second time
+ * it will always return non-zero. (Think of it like a mutex that can't
+ * be recursively locked.)
+ * Signals will be unblocked again by process_pending_signals().
+ *
+ * Return value: non-zero if there was a pending signal, zero if not.
+ */
+int block_signals(void); /* Returns non zero if signal pending */
#ifdef TARGET_I386
/* vm86.c */
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
abi_ulong new_addr);
-int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
-void cpu_list_lock(void);
-void cpu_list_unlock(void);
void mmap_fork_start(void);
void mmap_fork_end(int child);
#ifdef DEBUG_REMAP
{
void *addr;
- addr = malloc(len);
+ addr = g_malloc(len);
if (copy)
memcpy(addr, g2h(guest_addr), len);
else
return;
if (len > 0)
memcpy(g2h(guest_addr), host_ptr, len);
- free(host_ptr);
+ g_free(host_ptr);
#endif
}
#include <pthread.h>
+static inline int is_error(abi_long ret)
+{
+ return (abi_ulong)ret >= (abi_ulong)(-4096);
+}
+
+/**
+ * preexit_cleanup: housekeeping before the guest exits
+ *
+ * env: the CPU state
+ * code: the exit code
+ */
+void preexit_cleanup(CPUArchState *env, int code);
+
/* Include target-specific struct and function definitions;
* they may need access to the target-independent structures
* above, so include them last.
*/
#include "target_cpu.h"
-#include "target_signal.h"
#include "target_structs.h"
#endif /* QEMU_H */