6552 lines
245 KiB
Diff
6552 lines
245 KiB
Diff
------------------------------------------------------------------------
|
|
r13770 | sewardj | 2014-01-12 13:54:00 +0100 (So, 12. Jan 2014) | 2 Zeilen
|
|
|
|
Add support for ARMv8 AArch64 (the 64 bit ARM instruction set).
|
|
|
|
------------------------------------------------------------------------
|
|
Index: configure.ac
|
|
===================================================================
|
|
--- configure.ac.orig
|
|
+++ configure.ac
|
|
@@ -195,6 +195,11 @@ case "${host_cpu}" in
|
|
ARCH_MAX="arm"
|
|
;;
|
|
|
|
+ aarch64*)
|
|
+ AC_MSG_RESULT([ok (${host_cpu})])
|
|
+ ARCH_MAX="arm64"
|
|
+ ;;
|
|
+
|
|
mips)
|
|
AC_MSG_RESULT([ok (${host_cpu})])
|
|
ARCH_MAX="mips32"
|
|
@@ -559,6 +564,35 @@ case "$ARCH_MAX-$VGCONF_OS" in
|
|
valt_load_address_sec_inner="0xUNSET"
|
|
AC_MSG_RESULT([ok (${host_cpu}-${host_os})])
|
|
;;
|
|
+ arm64-linux)
|
|
+ valt_load_address_sec_norml="0xUNSET"
|
|
+ valt_load_address_sec_inner="0xUNSET"
|
|
+ if test x$vg_cv_only64bit = xyes; then
|
|
+ VGCONF_ARCH_PRI="arm64"
|
|
+ VGCONF_ARCH_SEC=""
|
|
+ VGCONF_PLATFORM_PRI_CAPS="ARM64_LINUX"
|
|
+ VGCONF_PLATFORM_SEC_CAPS=""
|
|
+ valt_load_address_pri_norml="0x38000000"
|
|
+ valt_load_address_pri_inner="0x28000000"
|
|
+ elif test x$vg_cv_only32bit = xyes; then
|
|
+ VGCONF_ARCH_PRI="arm"
|
|
+ VGCONF_ARCH_SEC=""
|
|
+ VGCONF_PLATFORM_PRI_CAPS="ARM_LINUX"
|
|
+ VGCONF_PLATFORM_SEC_CAPS=""
|
|
+ valt_load_address_pri_norml="0x38000000"
|
|
+ valt_load_address_pri_inner="0x28000000"
|
|
+ else
|
|
+ VGCONF_ARCH_PRI="arm64"
|
|
+ VGCONF_ARCH_SEC="arm"
|
|
+ VGCONF_PLATFORM_PRI_CAPS="ARM64_LINUX"
|
|
+ VGCONF_PLATFORM_SEC_CAPS="ARM_LINUX"
|
|
+ valt_load_address_pri_norml="0x38000000"
|
|
+ valt_load_address_pri_inner="0x28000000"
|
|
+ valt_load_address_sec_norml="0x38000000"
|
|
+ valt_load_address_sec_inner="0x28000000"
|
|
+ fi
|
|
+ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
|
|
+ ;;
|
|
s390x-linux)
|
|
VGCONF_ARCH_PRI="s390x"
|
|
VGCONF_ARCH_SEC=""
|
|
@@ -624,7 +658,10 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC3
|
|
AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC64,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX )
|
|
AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM,
|
|
- test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX )
|
|
+ test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
|
|
+ -o x$VGCONF_PLATFORM_SEC_CAPS = xARM_LINUX )
|
|
+AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM64,
|
|
+ test x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX )
|
|
AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_S390X,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX )
|
|
AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS32,
|
|
@@ -645,7 +682,10 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_
|
|
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_PPC64_LINUX,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX)
|
|
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM_LINUX,
|
|
- test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX)
|
|
+ test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
|
|
+ -o x$VGCONF_PLATFORM_SEC_CAPS = xARM_LINUX)
|
|
+AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM64_LINUX,
|
|
+ test x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX)
|
|
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
|
|
-o x$VGCONF_PLATFORM_SEC_CAPS = xS390X_LINUX)
|
|
@@ -653,7 +693,6 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX)
|
|
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS64_LINUX,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX)
|
|
-
|
|
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_DARWIN,
|
|
test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \
|
|
-o x$VGCONF_PLATFORM_SEC_CAPS = xX86_DARWIN)
|
|
@@ -670,6 +709,7 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX,
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
|
|
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX)
|
|
@@ -2406,6 +2446,7 @@ if test x$VGCONF_PLATFORM_PRI_CAPS = xX8
|
|
mflag_primary=$FLAG_M32
|
|
elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
|
|
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \
|
|
-o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then
|
|
mflag_primary=$FLAG_M64
|
|
elif test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN ; then
|
|
Index: drd/drd_bitmap.h
|
|
===================================================================
|
|
--- drd/drd_bitmap.h.orig
|
|
+++ drd/drd_bitmap.h
|
|
@@ -140,7 +140,7 @@ Addr make_address(const UWord a1, const
|
|
|| defined(VGA_mips32)
|
|
#define BITS_PER_BITS_PER_UWORD 5
|
|
#elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x) \
|
|
- || defined(VGA_mips64)
|
|
+ || defined(VGA_mips64) || defined(VGA_arm64)
|
|
#define BITS_PER_BITS_PER_UWORD 6
|
|
#else
|
|
#error Unknown platform.
|
|
Index: drd/drd_load_store.c
|
|
===================================================================
|
|
--- drd/drd_load_store.c.orig
|
|
+++ drd/drd_load_store.c
|
|
@@ -47,6 +47,8 @@
|
|
#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
|
|
#elif defined(VGA_arm)
|
|
#define STACK_POINTER_OFFSET OFFSET_arm_R13
|
|
+#elif defined(VGA_arm64)
|
|
+#define STACK_POINTER_OFFSET OFFSET_arm64_SP
|
|
#elif defined(VGA_s390x)
|
|
#define STACK_POINTER_OFFSET OFFSET_s390x_r15
|
|
#elif defined(VGA_mips32)
|
|
Index: coregrind/m_main.c
|
|
===================================================================
|
|
--- coregrind/m_main.c.orig
|
|
+++ coregrind/m_main.c
|
|
@@ -2021,6 +2021,8 @@ Int valgrind_main ( Int argc, HChar **ar
|
|
iters = 5;
|
|
# elif defined(VGP_arm_linux)
|
|
iters = 5;
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ iters = 5;
|
|
# elif defined(VGP_s390x_linux)
|
|
iters = 10;
|
|
# elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
@@ -2908,6 +2910,31 @@ asm("\n"
|
|
"\t.word "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n"
|
|
"\t.word "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n"
|
|
);
|
|
+#elif defined(VGP_arm64_linux)
|
|
+asm("\n"
|
|
+ "\t.text\n"
|
|
+ "\t.align 2\n"
|
|
+ "\t.type _start,#function\n"
|
|
+ "\t.global _start\n"
|
|
+ "_start:\n"
|
|
+ "\tadrp x0, vgPlain_interim_stack\n"
|
|
+ "\tadd x0, x0, :lo12:vgPlain_interim_stack\n"
|
|
+ // The next 2 assume that VG_STACK_GUARD_SZB fits in 32 bits
|
|
+ "\tmov x1, (("VG_STRINGIFY(VG_STACK_GUARD_SZB)") >> 0) & 0xFFFF\n"
|
|
+ "\tmovk x1, (("VG_STRINGIFY(VG_STACK_GUARD_SZB)") >> 16) & 0xFFFF,"
|
|
+ " lsl 16\n"
|
|
+ "\tadd x0, x0, x1\n"
|
|
+ // The next 2 assume that VG_STACK_ACTIVE_SZB fits in 32 bits
|
|
+ "\tmov x1, (("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)") >> 0) & 0xFFFF\n"
|
|
+ "\tmovk x1, (("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)") >> 16) & 0xFFFF,"
|
|
+ " lsl 16\n"
|
|
+ "\tadd x0, x0, x1\n"
|
|
+ "\tand x0, x0, -16\n"
|
|
+ "\tmov x1, sp\n"
|
|
+ "\tmov sp, x0\n"
|
|
+ "\tmov x0, x1\n"
|
|
+ "\tb _start_in_C_linux\n"
|
|
+);
|
|
#elif defined(VGP_mips32_linux)
|
|
asm("\n"
|
|
"\t.type _gp_disp,@object\n"
|
|
@@ -3033,7 +3060,8 @@ void _start_in_C_linux ( UWord* pArgc )
|
|
|
|
the_iicii.sp_at_startup = (Addr)pArgc;
|
|
|
|
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
|
|
+# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
{
|
|
/* ppc/ppc64 can be configured with different page sizes.
|
|
Determine this early. This is an ugly hack and really should
|
|
Index: coregrind/m_libcassert.c
|
|
===================================================================
|
|
--- coregrind/m_libcassert.c.orig
|
|
+++ coregrind/m_libcassert.c
|
|
@@ -136,6 +136,25 @@
|
|
(srP)->misc.ARM.r11 = block[4]; \
|
|
(srP)->misc.ARM.r7 = block[5]; \
|
|
}
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define GET_STARTREGS(srP) \
|
|
+ { ULong block[4]; \
|
|
+ __asm__ __volatile__( \
|
|
+ "adr x19, 0;" \
|
|
+ "str x19, [%0, #+0];" /* pc */ \
|
|
+ "mov x19, sp;" \
|
|
+ "str x19, [%0, #+8];" /* sp */ \
|
|
+ "str x29, [%0, #+16];" /* fp */ \
|
|
+ "str x30, [%0, #+24];" /* lr */ \
|
|
+ : /* out */ \
|
|
+ : /* in */ "r"(&block[0]) \
|
|
+ : /* trash */ "memory","x19" \
|
|
+ ); \
|
|
+ (srP)->r_pc = block[0]; \
|
|
+ (srP)->r_sp = block[1]; \
|
|
+ (srP)->misc.ARM64.x29 = block[2]; \
|
|
+ (srP)->misc.ARM64.x30 = block[3]; \
|
|
+ }
|
|
#elif defined(VGP_s390x_linux)
|
|
# define GET_STARTREGS(srP) \
|
|
{ ULong ia, sp, fp, lr; \
|
|
Index: coregrind/m_libcproc.c
|
|
===================================================================
|
|
--- coregrind/m_libcproc.c.orig
|
|
+++ coregrind/m_libcproc.c
|
|
@@ -458,8 +458,14 @@ Int VG_(gettid)(void)
|
|
* the /proc/self link is pointing...
|
|
*/
|
|
|
|
+# if defined(VGP_arm64_linux)
|
|
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
|
|
+ (UWord)"/proc/self",
|
|
+ (UWord)pid, sizeof(pid));
|
|
+# else
|
|
res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
|
|
(UWord)pid, sizeof(pid));
|
|
+# endif
|
|
if (!sr_isError(res) && sr_Res(res) > 0) {
|
|
HChar* s;
|
|
pid[sr_Res(res)] = '\0';
|
|
@@ -552,7 +558,7 @@ Int VG_(getgroups)( Int size, UInt* list
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
|
|
|| defined(VGP_arm_linux) \
|
|
|| defined(VGO_darwin) || defined(VGP_s390x_linux) \
|
|
- || defined(VGP_mips32_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_arm64_linux)
|
|
SysRes sres;
|
|
sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
|
|
if (sr_isError(sres))
|
|
@@ -763,6 +769,121 @@ void VG_(invalidate_icache) ( void *ptr,
|
|
Addr endaddr = startaddr + nbytes;
|
|
VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr);
|
|
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ // This arm64_linux section of this function VG_(invalidate_icache)
|
|
+ // is copied from
|
|
+ // https://github.com/armvixl/vixl/blob/master/src/a64/cpu-a64.cc
|
|
+ // which has the following copyright notice:
|
|
+ /*
|
|
+ Copyright 2013, ARM Limited
|
|
+ All rights reserved.
|
|
+
|
|
+ Redistribution and use in source and binary forms, with or without
|
|
+ modification, are permitted provided that the following conditions are met:
|
|
+
|
|
+ * Redistributions of source code must retain the above copyright notice,
|
|
+ this list of conditions and the following disclaimer.
|
|
+ * 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.
|
|
+ * Neither the name of ARM Limited nor the names of its contributors may be
|
|
+ used to endorse or promote products derived from this software without
|
|
+ specific prior written permission.
|
|
+
|
|
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 OWNER 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.
|
|
+ */
|
|
+
|
|
+ // Ask what the I and D line sizes are
|
|
+ UInt cache_type_register;
|
|
+ // Copy the content of the cache type register to a core register.
|
|
+ __asm__ __volatile__ ("mrs %[ctr], ctr_el0" // NOLINT
|
|
+ : [ctr] "=r" (cache_type_register));
|
|
+
|
|
+ const Int kDCacheLineSizeShift = 16;
|
|
+ const Int kICacheLineSizeShift = 0;
|
|
+ const UInt kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;
|
|
+ const UInt kICacheLineSizeMask = 0xf << kICacheLineSizeShift;
|
|
+
|
|
+ // The cache type register holds the size of the I and D caches as a power of
|
|
+ // two.
|
|
+ const UInt dcache_line_size_power_of_two =
|
|
+ (cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;
|
|
+ const UInt icache_line_size_power_of_two =
|
|
+ (cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;
|
|
+
|
|
+ const UInt dcache_line_size_ = 1 << dcache_line_size_power_of_two;
|
|
+ const UInt icache_line_size_ = 1 << icache_line_size_power_of_two;
|
|
+
|
|
+ Addr start = (Addr)ptr;
|
|
+ // Sizes will be used to generate a mask big enough to cover a pointer.
|
|
+ Addr dsize = (Addr)dcache_line_size_;
|
|
+ Addr isize = (Addr)icache_line_size_;
|
|
+
|
|
+ // Cache line sizes are always a power of 2.
|
|
+ Addr dstart = start & ~(dsize - 1);
|
|
+ Addr istart = start & ~(isize - 1);
|
|
+ Addr end = start + nbytes;
|
|
+
|
|
+ __asm__ __volatile__ (
|
|
+ // Clean every line of the D cache containing the target data.
|
|
+ "0: \n\t"
|
|
+ // dc : Data Cache maintenance
|
|
+ // c : Clean
|
|
+ // va : by (Virtual) Address
|
|
+ // u : to the point of Unification
|
|
+ // The point of unification for a processor is the point by which the
|
|
+ // instruction and data caches are guaranteed to see the same copy of a
|
|
+ // memory location. See ARM DDI 0406B page B2-12 for more information.
|
|
+ "dc cvau, %[dline] \n\t"
|
|
+ "add %[dline], %[dline], %[dsize] \n\t"
|
|
+ "cmp %[dline], %[end] \n\t"
|
|
+ "b.lt 0b \n\t"
|
|
+ // Barrier to make sure the effect of the code above is visible to the rest
|
|
+ // of the world.
|
|
+ // dsb : Data Synchronisation Barrier
|
|
+ // ish : Inner SHareable domain
|
|
+ // The point of unification for an Inner Shareable shareability domain is
|
|
+ // the point by which the instruction and data caches of all the processors
|
|
+ // in that Inner Shareable shareability domain are guaranteed to see the
|
|
+ // same copy of a memory location. See ARM DDI 0406B page B2-12 for more
|
|
+ // information.
|
|
+ "dsb ish \n\t"
|
|
+ // Invalidate every line of the I cache containing the target data.
|
|
+ "1: \n\t"
|
|
+ // ic : instruction cache maintenance
|
|
+ // i : invalidate
|
|
+ // va : by address
|
|
+ // u : to the point of unification
|
|
+ "ic ivau, %[iline] \n\t"
|
|
+ "add %[iline], %[iline], %[isize] \n\t"
|
|
+ "cmp %[iline], %[end] \n\t"
|
|
+ "b.lt 1b \n\t"
|
|
+ // Barrier to make sure the effect of the code above is visible to the rest
|
|
+ // of the world.
|
|
+ "dsb ish \n\t"
|
|
+ // Barrier to ensure any prefetching which happened before this code is
|
|
+ // discarded.
|
|
+ // isb : Instruction Synchronisation Barrier
|
|
+ "isb \n\t"
|
|
+ : [dline] "+r" (dstart),
|
|
+ [iline] "+r" (istart)
|
|
+ : [dsize] "r" (dsize),
|
|
+ [isize] "r" (isize),
|
|
+ [end] "r" (end)
|
|
+ // This code does not write to memory but without the dependency gcc might
|
|
+ // move this code before the code is generated.
|
|
+ : "cc", "memory"
|
|
+ );
|
|
+
|
|
# elif defined(VGA_mips32) || defined(VGA_mips64)
|
|
SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr,
|
|
(UWord) nbytes, (UWord) 3);
|
|
Index: coregrind/m_cache.c
|
|
===================================================================
|
|
--- coregrind/m_cache.c.orig
|
|
+++ coregrind/m_cache.c
|
|
@@ -539,7 +539,7 @@ get_cache_info(VexArchInfo *vai)
|
|
}
|
|
|
|
#elif defined(VGA_arm) || defined(VGA_ppc32) || defined(VGA_ppc64) || \
|
|
- defined(VGA_mips32) || defined(VGA_mips64)
|
|
+ defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64)
|
|
|
|
static Bool
|
|
get_cache_info(VexArchInfo *vai)
|
|
Index: coregrind/m_redir.c
|
|
===================================================================
|
|
--- coregrind/m_redir.c.orig
|
|
+++ coregrind/m_redir.c
|
|
@@ -1318,7 +1318,27 @@ void VG_(redir_initialise) ( void )
|
|
complain_about_stripped_glibc_ldso
|
|
);
|
|
}
|
|
- /* nothing so far */
|
|
+
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ /* If we're using memcheck, use these intercepts right from
|
|
+ the start, otherwise ld.so makes a lot of noise. */
|
|
+ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
|
|
+ // add_hardwired_spec(
|
|
+ // "ld-linux.so.3", "strlen",
|
|
+ // (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
|
|
+ // complain_about_stripped_glibc_ldso
|
|
+ // );
|
|
+ // //add_hardwired_spec(
|
|
+ // // "ld-linux.so.3", "index",
|
|
+ // // (Addr)&VG_(arm_linux_REDIR_FOR_index),
|
|
+ // // NULL
|
|
+ // //);
|
|
+ // add_hardwired_spec(
|
|
+ // "ld-linux.so.3", "memcpy",
|
|
+ // (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
|
|
+ // complain_about_stripped_glibc_ldso
|
|
+ // );
|
|
+ }
|
|
|
|
# elif defined(VGP_x86_darwin)
|
|
/* If we're using memcheck, use these intercepts right from
|
|
Index: coregrind/m_libcfile.c
|
|
===================================================================
|
|
--- coregrind/m_libcfile.c.orig
|
|
+++ coregrind/m_libcfile.c
|
|
@@ -116,8 +116,12 @@ SysRes VG_(mknod) ( const HChar* pathnam
|
|
}
|
|
|
|
SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
|
|
-{
|
|
-# if defined(VGO_linux)
|
|
+{
|
|
+# if defined(VGP_arm64_linux)
|
|
+ /* ARM64 wants to use __NR_openat rather than __NR_open. */
|
|
+ SysRes res = VG_(do_syscall4)(__NR_openat,
|
|
+ VKI_AT_FDCWD, (UWord)pathname, flags, mode);
|
|
+# elif defined(VGO_linux)
|
|
SysRes res = VG_(do_syscall3)(__NR_open,
|
|
(UWord)pathname, flags, mode);
|
|
# elif defined(VGO_darwin)
|
|
@@ -204,6 +208,9 @@ Int VG_(pipe) ( Int fd[2] )
|
|
} else {
|
|
return -1;
|
|
}
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
|
|
+ return sr_isError(res) ? -1 : 0;
|
|
# elif defined(VGO_linux)
|
|
SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
|
|
return sr_isError(res) ? -1 : 0;
|
|
@@ -289,8 +296,14 @@ SysRes VG_(stat) ( const HChar* file_nam
|
|
}
|
|
}
|
|
# endif /* defined(__NR_stat64) */
|
|
+ /* This is the fallback ("vanilla version"). */
|
|
{ struct vki_stat buf;
|
|
+# if defined(VGP_arm64_linux)
|
|
+ res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
|
|
+ (UWord)file_name, (UWord)&buf);
|
|
+# else
|
|
res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
|
|
+# endif
|
|
if (!sr_isError(res))
|
|
TRANSLATE_TO_vg_stat(vgbuf, &buf);
|
|
return res;
|
|
@@ -385,7 +398,12 @@ Int VG_(rename) ( const HChar* old_name,
|
|
|
|
Int VG_(unlink) ( const HChar* file_name )
|
|
{
|
|
+# if defined(VGP_arm64_linux)
|
|
+ SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
|
|
+ (UWord)file_name);
|
|
+# else
|
|
SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
|
|
+# endif
|
|
return sr_isError(res) ? (-1) : 0;
|
|
}
|
|
|
|
@@ -474,7 +492,12 @@ Int VG_(readlink) (const HChar* path, HC
|
|
{
|
|
SysRes res;
|
|
/* res = readlink( path, buf, bufsiz ); */
|
|
+# if defined(VGP_arm64_linux)
|
|
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
|
|
+ (UWord)path, (UWord)buf, bufsiz);
|
|
+# else
|
|
res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
|
|
+# endif
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
}
|
|
|
|
@@ -509,7 +532,11 @@ Int VG_(access) ( const HChar* path, Boo
|
|
UWord w = (irusr ? VKI_R_OK : 0)
|
|
| (iwusr ? VKI_W_OK : 0)
|
|
| (ixusr ? VKI_X_OK : 0);
|
|
+# if defined(VGP_arm64_linux)
|
|
+ SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
|
|
+# else
|
|
SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
|
|
+# endif
|
|
return sr_isError(res) ? 1 : 0;
|
|
|
|
# if defined(VGO_linux)
|
|
@@ -624,7 +651,8 @@ SysRes VG_(pread) ( Int fd, void* buf, I
|
|
return res;
|
|
# elif defined(VGP_amd64_linux) \
|
|
|| defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
|
|
return res;
|
|
# elif defined(VGP_amd64_darwin)
|
|
@@ -877,7 +905,8 @@ Int VG_(socket) ( Int domain, Int type,
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
@@ -916,7 +945,8 @@ Int my_connect ( Int sockfd, struct vki_
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
@@ -955,7 +985,8 @@ Int VG_(write_socket)( Int sd, const voi
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
|
|
count, VKI_MSG_NOSIGNAL, 0,0);
|
|
@@ -985,7 +1016,7 @@ Int VG_(getsockname) ( Int sd, struct vk
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall3)( __NR_getsockname,
|
|
(UWord)sd, (UWord)name, (UWord)namelen );
|
|
@@ -1016,7 +1047,7 @@ Int VG_(getpeername) ( Int sd, struct vk
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall3)( __NR_getpeername,
|
|
(UWord)sd, (UWord)name, (UWord)namelen );
|
|
@@ -1049,7 +1080,8 @@ Int VG_(getsockopt) ( Int sd, Int level,
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall5)( __NR_getsockopt,
|
|
(UWord)sd, (UWord)level, (UWord)optname,
|
|
@@ -1085,7 +1117,8 @@ Int VG_(setsockopt) ( Int sd, Int level,
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
SysRes res;
|
|
res = VG_(do_syscall5)( __NR_setsockopt,
|
|
(UWord)sd, (UWord)level, (UWord)optname,
|
|
Index: coregrind/pub_core_aspacemgr.h
|
|
===================================================================
|
|
--- coregrind/pub_core_aspacemgr.h.orig
|
|
+++ coregrind/pub_core_aspacemgr.h
|
|
@@ -345,7 +345,8 @@ extern Bool VG_(am_relocate_nooverlap_cl
|
|
// protects such stacks.
|
|
|
|
#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
# define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages
|
|
# define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
|
|
#else
|
|
Index: coregrind/pub_core_machine.h
|
|
===================================================================
|
|
--- coregrind/pub_core_machine.h.orig
|
|
+++ coregrind/pub_core_machine.h
|
|
@@ -66,6 +66,11 @@
|
|
# define VG_ELF_MACHINE EM_ARM
|
|
# define VG_ELF_CLASS ELFCLASS32
|
|
# undef VG_PLAT_USES_PPCTOC
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define VG_ELF_DATA2XXX ELFDATA2LSB
|
|
+# define VG_ELF_MACHINE EM_AARCH64
|
|
+# define VG_ELF_CLASS ELFCLASS64
|
|
+# undef VG_PLAT_USES_PPCTOC
|
|
#elif defined(VGO_darwin)
|
|
# undef VG_ELF_DATA2XXX
|
|
# undef VG_ELF_MACHINE
|
|
@@ -122,6 +127,10 @@
|
|
# define VG_INSTR_PTR guest_R15T
|
|
# define VG_STACK_PTR guest_R13
|
|
# define VG_FRAME_PTR guest_R11
|
|
+#elif defined(VGA_arm64)
|
|
+# define VG_INSTR_PTR guest_PC
|
|
+# define VG_STACK_PTR guest_SP
|
|
+# define VG_FRAME_PTR guest_SP // FIXME: is this right?
|
|
#elif defined(VGA_s390x)
|
|
# define VG_INSTR_PTR guest_IA
|
|
# define VG_STACK_PTR guest_SP
|
|
Index: coregrind/pub_core_syscall.h
|
|
===================================================================
|
|
--- coregrind/pub_core_syscall.h.orig
|
|
+++ coregrind/pub_core_syscall.h
|
|
@@ -76,6 +76,7 @@ extern SysRes VG_(mk_SysRes_amd64_linux)
|
|
extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so );
|
|
extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so );
|
|
extern SysRes VG_(mk_SysRes_arm_linux) ( Int val );
|
|
+extern SysRes VG_(mk_SysRes_arm64_linux) ( Long val );
|
|
extern SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
|
|
UInt wHI, UInt wLO );
|
|
extern SysRes VG_(mk_SysRes_amd64_darwin)( UChar scclass, Bool isErr,
|
|
Index: coregrind/launcher-linux.c
|
|
===================================================================
|
|
--- coregrind/launcher-linux.c.orig
|
|
+++ coregrind/launcher-linux.c
|
|
@@ -57,6 +57,10 @@
|
|
#define EM_X86_64 62 // elf.h doesn't define this on some older systems
|
|
#endif
|
|
|
|
+#ifndef EM_AARCH64
|
|
+#define EM_AARCH64 183 // ditto
|
|
+#endif
|
|
+
|
|
/* Report fatal errors */
|
|
__attribute__((noreturn))
|
|
static void barf ( const char *format, ... )
|
|
@@ -220,6 +224,10 @@ static const char *select_platform(const
|
|
(ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
|
|
ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
|
|
platform = "mips64-linux";
|
|
+ } else if (ehdr->e_machine == EM_AARCH64 &&
|
|
+ (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
|
|
+ ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
|
|
+ platform = "arm64-linux";
|
|
}
|
|
} else if (header[EI_DATA] == ELFDATA2MSB) {
|
|
# if !defined(VGPV_arm_linux_android) \
|
|
@@ -309,12 +317,13 @@ int main(int argc, char** argv, char** e
|
|
target, because on most ppc64-linux setups, the basic /bin,
|
|
/usr/bin, etc, stuff is built in 32-bit mode, not 64-bit
|
|
mode. */
|
|
- if ((0==strcmp(VG_PLATFORM,"x86-linux")) ||
|
|
- (0==strcmp(VG_PLATFORM,"amd64-linux")) ||
|
|
- (0==strcmp(VG_PLATFORM,"ppc32-linux")) ||
|
|
- (0==strcmp(VG_PLATFORM,"ppc64-linux")) ||
|
|
- (0==strcmp(VG_PLATFORM,"arm-linux")) ||
|
|
- (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
|
|
+ if ((0==strcmp(VG_PLATFORM,"x86-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"amd64-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"ppc32-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"ppc64-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"arm-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"arm64-linux")) ||
|
|
+ (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
|
|
(0==strcmp(VG_PLATFORM,"mips32-linux")) ||
|
|
(0==strcmp(VG_PLATFORM,"mips64-linux")))
|
|
default_platform = VG_PLATFORM;
|
|
Index: coregrind/m_trampoline.S
|
|
===================================================================
|
|
--- coregrind/m_trampoline.S.orig
|
|
+++ coregrind/m_trampoline.S
|
|
@@ -519,9 +519,9 @@ VG_(trampoline_stuff_end):
|
|
# undef UD2_1024
|
|
# undef UD2_PAGE
|
|
|
|
-/*---------------- ppc32-linux ----------------*/
|
|
-
|
|
-#elif defined(VGP_arm_linux)
|
|
+/*---------------- arm-linux ----------------*/
|
|
+#else
|
|
+#if defined(VGP_arm_linux)
|
|
|
|
# define UD2_4 .word 0xFFFFFFFF
|
|
# define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
|
|
@@ -680,6 +680,45 @@ VG_(trampoline_stuff_end):
|
|
# undef UD2_1024
|
|
# undef UD2_PAGE
|
|
|
|
+/*---------------- arm64-linux ----------------*/
|
|
+#else
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+# define UD2_4 .word 0xFFFFFFFF
|
|
+# define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
|
|
+# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
|
|
+# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
|
|
+# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
|
|
+# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
|
|
+
|
|
+ /* a leading page of unexecutable code */
|
|
+ UD2_PAGE
|
|
+
|
|
+.global VG_(trampoline_stuff_start)
|
|
+VG_(trampoline_stuff_start):
|
|
+
|
|
+.global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
|
|
+.type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
|
|
+VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
|
|
+ mov x8, # __NR_rt_sigreturn
|
|
+ svc #0
|
|
+ .long 0xFFFFFFFF /*illegal insn*/
|
|
+.size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
|
|
+ .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
|
|
+
|
|
+.global VG_(trampoline_stuff_end)
|
|
+VG_(trampoline_stuff_end):
|
|
+
|
|
+ /* and a trailing page of unexecutable code */
|
|
+ UD2_PAGE
|
|
+
|
|
+# undef UD2_4
|
|
+# undef UD2_16
|
|
+# undef UD2_64
|
|
+# undef UD2_256
|
|
+# undef UD2_1024
|
|
+# undef UD2_PAGE
|
|
+
|
|
/*---------------- x86-darwin ----------------*/
|
|
#else
|
|
#if defined(VGP_x86_darwin)
|
|
@@ -1142,6 +1181,8 @@ VG_(trampoline_stuff_end):
|
|
#endif
|
|
#endif
|
|
#endif
|
|
+#endif
|
|
+#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
Index: coregrind/m_coredump/coredump-elf.c
|
|
===================================================================
|
|
--- coregrind/m_coredump/coredump-elf.c.orig
|
|
+++ coregrind/m_coredump/coredump-elf.c
|
|
@@ -233,7 +233,7 @@ static void fill_prpsinfo(const ThreadSt
|
|
}
|
|
|
|
static void fill_prstatus(const ThreadState *tst,
|
|
- struct vki_elf_prstatus *prs,
|
|
+ /*OUT*/struct vki_elf_prstatus *prs,
|
|
const vki_siginfo_t *si)
|
|
{
|
|
struct vki_user_regs_struct *regs;
|
|
@@ -252,12 +252,11 @@ static void fill_prstatus(const ThreadSt
|
|
prs->pr_pgrp = VG_(getpgrp)();
|
|
prs->pr_sid = VG_(getpgrp)();
|
|
|
|
-#ifdef VGP_s390x_linux
|
|
+#if defined(VGP_s390x_linux)
|
|
/* prs->pr_reg has struct type. Need to take address. */
|
|
regs = (struct vki_user_regs_struct *)&(prs->pr_reg);
|
|
#else
|
|
regs = (struct vki_user_regs_struct *)prs->pr_reg;
|
|
-
|
|
vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
|
|
#endif
|
|
|
|
@@ -302,10 +301,6 @@ static void fill_prstatus(const ThreadSt
|
|
regs->r14 = arch->vex.guest_R14;
|
|
regs->r15 = arch->vex.guest_R15;
|
|
|
|
-//:: regs->cs = arch->vex.guest_CS;
|
|
-//:: regs->fs = arch->vex.guest_FS;
|
|
-//:: regs->gs = arch->vex.guest_GS;
|
|
-
|
|
#elif defined(VGP_ppc32_linux)
|
|
# define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n
|
|
DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
|
|
@@ -367,6 +362,10 @@ static void fill_prstatus(const ThreadSt
|
|
regs->ARM_pc = arch->vex.guest_R15T;
|
|
regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &arch->vex );
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ (void)arch;
|
|
+ I_die_here;
|
|
+
|
|
#elif defined(VGP_s390x_linux)
|
|
# define DO(n) regs->gprs[n] = arch->vex.guest_r##n
|
|
DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
|
|
@@ -377,6 +376,7 @@ static void fill_prstatus(const ThreadSt
|
|
DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
|
|
# undef DO
|
|
regs->orig_gpr2 = arch->vex.guest_r2;
|
|
+
|
|
#elif defined(VGP_mips32_linux)
|
|
# define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n
|
|
DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
|
|
@@ -386,6 +386,7 @@ static void fill_prstatus(const ThreadSt
|
|
# undef DO
|
|
regs->MIPS_hi = arch->vex.guest_HI;
|
|
regs->MIPS_lo = arch->vex.guest_LO;
|
|
+
|
|
#elif defined(VGP_mips64_linux)
|
|
# define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n
|
|
DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
|
|
@@ -395,6 +396,7 @@ static void fill_prstatus(const ThreadSt
|
|
# undef DO
|
|
regs->MIPS_hi = arch->vex.guest_HI;
|
|
regs->MIPS_lo = arch->vex.guest_LO;
|
|
+
|
|
#else
|
|
# error Unknown ELF platform
|
|
#endif
|
|
@@ -470,6 +472,9 @@ static void fill_fpu(const ThreadState *
|
|
#elif defined(VGP_arm_linux)
|
|
// umm ...
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
+
|
|
#elif defined(VGP_s390x_linux)
|
|
# define DO(n) fpu->fprs[n].ui = arch->vex.guest_f##n
|
|
DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
|
|
@@ -606,16 +611,13 @@ void make_elf_coredump(ThreadId tid, con
|
|
if (VG_(threads)[i].status == VgTs_Empty)
|
|
continue;
|
|
|
|
-# if defined(VGP_x86_linux)
|
|
-# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
|
|
- && !defined(VGPV_mips32_linux_android)
|
|
+# if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android)
|
|
{
|
|
vki_elf_fpxregset_t xfpu;
|
|
fill_xfpu(&VG_(threads)[i], &xfpu);
|
|
add_note(¬elist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu));
|
|
}
|
|
# endif
|
|
-# endif
|
|
|
|
fill_fpu(&VG_(threads)[i], &fpu);
|
|
# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \
|
|
Index: coregrind/m_machine.c
|
|
===================================================================
|
|
--- coregrind/m_machine.c.orig
|
|
+++ coregrind/m_machine.c
|
|
@@ -97,6 +97,11 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/U
|
|
= VG_(threads)[tid].arch.vex.guest_R11;
|
|
regs->misc.ARM.r7
|
|
= VG_(threads)[tid].arch.vex.guest_R7;
|
|
+# elif defined(VGA_arm64)
|
|
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
|
|
+ regs->r_sp = VG_(threads)[tid].arch.vex.guest_SP;
|
|
+ regs->misc.ARM64.x29 = VG_(threads)[tid].arch.vex.guest_X29;
|
|
+ regs->misc.ARM64.x30 = VG_(threads)[tid].arch.vex.guest_X30;
|
|
# elif defined(VGA_s390x)
|
|
regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
|
|
regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
|
|
@@ -127,38 +132,6 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/U
|
|
# endif
|
|
}
|
|
|
|
-
|
|
-void VG_(set_syscall_return_shadows) ( ThreadId tid,
|
|
- /* shadow vals for the result */
|
|
- UWord s1res, UWord s2res,
|
|
- /* shadow vals for the error val */
|
|
- UWord s1err, UWord s2err )
|
|
-{
|
|
-# if defined(VGP_x86_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
|
|
-# elif defined(VGP_amd64_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
|
|
-# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
|
|
-# elif defined(VGP_arm_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res;
|
|
-# elif defined(VGO_darwin)
|
|
- // GrP fixme darwin syscalls may return more values (2 registers plus error)
|
|
-# elif defined(VGP_s390x_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
|
|
-# elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
- VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
|
|
- VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
|
|
-# else
|
|
-# error "Unknown plat"
|
|
-# endif
|
|
-}
|
|
-
|
|
void
|
|
VG_(get_shadow_regs_area) ( ThreadId tid,
|
|
/*DST*/UChar* dst,
|
|
@@ -339,6 +312,9 @@ static void apply_to_GPs_of_tid(ThreadId
|
|
(*f)(tid, "r29", vex->guest_r29);
|
|
(*f)(tid, "r30", vex->guest_r30);
|
|
(*f)(tid, "r31", vex->guest_r31);
|
|
+#elif defined(VGA_arm64)
|
|
+ (void)vex; /* temporarily avoid unused-var warning from gcc */
|
|
+ I_die_here;
|
|
#else
|
|
# error Unknown arch
|
|
#endif
|
|
@@ -1193,7 +1169,7 @@ Bool VG_(machine_get_hwcaps)( void )
|
|
|
|
#elif defined(VGA_s390x)
|
|
|
|
-#include "libvex_s390x_common.h"
|
|
+# include "libvex_s390x_common.h"
|
|
|
|
{
|
|
/* Instruction set detection code borrowed from ppc above. */
|
|
@@ -1440,6 +1416,18 @@ Bool VG_(machine_get_hwcaps)( void )
|
|
return True;
|
|
}
|
|
|
|
+#elif defined(VGA_arm64)
|
|
+ {
|
|
+ va = VexArchARM64;
|
|
+
|
|
+ /* So far there are no variants. */
|
|
+ vai.hwcaps = 0;
|
|
+
|
|
+ VG_(machine_get_cache_info)(&vai);
|
|
+
|
|
+ return True;
|
|
+ }
|
|
+
|
|
#elif defined(VGA_mips32)
|
|
{
|
|
va = VexArchMIPS32;
|
|
@@ -1649,6 +1637,10 @@ Int VG_(machine_get_size_of_largest_gues
|
|
assume we always do. */
|
|
return 16;
|
|
|
|
+# elif defined(VGA_arm64)
|
|
+ /* ARM64 always has Neon, AFAICS. */
|
|
+ return 16;
|
|
+
|
|
# elif defined(VGA_mips32)
|
|
/* The guest state implies 4, but that can't really be true, can
|
|
it? */
|
|
@@ -1671,7 +1663,7 @@ void* VG_(fnptr_to_fnentry)( void* f )
|
|
|| defined(VGP_arm_linux) \
|
|
|| defined(VGP_ppc32_linux) || defined(VGO_darwin) \
|
|
|| defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
return f;
|
|
# elif defined(VGP_ppc64_linux)
|
|
/* ppc64-linux uses the AIX scheme, in which f is a pointer to a
|
|
Index: coregrind/m_syscall.c
|
|
===================================================================
|
|
--- coregrind/m_syscall.c.orig
|
|
+++ coregrind/m_syscall.c
|
|
@@ -128,6 +128,18 @@ SysRes VG_(mk_SysRes_arm_linux) ( Int va
|
|
return res;
|
|
}
|
|
|
|
+SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
|
|
+ SysRes res;
|
|
+ res._valEx = 0; /* unused except on mips-linux */
|
|
+ res._isError = val >= -4095 && val <= -1;
|
|
+ if (res._isError) {
|
|
+ res._val = (ULong)(-val);
|
|
+ } else {
|
|
+ res._val = (ULong)val;
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
/* MIPS uses a3 != 0 to flag an error */
|
|
SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
|
|
SysRes res;
|
|
@@ -437,6 +449,34 @@ asm(
|
|
".previous\n"
|
|
);
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+/* I think the conventions are:
|
|
+ args in r0 r1 r2 r3 r4 r5
|
|
+ sysno in r8
|
|
+ return value in r0, w/ same conventions as x86-linux, viz r0 in
|
|
+ -4096 .. -1 is an error value. All other values are success
|
|
+ values.
|
|
+
|
|
+ r0 to r5 remain unchanged, but syscall_no is in r6 and needs
|
|
+ to be moved to r8 (??)
|
|
+*/
|
|
+extern UWord do_syscall_WRK (
|
|
+ UWord a1, UWord a2, UWord a3,
|
|
+ UWord a4, UWord a5, UWord a6,
|
|
+ UWord syscall_no
|
|
+ );
|
|
+asm(
|
|
+".text\n"
|
|
+".globl do_syscall_WRK\n"
|
|
+"do_syscall_WRK:\n"
|
|
+" mov x8, x6\n"
|
|
+" mov x6, 0\n"
|
|
+" mov x7, 0\n"
|
|
+" svc 0\n"
|
|
+" ret\n"
|
|
+".previous\n"
|
|
+);
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
|
|
/* Incoming args (syscall number + up to 8 args) come in on the stack
|
|
@@ -696,6 +736,10 @@ SysRes VG_(do_syscall) ( UWord sysno, UW
|
|
UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
|
|
return VG_(mk_SysRes_arm_linux)( val );
|
|
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
|
|
+ return VG_(mk_SysRes_arm64_linux)( val );
|
|
+
|
|
# elif defined(VGP_x86_darwin)
|
|
UInt wLO = 0, wHI = 0, err = 0;
|
|
ULong u64;
|
|
Index: coregrind/pub_core_mallocfree.h
|
|
===================================================================
|
|
--- coregrind/pub_core_mallocfree.h.orig
|
|
+++ coregrind/pub_core_mallocfree.h
|
|
@@ -77,7 +77,8 @@ typedef Int ArenaId;
|
|
defined(VGP_s390x_linux) || \
|
|
defined(VGP_mips64_linux) || \
|
|
defined(VGP_x86_darwin) || \
|
|
- defined(VGP_amd64_darwin)
|
|
+ defined(VGP_amd64_darwin) || \
|
|
+ defined(VGP_arm64_linux)
|
|
# define VG_MIN_MALLOC_SZB 16
|
|
#else
|
|
# error Unknown platform
|
|
Index: coregrind/m_debuginfo/readelf.c
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/readelf.c.orig
|
|
+++ coregrind/m_debuginfo/readelf.c
|
|
@@ -2088,7 +2088,8 @@ Bool ML_(read_elf_debug_info) ( struct _
|
|
/* PLT is different on different platforms, it seems. */
|
|
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|
|
|| defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
|
|
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
/* Accept .plt where mapped as rx (code) */
|
|
if (0 == VG_(strcmp)(name, ".plt")) {
|
|
if (inrx && !di->plt_present) {
|
|
Index: coregrind/m_debuginfo/debuginfo.c
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/debuginfo.c.orig
|
|
+++ coregrind/m_debuginfo/debuginfo.c
|
|
@@ -825,7 +825,8 @@ ULong VG_(di_notify_mmap)( Addr a, Bool
|
|
|| defined(VGA_mips64)
|
|
is_rx_map = seg->hasR && seg->hasX;
|
|
is_rw_map = seg->hasR && seg->hasW;
|
|
-# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
|
|
+# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) \
|
|
+ || defined(VGA_arm64)
|
|
is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
|
|
is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
|
|
# elif defined(VGP_s390x_linux)
|
|
@@ -2251,6 +2252,8 @@ UWord evalCfiExpr ( XArray* exprs, Int i
|
|
case Creg_IA_BP: return eec->uregs->fp;
|
|
case Creg_MIPS_RA: return eec->uregs->ra;
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unsupported arch"
|
|
# endif
|
|
@@ -2495,6 +2498,8 @@ static Addr compute_cfa ( D3UnwindRegs*
|
|
cfa = cfsi->cfa_off + uregs->fp;
|
|
break;
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unsupported arch"
|
|
# endif
|
|
@@ -2591,6 +2596,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR
|
|
# elif defined(VGA_mips32) || defined(VGA_mips64)
|
|
ipHere = uregsHere->pc;
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unknown arch"
|
|
# endif
|
|
@@ -2671,6 +2678,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR
|
|
COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
|
|
COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unknown arch"
|
|
# endif
|
|
Index: coregrind/m_debuginfo/storage.c
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/storage.c.orig
|
|
+++ coregrind/m_debuginfo/storage.c
|
|
@@ -195,6 +195,8 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiEx
|
|
SHOW_HOW(si->sp_how, si->sp_off);
|
|
VG_(printf)(" FP=");
|
|
SHOW_HOW(si->fp_how, si->fp_off);
|
|
+# elif defined(VGA_arm64)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unknown arch"
|
|
# endif
|
|
Index: coregrind/m_debuginfo/priv_storage.h
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/priv_storage.h.orig
|
|
+++ coregrind/m_debuginfo/priv_storage.h
|
|
@@ -277,6 +277,18 @@ typedef
|
|
Int fp_off;
|
|
}
|
|
DiCfSI;
|
|
+#elif defined(VGA_arm64)
|
|
+/* Be generic until we know more about what's needed. */
|
|
+typedef
|
|
+ struct {
|
|
+ Addr base;
|
|
+ UInt len;
|
|
+ UChar cfa_how; /* a CFIC_ value */
|
|
+ UChar ra_how; /* a CFIR_ value */
|
|
+ Int cfa_off;
|
|
+ Int ra_off;
|
|
+ }
|
|
+ DiCfSI;
|
|
#else
|
|
# error "Unknown arch"
|
|
#endif
|
|
Index: coregrind/m_debuginfo/d3basics.c
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/d3basics.c.orig
|
|
+++ coregrind/m_debuginfo/d3basics.c
|
|
@@ -420,6 +420,8 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr*
|
|
# elif defined(VGP_mips64_linux)
|
|
if (regno == 29) { *a = regs->sp; return True; }
|
|
if (regno == 30) { *a = regs->fp; return True; }
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
# else
|
|
# error "Unknown platform"
|
|
# endif
|
|
Index: coregrind/m_debuginfo/readdwarf.c
|
|
===================================================================
|
|
--- coregrind/m_debuginfo/readdwarf.c.orig
|
|
+++ coregrind/m_debuginfo/readdwarf.c
|
|
@@ -1841,6 +1841,10 @@ void ML_(read_debuginfo_dwarf1) (
|
|
# define FP_REG 12
|
|
# define SP_REG 13
|
|
# define RA_REG_DEFAULT 14 //???
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define FP_REG 29 //???
|
|
+# define SP_REG 31 //???
|
|
+# define RA_REG_DEFAULT 30 //???
|
|
#elif defined(VGP_x86_darwin)
|
|
# define FP_REG 5
|
|
# define SP_REG 4
|
|
@@ -2179,6 +2183,8 @@ static Bool summarise_context( /*OUT*/Di
|
|
si->cfa_how = CFIC_IA_SPREL;
|
|
# elif defined(VGA_arm)
|
|
si->cfa_how = CFIC_ARM_R13REL;
|
|
+# elif defined(VGA_arm64)
|
|
+ I_die_here;
|
|
# else
|
|
si->cfa_how = 0; /* invalid */
|
|
# endif
|
|
@@ -2206,6 +2212,8 @@ static Bool summarise_context( /*OUT*/Di
|
|
si->cfa_how = CFIC_ARM_R7REL;
|
|
si->cfa_off = ctxs->cfa_off;
|
|
}
|
|
+# elif defined(VGA_arm64)
|
|
+ if (1) { I_die_here; } // do we need any arm64 specifics here?
|
|
# endif
|
|
else {
|
|
why = 1;
|
|
@@ -2249,6 +2257,7 @@ static Bool summarise_context( /*OUT*/Di
|
|
why = 2; goto failed; /* otherwise give up */ \
|
|
}
|
|
|
|
+
|
|
# if defined(VGA_x86) || defined(VGA_amd64)
|
|
|
|
/* --- entire tail of this fn specialised for x86/amd64 --- */
|
|
@@ -2339,9 +2348,10 @@ static Bool summarise_context( /*OUT*/Di
|
|
|
|
return True;
|
|
|
|
-
|
|
# elif defined(VGA_s390x)
|
|
|
|
+ /* --- entire tail of this fn specialised for s390 --- */
|
|
+
|
|
SUMMARISE_HOW(si->ra_how, si->ra_off,
|
|
ctxs->reg[ctx->ra_reg] );
|
|
SUMMARISE_HOW(si->fp_how, si->fp_off,
|
|
@@ -2387,7 +2397,6 @@ static Bool summarise_context( /*OUT*/Di
|
|
|
|
return True;
|
|
|
|
-
|
|
# elif defined(VGA_mips32) || defined(VGA_mips64)
|
|
|
|
/* --- entire tail of this fn specialised for mips --- */
|
|
@@ -2431,9 +2440,12 @@ static Bool summarise_context( /*OUT*/Di
|
|
|
|
return True;
|
|
|
|
-
|
|
+# elif defined(VGA_arm64)
|
|
+ I_die_here;
|
|
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+ /* These don't use CFI based unwinding (is that really true?) */
|
|
+
|
|
# else
|
|
# error "Unknown arch"
|
|
# endif
|
|
@@ -2521,6 +2533,8 @@ static Int copy_convert_CfiExpr_tree ( X
|
|
return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
|
|
if (dwreg == srcuc->ra_reg)
|
|
return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
|
|
+# elif defined(VGA_arm64)
|
|
+ I_die_here;
|
|
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
# else
|
|
# error "Unknown arch"
|
|
Index: coregrind/m_stacktrace.c
|
|
===================================================================
|
|
--- coregrind/m_stacktrace.c.orig
|
|
+++ coregrind/m_stacktrace.c
|
|
@@ -1034,6 +1034,24 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId
|
|
|
|
#endif
|
|
|
|
+/* ------------------------ arm64 ------------------------- */
|
|
+
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
+ /*OUT*/Addr* ips, UInt max_n_ips,
|
|
+ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
|
|
+ UnwindStartRegs* startRegs,
|
|
+ Addr fp_max_orig )
|
|
+{
|
|
+ ips[0] = startRegs->r_pc;
|
|
+ if (sps) sps[0] = startRegs->r_sp;
|
|
+ if (fps) fps[0] = startRegs->misc.ARM64.x29;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
/* ------------------------ s390x ------------------------- */
|
|
|
|
#if defined(VGP_s390x_linux)
|
|
Index: coregrind/m_signals.c
|
|
===================================================================
|
|
--- coregrind/m_signals.c.orig
|
|
+++ coregrind/m_signals.c
|
|
@@ -386,6 +386,19 @@ typedef struct SigQueue {
|
|
(srP)->misc.ARM.r7 = (uc)->uc_mcontext.arm_r7; \
|
|
}
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)((uc)->uc_mcontext.pc))
|
|
+# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)((uc)->uc_mcontext.sp))
|
|
+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
|
|
+ /* Convert the value in uc_mcontext.regs[0] into a SysRes. */ \
|
|
+ VG_(mk_SysRes_arm64_linux)( (uc)->uc_mcontext.regs[0] )
|
|
+# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
|
|
+ { (srP)->r_pc = (uc)->uc_mcontext.pc; \
|
|
+ (srP)->r_sp = (uc)->uc_mcontext.sp; \
|
|
+ (srP)->misc.ARM64.x29 = (uc)->uc_mcontext.regs[29]; \
|
|
+ (srP)->misc.ARM64.x30 = (uc)->uc_mcontext.regs[30]; \
|
|
+ }
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
|
|
static inline Addr VG_UCONTEXT_INSTR_PTR( void* ucV ) {
|
|
@@ -862,6 +875,15 @@ extern void my_sigreturn(void);
|
|
" svc 0x00000000\n" \
|
|
".previous\n"
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define _MY_SIGRETURN(name) \
|
|
+ ".text\n" \
|
|
+ ".globl my_sigreturn\n" \
|
|
+ "my_sigreturn:\n\t" \
|
|
+ " mov x8, #" #name "\n\t" \
|
|
+ " svc 0x0\n" \
|
|
+ ".previous\n"
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
# define _MY_SIGRETURN(name) \
|
|
".text\n" \
|
|
@@ -980,8 +1002,7 @@ static void handle_SCSS_change ( Bool fo
|
|
# if !defined(VGP_ppc32_linux) && \
|
|
!defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
|
|
!defined(VGP_mips32_linux) && !defined(VGP_mips64_linux)
|
|
- vg_assert(ksa_old.sa_restorer
|
|
- == my_sigreturn);
|
|
+ vg_assert(ksa_old.sa_restorer == my_sigreturn);
|
|
# endif
|
|
VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
|
|
VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP );
|
|
Index: coregrind/pub_core_threadstate.h
|
|
===================================================================
|
|
--- coregrind/pub_core_threadstate.h.orig
|
|
+++ coregrind/pub_core_threadstate.h
|
|
@@ -88,6 +88,8 @@ typedef
|
|
typedef VexGuestPPC64State VexGuestArchState;
|
|
#elif defined(VGA_arm)
|
|
typedef VexGuestARMState VexGuestArchState;
|
|
+#elif defined(VGA_arm64)
|
|
+ typedef VexGuestARM64State VexGuestArchState;
|
|
#elif defined(VGA_s390x)
|
|
typedef VexGuestS390XState VexGuestArchState;
|
|
#elif defined(VGA_mips32)
|
|
Index: coregrind/m_aspacemgr/aspacemgr-common.c
|
|
===================================================================
|
|
--- coregrind/m_aspacemgr/aspacemgr-common.c.orig
|
|
+++ coregrind/m_aspacemgr/aspacemgr-common.c
|
|
@@ -152,15 +152,19 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr s
|
|
{
|
|
SysRes res;
|
|
aspacem_assert(VG_IS_PAGE_ALIGNED(offset));
|
|
-# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
|
|
- || defined(VGP_arm_linux)
|
|
+
|
|
+# if defined(VGP_arm64_linux)
|
|
+ res = VG_(do_syscall6)(__NR3264_mmap, (UWord)start, length,
|
|
+ prot, flags, fd, offset);
|
|
+# elif defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
|
|
+ || defined(VGP_arm_linux)
|
|
/* mmap2 uses 4096 chunks even if actual page size is bigger. */
|
|
aspacem_assert((offset % 4096) == 0);
|
|
res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length,
|
|
prot, flags, fd, offset / 4096);
|
|
# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
|
|
|| defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
|
|
prot, flags, fd, offset);
|
|
# elif defined(VGP_x86_darwin)
|
|
@@ -242,8 +246,14 @@ SysRes ML_(am_do_relocate_nooverlap_mapp
|
|
/* --- Pertaining to files --- */
|
|
|
|
SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode )
|
|
-{
|
|
+{
|
|
+# if defined(VGP_arm64_linux)
|
|
+ /* ARM64 wants to use __NR_openat rather than __NR_open. */
|
|
+ SysRes res = VG_(do_syscall4)(__NR_openat,
|
|
+ VKI_AT_FDCWD, (UWord)pathname, flags, mode);
|
|
+# else
|
|
SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
|
|
+# endif
|
|
return res;
|
|
}
|
|
|
|
@@ -261,7 +271,12 @@ void ML_(am_close) ( Int fd )
|
|
Int ML_(am_readlink)(HChar* path, HChar* buf, UInt bufsiz)
|
|
{
|
|
SysRes res;
|
|
+# if defined(VGP_arm64_linux)
|
|
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
|
|
+ (UWord)path, (UWord)buf, bufsiz);
|
|
+# else
|
|
res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
|
|
+# endif
|
|
return sr_isError(res) ? -1 : sr_Res(res);
|
|
}
|
|
|
|
Index: coregrind/pub_core_trampoline.h
|
|
===================================================================
|
|
--- coregrind/pub_core_trampoline.h.orig
|
|
+++ coregrind/pub_core_trampoline.h
|
|
@@ -103,6 +103,10 @@ extern UInt VG_(arm_linux_REDIR_FOR_str
|
|
extern void* VG_(arm_linux_REDIR_FOR_memcpy)( void*, void*, Int );
|
|
#endif
|
|
|
|
+#if defined(VGP_arm64_linux)
|
|
+extern Addr VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
|
|
+#endif
|
|
+
|
|
#if defined(VGP_x86_darwin)
|
|
extern Addr VG_(x86_darwin_SUBST_FOR_sigreturn);
|
|
extern SizeT VG_(x86_darwin_REDIR_FOR_strlen)( void* );
|
|
Index: coregrind/m_debugger.c
|
|
===================================================================
|
|
--- coregrind/m_debugger.c.orig
|
|
+++ coregrind/m_debugger.c
|
|
@@ -232,6 +232,47 @@ static Int ptrace_setregs(Int pid, VexGu
|
|
uregs.ARM_cpsr = LibVEX_GuestARM_get_cpsr(vex);
|
|
return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &uregs);
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ I_die_here;
|
|
+ //ATC
|
|
+ struct vki_user_pt_regs uregs;
|
|
+ VG_(memset)(&uregs, 0, sizeof(uregs));
|
|
+ uregs.regs[0] = vex->guest_X0;
|
|
+ uregs.regs[1] = vex->guest_X1;
|
|
+ uregs.regs[2] = vex->guest_X2;
|
|
+ uregs.regs[3] = vex->guest_X3;
|
|
+ uregs.regs[4] = vex->guest_X4;
|
|
+ uregs.regs[5] = vex->guest_X5;
|
|
+ uregs.regs[6] = vex->guest_X6;
|
|
+ uregs.regs[7] = vex->guest_X7;
|
|
+ uregs.regs[8] = vex->guest_X8;
|
|
+ uregs.regs[9] = vex->guest_X9;
|
|
+ uregs.regs[10] = vex->guest_X10;
|
|
+ uregs.regs[11] = vex->guest_X11;
|
|
+ uregs.regs[12] = vex->guest_X12;
|
|
+ uregs.regs[13] = vex->guest_X13;
|
|
+ uregs.regs[14] = vex->guest_X14;
|
|
+ uregs.regs[15] = vex->guest_X15;
|
|
+ uregs.regs[16] = vex->guest_X16;
|
|
+ uregs.regs[17] = vex->guest_X17;
|
|
+ uregs.regs[18] = vex->guest_X18;
|
|
+ uregs.regs[19] = vex->guest_X19;
|
|
+ uregs.regs[20] = vex->guest_X20;
|
|
+ uregs.regs[21] = vex->guest_X21;
|
|
+ uregs.regs[22] = vex->guest_X22;
|
|
+ uregs.regs[23] = vex->guest_X23;
|
|
+ uregs.regs[24] = vex->guest_X24;
|
|
+ uregs.regs[25] = vex->guest_X25;
|
|
+ uregs.regs[26] = vex->guest_X26;
|
|
+ uregs.regs[27] = vex->guest_X27;
|
|
+ uregs.regs[28] = vex->guest_X28;
|
|
+ uregs.regs[29] = vex->guest_X29;
|
|
+ uregs.regs[30] = vex->guest_X30;
|
|
+ uregs.sp = vex->guest_SP;
|
|
+ uregs.pc = vex->guest_PC;
|
|
+ uregs.pstate = LibVEX_GuestARM64_get_nzcv(vex); /* is this correct? */
|
|
+ return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &uregs);
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
I_die_here;
|
|
|
|
Index: coregrind/pub_core_transtab_asm.h
|
|
===================================================================
|
|
--- coregrind/pub_core_transtab_asm.h.orig
|
|
+++ coregrind/pub_core_transtab_asm.h
|
|
@@ -37,10 +37,10 @@
|
|
On x86/amd64, the cache index is computed as
|
|
'address[VG_TT_FAST_BITS-1 : 0]'.
|
|
|
|
- On ppc32/ppc64, the bottom two bits of instruction addresses are
|
|
- zero, which means that function causes only 1/4 of the entries to
|
|
- ever be used. So instead the function is '(address >>u
|
|
- 2)[VG_TT_FAST_BITS-1 : 0]' on those targets.
|
|
+ On ppc32/ppc64/mips32/mips64/arm64, the bottom two bits of
|
|
+ instruction addresses are zero, which means that function causes
|
|
+ only 1/4 of the entries to ever be used. So instead the function
|
|
+ is '(address >>u 2)[VG_TT_FAST_BITS-1 : 0]' on those targets.
|
|
|
|
On ARM we shift by 1, since Thumb insns can be of size 2, hence to
|
|
minimise collisions and maximise cache utilisation we need to take
|
|
@@ -63,7 +63,7 @@
|
|
# define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 1) & VG_TT_FAST_MASK)
|
|
|
|
#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32) \
|
|
- || defined(VGA_mips64)
|
|
+ || defined(VGA_mips64) || defined(VGA_arm64)
|
|
# define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 2) & VG_TT_FAST_MASK)
|
|
|
|
#else
|
|
Index: coregrind/m_syswrap/syscall-arm64-linux.S
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ coregrind/m_syswrap/syscall-arm64-linux.S
|
|
@@ -0,0 +1,180 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- Support for doing system calls. syscall-arm64-linux.S ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+#include "pub_core_basics_asm.h"
|
|
+#include "pub_core_vkiscnums_asm.h"
|
|
+#include "libvex_guest_offsets.h"
|
|
+
|
|
+
|
|
+/*----------------------------------------------------------------*/
|
|
+/*
|
|
+ Perform a syscall for the client. This will run a syscall
|
|
+ with the client's specific per-thread signal mask.
|
|
+
|
|
+ The structure of this function is such that, if the syscall is
|
|
+ interrupted by a signal, we can determine exactly what
|
|
+ execution state we were in with respect to the execution of
|
|
+ the syscall by examining the value of IP in the signal
|
|
+ handler. This means that we can always do the appropriate
|
|
+ thing to precisely emulate the kernel's signal/syscall
|
|
+ interactions.
|
|
+
|
|
+ The syscall number is taken from the argument, even though it
|
|
+ should also be in guest_state->guest_X8. The syscall result
|
|
+ is written back to guest_state->guest_X0 on completion.
|
|
+
|
|
+ Returns 0 if the syscall was successfully called (even if the
|
|
+ syscall itself failed), or a nonzero error code in the lowest
|
|
+ 8 bits if one of the sigprocmasks failed (there's no way to
|
|
+ determine which one failed). And there's no obvious way to
|
|
+ recover from that either, but nevertheless we want to know.
|
|
+
|
|
+ VG_(fixup_guest_state_after_syscall_interrupted) does the
|
|
+ thread state fixup in the case where we were interrupted by a
|
|
+ signal.
|
|
+
|
|
+ Prototype:
|
|
+
|
|
+ UWord ML_(do_syscall_for_client_WRK)(
|
|
+ Int syscallno, // x0
|
|
+ void* guest_state, // x1
|
|
+ const vki_sigset_t *sysmask, // x2
|
|
+ const vki_sigset_t *postmask, // x3
|
|
+ Int nsigwords) // x4
|
|
+*/
|
|
+/* from vki-arm64-linux.h */
|
|
+#define VKI_SIG_SETMASK 2
|
|
+
|
|
+.globl ML_(do_syscall_for_client_WRK)
|
|
+ML_(do_syscall_for_client_WRK):
|
|
+
|
|
+ /* Stash callee-saves and our args on the stack */
|
|
+ stp x29, x30, [sp, #-16]!
|
|
+ stp x27, x28, [sp, #-16]!
|
|
+ stp x25, x26, [sp, #-16]!
|
|
+ stp x23, x24, [sp, #-16]!
|
|
+ stp x21, x22, [sp, #-16]!
|
|
+ stp x19, x20, [sp, #-16]!
|
|
+ stp x4, x5, [sp, #-16]!
|
|
+ stp x2, x3, [sp, #-16]!
|
|
+ stp x0, x1, [sp, #-16]!
|
|
+
|
|
+1:
|
|
+
|
|
+ mov x8, #__NR_rt_sigprocmask
|
|
+ mov x0, #VKI_SIG_SETMASK
|
|
+ mov x1, x2 /* sysmask */
|
|
+ mov x2, x3 /* postmask */
|
|
+ mov x3, x4 /* nsigwords */
|
|
+ svc 0x00000000
|
|
+
|
|
+
|
|
+ ldr x5, [sp, #8] /* saved x1 == guest_state */
|
|
+
|
|
+ ldr x8, [sp, #0] /* saved x0 == syscall# */
|
|
+ ldr x0, [x5, #OFFSET_arm64_X0]
|
|
+ ldr x1, [x5, #OFFSET_arm64_X1]
|
|
+ ldr x2, [x5, #OFFSET_arm64_X2]
|
|
+ ldr x3, [x5, #OFFSET_arm64_X3]
|
|
+ ldr x4, [x5, #OFFSET_arm64_X4]
|
|
+ ldr x5, [x5, #OFFSET_arm64_X5]
|
|
+
|
|
+2: svc 0x00000000
|
|
+3:
|
|
+ ldr x5, [sp, #8] /* saved x1 == guest_state */
|
|
+ str x0, [x5, #OFFSET_arm64_X0]
|
|
+
|
|
+4:
|
|
+ mov x8, #__NR_rt_sigprocmask
|
|
+ mov x0, #VKI_SIG_SETMASK
|
|
+ ldr x1, [sp, #24] /* saved x3 == postmask */
|
|
+ mov x2, #0
|
|
+ ldr x3, [sp, #32] /* saved x4 == nsigwords */
|
|
+ svc 0x00000000
|
|
+
|
|
+ cmp x0, #0
|
|
+ blt 7f
|
|
+
|
|
+5: /* Success: return zero */
|
|
+ mov x0, #0
|
|
+ ldp xzr, x1, [sp], #16
|
|
+ ldp x2, x3, [sp], #16
|
|
+ ldp x4, x5, [sp], #16
|
|
+ ldp x19, x20, [sp], #16
|
|
+ ldp x21, x22, [sp], #16
|
|
+ ldp x23, x24, [sp], #16
|
|
+ ldp x25, x26, [sp], #16
|
|
+ ldp x27, x28, [sp], #16
|
|
+ ldp x29, x30, [sp], #16
|
|
+ ret
|
|
+
|
|
+7: /* Failure: return 0x8000 | error code */
|
|
+ orr x0, x0, #0x8000
|
|
+ ldp xzr, x1, [sp], #16
|
|
+ ldp x2, x3, [sp], #16
|
|
+ ldp x4, x5, [sp], #16
|
|
+ ldp x19, x20, [sp], #16
|
|
+ ldp x21, x22, [sp], #16
|
|
+ ldp x23, x24, [sp], #16
|
|
+ ldp x25, x26, [sp], #16
|
|
+ ldp x27, x28, [sp], #16
|
|
+ ldp x29, x30, [sp], #16
|
|
+ ret
|
|
+
|
|
+
|
|
+
|
|
+.section .rodata
|
|
+/* export the ranges so that
|
|
+ VG_(fixup_guest_state_after_syscall_interrupted) can do the
|
|
+ right thing */
|
|
+
|
|
+.globl ML_(blksys_setup)
|
|
+.globl ML_(blksys_restart)
|
|
+.globl ML_(blksys_complete)
|
|
+.globl ML_(blksys_committed)
|
|
+.globl ML_(blksys_finished)
|
|
+ML_(blksys_setup): .quad 1b
|
|
+ML_(blksys_restart): .quad 2b
|
|
+ML_(blksys_complete): .quad 3b
|
|
+ML_(blksys_committed): .quad 4b
|
|
+ML_(blksys_finished): .quad 5b
|
|
+
|
|
+/* Let the linker know we don't need an executable stack */
|
|
+.section .note.GNU-stack,"",%progbits
|
|
+
|
|
+.previous
|
|
+
|
|
+#endif // defined(VGP_arm_linux)
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: coregrind/m_syswrap/syswrap-main.c
|
|
===================================================================
|
|
--- coregrind/m_syswrap/syswrap-main.c.orig
|
|
+++ coregrind/m_syswrap/syswrap-main.c
|
|
@@ -70,6 +70,7 @@
|
|
arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
|
|
mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
|
|
mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
|
|
+ arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
|
|
|
|
On s390x the svc instruction is used for system calls. The system call
|
|
number is encoded in the instruction (8 bit immediate field). Since Linux
|
|
@@ -464,6 +465,18 @@ void getSyscallArgsFromGuestState ( /*OU
|
|
canonical->arg7 = 0;
|
|
canonical->arg8 = 0;
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
|
|
+ canonical->sysno = gst->guest_X8;
|
|
+ canonical->arg1 = gst->guest_X0;
|
|
+ canonical->arg2 = gst->guest_X1;
|
|
+ canonical->arg3 = gst->guest_X2;
|
|
+ canonical->arg4 = gst->guest_X3;
|
|
+ canonical->arg5 = gst->guest_X4;
|
|
+ canonical->arg6 = gst->guest_X5;
|
|
+ canonical->arg7 = 0;
|
|
+ canonical->arg8 = 0;
|
|
+
|
|
#elif defined(VGP_mips32_linux)
|
|
VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
|
|
canonical->sysno = gst->guest_r2; // v0
|
|
@@ -694,6 +707,16 @@ void putSyscallArgsIntoGuestState ( /*IN
|
|
gst->guest_R4 = canonical->arg5;
|
|
gst->guest_R5 = canonical->arg6;
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
|
|
+ gst->guest_X8 = canonical->sysno;
|
|
+ gst->guest_X0 = canonical->arg1;
|
|
+ gst->guest_X1 = canonical->arg2;
|
|
+ gst->guest_X2 = canonical->arg3;
|
|
+ gst->guest_X3 = canonical->arg4;
|
|
+ gst->guest_X4 = canonical->arg5;
|
|
+ gst->guest_X5 = canonical->arg6;
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
|
|
UWord *stack = (UWord *)gst->guest_ESP;
|
|
@@ -746,8 +769,8 @@ void putSyscallArgsIntoGuestState ( /*IN
|
|
gst->guest_r5 = canonical->arg2;
|
|
gst->guest_r6 = canonical->arg3;
|
|
gst->guest_r7 = canonical->arg4;
|
|
- *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp)
|
|
- *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp)
|
|
+ *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp)
|
|
+ *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp)
|
|
} else {
|
|
canonical->arg8 = 0;
|
|
gst->guest_r2 = __NR_syscall;
|
|
@@ -755,9 +778,9 @@ void putSyscallArgsIntoGuestState ( /*IN
|
|
gst->guest_r5 = canonical->arg1;
|
|
gst->guest_r6 = canonical->arg2;
|
|
gst->guest_r7 = canonical->arg3;
|
|
- *((UInt*) (gst->guest_r29 + 16)) = canonical->arg4; // 16(guest_GPR29/sp)
|
|
- *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp)
|
|
- *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp)
|
|
+ *((UInt*) (gst->guest_r29 + 16)) = canonical->arg4; // 16(guest_GPR29/sp)
|
|
+ *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp)
|
|
+ *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp)
|
|
}
|
|
|
|
#elif defined(VGP_mips64_linux)
|
|
@@ -807,6 +830,11 @@ void getSyscallStatusFromGuestState ( /*
|
|
canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 );
|
|
canonical->what = SsComplete;
|
|
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
|
|
+ canonical->sres = VG_(mk_SysRes_arm64_linux)( gst->guest_X0 );
|
|
+ canonical->what = SsComplete;
|
|
+
|
|
# elif defined(VGP_mips32_linux)
|
|
VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
|
|
UInt v0 = gst->guest_r2; // v0
|
|
@@ -980,6 +1008,20 @@ void putSyscallStatusIntoGuestState ( /*
|
|
VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
|
|
OFFSET_arm_R0, sizeof(UWord) );
|
|
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
|
|
+ vg_assert(canonical->what == SsComplete);
|
|
+ if (sr_isError(canonical->sres)) {
|
|
+ /* This isn't exactly right, in that really a Failure with res
|
|
+ not in the range 1 .. 4095 is unrepresentable in the
|
|
+ Linux-arm64 scheme. Oh well. */
|
|
+ gst->guest_X0 = - (Long)sr_Err(canonical->sres);
|
|
+ } else {
|
|
+ gst->guest_X0 = sr_Res(canonical->sres);
|
|
+ }
|
|
+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
|
|
+ OFFSET_arm64_X0, sizeof(UWord) );
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
|
|
SysRes sres = canonical->sres;
|
|
@@ -1104,6 +1146,8 @@ void putSyscallStatusIntoGuestState ( /*
|
|
static
|
|
void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
|
|
{
|
|
+ VG_(bzero_inline)(layout, sizeof(*layout));
|
|
+
|
|
#if defined(VGP_x86_linux)
|
|
layout->o_sysno = OFFSET_x86_EAX;
|
|
layout->o_arg1 = OFFSET_x86_EBX;
|
|
@@ -1159,6 +1203,17 @@ void getSyscallArgLayout ( /*OUT*/Syscal
|
|
layout->uu_arg7 = -1; /* impossible value */
|
|
layout->uu_arg8 = -1; /* impossible value */
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ layout->o_sysno = OFFSET_arm64_X8;
|
|
+ layout->o_arg1 = OFFSET_arm64_X0;
|
|
+ layout->o_arg2 = OFFSET_arm64_X1;
|
|
+ layout->o_arg3 = OFFSET_arm64_X2;
|
|
+ layout->o_arg4 = OFFSET_arm64_X3;
|
|
+ layout->o_arg5 = OFFSET_arm64_X4;
|
|
+ layout->o_arg6 = OFFSET_arm64_X5;
|
|
+ layout->uu_arg7 = -1; /* impossible value */
|
|
+ layout->uu_arg8 = -1; /* impossible value */
|
|
+
|
|
#elif defined(VGP_mips32_linux)
|
|
layout->o_sysno = OFFSET_mips32_r2;
|
|
layout->o_arg1 = OFFSET_mips32_r4;
|
|
@@ -1990,6 +2045,10 @@ void ML_(fixup_guest_state_to_restart_sy
|
|
vg_assert(valid);
|
|
}
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ // probably simplest to copy the ppc version
|
|
+ I_die_here;
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL;
|
|
|
|
Index: coregrind/m_syswrap/syswrap-arm64-linux.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ coregrind/m_syswrap/syswrap-arm64-linux.c
|
|
@@ -0,0 +1,1341 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- Platform-specific syscalls stuff. syswrap-arm64-linux.c -----*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+#include "pub_core_basics.h"
|
|
+#include "pub_core_vki.h"
|
|
+#include "pub_core_vkiscnums.h"
|
|
+#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
|
|
+#include "pub_core_threadstate.h"
|
|
+#include "pub_core_aspacemgr.h"
|
|
+//ZZ #include "pub_core_debuglog.h"
|
|
+//ZZ #include "pub_core_libcbase.h"
|
|
+#include "pub_core_libcassert.h"
|
|
+#include "pub_core_libcprint.h"
|
|
+//ZZ #include "pub_core_libcproc.h"
|
|
+//ZZ #include "pub_core_libcsignal.h"
|
|
+#include "pub_core_options.h"
|
|
+//ZZ #include "pub_core_scheduler.h"
|
|
+#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
|
|
+//ZZ #include "pub_core_signals.h"
|
|
+#include "pub_core_syscall.h"
|
|
+#include "pub_core_syswrap.h"
|
|
+#include "pub_core_tooliface.h"
|
|
+//ZZ #include "pub_core_stacks.h" // VG_(register_stack)
|
|
+//ZZ #include "pub_core_transtab.h" // VG_(discard_translations)
|
|
+
|
|
+#include "priv_types_n_macros.h"
|
|
+#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
|
|
+#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
|
|
+//ZZ #include "priv_syswrap-main.h"
|
|
+
|
|
+
|
|
+/* ---------------------------------------------------------------------
|
|
+ clone() handling
|
|
+ ------------------------------------------------------------------ */
|
|
+
|
|
+/* Call f(arg1), but first switch stacks, using 'stack' as the new
|
|
+ stack, and use 'retaddr' as f's return-to address. Also, clear all
|
|
+ the integer registers before entering f.*/
|
|
+__attribute__((noreturn))
|
|
+void ML_(call_on_new_stack_0_1) ( Addr stack,
|
|
+ Addr retaddr,
|
|
+ void (*f)(Word),
|
|
+ Word arg1 );
|
|
+// r0 = stack
|
|
+// r1 = retaddr
|
|
+// r2 = f
|
|
+// r3 = arg1
|
|
+asm(
|
|
+".text\n"
|
|
+".globl vgModuleLocal_call_on_new_stack_0_1\n"
|
|
+"vgModuleLocal_call_on_new_stack_0_1:\n"
|
|
+" mov sp, x0\n\t" /* Stack pointer */
|
|
+" mov x30, x1\n\t" /* Return address (x30 is LR) */
|
|
+" mov x0, x3\n\t" /* First argument */
|
|
+" mov x9, x2\n\t" /* 'f': x9 won't be zeroed at start of f. Oh well. */
|
|
+" mov x1, #0\n\t" /* Clear our GPRs */
|
|
+" mov x2, #0\n\t"
|
|
+" mov x3, #0\n\t"
|
|
+" mov x4, #0\n\t"
|
|
+" mov x5, #0\n\t"
|
|
+" mov x6, #0\n\t"
|
|
+" mov x7, #0\n\t"
|
|
+" mov x8, #0\n\t"
|
|
+/* don't zero out x9 */
|
|
+" mov x10, #0\n\t"
|
|
+" mov x11, #0\n\t"
|
|
+" mov x12, #0\n\t"
|
|
+" mov x13, #0\n\t"
|
|
+" mov x14, #0\n\t"
|
|
+" mov x15, #0\n\t"
|
|
+" mov x16, #0\n\t"
|
|
+" mov x17, #0\n\t"
|
|
+" mov x18, #0\n\t"
|
|
+" mov x19, #0\n\t"
|
|
+" mov x20, #0\n\t"
|
|
+" mov x21, #0\n\t"
|
|
+" mov x22, #0\n\t"
|
|
+" mov x23, #0\n\t"
|
|
+" mov x24, #0\n\t"
|
|
+" mov x25, #0\n\t"
|
|
+" mov x26, #0\n\t"
|
|
+" mov x27, #0\n\t"
|
|
+" mov x28, #0\n\t"
|
|
+" mov x29, sp\n\t" /* FP = SP, in the absence of better suggestions */
|
|
+" br x9\n\t"
|
|
+".previous\n"
|
|
+);
|
|
+
|
|
+
|
|
+//ZZ #define __NR_CLONE VG_STRINGIFY(__NR_clone)
|
|
+//ZZ #define __NR_EXIT VG_STRINGIFY(__NR_exit)
|
|
+//ZZ
|
|
+//ZZ extern
|
|
+//ZZ ULong do_syscall_clone_arm_linux ( Word (*fn)(void *),
|
|
+//ZZ void* stack,
|
|
+//ZZ Int flags,
|
|
+//ZZ void* arg,
|
|
+//ZZ Int* child_tid,
|
|
+//ZZ Int* parent_tid,
|
|
+//ZZ void* tls );
|
|
+//ZZ asm(
|
|
+//ZZ ".text\n"
|
|
+//ZZ ".globl do_syscall_clone_arm_linux\n"
|
|
+//ZZ "do_syscall_clone_arm_linux:\n"
|
|
+//ZZ
|
|
+//ZZ /*Setup child stack */
|
|
+//ZZ " str r0, [r1, #-4]!\n"
|
|
+//ZZ " str r3, [r1, #-4]!\n"
|
|
+//ZZ " push {r4,r7}\n"
|
|
+//ZZ " mov r0, r2\n" /* arg1: flags */
|
|
+//ZZ /* r1 (arg2) is already our child's stack */
|
|
+//ZZ " ldr r2, [sp, #12]\n" // parent tid
|
|
+//ZZ " ldr r3, [sp, #16]\n" // tls
|
|
+//ZZ " ldr r4, [sp, #8]\n" // Child tid
|
|
+//ZZ " mov r7, #"__NR_CLONE"\n"
|
|
+//ZZ " svc 0x00000000\n"
|
|
+//ZZ " cmp r0, #0\n"
|
|
+//ZZ " beq 1f\n"
|
|
+//ZZ
|
|
+//ZZ /* Parent */
|
|
+//ZZ " pop {r4,r7}\n"
|
|
+//ZZ " bx lr\n"
|
|
+//ZZ
|
|
+//ZZ "1:\n" /*child*/
|
|
+//ZZ " mov lr, pc\n"
|
|
+//ZZ " pop {r0,pc}\n"
|
|
+//ZZ /* Retval from child is already in r0 */
|
|
+//ZZ " mov r7, #"__NR_EXIT"\n"
|
|
+//ZZ " svc 0x00000000\n"
|
|
+//ZZ /* Urh.. why did exit return? */
|
|
+//ZZ " .long 0\n"
|
|
+//ZZ " .previous\n"
|
|
+//ZZ );
|
|
+//ZZ
|
|
+//ZZ #undef __NR_CLONE
|
|
+//ZZ #undef __NR_EXIT
|
|
+//ZZ
|
|
+//ZZ // forward declarations
|
|
+//ZZ static void setup_child ( ThreadArchState*, ThreadArchState* );
|
|
+//ZZ static void assign_guest_tls(ThreadId ctid, Addr tlsptr);
|
|
+//ZZ static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
|
|
+//ZZ
|
|
+//ZZ /*
|
|
+//ZZ When a client clones, we need to keep track of the new thread. This means:
|
|
+//ZZ 1. allocate a ThreadId+ThreadState+stack for the the thread
|
|
+//ZZ
|
|
+//ZZ 2. initialize the thread's new VCPU state
|
|
+//ZZ
|
|
+//ZZ 3. create the thread using the same args as the client requested,
|
|
+//ZZ but using the scheduler entrypoint for IP, and a separate stack
|
|
+//ZZ for SP.
|
|
+//ZZ */
|
|
+//ZZ static SysRes do_clone ( ThreadId ptid,
|
|
+//ZZ UInt flags, Addr sp,
|
|
+//ZZ Int *parent_tidptr,
|
|
+//ZZ Int *child_tidptr,
|
|
+//ZZ Addr child_tls)
|
|
+//ZZ {
|
|
+//ZZ const Bool debug = False;
|
|
+//ZZ
|
|
+//ZZ ThreadId ctid = VG_(alloc_ThreadState)();
|
|
+//ZZ ThreadState* ptst = VG_(get_ThreadState)(ptid);
|
|
+//ZZ ThreadState* ctst = VG_(get_ThreadState)(ctid);
|
|
+//ZZ UInt r0;
|
|
+//ZZ UWord *stack;
|
|
+//ZZ NSegment const* seg;
|
|
+//ZZ SysRes res;
|
|
+//ZZ vki_sigset_t blockall, savedmask;
|
|
+//ZZ
|
|
+//ZZ VG_(sigfillset)(&blockall);
|
|
+//ZZ
|
|
+//ZZ vg_assert(VG_(is_running_thread)(ptid));
|
|
+//ZZ vg_assert(VG_(is_valid_tid)(ctid));
|
|
+//ZZ
|
|
+//ZZ stack = (UWord*)ML_(allocstack)(ctid);
|
|
+//ZZ
|
|
+//ZZ if(stack == NULL) {
|
|
+//ZZ res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
|
|
+//ZZ goto out;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ setup_child( &ctst->arch, &ptst->arch );
|
|
+//ZZ
|
|
+//ZZ ctst->arch.vex.guest_R0 = 0;
|
|
+//ZZ if(sp != 0)
|
|
+//ZZ ctst->arch.vex.guest_R13 = sp;
|
|
+//ZZ
|
|
+//ZZ ctst->os_state.parent = ptid;
|
|
+//ZZ
|
|
+//ZZ ctst->sig_mask = ptst->sig_mask;
|
|
+//ZZ ctst->tmp_sig_mask = ptst->sig_mask;
|
|
+//ZZ
|
|
+//ZZ /* Start the child with its threadgroup being the same as the
|
|
+//ZZ parent's. This is so that any exit_group calls that happen
|
|
+//ZZ after the child is created but before it sets its
|
|
+//ZZ os_state.threadgroup field for real (in thread_wrapper in
|
|
+//ZZ syswrap-linux.c), really kill the new thread. a.k.a this avoids
|
|
+//ZZ a race condition in which the thread is unkillable (via
|
|
+//ZZ exit_group) because its threadgroup is not set. The race window
|
|
+//ZZ is probably only a few hundred or a few thousand cycles long.
|
|
+//ZZ See #226116. */
|
|
+//ZZ ctst->os_state.threadgroup = ptst->os_state.threadgroup;
|
|
+//ZZ
|
|
+//ZZ seg = VG_(am_find_nsegment)((Addr)sp);
|
|
+//ZZ if (seg && seg->kind != SkResvn) {
|
|
+//ZZ ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
|
|
+//ZZ ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
|
|
+//ZZ
|
|
+//ZZ VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
|
|
+//ZZ
|
|
+//ZZ if (debug)
|
|
+//ZZ VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
|
|
+//ZZ ctid, seg->start, VG_PGROUNDUP(sp));
|
|
+//ZZ } else {
|
|
+//ZZ VG_(message)(Vg_UserMsg, "!? New thread %d starts with sp+%#lx) unmapped\n", ctid, sp);
|
|
+//ZZ ctst->client_stack_szB = 0;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ vg_assert(VG_(owns_BigLock_LL)(ptid));
|
|
+//ZZ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
|
|
+//ZZ
|
|
+//ZZ if (flags & VKI_CLONE_SETTLS) {
|
|
+//ZZ /* Just assign the tls pointer in the guest TPIDRURO. */
|
|
+//ZZ assign_guest_tls(ctid, child_tls);
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ flags &= ~VKI_CLONE_SETTLS;
|
|
+//ZZ
|
|
+//ZZ VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
|
|
+//ZZ
|
|
+//ZZ r0 = do_syscall_clone_arm_linux(
|
|
+//ZZ ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
|
|
+//ZZ child_tidptr, parent_tidptr, NULL
|
|
+//ZZ );
|
|
+//ZZ //VG_(printf)("AFTER SYSCALL, %x and %x CHILD: %d PARENT: %d\n",child_tidptr, parent_tidptr,*child_tidptr,*parent_tidptr);
|
|
+//ZZ
|
|
+//ZZ res = VG_(mk_SysRes_arm_linux)( r0 );
|
|
+//ZZ
|
|
+//ZZ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
|
|
+//ZZ
|
|
+//ZZ out:
|
|
+//ZZ if (sr_isError(res)) {
|
|
+//ZZ VG_(cleanup_thread)(&ctst->arch);
|
|
+//ZZ ctst->status = VgTs_Empty;
|
|
+//ZZ VG_TRACK( pre_thread_ll_exit, ctid );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ return res;
|
|
+//ZZ }
|
|
+
|
|
+
|
|
+
|
|
+/* ---------------------------------------------------------------------
|
|
+ More thread stuff
|
|
+ ------------------------------------------------------------------ */
|
|
+
|
|
+// ARM64 doesn't have any architecture specific thread stuff that
|
|
+// needs to be cleaned up
|
|
+void VG_(cleanup_thread) ( ThreadArchState* arch )
|
|
+{
|
|
+}
|
|
+
|
|
+//ZZ void setup_child ( /*OUT*/ ThreadArchState *child,
|
|
+//ZZ /*IN*/ ThreadArchState *parent )
|
|
+//ZZ {
|
|
+//ZZ child->vex = parent->vex;
|
|
+//ZZ child->vex_shadow1 = parent->vex_shadow1;
|
|
+//ZZ child->vex_shadow2 = parent->vex_shadow2;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ static void assign_guest_tls(ThreadId tid, Addr tlsptr)
|
|
+//ZZ {
|
|
+//ZZ VG_(threads)[tid].arch.vex.guest_TPIDRURO = tlsptr;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ /* Assigns tlsptr to the guest TPIDRURO.
|
|
+//ZZ If needed for the specific hardware, really executes
|
|
+//ZZ the set_tls syscall.
|
|
+//ZZ */
|
|
+//ZZ static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
|
|
+//ZZ {
|
|
+//ZZ assign_guest_tls(tid, tlsptr);
|
|
+//ZZ #if defined(ANDROID_HARDWARE_emulator)
|
|
+//ZZ /* Android emulator does not provide an hw tls register.
|
|
+//ZZ So, the tls register is emulated by the kernel.
|
|
+//ZZ This emulated value is set by the __NR_ARM_set_tls syscall.
|
|
+//ZZ The emulated value must be read by the kernel helper function
|
|
+//ZZ located at 0xffff0fe0.
|
|
+//ZZ
|
|
+//ZZ The emulated tlsptr is located at 0xffff0ff0
|
|
+//ZZ (so slightly after the kernel helper function).
|
|
+//ZZ Note that applications are not supposed to read this directly.
|
|
+//ZZ
|
|
+//ZZ For compatibility : if there is a hw tls register, the kernel
|
|
+//ZZ will put at 0xffff0fe0 the instructions to read it, so
|
|
+//ZZ as to have old applications calling the kernel helper
|
|
+//ZZ working properly.
|
|
+//ZZ
|
|
+//ZZ For having emulated guest TLS working correctly with
|
|
+//ZZ Valgrind, it is needed to execute the syscall to set
|
|
+//ZZ the emulated TLS value in addition to the assignment
|
|
+//ZZ of TPIDRURO.
|
|
+//ZZ
|
|
+//ZZ Note: the below means that if we need thread local storage
|
|
+//ZZ for Valgrind host, then there will be a conflict between
|
|
+//ZZ the need of the guest tls and of the host tls.
|
|
+//ZZ If all the guest code would cleanly call 0xffff0fe0,
|
|
+//ZZ then we might maybe intercept this. However, at least
|
|
+//ZZ __libc_preinit reads directly 0xffff0ff0.
|
|
+//ZZ */
|
|
+//ZZ /* ??? might call the below if auxv->u.a_val & VKI_HWCAP_TLS ???
|
|
+//ZZ Unclear if real hardware having tls hw register sets
|
|
+//ZZ VKI_HWCAP_TLS. */
|
|
+//ZZ return VG_(do_syscall1) (__NR_ARM_set_tls, tlsptr);
|
|
+//ZZ #else
|
|
+//ZZ return VG_(mk_SysRes_Success)( 0 );
|
|
+//ZZ #endif
|
|
+//ZZ }
|
|
+
|
|
+/* ---------------------------------------------------------------------
|
|
+ PRE/POST wrappers for arm/Linux-specific syscalls
|
|
+ ------------------------------------------------------------------ */
|
|
+
|
|
+#define PRE(name) DEFN_PRE_TEMPLATE(arm64_linux, name)
|
|
+#define POST(name) DEFN_POST_TEMPLATE(arm64_linux, name)
|
|
+
|
|
+//ZZ /* Add prototypes for the wrappers declared here, so that gcc doesn't
|
|
+//ZZ harass us for not having prototypes. Really this is a kludge --
|
|
+//ZZ the right thing to do is to make these wrappers 'static' since they
|
|
+//ZZ aren't visible outside this file, but that requires even more macro
|
|
+//ZZ magic. */
|
|
+//ZZ
|
|
+DECL_TEMPLATE(arm64_linux, sys_mmap);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_stat64);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_lstat64);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_fstatat64);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_fstat64);
|
|
+DECL_TEMPLATE(arm64_linux, sys_clone);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_sigreturn);
|
|
+DECL_TEMPLATE(arm64_linux, sys_rt_sigreturn);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_sigsuspend);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_set_tls);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_cacheflush);
|
|
+//ZZ DECL_TEMPLATE(arm_linux, sys_ptrace);
|
|
+//ZZ
|
|
+//ZZ PRE(sys_mmap2)
|
|
+//ZZ {
|
|
+//ZZ SysRes r;
|
|
+//ZZ
|
|
+//ZZ // Exactly like old_mmap() except:
|
|
+//ZZ // - all 6 args are passed in regs, rather than in a memory-block.
|
|
+//ZZ // - the file offset is specified in pagesize units rather than bytes,
|
|
+//ZZ // so that it can be used for files bigger than 2^32 bytes.
|
|
+//ZZ // pagesize or 4K-size units in offset? For ppc32/64-linux, this is
|
|
+//ZZ // 4K-sized. Assert that the page size is 4K here for safety.
|
|
+//ZZ vg_assert(VKI_PAGE_SIZE == 4096);
|
|
+//ZZ PRINT("sys_mmap2 ( %#lx, %llu, %ld, %ld, %ld, %ld )",
|
|
+//ZZ ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
|
|
+//ZZ PRE_REG_READ6(long, "mmap2",
|
|
+//ZZ unsigned long, start, unsigned long, length,
|
|
+//ZZ unsigned long, prot, unsigned long, flags,
|
|
+//ZZ unsigned long, fd, unsigned long, offset);
|
|
+//ZZ
|
|
+//ZZ r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
|
|
+//ZZ 4096 * (Off64T)ARG6 );
|
|
+//ZZ SET_STATUS_from_SysRes(r);
|
|
+//ZZ }
|
|
+
|
|
+// ARM64 FIXME is this correct?
|
|
+PRE(sys_mmap)
|
|
+{
|
|
+ SysRes r;
|
|
+
|
|
+ PRINT("sys_mmap ( %#lx, %llu, %ld, %ld, %d, %ld )",
|
|
+ ARG1, (ULong)ARG2, ARG3, ARG4, (Int)ARG5, ARG6 );
|
|
+ PRE_REG_READ6(long, "mmap",
|
|
+ unsigned long, start, unsigned long, length,
|
|
+ unsigned long, prot, unsigned long, flags,
|
|
+ unsigned long, fd, unsigned long, offset);
|
|
+
|
|
+ r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
|
|
+ SET_STATUS_from_SysRes(r);
|
|
+}
|
|
+
|
|
+//ZZ
|
|
+//ZZ // XXX: lstat64/fstat64/stat64 are generic, but not necessarily
|
|
+//ZZ // applicable to every architecture -- I think only to 32-bit archs.
|
|
+//ZZ // We're going to need something like linux/core_os32.h for such
|
|
+//ZZ // things, eventually, I think. --njn
|
|
+//ZZ PRE(sys_lstat64)
|
|
+//ZZ {
|
|
+//ZZ PRINT("sys_lstat64 ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
|
|
+//ZZ PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
|
|
+//ZZ PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
|
|
+//ZZ PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ POST(sys_lstat64)
|
|
+//ZZ {
|
|
+//ZZ vg_assert(SUCCESS);
|
|
+//ZZ if (RES == 0) {
|
|
+//ZZ POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ PRE(sys_stat64)
|
|
+//ZZ {
|
|
+//ZZ PRINT("sys_stat64 ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
|
|
+//ZZ PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
|
|
+//ZZ PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
|
|
+//ZZ PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ POST(sys_stat64)
|
|
+//ZZ {
|
|
+//ZZ POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ PRE(sys_fstatat64)
|
|
+//ZZ {
|
|
+//ZZ PRINT("sys_fstatat64 ( %ld, %#lx(%s), %#lx )",ARG1,ARG2,(char*)ARG2,ARG3);
|
|
+//ZZ PRE_REG_READ3(long, "fstatat64",
|
|
+//ZZ int, dfd, char *, file_name, struct stat64 *, buf);
|
|
+//ZZ PRE_MEM_RASCIIZ( "fstatat64(file_name)", ARG2 );
|
|
+//ZZ PRE_MEM_WRITE( "fstatat64(buf)", ARG3, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ POST(sys_fstatat64)
|
|
+//ZZ {
|
|
+//ZZ POST_MEM_WRITE( ARG3, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ PRE(sys_fstat64)
|
|
+//ZZ {
|
|
+//ZZ PRINT("sys_fstat64 ( %ld, %#lx )",ARG1,ARG2);
|
|
+//ZZ PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
|
|
+//ZZ PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ POST(sys_fstat64)
|
|
+//ZZ {
|
|
+//ZZ POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
|
|
+//ZZ }
|
|
+
|
|
+PRE(sys_clone)
|
|
+{
|
|
+ UInt cloneflags;
|
|
+
|
|
+ PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
|
|
+ PRE_REG_READ5(int, "clone",
|
|
+ unsigned long, flags,
|
|
+ void *, child_stack,
|
|
+ int *, parent_tidptr,
|
|
+ void *, child_tls,
|
|
+ int *, child_tidptr);
|
|
+
|
|
+ if (ARG1 & VKI_CLONE_PARENT_SETTID) {
|
|
+ PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
|
|
+ if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
|
|
+ VKI_PROT_WRITE)) {
|
|
+ SET_STATUS_Failure( VKI_EFAULT );
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
|
|
+ PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
|
|
+ if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
|
|
+ VKI_PROT_WRITE)) {
|
|
+ SET_STATUS_Failure( VKI_EFAULT );
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+//ZZ if (ARG1 & VKI_CLONE_SETTLS) {
|
|
+//ZZ PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
|
|
+//ZZ if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
|
|
+//ZZ VKI_PROT_READ)) {
|
|
+//ZZ SET_STATUS_Failure( VKI_EFAULT );
|
|
+//ZZ return;
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+
|
|
+ cloneflags = ARG1;
|
|
+
|
|
+ if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
|
|
+ SET_STATUS_Failure( VKI_EINVAL );
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* Only look at the flags we really care about */
|
|
+ switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
|
|
+ | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
|
|
+//ZZ case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
|
|
+//ZZ /* thread creation */
|
|
+//ZZ SET_STATUS_from_SysRes(
|
|
+//ZZ do_clone(tid,
|
|
+//ZZ ARG1, /* flags */
|
|
+//ZZ (Addr)ARG2, /* child ESP */
|
|
+//ZZ (Int *)ARG3, /* parent_tidptr */
|
|
+//ZZ (Int *)ARG5, /* child_tidptr */
|
|
+//ZZ (Addr)ARG4)); /* set_tls */
|
|
+//ZZ break;
|
|
+
|
|
+ case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
|
|
+ /* FALLTHROUGH - assume vfork == fork */
|
|
+ cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
|
|
+
|
|
+ case 0: /* plain fork */
|
|
+ SET_STATUS_from_SysRes(
|
|
+ ML_(do_fork_clone)(tid,
|
|
+ cloneflags, /* flags */
|
|
+ (Int *)ARG3, /* parent_tidptr */
|
|
+ (Int *)ARG5)); /* child_tidptr */
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ /* should we just ENOSYS? */
|
|
+ VG_(message)(Vg_UserMsg, "");
|
|
+ VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx", ARG1);
|
|
+ VG_(message)(Vg_UserMsg, "");
|
|
+ VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
|
|
+ VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
|
|
+ VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
|
|
+ VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
|
|
+ VG_(unimplemented)
|
|
+ ("Valgrind does not support general clone().");
|
|
+ }
|
|
+
|
|
+ if (SUCCESS) {
|
|
+ if (ARG1 & VKI_CLONE_PARENT_SETTID)
|
|
+ POST_MEM_WRITE(ARG3, sizeof(Int));
|
|
+ if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
|
|
+ POST_MEM_WRITE(ARG5, sizeof(Int));
|
|
+
|
|
+ /* Thread creation was successful; let the child have the chance
|
|
+ to run */
|
|
+ *flags |= SfYieldAfter;
|
|
+ }
|
|
+}
|
|
+
|
|
+//ZZ PRE(sys_sigreturn)
|
|
+//ZZ {
|
|
+//ZZ /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
|
|
+//ZZ an explanation of what follows. */
|
|
+//ZZ
|
|
+//ZZ PRINT("sys_sigreturn ( )");
|
|
+//ZZ
|
|
+//ZZ vg_assert(VG_(is_valid_tid)(tid));
|
|
+//ZZ vg_assert(tid >= 1 && tid < VG_N_THREADS);
|
|
+//ZZ vg_assert(VG_(is_running_thread)(tid));
|
|
+//ZZ
|
|
+//ZZ /* Restore register state from frame and remove it */
|
|
+//ZZ VG_(sigframe_destroy)(tid, False);
|
|
+//ZZ
|
|
+//ZZ /* Tell the driver not to update the guest state with the "result",
|
|
+//ZZ and set a bogus result to keep it happy. */
|
|
+//ZZ *flags |= SfNoWriteResult;
|
|
+//ZZ SET_STATUS_Success(0);
|
|
+//ZZ
|
|
+//ZZ /* Check to see if any signals arose as a result of this. */
|
|
+//ZZ *flags |= SfPollAfter;
|
|
+//ZZ }
|
|
+
|
|
+PRE(sys_rt_sigreturn)
|
|
+{
|
|
+ /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
|
|
+ an explanation of what follows. */
|
|
+
|
|
+ PRINT("rt_sigreturn ( )");
|
|
+
|
|
+ vg_assert(VG_(is_valid_tid)(tid));
|
|
+ vg_assert(tid >= 1 && tid < VG_N_THREADS);
|
|
+ vg_assert(VG_(is_running_thread)(tid));
|
|
+
|
|
+ /* Restore register state from frame and remove it */
|
|
+ VG_(sigframe_destroy)(tid, True);
|
|
+
|
|
+ /* Tell the driver not to update the guest state with the "result",
|
|
+ and set a bogus result to keep it happy. */
|
|
+ *flags |= SfNoWriteResult;
|
|
+ SET_STATUS_Success(0);
|
|
+
|
|
+ /* Check to see if any signals arose as a result of this. */
|
|
+ *flags |= SfPollAfter;
|
|
+}
|
|
+
|
|
+//ZZ /* NB: clone of x86-linux version, and ppc32-linux has an almost
|
|
+//ZZ identical one. */
|
|
+//ZZ PRE(sys_sigsuspend)
|
|
+//ZZ {
|
|
+//ZZ /* The C library interface to sigsuspend just takes a pointer to
|
|
+//ZZ a signal mask but this system call has three arguments - the first
|
|
+//ZZ two don't appear to be used by the kernel and are always passed as
|
|
+//ZZ zero by glibc and the third is the first word of the signal mask
|
|
+//ZZ so only 32 signals are supported.
|
|
+//ZZ
|
|
+//ZZ In fact glibc normally uses rt_sigsuspend if it is available as
|
|
+//ZZ that takes a pointer to the signal mask so supports more signals.
|
|
+//ZZ */
|
|
+//ZZ *flags |= SfMayBlock;
|
|
+//ZZ PRINT("sys_sigsuspend ( %ld, %ld, %ld )", ARG1,ARG2,ARG3 );
|
|
+//ZZ PRE_REG_READ3(int, "sigsuspend",
|
|
+//ZZ int, history0, int, history1,
|
|
+//ZZ vki_old_sigset_t, mask);
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ /* Very much ARM specific */
|
|
+//ZZ
|
|
+//ZZ PRE(sys_set_tls)
|
|
+//ZZ {
|
|
+//ZZ PRINT("set_tls (%lx)",ARG1);
|
|
+//ZZ PRE_REG_READ1(long, "set_tls", unsigned long, addr);
|
|
+//ZZ
|
|
+//ZZ SET_STATUS_from_SysRes( sys_set_tls( tid, ARG1 ) );
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ PRE(sys_cacheflush)
|
|
+//ZZ {
|
|
+//ZZ PRINT("cacheflush (%lx, %#lx, %#lx)",ARG1,ARG2,ARG3);
|
|
+//ZZ PRE_REG_READ3(long, "cacheflush", void*, addrlow,void*, addrhigh,int, flags);
|
|
+//ZZ VG_(discard_translations)( (Addr64)ARG1,
|
|
+//ZZ ((ULong)ARG2) - ((ULong)ARG1) + 1ULL/*paranoia*/,
|
|
+//ZZ "PRE(sys_cacheflush)" );
|
|
+//ZZ SET_STATUS_Success(0);
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ // ARG3 is only used for pointers into the traced process's address
|
|
+//ZZ // space and for offsets into the traced process's struct
|
|
+//ZZ // user_regs_struct. It is never a pointer into this process's memory
|
|
+//ZZ // space, and we should therefore not check anything it points to.
|
|
+//ZZ PRE(sys_ptrace)
|
|
+//ZZ {
|
|
+//ZZ PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
|
|
+//ZZ PRE_REG_READ4(int, "ptrace",
|
|
+//ZZ long, request, long, pid, long, addr, long, data);
|
|
+//ZZ switch (ARG1) {
|
|
+//ZZ case VKI_PTRACE_PEEKTEXT:
|
|
+//ZZ case VKI_PTRACE_PEEKDATA:
|
|
+//ZZ case VKI_PTRACE_PEEKUSR:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(peek)", ARG4,
|
|
+//ZZ sizeof (long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_regs_struct));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETFPREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_fp));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETWMMXREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getwmmxregs)", ARG4,
|
|
+//ZZ VKI_IWMMXT_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETCRUNCHREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getcrunchregs)", ARG4,
|
|
+//ZZ VKI_CRUNCH_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETVFPREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getvfpregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_vfp) );
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETHBPREGS:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(gethbpregs)", ARG4,
|
|
+//ZZ sizeof (unsigned long) );
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_regs_struct));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETFPREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_fp));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETWMMXREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setwmmxregs)", ARG4,
|
|
+//ZZ VKI_IWMMXT_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETCRUNCHREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setcrunchregs)", ARG4,
|
|
+//ZZ VKI_CRUNCH_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETVFPREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setvfpregs)", ARG4,
|
|
+//ZZ sizeof (struct vki_user_vfp));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETHBPREGS:
|
|
+//ZZ PRE_MEM_READ( "ptrace(sethbpregs)", ARG4, sizeof(unsigned long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GET_THREAD_AREA:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(get_thread_area)", ARG4, sizeof(unsigned long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETEVENTMSG:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETSIGINFO:
|
|
+//ZZ PRE_MEM_WRITE( "ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETSIGINFO:
|
|
+//ZZ PRE_MEM_READ( "ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETREGSET:
|
|
+//ZZ ML_(linux_PRE_getregset)(tid, ARG3, ARG4);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_SETREGSET:
|
|
+//ZZ ML_(linux_PRE_setregset)(tid, ARG3, ARG4);
|
|
+//ZZ break;
|
|
+//ZZ default:
|
|
+//ZZ break;
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ POST(sys_ptrace)
|
|
+//ZZ {
|
|
+//ZZ switch (ARG1) {
|
|
+//ZZ case VKI_PTRACE_PEEKTEXT:
|
|
+//ZZ case VKI_PTRACE_PEEKDATA:
|
|
+//ZZ case VKI_PTRACE_PEEKUSR:
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof (long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETREGS:
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETFPREGS:
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof (struct vki_user_fp));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETWMMXREGS:
|
|
+//ZZ POST_MEM_WRITE( ARG4, VKI_IWMMXT_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETCRUNCHREGS:
|
|
+//ZZ POST_MEM_WRITE( ARG4, VKI_CRUNCH_SIZE);
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETVFPREGS:
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof(struct vki_user_vfp));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GET_THREAD_AREA:
|
|
+//ZZ case VKI_PTRACE_GETHBPREGS:
|
|
+//ZZ case VKI_PTRACE_GETEVENTMSG:
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof(unsigned long));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETSIGINFO:
|
|
+//ZZ /* XXX: This is a simplification. Different parts of the
|
|
+//ZZ * siginfo_t are valid depending on the type of signal.
|
|
+//ZZ */
|
|
+//ZZ POST_MEM_WRITE( ARG4, sizeof(vki_siginfo_t));
|
|
+//ZZ break;
|
|
+//ZZ case VKI_PTRACE_GETREGSET:
|
|
+//ZZ ML_(linux_POST_getregset)(tid, ARG3, ARG4);
|
|
+//ZZ break;
|
|
+//ZZ default:
|
|
+//ZZ break;
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ #undef PRE
|
|
+//ZZ #undef POST
|
|
+
|
|
+/* ---------------------------------------------------------------------
|
|
+ The arm64/Linux syscall table
|
|
+ ------------------------------------------------------------------ */
|
|
+
|
|
+//ZZ #if 0
|
|
+//ZZ #define __NR_OABI_SYSCALL_BASE 0x900000
|
|
+//ZZ #else
|
|
+//ZZ #define __NR_OABI_SYSCALL_BASE 0x0
|
|
+//ZZ #endif
|
|
+
|
|
+#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(arm64_linux, sysno, name)
|
|
+#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(arm64_linux, sysno, name)
|
|
+
|
|
+// This table maps from __NR_xxx syscall numbers (from
|
|
+// linux/include/asm-arm/unistd.h) to the appropriate PRE/POST sys_foo()
|
|
+// wrappers on arm64 (as per sys_call_table in linux/arch/arm/kernel/entry.S).
|
|
+//
|
|
+// For those syscalls not handled by Valgrind, the annotation indicate its
|
|
+// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
|
|
+// (unknown).
|
|
+
|
|
+static SyscallTableEntry syscall_main_table[] = {
|
|
+ LINXY(__NR_getxattr, sys_getxattr), // 8
|
|
+ LINXY(__NR_lgetxattr, sys_lgetxattr), // 9
|
|
+ GENXY(__NR_getcwd, sys_getcwd), // 17
|
|
+ LINXY(__NR_dup3, sys_dup3), // 24
|
|
+
|
|
+ // FIXME IS THIS CORRECT?
|
|
+ LINXY(__NR3264_fcntl, sys_fcntl), // 25
|
|
+
|
|
+ LINXY(__NR_ioctl, sys_ioctl), // 29
|
|
+ LINX_(__NR_mkdirat, sys_mkdirat), // 34
|
|
+ LINX_(__NR_unlinkat, sys_unlinkat), // 35
|
|
+
|
|
+ // FIXME IS THIS CORRECT? it may well not be.
|
|
+ GENXY(__NR3264_statfs, sys_statfs), // 43
|
|
+
|
|
+ LINX_(__NR_faccessat, sys_faccessat), // 48
|
|
+ GENX_(__NR_chdir, sys_chdir), // 49
|
|
+ LINXY(__NR_openat, sys_openat), // 56
|
|
+ GENXY(__NR_close, sys_close), // 57
|
|
+ LINXY(__NR_pipe2, sys_pipe2), // 59
|
|
+ GENXY(__NR_getdents64, sys_getdents64), // 61
|
|
+
|
|
+ // FIXME IS THIS CORRECT?
|
|
+ LINX_(__NR3264_lseek, sys_lseek), // 62
|
|
+
|
|
+ GENXY(__NR_read, sys_read), // 63
|
|
+ GENX_(__NR_write, sys_write), // 64
|
|
+ GENX_(__NR_writev, sys_writev), // 66
|
|
+
|
|
+ LINX_(__NR_readlinkat, sys_readlinkat), // 78
|
|
+
|
|
+ // FIXME IS THIS CORRECT?
|
|
+ LINXY(__NR3264_fstatat, sys_newfstatat), // 79
|
|
+ GENXY(__NR3264_fstat, sys_newfstat), // 80
|
|
+
|
|
+ LINX_(__NR_exit_group, sys_exit_group), // 94
|
|
+ LINX_(__NR_set_tid_address, sys_set_tid_address), // 96
|
|
+ LINXY(__NR_futex, sys_futex), // 98
|
|
+ LINX_(__NR_set_robust_list, sys_set_robust_list), // 99
|
|
+ LINXY(__NR_clock_gettime, sys_clock_gettime), // 113
|
|
+ LINX_(__NR_tgkill, sys_tgkill), // 131 */Linux
|
|
+ LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 134
|
|
+ LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 135
|
|
+ PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 139
|
|
+ GENX_(__NR_getpgid, sys_getpgid), // 155
|
|
+ GENXY(__NR_uname, sys_newuname), // 160
|
|
+ GENXY(__NR_getrlimit, sys_old_getrlimit), // 163
|
|
+ GENXY(__NR_getrusage, sys_getrusage), // 165
|
|
+ GENXY(__NR_gettimeofday, sys_gettimeofday), // 169
|
|
+ GENX_(__NR_getpid, sys_getpid), // 172
|
|
+ GENX_(__NR_getppid, sys_getppid), // 173
|
|
+ GENX_(__NR_getuid, sys_getuid), // 174
|
|
+ GENX_(__NR_geteuid, sys_geteuid), // 175
|
|
+ GENX_(__NR_getgid, sys_getgid), // 176
|
|
+ GENX_(__NR_getegid, sys_getegid), // 177
|
|
+ LINX_(__NR_gettid, sys_gettid), // 178
|
|
+ LINXY(__NR_socket, sys_socket), // 198
|
|
+ LINX_(__NR_connect, sys_connect), // 203
|
|
+ GENX_(__NR_brk, sys_brk), // 214
|
|
+ GENXY(__NR_munmap, sys_munmap), // 215
|
|
+ PLAX_(__NR_clone, sys_clone), // 220
|
|
+ GENX_(__NR_execve, sys_execve), // 221
|
|
+
|
|
+ // FIXME IS THIS CORRECT?
|
|
+ PLAX_(__NR3264_mmap, sys_mmap), // 222
|
|
+
|
|
+ GENXY(__NR_mprotect, sys_mprotect), // 226
|
|
+ GENXY(__NR_wait4, sys_wait4), // 260
|
|
+
|
|
+// The numbers below are bogus. (See comment further down.)
|
|
+// When pulling entries above this line, change the numbers
|
|
+// to be correct.
|
|
+
|
|
+//ZZ GENX_(__NR_exit, sys_exit), // 93
|
|
+//ZZ //zz // (restart_syscall) // 0
|
|
+//ZZ GENX_(__NR_fork, sys_fork), // 2
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_open, sys_open), // 5
|
|
+//ZZ // GENXY(__NR_waitpid, sys_waitpid), // 7
|
|
+//ZZ GENXY(__NR_creat, sys_creat), // 8
|
|
+//ZZ GENX_(__NR_link, sys_link), // 9
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_unlink, sys_unlink), // 10
|
|
+//ZZ GENXY(__NR_time, sys_time), // 13
|
|
+//ZZ GENX_(__NR_mknod, sys_mknod), // 14
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_chmod, sys_chmod), // 15
|
|
+//ZZ //zz LINX_(__NR_lchown, sys_lchown16), // 16
|
|
+//ZZ // GENX_(__NR_break, sys_ni_syscall), // 17
|
|
+//ZZ //zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
|
|
+//ZZ LINX_(__NR_lseek, sys_lseek), // 19
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_getpid, sys_getpid), // 20
|
|
+//ZZ LINX_(__NR_mount, sys_mount), // 21
|
|
+//ZZ LINX_(__NR_umount, sys_oldumount), // 22
|
|
+//ZZ LINX_(__NR_setuid, sys_setuid16), // 23 ## P
|
|
+//ZZ LINX_(__NR_getuid, sys_getuid16), // 24 ## P
|
|
+//ZZ //zz
|
|
+//ZZ //zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
|
|
+//ZZ PLAXY(__NR_ptrace, sys_ptrace), // 26
|
|
+//ZZ GENX_(__NR_alarm, sys_alarm), // 27
|
|
+//ZZ //zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
|
|
+//ZZ GENX_(__NR_pause, sys_pause), // 29
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_utime, sys_utime), // 30
|
|
+//ZZ // GENX_(__NR_stty, sys_ni_syscall), // 31
|
|
+//ZZ // GENX_(__NR_gtty, sys_ni_syscall), // 32
|
|
+//ZZ GENX_(__NR_access, sys_access), // 33
|
|
+//ZZ GENX_(__NR_nice, sys_nice), // 34
|
|
+//ZZ
|
|
+//ZZ // GENX_(__NR_ftime, sys_ni_syscall), // 35
|
|
+//ZZ GENX_(__NR_sync, sys_sync), // 36
|
|
+//ZZ GENX_(__NR_kill, sys_kill), // 37
|
|
+//ZZ GENX_(__NR_rename, sys_rename), // 38
|
|
+//ZZ GENX_(__NR_mkdir, sys_mkdir), // 39
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_rmdir, sys_rmdir), // 40
|
|
+//ZZ GENXY(__NR_dup, sys_dup), // 41
|
|
+//ZZ LINXY(__NR_pipe, sys_pipe), // 42
|
|
+//ZZ GENXY(__NR_times, sys_times), // 43
|
|
+//ZZ // GENX_(__NR_prof, sys_ni_syscall), // 44
|
|
+
|
|
+//ZZ LINX_(__NR_setgid, sys_setgid16), // 46
|
|
+//ZZ LINX_(__NR_getgid, sys_getgid16), // 47
|
|
+//ZZ //zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
|
|
+//ZZ LINX_(__NR_geteuid, sys_geteuid16), // 49
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_getegid, sys_getegid16), // 50
|
|
+//ZZ GENX_(__NR_acct, sys_acct), // 51
|
|
+//ZZ LINX_(__NR_umount2, sys_umount), // 52
|
|
+//ZZ // GENX_(__NR_lock, sys_ni_syscall), // 53
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_fcntl, sys_fcntl), // 55
|
|
+//ZZ // GENX_(__NR_mpx, sys_ni_syscall), // 56
|
|
+//ZZ GENX_(__NR_setpgid, sys_setpgid), // 57
|
|
+//ZZ // GENX_(__NR_ulimit, sys_ni_syscall), // 58
|
|
+//ZZ //zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
|
|
+//ZZ //zz
|
|
+//ZZ GENX_(__NR_umask, sys_umask), // 60
|
|
+//ZZ GENX_(__NR_chroot, sys_chroot), // 61
|
|
+//ZZ //zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
|
|
+//ZZ GENXY(__NR_dup2, sys_dup2), // 63
|
|
+//ZZ GENX_(__NR_getppid, sys_getppid), // 64
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_getpgrp, sys_getpgrp), // 65
|
|
+//ZZ GENX_(__NR_setsid, sys_setsid), // 66
|
|
+//ZZ LINXY(__NR_sigaction, sys_sigaction), // 67
|
|
+//ZZ //zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
|
|
+//ZZ //zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
|
|
+//ZZ //zz
|
|
+//ZZ LINX_(__NR_setreuid, sys_setreuid16), // 70
|
|
+//ZZ LINX_(__NR_setregid, sys_setregid16), // 71
|
|
+//ZZ PLAX_(__NR_sigsuspend, sys_sigsuspend), // 72
|
|
+//ZZ LINXY(__NR_sigpending, sys_sigpending), // 73
|
|
+//ZZ //zz // (__NR_sethostname, sys_sethostname), // 74 */*
|
|
+//ZZ //zz
|
|
+//ZZ GENX_(__NR_setrlimit, sys_setrlimit), // 75
|
|
+//ZZ GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
|
|
+//ZZ GENX_(__NR_settimeofday, sys_settimeofday), // 79
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_getgroups, sys_getgroups16), // 80
|
|
+//ZZ LINX_(__NR_setgroups, sys_setgroups16), // 81
|
|
+//ZZ // PLAX_(__NR_select, old_select), // 82
|
|
+//ZZ GENX_(__NR_symlink, sys_symlink), // 83
|
|
+//ZZ //zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
|
|
+//ZZ //zz
|
|
+//ZZ GENX_(__NR_readlink, sys_readlink), // 85
|
|
+//ZZ //zz // (__NR_uselib, sys_uselib), // 86 */Linux
|
|
+//ZZ //zz // (__NR_swapon, sys_swapon), // 87 */Linux
|
|
+//ZZ //zz // (__NR_reboot, sys_reboot), // 88 */Linux
|
|
+//ZZ //zz // (__NR_readdir, old_readdir), // 89 -- superseded
|
|
+//ZZ //zz
|
|
+//ZZ // _____(__NR_mmap, old_mmap), // 90
|
|
+//ZZ GENXY(__NR_munmap, sys_munmap), // 91
|
|
+//ZZ GENX_(__NR_truncate, sys_truncate), // 92
|
|
+//ZZ GENX_(__NR_ftruncate, sys_ftruncate), // 93
|
|
+//ZZ GENX_(__NR_fchmod, sys_fchmod), // 94
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_fchown, sys_fchown16), // 95
|
|
+//ZZ GENX_(__NR_getpriority, sys_getpriority), // 96
|
|
+//ZZ GENX_(__NR_setpriority, sys_setpriority), // 97
|
|
+//ZZ // GENX_(__NR_profil, sys_ni_syscall), // 98
|
|
+//ZZ GENXY(__NR_statfs, sys_statfs), // 99
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_fstatfs, sys_fstatfs), // 100
|
|
+//ZZ // LINX_(__NR_ioperm, sys_ioperm), // 101
|
|
+//ZZ LINXY(__NR_socketcall, sys_socketcall), // 102
|
|
+//ZZ LINXY(__NR_syslog, sys_syslog), // 103
|
|
+//ZZ GENXY(__NR_setitimer, sys_setitimer), // 104
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_getitimer, sys_getitimer), // 105
|
|
+//ZZ GENXY(__NR_stat, sys_newstat), // 106
|
|
+//ZZ GENXY(__NR_lstat, sys_newlstat), // 107
|
|
+//ZZ GENXY(__NR_fstat, sys_newfstat), // 108
|
|
+//ZZ //zz // (__NR_olduname, sys_uname), // 109 -- obsolete
|
|
+//ZZ //zz
|
|
+//ZZ // GENX_(__NR_iopl, sys_iopl), // 110
|
|
+//ZZ LINX_(__NR_vhangup, sys_vhangup), // 111
|
|
+//ZZ // GENX_(__NR_idle, sys_ni_syscall), // 112
|
|
+//ZZ // PLAXY(__NR_vm86old, sys_vm86old), // 113 __NR_syscall... weird
|
|
+//ZZ //zz
|
|
+//ZZ //zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
|
|
+//ZZ LINXY(__NR_sysinfo, sys_sysinfo), // 116
|
|
+//ZZ // _____(__NR_ipc, sys_ipc), // 117
|
|
+//ZZ GENX_(__NR_fsync, sys_fsync), // 118
|
|
+//ZZ PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
|
|
+//ZZ
|
|
+//ZZ //zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
|
|
+//ZZ // PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
|
|
+//ZZ //zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
|
|
+//ZZ //zz
|
|
+//ZZ LINXY(__NR_sigprocmask, sys_sigprocmask), // 126
|
|
+//ZZ //zz // Nb: create_module() was removed 2.4-->2.6
|
|
+//ZZ // GENX_(__NR_create_module, sys_ni_syscall), // 127
|
|
+//ZZ LINX_(__NR_init_module, sys_init_module), // 128
|
|
+//ZZ LINX_(__NR_delete_module, sys_delete_module), // 129
|
|
+//ZZ //zz
|
|
+//ZZ //zz // Nb: get_kernel_syms() was removed 2.4-->2.6
|
|
+//ZZ // GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
|
|
+//ZZ LINX_(__NR_quotactl, sys_quotactl), // 131
|
|
+//ZZ GENX_(__NR_getpgid, sys_getpgid), // 132
|
|
+//ZZ GENX_(__NR_fchdir, sys_fchdir), // 133
|
|
+//ZZ //zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
|
|
+//ZZ //zz
|
|
+//ZZ //zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
|
|
+//ZZ LINX_(__NR_personality, sys_personality), // 136
|
|
+//ZZ // GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
|
|
+//ZZ LINX_(__NR_setfsuid, sys_setfsuid16), // 138
|
|
+//ZZ LINX_(__NR_setfsgid, sys_setfsgid16), // 139
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR__llseek, sys_llseek), // 140
|
|
+//ZZ GENXY(__NR_getdents, sys_getdents), // 141
|
|
+//ZZ GENX_(__NR__newselect, sys_select), // 142
|
|
+//ZZ GENX_(__NR_flock, sys_flock), // 143
|
|
+//ZZ GENX_(__NR_msync, sys_msync), // 144
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_readv, sys_readv), // 145
|
|
+//ZZ GENX_(__NR_getsid, sys_getsid), // 147
|
|
+//ZZ GENX_(__NR_fdatasync, sys_fdatasync), // 148
|
|
+//ZZ LINXY(__NR__sysctl, sys_sysctl), // 149
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_mlock, sys_mlock), // 150
|
|
+//ZZ GENX_(__NR_munlock, sys_munlock), // 151
|
|
+//ZZ GENX_(__NR_mlockall, sys_mlockall), // 152
|
|
+//ZZ LINX_(__NR_munlockall, sys_munlockall), // 153
|
|
+//ZZ LINXY(__NR_sched_setparam, sys_sched_setparam), // 154
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_sched_getparam, sys_sched_getparam), // 155
|
|
+//ZZ LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
|
|
+//ZZ LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
|
|
+//ZZ LINX_(__NR_sched_yield, sys_sched_yield), // 158
|
|
+//ZZ LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
|
|
+//ZZ //zz //LINX?(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
|
|
+//ZZ GENXY(__NR_nanosleep, sys_nanosleep), // 162
|
|
+//ZZ GENX_(__NR_mremap, sys_mremap), // 163
|
|
+//ZZ LINX_(__NR_setresuid, sys_setresuid16), // 164
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_getresuid, sys_getresuid16), // 165
|
|
+//ZZ // PLAXY(__NR_vm86, sys_vm86), // 166 x86/Linux-only
|
|
+//ZZ // GENX_(__NR_query_module, sys_ni_syscall), // 167
|
|
+//ZZ GENXY(__NR_poll, sys_poll), // 168
|
|
+//ZZ //zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
|
|
+//ZZ //zz
|
|
+//ZZ LINX_(__NR_setresgid, sys_setresgid16), // 170
|
|
+//ZZ LINXY(__NR_getresgid, sys_getresgid16), // 171
|
|
+//ZZ LINXY(__NR_prctl, sys_prctl), // 172
|
|
+//ZZ LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
|
|
+//ZZ LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
|
|
+//ZZ LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
|
|
+//ZZ LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_pread64, sys_pread64), // 180
|
|
+//ZZ GENX_(__NR_pwrite64, sys_pwrite64), // 181
|
|
+//ZZ LINX_(__NR_chown, sys_chown16), // 182
|
|
+//ZZ LINXY(__NR_capget, sys_capget), // 184
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_capset, sys_capset), // 185
|
|
+//ZZ GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
|
|
+//ZZ LINXY(__NR_sendfile, sys_sendfile), // 187
|
|
+//ZZ // GENXY(__NR_getpmsg, sys_getpmsg), // 188
|
|
+//ZZ // GENX_(__NR_putpmsg, sys_putpmsg), // 189
|
|
+//ZZ
|
|
+//ZZ // Nb: we treat vfork as fork
|
|
+//ZZ GENX_(__NR_vfork, sys_fork), // 190
|
|
+//ZZ GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
|
|
+//ZZ GENX_(__NR_truncate64, sys_truncate64), // 193
|
|
+//ZZ GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
|
|
+//ZZ
|
|
+//ZZ PLAXY(__NR_stat64, sys_stat64), // 195
|
|
+//ZZ PLAXY(__NR_lstat64, sys_lstat64), // 196
|
|
+//ZZ PLAXY(__NR_fstat64, sys_fstat64), // 197
|
|
+//ZZ GENX_(__NR_lchown32, sys_lchown), // 198
|
|
+//ZZ GENX_(__NR_getuid32, sys_getuid), // 199
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_getgid32, sys_getgid), // 200
|
|
+//ZZ GENX_(__NR_geteuid32, sys_geteuid), // 201
|
|
+//ZZ GENX_(__NR_getegid32, sys_getegid), // 202
|
|
+//ZZ GENX_(__NR_setreuid32, sys_setreuid), // 203
|
|
+//ZZ GENX_(__NR_setregid32, sys_setregid), // 204
|
|
+//ZZ
|
|
+//ZZ GENXY(__NR_getgroups32, sys_getgroups), // 205
|
|
+//ZZ GENX_(__NR_setgroups32, sys_setgroups), // 206
|
|
+//ZZ GENX_(__NR_fchown32, sys_fchown), // 207
|
|
+//ZZ LINX_(__NR_setresuid32, sys_setresuid), // 208
|
|
+//ZZ LINXY(__NR_getresuid32, sys_getresuid), // 209
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_setresgid32, sys_setresgid), // 210
|
|
+//ZZ LINXY(__NR_getresgid32, sys_getresgid), // 211
|
|
+//ZZ GENX_(__NR_chown32, sys_chown), // 212
|
|
+//ZZ GENX_(__NR_setuid32, sys_setuid), // 213
|
|
+//ZZ GENX_(__NR_setgid32, sys_setgid), // 214
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_setfsuid32, sys_setfsuid), // 215
|
|
+//ZZ LINX_(__NR_setfsgid32, sys_setfsgid), // 216
|
|
+//ZZ //zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
|
|
+//ZZ GENXY(__NR_mincore, sys_mincore), // 218
|
|
+//ZZ GENX_(__NR_madvise, sys_madvise), // 219
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_fcntl64, sys_fcntl64), // 221
|
|
+//ZZ // GENX_(222, sys_ni_syscall), // 222
|
|
+//ZZ // PLAXY(223, sys_syscall223), // 223 // sys_bproc?
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_readahead, sys_readahead), // 225 */Linux
|
|
+//ZZ LINX_(__NR_setxattr, sys_setxattr), // 226
|
|
+//ZZ LINX_(__NR_lsetxattr, sys_lsetxattr), // 227
|
|
+//ZZ LINX_(__NR_fsetxattr, sys_fsetxattr), // 228
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_fgetxattr, sys_fgetxattr), // 231
|
|
+//ZZ LINXY(__NR_listxattr, sys_listxattr), // 232
|
|
+//ZZ LINXY(__NR_llistxattr, sys_llistxattr), // 233
|
|
+//ZZ LINXY(__NR_flistxattr, sys_flistxattr), // 234
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_removexattr, sys_removexattr), // 235
|
|
+//ZZ LINX_(__NR_lremovexattr, sys_lremovexattr), // 236
|
|
+//ZZ LINX_(__NR_fremovexattr, sys_fremovexattr), // 237
|
|
+//ZZ LINXY(__NR_tkill, sys_tkill), // 238 */Linux
|
|
+//ZZ LINXY(__NR_sendfile64, sys_sendfile64), // 239
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_futex, sys_futex), // 240
|
|
+//ZZ LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
|
|
+//ZZ LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
|
|
+//ZZ // PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
|
|
+//ZZ // PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_io_setup, sys_io_setup), // 245
|
|
+//ZZ LINX_(__NR_io_destroy, sys_io_destroy), // 246
|
|
+//ZZ LINXY(__NR_io_getevents, sys_io_getevents), // 247
|
|
+//ZZ LINX_(__NR_io_submit, sys_io_submit), // 248
|
|
+//ZZ LINXY(__NR_io_cancel, sys_io_cancel), // 249
|
|
+//ZZ
|
|
+//ZZ // LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
|
|
+//ZZ GENX_(251, sys_ni_syscall), // 251
|
|
+//ZZ // GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
|
|
+//ZZ LINXY(__NR_epoll_create, sys_epoll_create), // 254
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
|
|
+//ZZ LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
|
|
+//ZZ //zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
|
|
+//ZZ LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
|
|
+//ZZ LINXY(__NR_timer_create, sys_timer_create), // 259
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
|
|
+//ZZ LINXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
|
|
+//ZZ LINX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
|
|
+//ZZ LINX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
|
|
+//ZZ LINX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
|
|
+//ZZ LINXY(__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
|
|
+//ZZ GENXY(__NR_statfs64, sys_statfs64), // 268
|
|
+//ZZ GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
|
|
+//ZZ
|
|
+//ZZ GENX_(__NR_utimes, sys_utimes), // 271
|
|
+//ZZ // LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
|
|
+//ZZ GENX_(__NR_vserver, sys_ni_syscall), // 273
|
|
+//ZZ LINX_(__NR_mbind, sys_mbind), // 274 ?/?
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
|
|
+//ZZ LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
|
|
+//ZZ LINXY(__NR_mq_open, sys_mq_open), // 277
|
|
+//ZZ LINX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
|
|
+//ZZ LINX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
|
|
+//ZZ LINX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
|
|
+//ZZ LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
|
|
+//ZZ LINXY(__NR_waitid, sys_waitid), // 280
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_bind, sys_bind), // 282
|
|
+//ZZ LINX_(__NR_listen, sys_listen), // 284
|
|
+//ZZ LINXY(__NR_accept, sys_accept), // 285
|
|
+//ZZ LINXY(__NR_getsockname, sys_getsockname), // 286
|
|
+//ZZ LINXY(__NR_getpeername, sys_getpeername), // 287
|
|
+//ZZ LINXY(__NR_socketpair, sys_socketpair), // 288
|
|
+//ZZ LINX_(__NR_send, sys_send),
|
|
+//ZZ LINX_(__NR_sendto, sys_sendto), // 290
|
|
+//ZZ LINXY(__NR_recv, sys_recv),
|
|
+//ZZ LINXY(__NR_recvfrom, sys_recvfrom), // 292
|
|
+//ZZ LINX_(__NR_shutdown, sys_shutdown), // 293
|
|
+//ZZ LINX_(__NR_setsockopt, sys_setsockopt), // 294
|
|
+//ZZ LINXY(__NR_getsockopt, sys_getsockopt), // 295
|
|
+//ZZ LINX_(__NR_sendmsg, sys_sendmsg), // 296
|
|
+//ZZ LINXY(__NR_recvmsg, sys_recvmsg), // 297
|
|
+//ZZ LINX_(__NR_semop, sys_semop), // 298
|
|
+//ZZ LINX_(__NR_semget, sys_semget), // 299
|
|
+//ZZ LINXY(__NR_semctl, sys_semctl), // 300
|
|
+//ZZ LINX_(__NR_msgget, sys_msgget),
|
|
+//ZZ LINX_(__NR_msgsnd, sys_msgsnd),
|
|
+//ZZ LINXY(__NR_msgrcv, sys_msgrcv),
|
|
+//ZZ LINXY(__NR_msgctl, sys_msgctl), // 304
|
|
+//ZZ LINX_(__NR_semtimedop, sys_semtimedop), // 312
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_add_key, sys_add_key), // 286
|
|
+//ZZ LINX_(__NR_request_key, sys_request_key), // 287
|
|
+//ZZ LINXY(__NR_keyctl, sys_keyctl), // not 288...
|
|
+//ZZ // LINX_(__NR_ioprio_set, sys_ioprio_set), // 289
|
|
+//ZZ
|
|
+//ZZ // LINX_(__NR_ioprio_get, sys_ioprio_get), // 290
|
|
+//ZZ LINX_(__NR_inotify_init, sys_inotify_init), // 291
|
|
+//ZZ LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
|
|
+//ZZ LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 293
|
|
+//ZZ // LINX_(__NR_migrate_pages, sys_migrate_pages), // 294
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_mknodat, sys_mknodat), // 297
|
|
+//ZZ LINX_(__NR_fchownat, sys_fchownat), // 298
|
|
+//ZZ LINX_(__NR_futimesat, sys_futimesat), // 326 on arm
|
|
+//ZZ
|
|
+//ZZ PLAXY(__NR_fstatat64, sys_fstatat64), // 300
|
|
+//ZZ LINX_(__NR_renameat, sys_renameat), // 302
|
|
+//ZZ LINX_(__NR_linkat, sys_linkat), // 303
|
|
+//ZZ LINX_(__NR_symlinkat, sys_symlinkat), // 304
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_fchmodat, sys_fchmodat), //
|
|
+//ZZ LINXY(__NR_shmat, wrap_sys_shmat), //305
|
|
+//ZZ LINXY(__NR_shmdt, sys_shmdt), //306
|
|
+//ZZ LINX_(__NR_shmget, sys_shmget), //307
|
|
+//ZZ LINXY(__NR_shmctl, sys_shmctl), // 308
|
|
+//ZZ // LINX_(__NR_pselect6, sys_pselect6), //
|
|
+//ZZ
|
|
+//ZZ // LINX_(__NR_unshare, sys_unshare), // 310
|
|
+//ZZ LINX_(__NR_set_robust_list, sys_set_robust_list), // 311
|
|
+//ZZ LINXY(__NR_get_robust_list, sys_get_robust_list), // 312
|
|
+//ZZ // LINX_(__NR_splice, sys_ni_syscall), // 313
|
|
+//ZZ // LINX_(__NR_sync_file_range, sys_sync_file_range), // 314
|
|
+//ZZ
|
|
+//ZZ // LINX_(__NR_tee, sys_ni_syscall), // 315
|
|
+//ZZ // LINX_(__NR_vmsplice, sys_ni_syscall), // 316
|
|
+//ZZ LINXY(__NR_move_pages, sys_move_pages), // 317
|
|
+//ZZ // LINX_(__NR_getcpu, sys_ni_syscall), // 318
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_utimensat, sys_utimensat), // 320
|
|
+//ZZ LINXY(__NR_signalfd, sys_signalfd), // 321
|
|
+//ZZ LINXY(__NR_timerfd_create, sys_timerfd_create), // 322
|
|
+//ZZ LINX_(__NR_eventfd, sys_eventfd), // 323
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_timerfd_settime, sys_timerfd_settime), // 325
|
|
+//ZZ LINXY(__NR_timerfd_gettime, sys_timerfd_gettime), // 326
|
|
+//ZZ
|
|
+//ZZ ///////////////
|
|
+//ZZ
|
|
+//ZZ // JRS 2010-Jan-03: I believe that all the numbers listed
|
|
+//ZZ // in comments in the table prior to this point (eg "// 326",
|
|
+//ZZ // etc) are bogus since it looks to me like they are copied
|
|
+//ZZ // verbatim from syswrap-x86-linux.c and they certainly do not
|
|
+//ZZ // correspond to what's in include/vki/vki-scnums-arm-linux.h.
|
|
+//ZZ // From here onwards, please ensure the numbers are correct.
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_pselect6, sys_pselect6), // 335
|
|
+//ZZ LINXY(__NR_ppoll, sys_ppoll), // 336
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 346
|
|
+//ZZ
|
|
+//ZZ LINX_(__NR_fallocate, sys_fallocate), // 352
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_signalfd4, sys_signalfd4), // 355
|
|
+//ZZ LINX_(__NR_eventfd2, sys_eventfd2), // 356
|
|
+//ZZ LINXY(__NR_epoll_create1, sys_epoll_create1), // 357
|
|
+//ZZ LINXY(__NR_inotify_init1, sys_inotify_init1), // 360
|
|
+//ZZ LINXY(__NR_preadv, sys_preadv), // 361
|
|
+//ZZ LINX_(__NR_pwritev, sys_pwritev), // 362
|
|
+//ZZ LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 363
|
|
+//ZZ LINXY(__NR_perf_event_open, sys_perf_event_open), // 364
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_accept4, sys_accept4), // 366
|
|
+//ZZ
|
|
+//ZZ LINXY(__NR_name_to_handle_at, sys_name_to_handle_at),// 370
|
|
+//ZZ LINXY(__NR_open_by_handle_at, sys_open_by_handle_at) // 371
|
|
+};
|
|
+
|
|
+
|
|
+//ZZ /* These are not in the main table because there indexes are not small
|
|
+//ZZ integers, but rather values close to one million. So their
|
|
+//ZZ inclusion would force the main table to be huge (about 8 MB). */
|
|
+//ZZ
|
|
+//ZZ static SyscallTableEntry ste___ARM_set_tls
|
|
+//ZZ = { WRAPPER_PRE_NAME(arm_linux,sys_set_tls), NULL };
|
|
+//ZZ
|
|
+//ZZ static SyscallTableEntry ste___ARM_cacheflush
|
|
+//ZZ = { WRAPPER_PRE_NAME(arm_linux,sys_cacheflush), NULL };
|
|
+
|
|
+SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
|
|
+{
|
|
+ const UInt syscall_main_table_size
|
|
+ = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]);
|
|
+
|
|
+ /* Is it in the contiguous initial section of the table? */
|
|
+ if (sysno < syscall_main_table_size) {
|
|
+ SyscallTableEntry* sys = &syscall_main_table[sysno];
|
|
+ if (sys->before == NULL)
|
|
+ return NULL; /* no entry */
|
|
+ else
|
|
+ return sys;
|
|
+ }
|
|
+
|
|
+//ZZ /* Check if it's one of the out-of-line entries. */
|
|
+//ZZ switch (sysno) {
|
|
+//ZZ case __NR_ARM_set_tls: return &ste___ARM_set_tls;
|
|
+//ZZ case __NR_ARM_cacheflush: return &ste___ARM_cacheflush;
|
|
+//ZZ default: break;
|
|
+//ZZ }
|
|
+
|
|
+ /* Can't find a wrapper */
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+#endif // defined(VGP_arm64_linux)
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end syswrap-arm64-linux.c ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: coregrind/m_syswrap/syscall-arm-linux.S
|
|
===================================================================
|
|
--- coregrind/m_syswrap/syscall-arm-linux.S.orig
|
|
+++ coregrind/m_syswrap/syscall-arm-linux.S
|
|
@@ -112,7 +112,7 @@ ML_(do_syscall_for_client_WRK):
|
|
ldr r3, [sp, #32] /* nsigwords */
|
|
svc 0x00000000
|
|
|
|
- cmp r0, #0
|
|
+ cmp r0, #0
|
|
blt 7f
|
|
add sp, sp, #4 /* r0 contains return value */
|
|
|
|
Index: coregrind/m_syswrap/syswrap-linux.c
|
|
===================================================================
|
|
--- coregrind/m_syswrap/syswrap-linux.c.orig
|
|
+++ coregrind/m_syswrap/syswrap-linux.c
|
|
@@ -209,6 +209,8 @@ static void run_a_thread_NORETURN ( Word
|
|
/* This releases the run lock */
|
|
VG_(exit_thread)(tid);
|
|
vg_assert(tst->status == VgTs_Zombie);
|
|
+ vg_assert(sizeof(tst->status) == 4);
|
|
+ vg_assert(sizeof(tst->os_state.exitcode) == sizeof(Word));
|
|
|
|
INNER_REQUEST (VALGRIND_STACK_DEREGISTER (registered_vgstack_id));
|
|
|
|
@@ -264,6 +266,16 @@ static void run_a_thread_NORETURN ( Word
|
|
: "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
|
|
: "r0", "r7"
|
|
);
|
|
+#elif defined(VGP_arm64_linux)
|
|
+ asm volatile (
|
|
+ "str %w1, %0\n" /* set tst->status = VgTs_Empty (32-bit store) */
|
|
+ "mov x8, %2\n" /* set %r7 = __NR_exit */
|
|
+ "ldr x0, %3\n" /* set %r0 = tst->os_state.exitcode */
|
|
+ "svc 0x00000000\n" /* exit(tst->os_state.exitcode) */
|
|
+ : "=m" (tst->status)
|
|
+ : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
|
|
+ : "r0", "r7"
|
|
+ );
|
|
#elif defined(VGP_s390x_linux)
|
|
asm volatile (
|
|
"st %1, %0\n" /* set tst->status = VgTs_Empty */
|
|
@@ -276,7 +288,7 @@ static void run_a_thread_NORETURN ( Word
|
|
#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
|
|
asm volatile (
|
|
"sw %1, %0\n\t" /* set tst->status = VgTs_Empty */
|
|
- "li $2, %2\n\t" /* set v0 = __NR_exit */
|
|
+ "li $2, %2\n\t" /* set v0 = __NR_exit */
|
|
"lw $4, %3\n\t" /* set a0 = tst->os_state.exitcode */
|
|
"syscall\n\t" /* exit(tst->os_state.exitcode) */
|
|
"nop"
|
|
@@ -428,7 +440,7 @@ SysRes ML_(do_fork_clone) ( ThreadId tid
|
|
#if defined(VGP_x86_linux) \
|
|
|| defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
|
|
|| defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
res = VG_(do_syscall5)( __NR_clone, flags,
|
|
(UWord)NULL, (UWord)parent_tidptr,
|
|
(UWord)NULL, (UWord)child_tidptr );
|
|
Index: coregrind/m_syswrap/priv_types_n_macros.h
|
|
===================================================================
|
|
--- coregrind/m_syswrap/priv_types_n_macros.h.orig
|
|
+++ coregrind/m_syswrap/priv_types_n_macros.h
|
|
@@ -92,7 +92,7 @@ typedef
|
|
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|
|
|| defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
|
|
|| defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
|
|
- || defined(VGP_mips64_linux)
|
|
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
|
|
Int o_arg1;
|
|
Int o_arg2;
|
|
Int o_arg3;
|
|
Index: coregrind/m_debuglog.c
|
|
===================================================================
|
|
--- coregrind/m_debuglog.c.orig
|
|
+++ coregrind/m_debuglog.c
|
|
@@ -103,6 +103,7 @@ static UInt local_sys_getpid ( void )
|
|
}
|
|
|
|
#elif defined(VGP_amd64_linux)
|
|
+
|
|
__attribute__((noinline))
|
|
static UInt local_sys_write_stderr ( const HChar* buf, Int n )
|
|
{
|
|
@@ -267,6 +268,42 @@ static UInt local_sys_getpid ( void )
|
|
return __res;
|
|
}
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+
|
|
+static UInt local_sys_write_stderr ( const HChar* buf, Int n )
|
|
+{
|
|
+ volatile ULong block[2];
|
|
+ block[0] = (ULong)buf;
|
|
+ block[1] = (ULong)n;
|
|
+ __asm__ volatile (
|
|
+ "mov x0, #2\n\t" /* stderr */
|
|
+ "ldr x1, [%0]\n\t" /* buf */
|
|
+ "ldr x2, [%0, #8]\n\t" /* n */
|
|
+ "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
|
|
+ "svc 0x0\n" /* write() */
|
|
+ "str x0, [%0]\n\t"
|
|
+ :
|
|
+ : "r" (block)
|
|
+ : "x0","x1","x2","x7"
|
|
+ );
|
|
+ if (block[0] < 0)
|
|
+ block[0] = -1;
|
|
+ return (UInt)block[0];
|
|
+}
|
|
+
|
|
+static UInt local_sys_getpid ( void )
|
|
+{
|
|
+ UInt __res;
|
|
+ __asm__ volatile (
|
|
+ "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
|
|
+ "svc 0x0\n" /* getpid() */
|
|
+ "mov %0, x0\n"
|
|
+ : "=r" (__res)
|
|
+ :
|
|
+ : "x0", "x8" );
|
|
+ return (UInt)__res;
|
|
+}
|
|
+
|
|
#elif defined(VGP_x86_darwin)
|
|
|
|
/* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
|
|
@@ -350,6 +387,7 @@ static UInt local_sys_getpid ( void )
|
|
}
|
|
|
|
#elif defined(VGP_s390x_linux)
|
|
+
|
|
static UInt local_sys_write_stderr ( const HChar* buf, Int n )
|
|
{
|
|
register Int r2 asm("2") = 2; /* file descriptor STDERR */
|
|
@@ -391,6 +429,7 @@ static UInt local_sys_getpid ( void )
|
|
}
|
|
|
|
#elif defined(VGP_mips32_linux)
|
|
+
|
|
static UInt local_sys_write_stderr ( const HChar* buf, Int n )
|
|
{
|
|
volatile Int block[2];
|
|
@@ -428,6 +467,7 @@ static UInt local_sys_getpid ( void )
|
|
}
|
|
|
|
#elif defined(VGP_mips64_linux)
|
|
+
|
|
static UInt local_sys_write_stderr ( const HChar* buf, Int n )
|
|
{
|
|
volatile Long block[2];
|
|
Index: coregrind/m_vki.c
|
|
===================================================================
|
|
--- coregrind/m_vki.c.orig
|
|
+++ coregrind/m_vki.c
|
|
@@ -42,7 +42,8 @@
|
|
/* ppc32/64-linux determines page size at startup, hence m_vki is
|
|
the logical place to store that info. */
|
|
|
|
-#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
|
|
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
|
|
+ || defined(VGP_arm64_linux)
|
|
unsigned long VKI_PAGE_SHIFT = 12;
|
|
unsigned long VKI_PAGE_SIZE = 1UL << 12;
|
|
#endif
|
|
Index: coregrind/m_options.c
|
|
===================================================================
|
|
--- coregrind/m_options.c.orig
|
|
+++ coregrind/m_options.c
|
|
@@ -48,7 +48,8 @@ Bool VG_(clo_error_limit) = True;
|
|
Int VG_(clo_error_exitcode) = 0;
|
|
|
|
#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
|
|
- || defined(VGPV_mips32_linux_android)
|
|
+ || defined(VGPV_mips32_linux_android) \
|
|
+ || defined(VGP_arm64_linux) // temporarily disabled on arm64-linux
|
|
VgVgdb VG_(clo_vgdb) = Vg_VgdbNo; // currently disabled on Android
|
|
#else
|
|
VgVgdb VG_(clo_vgdb) = Vg_VgdbYes;
|
|
Index: coregrind/m_scheduler/scheduler.c
|
|
===================================================================
|
|
--- coregrind/m_scheduler/scheduler.c.orig
|
|
+++ coregrind/m_scheduler/scheduler.c
|
|
@@ -790,12 +790,21 @@ static void do_pre_run_checks ( ThreadSt
|
|
vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_D1));
|
|
# endif
|
|
|
|
+# if defined(VGA_arm64)
|
|
+ vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex.guest_X0));
|
|
+ vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_X0));
|
|
+ vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_X0));
|
|
+ vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_Q0));
|
|
+ vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_Q0));
|
|
+ vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_Q0));
|
|
+# endif
|
|
+
|
|
# if defined(VGA_s390x)
|
|
/* no special requirements */
|
|
# endif
|
|
|
|
# if defined(VGA_mips32) || defined(VGA_mips64)
|
|
- /* no special requirements */
|
|
+ /* no special requirements */
|
|
# endif
|
|
}
|
|
|
|
@@ -1598,6 +1607,9 @@ void VG_(nuke_all_threads_except) ( Thre
|
|
#elif defined(VGA_arm)
|
|
# define VG_CLREQ_ARGS guest_R4
|
|
# define VG_CLREQ_RET guest_R3
|
|
+#elif defined(VGA_arm64)
|
|
+# define VG_CLREQ_ARGS guest_X4
|
|
+# define VG_CLREQ_RET guest_X3
|
|
#elif defined (VGA_s390x)
|
|
# define VG_CLREQ_ARGS guest_r2
|
|
# define VG_CLREQ_RET guest_r3
|
|
Index: coregrind/m_gdbserver/target.c
|
|
===================================================================
|
|
--- coregrind/m_gdbserver/target.c.orig
|
|
+++ coregrind/m_gdbserver/target.c
|
|
@@ -641,6 +641,8 @@ void valgrind_initialize_target(void)
|
|
amd64_init_architecture(&the_low_target);
|
|
#elif defined(VGA_arm)
|
|
arm_init_architecture(&the_low_target);
|
|
+#elif defined(VGA_arm64)
|
|
+ arm_init_architecture(&the_low_target);
|
|
#elif defined(VGA_ppc32)
|
|
ppc32_init_architecture(&the_low_target);
|
|
#elif defined(VGA_ppc64)
|
|
@@ -652,6 +654,6 @@ void valgrind_initialize_target(void)
|
|
#elif defined(VGA_mips64)
|
|
mips64_init_architecture(&the_low_target);
|
|
#else
|
|
- architecture missing in target.c valgrind_initialize_target
|
|
+ #error "architecture missing in target.c valgrind_initialize_target"
|
|
#endif
|
|
}
|
|
Index: coregrind/m_gdbserver/valgrind_low.h
|
|
===================================================================
|
|
--- coregrind/m_gdbserver/valgrind_low.h.orig
|
|
+++ coregrind/m_gdbserver/valgrind_low.h
|
|
@@ -73,6 +73,7 @@ struct valgrind_target_ops
|
|
extern void x86_init_architecture (struct valgrind_target_ops *target);
|
|
extern void amd64_init_architecture (struct valgrind_target_ops *target);
|
|
extern void arm_init_architecture (struct valgrind_target_ops *target);
|
|
+extern void arm64_init_architecture (struct valgrind_target_ops *target);
|
|
extern void ppc32_init_architecture (struct valgrind_target_ops *target);
|
|
extern void ppc64_init_architecture (struct valgrind_target_ops *target);
|
|
extern void s390x_init_architecture (struct valgrind_target_ops *target);
|
|
Index: coregrind/m_gdbserver/valgrind-low-arm64.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ coregrind/m_gdbserver/valgrind-low-arm64.c
|
|
@@ -0,0 +1,307 @@
|
|
+/* Low level interface to valgrind, for the remote server for GDB integrated
|
|
+ in valgrind.
|
|
+ Copyright (C) 2011
|
|
+ Free Software Foundation, Inc.
|
|
+
|
|
+ This file is part of VALGRIND.
|
|
+ It has been inspired from a file from gdbserver in gdb 6.6.
|
|
+
|
|
+ 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., 51 Franklin Street, Fifth Floor,
|
|
+ Boston, MA 02110-1301, USA. */
|
|
+
|
|
+#include "server.h"
|
|
+#include "target.h"
|
|
+#include "regdef.h"
|
|
+#include "regcache.h"
|
|
+
|
|
+#include "pub_core_aspacemgr.h"
|
|
+#include "pub_tool_machine.h"
|
|
+#include "pub_core_threadstate.h"
|
|
+#include "pub_core_transtab.h"
|
|
+#include "pub_core_gdbserver.h"
|
|
+#include "pub_core_debuginfo.h"
|
|
+
|
|
+#include "valgrind_low.h"
|
|
+
|
|
+#include "libvex_guest_arm64.h"
|
|
+
|
|
+//ZZ static struct reg regs[] = {
|
|
+//ZZ { "r0", 0, 32 },
|
|
+//ZZ { "r1", 32, 32 },
|
|
+//ZZ { "r2", 64, 32 },
|
|
+//ZZ { "r3", 96, 32 },
|
|
+//ZZ { "r4", 128, 32 },
|
|
+//ZZ { "r5", 160, 32 },
|
|
+//ZZ { "r6", 192, 32 },
|
|
+//ZZ { "r7", 224, 32 },
|
|
+//ZZ { "r8", 256, 32 },
|
|
+//ZZ { "r9", 288, 32 },
|
|
+//ZZ { "r10", 320, 32 },
|
|
+//ZZ { "r11", 352, 32 },
|
|
+//ZZ { "r12", 384, 32 },
|
|
+//ZZ { "sp", 416, 32 },
|
|
+//ZZ { "lr", 448, 32 },
|
|
+//ZZ { "pc", 480, 32 },
|
|
+//ZZ { "", 512, 0 }, // It seems these entries are needed
|
|
+//ZZ { "", 512, 0 }, // as previous versions of arm <-> gdb placed
|
|
+//ZZ { "", 512, 0 }, // some floating point registers here. So, cpsr
|
|
+//ZZ { "", 512, 0 }, // must be register 25.
|
|
+//ZZ { "", 512, 0 },
|
|
+//ZZ { "", 512, 0 },
|
|
+//ZZ { "", 512, 0 },
|
|
+//ZZ { "", 512, 0 },
|
|
+//ZZ { "", 512, 0 },
|
|
+//ZZ { "cpsr", 512, 32 },
|
|
+//ZZ { "d0", 544, 64 },
|
|
+//ZZ { "d1", 608, 64 },
|
|
+//ZZ { "d2", 672, 64 },
|
|
+//ZZ { "d3", 736, 64 },
|
|
+//ZZ { "d4", 800, 64 },
|
|
+//ZZ { "d5", 864, 64 },
|
|
+//ZZ { "d6", 928, 64 },
|
|
+//ZZ { "d7", 992, 64 },
|
|
+//ZZ { "d8", 1056, 64 },
|
|
+//ZZ { "d9", 1120, 64 },
|
|
+//ZZ { "d10", 1184, 64 },
|
|
+//ZZ { "d11", 1248, 64 },
|
|
+//ZZ { "d12", 1312, 64 },
|
|
+//ZZ { "d13", 1376, 64 },
|
|
+//ZZ { "d14", 1440, 64 },
|
|
+//ZZ { "d15", 1504, 64 },
|
|
+//ZZ { "d16", 1568, 64 },
|
|
+//ZZ { "d17", 1632, 64 },
|
|
+//ZZ { "d18", 1696, 64 },
|
|
+//ZZ { "d19", 1760, 64 },
|
|
+//ZZ { "d20", 1824, 64 },
|
|
+//ZZ { "d21", 1888, 64 },
|
|
+//ZZ { "d22", 1952, 64 },
|
|
+//ZZ { "d23", 2016, 64 },
|
|
+//ZZ { "d24", 2080, 64 },
|
|
+//ZZ { "d25", 2144, 64 },
|
|
+//ZZ { "d26", 2208, 64 },
|
|
+//ZZ { "d27", 2272, 64 },
|
|
+//ZZ { "d28", 2336, 64 },
|
|
+//ZZ { "d29", 2400, 64 },
|
|
+//ZZ { "d30", 2464, 64 },
|
|
+//ZZ { "d31", 2528, 64 },
|
|
+//ZZ { "fpscr", 2592, 32 }
|
|
+//ZZ };
|
|
+//ZZ static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
|
|
+//ZZ #define num_regs (sizeof (regs) / sizeof (regs[0]))
|
|
+//ZZ
|
|
+//ZZ static
|
|
+//ZZ CORE_ADDR get_pc (void)
|
|
+//ZZ {
|
|
+//ZZ unsigned long pc;
|
|
+//ZZ
|
|
+//ZZ collect_register_by_name ("pc", &pc);
|
|
+//ZZ
|
|
+//ZZ dlog(1, "stop pc is %p\n", (void *) pc);
|
|
+//ZZ return pc;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ static
|
|
+//ZZ void set_pc (CORE_ADDR newpc)
|
|
+//ZZ {
|
|
+//ZZ Bool mod;
|
|
+//ZZ supply_register_by_name ("pc", &newpc, &mod);
|
|
+//ZZ if (mod)
|
|
+//ZZ dlog(1, "set pc to %p\n", C2v (newpc));
|
|
+//ZZ else
|
|
+//ZZ dlog(1, "set pc not changed %p\n", C2v (newpc));
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ Addr thumb_pc (Addr pc)
|
|
+//ZZ {
|
|
+//ZZ // If the thumb bit (bit 0) is already set, we trust it.
|
|
+//ZZ if (pc & 1) {
|
|
+//ZZ dlog (1, "%p = thumb (bit0 is set)\n", C2v (pc));
|
|
+//ZZ return pc;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ // Here, bit 0 is not set.
|
|
+//ZZ // For a pc aligned on 4 bytes, we have to use the debug
|
|
+//ZZ // info to determine the thumb-ness.
|
|
+//ZZ // else (aligned on 2 bytes), we trust this is a thumb
|
|
+//ZZ // address and we set the thumb bit.
|
|
+//ZZ
|
|
+//ZZ if (pc & 2) {
|
|
+//ZZ dlog (1, "bit0 not set, bit1 set => %p = thumb\n", C2v (pc));
|
|
+//ZZ return pc | 1;
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ // pc aligned on 4 bytes. We need to use debug info.
|
|
+//ZZ {
|
|
+//ZZ HChar fnname[200]; // ??? max size
|
|
+//ZZ Addr entrypoint;
|
|
+//ZZ Addr ptoc; // unused but needed.
|
|
+//ZZ // If this is a thumb instruction, we need to ask
|
|
+//ZZ // the debug info with the bit0 set
|
|
+//ZZ // (why can't debug info do that for us ???)
|
|
+//ZZ // (why if this is a 4 bytes thumb instruction ???)
|
|
+//ZZ if (VG_(get_fnname_raw) (pc | 1, fnname, 200)) {
|
|
+//ZZ if (VG_(lookup_symbol_SLOW)( "*", fnname, &entrypoint, &ptoc )) {
|
|
+//ZZ dlog (1, "fnname %s lookupsym %p => %p %s.\n",
|
|
+//ZZ fnname, C2v(entrypoint), C2v(pc),
|
|
+//ZZ (entrypoint & 1 ? "thumb" : "arm"));
|
|
+//ZZ if (entrypoint & 1)
|
|
+//ZZ return pc | 1;
|
|
+//ZZ else
|
|
+//ZZ return pc;
|
|
+//ZZ
|
|
+//ZZ } else {
|
|
+//ZZ dlog (1, "%p fnname %s lookupsym failed?. Assume arm\n",
|
|
+//ZZ C2v (pc), fnname);
|
|
+//ZZ return pc;
|
|
+//ZZ }
|
|
+//ZZ } else {
|
|
+//ZZ // Can't find function name. We assume this is arm
|
|
+//ZZ dlog (1, "%p unknown fnname?. Assume arm\n", C2v (pc));
|
|
+//ZZ return pc;
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ /* store registers in the guest state (gdbserver_to_valgrind)
|
|
+//ZZ or fetch register from the guest state (valgrind_to_gdbserver). */
|
|
+//ZZ static
|
|
+//ZZ void transfer_register (ThreadId tid, int abs_regno, void * buf,
|
|
+//ZZ transfer_direction dir, int size, Bool *mod)
|
|
+//ZZ {
|
|
+//ZZ ThreadState* tst = VG_(get_ThreadState)(tid);
|
|
+//ZZ int set = abs_regno / num_regs;
|
|
+//ZZ int regno = abs_regno % num_regs;
|
|
+//ZZ *mod = False;
|
|
+//ZZ
|
|
+//ZZ VexGuestARMState* arm = (VexGuestARMState*) get_arch (set, tst);
|
|
+//ZZ
|
|
+//ZZ switch (regno) {
|
|
+//ZZ // numbers here have to match the order of regs above
|
|
+//ZZ // Attention: gdb order does not match valgrind order.
|
|
+//ZZ case 0: VG_(transfer) (&arm->guest_R0, buf, dir, size, mod); break;
|
|
+//ZZ case 1: VG_(transfer) (&arm->guest_R1, buf, dir, size, mod); break;
|
|
+//ZZ case 2: VG_(transfer) (&arm->guest_R2, buf, dir, size, mod); break;
|
|
+//ZZ case 3: VG_(transfer) (&arm->guest_R3, buf, dir, size, mod); break;
|
|
+//ZZ case 4: VG_(transfer) (&arm->guest_R4, buf, dir, size, mod); break;
|
|
+//ZZ case 5: VG_(transfer) (&arm->guest_R5, buf, dir, size, mod); break;
|
|
+//ZZ case 6: VG_(transfer) (&arm->guest_R6, buf, dir, size, mod); break;
|
|
+//ZZ case 7: VG_(transfer) (&arm->guest_R7, buf, dir, size, mod); break;
|
|
+//ZZ case 8: VG_(transfer) (&arm->guest_R8, buf, dir, size, mod); break;
|
|
+//ZZ case 9: VG_(transfer) (&arm->guest_R9, buf, dir, size, mod); break;
|
|
+//ZZ case 10: VG_(transfer) (&arm->guest_R10, buf, dir, size, mod); break;
|
|
+//ZZ case 11: VG_(transfer) (&arm->guest_R11, buf, dir, size, mod); break;
|
|
+//ZZ case 12: VG_(transfer) (&arm->guest_R12, buf, dir, size, mod); break;
|
|
+//ZZ case 13: VG_(transfer) (&arm->guest_R13, buf, dir, size, mod); break;
|
|
+//ZZ case 14: VG_(transfer) (&arm->guest_R14, buf, dir, size, mod); break;
|
|
+//ZZ case 15: {
|
|
+//ZZ VG_(transfer) (&arm->guest_R15T, buf, dir, size, mod);
|
|
+//ZZ if (dir == gdbserver_to_valgrind && *mod) {
|
|
+//ZZ // If gdb is changing the PC, we have to set the thumb bit
|
|
+//ZZ // if needed.
|
|
+//ZZ arm->guest_R15T = thumb_pc(arm->guest_R15T);
|
|
+//ZZ }
|
|
+//ZZ break;
|
|
+//ZZ }
|
|
+//ZZ case 16:
|
|
+//ZZ case 17:
|
|
+//ZZ case 18:
|
|
+//ZZ case 19:
|
|
+//ZZ case 20: /* 9 "empty registers". See struct reg regs above. */
|
|
+//ZZ case 21:
|
|
+//ZZ case 22:
|
|
+//ZZ case 23:
|
|
+//ZZ case 24: *mod = False; break;
|
|
+//ZZ case 25: {
|
|
+//ZZ UInt cpsr = LibVEX_GuestARM_get_cpsr (arm);
|
|
+//ZZ if (dir == valgrind_to_gdbserver) {
|
|
+//ZZ VG_(transfer) (&cpsr, buf, dir, size, mod);
|
|
+//ZZ } else {
|
|
+//ZZ # if 0
|
|
+//ZZ UInt newcpsr;
|
|
+//ZZ VG_(transfer) (&newcpsr, buf, dir, size, mod);
|
|
+//ZZ *mod = newcpsr != cpsr;
|
|
+//ZZ // GDBTD ???? see FIXME in guest_arm_helpers.c
|
|
+//ZZ LibVEX_GuestARM_put_flags (newcpsr, arm);
|
|
+//ZZ # else
|
|
+//ZZ *mod = False;
|
|
+//ZZ # endif
|
|
+//ZZ }
|
|
+//ZZ break;
|
|
+//ZZ }
|
|
+//ZZ case 26: VG_(transfer) (&arm->guest_D0, buf, dir, size, mod); break;
|
|
+//ZZ case 27: VG_(transfer) (&arm->guest_D1, buf, dir, size, mod); break;
|
|
+//ZZ case 28: VG_(transfer) (&arm->guest_D2, buf, dir, size, mod); break;
|
|
+//ZZ case 29: VG_(transfer) (&arm->guest_D3, buf, dir, size, mod); break;
|
|
+//ZZ case 30: VG_(transfer) (&arm->guest_D4, buf, dir, size, mod); break;
|
|
+//ZZ case 31: VG_(transfer) (&arm->guest_D5, buf, dir, size, mod); break;
|
|
+//ZZ case 32: VG_(transfer) (&arm->guest_D6, buf, dir, size, mod); break;
|
|
+//ZZ case 33: VG_(transfer) (&arm->guest_D7, buf, dir, size, mod); break;
|
|
+//ZZ case 34: VG_(transfer) (&arm->guest_D8, buf, dir, size, mod); break;
|
|
+//ZZ case 35: VG_(transfer) (&arm->guest_D9, buf, dir, size, mod); break;
|
|
+//ZZ case 36: VG_(transfer) (&arm->guest_D10, buf, dir, size, mod); break;
|
|
+//ZZ case 37: VG_(transfer) (&arm->guest_D11, buf, dir, size, mod); break;
|
|
+//ZZ case 38: VG_(transfer) (&arm->guest_D12, buf, dir, size, mod); break;
|
|
+//ZZ case 39: VG_(transfer) (&arm->guest_D13, buf, dir, size, mod); break;
|
|
+//ZZ case 40: VG_(transfer) (&arm->guest_D14, buf, dir, size, mod); break;
|
|
+//ZZ case 41: VG_(transfer) (&arm->guest_D15, buf, dir, size, mod); break;
|
|
+//ZZ case 42: VG_(transfer) (&arm->guest_D16, buf, dir, size, mod); break;
|
|
+//ZZ case 43: VG_(transfer) (&arm->guest_D17, buf, dir, size, mod); break;
|
|
+//ZZ case 44: VG_(transfer) (&arm->guest_D18, buf, dir, size, mod); break;
|
|
+//ZZ case 45: VG_(transfer) (&arm->guest_D19, buf, dir, size, mod); break;
|
|
+//ZZ case 46: VG_(transfer) (&arm->guest_D20, buf, dir, size, mod); break;
|
|
+//ZZ case 47: VG_(transfer) (&arm->guest_D21, buf, dir, size, mod); break;
|
|
+//ZZ case 48: VG_(transfer) (&arm->guest_D22, buf, dir, size, mod); break;
|
|
+//ZZ case 49: VG_(transfer) (&arm->guest_D23, buf, dir, size, mod); break;
|
|
+//ZZ case 50: VG_(transfer) (&arm->guest_D24, buf, dir, size, mod); break;
|
|
+//ZZ case 51: VG_(transfer) (&arm->guest_D25, buf, dir, size, mod); break;
|
|
+//ZZ case 52: VG_(transfer) (&arm->guest_D26, buf, dir, size, mod); break;
|
|
+//ZZ case 53: VG_(transfer) (&arm->guest_D27, buf, dir, size, mod); break;
|
|
+//ZZ case 54: VG_(transfer) (&arm->guest_D28, buf, dir, size, mod); break;
|
|
+//ZZ case 55: VG_(transfer) (&arm->guest_D29, buf, dir, size, mod); break;
|
|
+//ZZ case 56: VG_(transfer) (&arm->guest_D30, buf, dir, size, mod); break;
|
|
+//ZZ case 57: VG_(transfer) (&arm->guest_D31, buf, dir, size, mod); break;
|
|
+//ZZ case 58: VG_(transfer) (&arm->guest_FPSCR, buf, dir, size, mod); break;
|
|
+//ZZ default: vg_assert(0);
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ static
|
|
+//ZZ const char* target_xml (Bool shadow_mode)
|
|
+//ZZ {
|
|
+//ZZ if (shadow_mode) {
|
|
+//ZZ return "arm-with-vfpv3-valgrind.xml";
|
|
+//ZZ } else {
|
|
+//ZZ return "arm-with-vfpv3.xml";
|
|
+//ZZ }
|
|
+//ZZ }
|
|
+//ZZ
|
|
+//ZZ static struct valgrind_target_ops low_target = {
|
|
+//ZZ num_regs,
|
|
+//ZZ regs,
|
|
+//ZZ 13, //SP
|
|
+//ZZ transfer_register,
|
|
+//ZZ get_pc,
|
|
+//ZZ set_pc,
|
|
+//ZZ "arm",
|
|
+//ZZ target_xml
|
|
+//ZZ };
|
|
+
|
|
+void arm64_init_architecture (struct valgrind_target_ops *target)
|
|
+{
|
|
+ vg_assert(0); // IMPLEMENT ME
|
|
+ //ZZ *target = low_target;
|
|
+ //ZZ set_register_cache (regs, num_regs);
|
|
+ //ZZ gdbserver_expedite_regs = expedite_regs;
|
|
+}
|
|
Index: coregrind/pub_core_debuginfo.h
|
|
===================================================================
|
|
--- coregrind/pub_core_debuginfo.h.orig
|
|
+++ coregrind/pub_core_debuginfo.h
|
|
@@ -118,6 +118,10 @@ typedef
|
|
typedef
|
|
struct { Addr r15; Addr r14; Addr r13; Addr r12; Addr r11; Addr r7; }
|
|
D3UnwindRegs;
|
|
+#elif defined(VGA_arm64)
|
|
+typedef
|
|
+ struct { Addr pc; Addr sp; Addr lr; Addr fp; } /* PC, 31, 30, 29 */
|
|
+ D3UnwindRegs;
|
|
#elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
typedef
|
|
UChar /* should be void, but gcc complains at use points */
|
|
Index: coregrind/pub_core_basics.h
|
|
===================================================================
|
|
--- coregrind/pub_core_basics.h.orig
|
|
+++ coregrind/pub_core_basics.h
|
|
@@ -58,6 +58,8 @@
|
|
# include "libvex_guest_ppc64.h"
|
|
#elif defined(VGA_arm)
|
|
# include "libvex_guest_arm.h"
|
|
+#elif defined(VGA_arm64)
|
|
+# include "libvex_guest_arm64.h"
|
|
#elif defined(VGA_s390x)
|
|
# include "libvex_guest_s390x.h"
|
|
#elif defined(VGA_mips32)
|
|
@@ -109,6 +111,11 @@ typedef
|
|
UInt r7;
|
|
} ARM;
|
|
struct {
|
|
+ // FIXME ARM64 is this correct?
|
|
+ ULong x29; /* FP */
|
|
+ ULong x30; /* LR */
|
|
+ } ARM64;
|
|
+ struct {
|
|
ULong r_fp;
|
|
ULong r_lr;
|
|
} S390X;
|
|
Index: coregrind/Makefile.am
|
|
===================================================================
|
|
--- coregrind/Makefile.am.orig
|
|
+++ coregrind/Makefile.am
|
|
@@ -314,6 +314,7 @@ COREGRIND_SOURCES_COMMON = \
|
|
m_dispatch/dispatch-ppc32-linux.S \
|
|
m_dispatch/dispatch-ppc64-linux.S \
|
|
m_dispatch/dispatch-arm-linux.S \
|
|
+ m_dispatch/dispatch-arm64-linux.S \
|
|
m_dispatch/dispatch-s390x-linux.S \
|
|
m_dispatch/dispatch-mips32-linux.S \
|
|
m_dispatch/dispatch-mips64-linux.S \
|
|
@@ -330,6 +331,7 @@ COREGRIND_SOURCES_COMMON = \
|
|
m_gdbserver/valgrind-low-x86.c \
|
|
m_gdbserver/valgrind-low-amd64.c \
|
|
m_gdbserver/valgrind-low-arm.c \
|
|
+ m_gdbserver/valgrind-low-arm64.c \
|
|
m_gdbserver/valgrind-low-ppc32.c \
|
|
m_gdbserver/valgrind-low-ppc64.c \
|
|
m_gdbserver/valgrind-low-s390x.c \
|
|
@@ -353,6 +355,7 @@ COREGRIND_SOURCES_COMMON = \
|
|
m_sigframe/sigframe-ppc32-linux.c \
|
|
m_sigframe/sigframe-ppc64-linux.c \
|
|
m_sigframe/sigframe-arm-linux.c \
|
|
+ m_sigframe/sigframe-arm64-linux.c \
|
|
m_sigframe/sigframe-s390x-linux.c \
|
|
m_sigframe/sigframe-mips32-linux.c \
|
|
m_sigframe/sigframe-mips64-linux.c \
|
|
@@ -363,6 +366,7 @@ COREGRIND_SOURCES_COMMON = \
|
|
m_syswrap/syscall-ppc32-linux.S \
|
|
m_syswrap/syscall-ppc64-linux.S \
|
|
m_syswrap/syscall-arm-linux.S \
|
|
+ m_syswrap/syscall-arm64-linux.S \
|
|
m_syswrap/syscall-s390x-linux.S \
|
|
m_syswrap/syscall-mips32-linux.S \
|
|
m_syswrap/syscall-mips64-linux.S \
|
|
@@ -378,6 +382,7 @@ COREGRIND_SOURCES_COMMON = \
|
|
m_syswrap/syswrap-ppc32-linux.c \
|
|
m_syswrap/syswrap-ppc64-linux.c \
|
|
m_syswrap/syswrap-arm-linux.c \
|
|
+ m_syswrap/syswrap-arm64-linux.c \
|
|
m_syswrap/syswrap-s390x-linux.c \
|
|
m_syswrap/syswrap-mips32-linux.c \
|
|
m_syswrap/syswrap-mips64-linux.c \
|
|
Index: coregrind/m_sigframe/sigframe-arm64-linux.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ coregrind/m_sigframe/sigframe-arm64-linux.c
|
|
@@ -0,0 +1,337 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- Create/destroy signal delivery frames. ---*/
|
|
+/*--- sigframe-arm64-linux.c ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+#include "pub_core_basics.h"
|
|
+#include "pub_core_vki.h"
|
|
+//ZZ #include "pub_core_vkiscnums.h"
|
|
+#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
|
|
+#include "pub_core_threadstate.h"
|
|
+#include "pub_core_aspacemgr.h"
|
|
+#include "pub_core_libcbase.h"
|
|
+#include "pub_core_libcassert.h"
|
|
+#include "pub_core_libcprint.h"
|
|
+#include "pub_core_machine.h"
|
|
+#include "pub_core_options.h"
|
|
+#include "pub_core_sigframe.h"
|
|
+#include "pub_core_signals.h"
|
|
+#include "pub_core_tooliface.h"
|
|
+#include "pub_core_trampoline.h"
|
|
+//ZZ #include "pub_core_transtab.h" // VG_(discard_translations)
|
|
+
|
|
+
|
|
+/* This uses the hack of dumping the vex guest state along with both
|
|
+ shadows in the frame, and restoring it afterwards from there,
|
|
+ rather than pulling it out of the ucontext. That means that signal
|
|
+ handlers which modify the ucontext and then return, expecting their
|
|
+ modifications to take effect, will have those modifications
|
|
+ ignored. This could be fixed properly with an hour or so more
|
|
+ effort. */
|
|
+
|
|
+/* This also always does the 'has siginfo' behaviour whether or
|
|
+ not it is requested. */
|
|
+
|
|
+struct vg_sig_private {
|
|
+ UInt magicPI;
|
|
+ UInt sigNo_private;
|
|
+ VexGuestARM64State vex;
|
|
+ VexGuestARM64State vex_shadow1;
|
|
+ VexGuestARM64State vex_shadow2;
|
|
+};
|
|
+
|
|
+struct sigframe {
|
|
+ struct vki_ucontext uc;
|
|
+ unsigned long retcode[2];
|
|
+ struct vg_sig_private vp;
|
|
+};
|
|
+
|
|
+struct rt_sigframe {
|
|
+ vki_siginfo_t info;
|
|
+ struct sigframe sig;
|
|
+};
|
|
+
|
|
+static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
|
|
+{
|
|
+ ThreadId tid = tst->tid;
|
|
+ NSegment const* stackseg = NULL;
|
|
+
|
|
+ if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
|
|
+ stackseg = VG_(am_find_nsegment)(addr);
|
|
+ if (0 && stackseg)
|
|
+ VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
|
|
+ addr, stackseg->start, stackseg->end);
|
|
+ }
|
|
+
|
|
+ if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
|
|
+ VG_(message)(
|
|
+ Vg_UserMsg,
|
|
+ "Can't extend stack to %#lx during signal delivery for thread %d:",
|
|
+ addr, tid);
|
|
+ if (stackseg == NULL)
|
|
+ VG_(message)(Vg_UserMsg, " no stack segment");
|
|
+ else
|
|
+ VG_(message)(Vg_UserMsg, " too small or bad protection modes");
|
|
+
|
|
+ /* set SIGSEGV to default handler */
|
|
+ VG_(set_default_handler)(VKI_SIGSEGV);
|
|
+ VG_(synth_fault_mapping)(tid, addr);
|
|
+
|
|
+ /* The whole process should be about to die, since the default
|
|
+ action of SIGSEGV to kill the whole process. */
|
|
+ return False;
|
|
+ }
|
|
+
|
|
+ /* For tracking memory events, indicate the entire frame has been
|
|
+ allocated. */
|
|
+ VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
|
|
+ size + VG_STACK_REDZONE_SZB, tid );
|
|
+
|
|
+ return True;
|
|
+}
|
|
+
|
|
+static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
|
|
+ UWord trapno, UWord err, const vki_sigset_t *set,
|
|
+ struct vki_ucontext *uc)
|
|
+{
|
|
+
|
|
+ ThreadState *tst = VG_(get_ThreadState)(tid);
|
|
+ struct vki_sigcontext *sc = &uc->uc_mcontext;
|
|
+
|
|
+ VG_(memset)(uc, 0, sizeof(*uc));
|
|
+
|
|
+ uc->uc_flags = 0;
|
|
+ uc->uc_link = 0;
|
|
+ uc->uc_sigmask = *set;
|
|
+ uc->uc_stack = tst->altstack;
|
|
+
|
|
+# define SC2(reg) sc->regs[reg] = tst->arch.vex.guest_X##reg
|
|
+ SC2(0); SC2(1); SC2(2); SC2(3);
|
|
+ SC2(4); SC2(5); SC2(6); SC2(7);
|
|
+ SC2(8); SC2(9); SC2(10); SC2(11);
|
|
+ SC2(12); SC2(13); SC2(14); SC2(15);
|
|
+ SC2(16); SC2(17); SC2(18); SC2(19);
|
|
+ SC2(20); SC2(21); SC2(22); SC2(23);
|
|
+ SC2(24); SC2(25); SC2(26); SC2(27);
|
|
+ SC2(28); SC2(29); SC2(30);
|
|
+# undef SC2
|
|
+ sc->sp = tst->arch.vex.guest_SP;
|
|
+ sc->pc = tst->arch.vex.guest_PC;
|
|
+ sc->pstate = 0; /* slack .. could do better */
|
|
+
|
|
+ //sc->trap_no = trapno;
|
|
+ //sc->error_code = err;
|
|
+ sc->fault_address = (ULong)si->_sifields._sigfault._addr;
|
|
+}
|
|
+
|
|
+
|
|
+static void build_sigframe(ThreadState *tst,
|
|
+ struct sigframe *frame,
|
|
+ const vki_siginfo_t *siginfo,
|
|
+ const struct vki_ucontext *siguc,
|
|
+ void *handler, UInt flags,
|
|
+ const vki_sigset_t *mask,
|
|
+ void *restorer)
|
|
+{
|
|
+ UWord trapno;
|
|
+ UWord err;
|
|
+ Int sigNo = siginfo->si_signo;
|
|
+ struct vg_sig_private *priv = &frame->vp;
|
|
+
|
|
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
|
|
+ (Addr)frame, offsetof(struct sigframe, vp));
|
|
+
|
|
+ if (siguc) {
|
|
+ trapno = 0; //siguc->uc_mcontext.trap_no;
|
|
+ err = 0; //siguc->uc_mcontext.error_code;
|
|
+ } else {
|
|
+ trapno = 0;
|
|
+ err = 0;
|
|
+ }
|
|
+
|
|
+ synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
|
|
+
|
|
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
|
|
+ (Addr)frame, offsetof(struct sigframe, vp));
|
|
+
|
|
+ priv->magicPI = 0x31415927;
|
|
+ priv->sigNo_private = sigNo;
|
|
+ priv->vex = tst->arch.vex;
|
|
+ priv->vex_shadow1 = tst->arch.vex_shadow1;
|
|
+ priv->vex_shadow2 = tst->arch.vex_shadow2;
|
|
+}
|
|
+
|
|
+
|
|
+/* EXPORTED */
|
|
+void VG_(sigframe_create)( ThreadId tid,
|
|
+ Addr sp_top_of_frame,
|
|
+ const vki_siginfo_t *siginfo,
|
|
+ const struct vki_ucontext *siguc,
|
|
+ void *handler,
|
|
+ UInt flags,
|
|
+ const vki_sigset_t *mask,
|
|
+ void *restorer )
|
|
+{
|
|
+ ThreadState *tst;
|
|
+ Addr sp = sp_top_of_frame;
|
|
+ Int sigNo = siginfo->si_signo;
|
|
+ UInt size;
|
|
+
|
|
+ tst = VG_(get_ThreadState)(tid);
|
|
+
|
|
+ size = sizeof(struct rt_sigframe);
|
|
+
|
|
+ sp -= size;
|
|
+ sp = VG_ROUNDDN(sp, 16);
|
|
+
|
|
+ if (!extend(tst, sp, size))
|
|
+ return; // Give up. No idea if this is correct
|
|
+
|
|
+ struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
|
|
+
|
|
+ /* Track our writes to siginfo */
|
|
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, /* VVVVV */
|
|
+ "signal handler siginfo", (Addr)rsf,
|
|
+ offsetof(struct rt_sigframe, sig));
|
|
+
|
|
+ VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
|
|
+
|
|
+ if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
|
|
+ rsf->info._sifields._sigfault._addr
|
|
+ = (Addr*)(tst)->arch.vex.guest_PC;
|
|
+ }
|
|
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
|
|
+ (Addr)rsf, offsetof(struct rt_sigframe, sig));
|
|
+
|
|
+ build_sigframe(tst, &rsf->sig, siginfo, siguc,
|
|
+ handler, flags, mask, restorer);
|
|
+ tst->arch.vex.guest_X1 = (Addr)&rsf->info;
|
|
+ tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
|
|
+
|
|
+ VG_(set_SP)(tid, sp);
|
|
+ VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
|
|
+ sizeof(Addr));
|
|
+ tst->arch.vex.guest_X0 = sigNo;
|
|
+
|
|
+ if (flags & VKI_SA_RESTORER)
|
|
+ tst->arch.vex.guest_X30 = (Addr)restorer;
|
|
+ else
|
|
+ tst->arch.vex.guest_X30
|
|
+ = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
|
|
+
|
|
+ tst->arch.vex.guest_PC = (Addr)handler;
|
|
+}
|
|
+
|
|
+
|
|
+/*------------------------------------------------------------*/
|
|
+/*--- Destroying signal frames ---*/
|
|
+/*------------------------------------------------------------*/
|
|
+
|
|
+/* EXPORTED */
|
|
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
|
|
+{
|
|
+ ThreadState *tst;
|
|
+ struct vg_sig_private *priv;
|
|
+ Addr sp;
|
|
+ UInt frame_size;
|
|
+//ZZ struct vki_sigcontext *mc;
|
|
+ Int sigNo;
|
|
+ Bool has_siginfo = isRT;
|
|
+
|
|
+ vg_assert(VG_(is_valid_tid)(tid));
|
|
+ tst = VG_(get_ThreadState)(tid);
|
|
+ sp = tst->arch.vex.guest_SP;
|
|
+
|
|
+//ZZ if (has_siginfo) {
|
|
+ struct rt_sigframe *frame = (struct rt_sigframe *)sp;
|
|
+ frame_size = sizeof(*frame);
|
|
+ //mc = &frame->sig.uc.uc_mcontext;
|
|
+ priv = &frame->sig.vp;
|
|
+ vg_assert(priv->magicPI == 0x31415927);
|
|
+ tst->sig_mask = frame->sig.uc.uc_sigmask;
|
|
+//ZZ } else {
|
|
+//ZZ struct sigframe *frame = (struct sigframe *)sp;
|
|
+//ZZ frame_size = sizeof(*frame);
|
|
+//ZZ mc = &frame->uc.uc_mcontext;
|
|
+//ZZ priv = &frame->vp;
|
|
+//ZZ vg_assert(priv->magicPI == 0x31415927);
|
|
+//ZZ tst->sig_mask = frame->uc.uc_sigmask;
|
|
+//ZZ //VG_(printf)("Setting signmask to %08x%08x\n",
|
|
+//ZZ // tst->sig_mask[0],tst->sig_mask[1]);
|
|
+//ZZ }
|
|
+ tst->tmp_sig_mask = tst->sig_mask;
|
|
+
|
|
+ sigNo = priv->sigNo_private;
|
|
+
|
|
+//ZZ //XXX: restore regs
|
|
+//ZZ # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
|
|
+//ZZ REST(r0,R0);
|
|
+//ZZ REST(r1,R1);
|
|
+//ZZ REST(r2,R2);
|
|
+//ZZ REST(r3,R3);
|
|
+//ZZ REST(r4,R4);
|
|
+//ZZ REST(r5,R5);
|
|
+//ZZ REST(r6,R6);
|
|
+//ZZ REST(r7,R7);
|
|
+//ZZ REST(r8,R8);
|
|
+//ZZ REST(r9,R9);
|
|
+//ZZ REST(r10,R10);
|
|
+//ZZ REST(fp,R11);
|
|
+//ZZ REST(ip,R12);
|
|
+//ZZ REST(sp,R13);
|
|
+//ZZ REST(lr,R14);
|
|
+//ZZ REST(pc,R15T);
|
|
+//ZZ # undef REST
|
|
+
|
|
+ /* Uh, the next line makes all the REST() above pointless. */
|
|
+ tst->arch.vex = priv->vex;
|
|
+
|
|
+ tst->arch.vex_shadow1 = priv->vex_shadow1;
|
|
+ tst->arch.vex_shadow2 = priv->vex_shadow2;
|
|
+
|
|
+ VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
|
|
+ frame_size + VG_STACK_REDZONE_SZB );
|
|
+
|
|
+ if (VG_(clo_trace_signals))
|
|
+ VG_(message)(Vg_DebugMsg,
|
|
+ "vg_pop_signal_frame (thread %d): "
|
|
+ "isRT=%d valid magic; PC=%#llx\n",
|
|
+ tid, has_siginfo, tst->arch.vex.guest_PC);
|
|
+
|
|
+ /* tell the tools */
|
|
+ VG_TRACK( post_deliver_signal, tid, sigNo );
|
|
+}
|
|
+
|
|
+#endif // defined(VGP_arm_linux)
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end sigframe-arm64-linux.c ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: coregrind/m_dispatch/dispatch-arm64-linux.S
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ coregrind/m_dispatch/dispatch-arm64-linux.S
|
|
@@ -0,0 +1,241 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- The core dispatch loop, for jumping to a code address. ---*/
|
|
+/*--- dispatch-arm64-linux.S ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#if defined(VGP_arm64_linux)
|
|
+
|
|
+#include "pub_core_basics_asm.h"
|
|
+#include "pub_core_dispatch_asm.h"
|
|
+#include "pub_core_transtab_asm.h"
|
|
+#include "libvex_guest_offsets.h" /* for OFFSET_arm_R* */
|
|
+
|
|
+
|
|
+/*------------------------------------------------------------*/
|
|
+/*--- ---*/
|
|
+/*--- The dispatch loop. VG_(disp_run_translations) is ---*/
|
|
+/*--- used to run all translations, ---*/
|
|
+/*--- including no-redir ones. ---*/
|
|
+/*--- ---*/
|
|
+/*------------------------------------------------------------*/
|
|
+
|
|
+/*----------------------------------------------------*/
|
|
+/*--- Entry and preamble (set everything up) ---*/
|
|
+/*----------------------------------------------------*/
|
|
+
|
|
+/* signature:
|
|
+void VG_(disp_run_translations)( UWord* two_words,
|
|
+ void* guest_state,
|
|
+ Addr host_addr );
|
|
+*/
|
|
+.text
|
|
+.global VG_(disp_run_translations)
|
|
+VG_(disp_run_translations):
|
|
+ /* x0 holds two_words
|
|
+ x1 holds guest_state
|
|
+ x2 holds host_addr
|
|
+ */
|
|
+ /* Push the callee-saved registers. Unclear if x19/x20 are
|
|
+ callee-saved, but be on the safe side. Note this sequence
|
|
+ maintains 16-alignment of sp. Also save x0 since it will
|
|
+ be needed in the postamble. */
|
|
+ stp x29, x30, [sp, #-16]!
|
|
+ stp x27, x28, [sp, #-16]!
|
|
+ stp x25, x26, [sp, #-16]!
|
|
+ stp x23, x24, [sp, #-16]!
|
|
+ stp x21, x22, [sp, #-16]!
|
|
+ stp x19, x20, [sp, #-16]!
|
|
+ stp x0, xzr, [sp, #-16]!
|
|
+
|
|
+ /* set FPSCR to vex-required default value */
|
|
+ // FIXME
|
|
+ // mov r4, #0
|
|
+ // fmxr fpscr, r4
|
|
+
|
|
+ /* Set up the guest state pointer */
|
|
+ mov x21, x1
|
|
+
|
|
+ /* and jump into the code cache. Chained translations in
|
|
+ the code cache run, until for whatever reason, they can't
|
|
+ continue. When that happens, the translation in question
|
|
+ will jump (or call) to one of the continuation points
|
|
+ VG_(cp_...) below. */
|
|
+ br x2
|
|
+ /* NOTREACHED */
|
|
+
|
|
+/*----------------------------------------------------*/
|
|
+/*--- Postamble and exit. ---*/
|
|
+/*----------------------------------------------------*/
|
|
+
|
|
+postamble:
|
|
+ /* At this point, r1 and r2 contain two
|
|
+ words to be returned to the caller. r1
|
|
+ holds a TRC value, and r2 optionally may
|
|
+ hold another word (for CHAIN_ME exits, the
|
|
+ address of the place to patch.) */
|
|
+
|
|
+ /* We're leaving. Check that nobody messed with
|
|
+ FPSCR in ways we don't expect. */
|
|
+ // FIXME
|
|
+ // fmrx r4, fpscr
|
|
+ // bic r4, #0xF8000000 /* mask out NZCV and QC */
|
|
+ // bic r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
|
|
+ // cmp r4, #0
|
|
+ // beq remove_frame /* we're OK */
|
|
+ /* otherwise we have an invariant violation */
|
|
+ // movw r1, #VG_TRC_INVARIANT_FAILED
|
|
+ // movw r2, #0
|
|
+ /* fall through */
|
|
+
|
|
+remove_frame:
|
|
+ /* Restore int regs, including importantly x0 (two_words),
|
|
+ but not x1 */
|
|
+ ldp x0, xzr, [sp], #16
|
|
+ ldp x19, x20, [sp], #16
|
|
+ ldp x21, x22, [sp], #16
|
|
+ ldp x23, x24, [sp], #16
|
|
+ ldp x25, x26, [sp], #16
|
|
+ ldp x27, x28, [sp], #16
|
|
+ ldp x29, x30, [sp], #16
|
|
+
|
|
+ /* Stash return values */
|
|
+ str x1, [x0, #0]
|
|
+ str x2, [x0, #8]
|
|
+ ret
|
|
+
|
|
+/*----------------------------------------------------*/
|
|
+/*--- Continuation points ---*/
|
|
+/*----------------------------------------------------*/
|
|
+
|
|
+/* ------ Chain me to slow entry point ------ */
|
|
+.global VG_(disp_cp_chain_me_to_slowEP)
|
|
+VG_(disp_cp_chain_me_to_slowEP):
|
|
+ /* We got called. The return address indicates
|
|
+ where the patching needs to happen. Collect
|
|
+ the return address and, exit back to C land,
|
|
+ handing the caller the pair (Chain_me_S, RA) */
|
|
+ mov x1, #VG_TRC_CHAIN_ME_TO_SLOW_EP
|
|
+ mov x2, x30 // 30 == LR
|
|
+ /* 4 = movw x9, disp_cp_chain_me_to_slowEP[15:0]
|
|
+ 4 = movk x9, disp_cp_chain_me_to_slowEP[31:16], lsl 16
|
|
+ 4 = movk x9, disp_cp_chain_me_to_slowEP[47:32], lsl 32
|
|
+ 4 = movk x9, disp_cp_chain_me_to_slowEP[63:48], lsl 48
|
|
+ 4 = blr x9
|
|
+ */
|
|
+ sub x2, x2, #4+4+4+4+4
|
|
+ b postamble
|
|
+
|
|
+/* ------ Chain me to fast entry point ------ */
|
|
+.global VG_(disp_cp_chain_me_to_fastEP)
|
|
+VG_(disp_cp_chain_me_to_fastEP):
|
|
+ /* We got called. The return address indicates
|
|
+ where the patching needs to happen. Collect
|
|
+ the return address and, exit back to C land,
|
|
+ handing the caller the pair (Chain_me_F, RA) */
|
|
+ mov x1, #VG_TRC_CHAIN_ME_TO_FAST_EP
|
|
+ mov x2, x30 // 30 == LR
|
|
+ /* 4 = movw x9, disp_cp_chain_me_to_fastEP[15:0]
|
|
+ 4 = movk x9, disp_cp_chain_me_to_fastEP[31:16], lsl 16
|
|
+ 4 = movk x9, disp_cp_chain_me_to_fastEP[47:32], lsl 32
|
|
+ 4 = movk x9, disp_cp_chain_me_to_fastEP[63:48], lsl 48
|
|
+ 4 = blr x9
|
|
+ */
|
|
+ sub x2, x2, #4+4+4+4+4
|
|
+ b postamble
|
|
+
|
|
+/* ------ Indirect but boring jump ------ */
|
|
+.global VG_(disp_cp_xindir)
|
|
+VG_(disp_cp_xindir):
|
|
+ /* Where are we going? */
|
|
+ ldr x0, [x21, #OFFSET_arm64_PC]
|
|
+
|
|
+ /* stats only */
|
|
+ adrp x1, VG_(stats__n_xindirs_32)
|
|
+ add x1, x1, :lo12:VG_(stats__n_xindirs_32)
|
|
+ ldr w2, [x1, #0]
|
|
+ add w2, w2, #1
|
|
+ str w2, [x1, #0]
|
|
+
|
|
+ /* try a fast lookup in the translation cache */
|
|
+ // x0 = next guest, x1,x2,x3,x4 scratch
|
|
+ mov x1, #VG_TT_FAST_MASK // x1 = VG_TT_FAST_MASK
|
|
+ and x2, x1, x0, LSR #2 // x2 = entry # = (x1 & (x0 >> 2))
|
|
+
|
|
+ adrp x4, VG_(tt_fast)
|
|
+ add x4, x4, :lo12:VG_(tt_fast) // x4 = &VG_(tt_fast)
|
|
+
|
|
+ add x1, x4, x2, LSL #4 // r1 = &tt_fast[entry#]
|
|
+
|
|
+ ldp x4, x5, [x1, #0] // x4 = .guest, x5 = .host
|
|
+
|
|
+ cmp x4, x0
|
|
+
|
|
+ // jump to host if lookup succeeded
|
|
+ bne fast_lookup_failed
|
|
+ br x5
|
|
+ /*NOTREACHED*/
|
|
+
|
|
+fast_lookup_failed:
|
|
+ /* RM ME -- stats only */
|
|
+ adrp x1, VG_(stats__n_xindir_misses_32)
|
|
+ add x1, x1, :lo12:VG_(stats__n_xindir_misses_32)
|
|
+ ldr w2, [x1, #0]
|
|
+ add w2, w2, #1
|
|
+ str w2, [x1, #0]
|
|
+
|
|
+ mov x1, #VG_TRC_INNER_FASTMISS
|
|
+ mov x2, #0
|
|
+ b postamble
|
|
+
|
|
+/* ------ Assisted jump ------ */
|
|
+.global VG_(disp_cp_xassisted)
|
|
+VG_(disp_cp_xassisted):
|
|
+ /* x21 contains the TRC */
|
|
+ mov x1, x21
|
|
+ mov x2, #0
|
|
+ b postamble
|
|
+
|
|
+/* ------ Event check failed ------ */
|
|
+.global VG_(disp_cp_evcheck_fail)
|
|
+VG_(disp_cp_evcheck_fail):
|
|
+ mov x1, #VG_TRC_INNER_COUNTERZERO
|
|
+ mov x2, #0
|
|
+ b postamble
|
|
+
|
|
+
|
|
+.size VG_(disp_run_translations), .-VG_(disp_run_translations)
|
|
+
|
|
+/* Let the linker know we don't need an executable stack */
|
|
+.section .note.GNU-stack,"",%progbits
|
|
+
|
|
+#endif // defined(VGP_arm64_linux)
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end dispatch-arm64-linux.S ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: coregrind/m_initimg/initimg-linux.c
|
|
===================================================================
|
|
--- coregrind/m_initimg/initimg-linux.c.orig
|
|
+++ coregrind/m_initimg/initimg-linux.c
|
|
@@ -1052,7 +1052,7 @@ void VG_(ii_finalise_image)( IIFinaliseI
|
|
arch->vex.guest_GPR2 = iifii.initial_client_TOC;
|
|
arch->vex.guest_CIA = iifii.initial_client_IP;
|
|
|
|
-# elif defined(VGP_arm_linux)
|
|
+# elif defined(VGP_arm_linux)
|
|
/* Zero out the initial state, and set up the simulated FPU in a
|
|
sane way. */
|
|
LibVEX_GuestARM_initialise(&arch->vex);
|
|
@@ -1068,6 +1068,17 @@ void VG_(ii_finalise_image)( IIFinaliseI
|
|
// FIXME jrs: what's this for?
|
|
arch->vex.guest_R1 = iifii.initial_client_SP;
|
|
|
|
+# elif defined(VGP_arm64_linux)
|
|
+ /* Zero out the initial state. */
|
|
+ LibVEX_GuestARM64_initialise(&arch->vex);
|
|
+
|
|
+ /* Zero out the shadow areas. */
|
|
+ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestARM64State));
|
|
+ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestARM64State));
|
|
+
|
|
+ arch->vex.guest_SP = iifii.initial_client_SP;
|
|
+ arch->vex.guest_PC = iifii.initial_client_IP;
|
|
+
|
|
# elif defined(VGP_s390x_linux)
|
|
vg_assert(0 == sizeof(VexGuestS390XState) % 16);
|
|
|
|
Index: memcheck/mc_machine.c
|
|
===================================================================
|
|
--- memcheck/mc_machine.c.orig
|
|
+++ memcheck/mc_machine.c
|
|
@@ -76,6 +76,11 @@
|
|
# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState)
|
|
#endif
|
|
|
|
+#if defined(VGA_arm64)
|
|
+# include "libvex_guest_arm64.h"
|
|
+# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestARM64State)
|
|
+#endif
|
|
+
|
|
#if defined(VGA_mips32)
|
|
# include "libvex_guest_mips32.h"
|
|
# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestMIPS32State)
|
|
@@ -957,6 +962,27 @@ static Int get_otrack_shadow_offset_wrk
|
|
# undef GOF
|
|
# undef SZB
|
|
|
|
+ /* --------------------- arm64 --------------------- */
|
|
+
|
|
+# elif defined(VGA_arm64)
|
|
+
|
|
+# define GOF(_fieldname) \
|
|
+ (offsetof(VexGuestARM64State,guest_##_fieldname))
|
|
+# define SZB(_fieldname) \
|
|
+ (sizeof(((VexGuestARM64State*)0)->guest_##_fieldname))
|
|
+
|
|
+ Int o = offset;
|
|
+ Int sz = szB;
|
|
+ tl_assert(sz > 0);
|
|
+ tl_assert(host_is_little_endian());
|
|
+ (void)o; // RMME -- just to stop gcc warning that o is unused
|
|
+
|
|
+ VG_(printf)("MC_(get_otrack_shadow_offset)(arm64)(off=%d,sz=%d)\n",
|
|
+ offset,szB);
|
|
+ tl_assert(0);
|
|
+# undef GOF
|
|
+# undef SZB
|
|
+
|
|
/* --------------------- mips32 --------------------- */
|
|
|
|
# elif defined(VGA_mips32)
|
|
@@ -1242,6 +1268,13 @@ IRType MC_(get_otrack_reg_array_equiv_in
|
|
ppIRRegArray(arr);
|
|
VG_(printf)("\n");
|
|
tl_assert(0);
|
|
+
|
|
+ /* --------------------- arm64 --------------------- */
|
|
+# elif defined(VGA_arm64)
|
|
+ VG_(printf)("get_reg_array_equiv_int_type(arm64): unhandled: ");
|
|
+ ppIRRegArray(arr);
|
|
+ VG_(printf)("\n");
|
|
+ tl_assert(0);
|
|
|
|
/* --------------------- s390x --------------------- */
|
|
# elif defined(VGA_s390x)
|
|
Index: Makefile.all.am
|
|
===================================================================
|
|
--- Makefile.all.am.orig
|
|
+++ Makefile.all.am
|
|
@@ -156,6 +156,10 @@ AM_CFLAGS_ARM_LINUX = @FLAG_M32@ @
|
|
AM_CCASFLAGS_ARM_LINUX = @FLAG_M32@ \
|
|
-marm -mcpu=cortex-a8 -g
|
|
|
|
+AM_FLAG_M3264_ARM64_LINUX = @FLAG_M64@
|
|
+AM_CFLAGS_ARM64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
|
|
+AM_CCASFLAGS_ARM64_LINUX = @FLAG_M64@ -g
|
|
+
|
|
AM_FLAG_M3264_X86_DARWIN = -arch i386
|
|
AM_CFLAGS_X86_DARWIN = $(WERROR) -arch i386 $(AM_CFLAGS_BASE) \
|
|
-mmacosx-version-min=10.5 \
|
|
@@ -213,6 +217,7 @@ PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD
|
|
PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
|
|
PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
|
|
PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
|
|
+PRELOAD_LDFLAGS_ARM64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
|
|
PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386
|
|
PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64
|
|
PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
|
|
Index: cachegrind/cg_branchpred.c
|
|
===================================================================
|
|
--- cachegrind/cg_branchpred.c.orig
|
|
+++ cachegrind/cg_branchpred.c
|
|
@@ -44,12 +44,12 @@
|
|
|
|
/* How many bits at the bottom of an instruction address are
|
|
guaranteed to be zero? */
|
|
-#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm) \
|
|
- || defined(VGA_mips32) || defined(VGA_mips64)
|
|
+#if defined(VGA_ppc32) || defined(VGA_ppc64) \
|
|
+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64)
|
|
# define N_IADDR_LO_ZERO_BITS 2
|
|
#elif defined(VGA_x86) || defined(VGA_amd64)
|
|
# define N_IADDR_LO_ZERO_BITS 0
|
|
-#elif defined(VGA_s390x)
|
|
+#elif defined(VGA_s390x) || defined(VGA_arm)
|
|
# define N_IADDR_LO_ZERO_BITS 1
|
|
#else
|
|
# error "Unsupported architecture"
|
|
Index: cachegrind/cg_arch.c
|
|
===================================================================
|
|
--- cachegrind/cg_arch.c.orig
|
|
+++ cachegrind/cg_arch.c
|
|
@@ -367,6 +367,14 @@ configure_caches(cache_t *I1c, cache_t *
|
|
*D1c = (cache_t) { 16384, 4, 64 };
|
|
*LLc = (cache_t) { 262144, 8, 64 };
|
|
|
|
+#elif defined(VGA_arm64)
|
|
+
|
|
+ // Copy the 32-bit ARM version until such time as we have
|
|
+ // some real hardware to run on
|
|
+ *I1c = (cache_t) { 16384, 4, 64 };
|
|
+ *D1c = (cache_t) { 16384, 4, 64 };
|
|
+ *LLc = (cache_t) { 262144, 8, 64 };
|
|
+
|
|
#elif defined(VGA_s390x)
|
|
//
|
|
// Here is the cache data from older machine models:
|
|
Index: ARM64_TIDYUPS.txt
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ ARM64_TIDYUPS.txt
|
|
@@ -0,0 +1,178 @@
|
|
+
|
|
+## HOW TO Cross-CONFIGURE
|
|
+
|
|
+export CC=aarch64-linux-gnu-gcc
|
|
+export LD=aarch64-linux-gnu-ld
|
|
+export AR=aarch64-linux-gnu-ar
|
|
+
|
|
+./autogen.sh
|
|
+./configure --prefix=`pwd`/Inst --host=aarch64-unknown-linux --enable-only64bit
|
|
+
|
|
+##############################################################
|
|
+
|
|
+UnwindStartRegs -- what should that contain?
|
|
+
|
|
+
|
|
+
|
|
+vki-arm64-linux.h: vki_sigaction_base
|
|
+
|
|
+I really don't think that __vki_sigrestore_t sa_restorer
|
|
+should be present. Adding it surely puts sa_mask at a wrong
|
|
+offset compared to (kernel) reality. But not having it causes
|
|
+compilation of m_signals.c to fail in hard to understand ways,
|
|
+so adding it temporarily.
|
|
+
|
|
+
|
|
+m_trampoline.S: what's the unexecutable-insn value? 0xFFFFFFFF
|
|
+is there at the moment, but 0x00000000 is probably what it should be.
|
|
+Also, fix indentation/tab-vs-space stuff
|
|
+
|
|
+
|
|
+./include/vki/vki-arm64-linux.h: uses __uint128_t. Should change
|
|
+it to __vki_uint128_t, but what's the defn of that?
|
|
+
|
|
+
|
|
+
|
|
+m_debuginfo/priv_storage.h: need proper defn of DiCfSI
|
|
+
|
|
+
|
|
+readdwarf.c: is this correct?
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define FP_REG 29 //???
|
|
+# define SP_REG 31 //???
|
|
+# define RA_REG_DEFAULT 30 //???
|
|
+
|
|
+
|
|
+vki-arm64-linux.h:
|
|
+re linux-3.10.5/include/uapi/asm-generic/sembuf.h
|
|
+I'd say the amd64 version has padding it shouldn't have. Check?
|
|
+
|
|
+
|
|
+
|
|
+syswrap-linux.c run_a_thread_NORETURN assembly sections
|
|
+seems like tst->os_state.exitcode has word type
|
|
+in which case the ppc64_linux use of lwz to read it, is wrong
|
|
+
|
|
+
|
|
+
|
|
+syswrap-linux.c ML_(do_fork_clone)
|
|
+assuming that VGP_arm64_linux is the same as VGP_arm_linux here
|
|
+
|
|
+
|
|
+
|
|
+dispatch-arm64-linux.S: FIXME: set up FP control state before
|
|
+entering generated code. Also fix screwy indentation.
|
|
+
|
|
+dispatcher-ery general: what's a good (predictor-friendly) way to
|
|
+branch to a register?
|
|
+
|
|
+
|
|
+
|
|
+in vki-arm64-scnums.h
|
|
+//#if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
|
|
+Probably want to reenable that and clean up accordingly
|
|
+
|
|
+
|
|
+
|
|
+putIRegXXorZR: figure out a way that the computed value is actually
|
|
+used, so as to keep any memory reads that might generate it, alive.
|
|
+(else the simulation can lose exceptions). At least, for writes to
|
|
+the zero register generated by loads .. or .. can anything other
|
|
+integer instructions, that write to a register, cause exceptions?
|
|
+
|
|
+
|
|
+
|
|
+loads/stores: generate stack alignment checks as necessary
|
|
+
|
|
+
|
|
+
|
|
+fix barrier insns: ISB, DMB
|
|
+
|
|
+
|
|
+
|
|
+fix atomic loads/stores
|
|
+
|
|
+
|
|
+
|
|
+FMADD/FMSUB/FNMADD/FNMSUB: generate and use the relevant fused
|
|
+IROps so as to avoid double rounding
|
|
+
|
|
+
|
|
+
|
|
+ARM64Instr_Call getRegUsage: re-check relative to what
|
|
+getAllocableRegs_ARM64 makes available
|
|
+
|
|
+
|
|
+
|
|
+Make dispatch-arm64-linux.S save any callee-saved Q regs
|
|
+I think what is required is to save D8-D15 and nothing more than that.
|
|
+
|
|
+
|
|
+
|
|
+wrapper for __NR3264_fstat -- correct?
|
|
+
|
|
+
|
|
+
|
|
+PRE(sys_clone): get rid of references to vki_modify_ldt_t
|
|
+and the definition of it in vki-arm64-linux.h. Ditto for
|
|
+32 bit arm.
|
|
+
|
|
+
|
|
+
|
|
+sigframe-arm64-linux.c: build_sigframe: references to nonexistent
|
|
+siguc->uc_mcontext.trap_no, siguc->uc_mcontext.error_code have been
|
|
+replaced by zero. Also in synth_ucontext.
|
|
+
|
|
+
|
|
+
|
|
+m_debugger.c:
|
|
+uregs.pstate = LibVEX_GuestARM64_get_nzcv(vex); /* is this correct? */
|
|
+Is that remotely correct?
|
|
+
|
|
+
|
|
+
|
|
+host_arm64_defs.c: emit_ARM64INstr:
|
|
+ARM64in_VDfromX and ARM64in_VQfromXX: use simple top-half zeroing
|
|
+MOVs to vector registers instead of INS Vd.D[0], Xreg, to avoid false
|
|
+dependencies on the top half of the register. (Or at least check
|
|
+the semantocs of INS Vd.D[0] to see if it zeroes out the top.)
|
|
+
|
|
+
|
|
+
|
|
+preferredVectorSubTypeFromSize: review perf effects and decide
|
|
+on a types-for-subparts policy
|
|
+
|
|
+
|
|
+
|
|
+fold_IRExpr_Unop: add a reduction rule for this
|
|
+1Sto64(CmpNEZ64( Or64(GET:I64(1192),GET:I64(1184)) ))
|
|
+vis 1Sto64(CmpNEZ64(x)) --> CmpwNEZ64(x)
|
|
+
|
|
+
|
|
+
|
|
+check insn selection for memcheck-only primops:
|
|
+Left64 CmpwNEZ64 V128to64 V128HIto64 1Sto64 CmpNEZ64 CmpNEZ32
|
|
+widen_z_8_to_64 1Sto32 Left32 32HLto64 CmpwNEZ32 CmpNEZ8
|
|
+
|
|
+
|
|
+
|
|
+isel: get rid of various cases where zero is put into a register
|
|
+and just use xzr instead. Especially for CmpNEZ64/32. And for
|
|
+writing zeroes into the CC thunk fields.
|
|
+
|
|
+
|
|
+
|
|
+/* Keep this list in sync with that in iselNext below */
|
|
+/* Keep this list in sync with that for Ist_Exit above */
|
|
+uh .. they are not in sync
|
|
+
|
|
+
|
|
+
|
|
+very stupid:
|
|
+imm64 x23, 0xFFFFFFFFFFFFFFA0
|
|
+17 F4 9F D2 F7 FF BF F2 F7 FF DF F2 F7 FF FF F2
|
|
+
|
|
+
|
|
+
|
|
+valgrind.h: fix VALGRIND_ALIGN_STACK/VALGRIND_RESTORE_STACK,
|
|
+also add CFI annotations
|
|
Index: include/pub_tool_machine.h
|
|
===================================================================
|
|
--- include/pub_tool_machine.h.orig
|
|
+++ include/pub_tool_machine.h
|
|
@@ -67,6 +67,12 @@
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# define VG_MIN_INSTR_SZB 4
|
|
+# define VG_MAX_INSTR_SZB 4
|
|
+# define VG_CLREQ_SZB 20
|
|
+# define VG_STACK_REDZONE_SZB 0
|
|
+
|
|
#elif defined(VGP_s390x_linux)
|
|
# define VG_MIN_INSTR_SZB 2
|
|
# define VG_MAX_INSTR_SZB 6
|
|
@@ -124,14 +130,6 @@ VG_(set_shadow_regs_area) ( ThreadId tid
|
|
/*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
|
|
/*SRC*/const UChar* src );
|
|
|
|
-// Sets the shadow values for the syscall return value register(s).
|
|
-// This is platform specific.
|
|
-void VG_(set_syscall_return_shadows) ( ThreadId tid,
|
|
- /* shadow vals for the result */
|
|
- UWord s1res, UWord s2res,
|
|
- /* shadow vals for the error val */
|
|
- UWord s1err, UWord s2err );
|
|
-
|
|
// Apply a function 'f' to all the general purpose registers in all the
|
|
// current threads. This is all live threads, or (when the process is exiting)
|
|
// all threads that were instructed to die by the thread calling exit.
|
|
Index: include/vki/vki-arm64-linux.h
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ include/vki/vki-arm64-linux.h
|
|
@@ -0,0 +1,678 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- ARM64/Linux-specific kernel interface. vki-arm64-linux.h ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#ifndef __VKI_ARM64_LINUX_H
|
|
+#define __VKI_ARM64_LINUX_H
|
|
+
|
|
+// ARM64 is little-endian.
|
|
+#define VKI_LITTLE_ENDIAN 1
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/include/uapi/asm-generic/int-ll64.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+typedef unsigned char __vki_u8;
|
|
+
|
|
+typedef __signed__ short __vki_s16;
|
|
+typedef unsigned short __vki_u16;
|
|
+
|
|
+typedef __signed__ int __vki_s32;
|
|
+typedef unsigned int __vki_u32;
|
|
+
|
|
+typedef __signed__ long long __vki_s64;
|
|
+typedef unsigned long long __vki_u64;
|
|
+
|
|
+typedef unsigned short vki_u16;
|
|
+
|
|
+typedef unsigned int vki_u32;
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/arch/arm64/include/asm/page.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+/* Looks like arm64 can do both 4k and 64k pages, so we
|
|
+ use the at-startup detection scheme that ppc32/64 do. */
|
|
+extern UWord VKI_PAGE_SHIFT;
|
|
+extern UWord VKI_PAGE_SIZE;
|
|
+#define VKI_MAX_PAGE_SHIFT 16
|
|
+#define VKI_MAX_PAGE_SIZE (1UL << VKI_MAX_PAGE_SHIFT)
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/arch/arm64/include/asm/shmparam.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+// Trying to make sense of this .. it seems as if, for doing
|
|
+// shared memory with 64 bit processes, VKI_PAGE_SIZE is good
|
|
+// enough. But if sharing with a 32 bit process then we need
|
|
+// the old-style 16k value (4 * VKI_PAGE_SIZE) to be safe.
|
|
+// (From reading between the lines of arch/arm64/include/asm/shmparam.h)
|
|
+#define VKI_SHMLBA (4 * VKI_PAGE_SIZE)
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/signal.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define _VKI_NSIG 64
|
|
+#define _VKI_NSIG_BPW 64
|
|
+#define _VKI_NSIG_WORDS (_VKI_NSIG / _VKI_NSIG_BPW)
|
|
+
|
|
+typedef unsigned long vki_old_sigset_t;
|
|
+
|
|
+typedef struct {
|
|
+ unsigned long sig[_VKI_NSIG_WORDS];
|
|
+} vki_sigset_t;
|
|
+
|
|
+#define VKI_SIGHUP 1
|
|
+#define VKI_SIGINT 2
|
|
+#define VKI_SIGQUIT 3
|
|
+#define VKI_SIGILL 4
|
|
+#define VKI_SIGTRAP 5
|
|
+#define VKI_SIGABRT 6
|
|
+#define VKI_SIGBUS 7
|
|
+#define VKI_SIGFPE 8
|
|
+#define VKI_SIGKILL 9
|
|
+#define VKI_SIGUSR1 10
|
|
+#define VKI_SIGSEGV 11
|
|
+#define VKI_SIGUSR2 12
|
|
+#define VKI_SIGPIPE 13
|
|
+#define VKI_SIGALRM 14
|
|
+#define VKI_SIGTERM 15
|
|
+#define VKI_SIGSTKFLT 16
|
|
+#define VKI_SIGCHLD 17
|
|
+#define VKI_SIGCONT 18
|
|
+#define VKI_SIGSTOP 19
|
|
+#define VKI_SIGTSTP 20
|
|
+#define VKI_SIGTTIN 21
|
|
+#define VKI_SIGTTOU 22
|
|
+#define VKI_SIGURG 23
|
|
+#define VKI_SIGXCPU 24
|
|
+#define VKI_SIGXFSZ 25
|
|
+#define VKI_SIGVTALRM 26
|
|
+#define VKI_SIGPROF 27
|
|
+#define VKI_SIGWINCH 28
|
|
+#define VKI_SIGIO 29
|
|
+#define VKI_SIGPWR 30
|
|
+#define VKI_SIGSYS 31
|
|
+#define VKI_SIGUNUSED 31
|
|
+
|
|
+#define VKI_SIGRTMIN 32
|
|
+#define VKI_SIGRTMAX _VKI_NSIG
|
|
+
|
|
+#define VKI_SA_NOCLDSTOP 0x00000001
|
|
+#define VKI_SA_NOCLDWAIT 0x00000002
|
|
+#define VKI_SA_SIGINFO 0x00000004
|
|
+#define VKI_SA_ONSTACK 0x08000000
|
|
+#define VKI_SA_RESTART 0x10000000
|
|
+#define VKI_SA_NODEFER 0x40000000
|
|
+#define VKI_SA_RESETHAND 0x80000000
|
|
+
|
|
+#define VKI_SA_NOMASK VKI_SA_NODEFER
|
|
+#define VKI_SA_ONESHOT VKI_SA_RESETHAND
|
|
+
|
|
+// This is obsolete and should not be defined for new archs
|
|
+#define VKI_SA_RESTORER 0x04000000
|
|
+
|
|
+#define VKI_SS_ONSTACK 1
|
|
+#define VKI_SS_DISABLE 2
|
|
+
|
|
+#define VKI_MINSIGSTKSZ 2048
|
|
+
|
|
+#define VKI_SIG_BLOCK 0 /* for blocking signals */
|
|
+#define VKI_SIG_UNBLOCK 1 /* for unblocking signals */
|
|
+#define VKI_SIG_SETMASK 2 /* for setting the signal mask */
|
|
+
|
|
+typedef void __vki_signalfn_t(int);
|
|
+typedef __vki_signalfn_t __user *__vki_sighandler_t;
|
|
+
|
|
+typedef void __vki_restorefn_t(void);
|
|
+typedef __vki_restorefn_t __user *__vki_sigrestore_t;
|
|
+
|
|
+#define VKI_SIG_DFL ((__vki_sighandler_t)0) /* default signal handling */
|
|
+#define VKI_SIG_IGN ((__vki_sighandler_t)1) /* ignore signal */
|
|
+
|
|
+struct vki_sigaction_base {
|
|
+ // [[Nb: a 'k' prefix is added to "sa_handler" because
|
|
+ // bits/sigaction.h (which gets dragged in somehow via signal.h)
|
|
+ // #defines it as something else. Since that is done for glibc's
|
|
+ // purposes, which we don't care about here, we use our own name.]]
|
|
+ __vki_sighandler_t ksa_handler;
|
|
+ unsigned long sa_flags;
|
|
+ __vki_sigrestore_t sa_restorer; // I don't think arm64 has this
|
|
+ vki_sigset_t sa_mask; /* mask last for extensibility */
|
|
+};
|
|
+
|
|
+/* On Linux we use the same type for passing sigactions to
|
|
+ and from the kernel. Hence: */
|
|
+typedef struct vki_sigaction_base vki_sigaction_toK_t;
|
|
+typedef struct vki_sigaction_base vki_sigaction_fromK_t;
|
|
+
|
|
+
|
|
+typedef struct vki_sigaltstack {
|
|
+ void __user *ss_sp;
|
|
+ int ss_flags;
|
|
+ vki_size_t ss_size;
|
|
+} vki_stack_t;
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/arch/arm64/include/uapi/asm/sigcontext.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_sigcontext {
|
|
+ __vki_u64 fault_address;
|
|
+ /* AArch64 registers */
|
|
+ __vki_u64 regs[31];
|
|
+ __vki_u64 sp;
|
|
+ __vki_u64 pc;
|
|
+ __vki_u64 pstate;
|
|
+ /* 4K reserved for FP/SIMD state and future expansion */
|
|
+ __vki_u8 __reserved[4096] __attribute__((__aligned__(16)));
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/uapi/include/asm-generic/mman-common.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_PROT_READ 0x1 /* page can be read */
|
|
+#define VKI_PROT_WRITE 0x2 /* page can be written */
|
|
+#define VKI_PROT_EXEC 0x4 /* page can be executed */
|
|
+#define VKI_PROT_NONE 0x0 /* page can not be accessed */
|
|
+#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
|
|
+#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
|
|
+
|
|
+#define VKI_MAP_SHARED 0x01 /* Share changes */
|
|
+#define VKI_MAP_PRIVATE 0x02 /* Changes are private */
|
|
+#define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */
|
|
+#define VKI_MAP_ANONYMOUS 0x20 /* don't use a file */
|
|
+#define VKI_MAP_NORESERVE 0x4000 /* don't check for reservations */
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/uapi/include/asm-generic/fcntl.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_O_ACCMODE 03
|
|
+#define VKI_O_RDONLY 00
|
|
+#define VKI_O_WRONLY 01
|
|
+#define VKI_O_RDWR 02
|
|
+#define VKI_O_CREAT 0100 /* not fcntl */
|
|
+#define VKI_O_EXCL 0200 /* not fcntl */
|
|
+#define VKI_O_TRUNC 01000 /* not fcntl */
|
|
+#define VKI_O_APPEND 02000
|
|
+#define VKI_O_NONBLOCK 04000
|
|
+#define VKI_O_LARGEFILE 0100000
|
|
+
|
|
+#define VKI_AT_FDCWD -100
|
|
+
|
|
+#define VKI_F_DUPFD 0 /* dup */
|
|
+#define VKI_F_GETFD 1 /* get close_on_exec */
|
|
+#define VKI_F_SETFD 2 /* set/clear close_on_exec */
|
|
+#define VKI_F_GETFL 3 /* get file->f_flags */
|
|
+#define VKI_F_SETFL 4 /* set file->f_flags */
|
|
+#define VKI_F_GETLK 5
|
|
+#define VKI_F_SETLK 6
|
|
+#define VKI_F_SETLKW 7
|
|
+
|
|
+#define VKI_F_SETOWN 8 /* for sockets. */
|
|
+#define VKI_F_GETOWN 9 /* for sockets. */
|
|
+#define VKI_F_SETSIG 10 /* for sockets. */
|
|
+#define VKI_F_GETSIG 11 /* for sockets. */
|
|
+
|
|
+#define VKI_F_SETOWN_EX 15
|
|
+#define VKI_F_GETOWN_EX 16
|
|
+
|
|
+#define VKI_F_OWNER_TID 0
|
|
+#define VKI_F_OWNER_PID 1
|
|
+#define VKI_F_OWNER_PGRP 2
|
|
+
|
|
+struct vki_f_owner_ex {
|
|
+ int type;
|
|
+ __vki_kernel_pid_t pid;
|
|
+};
|
|
+
|
|
+#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */
|
|
+
|
|
+#define VKI_F_LINUX_SPECIFIC_BASE 1024
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/resource.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_RLIMIT_DATA 2 /* max data size */
|
|
+#define VKI_RLIMIT_STACK 3 /* max stack size */
|
|
+#define VKI_RLIMIT_CORE 4 /* max core file size */
|
|
+#define VKI_RLIMIT_NOFILE 7 /* max number of open files */
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/socket.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_SOL_SOCKET 1
|
|
+
|
|
+#define VKI_SO_TYPE 3
|
|
+
|
|
+#define VKI_SO_ATTACH_FILTER 26
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/sockios.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_SIOCSPGRP 0x8902
|
|
+#define VKI_SIOCGPGRP 0x8904
|
|
+#define VKI_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
|
|
+#define VKI_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/stat.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_stat {
|
|
+ unsigned long st_dev;
|
|
+ unsigned long st_ino;
|
|
+ unsigned int st_mode;
|
|
+ unsigned int st_nlink;
|
|
+ unsigned int st_uid;
|
|
+ unsigned int st_gid;
|
|
+ unsigned long st_rdev;
|
|
+ unsigned long __pad1;
|
|
+ long st_size;
|
|
+ int st_blksize;
|
|
+ int __pad2;
|
|
+ long st_blocks;
|
|
+ long st_atime;
|
|
+ unsigned long st_atime_nsec;
|
|
+ long st_mtime;
|
|
+ unsigned long st_mtime_nsec;
|
|
+ long st_ctime;
|
|
+ unsigned long st_ctime_nsec;
|
|
+ unsigned int __unused4;
|
|
+ unsigned int __unused5;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/statfs.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_statfs {
|
|
+ long f_type;
|
|
+ long f_bsize;
|
|
+ long f_blocks;
|
|
+ long f_bfree;
|
|
+ long f_bavail;
|
|
+ long f_files;
|
|
+ long f_ffree;
|
|
+ __vki_kernel_fsid_t f_fsid;
|
|
+ long f_namelen;
|
|
+ long f_frsize;
|
|
+ long f_flags;
|
|
+ long f_spare[4];
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/termios.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_winsize {
|
|
+ unsigned short ws_row;
|
|
+ unsigned short ws_col;
|
|
+ unsigned short ws_xpixel;
|
|
+ unsigned short ws_ypixel;
|
|
+};
|
|
+
|
|
+#define VKI_NCC 8
|
|
+struct vki_termio {
|
|
+ unsigned short c_iflag; /* input mode flags */
|
|
+ unsigned short c_oflag; /* output mode flags */
|
|
+ unsigned short c_cflag; /* control mode flags */
|
|
+ unsigned short c_lflag; /* local mode flags */
|
|
+ unsigned char c_line; /* line discipline */
|
|
+ unsigned char c_cc[VKI_NCC]; /* control characters */
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/termbits.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+typedef unsigned char vki_cc_t;
|
|
+typedef unsigned int vki_tcflag_t;
|
|
+
|
|
+#define VKI_NCCS 19
|
|
+struct vki_termios {
|
|
+ vki_tcflag_t c_iflag; /* input mode flags */
|
|
+ vki_tcflag_t c_oflag; /* output mode flags */
|
|
+ vki_tcflag_t c_cflag; /* control mode flags */
|
|
+ vki_tcflag_t c_lflag; /* local mode flags */
|
|
+ vki_cc_t c_line; /* line discipline */
|
|
+ vki_cc_t c_cc[VKI_NCCS]; /* control characters */
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/include/uapi/asm-generic/ioctl.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define _VKI_IOC_NRBITS 8
|
|
+#define _VKI_IOC_TYPEBITS 8
|
|
+#define _VKI_IOC_SIZEBITS 14
|
|
+#define _VKI_IOC_DIRBITS 2
|
|
+
|
|
+#define _VKI_IOC_SIZEMASK ((1 << _VKI_IOC_SIZEBITS)-1)
|
|
+#define _VKI_IOC_DIRMASK ((1 << _VKI_IOC_DIRBITS)-1)
|
|
+
|
|
+#define _VKI_IOC_NRSHIFT 0
|
|
+#define _VKI_IOC_TYPESHIFT (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS)
|
|
+#define _VKI_IOC_SIZESHIFT (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS)
|
|
+#define _VKI_IOC_DIRSHIFT (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS)
|
|
+
|
|
+#define _VKI_IOC_NONE 0U
|
|
+#define _VKI_IOC_WRITE 1U
|
|
+#define _VKI_IOC_READ 2U
|
|
+
|
|
+#define _VKI_IOC(dir,type,nr,size) \
|
|
+ (((dir) << _VKI_IOC_DIRSHIFT) | \
|
|
+ ((type) << _VKI_IOC_TYPESHIFT) | \
|
|
+ ((nr) << _VKI_IOC_NRSHIFT) | \
|
|
+ ((size) << _VKI_IOC_SIZESHIFT))
|
|
+
|
|
+#define _VKI_IO(type,nr) _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0)
|
|
+#define _VKI_IOR(type,nr,size) _VKI_IOC(_VKI_IOC_READ,(type),(nr),sizeof(size))
|
|
+#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr),sizeof(size))
|
|
+#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type),(nr),sizeof(size))
|
|
+
|
|
+#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK)
|
|
+#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK)
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/ioctls.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_TCGETS 0x5401
|
|
+#define VKI_TCSETS 0x5402
|
|
+#define VKI_TCSETSW 0x5403
|
|
+#define VKI_TCSETSF 0x5404
|
|
+#define VKI_TCGETA 0x5405
|
|
+#define VKI_TCSETA 0x5406
|
|
+#define VKI_TCSETAW 0x5407
|
|
+#define VKI_TCSETAF 0x5408
|
|
+#define VKI_TCSBRK 0x5409
|
|
+#define VKI_TCXONC 0x540A
|
|
+#define VKI_TCFLSH 0x540B
|
|
+#define VKI_TIOCSCTTY 0x540E
|
|
+#define VKI_TIOCGPGRP 0x540F
|
|
+#define VKI_TIOCSPGRP 0x5410
|
|
+#define VKI_TIOCOUTQ 0x5411
|
|
+#define VKI_TIOCGWINSZ 0x5413
|
|
+#define VKI_TIOCSWINSZ 0x5414
|
|
+#define VKI_TIOCMGET 0x5415
|
|
+#define VKI_TIOCMBIS 0x5416
|
|
+#define VKI_TIOCMBIC 0x5417
|
|
+#define VKI_TIOCMSET 0x5418
|
|
+#define VKI_FIONREAD 0x541B
|
|
+#define VKI_TIOCLINUX 0x541C
|
|
+#define VKI_FIONBIO 0x5421
|
|
+#define VKI_TCSBRKP 0x5425
|
|
+#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int)
|
|
+#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int)
|
|
+
|
|
+#define VKI_FIONCLEX 0x5450
|
|
+#define VKI_FIOCLEX 0x5451
|
|
+#define VKI_FIOASYNC 0x5452
|
|
+#define VKI_TIOCSERGETLSR 0x5459
|
|
+
|
|
+#define VKI_TIOCGICOUNT 0x545D
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/include/uapi/asm-generic/poll.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_POLLIN 0x0001
|
|
+
|
|
+struct vki_pollfd {
|
|
+ int fd;
|
|
+ short events;
|
|
+ short revents;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/arch/arm64/include/uapi/asm/ptrace.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+//ZZ struct vki_user_i387_struct {
|
|
+//ZZ unsigned short cwd;
|
|
+//ZZ unsigned short swd;
|
|
+//ZZ unsigned short twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
|
|
+//ZZ unsigned short fop;
|
|
+//ZZ __vki_u64 rip;
|
|
+//ZZ __vki_u64 rdp;
|
|
+//ZZ __vki_u32 mxcsr;
|
|
+//ZZ __vki_u32 mxcsr_mask;
|
|
+//ZZ __vki_u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
|
|
+//ZZ __vki_u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
|
|
+//ZZ __vki_u32 padding[24];
|
|
+//ZZ };
|
|
+//ZZ
|
|
+//ZZ struct vki_user_regs_struct {
|
|
+//ZZ unsigned long r15,r14,r13,r12,rbp,rbx,r11,r10;
|
|
+//ZZ unsigned long r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
|
|
+//ZZ unsigned long rip,cs,eflags;
|
|
+//ZZ unsigned long rsp,ss;
|
|
+//ZZ unsigned long fs_base, gs_base;
|
|
+//ZZ unsigned long ds,es,fs,gs;
|
|
+//ZZ };
|
|
+
|
|
+struct vki_user_pt_regs {
|
|
+ __vki_u64 regs[31];
|
|
+ __vki_u64 sp;
|
|
+ __vki_u64 pc;
|
|
+ __vki_u64 pstate;
|
|
+};
|
|
+
|
|
+/* I think that the new name in the kernel for these is "user_pt_regs"
|
|
+ and the old name is "user_regs_struct". Unfortunately can't clone
|
|
+ a 'struct' type using 'typedef' and still have a 'struct' type, so
|
|
+ use a blunter instrument instead. */
|
|
+#define vki_user_regs_struct vki_user_pt_regs
|
|
+
|
|
+struct vki_user_fpsimd_state {
|
|
+ __uint128_t vregs[32];
|
|
+ __vki_u32 fpsr;
|
|
+ __vki_u32 fpcr;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/arch/arm64/include/asm/elf.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+typedef unsigned long vki_elf_greg_t;
|
|
+
|
|
+#define VKI_ELF_NGREG (sizeof (struct vki_user_pt_regs) / sizeof(vki_elf_greg_t))
|
|
+typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG];
|
|
+
|
|
+typedef struct vki_user_fpsimd_state vki_elf_fpregset_t;
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/ucontext.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_ucontext {
|
|
+ unsigned long uc_flags;
|
|
+ struct vki_ucontext *uc_link;
|
|
+ vki_stack_t uc_stack;
|
|
+ struct vki_sigcontext uc_mcontext;
|
|
+ vki_sigset_t uc_sigmask;
|
|
+};
|
|
+
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ // From linux-2.6.9/include/asm-x86_64/segment.h
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ
|
|
+//ZZ #define VKI_GDT_ENTRY_TLS_ENTRIES 3
|
|
+//ZZ
|
|
+//ZZ #define VKI_GDT_ENTRY_TLS_MIN 11
|
|
+//ZZ #define VKI_GDT_ENTRY_TLS_MAX 13
|
|
+//ZZ
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ // From linux-2.6.11.9/include/asm-x86_64/prctl.h
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ
|
|
+//ZZ #define VKI_ARCH_SET_GS 0x1001
|
|
+//ZZ #define VKI_ARCH_SET_FS 0x1002
|
|
+//ZZ #define VKI_ARCH_GET_FS 0x1003
|
|
+//ZZ #define VKI_ARCH_GET_GS 0x1004
|
|
+//ZZ
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ // From linux-2.6.9/include/asm-x86_64/ldt.h
|
|
+//ZZ //----------------------------------------------------------------------
|
|
+//ZZ
|
|
+//ZZ // I think this LDT stuff will have to be reinstated for amd64, but I'm not
|
|
+//ZZ // certain. (Nb: The sys_arch_prctl seems to have replaced
|
|
+//ZZ // [gs]et_thread_area syscalls.)
|
|
+//ZZ //
|
|
+//ZZ // Note that the type here is very slightly different to the
|
|
+//ZZ // type for x86 (the final 'lm' field is added); I'm not sure about the
|
|
+//ZZ // significance of that... --njn
|
|
+//ZZ
|
|
+//ZZ /* [[Nb: This is the structure passed to the modify_ldt syscall. Just so as
|
|
+//ZZ to confuse and annoy everyone, this is _not_ the same as an
|
|
+//ZZ VgLdtEntry and has to be translated into such. The logic for doing
|
|
+//ZZ so, in vg_ldt.c, is copied from the kernel sources.]] */
|
|
+//ZZ /* Note also that a comment in ldt.h indicates that the below
|
|
+//ZZ contains several fields ignored on 64bit, and that modify_ldt
|
|
+//ZZ is rather for 32bit. */
|
|
+//ZZ struct vki_user_desc {
|
|
+//ZZ unsigned int entry_number;
|
|
+//ZZ unsigned long base_addr;
|
|
+//ZZ unsigned int limit;
|
|
+//ZZ unsigned int seg_32bit:1;
|
|
+//ZZ unsigned int contents:2;
|
|
+//ZZ unsigned int read_exec_only:1;
|
|
+//ZZ unsigned int limit_in_pages:1;
|
|
+//ZZ unsigned int seg_not_present:1;
|
|
+//ZZ unsigned int useable:1;
|
|
+//ZZ unsigned int lm:1;
|
|
+//ZZ };
|
|
+//ZZ
|
|
+//ZZ // [[Nb: for our convenience within Valgrind, use a more specific name]]
|
|
+//ZZ typedef struct vki_user_desc vki_modify_ldt_t;
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/asm-generic/ipcbuf.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_ipc64_perm
|
|
+{
|
|
+ __vki_kernel_key_t key;
|
|
+ __vki_kernel_uid32_t uid;
|
|
+ __vki_kernel_gid32_t gid;
|
|
+ __vki_kernel_uid32_t cuid;
|
|
+ __vki_kernel_gid32_t cgid;
|
|
+ __vki_kernel_mode_t mode;
|
|
+ unsigned char __pad1[4 - sizeof(__vki_kernel_mode_t)];
|
|
+ unsigned short seq;
|
|
+ unsigned short __pad2;
|
|
+ unsigned long __unused1;
|
|
+ unsigned long __unused2;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/sembuf.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_semid64_ds {
|
|
+ struct vki_ipc64_perm sem_perm; /* permissions .. see ipc.h */
|
|
+ __vki_kernel_time_t sem_otime; /* last semop time */
|
|
+ __vki_kernel_time_t sem_ctime; /* last change time */
|
|
+ unsigned long sem_nsems; /* no. of semaphores in array */
|
|
+ unsigned long __unused3;
|
|
+ unsigned long __unused4;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/msgbuf.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_msqid64_ds {
|
|
+ struct vki_ipc64_perm msg_perm;
|
|
+ __vki_kernel_time_t msg_stime; /* last msgsnd time */
|
|
+ __vki_kernel_time_t msg_rtime; /* last msgrcv time */
|
|
+ __vki_kernel_time_t msg_ctime; /* last change time */
|
|
+ unsigned long msg_cbytes; /* current number of bytes on queue */
|
|
+ unsigned long msg_qnum; /* number of messages in queue */
|
|
+ unsigned long msg_qbytes; /* max number of bytes on queue */
|
|
+ __vki_kernel_pid_t msg_lspid; /* pid of last msgsnd */
|
|
+ __vki_kernel_pid_t msg_lrpid; /* last receive pid */
|
|
+ unsigned long __unused4;
|
|
+ unsigned long __unused5;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.10.5/include/uapi/asm-generic/shmbuf.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+struct vki_shmid64_ds {
|
|
+ struct vki_ipc64_perm shm_perm; /* operation perms */
|
|
+ vki_size_t shm_segsz; /* size of segment (bytes) */
|
|
+ __vki_kernel_time_t shm_atime; /* last attach time */
|
|
+ __vki_kernel_time_t shm_dtime; /* last detach time */
|
|
+ __vki_kernel_time_t shm_ctime; /* last change time */
|
|
+ __vki_kernel_pid_t shm_cpid; /* pid of creator */
|
|
+ __vki_kernel_pid_t shm_lpid; /* pid of last operator */
|
|
+ unsigned long shm_nattch; /* no. of current attaches */
|
|
+ unsigned long __unused4;
|
|
+ unsigned long __unused5;
|
|
+};
|
|
+
|
|
+struct vki_shminfo64 {
|
|
+ unsigned long shmmax;
|
|
+ unsigned long shmmin;
|
|
+ unsigned long shmmni;
|
|
+ unsigned long shmseg;
|
|
+ unsigned long shmall;
|
|
+ unsigned long __unused1;
|
|
+ unsigned long __unused2;
|
|
+ unsigned long __unused3;
|
|
+ unsigned long __unused4;
|
|
+};
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/arch/arm64/include/asm/ptrace.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#define VKI_PTRACE_GETREGS 12
|
|
+#define VKI_PTRACE_SETREGS 13
|
|
+//#define VKI_PTRACE_GETFPREGS 14
|
|
+//#define VKI_PTRACE_SETFPREGS 15
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// And that's it!
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+#endif // __VKI_ARM64_LINUX_H
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: include/vki/vki-ppc64-linux.h
|
|
===================================================================
|
|
--- include/vki/vki-ppc64-linux.h.orig
|
|
+++ include/vki/vki-ppc64-linux.h
|
|
@@ -64,8 +64,8 @@ typedef unsigned int vki_u32;
|
|
|
|
/* PAGE_SHIFT determines the page size, unfortunately
|
|
page size might vary between 32-bit and 64-bit ppc kernels */
|
|
-extern unsigned long VKI_PAGE_SHIFT;
|
|
-extern unsigned long VKI_PAGE_SIZE;
|
|
+extern UWord VKI_PAGE_SHIFT;
|
|
+extern UWord VKI_PAGE_SIZE;
|
|
#define VKI_MAX_PAGE_SHIFT 16
|
|
#define VKI_MAX_PAGE_SIZE (1UL << VKI_MAX_PAGE_SHIFT)
|
|
|
|
Index: include/vki/vki-linux.h
|
|
===================================================================
|
|
--- include/vki/vki-linux.h.orig
|
|
+++ include/vki/vki-linux.h
|
|
@@ -89,6 +89,8 @@
|
|
# include "vki-posixtypes-ppc64-linux.h"
|
|
#elif defined(VGA_arm)
|
|
# include "vki-posixtypes-arm-linux.h"
|
|
+#elif defined(VGA_arm64)
|
|
+# include "vki-posixtypes-arm64-linux.h"
|
|
#elif defined(VGA_s390x)
|
|
# include "vki-posixtypes-s390x-linux.h"
|
|
#elif defined(VGA_mips32)
|
|
@@ -213,6 +215,8 @@ typedef unsigned int vki_uint;
|
|
# include "vki-ppc64-linux.h"
|
|
#elif defined(VGA_arm)
|
|
# include "vki-arm-linux.h"
|
|
+#elif defined(VGA_arm64)
|
|
+# include "vki-arm64-linux.h"
|
|
#elif defined(VGA_s390x)
|
|
# include "vki-s390x-linux.h"
|
|
#elif defined(VGA_mips32)
|
|
Index: include/vki/vki-posixtypes-arm64-linux.h
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ include/vki/vki-posixtypes-arm64-linux.h
|
|
@@ -0,0 +1,68 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- arm64/Linux-specific kernel interface: posix types. ---*/
|
|
+/*--- vki-posixtypes-arm64-linux.h ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#ifndef __VKI_POSIXTYPES_ARM64_LINUX_H
|
|
+#define __VKI_POSIXTYPES_ARM64_LINUX_H
|
|
+
|
|
+//----------------------------------------------------------------------
|
|
+// From linux-3.9.9/include/uapi/asm-generic/posix_types.h
|
|
+//----------------------------------------------------------------------
|
|
+
|
|
+typedef unsigned int __vki_kernel_mode_t;
|
|
+typedef long __vki_kernel_off_t;
|
|
+typedef int __vki_kernel_pid_t;
|
|
+typedef int __vki_kernel_ipc_pid_t;
|
|
+typedef unsigned int __vki_kernel_uid_t;
|
|
+typedef unsigned int __vki_kernel_gid_t;
|
|
+typedef unsigned long __vki_kernel_size_t;
|
|
+typedef long __vki_kernel_time_t;
|
|
+typedef long __vki_kernel_suseconds_t;
|
|
+typedef long __vki_kernel_clock_t;
|
|
+typedef int __vki_kernel_timer_t;
|
|
+typedef int __vki_kernel_clockid_t;
|
|
+typedef char * __vki_kernel_caddr_t;
|
|
+typedef unsigned int __vki_kernel_uid32_t;
|
|
+typedef unsigned int __vki_kernel_gid32_t;
|
|
+
|
|
+typedef unsigned int __vki_kernel_old_uid_t;
|
|
+typedef unsigned int __vki_kernel_old_gid_t;
|
|
+
|
|
+typedef long long __vki_kernel_loff_t;
|
|
+
|
|
+typedef struct {
|
|
+ int val[2];
|
|
+} __vki_kernel_fsid_t;
|
|
+
|
|
+#endif // __VKI_POSIXTYPES_ARM64_LINUX_H
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end vki-posixtypes-arm64-linux.h ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: include/vki/vki-ppc32-linux.h
|
|
===================================================================
|
|
--- include/vki/vki-ppc32-linux.h.orig
|
|
+++ include/vki/vki-ppc32-linux.h
|
|
@@ -63,8 +63,8 @@ typedef struct {
|
|
|
|
/* PAGE_SHIFT determines the page size, unfortunately
|
|
page size might vary between 32-bit and 64-bit ppc kernels */
|
|
-extern unsigned long VKI_PAGE_SHIFT;
|
|
-extern unsigned long VKI_PAGE_SIZE;
|
|
+extern UWord VKI_PAGE_SHIFT;
|
|
+extern UWord VKI_PAGE_SIZE;
|
|
#define VKI_MAX_PAGE_SHIFT 16
|
|
#define VKI_MAX_PAGE_SIZE (1UL << VKI_MAX_PAGE_SHIFT)
|
|
|
|
Index: include/vki/vki-scnums-arm64-linux.h
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ include/vki/vki-scnums-arm64-linux.h
|
|
@@ -0,0 +1,510 @@
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- System call numbers for arm64-linux. ---*/
|
|
+/*--- vki-scnums-arm64-linux.h ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
+
|
|
+/*
|
|
+ This file is part of Valgrind, a dynamic binary instrumentation
|
|
+ framework.
|
|
+
|
|
+ Copyright (C) 2013-2013 OpenWorks
|
|
+ info@open-works.net
|
|
+
|
|
+ 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.
|
|
+*/
|
|
+
|
|
+#ifndef __VKI_SCNUMS_ARM64_LINUX_H
|
|
+#define __VKI_SCNUMS_ARM64_LINUX_H
|
|
+
|
|
+// From linux-3.10.5/arch/arm64/include/uapi/asm/unistd.h
|
|
+// is a #include of
|
|
+// linux-3.10.5/include/uapi/asm-generic/unistd.h
|
|
+
|
|
+#define __NR_io_setup 0
|
|
+#define __NR_io_destroy 1
|
|
+#define __NR_io_submit 2
|
|
+#define __NR_io_cancel 3
|
|
+#define __NR_io_getevents 4
|
|
+#define __NR_setxattr 5
|
|
+#define __NR_lsetxattr 6
|
|
+#define __NR_fsetxattr 7
|
|
+#define __NR_getxattr 8
|
|
+#define __NR_lgetxattr 9
|
|
+#define __NR_fgetxattr 10
|
|
+#define __NR_listxattr 11
|
|
+#define __NR_llistxattr 12
|
|
+#define __NR_flistxattr 13
|
|
+#define __NR_removexattr 14
|
|
+#define __NR_lremovexattr 15
|
|
+#define __NR_fremovexattr 16
|
|
+#define __NR_getcwd 17
|
|
+#define __NR_lookup_dcookie 18
|
|
+#define __NR_eventfd2 19
|
|
+#define __NR_epoll_create1 20
|
|
+#define __NR_epoll_ctl 21
|
|
+#define __NR_epoll_pwait 22
|
|
+#define __NR_dup 23
|
|
+#define __NR_dup3 24
|
|
+#define __NR3264_fcntl 25
|
|
+#define __NR_inotify_init1 26
|
|
+#define __NR_inotify_add_watch 27
|
|
+#define __NR_inotify_rm_watch 28
|
|
+#define __NR_ioctl 29
|
|
+#define __NR_ioprio_set 30
|
|
+#define __NR_ioprio_get 31
|
|
+#define __NR_flock 32
|
|
+#define __NR_mknodat 33
|
|
+#define __NR_mkdirat 34
|
|
+#define __NR_unlinkat 35
|
|
+#define __NR_symlinkat 36
|
|
+#define __NR_linkat 37
|
|
+#define __NR_renameat 38
|
|
+#define __NR_umount2 39
|
|
+#define __NR_mount 40
|
|
+#define __NR_pivot_root 41
|
|
+#define __NR_nfsservctl 42
|
|
+#define __NR3264_statfs 43
|
|
+#define __NR3264_fstatfs 44
|
|
+#define __NR3264_truncate 45
|
|
+#define __NR3264_ftruncate 46
|
|
+#define __NR_fallocate 47
|
|
+#define __NR_faccessat 48
|
|
+#define __NR_chdir 49
|
|
+#define __NR_fchdir 50
|
|
+#define __NR_chroot 51
|
|
+#define __NR_fchmod 52
|
|
+#define __NR_fchmodat 53
|
|
+#define __NR_fchownat 54
|
|
+#define __NR_fchown 55
|
|
+#define __NR_openat 56
|
|
+#define __NR_close 57
|
|
+#define __NR_vhangup 58
|
|
+#define __NR_pipe2 59
|
|
+#define __NR_quotactl 60
|
|
+#define __NR_getdents64 61
|
|
+#define __NR3264_lseek 62
|
|
+#define __NR_read 63
|
|
+#define __NR_write 64
|
|
+#define __NR_readv 65
|
|
+#define __NR_writev 66
|
|
+#define __NR_pread64 67
|
|
+#define __NR_pwrite64 68
|
|
+#define __NR_preadv 69
|
|
+#define __NR_pwritev 70
|
|
+#define __NR3264_sendfile 71
|
|
+#define __NR_pselect6 72
|
|
+#define __NR_ppoll 73
|
|
+#define __NR_signalfd4 74
|
|
+#define __NR_vmsplice 75
|
|
+#define __NR_splice 76
|
|
+#define __NR_tee 77
|
|
+#define __NR_readlinkat 78
|
|
+#define __NR3264_fstatat 79
|
|
+#define __NR3264_fstat 80
|
|
+#define __NR_sync 81
|
|
+#define __NR_fsync 82
|
|
+#define __NR_fdatasync 83
|
|
+
|
|
+//#ifdef __ARCH_WANT_SYNC_FILE_RANGE2
|
|
+//#define __NR_sync_file_range2 84
|
|
+//#else
|
|
+#define __NR_sync_file_range 84
|
|
+//#endif
|
|
+
|
|
+#define __NR_timerfd_create 85
|
|
+#define __NR_timerfd_settime 86
|
|
+#define __NR_timerfd_gettime 87
|
|
+#define __NR_utimensat 88
|
|
+#define __NR_acct 89
|
|
+#define __NR_capget 90
|
|
+#define __NR_capset 91
|
|
+#define __NR_personality 92
|
|
+#define __NR_exit 93
|
|
+#define __NR_exit_group 94
|
|
+#define __NR_waitid 95
|
|
+#define __NR_set_tid_address 96
|
|
+#define __NR_unshare 97
|
|
+#define __NR_futex 98
|
|
+#define __NR_set_robust_list 99
|
|
+#define __NR_get_robust_list 100
|
|
+#define __NR_nanosleep 101
|
|
+#define __NR_getitimer 102
|
|
+#define __NR_setitimer 103
|
|
+#define __NR_kexec_load 104
|
|
+#define __NR_init_module 105
|
|
+#define __NR_delete_module 106
|
|
+#define __NR_timer_create 107
|
|
+#define __NR_timer_gettime 108
|
|
+#define __NR_timer_getoverrun 109
|
|
+#define __NR_timer_settime 110
|
|
+#define __NR_timer_delete 111
|
|
+#define __NR_clock_settime 112
|
|
+#define __NR_clock_gettime 113
|
|
+#define __NR_clock_getres 114
|
|
+#define __NR_clock_nanosleep 115
|
|
+#define __NR_syslog 116
|
|
+#define __NR_ptrace 117
|
|
+#define __NR_sched_setparam 118
|
|
+#define __NR_sched_setscheduler 119
|
|
+#define __NR_sched_getscheduler 120
|
|
+#define __NR_sched_getparam 121
|
|
+#define __NR_sched_setaffinity 122
|
|
+#define __NR_sched_getaffinity 123
|
|
+#define __NR_sched_yield 124
|
|
+#define __NR_sched_get_priority_max 125
|
|
+#define __NR_sched_get_priority_min 126
|
|
+#define __NR_sched_rr_get_interval 127
|
|
+#define __NR_restart_syscall 128
|
|
+#define __NR_kill 129
|
|
+#define __NR_tkill 130
|
|
+#define __NR_tgkill 131
|
|
+#define __NR_sigaltstack 132
|
|
+#define __NR_rt_sigsuspend 133
|
|
+#define __NR_rt_sigaction 134
|
|
+#define __NR_rt_sigprocmask 135
|
|
+#define __NR_rt_sigpending 136
|
|
+#define __NR_rt_sigtimedwait 137
|
|
+#define __NR_rt_sigqueueinfo 138
|
|
+#define __NR_rt_sigreturn 139
|
|
+#define __NR_setpriority 140
|
|
+#define __NR_getpriority 141
|
|
+#define __NR_reboot 142
|
|
+#define __NR_setregid 143
|
|
+#define __NR_setgid 144
|
|
+#define __NR_setreuid 145
|
|
+#define __NR_setuid 146
|
|
+#define __NR_setresuid 147
|
|
+#define __NR_getresuid 148
|
|
+#define __NR_setresgid 149
|
|
+#define __NR_getresgid 150
|
|
+#define __NR_setfsuid 151
|
|
+#define __NR_setfsgid 152
|
|
+#define __NR_times 153
|
|
+#define __NR_setpgid 154
|
|
+#define __NR_getpgid 155
|
|
+#define __NR_getsid 156
|
|
+#define __NR_setsid 157
|
|
+#define __NR_getgroups 158
|
|
+#define __NR_setgroups 159
|
|
+#define __NR_uname 160
|
|
+#define __NR_sethostname 161
|
|
+#define __NR_setdomainname 162
|
|
+#define __NR_getrlimit 163
|
|
+#define __NR_setrlimit 164
|
|
+#define __NR_getrusage 165
|
|
+#define __NR_umask 166
|
|
+#define __NR_prctl 167
|
|
+#define __NR_getcpu 168
|
|
+#define __NR_gettimeofday 169
|
|
+#define __NR_settimeofday 170
|
|
+#define __NR_adjtimex 171
|
|
+#define __NR_getpid 172
|
|
+#define __NR_getppid 173
|
|
+#define __NR_getuid 174
|
|
+#define __NR_geteuid 175
|
|
+#define __NR_getgid 176
|
|
+#define __NR_getegid 177
|
|
+#define __NR_gettid 178
|
|
+#define __NR_sysinfo 179
|
|
+#define __NR_mq_open 180
|
|
+#define __NR_mq_unlink 181
|
|
+#define __NR_mq_timedsend 182
|
|
+#define __NR_mq_timedreceive 183
|
|
+#define __NR_mq_notify 184
|
|
+#define __NR_mq_getsetattr 185
|
|
+#define __NR_msgget 186
|
|
+#define __NR_msgctl 187
|
|
+#define __NR_msgrcv 188
|
|
+#define __NR_msgsnd 189
|
|
+#define __NR_semget 190
|
|
+#define __NR_semctl 191
|
|
+#define __NR_semtimedop 192
|
|
+#define __NR_semop 193
|
|
+#define __NR_shmget 194
|
|
+#define __NR_shmctl 195
|
|
+#define __NR_shmat 196
|
|
+#define __NR_shmdt 197
|
|
+#define __NR_socket 198
|
|
+#define __NR_socketpair 199
|
|
+#define __NR_bind 200
|
|
+#define __NR_listen 201
|
|
+#define __NR_accept 202
|
|
+#define __NR_connect 203
|
|
+#define __NR_getsockname 204
|
|
+#define __NR_getpeername 205
|
|
+#define __NR_sendto 206
|
|
+#define __NR_recvfrom 207
|
|
+#define __NR_setsockopt 208
|
|
+#define __NR_getsockopt 209
|
|
+#define __NR_shutdown 210
|
|
+#define __NR_sendmsg 211
|
|
+#define __NR_recvmsg 212
|
|
+#define __NR_readahead 213
|
|
+#define __NR_brk 214
|
|
+#define __NR_munmap 215
|
|
+#define __NR_mremap 216
|
|
+#define __NR_add_key 217
|
|
+#define __NR_request_key 218
|
|
+#define __NR_keyctl 219
|
|
+#define __NR_clone 220
|
|
+#define __NR_execve 221
|
|
+#define __NR3264_mmap 222
|
|
+#define __NR3264_fadvise64 223
|
|
+#define __NR_swapon 224
|
|
+#define __NR_swapoff 225
|
|
+#define __NR_mprotect 226
|
|
+#define __NR_msync 227
|
|
+#define __NR_mlock 228
|
|
+#define __NR_munlock 229
|
|
+#define __NR_mlockall 230
|
|
+#define __NR_munlockall 231
|
|
+#define __NR_mincore 232
|
|
+#define __NR_madvise 233
|
|
+#define __NR_remap_file_pages 234
|
|
+#define __NR_mbind 235
|
|
+#define __NR_get_mempolicy 236
|
|
+#define __NR_set_mempolicy 237
|
|
+#define __NR_migrate_pages 238
|
|
+#define __NR_move_pages 239
|
|
+#define __NR_rt_tgsigqueueinfo 240
|
|
+#define __NR_perf_event_open 241
|
|
+#define __NR_accept4 242
|
|
+#define __NR_recvmmsg 243
|
|
+
|
|
+///*
|
|
+// * Architectures may provide up to 16 syscalls of their own
|
|
+// * starting with this value.
|
|
+// */
|
|
+//#define __NR_arch_specific_syscall 244
|
|
+
|
|
+#define __NR_wait4 260
|
|
+#define __NR_prlimit64 261
|
|
+#define __NR_fanotify_init 262
|
|
+#define __NR_fanotify_mark 263
|
|
+#define __NR_name_to_handle_at 264
|
|
+#define __NR_open_by_handle_at 265
|
|
+#define __NR_clock_adjtime 266
|
|
+#define __NR_syncfs 267
|
|
+#define __NR_setns 268
|
|
+#define __NR_sendmmsg 269
|
|
+#define __NR_process_vm_readv 270
|
|
+#define __NR_process_vm_writev 271
|
|
+#define __NR_kcmp 272
|
|
+#define __NR_finit_module 273
|
|
+
|
|
+#undef __NR_syscalls
|
|
+#define __NR_syscalls 274
|
|
+
|
|
+///*
|
|
+// * All syscalls below here should go away really,
|
|
+// * these are provided for both review and as a porting
|
|
+// * help for the C library version.
|
|
+//*
|
|
+// * Last chance: are any of these important enough to
|
|
+// * enable by default?
|
|
+// */
|
|
+//#ifdef __ARCH_WANT_SYSCALL_NO_AT
|
|
+//ZZZZ#define __NR_open 1024
|
|
+//#define __NR_link 1025
|
|
+//__SYSCALL(__NR_link, sys_link)
|
|
+//#define __NR_unlink 1026
|
|
+#define __NR_mknod 1027
|
|
+//#define __NR_chmod 1028
|
|
+//__SYSCALL(__NR_chmod, sys_chmod)
|
|
+//#define __NR_chown 1029
|
|
+//__SYSCALL(__NR_chown, sys_chown)
|
|
+//#define __NR_mkdir 1030
|
|
+//__SYSCALL(__NR_mkdir, sys_mkdir)
|
|
+//#define __NR_rmdir 1031
|
|
+//__SYSCALL(__NR_rmdir, sys_rmdir)
|
|
+//#define __NR_lchown 1032
|
|
+//__SYSCALL(__NR_lchown, sys_lchown)
|
|
+#define __NR_access 1033
|
|
+#define __NR_rename 1034
|
|
+//#define __NR_readlink 1035
|
|
+//#define __NR_symlink 1036
|
|
+//__SYSCALL(__NR_symlink, sys_symlink)
|
|
+//#define __NR_utimes 1037
|
|
+//__SYSCALL(__NR_utimes, sys_utimes)
|
|
+//#define __NR3264_stat 1038
|
|
+//__SC_3264(__NR3264_stat, sys_stat64, sys_newstat)
|
|
+//#define __NR3264_lstat 1039
|
|
+//__SC_3264(__NR3264_lstat, sys_lstat64, sys_newlstat)
|
|
+//
|
|
+//#undef __NR_syscalls
|
|
+//#define __NR_syscalls (__NR3264_lstat+1)
|
|
+//#endif /* __ARCH_WANT_SYSCALL_NO_AT */
|
|
+//
|
|
+//#ifdef __ARCH_WANT_SYSCALL_NO_FLAGS
|
|
+#define __NR_pipe 1040
|
|
+#define __NR_dup2 1041
|
|
+//#define __NR_epoll_create 1042
|
|
+//__SYSCALL(__NR_epoll_create, sys_epoll_create)
|
|
+//#define __NR_inotify_init 1043
|
|
+//__SYSCALL(__NR_inotify_init, sys_inotify_init)
|
|
+//#define __NR_eventfd 1044
|
|
+//__SYSCALL(__NR_eventfd, sys_eventfd)
|
|
+//#define __NR_signalfd 1045
|
|
+//__SYSCALL(__NR_signalfd, sys_signalfd)
|
|
+//
|
|
+//#undef __NR_syscalls
|
|
+//#define __NR_syscalls (__NR_signalfd+1)
|
|
+//#endif /* __ARCH_WANT_SYSCALL_NO_FLAGS */
|
|
+//
|
|
+/* #if (__BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT)) && \
|
|
+ defined(__ARCH_WANT_SYSCALL_OFF_T)
|
|
+*/
|
|
+//#define __NR_sendfile 1046
|
|
+//__SYSCALL(__NR_sendfile, sys_sendfile)
|
|
+//#define __NR_ftruncate 1047
|
|
+//__SYSCALL(__NR_ftruncate, sys_ftruncate)
|
|
+//#define __NR_truncate 1048
|
|
+//__SYSCALL(__NR_truncate, sys_truncate)
|
|
+#define __NR_stat 1049
|
|
+//#define __NR_lstat 1050
|
|
+//__SYSCALL(__NR_lstat, sys_newlstat)
|
|
+//ZZ#define __NR_fstat 1051
|
|
+//#define __NR_fcntl 1052
|
|
+//#define __NR_fadvise64 1053
|
|
+//#define __ARCH_WANT_SYS_FADVISE64
|
|
+//__SYSCALL(__NR_fadvise64, sys_fadvise64)
|
|
+//#define __NR_newfstatat 1054
|
|
+//#define __ARCH_WANT_SYS_NEWFSTATAT
|
|
+//__SYSCALL(__NR_newfstatat, sys_newfstatat)
|
|
+//#define __NR_fstatfs 1055
|
|
+//__SYSCALL(__NR_fstatfs, sys_fstatfs)
|
|
+//#define __NR_statfs 1056
|
|
+//__SYSCALL(__NR_statfs, sys_statfs)
|
|
+#define __NR_lseek 1057
|
|
+#define __NR_mmap 1058
|
|
+//
|
|
+//#undef __NR_syscalls
|
|
+//#define __NR_syscalls (__NR_mmap+1)
|
|
+//#endif /* 32 bit off_t syscalls */
|
|
+//
|
|
+//#ifdef __ARCH_WANT_SYSCALL_DEPRECATED
|
|
+//#define __NR_alarm 1059
|
|
+//#define __ARCH_WANT_SYS_ALARM
|
|
+//__SYSCALL(__NR_alarm, sys_alarm)
|
|
+#define __NR_getpgrp 1060
|
|
+//#define __ARCH_WANT_SYS_GETPGRP
|
|
+//__SYSCALL(__NR_getpgrp, sys_getpgrp)
|
|
+//#define __NR_pause 1061
|
|
+//#define __ARCH_WANT_SYS_PAUSE
|
|
+//__SYSCALL(__NR_pause, sys_pause)
|
|
+//#define __NR_time 1062
|
|
+//#define __ARCH_WANT_SYS_TIME
|
|
+//#define __ARCH_WANT_COMPAT_SYS_TIME
|
|
+//__SYSCALL(__NR_time, sys_time)
|
|
+//#define __NR_utime 1063
|
|
+//#define __ARCH_WANT_SYS_UTIME
|
|
+//__SYSCALL(__NR_utime, sys_utime)
|
|
+//
|
|
+//#define __NR_creat 1064
|
|
+//__SYSCALL(__NR_creat, sys_creat)
|
|
+#define __NR_getdents 1065
|
|
+//#define __NR_futimesat 1066
|
|
+//__SYSCALL(__NR_futimesat, sys_futimesat)
|
|
+//#define __NR_select 1067
|
|
+//#define __ARCH_WANT_SYS_SELECT
|
|
+//__SYSCALL(__NR_select, sys_select)
|
|
+#define __NR_poll 1068
|
|
+//#define __NR_epoll_wait 1069
|
|
+//__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
|
|
+//#define __NR_ustat 1070
|
|
+//__SYSCALL(__NR_ustat, sys_ustat)
|
|
+//#define __NR_vfork 1071
|
|
+//__SYSCALL(__NR_vfork, sys_vfork)
|
|
+//#define __NR_oldwait4 1072
|
|
+//__SYSCALL(__NR_oldwait4, sys_wait4)
|
|
+//#define __NR_recv 1073
|
|
+//__SYSCALL(__NR_recv, sys_recv)
|
|
+//#define __NR_send 1074
|
|
+//__SYSCALL(__NR_send, sys_send)
|
|
+//#define __NR_bdflush 1075
|
|
+//__SYSCALL(__NR_bdflush, sys_bdflush)
|
|
+//#define __NR_umount 1076
|
|
+//__SYSCALL(__NR_umount, sys_oldumount)
|
|
+//#define __ARCH_WANT_SYS_OLDUMOUNT
|
|
+//#define __NR_uselib 1077
|
|
+//__SYSCALL(__NR_uselib, sys_uselib)
|
|
+//#define __NR__sysctl 1078
|
|
+//__SYSCALL(__NR__sysctl, sys_sysctl)
|
|
+//
|
|
+#define __NR_fork 1079
|
|
+//#ifdef CONFIG_MMU
|
|
+//__SYSCALL(__NR_fork, sys_fork)
|
|
+//#else
|
|
+//__SYSCALL(__NR_fork, sys_ni_syscall)
|
|
+//#endif /* CONFIG_MMU */
|
|
+//
|
|
+//#undef __NR_syscalls
|
|
+//#define __NR_syscalls (__NR_fork+1)
|
|
+//
|
|
+//#endif /* __ARCH_WANT_SYSCALL_DEPRECATED */
|
|
+//
|
|
+///*
|
|
+// * 32 bit systems traditionally used different
|
|
+// * syscalls for off_t and loff_t arguments, while
|
|
+// * 64 bit systems only need the off_t version.
|
|
+// * For new 32 bit platforms, there is no need to
|
|
+// * implement the old 32 bit off_t syscalls, so
|
|
+// * they take different names.
|
|
+// * Here we map the numbers so that both versions
|
|
+// * use the same syscall table layout.
|
|
+// */
|
|
+//#if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
|
|
+#define __NR_fcntl __NR3264_fcntl
|
|
+//#define __NR_statfs __NR3264_statfs
|
|
+//#define __NR_fstatfs __NR3264_fstatfs
|
|
+//#define __NR_truncate __NR3264_truncate
|
|
+//#define __NR_ftruncate __NR3264_ftruncate
|
|
+//#define __NR_lseek __NR3264_lseek
|
|
+//#define __NR_sendfile __NR3264_sendfile
|
|
+//#define __NR_newfstatat __NR3264_fstatat
|
|
+#define __NR_fstat __NR3264_fstat
|
|
+//#define __NR_mmap __NR3264_mmap
|
|
+//#define __NR_fadvise64 __NR3264_fadvise64
|
|
+//#ifdef __NR3264_stat
|
|
+//#define __NR_stat __NR3264_stat
|
|
+//#define __NR_lstat __NR3264_lstat
|
|
+//#endif
|
|
+//#else
|
|
+//#define __NR_fcntl64 __NR3264_fcntl
|
|
+//#define __NR_statfs64 __NR3264_statfs
|
|
+//#define __NR_fstatfs64 __NR3264_fstatfs
|
|
+//#define __NR_truncate64 __NR3264_truncate
|
|
+//#define __NR_ftruncate64 __NR3264_ftruncate
|
|
+//#define __NR_llseek __NR3264_lseek
|
|
+//#define __NR_sendfile64 __NR3264_sendfile
|
|
+//#define __NR_fstatat64 __NR3264_fstatat
|
|
+//#define __NR_fstat64 __NR3264_fstat
|
|
+//#define __NR_mmap2 __NR3264_mmap
|
|
+//#define __NR_fadvise64_64 __NR3264_fadvise64
|
|
+//#ifdef __NR3264_stat
|
|
+//#define __NR_stat64 __NR3264_stat
|
|
+//#define __NR_lstat64 __NR3264_lstat
|
|
+//#endif
|
|
+//#endif
|
|
+
|
|
+#endif /* __VKI_SCNUMS_ARM64_LINUX_H */
|
|
+
|
|
+/*--------------------------------------------------------------------*/
|
|
+/*--- end vki-scnums-arm64-linux.h ---*/
|
|
+/*--------------------------------------------------------------------*/
|
|
Index: include/valgrind.h
|
|
===================================================================
|
|
--- include/valgrind.h.orig
|
|
+++ include/valgrind.h
|
|
@@ -117,6 +117,7 @@
|
|
#undef PLAT_ppc32_linux
|
|
#undef PLAT_ppc64_linux
|
|
#undef PLAT_arm_linux
|
|
+#undef PLAT_arm64_linux
|
|
#undef PLAT_s390x_linux
|
|
#undef PLAT_mips32_linux
|
|
#undef PLAT_mips64_linux
|
|
@@ -139,16 +140,16 @@
|
|
# define PLAT_ppc32_linux 1
|
|
#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
|
|
# define PLAT_ppc64_linux 1
|
|
-#elif defined(__linux__) && defined(__arm__)
|
|
+#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
|
|
# define PLAT_arm_linux 1
|
|
+#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
|
|
+# define PLAT_arm64_linux 1
|
|
#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
|
|
# define PLAT_s390x_linux 1
|
|
-#elif defined(__linux__) && defined(__mips__)
|
|
-#if (__mips==64)
|
|
+#elif defined(__linux__) && defined(__mips__) && (__mips==64)
|
|
# define PLAT_mips64_linux 1
|
|
-#else
|
|
+#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
|
|
# define PLAT_mips32_linux 1
|
|
-#endif
|
|
#else
|
|
/* If we're not compiling for our target platform, don't generate
|
|
any inline asms. */
|
|
@@ -654,6 +655,74 @@ typedef
|
|
|
|
#endif /* PLAT_arm_linux */
|
|
|
|
+/* ------------------------ arm64-linux ------------------------- */
|
|
+
|
|
+#if defined(PLAT_arm64_linux)
|
|
+
|
|
+typedef
|
|
+ struct {
|
|
+ unsigned long long int nraddr; /* where's the code? */
|
|
+ }
|
|
+ OrigFn;
|
|
+
|
|
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
|
|
+ "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
|
|
+ "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
|
|
+
|
|
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
|
|
+ _zzq_default, _zzq_request, \
|
|
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
|
|
+ \
|
|
+ __extension__ \
|
|
+ ({volatile unsigned long long int _zzq_args[6]; \
|
|
+ volatile unsigned long long int _zzq_result; \
|
|
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
|
|
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
|
|
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
|
|
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
|
|
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
|
|
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
|
|
+ __asm__ volatile("mov x3, %1\n\t" /*default*/ \
|
|
+ "mov x4, %2\n\t" /*ptr*/ \
|
|
+ __SPECIAL_INSTRUCTION_PREAMBLE \
|
|
+ /* X3 = client_request ( X4 ) */ \
|
|
+ "orr x10, x10, x10\n\t" \
|
|
+ "mov %0, x3" /*result*/ \
|
|
+ : "=r" (_zzq_result) \
|
|
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
|
|
+ : "cc","memory", "x3", "x4"); \
|
|
+ _zzq_result; \
|
|
+ })
|
|
+
|
|
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
|
|
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
|
|
+ unsigned long long int __addr; \
|
|
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
|
|
+ /* X3 = guest_NRADDR */ \
|
|
+ "orr x11, x11, x11\n\t" \
|
|
+ "mov %0, x3" \
|
|
+ : "=r" (__addr) \
|
|
+ : \
|
|
+ : "cc", "memory", "x3" \
|
|
+ ); \
|
|
+ _zzq_orig->nraddr = __addr; \
|
|
+ }
|
|
+
|
|
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ __SPECIAL_INSTRUCTION_PREAMBLE \
|
|
+ /* branch-and-link-to-noredir X8 */ \
|
|
+ "orr x12, x12, x12\n\t"
|
|
+
|
|
+#define VALGRIND_VEX_INJECT_IR() \
|
|
+ do { \
|
|
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
|
|
+ "orr x9, x9, x9\n\t" \
|
|
+ : : : "cc", "memory" \
|
|
+ ); \
|
|
+ } while (0)
|
|
+
|
|
+#endif /* PLAT_arm64_linux */
|
|
+
|
|
/* ------------------------ s390x-linux ------------------------ */
|
|
|
|
#if defined(PLAT_s390x_linux)
|
|
@@ -3470,6 +3539,143 @@ typedef
|
|
|
|
#endif /* PLAT_arm_linux */
|
|
|
|
+/* ------------------------ arm64-linux ------------------------ */
|
|
+
|
|
+#if defined(PLAT_arm64_linux)
|
|
+
|
|
+/* These regs are trashed by the hidden call. */
|
|
+#define __CALLER_SAVED_REGS \
|
|
+ "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
|
|
+ "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
|
|
+ "x18", "x19", "x20", \
|
|
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
|
|
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
|
|
+ "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
|
|
+ "v26", "v27", "v28", "v29", "v30", "v31"
|
|
+
|
|
+#define VALGRIND_ALIGN_STACK /* FIXME! */
|
|
+#define VALGRIND_RESTORE_STACK /* FIXME! */
|
|
+
|
|
+/* These CALL_FN_ macros assume that on arm64-linux,
|
|
+ sizeof(unsigned long) == 8. */
|
|
+
|
|
+#define CALL_FN_W_v(lval, orig) \
|
|
+ do { \
|
|
+ volatile OrigFn _orig = (orig); \
|
|
+ volatile unsigned long _argvec[1]; \
|
|
+ volatile unsigned long _res; \
|
|
+ _argvec[0] = (unsigned long)_orig.nraddr; \
|
|
+ __asm__ volatile( \
|
|
+ VALGRIND_ALIGN_STACK \
|
|
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
|
|
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ VALGRIND_RESTORE_STACK \
|
|
+ "mov %0, x0\n" \
|
|
+ : /*out*/ "=r" (_res) \
|
|
+ : /*in*/ "0" (&_argvec[0]) \
|
|
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
|
|
+ ); \
|
|
+ lval = (__typeof__(lval)) _res; \
|
|
+ } while (0)
|
|
+
|
|
+#define CALL_FN_W_W(lval, orig, arg1) \
|
|
+ do { \
|
|
+ volatile OrigFn _orig = (orig); \
|
|
+ volatile unsigned long _argvec[2]; \
|
|
+ volatile unsigned long _res; \
|
|
+ _argvec[0] = (unsigned long)_orig.nraddr; \
|
|
+ _argvec[1] = (unsigned long)(arg1); \
|
|
+ __asm__ volatile( \
|
|
+ VALGRIND_ALIGN_STACK \
|
|
+ "ldr x0, [%1, #8] \n\t" \
|
|
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
|
|
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ VALGRIND_RESTORE_STACK \
|
|
+ "mov %0, x0\n" \
|
|
+ : /*out*/ "=r" (_res) \
|
|
+ : /*in*/ "0" (&_argvec[0]) \
|
|
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS/*, "r10"*/ \
|
|
+ ); \
|
|
+ lval = (__typeof__(lval)) _res; \
|
|
+ } while (0)
|
|
+
|
|
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
|
|
+ do { \
|
|
+ volatile OrigFn _orig = (orig); \
|
|
+ volatile unsigned long _argvec[3]; \
|
|
+ volatile unsigned long _res; \
|
|
+ _argvec[0] = (unsigned long)_orig.nraddr; \
|
|
+ _argvec[1] = (unsigned long)(arg1); \
|
|
+ _argvec[2] = (unsigned long)(arg2); \
|
|
+ __asm__ volatile( \
|
|
+ VALGRIND_ALIGN_STACK \
|
|
+ "ldr x0, [%1, #8] \n\t" \
|
|
+ "ldr x1, [%1, #16] \n\t" \
|
|
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
|
|
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ VALGRIND_RESTORE_STACK \
|
|
+ "mov %0, x0\n" \
|
|
+ : /*out*/ "=r" (_res) \
|
|
+ : /*in*/ "0" (&_argvec[0]) \
|
|
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS/*, "r10"*/ \
|
|
+ ); \
|
|
+ lval = (__typeof__(lval)) _res; \
|
|
+ } while (0)
|
|
+
|
|
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
|
|
+ do { \
|
|
+ volatile OrigFn _orig = (orig); \
|
|
+ volatile unsigned long _argvec[4]; \
|
|
+ volatile unsigned long _res; \
|
|
+ _argvec[0] = (unsigned long)_orig.nraddr; \
|
|
+ _argvec[1] = (unsigned long)(arg1); \
|
|
+ _argvec[2] = (unsigned long)(arg2); \
|
|
+ _argvec[3] = (unsigned long)(arg3); \
|
|
+ __asm__ volatile( \
|
|
+ VALGRIND_ALIGN_STACK \
|
|
+ "ldr x0, [%1, #8] \n\t" \
|
|
+ "ldr x1, [%1, #16] \n\t" \
|
|
+ "ldr x2, [%1, #24] \n\t" \
|
|
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
|
|
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ VALGRIND_RESTORE_STACK \
|
|
+ "mov %0, x0\n" \
|
|
+ : /*out*/ "=r" (_res) \
|
|
+ : /*in*/ "0" (&_argvec[0]) \
|
|
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS/*, "r10"*/ \
|
|
+ ); \
|
|
+ lval = (__typeof__(lval)) _res; \
|
|
+ } while (0)
|
|
+
|
|
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
|
|
+ do { \
|
|
+ volatile OrigFn _orig = (orig); \
|
|
+ volatile unsigned long _argvec[5]; \
|
|
+ volatile unsigned long _res; \
|
|
+ _argvec[0] = (unsigned long)_orig.nraddr; \
|
|
+ _argvec[1] = (unsigned long)(arg1); \
|
|
+ _argvec[2] = (unsigned long)(arg2); \
|
|
+ _argvec[3] = (unsigned long)(arg3); \
|
|
+ _argvec[4] = (unsigned long)(arg4); \
|
|
+ __asm__ volatile( \
|
|
+ VALGRIND_ALIGN_STACK \
|
|
+ "ldr x0, [%1, #8] \n\t" \
|
|
+ "ldr x1, [%1, #16] \n\t" \
|
|
+ "ldr x2, [%1, #24] \n\t" \
|
|
+ "ldr x3, [%1, #32] \n\t" \
|
|
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
|
|
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
|
|
+ VALGRIND_RESTORE_STACK \
|
|
+ "mov %0, x0" \
|
|
+ : /*out*/ "=r" (_res) \
|
|
+ : /*in*/ "0" (&_argvec[0]) \
|
|
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS/*, "r10"*/ \
|
|
+ ); \
|
|
+ lval = (__typeof__(lval)) _res; \
|
|
+ } while (0)
|
|
+
|
|
+#endif /* PLAT_arm64_linux */
|
|
+
|
|
/* ------------------------- s390x-linux ------------------------- */
|
|
|
|
#if defined(PLAT_s390x_linux)
|
|
Index: include/pub_tool_basics.h
|
|
===================================================================
|
|
--- include/pub_tool_basics.h.orig
|
|
+++ include/pub_tool_basics.h
|
|
@@ -269,7 +269,8 @@ static inline Bool sr_EQ ( SysRes sr1, S
|
|
#undef VG_LITTLEENDIAN
|
|
|
|
#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \
|
|
- || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEL))
|
|
+ || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEL)) \
|
|
+ || defined(VGA_arm64)
|
|
# define VG_LITTLEENDIAN 1
|
|
#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
|
|
|| ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEB))
|
|
@@ -283,7 +284,8 @@ static inline Bool sr_EQ ( SysRes sr1, S
|
|
# define VG_REGPARM(n) __attribute__((regparm(n)))
|
|
#elif defined(VGA_amd64) || defined(VGA_ppc32) \
|
|
|| defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x) \
|
|
- || defined(VGA_mips32) || defined(VGA_mips64)
|
|
+ || defined(VGA_mips32) || defined(VGA_mips64) \
|
|
+ || defined(VGA_arm64)
|
|
# define VG_REGPARM(n) /* */
|
|
#else
|
|
# error Unknown arch
|
|
Index: include/pub_tool_vkiscnums_asm.h
|
|
===================================================================
|
|
--- include/pub_tool_vkiscnums_asm.h.orig
|
|
+++ include/pub_tool_vkiscnums_asm.h
|
|
@@ -51,6 +51,9 @@
|
|
#elif defined(VGP_arm_linux)
|
|
# include "vki/vki-scnums-arm-linux.h"
|
|
|
|
+#elif defined(VGP_arm64_linux)
|
|
+# include "vki/vki-scnums-arm64-linux.h"
|
|
+
|
|
#elif defined(VGP_mips32_linux)
|
|
# include "vki/vki-scnums-mips32-linux.h"
|
|
|
|
Index: Makefile.tool.am
|
|
===================================================================
|
|
--- Makefile.tool.am.orig
|
|
+++ Makefile.tool.am
|
|
@@ -52,6 +52,9 @@ TOOL_LDFLAGS_PPC64_LINUX = \
|
|
TOOL_LDFLAGS_ARM_LINUX = \
|
|
$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@
|
|
|
|
+TOOL_LDFLAGS_ARM64_LINUX = \
|
|
+ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@
|
|
+
|
|
TOOL_LDFLAGS_S390X_LINUX = \
|
|
$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@
|
|
|
|
@@ -105,6 +108,9 @@ LIBREPLACEMALLOC_PPC64_LINUX = \
|
|
LIBREPLACEMALLOC_ARM_LINUX = \
|
|
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm-linux.a
|
|
|
|
+LIBREPLACEMALLOC_ARM64_LINUX = \
|
|
+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm64-linux.a
|
|
+
|
|
LIBREPLACEMALLOC_X86_DARWIN = \
|
|
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-darwin.a
|
|
|
|
@@ -145,6 +151,11 @@ LIBREPLACEMALLOC_LDFLAGS_ARM_LINUX = \
|
|
$(LIBREPLACEMALLOC_ARM_LINUX) \
|
|
-Wl,--no-whole-archive
|
|
|
|
+LIBREPLACEMALLOC_LDFLAGS_ARM64_LINUX = \
|
|
+ -Wl,--whole-archive \
|
|
+ $(LIBREPLACEMALLOC_ARM64_LINUX) \
|
|
+ -Wl,--no-whole-archive
|
|
+
|
|
LIBREPLACEMALLOC_LDFLAGS_X86_DARWIN = \
|
|
$(LIBREPLACEMALLOC_X86_DARWIN)
|
|
|
|
Index: docs/internals/register-uses.txt
|
|
===================================================================
|
|
--- docs/internals/register-uses.txt.orig
|
|
+++ docs/internals/register-uses.txt
|
|
@@ -134,6 +134,46 @@ insns have reg+offset forms for offsets
|
|
often isn't enough.
|
|
|
|
|
|
+arm64-linux
|
|
+~~~~~~~~~~~
|
|
+
|
|
+Reg Callee Arg
|
|
+Name Saves? Reg? Comment Vex-uses?
|
|
+---------------------------------------------------------------
|
|
+r0 int#0 ret#0 (??)
|
|
+r1 int#1 ret#1 (??)
|
|
+r2-7 int#2..7
|
|
+r8 "Indirect res loc reg"
|
|
+r9 "Temporary regs" chaining scratch
|
|
+r10-15 "Temporary regs" avail
|
|
+r16(IP0)
|
|
+r17(IP1)
|
|
+r18 "Platform reg"
|
|
+r19-20 maybe "Temporary regs"
|
|
+r21 y "Callee saved" GSP
|
|
+r22-28 y "Callee saved"
|
|
+r29(FP) y
|
|
+r30(LR) y
|
|
+
|
|
+NZCV "Status register"
|
|
+
|
|
+Is there a TLS register?
|
|
+
|
|
+x21 is the GSP. x9 is a scratch chaining/spill temp. Neither
|
|
+are available to the register allocator.
|
|
+
|
|
+Q registers:
|
|
+It's a little awkward. Basically, D registers are the same as ARM,
|
|
+so d0-d7 and d16-d31 are caller-saved, but d8-d15 are callee-saved.
|
|
+
|
|
+Q registers are the same, except that the upper 64 bits of q8-q15
|
|
+are caller-saved.
|
|
+
|
|
+The idea is that you only need to preserve D registers, not Q
|
|
+registers.
|
|
+
|
|
+
|
|
+
|
|
s390x-linux
|
|
~~~~~~~~~~~
|
|
|
|
Index: Makefile.vex.am
|
|
===================================================================
|
|
--- Makefile.vex.am.orig
|
|
+++ Makefile.vex.am
|
|
@@ -24,6 +24,7 @@ pkginclude_HEADERS = \
|
|
pub/libvex_guest_ppc32.h \
|
|
pub/libvex_guest_ppc64.h \
|
|
pub/libvex_guest_arm.h \
|
|
+ pub/libvex_guest_arm64.h \
|
|
pub/libvex_guest_s390x.h \
|
|
pub/libvex_guest_mips32.h \
|
|
pub/libvex_guest_mips64.h \
|
|
@@ -42,6 +43,7 @@ noinst_HEADERS = \
|
|
priv/guest_amd64_defs.h \
|
|
priv/guest_ppc_defs.h \
|
|
priv/guest_arm_defs.h \
|
|
+ priv/guest_arm64_defs.h \
|
|
priv/guest_s390_defs.h \
|
|
priv/guest_mips_defs.h \
|
|
priv/host_generic_regs.h \
|
|
@@ -53,6 +55,7 @@ noinst_HEADERS = \
|
|
priv/host_amd64_defs.h \
|
|
priv/host_ppc_defs.h \
|
|
priv/host_arm_defs.h \
|
|
+ priv/host_arm64_defs.h \
|
|
priv/host_s390_defs.h \
|
|
priv/s390_disasm.h \
|
|
priv/s390_defs.h \
|
|
@@ -71,6 +74,7 @@ pub/libvex_guest_offsets.h: auxprogs/gen
|
|
pub/libvex_guest_ppc32.h \
|
|
pub/libvex_guest_ppc64.h \
|
|
pub/libvex_guest_arm.h \
|
|
+ pub/libvex_guest_arm64.h \
|
|
pub/libvex_guest_s390x.h \
|
|
pub/libvex_guest_mips32.h \
|
|
pub/libvex_guest_mips64.h
|
|
@@ -114,6 +118,8 @@ LIBVEX_SOURCES_COMMON = \
|
|
priv/guest_ppc_toIR.c \
|
|
priv/guest_arm_helpers.c \
|
|
priv/guest_arm_toIR.c \
|
|
+ priv/guest_arm64_helpers.c \
|
|
+ priv/guest_arm64_toIR.c \
|
|
priv/guest_s390_helpers.c \
|
|
priv/guest_s390_toIR.c \
|
|
priv/guest_mips_helpers.c \
|
|
@@ -132,6 +138,8 @@ LIBVEX_SOURCES_COMMON = \
|
|
priv/host_ppc_isel.c \
|
|
priv/host_arm_defs.c \
|
|
priv/host_arm_isel.c \
|
|
+ priv/host_arm64_defs.c \
|
|
+ priv/host_arm64_isel.c \
|
|
priv/host_s390_defs.c \
|
|
priv/host_s390_isel.c \
|
|
priv/s390_disasm.c \
|
|
Index: coregrind/vgdb.c
|
|
===================================================================
|
|
--- coregrind/vgdb.c.orig
|
|
+++ coregrind/vgdb.c
|
|
@@ -80,7 +80,7 @@
|
|
can be "waken up". PTRACEINVOKER implies some architecture
|
|
specific code and/or some OS specific code. */
|
|
#if defined(VGA_arm) || defined(VGA_x86) || defined(VGA_amd64) \
|
|
- || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
|
|
+ || defined(VGA_ppc32) || defined(VGA_ppc64le) || defined(VGA_ppc64be) || defined(VGA_s390x) \
|
|
|| defined(VGA_mips32) || defined(VGA_mips64)
|
|
#define PTRACEINVOKER
|
|
#else
|
|
@@ -911,7 +911,7 @@ Bool invoke_gdbserver (int pid)
|
|
sp = user_mod.regs.uregs[13];
|
|
#elif defined(VGA_ppc32)
|
|
sp = user_mod.regs.gpr[1];
|
|
-#elif defined(VGA_ppc64)
|
|
+#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
|
|
sp = user_mod.regs.gpr[1];
|
|
#elif defined(VGA_s390x)
|
|
sp = user_mod.regs.gprs[15];
|
|
@@ -975,7 +975,7 @@ Bool invoke_gdbserver (int pid)
|
|
I_die_here : not x86 or amd64 in x86/amd64 section/
|
|
#endif
|
|
|
|
-#elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
|
+#elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
|
|
user_mod.regs.nip = shared32->invoke_gdbserver;
|
|
user_mod.regs.trap = -1L;
|
|
/* put check arg in register 3 */
|
|
@@ -1042,7 +1042,7 @@ Bool invoke_gdbserver (int pid)
|
|
assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
|
|
#elif defined(VGA_ppc32)
|
|
assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
|
|
-#elif defined(VGA_ppc64)
|
|
+#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
|
|
Addr64 func_addr;
|
|
Addr64 toc_addr;
|
|
int rw;
|