I_die_here; \
} while (0)
+
+/* Use libc setjmp/longjmp. longjmp must not restore signal mask
+ state, but does need to pass though "val". */
+#include <setjmp.h> /* for jmp_buf */
+
+#define SETJMP(env) setjmp(env)
+#define LONGJMP(env, val) longjmp(env, val)
+
#endif // __AMD64_LINUX_CORE_PLATFORM_H
/*--------------------------------------------------------------------*/
#endif
}
+/* ---------------------------------------------------------------------
+ Stacks, thread wrappers, clone
+ Note. Why is this stuff here?
+ ------------------------------------------------------------------ */
+
+/*
+ Allocate a stack for this thread.
+
+ They're allocated lazily, but never freed.
+ */
+#define FILL 0xdeadbeef
+
+
+/* NB: this is identical the the x86 version. */
+/* Return how many bytes of this stack have not been used */
+Int VGA_(stack_unused)(ThreadId tid)
+{
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+ UInt *p;
+
+ for (p = tst->os_state.stack;
+ p && (p < (tst->os_state.stack + tst->os_state.stacksize));
+ p++)
+ if (*p != FILL)
+ break;
+
+ if (0)
+ VG_(printf)("p=%p %x tst->os_state.stack=%p\n", p, *p, tst->os_state.stack);
+
+ return (p - tst->os_state.stack) * sizeof(*p);
+}
+
+static ULong *allocstack(ThreadId tid)
+{
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+ ULong* rsp;
+ UInt* pUInt;
+
+ if (tst->os_state.stack == NULL) {
+ void *stk = VG_(mmap)(0, VG_STACK_SIZE_W * sizeof(Int) + VKI_PAGE_SIZE,
+ VKI_PROT_READ|VKI_PROT_WRITE,
+ VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
+ SF_VALGRIND,
+ -1, 0);
+
+ if (stk != (void *)-1) {
+ VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page */
+ tst->os_state.stack = (UInt *)stk + VKI_PAGE_SIZE/sizeof(UInt);
+ tst->os_state.stacksize = VG_STACK_SIZE_W;
+ } else
+ return (ULong *)-1;
+ }
+
+ for (pUInt = tst->os_state.stack;
+ pUInt < (tst->os_state.stack + tst->os_state.stacksize);
+ pUInt++)
+ *pUInt = FILL;
+ /* rsp is left at top of stack */
+ rsp = pUInt;
+
+ if (0)
+ VG_(printf)("stack for tid %d at %p (%x); esp=%p\n",
+ tid, tst->os_state.stack, *tst->os_state.stack,
+ rsp);
+
+ return rsp;
+}
+
+
+/*
+ Allocate a stack for the main thread, and call VGA_(thread_wrapper)
+ on that stack.
+ */
+void VGA_(main_thread_wrapper)(ThreadId tid)
+{
+ ULong *rsp = allocstack(tid);
+
+ vg_assert(tid == VG_(master_tid));
+
+ VG_(threads)[tid].arch.vex.guest_RDI = (ULong)tid; /* set arg */
+ *--rsp = 0; /* bogus return address */
+ jmp_with_stack((void (*)(void))VGA_(thread_wrapper), (Addr)rsp);
+}
+
+
/* ---------------------------------------------------------------------
PRE/POST wrappers for AMD64/Linux-specific syscalls
------------------------------------------------------------------ */
noinst_LIBRARIES = libarch.a
EXTRA_DIST = \
- jmp_with_stack.c \
- libpthread.c
+ jmp_with_stack.c
BUILT_SOURCES = stage2.lds
CLEANFILES = stage2.lds
helpers.S \
dispatch.S \
signals.c \
+ jmp_with_stack.c \
state.c
# Extract ld's default linker script and hack it to our needs
// ToDo XXX??? not at all sure about this...
struct _ThreadArchAux {
- void* tls_data;
- int tls_segment;
- unsigned long sysinfo;
+ // void* tls_data;
+ // int tls_segment;
+ // unsigned long sysinfo;
};
/* ---------------------------------------------------------------------
// Valgrind's signal stack size, in words.
#define VG_SIGSTACK_SIZE_W 10000
+// Valgrind's stack size, in words.
+#define VG_STACK_SIZE_W 16384
+
// Base address of client address space.
#define CLIENT_BASE 0x00000000ul
*/
#include "core_asm.h"
+#include "vki_unistd.h"
/* ------------------ SIMULATED CPU HELPERS ------------------ */
/* A stubs for a return which we want to catch: a signal return.
.global VG_(tramp_syscall_offset)
VG_(trampoline_code_start):
-sigreturn_start:
- subl $20, %esp # allocate arg block
- movl %esp, %edx # %edx == &_zzq_args[0]
- movl $VG_USERREQ__SIGNAL_RETURNS, 0(%edx) # request
- movl $0, 4(%edx) # arg1
- movl $0, 8(%edx) # arg2
- movl $0, 12(%edx) # arg3
- movl $0, 16(%edx) # arg4
- movl %edx, %eax
- # and now the magic sequence itself:
- roll $29, %eax
- roll $3, %eax
- rorl $27, %eax
- rorl $5, %eax
- roll $13, %eax
- roll $19, %eax
- # should never get here
- ud2
+sigreturn_start:
+ /* This is a very specific sequence which GDB uses to
+ recognize signal handler frames. */
+ popq %rax
+ movq $__NR_rt_sigreturn, %rax
+ syscall
+ ud2
+
+rt_sigreturn_start:
+ /* Likewise for rt signal frames */
+ movq $__NR_rt_sigreturn, %rax
+ syscall
+ ud2
# We can point our sysinfo stuff here
.align 16
#include "ume.h"
-void jmp_with_stack(Addr rip, Addr rsp)
+void jmp_with_stack(void(*rip)(void), Addr rsp)
{
asm volatile (
"movq %1, %%rsp;" // set rsp
void VGA_(push_signal_frame)(ThreadId tid, Addr esp_top_of_frame,
const vki_siginfo_t *siginfo,
void *handler, UInt flags,
- const vki_sigset_t *mask)
+ const vki_sigset_t *mask,
+ void* restorer)
{
I_die_here;
#if 0
}
-void VGA_(setup_child) ( ThreadArchState *arch, ThreadArchState *parent_arch )
+void VGA_(setup_child) ( /*OUT*/ ThreadArchState *child,
+ /*IN*/ ThreadArchState *parent )
{
I_die_here;
#if 0
+ /* We inherit our parent's guest state. */
+ child->vex = parent->vex;
+ child->vex_shadow = parent->vex_shadow;
/* We inherit our parent's LDT. */
- if (parent_arch->ldt == NULL) {
+ if (parent->vex.guest_LDT == (HWord)NULL) {
/* We hope this is the common case. */
- arch->ldt = NULL;
+ child->vex.guest_LDT = (HWord)NULL;
} else {
/* No luck .. we have to take a copy of the parent's. */
- arch->ldt = VG_(allocate_LDT_for_thread)( parent_arch->ldt );
+ child->vex.guest_LDT = (HWord)VG_(alloc_zeroed_x86_LDT)();
+ copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,
+ (VexGuestX86SegDescr*)child->vex.guest_LDT );
}
- /* Initialise the thread's TLS array */
- VG_(clear_TLS_for_thread)( arch->tls );
+ /* We need an empty GDT. */
+ child->vex.guest_GDT = (HWord)NULL;
#endif
}
+void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr))
+{
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+ ThreadArchState *arch = &tst->arch;
+
+ /* XXX ask tool about validity? */
+ (*marker)(arch->vex.guest_RAX);
+ (*marker)(arch->vex.guest_RCX);
+ (*marker)(arch->vex.guest_RDX);
+ (*marker)(arch->vex.guest_RBX);
+ (*marker)(arch->vex.guest_RSI);
+ (*marker)(arch->vex.guest_RDI);
+ (*marker)(arch->vex.guest_RSP);
+ (*marker)(arch->vex.guest_RBP);
+ (*marker)(arch->vex.guest_R8);
+ (*marker)(arch->vex.guest_R9);
+ (*marker)(arch->vex.guest_R10);
+ (*marker)(arch->vex.guest_R11);
+ (*marker)(arch->vex.guest_R12);
+ (*marker)(arch->vex.guest_R13);
+ (*marker)(arch->vex.guest_R14);
+ (*marker)(arch->vex.guest_R15);
+}
+
/*------------------------------------------------------------*/
/*--- Symtab stuff ---*/
/* Support for getrlimit. */
Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
{
- Int res;
+ Int res = -VKI_ENOSYS;
/* res = getrlimit( resource, rlim ); */
+# ifdef __NR_ugetrlimit
res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
+# endif
if (res == -VKI_ENOSYS)
res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
- if(VG_(is_kerror)(res)) res = -1;
+ if (VG_(is_kerror)(res)) res = -1;
return res;
}
Int res;
/* res = setrlimit( resource, rlim ); */
res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
- if(VG_(is_kerror)(res)) res = -1;
+ if (VG_(is_kerror)(res)) res = -1;
return res;
}
"si_code=%x Fault EIP: %p%s; Faulting address: %p",
info->si_code, context_ip, buf, info->_sifields._sigfault._addr);
VG_(message)(Vg_DebugMsg,
- " esp=%p\n", uc->uc_mcontext.esp);
+ " sp=%p\n", UCONTEXT_STACK_PTR(uc));
if (0)
VG_(kill_self)(sigNo); /* generate a core dump */
#include "core.h"
#include "ume.h" /* for jmp_with_stack */
+
+/* ---------------------------------------------------------------------
+ Stacks, thread wrappers, clone
+ Note. Why is this stuff here?
+ ------------------------------------------------------------------ */
+
/* These are addresses within VGA_(client_syscall). See syscall.S for details. */
extern const Word VGA_(blksys_setup);
extern const Word VGA_(blksys_restart);
return esp;
}
+/* NB: this is identical the the amd64 version. */
/* Return how many bytes of this stack have not been used */
Int VGA_(stack_unused)(ThreadId tid)
{
#define VKI_PROT_READ 0x1 /* page can be read */
#define VKI_PROT_WRITE 0x2 /* page can be written */
#define VKI_PROT_EXEC 0x4 /* page can be executed */
-//#define VKI_PROT_NONE 0x0 /* page can not be accessed */
+#define VKI_PROT_NONE 0x0 /* page can not be accessed */
#define VKI_MAP_SHARED 0x01 /* Share changes */
#define VKI_MAP_PRIVATE 0x02 /* Changes are private */
typedef struct vki_user_desc vki_modify_ldt_t;
#endif
+typedef void vki_modify_ldt_t;
+
//----------------------------------------------------------------------
// And that's it!
//----------------------------------------------------------------------