mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
Update Android port
* exec/config.h.in (__bool_true_false_are_defined): * exec/configure.ac (REENTRANT): New definition. (READLINKAT_SYSCALL, READLINK_SYSCALL): New defines. Set on all hosts. * exec/exec.c (MIN, MAX): Remove redundant declarations. Move to config.h. (exec_0): Copy name of executable into NAME when !REENTRANT. * exec/exec.h (struct exec_tracee): New struct `exec_file'. * exec/trace.c (remove_tracee, handle_exec, handle_readlinkat) (process_system_call, after_fork): Handle readlinkat system calls.
This commit is contained in:
parent
f4512cca0b
commit
c47716f95b
5 changed files with 288 additions and 20 deletions
|
|
@ -76,6 +76,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
#undef HAVE_STRING_H
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
|
#undef HAVE_SYS_PARAM_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
#undef HAVE_SYS_STAT_H
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
|
@ -115,6 +118,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#undef PACKAGE_VERSION
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to number of the `readlinkat' system call. */
|
||||||
|
#undef READLINKAT_SYSCALL
|
||||||
|
|
||||||
|
/* Define to number of the `readlink' system call. */
|
||||||
|
#undef READLINK_SYSCALL
|
||||||
|
|
||||||
|
/* Define to 1 if the library is used within a signal handler. */
|
||||||
|
#undef REENTRANT
|
||||||
|
|
||||||
/* Define to 1 if the stack grows downwards. */
|
/* Define to 1 if the stack grows downwards. */
|
||||||
#undef STACK_GROWS_DOWNWARDS
|
#undef STACK_GROWS_DOWNWARDS
|
||||||
|
|
||||||
|
|
@ -129,6 +141,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
/* Define to register holding arg1 to system calls. */
|
/* Define to register holding arg1 to system calls. */
|
||||||
#undef SYSCALL_ARG1_REG
|
#undef SYSCALL_ARG1_REG
|
||||||
|
|
||||||
|
/* Define to register holding arg2 to system calls. */
|
||||||
|
#undef SYSCALL_ARG2_REG
|
||||||
|
|
||||||
|
/* Define to register holding arg3 to system calls. */
|
||||||
|
#undef SYSCALL_ARG3_REG
|
||||||
|
|
||||||
/* Define to register holding arg0 to system calls. */
|
/* Define to register holding arg0 to system calls. */
|
||||||
#undef SYSCALL_ARG_REG
|
#undef SYSCALL_ARG_REG
|
||||||
|
|
||||||
|
|
@ -217,3 +235,15 @@ typedef bool _Bool;
|
||||||
# define __bool_true_false_are_defined 1
|
# define __bool_true_false_are_defined 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif /* HAVE_SYS_PARAM_H */
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif /* MAX */
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif /* MIN */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,11 @@ General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */])
|
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */])
|
||||||
|
|
||||||
|
AC_ARG_WITH([reentrancy],
|
||||||
|
[AS_HELP_STRING([--with-reentrancy],
|
||||||
|
[Generate library which can be used within a signal handler.])],
|
||||||
|
[AC_DEFINE([REENTRANT], [1])])
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
|
@ -56,6 +61,7 @@ AC_TYPE_PID_T
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
|
AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
|
||||||
AC_CHECK_DECLS([stpcpy, stpncpy])
|
AC_CHECK_DECLS([stpcpy, stpncpy])
|
||||||
|
AC_CHECK_HEADERS([sys/param.h]) dnl for MIN and MAX
|
||||||
|
|
||||||
AH_BOTTOM([
|
AH_BOTTOM([
|
||||||
#ifdef HAVE_STDBOOL_H
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
|
@ -73,6 +79,18 @@ typedef bool _Bool;
|
||||||
# define true 1
|
# define true 1
|
||||||
# define __bool_true_false_are_defined 1
|
# define __bool_true_false_are_defined 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif /* HAVE_SYS_PARAM_H */
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif /* MAX */
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif /* MIN */
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
AC_C_BIGENDIAN
|
||||||
|
|
@ -83,6 +101,8 @@ AH_TEMPLATE([USER_REGS_STRUCT], [Define to structure holding user registers.])
|
||||||
AH_TEMPLATE([SYSCALL_NUM_REG], [Define to register holding the system call number.])
|
AH_TEMPLATE([SYSCALL_NUM_REG], [Define to register holding the system call number.])
|
||||||
AH_TEMPLATE([SYSCALL_ARG_REG], [Define to register holding arg0 to system calls.])
|
AH_TEMPLATE([SYSCALL_ARG_REG], [Define to register holding arg0 to system calls.])
|
||||||
AH_TEMPLATE([SYSCALL_ARG1_REG], [Define to register holding arg1 to system calls.])
|
AH_TEMPLATE([SYSCALL_ARG1_REG], [Define to register holding arg1 to system calls.])
|
||||||
|
AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls.])
|
||||||
|
AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.])
|
||||||
AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.])
|
AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.])
|
||||||
AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.])
|
AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.])
|
||||||
AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.])
|
AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.])
|
||||||
|
|
@ -94,6 +114,9 @@ AH_TEMPLATE([EXECUTABLE_BASE], [Virtual address for loading PIC executables])
|
||||||
AH_TEMPLATE([INTERPRETER_BASE], [Virtual address for loading PIC interpreters])
|
AH_TEMPLATE([INTERPRETER_BASE], [Virtual address for loading PIC interpreters])
|
||||||
AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.])
|
AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.])
|
||||||
AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
|
AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
|
||||||
|
AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.])
|
||||||
|
AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.])
|
||||||
|
AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.])
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
|
@ -206,6 +229,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [rax])
|
AC_DEFINE([SYSCALL_RET_REG], [rax])
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [rdi])
|
AC_DEFINE([SYSCALL_ARG_REG], [rdi])
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [rsi])
|
AC_DEFINE([SYSCALL_ARG1_REG], [rsi])
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [rdx])
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [r10])
|
||||||
AC_DEFINE([STACK_POINTER], [rsp])
|
AC_DEFINE([STACK_POINTER], [rsp])
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -215,6 +240,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x600000000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x600000000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
exec_CHECK_LINUX_CLONE3
|
exec_CHECK_LINUX_CLONE3
|
||||||
# Make sure the loader doesn't conflict with other position
|
# Make sure the loader doesn't conflict with other position
|
||||||
# dependent code.
|
# dependent code.
|
||||||
|
|
@ -232,6 +259,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [eax])
|
AC_DEFINE([SYSCALL_RET_REG], [eax])
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [ebx])
|
AC_DEFINE([SYSCALL_ARG_REG], [ebx])
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [ecx])
|
AC_DEFINE([SYSCALL_ARG1_REG], [ecx])
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [edx])
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [esi])
|
||||||
AC_DEFINE([STACK_POINTER], [esp])
|
AC_DEFINE([STACK_POINTER], [esp])
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -239,6 +268,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0xaf000000])
|
AC_DEFINE([INTERPRETER_BASE], [0xaf000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
exec_CHECK_LINUX_CLONE3
|
exec_CHECK_LINUX_CLONE3
|
||||||
# Make sure the loader doesn't conflict with other position
|
# Make sure the loader doesn't conflict with other position
|
||||||
# dependent code.
|
# dependent code.
|
||||||
|
|
@ -256,6 +287,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [[regs[0]]])
|
AC_DEFINE([SYSCALL_RET_REG], [[regs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [[regs[0]]])
|
AC_DEFINE([SYSCALL_ARG_REG], [[regs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [[regs[1]]])
|
AC_DEFINE([SYSCALL_ARG1_REG], [[regs[1]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [[regs[2]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [[regs[3]]])
|
||||||
AC_DEFINE([STACK_POINTER], [sp])
|
AC_DEFINE([STACK_POINTER], [sp])
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -264,6 +297,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
# Note that aarch64 has no `readlink'.
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
exec_CHECK_LINUX_CLONE3
|
exec_CHECK_LINUX_CLONE3
|
||||||
# Make sure the loader doesn't conflict with other position
|
# Make sure the loader doesn't conflict with other position
|
||||||
# dependent code. ARM places rather significant restrictions on
|
# dependent code. ARM places rather significant restrictions on
|
||||||
|
|
@ -282,6 +317,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
|
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
|
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
|
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
|
||||||
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -289,6 +326,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
exec_CHECK_LINUX_CLONE3
|
exec_CHECK_LINUX_CLONE3
|
||||||
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
|
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
|
||||||
exec_loader=loader-armeabi.s],
|
exec_loader=loader-armeabi.s],
|
||||||
|
|
@ -300,6 +339,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
|
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
|
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
|
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
|
||||||
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -307,6 +348,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
exec_CHECK_LINUX_CLONE3
|
exec_CHECK_LINUX_CLONE3
|
||||||
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
|
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
|
||||||
exec_loader=loader-armeabi.s],
|
exec_loader=loader-armeabi.s],
|
||||||
|
|
@ -324,6 +367,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
|
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
|
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
|
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
|
||||||
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -331,6 +376,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
AC_CHECK_DECL([_MIPS_SIM], [exec_CHECK_MIPS_NABI],
|
AC_CHECK_DECL([_MIPS_SIM], [exec_CHECK_MIPS_NABI],
|
||||||
[AC_MSG_ERROR([_MIPS_SIM could not be determined]),
|
[AC_MSG_ERROR([_MIPS_SIM could not be determined]),
|
||||||
[[
|
[[
|
||||||
|
|
@ -347,6 +394,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
|
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
|
||||||
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
|
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
|
||||||
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
|
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
|
||||||
|
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
|
||||||
|
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
|
||||||
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
||||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||||
|
|
@ -355,6 +404,8 @@ AS_CASE([$host], [x86_64-*linux*],
|
||||||
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
|
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
|
||||||
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
|
||||||
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
|
||||||
|
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
|
||||||
|
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
|
||||||
AC_CACHE_CHECK([whether as understands `daddi'],
|
AC_CACHE_CHECK([whether as understands `daddi'],
|
||||||
[exec_cv_as_daddi],
|
[exec_cv_as_daddi],
|
||||||
[exec_cv_as_daddi=no
|
[exec_cv_as_daddi=no
|
||||||
|
|
|
||||||
52
exec/exec.c
52
exec/exec.c
|
|
@ -31,14 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#endif /* MIN */
|
|
||||||
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(a, b) ((a) < (b) ? (b) : (a))
|
|
||||||
#endif /* MAX */
|
|
||||||
|
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
|
|
||||||
#if defined __mips__ && !defined MIPS_NABI
|
#if defined __mips__ && !defined MIPS_NABI
|
||||||
|
|
@ -938,6 +930,10 @@ format_pid (char *in, unsigned int pid)
|
||||||
with #!; in that case, find the program to open and use that
|
with #!; in that case, find the program to open and use that
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
If REENTRANT is not defined, NAME is actually a buffer of size
|
||||||
|
PATH_MAX + 80. In that case, copy over the file name actually
|
||||||
|
opened.
|
||||||
|
|
||||||
Next, read the executable header, and add the necessary memory
|
Next, read the executable header, and add the necessary memory
|
||||||
mappings for each file. Finally, return the action data and its
|
mappings for each file. Finally, return the action data and its
|
||||||
size in *SIZE.
|
size in *SIZE.
|
||||||
|
|
@ -948,7 +944,7 @@ format_pid (char *in, unsigned int pid)
|
||||||
Value is NULL upon failure, with errno set accordingly. */
|
Value is NULL upon failure, with errno set accordingly. */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
exec_0 (const char *name, struct exec_tracee *tracee,
|
exec_0 (char *name, struct exec_tracee *tracee,
|
||||||
size_t *size, USER_REGS_STRUCT *regs)
|
size_t *size, USER_REGS_STRUCT *regs)
|
||||||
{
|
{
|
||||||
int fd, rc, i;
|
int fd, rc, i;
|
||||||
|
|
@ -961,7 +957,8 @@ exec_0 (const char *name, struct exec_tracee *tracee,
|
||||||
#if defined __mips__ && !defined MIPS_NABI
|
#if defined __mips__ && !defined MIPS_NABI
|
||||||
int fpu_mode;
|
int fpu_mode;
|
||||||
#endif /* defined __mips__ && !defined MIPS_NABI */
|
#endif /* defined __mips__ && !defined MIPS_NABI */
|
||||||
char buffer[PATH_MAX + 80], *rewrite;
|
char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
|
||||||
|
ssize_t link_size;
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
|
|
||||||
/* If name is not absolute, then make it relative to TRACEE's
|
/* If name is not absolute, then make it relative to TRACEE's
|
||||||
|
|
@ -971,18 +968,43 @@ exec_0 (const char *name, struct exec_tracee *tracee,
|
||||||
{
|
{
|
||||||
/* Clear `buffer'. */
|
/* Clear `buffer'. */
|
||||||
memset (buffer, 0, sizeof buffer);
|
memset (buffer, 0, sizeof buffer);
|
||||||
|
memset (buffer1, 0, sizeof buffer);
|
||||||
|
|
||||||
/* Copy over /proc, the PID, and /cwd/. */
|
/* Copy over /proc, the PID, and /cwd/. */
|
||||||
rewrite = stpcpy (buffer, "/proc/");
|
rewrite = stpcpy (buffer, "/proc/");
|
||||||
rewrite = format_pid (rewrite, tracee->pid);
|
rewrite = format_pid (rewrite, tracee->pid);
|
||||||
rewrite = stpcpy (rewrite, "/cwd/");
|
stpcpy (rewrite, "/cwd");
|
||||||
|
|
||||||
/* Make sure there is enough free space. */
|
/* Resolve this symbolic link. */
|
||||||
remaining = buffer + sizeof buffer - rewrite - 1;
|
|
||||||
|
link_size = readlink (buffer, buffer1,
|
||||||
|
PATH_MAX + 1);
|
||||||
|
|
||||||
|
if (link_size < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check that the name is a reasonable size. */
|
||||||
|
|
||||||
|
if (link_size > PATH_MAX)
|
||||||
|
{
|
||||||
|
/* The name is too long. */
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a directory separator if necessary. */
|
||||||
|
|
||||||
|
if (!link_size || buffer1[link_size - 1] != '/')
|
||||||
|
buffer1[link_size] = '/', link_size++;
|
||||||
|
|
||||||
|
rewrite = buffer1 + link_size;
|
||||||
|
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
|
||||||
rewrite = stpncpy (rewrite, name, remaining);
|
rewrite = stpncpy (rewrite, name, remaining);
|
||||||
|
|
||||||
/* Replace name with buffer. */
|
/* Replace name with buffer1. */
|
||||||
name = buffer;
|
#ifndef REENTRANT
|
||||||
|
strcpy (name, buffer1);
|
||||||
|
#endif /* REENTRANT */
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open (name, O_RDONLY);
|
fd = open (name, O_RDONLY);
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,11 @@ struct exec_tracee
|
||||||
/* Whether or not the tracee is currently waiting for a system call
|
/* Whether or not the tracee is currently waiting for a system call
|
||||||
to complete. */
|
to complete. */
|
||||||
bool waiting_for_syscall;
|
bool waiting_for_syscall;
|
||||||
|
|
||||||
|
#ifndef REENTRANT
|
||||||
|
/* Name of the executable being run. */
|
||||||
|
char *exec_file;
|
||||||
|
#endif /* !REENTRANT */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -184,7 +189,7 @@ extern pid_t exec_waitpid (pid_t, int *, int);
|
||||||
|
|
||||||
/* Defined in exec.c. */
|
/* Defined in exec.c. */
|
||||||
|
|
||||||
extern char *exec_0 (const char *, struct exec_tracee *,
|
extern char *exec_0 (char *, struct exec_tracee *,
|
||||||
size_t *, USER_REGS_STRUCT *);
|
size_t *, USER_REGS_STRUCT *);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
168
exec/trace.c
168
exec/trace.c
|
|
@ -315,6 +315,13 @@ remove_tracee (struct exec_tracee *tracee)
|
||||||
|
|
||||||
/* Link the tracee onto the list of free tracees. */
|
/* Link the tracee onto the list of free tracees. */
|
||||||
tracee->next = free_tracees;
|
tracee->next = free_tracees;
|
||||||
|
|
||||||
|
#ifndef REENTRANT
|
||||||
|
/* Free the exec file, if any. */
|
||||||
|
free (tracee->exec_file);
|
||||||
|
tracee->exec_file = NULL;
|
||||||
|
#endif /* REENTRANT */
|
||||||
|
|
||||||
free_tracees = tracee;
|
free_tracees = tracee;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -431,7 +438,7 @@ syscall_trap_p (siginfo_t *signal)
|
||||||
static int
|
static int
|
||||||
handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX], *area;
|
char buffer[PATH_MAX + 80], *area;
|
||||||
USER_REGS_STRUCT original;
|
USER_REGS_STRUCT original;
|
||||||
size_t size, loader_size;
|
size_t size, loader_size;
|
||||||
USER_WORD loader, size1, sp;
|
USER_WORD loader, size1, sp;
|
||||||
|
|
@ -517,6 +524,17 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef REENTRANT
|
||||||
|
/* Now that the loader has started, record the value to use for
|
||||||
|
/proc/self/exe. Don't give up just because strdup fails.
|
||||||
|
|
||||||
|
Note that exec_0 copies the absolute file name into buffer. */
|
||||||
|
|
||||||
|
if (tracee->exec_file)
|
||||||
|
free (tracee->exec_file);
|
||||||
|
tracee->exec_file = strdup (buffer);
|
||||||
|
#endif /* REENTRANT */
|
||||||
|
|
||||||
again:
|
again:
|
||||||
rc = waitpid (tracee->pid, &wstatus, __WALL);
|
rc = waitpid (tracee->pid, &wstatus, __WALL);
|
||||||
if (rc == -1 && errno == EINTR)
|
if (rc == -1 && errno == EINTR)
|
||||||
|
|
@ -622,6 +640,91 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a `readlink' or `readlinkat' system call.
|
||||||
|
|
||||||
|
CALLNO is the system call number, and REGS are the current user
|
||||||
|
registers of the TRACEE.
|
||||||
|
|
||||||
|
If the first argument of a `readlinkat' system call is AT_FDCWD,
|
||||||
|
and the file name specified in either a `readlink' or `readlinkat'
|
||||||
|
system call is `/proc/self/exe', write the name of the executable
|
||||||
|
being run into the buffer specified in the system call.
|
||||||
|
|
||||||
|
Return the number of bytes written to the tracee's buffer in
|
||||||
|
*RESULT.
|
||||||
|
|
||||||
|
Value is 0 upon success. Value is 1 upon failure, and 2 if the
|
||||||
|
system call has been emulated. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs,
|
||||||
|
struct exec_tracee *tracee, USER_WORD *result)
|
||||||
|
{
|
||||||
|
#ifdef REENTRANT
|
||||||
|
/* readlinkat cannot be handled specially when the library is built
|
||||||
|
to be reentrant, as the file name information cannot be
|
||||||
|
recorded. */
|
||||||
|
return 0;
|
||||||
|
#else /* !REENTRANT */
|
||||||
|
|
||||||
|
char buffer[PATH_MAX + 1];
|
||||||
|
USER_WORD address, return_buffer, size;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
/* Read the file name. */
|
||||||
|
|
||||||
|
#ifdef READLINK_SYSCALL
|
||||||
|
if (callno == READLINK_SYSCALL)
|
||||||
|
{
|
||||||
|
address = regs->SYSCALL_ARG_REG;
|
||||||
|
return_buffer = regs->SYSCALL_ARG1_REG;
|
||||||
|
size = regs->SYSCALL_ARG2_REG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* READLINK_SYSCALL */
|
||||||
|
{
|
||||||
|
address = regs->SYSCALL_ARG1_REG;
|
||||||
|
return_buffer = regs->SYSCALL_ARG2_REG;
|
||||||
|
size = regs->SYSCALL_ARG3_REG;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_memory (tracee, buffer, PATH_MAX, address);
|
||||||
|
|
||||||
|
/* Make sure BUFFER is NULL terminated. */
|
||||||
|
|
||||||
|
if (!memchr (buffer, '\0', PATH_MAX))
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check if the caller is looking for /proc/self/exe.
|
||||||
|
|
||||||
|
dirfd can be ignored, as for now only absolute file names are
|
||||||
|
handled. FIXME. */
|
||||||
|
|
||||||
|
if (strcmp (buffer, "/proc/self/exe") || !tracee->exec_file)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Copy over tracee->exec_file. Truncate it to PATH_MAX, length, or
|
||||||
|
size, whichever is less. */
|
||||||
|
|
||||||
|
length = strlen (tracee->exec_file);
|
||||||
|
length = MIN (size, MIN (PATH_MAX, length));
|
||||||
|
strncpy (buffer, tracee->exec_file, length);
|
||||||
|
|
||||||
|
if (user_copy (tracee, (unsigned char *) buffer,
|
||||||
|
return_buffer, length))
|
||||||
|
{
|
||||||
|
errno = EIO;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = length;
|
||||||
|
return 2;
|
||||||
|
#endif /* REENTRANT */
|
||||||
|
}
|
||||||
|
|
||||||
/* Process the system call at which TRACEE is stopped. If the system
|
/* Process the system call at which TRACEE is stopped. If the system
|
||||||
call is not known or not exec, send TRACEE on its way. Otherwise,
|
call is not known or not exec, send TRACEE on its way. Otherwise,
|
||||||
rewrite it to load the loader and perform an appropriate action. */
|
rewrite it to load the loader and perform an appropriate action. */
|
||||||
|
|
@ -635,6 +738,8 @@ process_system_call (struct exec_tracee *tracee)
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
USER_WORD old_w1, old_w2;
|
USER_WORD old_w1, old_w2;
|
||||||
#endif /* __aarch64__ */
|
#endif /* __aarch64__ */
|
||||||
|
USER_WORD result;
|
||||||
|
bool reporting_error;
|
||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
rc = aarch64_get_regs (tracee->pid, ®s);
|
rc = aarch64_get_regs (tracee->pid, ®s);
|
||||||
|
|
@ -678,6 +783,24 @@ process_system_call (struct exec_tracee *tracee)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef READLINK_SYSCALL
|
||||||
|
case READLINK_SYSCALL:
|
||||||
|
#endif /* READLINK_SYSCALL */
|
||||||
|
case READLINKAT_SYSCALL:
|
||||||
|
|
||||||
|
/* Handle this readlinkat system call. */
|
||||||
|
rc = handle_readlinkat (callno, ®s, tracee,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
/* rc means the same as in `handle_exec'. */
|
||||||
|
|
||||||
|
if (rc == 1)
|
||||||
|
goto report_syscall_error;
|
||||||
|
else if (rc == 2)
|
||||||
|
goto emulate_syscall;
|
||||||
|
|
||||||
|
/* Fallthrough. */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Don't wait for the system call to finish; instead, the system
|
/* Don't wait for the system call to finish; instead, the system
|
||||||
will DTRT upon the next call to PTRACE_SYSCALL after the
|
will DTRT upon the next call to PTRACE_SYSCALL after the
|
||||||
|
|
@ -694,8 +817,16 @@ process_system_call (struct exec_tracee *tracee)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
report_syscall_error:
|
report_syscall_error:
|
||||||
/* Reporting an error works by setting the system call number to -1,
|
reporting_error = true;
|
||||||
letting it continue, and then substituting errno for ENOSYS.
|
goto common;
|
||||||
|
|
||||||
|
emulate_syscall:
|
||||||
|
reporting_error = false;
|
||||||
|
common:
|
||||||
|
|
||||||
|
/* Reporting an error or emulating a system call works by setting
|
||||||
|
the system call number to -1, letting it continue, and then
|
||||||
|
substituting errno for ENOSYS in the case of an error.
|
||||||
|
|
||||||
Make sure that the stack pointer is restored to its original
|
Make sure that the stack pointer is restored to its original
|
||||||
position upon exit, or bad things can happen. */
|
position upon exit, or bad things can happen. */
|
||||||
|
|
@ -755,7 +886,7 @@ process_system_call (struct exec_tracee *tracee)
|
||||||
/* The process has been killed in response to a signal. In this
|
/* The process has been killed in response to a signal. In this
|
||||||
case, simply unlink the tracee and return. */
|
case, simply unlink the tracee and return. */
|
||||||
remove_tracee (tracee);
|
remove_tracee (tracee);
|
||||||
else
|
else if (reporting_error)
|
||||||
{
|
{
|
||||||
#ifdef __mips__
|
#ifdef __mips__
|
||||||
/* MIPS systems place errno in v0 and set a3 to 1. */
|
/* MIPS systems place errno in v0 and set a3 to 1. */
|
||||||
|
|
@ -775,6 +906,32 @@ process_system_call (struct exec_tracee *tracee)
|
||||||
ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s);
|
ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s);
|
||||||
#endif /* __aarch64__ */
|
#endif /* __aarch64__ */
|
||||||
|
|
||||||
|
/* Now wait for the next system call to happen. */
|
||||||
|
ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No error is being reported. Return the result in the
|
||||||
|
appropriate registers. */
|
||||||
|
|
||||||
|
#ifdef __mips__
|
||||||
|
/* MIPS systems place errno in v0 and set a3 to 1. */
|
||||||
|
regs.gregs[2] = result;
|
||||||
|
regs.gregs[7] = 0;
|
||||||
|
#else /* !__mips__ */
|
||||||
|
regs.SYSCALL_RET_REG = result;
|
||||||
|
#endif /* __mips__ */
|
||||||
|
|
||||||
|
/* Report errno. */
|
||||||
|
#ifdef __aarch64__
|
||||||
|
/* Restore x1 and x2. x0 is clobbered by errno. */
|
||||||
|
regs.regs[1] = old_w1;
|
||||||
|
regs.regs[2] = old_w2;
|
||||||
|
aarch64_set_regs (tracee->pid, ®s, false);
|
||||||
|
#else /* !__aarch64__ */
|
||||||
|
ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s);
|
||||||
|
#endif /* __aarch64__ */
|
||||||
|
|
||||||
/* Now wait for the next system call to happen. */
|
/* Now wait for the next system call to happen. */
|
||||||
ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL);
|
ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -869,6 +1026,9 @@ after_fork (pid_t pid)
|
||||||
tracee->pid = pid;
|
tracee->pid = pid;
|
||||||
tracee->next = tracing_processes;
|
tracee->next = tracing_processes;
|
||||||
tracee->waiting_for_syscall = false;
|
tracee->waiting_for_syscall = false;
|
||||||
|
#ifndef REENTRANT
|
||||||
|
tracee->exec_file = NULL;
|
||||||
|
#endif /* REENTRANT */
|
||||||
tracing_processes = tracee;
|
tracing_processes = tracee;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue