Jeremy Fitzhardinge 1e6361234c A complete reworking of Valgrind's handling of system calls and signals,
with the aim of making it more robust, more correct and perhaps faster.

This patch removes the need to poll blocking syscalls, by adding a proxy
LWP for each application thread.  This LWP is a kernel thread whose job
is to run all (potentially) blocking syscalls, and also to handle signals.

This allows the kernel to do more of the work of dealing with signals,
so on kernels which do this properly (2.6), Valgrind's behavious is a
lot more posix compliant.  On base 2.4 kernels, we emulate some of the
missing 2.6 functionality.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1918
2003-10-13 22:26:55 +00:00

119 lines
3.2 KiB
ArmAsm

##--------------------------------------------------------------------##
##--- Support for doing system calls. ---##
##--- vg_syscall.S ---##
##--------------------------------------------------------------------##
/*
This file is part of Valgrind, an extensible x86 protected-mode
emulator for monitoring program execution on x86-Unixes.
Copyright (C) 2000-2003 Julian Seward
jseward@acm.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file COPYING.
*/
#include "vg_constants.h"
#include "vg_unistd.h"
.globl VG_(do_syscall)
/*
Perform a Linux syscall with int 0x80
Syscall args are passed on the stack
Int VG_(do_syscall)(Int syscall_no, ...)
This has no effect on the virtual machine; the expectation is
that the syscall mechanism makes no useful changes to any
register except %eax, which is returned.
*/
VG_(do_syscall):
push %esi
push %edi
push %ebx
push %ebp
movl 16+ 4(%esp),%eax
movl 16+ 8(%esp),%ebx
movl 16+12(%esp),%ecx
movl 16+16(%esp),%edx
movl 16+20(%esp),%esi
movl 16+24(%esp),%edi
movl 16+28(%esp),%ebp
int $0x80
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
/*
Perform a clone system call. clone is strange because it has
fork()-like return-twice semantics, so it needs special
handling here.
int VG_(clone)(int (*fn)(void *), void *child_stack, int flags, void *arg,
0 4 8 12
pid_t *child_tid, pid_t *parent_tid)
16 20
*/
.globl VG_(clone)
VG_(clone):
#define FSZ (4+4+4) /* frame size = retaddr+ebx+edi */
push %ebx
push %edi
/* set up child stack with function and arg */
movl 4+FSZ(%esp), %ecx /* child stack */
movl 12+FSZ(%esp), %ebx /* fn arg */
movl 0+FSZ(%esp), %eax /* fn */
lea -8(%ecx), %ecx /* make space on stack */
movl %ebx, 4(%ecx) /* fn arg */
movl %eax, 0(%ecx) /* fn */
/* get other args to clone */
movl 8+FSZ(%esp), %ebx /* flags */
movl 20+FSZ(%esp), %edx /* parent tid * */
movl 16+FSZ(%esp), %edi /* child tid * */
movl $__NR_clone, %eax
int $0x80
testl %eax, %eax
jnz 1f
/* CHILD - call thread function */
popl %eax
call *%eax
/* exit with result */
movl %eax, %ebx
movl $__NR_exit, %eax
int $0x80
/* Hm, exit returned */
ud2
1: /* PARENT or ERROR */
pop %edi
pop %ebx
ret
##--------------------------------------------------------------------##
##--- end vg_syscall.S ---##
##--------------------------------------------------------------------##