From ad1bf0073e7b7b3f9763162fa6caa8b537b59a8d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Nov 2004 16:04:58 +0000 Subject: [PATCH] Clear a few more AMD64 start-up hurdles: - implemented VG_(clone)() - implemented PLATFORM_DO_MMAP() - implemented VG_(init_thread1state)() [will need to be updated as the Vex AMD64 guest state is updated] - implemented OYNK, because it's useful Also a couple of general cleaning up things. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3165 --- coregrind/amd64-linux/core_platform.h | 3 +- coregrind/amd64-linux/syscall.S | 51 +++++++++++++++++++++++++-- coregrind/amd64/core_arch_asm.h | 9 +++++ coregrind/amd64/state.c | 37 +++++++------------ coregrind/vg_main.c | 12 +++++++ coregrind/x86/state.c | 5 +-- 6 files changed, 87 insertions(+), 30 deletions(-) diff --git a/coregrind/amd64-linux/core_platform.h b/coregrind/amd64-linux/core_platform.h index c6f5a681a..568d80f21 100644 --- a/coregrind/amd64-linux/core_platform.h +++ b/coregrind/amd64-linux/core_platform.h @@ -95,7 +95,8 @@ extern Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr ); ------------------------------------------------------------------ */ #define PLATFORM_DO_MMAP(ret, start, length, prot, flags, fd, offset) { \ - I_die_here; \ + ret = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length), \ + (prot), (flags), (fd), (offset)); \ } while (0) #define PLATFORM_GET_MMAP_ARGS(tst, a1, a2, a3, a4, a5, a6) do {\ diff --git a/coregrind/amd64-linux/syscall.S b/coregrind/amd64-linux/syscall.S index 2b01fdc41..3282b9057 100644 --- a/coregrind/amd64-linux/syscall.S +++ b/coregrind/amd64-linux/syscall.S @@ -65,12 +65,59 @@ VG_(do_syscall): ret +/* + Perform a clone system call. clone is strange because it has + fork()-like return-twice semantics, so it needs special + handling here. -# XXX: must reinstate comments also -- see x86-linux/syscall.S + Upon entry, we have: + int (*fn)(void*) in %rdi + void* child_stack in %rsi + int flags in %rdx + void* arg in %rcx + pid_t* child_tid in %r8 + pid_t* parent_tid in %r9 + */ .globl VG_(clone) VG_(clone): - ud2 + // set up child stack, temporarily preserving fn and arg + subq $16, %rsi // make space on stack + movq %rcx, 8(%rsi) // save arg + movq %rdi, 0(%rsi) // save fn + + // setup syscall + movl $__NR_clone, %eax // syscall number + movq %rdx, %rdi // syscall arg1: flags + // %rsi already setup // syscall arg2: child_stack + movq %r9, %rdx // syscall arg3: parent_tid + movq %r8, %rcx // syscall arg4: child_tid + + syscall // clone() + + testq %rax, %rax // child if retval == 0 + jnz 1f + + // CHILD - call thread function + pop %rax // pop fn + pop %rdi // pop fn arg1: arg + call *%eax // call fn + + // exit with result + movq %rax, %rdi // arg1: return value from fn + movl $__NR_exit, %eax + + syscall + + // Exit returned?! + ud2 + +1: // PARENT or ERROR + ret + + + +# XXX: must reinstate comments also -- see x86-linux/syscall.S .globl VG_(sigreturn) VG_(sigreturn): diff --git a/coregrind/amd64/core_arch_asm.h b/coregrind/amd64/core_arch_asm.h index a00b01123..ddcdcda57 100644 --- a/coregrind/amd64/core_arch_asm.h +++ b/coregrind/amd64/core_arch_asm.h @@ -30,6 +30,15 @@ #ifndef __AMD64_CORE_ARCH_ASM_H #define __AMD64_CORE_ARCH_ASM_H +// Print a constant from asm code. +#define OYNK(nnn) push %r8 ; push %r9 ; push %r10; push %r11; \ + push %rax; push %rbx; push %rcx; push %rdx; \ + push %rsi; push %rdi; \ + movl $nnn, %edi; call VG_(oynk); \ + pop %rdi; pop %rsi; pop %rdx; pop %rcx; \ + pop %rbx; pop %rax; pop %r11; pop %r10; \ + pop %r9 ; pop %r8 + #endif // __AMD64_CORE_ARCH_ASM_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/amd64/state.c b/coregrind/amd64/state.c index 56570b44f..0143dd092 100644 --- a/coregrind/amd64/state.c +++ b/coregrind/amd64/state.c @@ -42,27 +42,29 @@ thread), initialise the VEX guest state, and copy in essential starting values. */ -void VGA_(init_thread1state) ( Addr client_eip, - Addr esp_at_startup, +void VGA_(init_thread1state) ( Addr client_rip, + Addr rsp_at_startup, /*MOD*/ ThreadArchState* arch ) { - I_die_here; -#if 0 - vg_assert(0 == sizeof(VexGuestX86State) % 8); + vg_assert(0 == sizeof(VexGuestAMD64State) % 8); /* Zero out the initial state, and set up the simulated FPU in a sane way. */ - LibVEX_GuestX86_initialise(&arch->vex); + LibVEX_GuestAMD64_initialise(&arch->vex); /* Zero out the shadow area. */ - VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State)); + VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State)); /* Put essential stuff into the new state. */ + + arch->vex.guest_RSP = rsp_at_startup; + arch->vex.guest_RIP = client_rip; + + // XXX: something will probably have to be done with the segment + // registers, once they're added to Vex-AMD64. +#if 0 /* initialise %cs, %ds and %ss to point at the operating systems default code, data and stack segments */ - arch->vex.guest_ESP = esp_at_startup; - arch->vex.guest_EIP = client_eip; - asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS)); @@ -72,21 +74,6 @@ void VGA_(init_thread1state) ( Addr client_eip, asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS)); - - VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, - sizeof(VexGuestArchState)); - - /* I assume that if we have SSE2 we also have SSE */ - VG_(have_ssestate) = False; - // VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) && - // VG_(cpu_has_feature)(VG_X86_FEAT_SSE); - - if (0) { - if (VG_(have_ssestate)) - VG_(printf)("Looks like a SSE-capable CPU\n"); - else - VG_(printf)("Looks like a MMX-only CPU\n"); - } #endif } diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 04005ab96..ad8247cb3 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -319,6 +319,12 @@ Addr VG_(get_stack_pointer) ( ThreadId tid ) return STACK_PTR( VG_(threads)[tid].arch ); } +/* Debugging thing .. can be called from assembly with OYNK macro. */ +void VG_(oynk) ( Int n ) +{ + OINK(n); +} + /* Initialize the PID and PGRP of scheduler LWP; this is also called in any new children after fork. */ static void newpid(ThreadId unused) @@ -2605,6 +2611,12 @@ int main(int argc, char **argv) // setup_scheduler() [for the rest of state 1 stuff] //-------------------------------------------------------------- VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch ); + + // Tell the tool that we just wrote to the registers. + VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, + sizeof(VexGuestArchState)); + + // Record the instr ptr offset, for use by asm code. VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR); //-------------------------------------------------------------- diff --git a/coregrind/x86/state.c b/coregrind/x86/state.c index 024bc4e80..3b6df2053 100644 --- a/coregrind/x86/state.c +++ b/coregrind/x86/state.c @@ -56,11 +56,12 @@ void VGA_(init_thread1state) ( Addr client_eip, VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State)); /* Put essential stuff into the new state. */ - /* initialise %cs, %ds and %ss to point at the operating systems - default code, data and stack segments */ + arch->vex.guest_ESP = esp_at_startup; arch->vex.guest_EIP = client_eip; + /* initialise %cs, %ds and %ss to point at the operating systems + default code, data and stack segments */ asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));