libc

/* $Id$ */
/* Copyright (c) 2008-2017 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. */
_syscall:
mov %rcx, %r10
syscall
jnc _syscall_return
.errno:
#ifdef __PIC__
mov errno@GOTPCREL(%rip), %rcx
mov %rax, (%rcx)
#else
mov %rax, errno
#endif
mov $-1, %rax
_syscall_return:
ret
/* macros */
#ifndef SYSCALL
# ifdef __PIC__
# define SYSCALL(name) \
.global name; \
.type name,@function; \
name:; \
mov $SYS_ ## name, %rax; \
jmp _syscall@PLT
# else
# define SYSCALL(name) \
.global name; \
.type name,@function; \
name:; \
mov $SYS_ ## name, %rax; \
jmp _syscall
# endif
#endif
/* functions */
/* _brk */
.global _brk
.type _brk,@function
_brk:
mov $SYS_brk, %rax
syscall
jc .errno
ret
#undef SYS_brk
/* _exit */
.global _exit
.type _exit,@function
_exit:
mov $SYS_exit, %rax
#ifdef __PIC__
jmp _syscall@PLT
#else
jmp _syscall
#endif
/* execve */
.global execve
.type execve,@function
execve:
mov $SYS_execve, %rax
syscall
#ifdef __PIC__
mov errno@GOTPCREL(%rip), %rcx
mov %rax, (%rcx)
#else
mov %rax, errno
#endif
mov $-1, %rax
ret
#undef SYS_execve
/* _longjmp */
.global _longjmp
.type _longjmp,@function
_longjmp:
/* restore registers */
mov 64(%rdi), %r15 /* %r15 */
mov 56(%rdi), %r14 /* %r14 */
mov 48(%rdi), %r13 /* %r13 */
mov 40(%rdi), %r12 /* %r12 */
mov 32(%rdi), %r11 /* %r11 */
mov 24(%rdi), %rbp /* base pointer */
mov 16(%rdi), %rsp /* stack pointer */
mov 8(%rdi), %rbx
mov 0(%rdi), %rdx /* return address */
mov %rdx, 0(%rsp)
mov %esi, %eax /* if(val != 0) */
test %eax, %eax
jnz __longjmp_return /* goto __longjmp_return */
inc %eax /* val = 1 */
__longjmp_return:
ret /* return val */
/* longjmp */
.global longjmp
.type longjmp,@function
longjmp:
.global siglongjmp
.type siglongjmp,@function
siglongjmp:
mov 72(%rdi), %rdx /* if(env[9] == 0) */
test %rdx, %rdx
jz _longjmp_registers /* goto _longjmp_registers */
/* restore the signal mask */
/* sigprocmask(SIG_SETMASK, &env[10], NULL) */
push %rdi
push %rsi
mov $0x3, %rdi
lea 80(%rdi), %rsi
mov $0x0, %rdx
#ifdef __PIC__
call sigprocmask@PLT
#else
call sigprocmask
#endif
pop %rsi
pop %rdi
/* restore registers */
_longjmp_registers:
mov 64(%rdi), %r15 /* %r15 */
mov 56(%rdi), %r14 /* %r14 */
mov 48(%rdi), %r13 /* %r13 */
mov 40(%rdi), %r12 /* %r12 */
mov 32(%rdi), %r11 /* %r11 */
mov 24(%rdi), %rbp /* base pointer */
mov 16(%rdi), %rsp /* stack pointer */
mov 8(%rdi), %rbx
mov 0(%rdi), %rdx /* return address */
mov %rdx, 0(%rsp)
mov %esi, %eax /* if(val != 0) */
test %eax, %eax
jnz _longjmp_return /* goto _longjmp_return */
inc %eax /* else val = 1 */
_longjmp_return:
ret /* return val */
/* lseek */
.global lseek
.type lseek,@function
lseek:
mov %rdx, %rcx
mov %rsi, %rdx
mov $0, %rsi
mov $SYS_lseek, %rax
jmp _syscall
#undef SYS_lseek
/* mmap */
.global mmap
.type mmap,@function
mmap:
sub $0x10, %rsp
mov %r9, 0x8(%rsp)
mov $0, %r9
mov $SYS_mmap, %rax
mov %rcx, %r10
syscall
add $0x10, %rsp /* XXX clears carry flag? */
jc .errno
ret
#undef SYS_mmap
/* pipe */
.global pipe
.type pipe,@function
pipe:
mov $SYS_pipe, %rax
syscall
jc .errno
mov %eax, (%rdi)
mov %edx, 4(%rdi)
mov $0, %rax
ret
#undef SYS_pipe
/* _setjmp */
.global _setjmp
.type _setjmp,@function
_setjmp:
/* save registers */
mov 0(%rsp), %rax /* return address */
mov %rax, 0(%rdi)
mov %rbx, 8(%rdi) /* %rbx */
mov %rsp, 16(%rdi) /* stack pointer */
mov %rbp, 24(%rdi) /* base pointer */
mov %r11, 32(%rdi) /* %r11 */
mov %r12, 40(%rdi) /* %r12 */
mov %r13, 48(%rdi) /* %r13 */
mov %r14, 56(%rdi) /* %r14 */
mov %r15, 64(%rdi) /* %r15 */
/* the signal mask is not saved */
movq $0x0, 72(%rdi) /* env[9] = 0 */
mov $0x0, %eax /* return 0 */
ret
/* setjmp */
.global setjmp
.type setjmp,@function
setjmp:
/* save registers */
mov 0(%rsp), %rax /* return address */
mov %rax, 0(%rdi)
mov %rbx, 8(%rdi) /* %rbx */
mov %rsp, 16(%rdi) /* stack pointer */
mov %rbp, 24(%rdi) /* base pointer */
mov %r11, 32(%rdi) /* %r11 */
mov %r12, 40(%rdi) /* %r12 */
mov %r13, 48(%rdi) /* %r13 */
mov %r14, 56(%rdi) /* %r14 */
mov %r15, 64(%rdi) /* %r15 */
/* the signal mask is not saved yet */
movq $0x0, 72(%rdi) /* env[9] = 0 */
/* res = sigprocmask(0, NULL, &env[10]) */
push %rdi
mov $0x0, %rdi
mov $0x0, %rsi
lea 80(%rax), %rdx
#ifdef __PIC__
call sigprocmask@PLT
#else
call sigprocmask
#endif
pop %rdi
/* the signal mask was saved */
test %eax, %eax /* if(res == 0) */
jnz _setjmp_return
movq $0x1, 72(%rdi) /* env[9] = 1 */
_setjmp_return:
mov $0x0, %eax /* return 0 */
ret
/* sigaction */
.global __sigaction_sigtramp
.type __sigaction_sigtramp,@function
__sigaction_sigtramp:
mov %r15, %rdi
mov $SYS_setcontext, %rax
syscall
/* this should never be reached */
mov $SYS_exit, %rax
mov $-1, %rdi
syscall
.global sigaction
.type sigaction,@function
sigaction:
mov $SYS_sigaction, %rax
#ifdef __PIC__
lea __sigaction_sigtramp@GOTPCREL(%rip), %rcx
mov (%rcx), %rcx
#else
lea __sigaction_sigtramp, %rcx
#endif
mov $0x2, %r8
#ifdef __PIC__
jmp _syscall@PLT
#else
jmp _syscall
#endif
#undef SYS_sigaction
/* sigsetjmp */
.global sigsetjmp
.type sigsetjmp,@function
sigsetjmp:
test %esi, %esi /* if(savemask != 0) */
#ifdef __PIC__
jnz setjmp@PLT /* return setjmp() */
#else
jnz setjmp
#endif
#ifdef __PIC__
jmp _setjmp@PLT /* return _setjmp() */
#else
jmp _setjmp
#endif