libc

/* $Id$ */
/* Copyright (c) 2006-2016 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libc */
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 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 THE COPYRIGHT
* HOLDER 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. */
/* FIXME:
* - check errors from sigprocmask()?
* - some syscalls may return an additional value into %edx (eg lseek)
* - ftruncate() and truncate() probably need a wrapper (for padding) */
_syscall:
int $0x80
jnc _syscall_return
.errno:
mov %eax, errno
mov $-1, %eax
_syscall_return:
ret
/* macros */
#ifndef SYSCALL
# define SYSCALL(name) \
.global name; \
.type name,@function; \
name:; \
mov $SYS_ ## name, %eax; \
jmp _syscall
#endif
/* functions */
/* _brk */
.global _brk
.type _brk,@function
_brk:
mov $SYS_brk, %eax
int $0x80
jc .errno
ret
#undef SYS_brk
/* _exit */
.global _exit
.type _exit,@function
_exit:
mov $SYS_exit, %eax
jmp _syscall
/* execve */
.global execve
.type execve,@function
execve:
mov $SYS_execve, %eax
int $0x80
mov %eax, errno
mov $-1, %eax
ret
#undef SYS_execve
/* _longjmp */
.global _longjmp
.type _longjmp,@function
_longjmp:
push %ebp
mov %esp, %ebp
mov 12(%ebp), %eax /* eax = val */
/* restore registers */
mov 8(%ebp), %edx /* edx = env */
mov 20(%edx), %edi /* edi = env[5] */
mov 16(%edx), %esi /* esi = env[4] */
mov 12(%edx), %ecx /* base pointer = env[3] */
mov %ecx, %ebp
mov 8(%edx), %esp /* stack pointer = env[2] */
mov 4(%edx), %ebx /* ebx = env[1] */
mov 0(%edx), %ecx /* return address = env[0] */
mov %ecx, 0(%esp)
/* if(val != 0) return val; else return ++val */
test %eax, %eax
jnz __longjmp_return
inc %eax
/* return val */
__longjmp_return:
ret
/* longjmp */
.global longjmp
.type longjmp,@function
longjmp:
.global siglongjmp
.type siglongjmp,@function
siglongjmp:
push %ebp
mov %esp, %ebp
/* if(env[6] == 0) goto _longjmp_registers */
mov 8(%ebp), %eax /* eax = env */
mov 24(%eax), %ecx /* ecx = env[6] */
test %ecx, %ecx
jz _longjmp_registers
/* restore the signal mask */
/* sigprocmask(SIG_SETMASK, &env[7], NULL) */
push $0x0
lea 28(%eax), %ecx
push %ecx
push $0x3
call sigprocmask
add $12, %esp
/* restore registers */
_longjmp_registers:
mov 8(%ebp), %edx /* edx = env */
mov 12(%ebp), %eax /* eax = val */
mov 20(%edx), %edi /* edi = env[5] */
mov 16(%edx), %esi /* esi = env[4] */
mov 12(%edx), %ecx /* base pointer = env[3] */
mov %ecx, %ebp
mov 8(%edx), %esp /* stack pointer = env[2] */
mov 4(%edx), %ebx /* ebx = env[1] */
mov 0(%edx), %ecx /* return address = env[0] */
mov %ecx, 0(%esp)
/* if(val != 0) return val; else return ++val */
test %eax, %eax
jnz _longjmp_return
inc %eax
/* return val */
_longjmp_return:
ret
/* pipe */
.global pipe
.type pipe,@function
pipe:
mov $SYS_pipe, %eax
int $0x80
jc .errno
mov 4(%esp), %ecx
mov %eax, (%ecx)
mov %edx, 4(%ecx)
mov $0, %eax
ret
#undef SYS_pipe
/* _setjmp */
.global _setjmp
.type _setjmp,@function
_setjmp:
/* eax = env */
mov 4(%esp), %eax
/* save registers */
mov 0(%esp), %edx /* env[0] = return address */
mov %edx, 0(%eax)
mov %ebx, 4(%eax) /* env[1] = ebx */
mov %esp, 8(%eax) /* env[2] = stack pointer */
mov %ebp, %edx /* env[3] = base pointer */
mov %edx, 12(%eax)
mov %esi, 16(%eax) /* env[4] = esi */
mov %edi, 20(%eax) /* env[5] = edi */
/* the signal mask is not saved */
movl $0x0, 24(%eax) /* env[6] = 0 */
/* return 0 */
mov $0x0, %eax
ret
/* setjmp */
.global setjmp
.type setjmp,@function
setjmp:
/* eax = env */
mov 4(%esp), %eax
/* save registers */
mov 0(%esp), %edx /* return address */
mov %edx, 0(%eax)
mov %ebx, 4(%eax)
mov %esp, 8(%eax) /* stack pointer */
mov %ebp, %edx /* base pointer */
mov %edx, 12(%eax)
mov %esi, 16(%eax)
mov %edi, 20(%eax)
/* the signal mask is not saved yet */
movl $0x0, 24(%eax) /* env[6] = 0 */
/* res = sigprocmask(0, NULL, &env[7]) */
lea 28(%eax), %ecx
push %ecx
push $0x0
push $0x0
call sigprocmask
add $12, %esp
/* the signal mask was saved */
/* if(res == 0) env[6] = 1 */
test %eax, %eax
jnz _setjmp_return
mov 4(%esp), %eax
movl $0x1, 24(%eax)
/* return 0 */
_setjmp_return:
mov $0x0, %eax
ret
/* sigaction */
.global __sigaction_sigtramp
.type __sigaction_sigtramp,@function
__sigaction_sigtramp:
lea 12+128(%esp), %eax
mov %eax, 4(%esp)
mov $SYS_setcontext, %eax
int $0x80
/* should not happen */
movl $-1, 4(%esp)
int $0x80
.global sigaction
.type sigaction,@function
sigaction:
lea __sigaction_sigtramp, %eax
mov %eax, 16(%esp)
mov $SYS_sigaction, %eax
movl $0x2, 20(%esp)
jmp _syscall
#undef SYS_sigaction
/* sigsetjmp */
.global sigsetjmp
.type sigsetjmp,@function
sigsetjmp:
/* if(savemask != 0) return setjmp(); else return _setjmp(); */
mov 8(%esp), %eax
test %eax, %eax
jnz setjmp
jmp _setjmp