From: Petar Jovanovic Date: Wed, 27 Feb 2013 23:17:33 +0000 (+0000) Subject: mips: adding MIPS64LE support to Valgrind X-Git-Tag: svn/VALGRIND_3_9_0~389 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5dd4c02e39ed0e4e5cb12675e8722fe3f40997bd;p=thirdparty%2Fvalgrind.git mips: adding MIPS64LE support to Valgrind Necessary changes to Valgrind to support MIPS64LE on Linux. Minor cleanup/style changes embedded in the patch as well. The change corresponds to r2687 in VEX. Patch written by Dejan Jevtic and Petar Jovanovic. More information about this issue: https://bugs.kde.org/show_bug.cgi?id=313267 git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13292 --- diff --git a/Makefile.all.am b/Makefile.all.am index 66bd414feb..1f69802c22 100644 --- a/Makefile.all.am +++ b/Makefile.all.am @@ -176,6 +176,9 @@ AM_FLAG_M3264_MIPS32_LINUX = @FLAG_M32@ AM_CFLAGS_MIPS32_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE) -mips32 AM_CCASFLAGS_MIPS32_LINUX = @FLAG_M32@ -mips32 -g +AM_FLAG_M3264_MIPS64_LINUX = @FLAG_M64@ +AM_CFLAGS_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) -mips64 +AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -mips64 -g # Flags for the primary target. These must be used to build the # regtests and performance tests. In fact, these must be used to @@ -214,4 +217,5 @@ 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@ PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ +PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ diff --git a/Makefile.tool.am b/Makefile.tool.am index 6f5a6eab53..b6c1509c94 100644 --- a/Makefile.tool.am +++ b/Makefile.tool.am @@ -64,6 +64,10 @@ TOOL_LDFLAGS_MIPS32_LINUX = \ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ @FLAG_M32@ +TOOL_LDFLAGS_MIPS64_LINUX = \ + -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ + @FLAG_M64@ + # On Android we must ask for non-executable stack, not sure why. if VGCONF_PLATFORMS_INCLUDE_ARM_LINUX if VGCONF_PLATVARIANT_IS_ANDROID @@ -111,6 +115,9 @@ LIBREPLACEMALLOC_S390X_LINUX = \ LIBREPLACEMALLOC_MIPS32_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips32-linux.a +LIBREPLACEMALLOC_MIPS64_LINUX = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a + LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \ -Wl,--whole-archive \ $(LIBREPLACEMALLOC_X86_LINUX) \ @@ -152,6 +159,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS32_LINUX = \ $(LIBREPLACEMALLOC_MIPS32_LINUX) \ -Wl,--no-whole-archive +LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_MIPS64_LINUX) \ + -Wl,--no-whole-archive + #---------------------------------------------------------------------------- # General stuff #---------------------------------------------------------------------------- diff --git a/README b/README index 9af6be278e..075227f739 100644 --- a/README +++ b/README @@ -41,6 +41,7 @@ platforms: - AMD64/MacOSX - S390X/Linux - MIPS32/Linux +- MIPS64/Linux Note that AMD64 is just another name for x86_64, and Valgrind runs fine on Intel processors. Also note that the core of MacOSX is called diff --git a/cachegrind/cg-arch.c b/cachegrind/cg-arch.c index da20441c65..18d2912e8c 100644 --- a/cachegrind/cg-arch.c +++ b/cachegrind/cg-arch.c @@ -404,6 +404,13 @@ configure_caches(cache_t *I1c, cache_t *D1c, cache_t *LLc, *D1c = (cache_t) { 32768, 4, 32 }; *LLc = (cache_t) { 524288, 8, 32 }; +#elif defined(VGA_mips64) + + // Set caches to default (for MIPS64 - 5kc) + *I1c = (cache_t) { 32768, 4, 32 }; + *D1c = (cache_t) { 32768, 4, 32 }; + *LLc = (cache_t) { 524288, 8, 32 }; + #elif defined(VGA_x86) || defined(VGA_amd64) *I1c = (cache_t) { 65536, 2, 64 }; diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c index cc246c311c..0324d31ac7 100644 --- a/cachegrind/cg_branchpred.c +++ b/cachegrind/cg_branchpred.c @@ -45,7 +45,7 @@ /* 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_mips32) || defined(VGA_mips64) # define N_IADDR_LO_ZERO_BITS 2 #elif defined(VGA_x86) || defined(VGA_amd64) # define N_IADDR_LO_ZERO_BITS 0 diff --git a/configure.in b/configure.in index 0f3b3df874..391b763ba2 100644 --- a/configure.in +++ b/configure.in @@ -192,20 +192,29 @@ case "${host_cpu}" in ;; mips) - AC_MSG_RESULT([ok (${host_cpu})]) - ARCH_MAX="mips32" - ;; + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; mipsel) - AC_MSG_RESULT([ok (${host_cpu})]) - ARCH_MAX="mips32" - ;; + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; mipsisa32r2) - AC_MSG_RESULT([ok (${host_cpu})]) - ARCH_MAX="mips32" - ;; + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; + mips64*) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips64" + ;; + + mipsisa64*) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips64" + ;; *) AC_MSG_RESULT([no (${host_cpu})]) AC_MSG_ERROR([Unsupported host architecture. Sorry]) @@ -567,7 +576,16 @@ case "$ARCH_MAX-$VGCONF_OS" in valt_load_address_sec_norml="0xUNSET" valt_load_address_sec_inner="0xUNSET" AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) - AC_MSG_RESULT([ok (${host_cpu}-${host_os})]) + ;; + mips64-linux) + VGCONF_ARCH_PRI="mips64" + VGCONF_PLATFORM_PRI_CAPS="MIPS64_LINUX" + VGCONF_PLATFORM_SEC_CAPS="" + valt_load_address_pri_norml="0x38000000" + valt_load_address_pri_inner="0x28000000" + valt_load_address_sec_norml="0xUNSET" + valt_load_address_sec_inner="0xUNSET" + AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) ;; *) VGCONF_ARCH_PRI="unknown" @@ -606,6 +624,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_S390X, test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ) AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS32, test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX ) +AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS64, + test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ) # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these # become defined. @@ -626,6 +646,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX, -o x$VGCONF_PLATFORM_SEC_CAPS = xS390X_LINUX) AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS32_LINUX, 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 \ @@ -644,7 +666,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX, -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ - -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX) + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX) AM_CONDITIONAL(VGCONF_OS_IS_DARWIN, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_DARWIN) @@ -2079,7 +2102,8 @@ mflag_primary= if test x$VGCONF_PLATFORM_PRI_CAPS = xX86_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ - -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX ; then + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ; then mflag_primary=$FLAG_M32 elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index d557e14935..d2ac70d6c6 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -308,6 +308,7 @@ COREGRIND_SOURCES_COMMON = \ m_dispatch/dispatch-arm-linux.S \ m_dispatch/dispatch-s390x-linux.S \ m_dispatch/dispatch-mips32-linux.S \ + m_dispatch/dispatch-mips64-linux.S \ m_dispatch/dispatch-x86-darwin.S \ m_dispatch/dispatch-amd64-darwin.S \ m_gdbserver/inferiors.c \ @@ -325,6 +326,7 @@ COREGRIND_SOURCES_COMMON = \ m_gdbserver/valgrind-low-ppc64.c \ m_gdbserver/valgrind-low-s390x.c \ m_gdbserver/valgrind-low-mips32.c \ + m_gdbserver/valgrind-low-mips64.c \ m_gdbserver/version.c \ m_initimg/initimg-linux.c \ m_initimg/initimg-darwin.c \ @@ -345,6 +347,7 @@ COREGRIND_SOURCES_COMMON = \ m_sigframe/sigframe-arm-linux.c \ m_sigframe/sigframe-s390x-linux.c \ m_sigframe/sigframe-mips32-linux.c \ + m_sigframe/sigframe-mips64-linux.c \ m_sigframe/sigframe-x86-darwin.c \ m_sigframe/sigframe-amd64-darwin.c \ m_syswrap/syscall-x86-linux.S \ @@ -354,6 +357,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syscall-arm-linux.S \ m_syswrap/syscall-s390x-linux.S \ m_syswrap/syscall-mips32-linux.S \ + m_syswrap/syscall-mips64-linux.S \ m_syswrap/syscall-x86-darwin.S \ m_syswrap/syscall-amd64-darwin.S \ m_syswrap/syswrap-main.c \ @@ -368,6 +372,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syswrap-arm-linux.c \ m_syswrap/syswrap-s390x-linux.c \ m_syswrap/syswrap-mips32-linux.c \ + m_syswrap/syswrap-mips64-linux.c \ m_syswrap/syswrap-x86-darwin.c \ m_syswrap/syswrap-amd64-darwin.c \ m_syswrap/syswrap-xen.c \ @@ -554,7 +559,18 @@ GDBSERVER_XML_FILES = \ m_gdbserver/mips-linux-valgrind.xml \ m_gdbserver/mips-fpu-valgrind-s1.xml \ m_gdbserver/mips-fpu-valgrind-s2.xml \ - m_gdbserver/mips-fpu.xml + m_gdbserver/mips-fpu.xml \ + m_gdbserver/mips64-cp0-valgrind-s1.xml \ + m_gdbserver/mips64-cp0-valgrind-s2.xml \ + m_gdbserver/mips64-cp0.xml \ + m_gdbserver/mips64-cpu-valgrind-s1.xml \ + m_gdbserver/mips64-cpu-valgrind-s2.xml \ + m_gdbserver/mips64-cpu.xml \ + m_gdbserver/mips64-linux.xml \ + m_gdbserver/mips64-linux-valgrind.xml \ + m_gdbserver/mips64-fpu-valgrind-s1.xml \ + m_gdbserver/mips64-fpu-valgrind-s2.xml \ + m_gdbserver/mips64-fpu.xml # so as to make sure these get copied into the install tree vglibdir = $(pkglibdir) diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c index 5c77071af8..469380f25c 100644 --- a/coregrind/launcher-linux.c +++ b/coregrind/launcher-linux.c @@ -211,6 +211,10 @@ static const char *select_platform(const char *clientname) (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { platform = "amd64-linux"; + } else if (ehdr->e_machine == EM_MIPS && + (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || + ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { + platform = "mips64-linux"; } } else if (header[EI_DATA] == ELFDATA2MSB) { # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) @@ -224,6 +228,10 @@ static const char *select_platform(const char *clientname) (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { platform = "s390x-linux"; + } else if (ehdr->e_machine == EM_MIPS && + (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || + ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { + platform = "mips64-linux"; } # endif } @@ -300,7 +308,8 @@ int main(int argc, char** argv, char** envp) (0==strcmp(VG_PLATFORM,"ppc64-linux")) || (0==strcmp(VG_PLATFORM,"arm-linux")) || (0==strcmp(VG_PLATFORM,"s390x-linux")) || - (0==strcmp(VG_PLATFORM,"mips32-linux"))) + (0==strcmp(VG_PLATFORM,"mips32-linux")) || + (0==strcmp(VG_PLATFORM,"mips64-linux"))) default_platform = VG_PLATFORM; else barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM); diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index 45d7d086d3..228ba8fe33 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -159,7 +159,8 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot, 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_s390x_linux) || defined(VGP_mips32_linux) \ + || defined(VGP_mips64_linux) res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, prot, flags, fd, offset); # elif defined(VGP_x86_darwin) diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index eddb4de7b1..9db3820a23 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -2533,7 +2533,7 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot, /* Ask for an advisory. If it's negative, fail immediately. */ req.rkind = MAny; req.start = 0; - #if defined(VGA_arm) || defined(VGA_mips32) + #if defined(VGA_arm) || defined(VGA_mips32) || defined(VGA_mips64) aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); #else aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE); diff --git a/coregrind/m_cache.c b/coregrind/m_cache.c index f83f62d9a3..077fc0a9a5 100644 --- a/coregrind/m_cache.c +++ b/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_mips32) || defined(VGA_mips64) static Bool get_cache_info(VexArchInfo *vai) diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c index bc6b3f84ae..ebf31d0dbe 100644 --- a/coregrind/m_coredump/coredump-elf.c +++ b/coregrind/m_coredump/coredump-elf.c @@ -376,6 +376,15 @@ static void fill_prstatus(const ThreadState *tst, # 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); + DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); + DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); + DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); +# 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); DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); @@ -471,6 +480,13 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); # undef DO +#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) +# define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_f##n) + DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); + DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); + DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); + DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); +# undef DO #else # error Unknown ELF platform #endif diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c index 14ae9eff8c..e53094be7c 100644 --- a/coregrind/m_debugger.c +++ b/coregrind/m_debugger.c @@ -307,7 +307,7 @@ static Int ptrace_setregs(Int pid, VexGuestArchState* vex) return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid, &pa, NULL); -#elif defined(VGP_mips32_linux) +#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) struct vki_user_regs_struct regs; VG_(memset)(®s, 0, sizeof(regs)); regs.MIPS_r0 = vex->guest_r0; diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c index 88475bc309..13297fb76c 100644 --- a/coregrind/m_debuginfo/d3basics.c +++ b/coregrind/m_debuginfo/d3basics.c @@ -415,6 +415,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs ) # elif defined(VGP_mips32_linux) if (regno == 29) { *a = regs->sp; return True; } if (regno == 30) { *a = regs->fp; return True; } +# elif defined(VGP_mips64_linux) + if (regno == 29) { *a = regs->sp; return True; } + if (regno == 30) { *a = regs->fp; return True; } # else # error "Unknown platform" # endif diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 2d7ec822c7..e866420311 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -819,7 +819,8 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ) is_rw_map = False; is_ro_map = False; -# if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) +# if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \ + || 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) @@ -2105,7 +2106,7 @@ UWord evalCfiExpr ( XArray* exprs, Int ix, case Creg_IA_SP: return eec->uregs->sp; case Creg_IA_BP: return eec->uregs->fp; case Creg_S390_R14: return eec->uregs->lr; -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) case Creg_IA_IP: return eec->uregs->pc; case Creg_IA_SP: return eec->uregs->sp; case Creg_IA_BP: return eec->uregs->fp; @@ -2344,7 +2345,7 @@ static Addr compute_cfa ( D3UnwindRegs* uregs, case CFIC_IA_BPREL: cfa = cfsi->cfa_off + uregs->fp; break; -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) case CFIC_IA_SPREL: cfa = cfsi->cfa_off + uregs->sp; break; @@ -2448,7 +2449,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, ipHere = uregsHere->r15; # elif defined(VGA_s390x) ipHere = uregsHere->ia; -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) ipHere = uregsHere->pc; # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else @@ -2526,7 +2527,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off); 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_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off); COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off); COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off); diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index a88c2e4e19..ecf7fae735 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -257,7 +257,7 @@ typedef Int fp_off; } DiCfSI; -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_mips64) typedef struct { Addr base; diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index e5471706fd..ce34bc767b 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -1859,6 +1859,10 @@ void ML_(read_debuginfo_dwarf1) ( # define FP_REG 30 # define SP_REG 29 # define RA_REG_DEFAULT 31 +#elif defined(VGP_mips64_linux) +# define FP_REG 30 +# define SP_REG 29 +# define RA_REG_DEFAULT 31 #else # error "Unknown platform" #endif @@ -1868,7 +1872,7 @@ void ML_(read_debuginfo_dwarf1) ( 7 (DWARF for the ARM Architecture) specifies that values up to 320 might exist, for Neon/VFP-v3. */ #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) # define N_CFI_REGS 72 #elif defined(VGP_arm_linux) # define N_CFI_REGS 320 @@ -2173,7 +2177,7 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) { si->cfa_off = ctxs->cfa_off; # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ - || defined(VGA_mips32) + || defined(VGA_mips32) || defined(VGA_mips64) si->cfa_how = CFIC_IA_SPREL; # elif defined(VGA_arm) si->cfa_how = CFIC_ARM_R13REL; @@ -2185,7 +2189,7 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) { si->cfa_off = ctxs->cfa_off; # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ - || defined(VGA_mips32) + || defined(VGA_mips32) || defined(VGA_mips64) si->cfa_how = CFIC_IA_BPREL; # elif defined(VGA_arm) si->cfa_how = CFIC_ARM_R12REL; @@ -2386,7 +2390,7 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, return True; -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) /* --- entire tail of this fn specialised for mips --- */ @@ -2512,7 +2516,7 @@ static Int copy_convert_CfiExpr_tree ( XArray* dstxa, return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP ); if (dwreg == srcuc->ra_reg) return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */ -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) if (dwreg == SP_REG) return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP ); if (dwreg == FP_REG) diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index 204af5569a..cf7b5d34c0 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -2042,7 +2042,7 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) /* 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_mips32_linux) || defined(VGP_mips64_linux) /* Accept .plt where mapped as rx (code) */ if (0 == VG_(strcmp)(name, ".plt")) { if (inrx && !di->plt_present) { @@ -2693,7 +2693,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) && !defined(VGP_s390x_linux) \ && !defined(VGP_ppc64_linux) \ && !defined(VGPV_arm_linux_android) \ - && !defined(VGPV_x86_linux_android) + && !defined(VGPV_x86_linux_android) \ + && !defined(VGP_mips64_linux) if (stab_img && stabstr_img) { ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz, stabstr_img, stabstr_sz ); diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index f344c8f70e..43e4a8fb61 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -189,7 +189,7 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si ) VG_(printf)(" R7="); SHOW_HOW(si->r7_how, si->r7_off); # elif defined(VGA_ppc32) || defined(VGA_ppc64) -# elif defined(VGA_s390x) || defined(VGA_mips32) +# elif defined(VGA_s390x) || defined(VGA_mips32) || defined(VGA_mips64) VG_(printf)(" SP="); SHOW_HOW(si->sp_how, si->sp_off); VG_(printf)(" FP="); diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c index 3c6025e2b0..961d86c544 100644 --- a/coregrind/m_debuglog.c +++ b/coregrind/m_debuglog.c @@ -427,6 +427,42 @@ static UInt local_sys_getpid ( void ) return __res; } +#elif defined(VGP_mips64_linux) +static UInt local_sys_write_stderr ( const HChar* buf, Int n ) +{ + volatile Long block[2]; + block[0] = (Long)buf; + block[1] = n; + __asm__ volatile ( + "li $4, 2\n\t" /* std output*/ + "ld $5, 0(%0)\n\t" /*$5 = buf*/ + "ld $6, 8(%0)\n\t" /*$6 = n */ + "move $7, $0\n\t" + "li $2, %1\n\t" /* set v0 = __NR_write */ + "\tsyscall\n" + "\tnop\n" + : /*wr*/ + : /*rd*/ "r" (block), "n" (__NR_write) + : "2", "4", "5", "6", "7" + ); + if (block[0] < 0) + block[0] = -1; + return (UInt)(Int)block[0]; +} + +static UInt local_sys_getpid ( void ) +{ + ULong __res; + __asm__ volatile ( + "li $2, %1\n\t" /* set v0 = __NR_getpid */ + "syscall\n\t" /* getpid() */ + "nop\n\t" + "move %0, $2\n" + : "=r" (__res) + : "n" (__NR_getpid) + : "$2" ); + return (UInt)(__res); +} #else # error Unknown platform diff --git a/coregrind/m_dispatch/dispatch-mips32-linux.S b/coregrind/m_dispatch/dispatch-mips32-linux.S index f732b3c7c7..a059b98afc 100644 --- a/coregrind/m_dispatch/dispatch-mips32-linux.S +++ b/coregrind/m_dispatch/dispatch-mips32-linux.S @@ -87,8 +87,8 @@ VG_(disp_run_translations): return values can be written */ sw $4, 60($29) - /* Load address of guest state into guest state register (r10) */ - move $10, $5 + /* Load address of guest state into guest state register ($23) */ + move $23, $5 /* and jump into the code cache. Chained translations in the code cache run, until for whatever reason, they can't @@ -103,9 +103,9 @@ VG_(disp_run_translations): /*----------------------------------------------------*/ postamble: - /* At this point, r2 and r3 contain two - words to be returned to the caller. r2 - holds a TRC value, and r3 optionally may + /* At this point, $2 and $3 contain two + words to be returned to the caller. $2 + holds a TRC value, and $3 optionally may hold another word (for CHAIN_ME exits, the address of the place to patch.) */ @@ -175,7 +175,7 @@ VG_(disp_cp_chain_me_to_fastEP): .global VG_(disp_cp_xindir) VG_(disp_cp_xindir): /* Where are we going? */ - lw $11, OFFSET_mips32_PC($10) + lw $11, OFFSET_mips32_PC($23) lw $13, vgPlain_stats__n_xindirs_32 addiu $13, $13, 0x1 @@ -222,7 +222,7 @@ fast_lookup_failed: VG_(disp_cp_xassisted): /* guest-state-pointer contains the TRC. Put the value into the return register */ - move $2, $10 + move $2, $23 move $3, $0 b postamble diff --git a/coregrind/m_dispatch/dispatch-mips64-linux.S b/coregrind/m_dispatch/dispatch-mips64-linux.S new file mode 100644 index 0000000000..152a633a6b --- /dev/null +++ b/coregrind/m_dispatch/dispatch-mips64-linux.S @@ -0,0 +1,245 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-mips64-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2013 RT-RK + mips-valgrind@rt-rk.com + + 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_mips64_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_mips_PC */ + + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- 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 +.globl VG_(disp_run_translations) +VG_(disp_run_translations): + /* a0 ($4) holds two_words */ + /* a1 ($5) holds guest_state */ + /* a2 ($6) holds host_addr */ + + /* New stack frame. Stack must remain 16 aligned (at least) */ + daddiu $29, -176 + + /* Save ra */ + sd $31, 72($29) + + /* ... and s0 - s7 */ + sd $16, 80($29) + sd $17, 88($29) + sd $18, 96($29) + sd $19, 104($29) + sd $20, 112($29) + sd $21, 120($29) + sd $22, 128($29) + sd $23, 136($29) + + /* ... and gp, fp/s8 */ + sd $28, 144($29) + sd $30, 152($29) + + /* Save a0 ($4) on stack. In postamble it will be restored such that the + return values can be written */ + sd $4, 160($29) + + /* Load address of guest state into guest state register ($23) */ + move $23, $5 + + /* 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. */ + jr $6 + /*NOTREACHED*/ + +/*----------------------------------------------------*/ +/*--- Postamble and exit. ---*/ +/*----------------------------------------------------*/ + +postamble: + /* At this point, $2 and $3 contain two + words to be returned to the caller. $2 + holds a TRC value, and $3 optionally may + hold another word (for CHAIN_ME exits, the + address of the place to patch.) */ + + /* Restore $4 from stack; holds address of two_words */ + ld $4, 160($29) + sd $2, 0($4) /* Store $2 to two_words[0] */ + sd $3, 8($4) /* Store $3 to two_words[1] */ + + /* Restore callee-saved registers... */ + + /* Restore ra */ + ld $31, 72($29) + + /* ... and s0 - s7 */ + ld $16, 80($29) + ld $17, 88($29) + ld $18, 96($29) + ld $19, 104($29) + ld $20, 112($29) + ld $21, 120($29) + ld $22, 128($29) + ld $23, 136($29) + + /* ... and gp, fp/s8 */ + ld $28, 144($29) + ld $30, 152($29) + + daddiu $29, 176 /* stack_size */ + jr $31 + nop + +/*----------------------------------------------------*/ +/*--- 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) */ + li $2, VG_TRC_CHAIN_ME_TO_SLOW_EP + move $3, $31 + /* 8 = mkLoadImm_EXACTLY2or6 + 4 = jalr $9 + 4 = nop */ + daddiu $3, $3, -32 + b postamble + +/* ------ Chain me to slow 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_S, RA) */ + li $2, VG_TRC_CHAIN_ME_TO_FAST_EP + move $3, $31 + /* 8 = mkLoadImm_EXACTLY2or6 + 4 = jalr $9 + 4 = nop */ + daddiu $3, $3, -32 + b postamble + +/* ------ Indirect but boring jump ------ */ +.global VG_(disp_cp_xindir) +VG_(disp_cp_xindir): + /* Where are we going? */ + ld $11, OFFSET_mips64_PC($23) + + lw $13, vgPlain_stats__n_xindirs_32 + addiu $13, $13, 0x1 + sw $13, vgPlain_stats__n_xindirs_32 + + /* try a fast lookup in the translation cache */ + /* t1 = VG_TT_FAST_HASH(addr) * sizeof(ULong*) + = (t8 >> 2 & VG_TT_FAST_MASK) << 3 */ + + move $14, $11 + li $12, VG_TT_FAST_MASK + srl $14, $14, 2 + and $14, $14, $12 + sll $14, $14, 3 + + /* t2 = (addr of VG_(tt_fast)) + t1 */ + la $13, VG_(tt_fast) + addu $13, $13, $14 + + ld $12, 0($13) /* t3 = VG_(tt_fast)[hash] :: ULong* */ + addi $13, $13, 8 + ld $25, 0($13) /* little-endian, so comparing 1st 32bit word */ + nop + +check: + bne $12, $11, fast_lookup_failed + /* run the translation */ + jr $25 + .long 0x0 /* persuade insn decoders not to speculate past here */ + +fast_lookup_failed: + /* %PC is up to date */ + /* back out decrement of the dispatch counter */ + /* hold dispatch_ctr in t0 (r8) */ + lw $13, vgPlain_stats__n_xindirs_32 + addiu $13, $13, 0x1 + sw $13, vgPlain_stats__n_xindirs_32 + li $2, VG_TRC_INNER_FASTMISS + li $3, 0 + b postamble + +/* ------ Assisted jump ------ */ + .global VG_(disp_cp_xassisted) +VG_(disp_cp_xassisted): + /* guest-state-pointer contains the TRC. Put the value into the + return register */ + move $2, $23 + move $3, $0 + b postamble + +/* ------ Event check failed ------ */ + .global VG_(disp_cp_evcheck_fail) +VG_(disp_cp_evcheck_fail): + li $2, VG_TRC_INNER_COUNTERZERO + move $3, $0 + b postamble + +.size VG_(disp_run_translations), .-VG_(disp_run_translations) + + +/* Let the linker know we do not need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif // defined(VGP_mips64_linux) +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml new file mode 100644 index 0000000000..21447d1294 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml new file mode 100644 index 0000000000..3623f39fff --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-cp0.xml b/coregrind/m_gdbserver/mips64-cp0.xml new file mode 100644 index 0000000000..d6d422fd6a --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cp0.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml new file mode 100644 index 0000000000..549dd72bd3 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml new file mode 100644 index 0000000000..f054a8fde7 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-cpu.xml b/coregrind/m_gdbserver/mips64-cpu.xml new file mode 100644 index 0000000000..5ee6cfae8f --- /dev/null +++ b/coregrind/m_gdbserver/mips64-cpu.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml new file mode 100644 index 0000000000..6aa735e811 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml new file mode 100644 index 0000000000..3d5c2783e7 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-fpu.xml b/coregrind/m_gdbserver/mips64-fpu.xml new file mode 100644 index 0000000000..e5a39150ec --- /dev/null +++ b/coregrind/m_gdbserver/mips64-fpu.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coregrind/m_gdbserver/mips64-linux-valgrind.xml b/coregrind/m_gdbserver/mips64-linux-valgrind.xml new file mode 100644 index 0000000000..baf65336e7 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-linux-valgrind.xml @@ -0,0 +1,24 @@ + + + + + + mips + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/mips64-linux.xml b/coregrind/m_gdbserver/mips64-linux.xml new file mode 100644 index 0000000000..58d5a154f4 --- /dev/null +++ b/coregrind/m_gdbserver/mips64-linux.xml @@ -0,0 +1,18 @@ + + + + + + mips + + + + + + + + \ No newline at end of file diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c index 7c95ecde1a..72cf24243c 100644 --- a/coregrind/m_gdbserver/target.c +++ b/coregrind/m_gdbserver/target.c @@ -649,6 +649,8 @@ void valgrind_initialize_target(void) s390x_init_architecture(&the_low_target); #elif defined(VGA_mips32) mips32_init_architecture(&the_low_target); +#elif defined(VGA_mips64) + mips64_init_architecture(&the_low_target); #else architecture missing in target.c valgrind_initialize_target #endif diff --git a/coregrind/m_gdbserver/valgrind-low-mips64.c b/coregrind/m_gdbserver/valgrind-low-mips64.c new file mode 100644 index 0000000000..9c073364d0 --- /dev/null +++ b/coregrind/m_gdbserver/valgrind-low-mips64.c @@ -0,0 +1,259 @@ +/* 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 "valgrind_low.h" + +#include "libvex_guest_mips64.h" + +static struct reg regs[] = { + { "r0", 0, 64 }, + { "r1", 64, 64 }, + { "r2", 128, 64 }, + { "r3", 192, 64 }, + { "r4", 256, 64 }, + { "r5", 320, 64 }, + { "r6", 384, 64 }, + { "r7", 448, 64 }, + { "r8", 512, 64 }, + { "r9", 576, 64 }, + { "r10", 640, 64 }, + { "r11", 704, 64 }, + { "r12", 768, 64 }, + { "r13", 832, 64 }, + { "r14", 896, 64 }, + { "r15", 960, 64 }, + { "r16", 1024, 64 }, + { "r17", 1088, 64 }, + { "r18", 1152, 64 }, + { "r19", 1216, 64 }, + { "r20", 1280, 64 }, + { "r21", 1344, 64 }, + { "r22", 1408, 64 }, + { "r23", 1472, 64 }, + { "r24", 1536, 64 }, + { "r25", 1600, 64 }, + { "r26", 1664, 64 }, + { "r27", 1728, 64 }, + { "r28", 1792, 64 }, + { "r29", 1856, 64 }, + { "r30", 1920, 64 }, + { "r31", 1984, 64 }, + { "status", 2048, 64 }, + { "lo", 2112, 64 }, + { "hi", 2176, 64 }, + { "badvaddr", 2240, 64 }, + { "cause", 2304, 64 }, + { "pc", 2368, 64 }, + { "f0", 2432, 64 }, + { "f1", 2496, 64 }, + { "f2", 2560, 64 }, + { "f3", 2624, 64 }, + { "f4", 2688, 64 }, + { "f5", 2752, 64 }, + { "f6", 2816, 64 }, + { "f7", 2880, 64 }, + { "f8", 2944, 64 }, + { "f9", 3008, 64 }, + { "f10", 3072, 64 }, + { "f11", 3136, 64 }, + { "f12", 3200, 64 }, + { "f13", 3264, 64 }, + { "f14", 3328, 64 }, + { "f15", 3392, 64 }, + { "f16", 3456, 64 }, + { "f17", 3520, 64 }, + { "f18", 3584, 64 }, + { "f19", 3648, 64 }, + { "f20", 3712, 64 }, + { "f21", 3776, 64 }, + { "f22", 3840, 64 }, + { "f23", 3904, 64 }, + { "f24", 3968, 64 }, + { "f25", 4032, 64 }, + { "f26", 4096, 64 }, + { "f27", 4160, 64 }, + { "f28", 4224, 64 }, + { "f29", 4288, 64 }, + { "f30", 4352, 64 }, + { "f31", 4416, 64 }, + { "fcsr", 4480, 64 }, + { "fir", 4544, 64 }, + { "restart", 4608, 64 } +}; + + +#define num_regs (sizeof (regs) / sizeof (regs[0])) + +static const char *expedite_regs[] = { "r29", "pc", 0 }; + +static +CORE_ADDR get_pc (void) +{ + unsigned long pc; + + collect_register_by_name ("pc", &pc); + + dlog(1, "stop pc is %p\n", (void *) pc); + return pc; +} + +static +void set_pc (CORE_ADDR newpc) +{ + Bool mod; + supply_register_by_name ("pc", &newpc, &mod); + if (mod) + dlog(1, "set pc to %p\n", C2v (newpc)); + else + dlog(1, "set pc not changed %p\n", C2v (newpc)); +} + +/* store registers in the guest state (gdbserver_to_valgrind) + or fetch register from the guest state (valgrind_to_gdbserver). */ +static +void transfer_register (ThreadId tid, int abs_regno, void * buf, + transfer_direction dir, int size, Bool *mod) +{ + ThreadState* tst = VG_(get_ThreadState)(tid); + int set = abs_regno / num_regs; + int regno = abs_regno % num_regs; + *mod = False; + + VexGuestMIPS64State* mips1 = (VexGuestMIPS64State*) get_arch (set, tst); + + switch (regno) { + case 0: VG_(transfer) (&mips1->guest_r0, buf, dir, size, mod); break; + case 1: VG_(transfer) (&mips1->guest_r1, buf, dir, size, mod); break; + case 2: VG_(transfer) (&mips1->guest_r2, buf, dir, size, mod); break; + case 3: VG_(transfer) (&mips1->guest_r3, buf, dir, size, mod); break; + case 4: VG_(transfer) (&mips1->guest_r4, buf, dir, size, mod); break; + case 5: VG_(transfer) (&mips1->guest_r5, buf, dir, size, mod); break; + case 6: VG_(transfer) (&mips1->guest_r6, buf, dir, size, mod); break; + case 7: VG_(transfer) (&mips1->guest_r7, buf, dir, size, mod); break; + case 8: VG_(transfer) (&mips1->guest_r8, buf, dir, size, mod); break; + case 9: VG_(transfer) (&mips1->guest_r9, buf, dir, size, mod); break; + case 10: VG_(transfer) (&mips1->guest_r10, buf, dir, size, mod); break; + case 11: VG_(transfer) (&mips1->guest_r11, buf, dir, size, mod); break; + case 12: VG_(transfer) (&mips1->guest_r12, buf, dir, size, mod); break; + case 13: VG_(transfer) (&mips1->guest_r13, buf, dir, size, mod); break; + case 14: VG_(transfer) (&mips1->guest_r14, buf, dir, size, mod); break; + case 15: VG_(transfer) (&mips1->guest_r15, buf, dir, size, mod); break; + case 16: VG_(transfer) (&mips1->guest_r16, buf, dir, size, mod); break; + case 17: VG_(transfer) (&mips1->guest_r17, buf, dir, size, mod); break; + case 18: VG_(transfer) (&mips1->guest_r18, buf, dir, size, mod); break; + case 19: VG_(transfer) (&mips1->guest_r19, buf, dir, size, mod); break; + case 20: VG_(transfer) (&mips1->guest_r20, buf, dir, size, mod); break; + case 21: VG_(transfer) (&mips1->guest_r21, buf, dir, size, mod); break; + case 22: VG_(transfer) (&mips1->guest_r22, buf, dir, size, mod); break; + case 23: VG_(transfer) (&mips1->guest_r23, buf, dir, size, mod); break; + case 24: VG_(transfer) (&mips1->guest_r24, buf, dir, size, mod); break; + case 25: VG_(transfer) (&mips1->guest_r25, buf, dir, size, mod); break; + case 26: VG_(transfer) (&mips1->guest_r26, buf, dir, size, mod); break; + case 27: VG_(transfer) (&mips1->guest_r27, buf, dir, size, mod); break; + case 28: VG_(transfer) (&mips1->guest_r28, buf, dir, size, mod); break; + case 29: VG_(transfer) (&mips1->guest_r29, buf, dir, size, mod); break; + case 30: VG_(transfer) (&mips1->guest_r30, buf, dir, size, mod); break; + case 31: VG_(transfer) (&mips1->guest_r31, buf, dir, size, mod); break; + case 32: *mod = False; break; // GDBTD???? VEX { "status", 1024, 64 } + case 33: VG_(transfer) (&mips1->guest_LO, buf, dir, size, mod); break; + case 34: VG_(transfer) (&mips1->guest_HI, buf, dir, size, mod); break; + case 35: *mod = False; break; // GDBTD???? VEX { "badvaddr", 1120, 64 }, + case 36: *mod = False; break; // GDBTD???? VEX { "cause", 1152, 64 }, + case 37: VG_(transfer) (&mips1->guest_PC, buf, dir, size, mod); break; + case 38: VG_(transfer) (&mips1->guest_f0, buf, dir, size, mod); break; + case 39: VG_(transfer) (&mips1->guest_f1, buf, dir, size, mod); break; + case 40: VG_(transfer) (&mips1->guest_f2, buf, dir, size, mod); break; + case 41: VG_(transfer) (&mips1->guest_f3, buf, dir, size, mod); break; + case 42: VG_(transfer) (&mips1->guest_f4, buf, dir, size, mod); break; + case 43: VG_(transfer) (&mips1->guest_f5, buf, dir, size, mod); break; + case 44: VG_(transfer) (&mips1->guest_f6, buf, dir, size, mod); break; + case 45: VG_(transfer) (&mips1->guest_f7, buf, dir, size, mod); break; + case 46: VG_(transfer) (&mips1->guest_f8, buf, dir, size, mod); break; + case 47: VG_(transfer) (&mips1->guest_f9, buf, dir, size, mod); break; + case 48: VG_(transfer) (&mips1->guest_f10, buf, dir, size, mod); break; + case 49: VG_(transfer) (&mips1->guest_f11, buf, dir, size, mod); break; + case 50: VG_(transfer) (&mips1->guest_f12, buf, dir, size, mod); break; + case 51: VG_(transfer) (&mips1->guest_f13, buf, dir, size, mod); break; + case 52: VG_(transfer) (&mips1->guest_f14, buf, dir, size, mod); break; + case 53: VG_(transfer) (&mips1->guest_f15, buf, dir, size, mod); break; + case 54: VG_(transfer) (&mips1->guest_f16, buf, dir, size, mod); break; + case 55: VG_(transfer) (&mips1->guest_f17, buf, dir, size, mod); break; + case 56: VG_(transfer) (&mips1->guest_f18, buf, dir, size, mod); break; + case 57: VG_(transfer) (&mips1->guest_f19, buf, dir, size, mod); break; + case 58: VG_(transfer) (&mips1->guest_f20, buf, dir, size, mod); break; + case 59: VG_(transfer) (&mips1->guest_f21, buf, dir, size, mod); break; + case 60: VG_(transfer) (&mips1->guest_f22, buf, dir, size, mod); break; + case 61: VG_(transfer) (&mips1->guest_f23, buf, dir, size, mod); break; + case 62: VG_(transfer) (&mips1->guest_f24, buf, dir, size, mod); break; + case 63: VG_(transfer) (&mips1->guest_f25, buf, dir, size, mod); break; + case 64: VG_(transfer) (&mips1->guest_f26, buf, dir, size, mod); break; + case 65: VG_(transfer) (&mips1->guest_f27, buf, dir, size, mod); break; + case 66: VG_(transfer) (&mips1->guest_f28, buf, dir, size, mod); break; + case 67: VG_(transfer) (&mips1->guest_f29, buf, dir, size, mod); break; + case 68: VG_(transfer) (&mips1->guest_f30, buf, dir, size, mod); break; + case 69: VG_(transfer) (&mips1->guest_f31, buf, dir, size, mod); break; + case 70: VG_(transfer) (&mips1->guest_FCSR, buf, dir, size, mod); break; + case 71: VG_(transfer) (&mips1->guest_FIR, buf, dir, size, mod); break; + case 72: *mod = False; break; // GDBTD???? VEX{ "restart", 2304, 64 }, + default: VG_(printf)("regno: %d\n", regno); vg_assert(0); + } +} + +static +const char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { + return "mips64-linux-valgrind.xml"; + } else { + return "mips64-linux.xml"; + } +} + +static struct valgrind_target_ops low_target = { + num_regs, + regs, + 29, //sp = r29, which is register offset 29 in regs + transfer_register, + get_pc, + set_pc, + "mips64", + target_xml +}; + +void mips64_init_architecture (struct valgrind_target_ops *target) +{ + *target = low_target; + set_register_cache (regs, num_regs); + gdbserver_expedite_regs = expedite_regs; +} diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h index 3ff6d19c40..c8d53cbaf5 100644 --- a/coregrind/m_gdbserver/valgrind_low.h +++ b/coregrind/m_gdbserver/valgrind_low.h @@ -74,5 +74,6 @@ 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); extern void mips32_init_architecture (struct valgrind_target_ops *target); +extern void mips64_init_architecture (struct valgrind_target_ops *target); #endif diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index 1510f8c54b..f9a68a6715 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -1110,6 +1110,20 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) arch->vex.guest_PC = iifii.initial_client_IP; arch->vex.guest_r31 = iifii.initial_client_SP; +# elif defined(VGP_mips64_linux) + vg_assert(0 == sizeof(VexGuestMIPS64State) % 16); + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestMIPS64_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS64State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS64State)); + + arch->vex.guest_r29 = iifii.initial_client_SP; + arch->vex.guest_PC = iifii.initial_client_IP; + arch->vex.guest_r31 = iifii.initial_client_SP; + # else # error Unknown platform # endif diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index c38fe84548..c8efddedeb 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -177,6 +177,31 @@ (srP)->misc.MIPS32.r31 = (ULong)ra; \ (srP)->misc.MIPS32.r28 = (ULong)gp; \ } +#elif defined(VGP_mips64_linux) +# define GET_STARTREGS(srP) \ + { ULong pc, sp, fp, ra, gp; \ + asm("move $8, $31;" /* t0 = ra */ \ + "bal m_libcassert_get_ip;" /* ra = pc */ \ + "m_libcassert_get_ip:\n" \ + "move %0, $31;" \ + "move $31, $8;" /* restore lr */ \ + "move %1, $29;" \ + "move %2, $30;" \ + "move %3, $31;" \ + "move %4, $28;" \ + : "=r" (pc), \ + "=r" (sp), \ + "=r" (fp), \ + "=r" (ra), \ + "=r" (gp) \ + : /* reads none */ \ + : "$8" /* trashed */ ); \ + (srP)->r_pc = (ULong)pc - 8; \ + (srP)->r_sp = (ULong)sp; \ + (srP)->misc.MIPS64.r30 = (ULong)fp; \ + (srP)->misc.MIPS64.r31 = (ULong)ra; \ + (srP)->misc.MIPS64.r28 = (ULong)gp; \ + } #else # error Unknown platform #endif diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 2e8ebca806..3364abca5f 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -194,9 +194,9 @@ Int VG_(write) ( Int fd, const void* buf, Int count) Int VG_(pipe) ( Int fd[2] ) { -# if defined(VGP_mips32_linux) +# if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) /* __NR_pipe has a strange return convention on mips32-linux. */ - SysRes res = VG_(do_syscall0)(__NR_pipe); + SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); if (!sr_isError(res)) { fd[0] = (Int)sr_Res(res); fd[1] = (Int)sr_ResEx(res); @@ -612,18 +612,19 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) 0, // Padding needed on PPC32 0, offset); // Big endian long long return res; -# elif defined(VGP_mips32_linux) && VKI_LITTLE_ENDIAN +# elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN) vg_assert(sizeof(OffT) == 4); res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 0, offset, 0); return res; -# elif defined(VGP_mips32_linux) && VKI_BIG_ENDIAN +# elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN) vg_assert(sizeof(OffT) == 4); res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 0, 0, offset); return res; # elif defined(VGP_amd64_linux) \ - || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) + || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \ + || defined(VGP_mips64_linux) res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); return res; # elif defined(VGP_amd64_darwin) @@ -864,7 +865,7 @@ Int VG_(socket) ( Int domain, Int type, Int protocol ) return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); return sr_isError(res) ? -1 : sr_Res(res); @@ -903,7 +904,7 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); return sr_isError(res) ? -1 : sr_Res(res); @@ -942,7 +943,7 @@ Int VG_(write_socket)( Int sd, const void *msg, Int count ) return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, VKI_MSG_NOSIGNAL, 0,0); @@ -971,7 +972,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); return sr_isError(res) ? -1 : sr_Res(res); -# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) +# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ + || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getsockname, (UWord)sd, (UWord)name, (UWord)namelen ); @@ -1001,7 +1003,8 @@ Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); return sr_isError(res) ? -1 : sr_Res(res); -# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) +# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ + || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getpeername, (UWord)sd, (UWord)name, (UWord)namelen ); @@ -1034,7 +1037,7 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) SysRes res; res = VG_(do_syscall5)( __NR_getsockopt, (UWord)sd, (UWord)level, (UWord)optname, diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c index 68328699d6..045a37870c 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -533,7 +533,8 @@ Int VG_(getegid) ( void ) platform. */ Int VG_(getgroups)( Int size, UInt* list ) { -# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_mips64_linux) Int i; SysRes sres; UShort list16[64]; @@ -762,7 +763,7 @@ void VG_(invalidate_icache) ( void *ptr, SizeT nbytes ) Addr endaddr = startaddr + nbytes; VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr); -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_mips64) SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr, (UWord) nbytes, (UWord) 3); vg_assert( sres._isError == 0 ); diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index bbbea7e9a2..b40cb28196 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -113,6 +113,15 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs, = VG_(threads)[tid].arch.vex.guest_r31; regs->misc.MIPS32.r28 = VG_(threads)[tid].arch.vex.guest_r28; +# elif defined(VGA_mips64) + regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC; + regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29; + regs->misc.MIPS64.r30 + = VG_(threads)[tid].arch.vex.guest_r30; + regs->misc.MIPS64.r31 + = VG_(threads)[tid].arch.vex.guest_r31; + regs->misc.MIPS64.r28 + = VG_(threads)[tid].arch.vex.guest_r28; # else # error "Unknown arch" # endif @@ -142,7 +151,7 @@ void VG_(set_syscall_return_shadows) ( ThreadId tid, # 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) +# 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 @@ -296,7 +305,7 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, (*f)(tid, "r13", vex->guest_r13); (*f)(tid, "r14", vex->guest_r14); (*f)(tid, "r15", vex->guest_r15); -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_mips64) (*f)(tid, "r0" , vex->guest_r0 ); (*f)(tid, "r1" , vex->guest_r1 ); (*f)(tid, "r2" , vex->guest_r2 ); @@ -615,13 +624,14 @@ static UInt VG_(get_machine_model)(void) #endif /* VGA_s390x */ -#ifdef VGA_mips32 +#if defined(VGA_mips32) || defined(VGA_mips64) /* Read /proc/cpuinfo and return the machine model. */ static UInt VG_(get_machine_model)(void) { - char *search_MIPS_str = "MIPS"; - char *search_Broadcom_str = "Broadcom"; + const char *search_MIPS_str = "MIPS"; + const char *search_Broadcom_str = "Broadcom"; + const char *search_Netlogic_str = "Netlogic"; Int n, fh; SysRes fd; SizeT num_bytes, file_buf_size; @@ -664,6 +674,8 @@ static UInt VG_(get_machine_model)(void) /* Parse file */ if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL) return VEX_PRID_COMP_BROADCOM; + if (VG_(strstr) (file_buf, search_Netlogic_str) != NULL) + return VEX_PRID_COMP_NETLOGIC; if (VG_(strstr) (file_buf, search_MIPS_str) != NULL) return VEX_PRID_COMP_MIPS; @@ -1377,6 +1389,20 @@ Bool VG_(machine_get_hwcaps)( void ) return True; } +#elif defined(VGA_mips64) + { + va = VexArchMIPS64; + UInt model = VG_(get_machine_model)(); + if (model== -1) + return False; + + vai.hwcaps = model; + + VG_(machine_get_cache_info)(&vai); + + return True; + } + #else # error "Unknown arch" #endif @@ -1503,6 +1529,9 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void ) it? */ return 8; +# elif defined(VGA_mips64) + return 8; + # else # error "Unknown arch" # endif @@ -1516,7 +1545,8 @@ void* VG_(fnptr_to_fnentry)( void* f ) # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ || defined(VGP_arm_linux) \ || defined(VGP_ppc32_linux) || defined(VGO_darwin) \ - || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) + || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \ + || defined(VGP_mips64_linux) return f; # elif defined(VGP_ppc64_linux) /* ppc64-linux uses the AIX scheme, in which f is a pointer to a diff --git a/coregrind/m_main.c b/coregrind/m_main.c index e0df961c16..fe8746616c 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -2008,7 +2008,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) iters = 5; # elif defined(VGP_s390x_linux) iters = 10; -# elif defined(VGP_mips32_linux) +# elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) iters = 10; # elif defined(VGO_darwin) iters = 3; @@ -2591,7 +2591,7 @@ static void final_tidyup(ThreadId tid) VG_(threads)[tid].arch.vex.guest_GPR2 = r2; # endif /* mips-linux note: we need to set t9 */ -# if defined(VGP_mips32_linux) +# if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) VG_(threads)[tid].arch.vex.guest_r25 = __libc_freeres_wrapper; # endif @@ -2937,6 +2937,45 @@ asm("\n" "\tbreak 0x7\n" ".previous\n" ); +#elif defined(VGP_mips64_linux) +asm( +".text\n" +".globl __start\n" +".type __start,@function\n" +"__start:\n" + "\t.set noreorder\n" + "\t.cpload $25\n" + "\t.set reorder\n" + "\t.cprestore 16\n" + "\tlui $9, %hi(vgPlain_interim_stack)\n" + /* t1/$9 <- Addr(interim_stack) */ + "\tdaddiu $9, %lo(vgPlain_interim_stack)\n" + + "\tli $10, "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n" + "\tli $11, "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n" + + "\tdaddu $9, $9, $10\n" + "\tdaddu $9, $9, $11\n" + "\tli $12, 0xFFFFFF00\n" + "\tand $9, $9, $12\n" + /* now t1/$9 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB + + VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte + boundary. And $29 is the original SP. Set the SP to t1 and + call _start_in_C, passing it the initial SP. */ + + "\tmove $4, $29\n" // a0 <- $sp (_start_in_C first arg) + "\tmove $29, $9\n" // $sp <- t1 (new sp) + + "\tlui $9, %highest(_start_in_C_linux)\n" + "\tori $9, %higher(_start_in_C_linux)\n" + "\tdsll32 $9, $9, 0x0\n" + "\tlui $10, %hi(_start_in_C_linux)\n" + "\tdaddiu $10, %lo(_start_in_C_linux)\n" + "\tdaddu $25, $9, $10\n" + "\tjalr $25\n" + "\tnop\n" +".end __start\n" +); #else # error "Unknown linux platform" #endif diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index 40f6980066..df9246bfcf 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -1369,6 +1369,17 @@ void VG_(redir_initialise) ( void ) ); } +# elif defined(VGP_mips64_linux) + if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { + + /* this is mandatory - can't sanely continue without it */ + add_hardwired_spec( + "ld.so.3", "strlen", + (Addr)&VG_(mips64_linux_REDIR_FOR_strlen), + complain_about_stripped_glibc_ldso + ); + } + # else # error Unknown platform # endif diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index ebe6eb40e4..1e5a8c1fdc 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -790,7 +790,7 @@ static void do_pre_run_checks ( ThreadState* tst ) /* no special requirements */ # endif -# if defined(VGA_mips32) +# if defined(VGA_mips32) || defined(VGA_mips64) /* no special requirements */ # endif } @@ -1597,7 +1597,7 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src ) #elif defined (VGA_s390x) # define VG_CLREQ_ARGS guest_r2 # define VG_CLREQ_RET guest_r3 -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_mips64) # define VG_CLREQ_ARGS guest_r12 # define VG_CLREQ_RET guest_r11 #else diff --git a/coregrind/m_sigframe/sigframe-mips32-linux.c b/coregrind/m_sigframe/sigframe-mips32-linux.c index c711a6a455..e0220beef1 100644 --- a/coregrind/m_sigframe/sigframe-mips32-linux.c +++ b/coregrind/m_sigframe/sigframe-mips32-linux.c @@ -116,7 +116,8 @@ static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) } static -void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, const vki_siginfo_t *si) +void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, + const vki_siginfo_t *si) { struct vki_sigcontext *sc = *sc1; @@ -171,7 +172,6 @@ void VG_(sigframe_create)( ThreadId tid, { Addr sp; ThreadState* tst = VG_(get_ThreadState)(tid); - Addr faultaddr; Int sigNo = siginfo->si_signo; struct vg_sig_private *priv; @@ -192,12 +192,6 @@ void VG_(sigframe_create)( ThreadId tid, return; vg_assert(VG_IS_8_ALIGNED(sp)); - - /* SIGILL defines addr to be the faulting address */ - - faultaddr = (Addr)siginfo->_sifields._sigfault._addr; - if (sigNo == VKI_SIGILL && siginfo->si_code > 0) - faultaddr = tst->arch.vex.guest_PC; if (flags & VKI_SA_SIGINFO) { diff --git a/coregrind/m_sigframe/sigframe-mips64-linux.c b/coregrind/m_sigframe/sigframe-mips64-linux.c new file mode 100644 index 0000000000..fc8e613c20 --- /dev/null +++ b/coregrind/m_sigframe/sigframe-mips64-linux.c @@ -0,0 +1,317 @@ + +/*--------------------------------------------------------------------*/ +/*--- Create/destroy signal delivery frames. ---*/ +/*--- sigframe-mips64-linux.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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_mips64_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" +#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" +#include "pub_core_transtab.h" /* VG_(discard_translations) */ + +struct vg_sig_private { + UInt magicPI; + UInt sigNo_private; + VexGuestMIPS64State vex_shadow1; + VexGuestMIPS64State vex_shadow2; +}; + +struct sigframe { + UInt sf_ass[4]; /* argument save space for o32 */ + UInt sf_pad[2]; /* Was: signal trampoline */ + struct vki_sigcontext sf_sc; + vki_sigset_t sf_mask; + struct vg_sig_private priv; +}; + +struct rt_sigframe { + UInt rs_ass[4]; /* argument save space for o32 */ + UInt rs_pad[2]; /* Was: signal trampoline */ + vki_siginfo_t rs_info; + struct vki_ucontext rs_uc; + struct vg_sig_private priv; +}; + +/* Extend the stack segment downwards if needed so as to ensure the new signal + frames are mapped to something. Return a Bool indicating whether or not the + operation was successful. +*/ +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 (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { + VG_(message)(Vg_UserMsg, + "Can't extend stack to %#lx during signal delivery for thread %d:\n", + addr, tid); + if (stackseg == NULL) + VG_(message)(Vg_UserMsg, " no stack segment\n"); + else + VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); + + /* 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 setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1, + const vki_siginfo_t *si) +{ + struct vki_sigcontext *sc = *sc1; + + VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", + (Addr)sc, sizeof(unsigned long long)*34); + sc->sc_regs[1] = tst->arch.vex.guest_r1; + sc->sc_regs[2] = tst->arch.vex.guest_r2; + sc->sc_regs[3] = tst->arch.vex.guest_r3; + sc->sc_regs[4] = tst->arch.vex.guest_r4; + sc->sc_regs[5] = tst->arch.vex.guest_r5; + sc->sc_regs[6] = tst->arch.vex.guest_r6; + sc->sc_regs[7] = tst->arch.vex.guest_r7; + sc->sc_regs[8] = tst->arch.vex.guest_r8; + sc->sc_regs[9] = tst->arch.vex.guest_r9; + sc->sc_regs[10] = tst->arch.vex.guest_r10; + sc->sc_regs[11] = tst->arch.vex.guest_r11; + sc->sc_regs[12] = tst->arch.vex.guest_r12; + sc->sc_regs[13] = tst->arch.vex.guest_r13; + sc->sc_regs[14] = tst->arch.vex.guest_r14; + sc->sc_regs[15] = tst->arch.vex.guest_r15; + sc->sc_regs[16] = tst->arch.vex.guest_r16; + sc->sc_regs[17] = tst->arch.vex.guest_r17; + sc->sc_regs[18] = tst->arch.vex.guest_r18; + sc->sc_regs[19] = tst->arch.vex.guest_r19; + sc->sc_regs[20] = tst->arch.vex.guest_r20; + sc->sc_regs[21] = tst->arch.vex.guest_r21; + sc->sc_regs[22] = tst->arch.vex.guest_r22; + sc->sc_regs[23] = tst->arch.vex.guest_r23; + sc->sc_regs[24] = tst->arch.vex.guest_r24; + sc->sc_regs[25] = tst->arch.vex.guest_r25; + sc->sc_regs[26] = tst->arch.vex.guest_r26; + sc->sc_regs[27] = tst->arch.vex.guest_r27; + sc->sc_regs[28] = tst->arch.vex.guest_r28; + sc->sc_regs[29] = tst->arch.vex.guest_r29; + sc->sc_regs[30] = tst->arch.vex.guest_r30; + sc->sc_regs[31] = tst->arch.vex.guest_r31; + sc->sc_pc = tst->arch.vex.guest_PC; + sc->sc_mdhi = tst->arch.vex.guest_HI; + sc->sc_mdlo = tst->arch.vex.guest_LO; +} + +/* 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 ) +{ + Addr sp; + ThreadState* tst = VG_(get_ThreadState)(tid); + Int sigNo = siginfo->si_signo; + struct vg_sig_private *priv; + /* Stack must be 16-byte aligned */ + sp_top_of_frame &= ~0xf; + + sp = sp_top_of_frame - sizeof(struct rt_sigframe); + + tst = VG_(get_ThreadState)(tid); + if (!extend(tst, sp, sp_top_of_frame - sp)) + return; + + sp = VG_ROUNDDN(sp, 16); + + struct rt_sigframe *frame = (struct rt_sigframe *)sp; + struct vki_ucontext *ucp = &frame->rs_uc; + if (VG_(clo_trace_signals)) + VG_(printf)("rt_sigframe\n"); + /* Create siginfo. */ + VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", + (Addr)&frame->rs_info, sizeof(frame->rs_info)); + + VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo)); + + VG_TRACK(post_mem_write, Vg_CoreSignal, tid, + (Addr)&frame->rs_info, sizeof(frame->rs_info)); + + /* Create the ucontext. */ + VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", + (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext)); + + ucp->uc_flags = 0; + ucp->uc_link = 0; + ucp->uc_stack = tst->altstack; + + VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, + offsetof(struct vki_ucontext, uc_mcontext)); + + struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext); + setup_sigcontext(tst, &(scp), siginfo); + ucp->uc_sigmask = tst->sig_mask; + priv = &frame->priv; + + /* Arguments to signal handler: + + a0 = signal number + a1 = 0 (should be cause) + a2 = pointer to ucontext + + $25 and c0_epc point to the signal handler, $29 points to + the struct rt_sigframe. */ + + tst->arch.vex.guest_r4 = siginfo->si_signo; + tst->arch.vex.guest_r5 = (Addr) &frame->rs_info; + tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc; + tst->arch.vex.guest_r29 = (Addr) frame; + tst->arch.vex.guest_r25 = (Addr) handler; + + if (flags & VKI_SA_RESTORER) + tst->arch.vex.guest_r31 = (Addr) restorer; + else + tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn); + + priv->magicPI = 0x31415927; + priv->sigNo_private = sigNo; + priv->vex_shadow1 = tst->arch.vex_shadow1; + priv->vex_shadow2 = tst->arch.vex_shadow2; + /* Set the thread so it will next run the handler. */ + VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); + if (VG_(clo_trace_signals)) + VG_(printf)("handler = %p\n", handler); + tst->arch.vex.guest_PC = (Addr) handler; + /* This thread needs to be marked runnable, but we leave that + the caller to do. */ +} + +/* EXPORTED */ +void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT ) +{ + ThreadState *tst; + struct vg_sig_private *priv1; + Addr sp; + UInt frame_size; + struct vki_sigcontext *mc; + Int sigNo; + + vg_assert(VG_(is_valid_tid)(tid)); + tst = VG_(get_ThreadState)(tid); + sp = tst->arch.vex.guest_r29; + struct rt_sigframe *frame = (struct rt_sigframe *)sp; + struct vki_ucontext *ucp = &frame->rs_uc; + frame_size = sizeof(*frame); + mc = &ucp->uc_mcontext; + tst->sig_mask = ucp->uc_sigmask; + tst->tmp_sig_mask = ucp->uc_sigmask; + priv1 = &frame->priv; + sigNo = priv1->sigNo_private; + vg_assert(priv1->magicPI == 0x31415927); + /* restore regs */ + tst->arch.vex.guest_r1 = mc->sc_regs[1]; + tst->arch.vex.guest_r2 = mc->sc_regs[2]; + tst->arch.vex.guest_r3 = mc->sc_regs[3]; + tst->arch.vex.guest_r4 = mc->sc_regs[4]; + tst->arch.vex.guest_r5 = mc->sc_regs[5]; + tst->arch.vex.guest_r6 = mc->sc_regs[6]; + tst->arch.vex.guest_r7 = mc->sc_regs[7]; + tst->arch.vex.guest_r8 = mc->sc_regs[8]; + tst->arch.vex.guest_r9 = mc->sc_regs[9]; + tst->arch.vex.guest_r10 = mc->sc_regs[10]; + tst->arch.vex.guest_r11 = mc->sc_regs[11]; + tst->arch.vex.guest_r12 = mc->sc_regs[12]; + tst->arch.vex.guest_r13= mc->sc_regs[13]; + tst->arch.vex.guest_r14 = mc->sc_regs[14]; + tst->arch.vex.guest_r15 = mc->sc_regs[15]; + tst->arch.vex.guest_r16 = mc->sc_regs[16]; + tst->arch.vex.guest_r17 = mc->sc_regs[17]; + tst->arch.vex.guest_r18 = mc->sc_regs[18]; + tst->arch.vex.guest_r19 = mc->sc_regs[19]; + tst->arch.vex.guest_r20 = mc->sc_regs[20]; + tst->arch.vex.guest_r21 = mc->sc_regs[21]; + tst->arch.vex.guest_r22 = mc->sc_regs[22]; + tst->arch.vex.guest_r23 = mc->sc_regs[23]; + tst->arch.vex.guest_r24 = mc->sc_regs[24]; + tst->arch.vex.guest_r25 = mc->sc_regs[25]; + tst->arch.vex.guest_r26 = mc->sc_regs[26]; + tst->arch.vex.guest_r27 = mc->sc_regs[27]; + tst->arch.vex.guest_r28 = mc->sc_regs[28]; + tst->arch.vex.guest_r30 = mc->sc_regs[30]; + tst->arch.vex.guest_PC = mc->sc_pc; + tst->arch.vex.guest_r31 = mc->sc_regs[31]; + tst->arch.vex.guest_r29 = mc->sc_regs[29]; + + tst->arch.vex.guest_HI = mc->sc_mdhi; + tst->arch.vex.guest_LO = mc->sc_mdlo; + tst->arch.vex_shadow1 = priv1->vex_shadow1; + tst->arch.vex_shadow2 = priv1->vex_shadow2; + + VG_TRACK(die_mem_stack_signal, sp, frame_size); + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, + "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n", + tid, isRT, tst->arch.vex.guest_PC); + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); +} + +#endif /* defined(VGP_mips64_linux) */ + +/*--------------------------------------------------------------------*/ +/*--- end sigframe-mips64-linux.c ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 88f7b9d1f3..44231908d8 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -535,6 +535,24 @@ typedef struct SigQueue { (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \ } +#elif defined(VGP_mips64_linux) +# define VG_UCONTEXT_INSTR_PTR(uc) (((uc)->uc_mcontext.sc_pc)) +# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.sc_regs[29]) +# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.sc_regs[30]) +# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.sc_regs[2]) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.rax into a SysRes. */ \ + VG_(mk_SysRes_mips64_linux)((uc)->uc_mcontext.sc_regs[2], \ + (uc)->uc_mcontext.sc_regs[3], \ + (uc)->uc_mcontext.sc_regs[7]) + +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (uc)->uc_mcontext.sc_pc; \ + (srP)->r_sp = (uc)->uc_mcontext.sc_regs[29]; \ + (srP)->misc.MIPS64.r30 = (uc)->uc_mcontext.sc_regs[30]; \ + (srP)->misc.MIPS64.r31 = (uc)->uc_mcontext.sc_regs[31]; \ + (srP)->misc.MIPS64.r28 = (uc)->uc_mcontext.sc_regs[28]; \ + } #else # error Unknown platform @@ -876,6 +894,14 @@ extern void my_sigreturn(void); " syscall\n" \ ".previous\n" +#elif defined(VGP_mips64_linux) +# define _MY_SIGRETURN(name) \ + ".text\n" \ + "my_sigreturn:\n" \ + " li $2, " #name "\n" \ + " syscall\n" \ + ".previous\n" + #else # error Unknown platform #endif @@ -953,7 +979,7 @@ static void handle_SCSS_change ( Bool force_update ) == skss_old.skss_per_sig[sig].skss_flags); # if !defined(VGP_ppc32_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ - !defined(VGP_mips32_linux) + !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif @@ -1944,8 +1970,8 @@ void VG_(synth_sigtrap)(ThreadId tid) // Synthesise a SIGFPE. void VG_(synth_sigfpe)(ThreadId tid, UInt code) { -// Only tested on mips32 -#if !defined(VGA_mips32) +// Only tested on mips32 and mips64 +#if !defined(VGA_mips32) && !defined(VGA_mips64) vg_assert(0); #else vki_siginfo_t info; diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index ea8b1661b0..0420200a1c 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -1110,10 +1110,8 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, #endif -/* ------------------------ mips 32------------------------- */ - -#if defined(VGP_mips32_linux) - +/* ------------------------ mips 32/64 ------------------------- */ +#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /*OUT*/Addr* ips, UInt max_n_ips, /*OUT*/Addr* sps, /*OUT*/Addr* fps, @@ -1134,8 +1132,13 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, uregs.sp = startRegs->r_sp; Addr fp_min = uregs.sp; +#if defined(VGP_mips32_linux) uregs.fp = startRegs->misc.MIPS32.r30; uregs.ra = startRegs->misc.MIPS32.r31; +#elif defined(VGP_mips64_linux) + uregs.fp = startRegs->misc.MIPS64.r30; + uregs.ra = startRegs->misc.MIPS64.r31; +#endif /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1], stopping when the trail goes cold, which we guess to be @@ -1192,7 +1195,6 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) { unsigned long inst, high_word, low_word; unsigned long * cur_inst; - int reg; /* Fetch the instruction. */ cur_inst = (unsigned long *)cur_pc; inst = *((UInt *) cur_inst); @@ -1202,7 +1204,6 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /* Save some code by pre-extracting some useful fields. */ high_word = (inst >> 16) & 0xffff; low_word = inst & 0xffff; - reg = high_word & 0x1f; if (high_word == 0x27bd /* addiu $sp,$sp,-i */ || high_word == 0x23bd /* addi $sp,$sp,-i */ diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c index 668d08b16a..4312d132f3 100644 --- a/coregrind/m_syscall.c +++ b/coregrind/m_syscall.c @@ -137,6 +137,15 @@ SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) { return res; } +/* MIPS uses a3 != 0 to flag an error */ +SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) { + SysRes res; + res._isError = (a3 != (ULong)0); + res._val = v0; + res._valEx = v1; + return res; +} + /* Generic constructors. */ SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes r; @@ -626,6 +635,25 @@ asm( ".end do_syscall_WRK\n" ); +#elif defined(VGP_mips64_linux) +extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, + UWord a6, UWord syscall_no, ULong* V1_val ); +asm ( +".text\n" +".globl do_syscall_WRK\n" +"do_syscall_WRK:\n" +" daddiu $29, $29, -8\n" +" sd $11, 0($29)\n" +" move $2, $10\n" +" syscall\n" +" ld $11, 0($29)\n" +" daddiu $29, $29, 8\n" +" sd $3, 0($11)\n" /* store vale of v1 in last param */ +" sd $7, 8($11)\n" /* store vale of a3 in last param */ +" jr $31\n" +".previous\n" +); + #else # error Unknown platform #endif @@ -740,6 +768,16 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, UWord valLo = 0; (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo); return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err ); + +#elif defined(VGP_mips64_linux) + ULong v1_a3[2]; + v1_a3[0] = 0xFF00; + v1_a3[1] = 0xFF00; + ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3); + ULong V1 = (ULong)v1_a3[0]; + ULong A3 = (ULong)v1_a3[1]; + return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 ); + #else # error Unknown platform #endif diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h index 70752ab3bd..ce07877da4 100644 --- a/coregrind/m_syswrap/priv_types_n_macros.h +++ b/coregrind/m_syswrap/priv_types_n_macros.h @@ -89,7 +89,8 @@ typedef Int o_sysno; # 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_arm_linux) || defined(VGP_s390x_linux) \ + || defined(VGP_mips64_linux) Int o_arg1; Int o_arg2; Int o_arg3; diff --git a/coregrind/m_syswrap/syscall-mips64-linux.S b/coregrind/m_syswrap/syscall-mips64-linux.S new file mode 100644 index 0000000000..4405b54b87 --- /dev/null +++ b/coregrind/m_syswrap/syscall-mips64-linux.S @@ -0,0 +1,156 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-mips64-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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_mips64_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 PC 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 regs->v0. The syscall result is written + back to regs->v0 on completion. + + 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, // $4 - a0 + void* guest_state, // $5 - a1 + const vki_sigset_t *sysmask, // $6 - a2 + const vki_sigset_t *postmask, // $7 - a3 + Int nsigwords) // $8 - a4 +*/ + +/* from vki_arch.h */ +#define VKI_SIG_SETMASK 3 + +.globl ML_(do_syscall_for_client_WRK) +ML_(do_syscall_for_client_WRK): + + /* save regs $a0 - $a4 on stack */ + daddiu $29, $29, -48 + sd $4, 0($29) /* syscallno */ + sd $5, 8($29) /* guest_state */ + sd $6, 16($29) /* sysmask */ + sd $7, 24($29) /* postmask */ + sd $8, 32($29) /* nsigwords */ + +1: li $2, __NR_rt_sigprocmask + li $4, VKI_SIG_SETMASK + move $5, $6 /* sysmask */ + move $6, $7 /* postmask */ + move $7, $8 /* nsigwords */ + syscall + + bnez $7, 7f + nop + + /* Actually do the client syscall */ + ld $5, 8($29) /* guest_state */ + ld $4, OFFSET_mips64_r4($5) /* a0 */ + + ld $6, OFFSET_mips64_r6($5) /* a2 */ + ld $7, OFFSET_mips64_r7($5) /* a3 */ + ld $8, OFFSET_mips64_r8($5) /* a4 */ + ld $9, OFFSET_mips64_r9($5) /* a5 */ + + ld $5, OFFSET_mips64_r5($5) /* a1 */ + ld $2, 0($29) /* syscallno */ +2: nop + + syscall + + /* Saving return values into Guest state */ +3: ld $5, 8($29) /* guest_state */ + sd $2, OFFSET_mips64_r2($5) /* v0 */ + sd $7, OFFSET_mips64_r7($5) /* a3 */ + +4: li $2, __NR_rt_sigprocmask + li $4, VKI_SIG_SETMASK + ld $5, 24($29) /* postmask */ + move $6, $0 /* 0 (zero) */ + ld $7, 32($29) /* nsigwords */ + syscall + + bnez $7, 7f + nop + +5: /* restore 29 and return */ + daddiu $29, $29, 48 + jr $31 + nop + +7: /* error */ + daddiu $29, $29, 48 + li $2, 0x8000 + jr $31 + nop + +.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 +.previous +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",%progbits + +#endif // defined(VGP_mips64_linux) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 46bc7361fe..bc0400114a 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -274,7 +274,7 @@ static void run_a_thread_NORETURN ( Word tidW ) : "d" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode) : "2" ); -#elif defined(VGP_mips32_linux) +#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 */ @@ -428,7 +428,8 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, VG_(clone) stuff */ #if defined(VGP_x86_linux) \ || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ - || defined(VGP_arm_linux) || defined(VGP_mips32_linux) + || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \ + || defined(VGP_mips64_linux) res = VG_(do_syscall5)( __NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, (UWord)NULL, (UWord)child_tidptr ); diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index f696f5188d..2dbbaa1f4a 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -68,7 +68,8 @@ ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1) arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1) - mips v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM) + 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) 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 @@ -486,6 +487,16 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, canonical->arg8 = __NR_syscall; } +#elif defined(VGP_mips64_linux) + VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla; + canonical->sysno = gst->guest_r2; // v0 + canonical->arg1 = gst->guest_r4; // a0 + canonical->arg2 = gst->guest_r5; // a1 + canonical->arg3 = gst->guest_r6; // a2 + canonical->arg4 = gst->guest_r7; // a3 + canonical->arg5 = gst->guest_r8; // a4 + canonical->arg6 = gst->guest_r9; // a5 + #elif defined(VGP_x86_darwin) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; UWord *stack = (UWord *)gst->guest_ESP; @@ -740,6 +751,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp) *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp) } + +#elif defined(VGP_mips64_linux) + VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla; + gst->guest_r2 = canonical->sysno; + gst->guest_r4 = canonical->arg1; + gst->guest_r5 = canonical->arg2; + gst->guest_r6 = canonical->arg3; + gst->guest_r7 = canonical->arg4; + gst->guest_r8 = canonical->arg5; + gst->guest_r9 = canonical->arg6; #else # error "putSyscallArgsIntoGuestState: unknown arch" #endif @@ -786,6 +807,14 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, canonical->sres = VG_(mk_SysRes_mips32_linux)( v0, v1, a3 ); canonical->what = SsComplete; +# elif defined(VGP_mips64_linux) + VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla; + ULong v0 = gst->guest_r2; // v0 + ULong v1 = gst->guest_r3; // v1 + ULong a3 = gst->guest_r7; // a3 + canonical->sres = VG_(mk_SysRes_mips64_linux)(v0, v1, a3); + canonical->what = SsComplete; + # elif defined(VGP_x86_darwin) /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; @@ -1036,6 +1065,24 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, OFFSET_mips32_r7, sizeof(UWord) ); +# elif defined(VGP_mips64_linux) + VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla; + vg_assert(canonical->what == SsComplete); + if (sr_isError(canonical->sres)) { + gst->guest_r2 = (Int)sr_Err(canonical->sres); + gst->guest_r7 = (Int)sr_Err(canonical->sres); + } else { + gst->guest_r2 = sr_Res(canonical->sres); + gst->guest_r3 = sr_ResEx(canonical->sres); + gst->guest_r7 = (Int)sr_Err(canonical->sres); + } + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_mips64_r2, sizeof(UWord) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_mips64_r3, sizeof(UWord) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_mips64_r7, sizeof(UWord) ); + # else # error "putSyscallStatusIntoGuestState: unknown arch" # endif @@ -1115,6 +1162,17 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->uu_arg7 = -1; /* impossible value */ layout->uu_arg8 = -1; /* impossible value */ +#elif defined(VGP_mips64_linux) + layout->o_sysno = OFFSET_mips64_r2; + layout->o_arg1 = OFFSET_mips64_r4; + layout->o_arg2 = OFFSET_mips64_r5; + layout->o_arg3 = OFFSET_mips64_r6; + layout->o_arg4 = OFFSET_mips64_r7; + layout->o_arg5 = OFFSET_mips64_r8; + layout->o_arg6 = OFFSET_mips64_r9; + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ + #elif defined(VGP_x86_darwin) layout->o_sysno = OFFSET_x86_EAX; // syscall parameters are on stack in C convention @@ -1970,7 +2028,7 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) vg_assert(p[0] == 0x0A); } -#elif defined(VGP_mips32_linux) +#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) arch->vex.guest_PC -= 4; // sizeof(mips instr) @@ -1986,14 +2044,14 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) # if defined (VG_LITTLEENDIAN) if (p[0] != 0x0c || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00) VG_(message)(Vg_DebugMsg, - "?! restarting over syscall at %#x %02x %02x %02x %02x\n", + "?! restarting over syscall at %#llx %02x %02x %02x %02x\n", arch->vex.guest_PC, p[0], p[1], p[2], p[3]); vg_assert(p[0] == 0x0c && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00); # elif defined (VG_BIGENDIAN) if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x0c) VG_(message)(Vg_DebugMsg, - "?! restarting over syscall at %#x %02x %02x %02x %02x\n", + "?! restarting over syscall at %#llx %02x %02x %02x %02x\n", arch->vex.guest_PC, p[0], p[1], p[2], p[3]); vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c); diff --git a/coregrind/m_syswrap/syswrap-mips32-linux.c b/coregrind/m_syswrap/syswrap-mips32-linux.c index f21f2acc96..88e76a384c 100644 --- a/coregrind/m_syswrap/syswrap-mips32-linux.c +++ b/coregrind/m_syswrap/syswrap-mips32-linux.c @@ -949,12 +949,10 @@ PRE (sys_clone) PRE (sys_sigreturn) { - ThreadState * tst; PRINT ("sys_sigreturn ( )"); vg_assert (VG_ (is_valid_tid) (tid)); vg_assert (tid >= 1 && tid < VG_N_THREADS); vg_assert (VG_ (is_running_thread) (tid)); - tst = VG_ (get_ThreadState) (tid); VG_ (sigframe_destroy) (tid, False); /* Tell the driver not to update the guest state with the "result", and set a bogus result to keep it happy. */ diff --git a/coregrind/m_syswrap/syswrap-mips64-linux.c b/coregrind/m_syswrap/syswrap-mips64-linux.c new file mode 100644 index 0000000000..f6a4bc40c5 --- /dev/null +++ b/coregrind/m_syswrap/syswrap-mips64-linux.c @@ -0,0 +1,1304 @@ + +/*--------------------------------------------------------------------*/ +/*--- Platform-specific syscalls stuff. syswrap-mips64-linux.c ----*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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_mips64_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" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_sigframe.h" /* For VG_(sigframe_destroy)() */ +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" +#include "pub_core_tooliface.h" +#include "pub_core_stacks.h" /* VG_(register_stack) */ +#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 */ +#include "priv_syswrap-main.h" + +#include "pub_core_debuginfo.h" /* VG_(di_notify_*) */ +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" /* VG_(brk_base), VG_(brk_limit) */ +#include "pub_core_errormgr.h" +#include "pub_tool_gdbserver.h" /* VG_(gdbserver) */ +#include "pub_core_libcfile.h" +#include "pub_core_machine.h" /* VG_(get_SP) */ +#include "pub_core_mallocfree.h" +#include "pub_core_stacktrace.h" /* For VG_(get_and_pp_StackTrace)() */ +#include "pub_core_ume.h" + +#include "config.h" + +#include + +/* --------------------------------------------------------------------- + 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, /* $4 - $a0 */ + Addr retaddr, /* $5 - $a1 */ + void (*f_desc) (Word), /* $6 - $a2 */ + Word arg1 ); /* $7 - $a3 */ +asm ( +".text\n" +".globl vgModuleLocal_call_on_new_stack_0_1\n" +"vgModuleLocal_call_on_new_stack_0_1:\n" +" move $29, $4\n" /* set stack */ +" move $4, $7\n" /* arg1 to $4 */ +" move $25, $6\n" +" move $31, $5\n" /* retaddr to $ra */ +" jr $25\n" /* jump to f */ +" break 0x7\n" /* should never get here */ +".previous\n" +); + +/* Perform a clone system call. clone is strange because it has fork()-like + return-twice semantics, so it needs special handling here. + + Upon entry, we have: + + word (fn)(void*) in a0 = 4 + void* child_stack in a1 = 5 + word flags in a2 = 6 + void* arg in a3 = 7 + pid_t* parent_tid in a4 = 8 + void* tls in a5 = 9 + pid_t* child_tid in a6 = 10 + + System call requires: + + int $__NR_clone in v0 + int flags in a0 = 4 + void* child_stack in a1 = 5 + pid_t* parent_tid in a2 = 6 + void* tls_ptr in a3 = 7 + pid_t* child_tid in a4 = 8 */ + +#define __NR_CLONE __NR_clone +#define __NR_EXIT __NR_exit + +ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *), /* a0 - 4 */ + void* stack, /* a1 - 5 */ + Int flags, /* a2 - 6 */ + void* arg, /* a3 - 7 */ + Int* parent_tid, /* a4 - 8 */ + void* /* Int tls */, /* a5 - 9 */ + Int* child_tid ); /* a6 - 10 */ + +asm( +".text\n" +".set noreorder\n" +".set nomacro\n" +".globl do_syscall_clone_mips64_linux\n" +"do_syscall_clone_mips64_linux:\n" +" daddiu $29, $29, -32\n" +" sd $31, 0($29)\n" +" sd $30, 8($29)\n" +" sd $28, 16($29)\n" + +" daddiu $5, $5, -32\n" +" sd $4, 0($5)\n" /* fn */ +" sd $7, 8($5)\n" /* arg */ +" sd $6, 16($5)\n" /* flags */ + +/* 1. arg for syscalls */ +" move $4, $6\n" /* flags */ +" move $6, $8\n" /* parent */ +" move $7, $a5\n" /* tls */ +" move $8, $a6\n" /* child */ + +/* 2. do a syscall to clone */ +" li $2, 5055\n" /* syscall num for clone */ +" syscall\n" + +/* 3. See if we are a child, call fn and after that exit */ +" bnez $7, p_or_error\n" +" nop\n" + +" bnez $2, p_or_error\n" +" nop\n" + +" ld $25,0($29)\n" +" jalr $25\n" +" ld $4,8($29)\n" + +" move $4, $2\n\t" /* retval from fn is in $v0 */ +" li $2, 5058\n\t" /* NR_exit */ +" syscall\n\t" +" nop\n\t" +/* 4. If we are parent or error, just return to caller */ +" p_or_error:\n" +" ld $31, 0($29)\n" +" ld $30, 8($29)\n" +" ld $28, 16($29)\n" +" jr $31\n" +" daddi $29,$29, 32\n" +".previous\n" +); + +#undef __NR_CLONE +#undef __NR_EXIT + +/* forward declarations */ +static void setup_child ( ThreadArchState *, ThreadArchState *); +static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr); + +/* When a client clones, we need to keep track of the new thread. This means: + 1. allocate a ThreadId+ThreadState+stack for the the thread + + 2. initialize the thread's new VCPU state + + 3. create the thread using the same args as the client requested, but using + the scheduler entrypoint for IP, and a separate stack for SP. */ +static SysRes do_clone ( ThreadId ptid, + UInt flags, Addr sp, + Int* parent_tidptr, + Int* child_tidptr, + Addr child_tls ) +{ + const Bool debug = False; + ThreadId ctid = VG_ (alloc_ThreadState) (); + ThreadState * ptst = VG_ (get_ThreadState) (ptid); + ThreadState * ctst = VG_ (get_ThreadState) (ctid); + UInt ret = 0; + UWord * stack; + NSegment const *seg; + SysRes res; + vki_sigset_t blockall, savedmask; + + VG_(sigfillset)(&blockall); + vg_assert(VG_(is_running_thread)(ptid)); + vg_assert(VG_(is_valid_tid)(ctid)); + stack = (UWord *)ML_(allocstack)(ctid); + if (stack == NULL) { + res = VG_(mk_SysRes_Error)(VKI_ENOMEM); + goto out; + } + setup_child(&ctst->arch, &ptst->arch); + + /* on MIPS we need to set V0 and A3 to zero */ + ctst->arch.vex.guest_r2 = 0; + ctst->arch.vex.guest_r7 = 0; + if (sp != 0) + ctst->arch.vex.guest_r29 = sp; + + ctst->os_state.parent = ptid; + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + ctst->os_state.threadgroup = ptst->os_state.threadgroup; + seg = VG_(am_find_nsegment)((Addr)sp); + + if (seg && seg->kind != SkResvn) { + ctst->client_stack_highest_word = sp; + ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start; + VG_(register_stack)(seg->start, ctst->client_stack_highest_word); + if (debug) + VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n", + ctid, seg->start, sp /* VG_PGROUNDUP (sp) */ ); + } else { + VG_(message)(Vg_UserMsg, + "!? New thread %d starts with sp+%#lx) unmapped\n", + ctid, sp); + ctst->client_stack_szB = 0; + } + + VG_TRACK(pre_thread_ll_create, ptid, ctid); + if (flags & VKI_CLONE_SETTLS) { + if (debug) + VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls); + res = sys_set_tls(ctid, child_tls); + if (sr_isError(res)) + goto out; + ctst->arch.vex.guest_r27 = child_tls; + } + + flags &= ~VKI_CLONE_SETTLS; + VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask); + /* Create the new thread */ + ret = do_syscall_clone_mips64_linux(ML_(start_thread_NORETURN), + stack, flags, &VG_(threads)[ctid], + parent_tidptr, NULL /*child_tls*/, + child_tidptr); + if (debug) + VG_(printf)("ret: 0x%x\n", ret); + + res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0); + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + + out: + if (sr_isError (res)) { + VG_ (cleanup_thread) (&ctst->arch); + ctst->status = VgTs_Empty; + VG_TRACK (pre_thread_ll_exit, ctid); + } + ptst->arch.vex.guest_r2 = 0; + + return res; +} + +/* --------------------------------------------------------------------- + More thread stuff + ------------------------------------------------------------------ */ +void VG_(cleanup_thread) ( ThreadArchState * arch ) { }; + +void setup_child ( /* OUT */ ThreadArchState * child, + /* IN */ ThreadArchState * parent ) +{ + /* We inherit our parent's guest state. */ + child->vex = parent->vex; + child->vex_shadow1 = parent->vex_shadow1; + child->vex_shadow2 = parent->vex_shadow2; +} + +SysRes sys_set_tls ( ThreadId tid, Addr tlsptr ) +{ + VG_(threads)[tid].arch.vex.guest_ULR = tlsptr; + return VG_(mk_SysRes_Success)( 0 ); +} + +/* --------------------------------------------------------------------- + PRE/POST wrappers for mips/Linux-specific syscalls + ------------------------------------------------------------------ */ + +#define PRE(name) DEFN_PRE_TEMPLATE(mips_linux, name) +#define POST(name) DEFN_POST_TEMPLATE(mips_linux, name) + +/* Add prototypes for the wrappers declared here, so that gcc doesn't harass us + for not having prototypes. Really this is a kludge -- the right thing to do + is to make these wrappers 'static' since they aren't visible outside this + file, but that requires even more macro magic. */ + +DECL_TEMPLATE (mips_linux, sys_set_thread_area); +DECL_TEMPLATE (mips_linux, sys_clone); +DECL_TEMPLATE (mips_linux, sys_socket); +DECL_TEMPLATE (mips_linux, sys_setsockopt); +DECL_TEMPLATE (mips_linux, sys_getsockopt); +DECL_TEMPLATE (mips_linux, sys_connect); +DECL_TEMPLATE (mips_linux, sys_accept); +DECL_TEMPLATE (mips_linux, sys_tee); +DECL_TEMPLATE (mips_linux, sys_splice); +DECL_TEMPLATE (mips_linux, sys_vmsplice); +DECL_TEMPLATE (mips_linux, sys_ustat); +DECL_TEMPLATE (mips_linux, sys_sysfs); +DECL_TEMPLATE (mips_linux, sys_swapon); +DECL_TEMPLATE (mips_linux, sys_swapoff); +DECL_TEMPLATE (mips_linux, sys_setdomainname); +DECL_TEMPLATE (mips_linux, sys_sethostname); +DECL_TEMPLATE (mips_linux, sys_accept4); +DECL_TEMPLATE (mips_linux, sys_sendto); +DECL_TEMPLATE (mips_linux, sys_recvfrom); +DECL_TEMPLATE (mips_linux, sys_sendmsg); +DECL_TEMPLATE (mips_linux, sys_recvmsg); +DECL_TEMPLATE (mips_linux, sys_shutdown); +DECL_TEMPLATE (mips_linux, sys_bind); +DECL_TEMPLATE (mips_linux, sys_reboot); +DECL_TEMPLATE (mips_linux, sys_listen); +DECL_TEMPLATE (mips_linux, sys_getsockname); +DECL_TEMPLATE (mips_linux, sys_getpeername); +DECL_TEMPLATE (mips_linux, sys_socketpair); +DECL_TEMPLATE (mips_linux, sys_semget); +DECL_TEMPLATE (mips_linux, sys_semop); +DECL_TEMPLATE (mips_linux, sys_semtimedop); +DECL_TEMPLATE (mips_linux, sys_cacheflush); +DECL_TEMPLATE (mips_linux, sys_semctl); +DECL_TEMPLATE (mips_linux, sys_sched_rr_get_interval); +DECL_TEMPLATE (mips_linux, sys_msgget); +DECL_TEMPLATE (mips_linux, sys_msgrcv); +DECL_TEMPLATE (mips_linux, sys_unshare); +DECL_TEMPLATE (mips_linux, sys_msgsnd); +DECL_TEMPLATE (mips_linux, sys_msgctl); +DECL_TEMPLATE (mips_linux, sys_shmget); +DECL_TEMPLATE (mips_linux, wrap_sys_shmat); +DECL_TEMPLATE (mips_linux, sys_shmdt); +DECL_TEMPLATE (mips_linux, sys_shmdt); +DECL_TEMPLATE (mips_linux, sys_shmctl); +DECL_TEMPLATE (mips_linux, sys_arch_prctl); +DECL_TEMPLATE (mips_linux, sys_ptrace); +DECL_TEMPLATE (mips_linux, sys_mmap); +DECL_TEMPLATE (mips_linux, sys_rt_sigreturn); +DECL_TEMPLATE (mips_linux, sys_pipe); + +PRE(sys_socketpair) +{ + PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "socketpair", int, d, int, type, int, protocol, + int *, sv); + ML_(generic_PRE_sys_socketpair)(tid, ARG1, ARG2, ARG3, ARG4); +} + +POST(sys_socketpair) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES), + ARG1, ARG2, ARG3, ARG4); +} + +PRE(wrap_sys_shmat) +{ + UWord arg2tmp; + PRINT("wrap_sys_shmat ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "shmat", int, shmid, const void *, shmaddr, int, shmflg); + arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1, ARG2, ARG3); + if (arg2tmp == 0) + SET_STATUS_Failure(VKI_EINVAL); + else + ARG2 = arg2tmp; +} + +POST(wrap_sys_shmat) +{ + ML_(generic_POST_sys_shmat)(tid, RES, ARG1, ARG2, ARG3); +} + +PRE(sys_shmdt) +{ + PRINT("sys_shmdt ( %#lx )", ARG1); + PRE_REG_READ1(long, "shmdt", const void *, shmaddr); + if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1)) + SET_STATUS_Failure(VKI_EINVAL); +} + +POST(sys_shmdt) +{ + ML_(generic_POST_sys_shmdt)(tid, RES, ARG1); +} + +PRE(sys_shmctl) +{ + PRINT("sys_shmctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "shmctl", int, shmid, int, cmd, struct shmid_ds *, buf); + ML_(generic_PRE_sys_shmctl)(tid, ARG1, ARG2, ARG3); +} + +POST(sys_shmctl) +{ + ML_(generic_POST_sys_shmctl)(tid, RES, ARG1, ARG2, ARG3); +} + +PRE(sys_shmget) +{ + PRINT("sys_shmget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg); +} + +PRE(sys_tee) +{ + PRINT("sys_tee ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "sys_tee", int, fdin, int, fdout, vki_size_t, len, + int, flags); +} + +PRE(sys_splice) +{ + PRINT("sys_splice ( %ld, %ld, %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, + ARG4, ARG5, ARG6); + + PRE_REG_READ6(long, "sys_splice", int, fdin, vki_loff_t, sizein, int, + fdout, vki_loff_t, sizeout, vki_size_t, len, int, flags); +} + +PRE(sys_vmsplice) +{ + PRINT("sys_vmsplice ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "sys_vmsplice", int, fdin, struct vki_iovec *, v, + vki_size_t, len, int, flags); +} + +PRE(sys_unshare) +{ + PRINT("sys_unshare ( %ld )", ARG1); + PRE_REG_READ1(long, "sys_unshare", int, flags); +} + +PRE(sys_msgctl) +{ + PRINT("sys_msgctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "msgctl", int, msqid, int, cmd, struct msqid_ds *, buf); + ML_(linux_PRE_sys_msgctl) (tid, ARG1, ARG2, ARG3); +} + +POST(sys_msgctl) +{ + ML_(linux_POST_sys_msgctl)(tid, RES, ARG1, ARG2, ARG3); +} + +PRE(sys_msgget) +{ + PRINT("sys_msgget ( %ld, %ld )", ARG1, ARG2); + PRE_REG_READ2(long, "msgget", vki_key_t, key, int, msgflg); +} + +PRE(sys_sched_rr_get_interval) +{ + PRINT("sys_sched_rr_get_interval ( %ld, %#lx)", ARG1, ARG2); + PRE_REG_READ2(long, "sched_rr_get_interval", int, flags, + struct timespec *, timer); + *flags |= SfMayBlock; +} + +PRE(sys_ustat) +{ + PRINT("sys_ustat ( %ld, %#lx)", ARG1, ARG2); + PRE_REG_READ2(long, "ustat", int, flags, const void *, path); +} + +PRE(sys_swapon) +{ + PRINT("sys_swapon ( %#lx, %ld )", ARG1, ARG2); + PRE_REG_READ2(long, "swapon", const void *, path, int, flags); +} + +PRE(sys_swapoff) +{ + PRINT("sys_swapoff ( %#lx )", ARG1); + PRE_REG_READ1(long, "swapoff", const void *, path); +} + +PRE(sys_sysfs) +{ + PRINT("sys_sysfs ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sysfs", int, flags, int, desc, const void *, path); +} + +PRE(sys_msgsnd) +{ + PRINT("sys_msgsnd ( %ld, %#lx, %ld, %ld )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "msgsnd", int, msqid, struct msgbuf *, msgp, + vki_size_t, msgsz, int, msgflg); + ML_(linux_PRE_sys_msgsnd)(tid, ARG1, ARG2, ARG3, ARG4); + if ((ARG4 & VKI_IPC_NOWAIT) == 0) + *flags |= SfMayBlock; +} + +PRE(sys_msgrcv) +{ + PRINT("sys_msgrcv ( %ld, %#lx, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4, + ARG5); + PRE_REG_READ5(long, "msgrcv", int, msqid, struct msgbuf *, msgp, + vki_size_t, msgsz, long, msgytp, int, msgflg); + ML_(linux_PRE_sys_msgrcv) (tid, ARG1, ARG2, ARG3, ARG4, ARG5); + if ((ARG4 & VKI_IPC_NOWAIT) == 0) + *flags |= SfMayBlock; +} + +POST(sys_msgrcv) +{ + ML_(linux_POST_sys_msgrcv)(tid, RES, ARG1, ARG2, ARG3, ARG4, ARG5); +} + +PRE(sys_semctl) +{ + switch (ARG3 & ~VKI_IPC_64) { + case VKI_IPC_INFO: + case VKI_SEM_INFO: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd, + struct seminfo *, arg); + break; + case VKI_IPC_STAT: + case VKI_SEM_STAT: + case VKI_IPC_SET: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd, + struct semid_ds *, arg); + break; + case VKI_GETALL: + case VKI_SETALL: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd, + unsigned short *, arg); + break; + default: + PRINT("sys_semctl ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "semctl", int, semid, int, semnum, int, cmd); + break; + } + ML_(generic_PRE_sys_semctl)(tid, ARG1, ARG2, ARG3, ARG4); +} + +POST(sys_semctl) +{ + ML_(generic_POST_sys_semctl)(tid, RES, ARG1, ARG2, ARG3, ARG4); +} + +PRE(sys_semget) +{ + PRINT("sys_semget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg); +} + +PRE(sys_semop) +{ + *flags |= SfMayBlock; + PRINT("sys_semop ( %ld, %#lx, %lu )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "semop", int, semid, struct sembuf *, sops, + unsigned, nsoops); + ML_(generic_PRE_sys_semop)(tid, ARG1, ARG2, ARG3); +} + +PRE(sys_semtimedop) +{ + *flags |= SfMayBlock; + PRINT("sys_semtimedop ( %ld, %#lx, %lu, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(long, "semtimedop", int, semid, struct sembuf *, sops, + unsigned, nsoops, struct timespec *, timeout); + ML_(generic_PRE_sys_semtimedop)(tid, ARG1, ARG2, ARG3, ARG4); +} + +/* Very much MIPS specific */ +PRE(sys_cacheflush) +{ + PRINT("cacheflush (%lx, %#lx, %#lx)", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "cacheflush", void *, addrlow, void *, addrhigh, + int, flags); + VG_(discard_translations)((Addr64) ARG1, ((ULong) ARG2) - ((ULong) ARG1) + + 1ULL /*paranoia */ , "PRE(sys_cacheflush)"); + SET_STATUS_Success(0); +} + +PRE(sys_getpeername) +{ + PRINT("sys_getpeername ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "getpeername", int, s, struct sockaddr *, name, + int *, namelen); + ML_(generic_PRE_sys_getpeername) (tid, ARG1, ARG2, ARG3); +} + +POST(sys_getpeername) +{ + vg_assert (SUCCESS); + ML_(generic_POST_sys_getpeername)(tid, VG_ (mk_SysRes_Success) (RES), + ARG1, ARG2, ARG3); +} + +PRE(sys_getsockname) +{ + PRINT("sys_getsockname ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "getsockname", int, s, struct sockaddr *, name, + int *, namelen); + ML_(generic_PRE_sys_getsockname)(tid, ARG1, ARG2, ARG3); +} + +POST(sys_getsockname) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_getsockname)(tid, VG_ (mk_SysRes_Success) (RES), + ARG1, ARG2, ARG3); +} + +PRE(sys_shutdown) +{ + *flags |= SfMayBlock; + PRINT("sys_shutdown ( %ld, %ld )", ARG1, ARG2); + PRE_REG_READ2(int, "shutdown", int, s, int, how); +} + +PRE(sys_reboot) +{ + PRINT("sys_reboot ( %ld )", ARG1); + PRE_REG_READ1(int, "reboot", int, flags); + *flags |= SfMayBlock; +} + +PRE(sys_bind) +{ + PRINT("sys_bind ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "bind", int, sockfd, struct sockaddr *, my_addr, + int, addrlen); + ML_(generic_PRE_sys_bind)(tid, ARG1, ARG2, ARG3); +} + +PRE(sys_setdomainname) +{ + PRINT ("sys_setdomainname ( %#lx, %ld )", ARG1, ARG2); + PRE_REG_READ2 (long, "setdomainname", const void *, name, int, len); +} + +PRE(sys_sethostname) +{ + PRINT ("sys_sethostname ( %ld, %ld )", ARG1, ARG2); + PRE_REG_READ2 (long, "sethostname", const void *, name, int, len); +} + +PRE(sys_listen) +{ + PRINT ("sys_listen ( %ld, %ld )", ARG1, ARG2); + PRE_REG_READ2 (long, "listen", int, s, int, backlog); +} + +PRE(sys_sendmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sendmsg", int, s, const struct msghdr *, msg, + int, flags); + ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2); +} + +PRE(sys_recvmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags); + ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2); +} + +POST(sys_recvmsg) +{ + ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES); +} + +PRE(sys_sendto) +{ + *flags |= SfMayBlock; + PRINT ("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )", ARG1, ARG2, ARG3, + ARG4, ARG5, ARG6); + PRE_REG_READ6 (long, "sendto", int, s, const void *, msg, int, len, + unsigned int, flags, const struct sockaddr *, to, int, tolen); + ML_(generic_PRE_sys_sendto) (tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); +} + +PRE(sys_recvfrom) +{ + *flags |= SfMayBlock; + PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )", ARG1, ARG2, + ARG3, ARG4, ARG5, ARG6); + PRE_REG_READ6(long, "recvfrom", int, s, void *, buf, int, len, + unsigned int, flags, struct sockaddr *, from, int *, fromlen); + ML_(generic_PRE_sys_recvfrom)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); +} + +POST(sys_recvfrom) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES), + ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); +} + +PRE (sys_connect) +{ + *flags |= SfMayBlock; + PRINT("sys_connect ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "connect", int, sockfd, struct sockaddr *, serv_addr, + int, addrlen); + ML_(generic_PRE_sys_connect)(tid, ARG1, ARG2, ARG3); +} + +PRE(sys_accept) +{ + *flags |= SfMayBlock; + PRINT("sys_accept ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "accept", int, s, struct sockaddr *, addr, + int, *addrlen); + ML_(generic_PRE_sys_accept)(tid, ARG1, ARG2, ARG3); +} + +PRE(sys_accept4) +{ + *flags |= SfMayBlock; +} + +POST(sys_accept) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_accept)(tid, VG_ (mk_SysRes_Success) (RES), + ARG1, ARG2, ARG3); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_setsockopt) +{ + PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, + ARG4, ARG5); + PRE_REG_READ5(long, "setsockopt", int, s, int, level, int, optname, + const void *, optval, int, optlen); + ML_(generic_PRE_sys_setsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5); +} + +PRE(sys_getsockopt) +{ + PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, + ARG4, ARG5); + PRE_REG_READ5(long, "getsockopt", int, s, int, level, int, optname, + void *, optval, int, *optlen); + ML_(linux_PRE_sys_getsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5); +} + +POST(sys_getsockopt) +{ + vg_assert(SUCCESS); + ML_(linux_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success) (RES), + ARG1, ARG2, ARG3, ARG4, ARG5); +} + +PRE(sys_socket) +{ + PRINT("sys_socket ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol); +} + +POST(sys_socket) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES)); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_ptrace) +{ + PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(int, "ptrace", long, request, long, pid, long, addr, + long, data); + switch (ARG1) { + case VKI_PTRACE_PEEKTEXT: + case VKI_PTRACE_PEEKDATA: + case VKI_PTRACE_PEEKUSR: + PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long)); + break; + case VKI_PTRACE_GETEVENTMSG: + PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long)); + break; + case VKI_PTRACE_GETSIGINFO: + PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t)); + break; + case VKI_PTRACE_SETSIGINFO: + PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t)); + break; + default: + break; + } +} + +POST(sys_ptrace) +{ + switch (ARG1) { + case VKI_PTRACE_PEEKTEXT: + case VKI_PTRACE_PEEKDATA: + case VKI_PTRACE_PEEKUSR: + POST_MEM_WRITE (ARG4, sizeof(long)); + break; + case VKI_PTRACE_GETEVENTMSG: + POST_MEM_WRITE (ARG4, sizeof(unsigned long)); + break; + case VKI_PTRACE_GETSIGINFO: + POST_MEM_WRITE (ARG4, sizeof(vki_siginfo_t)); + break; + default: + break; + } +} + +PRE (sys_mmap) +{ + SysRes r; + PRINT("sys_mmap ( %#lx, %llu, %lu, %lu, %lu, %ld )", ARG1, (ULong)ARG2, + ARG3, ARG4, ARG5, ARG6); + PRE_REG_READ6(long, "mmap", unsigned long, start, vki_size_t, length, + int, prot, int, flags, int, fd, unsigned long, offset); + r = ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, + (Off64T) ARG6); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_clone) +{ + Bool badarg = False; + UInt cloneflags; + PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3, + ARG4, ARG5); + PRE_REG_READ2(int, "clone", unsigned long, flags, void *, child_stack); + if (ARG1 & VKI_CLONE_PARENT_SETTID) { + if (VG_(tdict).track_pre_reg_read) { + PRA3("clone", int *, parent_tidptr); + } + PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int)); + if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) { + badarg = True; + } + } + if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) { + if (VG_(tdict).track_pre_reg_read) { + PRA5("clone", int *, child_tidptr); + } + PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof (Int)); + if (!VG_(am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE)) + badarg = True; + } + if (badarg) { + SET_STATUS_Failure(VKI_EFAULT); + return; + } + 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)) { + case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES: + /* thread creation */ + SET_STATUS_from_SysRes(do_clone(tid, + ARG1, /* flags */ + (Addr)ARG2, /* child SP */ + (Int *)ARG3, /* parent_tidptr */ + (Int *)ARG5, /* child_tidptr */ + (Addr)ARG4)); /* child_tls */ + 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, "Unsupported clone() flags: 0x%lx\n", ARG1); + VG_(message)(Vg_UserMsg, "\n"); + VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n"); + VG_(message)(Vg_UserMsg, + " - via a threads library (LinuxThreads or NPTL)\n"); + VG_(message)(Vg_UserMsg, + " - via the implementation of fork or vfork\n"); + 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; + } +} + +PRE(sys_rt_sigreturn) +{ + /* See comments on PRE(sys_rt_sigreturn) in syswrap-s390x-linux.c for + an explanation of what follows. */ + ThreadState* tst; + PRINT("sys_rt_sigreturn ( )"); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + + /* This is only so that the IA is (might be) useful to report if + something goes wrong in the sigreturn */ + ML_(fixup_guest_state_to_restart_syscall)(&tst->arch); + + /* 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; +} + +PRE(sys_set_thread_area) +{ + PRINT("set_thread_area (%lx)", ARG1); + PRE_REG_READ1(long, "set_thread_area", unsigned long, addr); + SET_STATUS_from_SysRes(sys_set_tls(tid, ARG1)); +} + +PRE(sys_pipe) +{ + PRINT("sys_pipe ( %#lx )", ARG1); + PRE_REG_READ1(int, "pipe", int *, filedes); + PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) ); +} + +POST(sys_pipe) +{ + Int p0, p1; + vg_assert(SUCCESS); + p0 = RES; + p1 = sr_ResEx(status->sres); + + if (!ML_(fd_allowed)(p0, "pipe", tid, True) || + !ML_(fd_allowed)(p1, "pipe", tid, True)) { + VG_(close)(p0); + VG_(close)(p1); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, p0); + ML_(record_fd_open_nameless)(tid, p1); + } + } +} + +#undef PRE +#undef POST + +/* --------------------------------------------------------------------- + The mips64/Linux syscall table + ------------------------------------------------------------------ */ + +/* Add an mips64-linux specific wrapper to a syscall table. */ +#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(mips_linux, sysno, name) +#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(mips_linux, sysno, name) + +static SyscallTableEntry syscall_main_table[] = { + GENXY (__NR_read, sys_read), /* 5000 */ + GENX_ (__NR_write, sys_write), + GENXY (__NR_open, sys_open), + GENXY (__NR_close, sys_close), + GENXY (__NR_stat, sys_newstat), + GENXY (__NR_fstat, sys_newfstat), + GENXY (__NR_lstat, sys_newlstat), + GENXY (__NR_poll, sys_poll), + LINX_ (__NR_lseek, sys_lseek), + PLAX_ (__NR_mmap, sys_mmap), + GENXY (__NR_mprotect, sys_mprotect), + GENXY (__NR_munmap, sys_munmap), + GENX_ (__NR_brk, sys_brk), + LINXY (__NR_rt_sigaction, sys_rt_sigaction), + LINXY (__NR_rt_sigprocmask, sys_rt_sigprocmask), + LINXY (__NR_ioctl, sys_ioctl), + LINXY (__NR_eventfd2, sys_eventfd2), + LINXY (__NR_signalfd4, sys_signalfd4), + GENXY (__NR_pread64, sys_pread64), + GENX_ (__NR_pwrite64, sys_pwrite64), + GENXY (__NR_readv, sys_readv), + GENX_ (__NR_writev, sys_writev), + GENX_ (__NR_access, sys_access), + PLAXY (__NR_pipe, sys_pipe), + LINXY (__NR_pipe2, sys_pipe2), + GENX_ (__NR__newselect,sys_select), + LINX_ (__NR_sched_yield, sys_sched_yield), + GENX_ (__NR_mremap, sys_mremap), + GENX_ (__NR_msync, sys_msync), + GENXY (__NR_mincore, sys_mincore), + GENX_ (__NR_madvise, sys_madvise), + PLAX_ (__NR_shmget, sys_shmget), + /* PLAXY(__NR_shmat,sys_shmat), */ + PLAXY (__NR_shmctl, sys_shmctl), + GENXY (__NR_dup, sys_dup), + GENXY (__NR_dup2, sys_dup2), + /* GENXY(__NR_dup3,sys_dup3), */ + GENX_ (__NR_pause, sys_pause), + GENXY (__NR_nanosleep, sys_nanosleep), + GENXY (__NR_getitimer, sys_getitimer), + GENXY (__NR_setitimer, sys_setitimer), + GENX_ (__NR_alarm, sys_alarm), + GENX_ (__NR_getpid, sys_getpid), + /* LINX_(__NR_fallocate,sys_fallocate), */ + LINXY (__NR_sendfile, sys_sendfile), + PLAXY (__NR_socket, sys_socket), + PLAX_ (__NR_connect, sys_connect), + PLAXY (__NR_accept, sys_accept), + /* PLAX_(__NR_accept4,sys_accept4), */ + PLAX_ (__NR_sendto, sys_sendto), + PLAXY (__NR_recvfrom, sys_recvfrom), + PLAX_ (__NR_sendmsg, sys_sendmsg), + PLAXY (__NR_recvmsg, sys_recvmsg), + PLAX_ (__NR_shutdown, sys_shutdown), + PLAX_ (__NR_bind, sys_bind), + PLAX_ (__NR_listen, sys_listen), + PLAXY (__NR_getsockname, sys_getsockname), + PLAXY (__NR_getpeername, sys_getpeername), + PLAXY (__NR_socketpair, sys_socketpair), + PLAX_ (__NR_setsockopt, sys_setsockopt), + PLAXY (__NR_getsockopt, sys_getsockopt), + PLAX_ (__NR_clone, sys_clone), + GENX_ (__NR_fork, sys_fork), + GENX_ (__NR_execve, sys_execve), + GENX_ (__NR_exit, sys_exit), + GENXY (__NR_wait4, sys_wait4), + GENX_ (__NR_kill, sys_kill), + GENXY (__NR_uname, sys_newuname), + PLAX_ (__NR_semget, sys_semget), + PLAX_ (__NR_semop, sys_semop), + PLAXY (__NR_semctl, sys_semctl), + PLAXY (__NR_shmdt, sys_shmdt), + PLAX_ (__NR_msgget, sys_msgget), + PLAX_ (__NR_msgsnd, sys_msgsnd), + PLAXY (__NR_msgrcv, sys_msgrcv), + PLAXY (__NR_msgctl, sys_msgctl), + LINXY (__NR_fcntl, sys_fcntl), + GENX_ (__NR_flock, sys_flock), + GENX_ (__NR_fsync, sys_fsync), + GENX_ (__NR_fdatasync, sys_fdatasync), + GENX_ (__NR_truncate, sys_truncate), + GENX_ (__NR_ftruncate, sys_ftruncate), + GENXY (__NR_getdents, sys_getdents), + GENXY (__NR_getcwd, sys_getcwd), + GENX_ (__NR_chdir, sys_chdir), + GENX_ (__NR_fchdir, sys_fchdir), + GENX_ (__NR_rename, sys_rename), + GENX_ (__NR_mkdir, sys_mkdir), + GENX_ (__NR_rmdir, sys_rmdir), + GENXY (__NR_creat, sys_creat), + GENX_ (__NR_link, sys_link), + GENX_ (__NR_unlink, sys_unlink), + GENX_ (__NR_symlink, sys_symlink), + GENX_ (__NR_readlink, sys_readlink), + GENX_ (__NR_chmod, sys_chmod), + GENX_ (__NR_fchmod, sys_fchmod), + GENX_ (__NR_chown, sys_chown), + GENX_ (__NR_fchown, sys_fchown), + GENX_ (__NR_lchown, sys_lchown), + GENX_ (__NR_umask, sys_umask), + GENXY (__NR_gettimeofday, sys_gettimeofday), + GENXY (__NR_getrlimit, sys_getrlimit), + GENXY (__NR_getrusage, sys_getrusage), + LINXY (__NR_sysinfo, sys_sysinfo), + GENXY (__NR_times, sys_times), + PLAXY (__NR_ptrace, sys_ptrace), + GENX_ (__NR_getuid, sys_getuid), + LINXY (__NR_syslog, sys_syslog), + GENX_ (__NR_getgid, sys_getgid), + GENX_ (__NR_setuid, sys_setuid), + GENX_ (__NR_setgid, sys_setgid), + GENX_ (__NR_geteuid, sys_geteuid), + GENX_ (__NR_getegid, sys_getegid), + GENX_ (__NR_setpgid, sys_setpgid), + GENX_ (__NR_getppid, sys_getppid), + GENX_ (__NR_getpgrp, sys_getpgrp), + GENX_ (__NR_setsid, sys_setsid), + GENX_ (__NR_setreuid, sys_setreuid), + GENX_ (__NR_setregid, sys_setregid), + GENXY (__NR_getgroups, sys_getgroups), + GENX_ (__NR_setgroups, sys_setgroups), + LINX_ (__NR_setresuid, sys_setresuid), + LINXY (__NR_getresuid, sys_getresuid), + LINX_ (__NR_setresgid, sys_setresgid), + LINXY (__NR_getresgid, sys_getresgid), + GENX_ (__NR_getpgid, sys_getpgid), + LINX_ (__NR_setfsuid, sys_setfsuid), + LINX_ (__NR_setfsgid, sys_setfsgid), + GENX_ (__NR_getsid, sys_getsid), + LINXY (__NR_capget, sys_capget), + LINX_ (__NR_capset, sys_capset), + LINXY (__NR_rt_sigpending, sys_rt_sigpending), + LINXY (__NR_rt_sigtimedwait, sys_rt_sigtimedwait), + LINXY (__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), + LINX_ (__NR_rt_sigsuspend, sys_rt_sigsuspend), + GENXY (__NR_sigaltstack, sys_sigaltstack), + LINX_ (__NR_utime, sys_utime), + GENX_ (__NR_mknod, sys_mknod), + LINX_ (__NR_personality, sys_personality), + PLAX_ (__NR_ustat, sys_ustat), + GENXY (__NR_statfs, sys_statfs), + GENXY (__NR_fstatfs, sys_fstatfs), + PLAX_ (__NR_sysfs, sys_sysfs), + GENX_ (__NR_getpriority, sys_getpriority), + GENX_ (__NR_setpriority, sys_setpriority), + LINXY (__NR_sched_setparam, sys_sched_setparam), + LINXY (__NR_sched_getparam, sys_sched_getparam), + LINX_ (__NR_sched_setscheduler, sys_sched_setscheduler), + LINX_ (__NR_sched_getscheduler, sys_sched_getscheduler), + LINX_ (__NR_sched_get_priority_max, sys_sched_get_priority_max), + LINX_ (__NR_sched_get_priority_min, sys_sched_get_priority_min), + PLAX_ (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), + GENX_ (__NR_mlock, sys_mlock), + GENX_ (__NR_munlock, sys_munlock), + GENX_ (__NR_mlockall, sys_mlockall), + LINX_ (__NR_munlockall, sys_munlockall), + LINX_ (__NR_vhangup, sys_vhangup), + /* GENX_(__NR_pivot_root,sys_pivot_root), */ + LINXY (__NR__sysctl, sys_sysctl), + LINXY (__NR_prctl, sys_prctl), + LINXY (__NR_adjtimex, sys_adjtimex), + GENX_ (__NR_setrlimit, sys_setrlimit), + GENX_ (__NR_chroot, sys_chroot), + GENX_ (__NR_sync, sys_sync), + GENX_ (__NR_acct, sys_acct), + GENX_ (__NR_settimeofday, sys_settimeofday), + LINX_ (__NR_mount, sys_mount), + LINX_ (__NR_umount2, sys_umount), + PLAX_ (__NR_swapon, sys_swapon), + PLAX_ (__NR_swapoff, sys_swapoff), + PLAX_ (__NR_reboot, sys_reboot), + PLAX_ (__NR_sethostname, sys_sethostname), + PLAX_ (__NR_setdomainname, sys_setdomainname), + GENX_ (__NR_create_module, sys_ni_syscall), + LINX_ (__NR_init_module, sys_init_module), + LINX_ (__NR_delete_module, sys_delete_module), + GENX_ (__NR_get_kernel_syms, sys_ni_syscall), + GENX_ (__NR_query_module, sys_ni_syscall), + LINX_ (__NR_quotactl, sys_quotactl), + /* GENX_(__NR_nfsservctl,sys_nfsservctl), */ + GENXY (__NR_getpmsg, sys_getpmsg), + GENX_ (__NR_putpmsg, sys_putpmsg), + GENX_ (__NR_afs_syscall, sys_ni_syscall), + /* GENX_(__NR_reserved177,sys_reserved177), */ + LINX_ (__NR_gettid, sys_gettid), + /* GENX_(__NR_readahead,sys_readahead), */ + LINX_ (__NR_setxattr, sys_setxattr), + LINX_ (__NR_lsetxattr, sys_lsetxattr), + LINX_ (__NR_fsetxattr, sys_fsetxattr), + LINXY (__NR_getxattr, sys_getxattr), + LINXY (__NR_lgetxattr, sys_lgetxattr), + LINXY (__NR_fgetxattr, sys_fgetxattr), + LINXY (__NR_listxattr, sys_listxattr), + LINXY (__NR_llistxattr, sys_llistxattr), + LINXY (__NR_flistxattr, sys_flistxattr), + LINX_ (__NR_removexattr, sys_removexattr), + LINX_ (__NR_lremovexattr, sys_lremovexattr), + LINX_ (__NR_fremovexattr, sys_fremovexattr), + LINXY (__NR_tkill, sys_tkill), + /* GENX_(__NR_reserved193,sys_reserved193), */ + LINXY (__NR_futex, sys_futex), + LINX_ (__NR_sched_setaffinity, sys_sched_setaffinity), + LINXY (__NR_sched_getaffinity, sys_sched_getaffinity), + PLAX_ (__NR_cacheflush, sys_cacheflush), + LINXY (__NR_io_setup, sys_io_setup), + LINX_ (__NR_io_destroy, sys_io_destroy), + LINXY (__NR_io_getevents, sys_io_getevents), + LINX_ (__NR_io_submit, sys_io_submit), + LINXY (__NR_io_cancel, sys_io_cancel), + LINX_ (__NR_exit_group, sys_exit_group), + /* LINXY (__NR_lookup_dcookie, sys_lookup_dcookie), */ + LINXY (__NR_epoll_create, sys_epoll_create), + /* LINXY(__NR_epoll_create1,sys_epoll_create1), */ + LINX_ (__NR_epoll_ctl, sys_epoll_ctl), + LINXY (__NR_epoll_wait, sys_epoll_wait), + PLAX_(__NR_rt_sigreturn,sys_rt_sigreturn), + /* LINXY(__NR_fcntl64,sys_fcntl64), */ + LINX_ (__NR_set_tid_address, sys_set_tid_address), + PLAX_ (__NR_semtimedop, sys_semtimedop), + LINX_ (__NR_fadvise64, sys_fadvise64), + LINXY (__NR_timer_create, sys_timer_create), + LINXY (__NR_timer_settime, sys_timer_settime), + LINXY (__NR_timer_gettime, sys_timer_gettime), + LINX_ (__NR_timer_getoverrun, sys_timer_getoverrun), + LINX_ (__NR_timer_delete, sys_timer_delete), + LINX_ (__NR_clock_settime, sys_clock_settime), + LINXY (__NR_clock_gettime, sys_clock_gettime), + LINXY (__NR_clock_getres, sys_clock_getres), + LINXY (__NR_clock_nanosleep, sys_clock_nanosleep), + LINX_ (__NR_tgkill, sys_tgkill), + GENX_ (__NR_utimes, sys_utimes), + LINX_ (__NR_mbind, sys_mbind), + LINXY (__NR_get_mempolicy, sys_get_mempolicy), + LINX_ (__NR_set_mempolicy, sys_set_mempolicy), + LINXY (__NR_mq_open, sys_mq_open), + LINX_ (__NR_mq_unlink, sys_mq_unlink), + LINX_ (__NR_mq_timedsend, sys_mq_timedsend), + LINXY (__NR_mq_timedreceive, sys_mq_timedreceive), + LINX_ (__NR_mq_notify, sys_mq_notify), + LINXY (__NR_mq_getsetattr, sys_mq_getsetattr), + GENX_ (__NR_vserver, sys_ni_syscall), + LINXY (__NR_waitid, sys_waitid), + LINX_ (__NR_add_key, sys_add_key), + LINX_ (__NR_request_key, sys_request_key), + LINXY (__NR_keyctl, sys_keyctl), + PLAX_ (__NR_set_thread_area, sys_set_thread_area), + LINX_ (__NR_inotify_init, sys_inotify_init), + LINX_ (__NR_inotify_add_watch, sys_inotify_add_watch), + LINX_ (__NR_inotify_rm_watch, sys_inotify_rm_watch), + LINXY (__NR_openat, sys_openat), + LINX_ (__NR_mkdirat, sys_mkdirat), + LINX_ (__NR_mknodat, sys_mknodat), + LINX_ (__NR_fchownat, sys_fchownat), + LINX_ (__NR_futimesat, sys_futimesat), + LINX_ (__NR_unlinkat, sys_unlinkat), + LINX_ (__NR_renameat, sys_renameat), + LINX_ (__NR_linkat, sys_linkat), + LINX_ (__NR_symlinkat, sys_symlinkat), + LINX_ (__NR_readlinkat, sys_readlinkat), + LINX_ (__NR_fchmodat, sys_fchmodat), + LINX_ (__NR_faccessat, sys_faccessat), + LINX_ (__NR_pselect6, sys_pselect6), + LINXY (__NR_ppoll, sys_ppoll), + PLAX_ (__NR_unshare, sys_unshare), + PLAX_ (__NR_splice, sys_splice), + LINX_ (__NR_sync_file_range, sys_sync_file_range), + PLAX_ (__NR_tee, sys_tee), + PLAX_ (__NR_vmsplice, sys_vmsplice), + LINX_ (__NR_set_robust_list, sys_set_robust_list), + LINXY (__NR_get_robust_list, sys_get_robust_list), + LINXY (__NR_epoll_pwait, sys_epoll_pwait), + LINX_ (__NR_ioprio_set, sys_ioprio_set), + LINX_ (__NR_ioprio_get, sys_ioprio_get), + LINX_ (__NR_utimensat, sys_utimensat), + LINXY (__NR_signalfd, sys_signalfd), + LINXY (__NR_eventfd, sys_eventfd), + LINX_ (__NR_fallocate, sys_fallocate), + LINXY (__NR_timerfd_create, sys_timerfd_create), + LINXY (__NR_timerfd_gettime, sys_timerfd_gettime), + LINXY (__NR_timerfd_settime, sys_timerfd_settime) +}; + +SyscallTableEntry * ML_(get_linux_syscall_entry) ( UInt sysno ) +{ + const UInt syscall_main_table_size + = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]); + + if (sysno < syscall_main_table_size) { + SyscallTableEntry * sys = &syscall_main_table[sysno]; + if (sys->before == NULL) + return NULL; /* no entry */ + else + return sys; + } + /* Can't find a wrapper */ + return NULL; +} + +#endif /* defined(VGP_mips64_linux) */ + +/*--------------------------------------------------------------------*/ +/*--- end syswrap-mips64-linux.c ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index d41e2d6e04..f2a86eae5c 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -1073,6 +1073,62 @@ VG_(mips32_linux_REDIR_FOR_strlen): VG_(trampoline_stuff_end): +# undef UD2_16 +# undef UD2_64 +# undef UD2_256 +# undef UD2_1024 +# undef UD2_PAGE + +/*---------------------- mips64-linux ----------------------*/ +#else +#if defined(VGP_mips64_linux) + +# define UD2_16 trap ; trap ; trap; trap +# 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 + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(mips64_linux_SUBST_FOR_rt_sigreturn) +VG_(mips64_linux_SUBST_FOR_rt_sigreturn): + li $2,__NR_rt_sigreturn + syscall + nop + .long 0 /*illegal insn*/ + +/* There's no particular reason that this needs to be handwritten + assembly, but since that's what this file contains, here's a + simple strlen implementation (written in C and compiled by gcc.) +*/ +.global VG_(mips64_linux_REDIR_FOR_strlen) +.type VG_(mips64_linux_REDIR_FOR_strlen), @function +VG_(mips64_linux_REDIR_FOR_strlen): + lbu $12, 0($4) + li $13, 0 + beq $12, $0, M01 + nop + +M02: + addiu $13, $13, 1 + addiu $4, $4, 1 + lbu $12, 0($4) + bne $12, $0, M02 + nop + +M01: + move $2, $13 + jr $31 + nop + +.size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen) + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + + # undef UD2_16 # undef UD2_64 # undef UD2_256 @@ -1091,6 +1147,7 @@ VG_(trampoline_stuff_end): #endif #endif #endif +#endif #if defined(VGO_linux) /* Let the linker know we don't need an executable stack */ diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 6f8eeef415..5088c3667d 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -749,7 +749,8 @@ void log_bytes ( HChar* bytes, Int nbytes ) static Bool translations_allowable_from_seg ( NSegment const* seg ) { -# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) +# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \ + || defined(VGA_mips64) Bool allowR = True; # else Bool allowR = False; @@ -1211,11 +1212,16 @@ Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb ) nraddr_szB == 8 ? mkU64(0) : mkU32(0) ) ); -# if defined(VGP_mips32_linux) // t9 needs to be set to point to the start of the redirected function. +# if defined(VGP_mips32_linux) + VgCallbackClosure* closure = (VgCallbackClosure*)closureV; + Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25); + addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr))); +# endif +# if defined(VGP_mips64_linux) VgCallbackClosure* closure = (VgCallbackClosure*)closureV; - Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25); - addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) ); + Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); + addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); # endif # if defined(VG_PLAT_USES_PPCTOC) { VgCallbackClosure* closure = (VgCallbackClosure*)closureV; @@ -1253,10 +1259,14 @@ Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb ) : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr )) ) ); -# if defined(VGP_mips32_linux) // t9 needs to be set to point to the start of the redirected function. - Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25); - addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) ); +# if defined(VGP_mips32_linux) + Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25); + addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr))); +# endif +# if defined(VGP_mips64_linux) + Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); + addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); # endif # if defined(VGP_ppc64_linux) addStmtToIRSB( diff --git a/coregrind/m_ume/elf.c b/coregrind/m_ume/elf.c index 4686e43d20..9a43bf5fc7 100644 --- a/coregrind/m_ume/elf.c +++ b/coregrind/m_ume/elf.c @@ -338,8 +338,14 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info) which totally screws things up, because nothing else can go there. So bump the hacky load addess along by 0x8000, to 0x108000. */ + /* Later .. on mips64 we can't use 0x108000, because mapelf will fail. */ +#if defined(VGP_mips64_linux) + if (ebase < 0x100000) + ebase = 0x100000; +#else if (ebase < 0x108000) ebase = 0x108000; +#endif } info->phnum = e->e.e_phnum; diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h index 17b33f677f..b6821f3694 100644 --- a/coregrind/pub_core_aspacemgr.h +++ b/coregrind/pub_core_aspacemgr.h @@ -345,7 +345,7 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, // protects such stacks. #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ - || defined(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) # define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb #else diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h index 4431b38207..a086986497 100644 --- a/coregrind/pub_core_basics.h +++ b/coregrind/pub_core_basics.h @@ -62,6 +62,8 @@ # include "libvex_guest_s390x.h" #elif defined(VGA_mips32) # include "libvex_guest_mips32.h" +#elif defined(VGA_mips64) +# include "libvex_guest_mips64.h" #else # error Unknown arch #endif @@ -115,6 +117,11 @@ typedef UInt r31; /* Return address of the last subroutine call */ UInt r28; } MIPS32; + struct { + ULong r30; /* Stack frame pointer or subroutine variable */ + ULong r31; /* Return address of the last subroutine call */ + ULong r28; + } MIPS64; } misc; } UnwindStartRegs; diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index bcf1a74915..6705bffdfa 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -120,7 +120,7 @@ typedef typedef struct { Addr ia; Addr sp; Addr fp; Addr lr;} D3UnwindRegs; -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_mips64) typedef struct { Addr pc; Addr sp; Addr fp; Addr ra; } D3UnwindRegs; diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h index 11e590a8cf..97324a3807 100644 --- a/coregrind/pub_core_machine.h +++ b/coregrind/pub_core_machine.h @@ -86,6 +86,17 @@ # define VG_ELF_MACHINE EM_MIPS # define VG_ELF_CLASS ELFCLASS32 # undef VG_PLAT_USES_PPCTOC +#elif defined(VGP_mips64_linux) +# if defined (VG_LITTLEENDIAN) +# define VG_ELF_DATA2XXX ELFDATA2LSB +# elif defined (VG_BIGENDIAN) +# define VG_ELF_DATA2XXX ELFDATA2MSB +# else +# error "Unknown endianness" +# endif +# define VG_ELF_MACHINE EM_MIPS +# define VG_ELF_CLASS ELFCLASS64 +# undef VG_PLAT_USES_PPCTOC #else # error Unknown platform #endif @@ -119,6 +130,10 @@ # define VG_INSTR_PTR guest_PC # define VG_STACK_PTR guest_r29 # define VG_FRAME_PTR guest_r30 +#elif defined(VGA_mips64) +# define VG_INSTR_PTR guest_PC +# define VG_STACK_PTR guest_r29 +# define VG_FRAME_PTR guest_r30 #else # error Unknown arch #endif diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h index 54b4020112..814d2300b9 100644 --- a/coregrind/pub_core_mallocfree.h +++ b/coregrind/pub_core_mallocfree.h @@ -71,7 +71,8 @@ typedef Int ArenaId; // greater than 8. #if defined(VGP_x86_linux) || \ defined(VGP_arm_linux) || \ - defined(VGP_mips32_linux) + defined(VGP_mips32_linux) || \ + defined(VGP_mips64_linux) # define VG_MIN_MALLOC_SZB 8 // Nb: We always use 16 bytes for Darwin, even on 32-bits, so it can be used // for any AltiVec- or SSE-related type. This matches the Darwin libc. diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h index 9cd0ea80c9..1648f8c15c 100644 --- a/coregrind/pub_core_syscall.h +++ b/coregrind/pub_core_syscall.h @@ -81,6 +81,8 @@ extern SysRes VG_(mk_SysRes_amd64_darwin)( UChar scclass, Bool isErr, extern SysRes VG_(mk_SysRes_s390x_linux) ( Long val ); extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1, UWord a3 ); +extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1, + ULong a3 ); extern SysRes VG_(mk_SysRes_Error) ( UWord val ); extern SysRes VG_(mk_SysRes_Success) ( UWord val ); diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h index 0bd9927033..7e7fa874db 100644 --- a/coregrind/pub_core_threadstate.h +++ b/coregrind/pub_core_threadstate.h @@ -89,6 +89,8 @@ typedef typedef VexGuestS390XState VexGuestArchState; #elif defined(VGA_mips32) typedef VexGuestMIPS32State VexGuestArchState; +#elif defined(VGA_mips64) + typedef VexGuestMIPS64State VexGuestArchState; #else # error Unknown architecture #endif diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 209213fe7a..b536edec17 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -133,6 +133,11 @@ extern Addr VG_(mips32_linux_SUBST_FOR_rt_sigreturn); extern UInt VG_(mips32_linux_REDIR_FOR_strlen)( void* ); #endif +#if defined(VGP_mips64_linux) +extern Addr VG_(mips64_linux_SUBST_FOR_rt_sigreturn); +extern UInt VG_(mips64_linux_REDIR_FOR_strlen)( void* ); +#endif + #endif // __PUB_CORE_TRAMPOLINE_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h index 6473294f8a..c3b3855eb2 100644 --- a/coregrind/pub_core_transtab_asm.h +++ b/coregrind/pub_core_transtab_asm.h @@ -62,7 +62,8 @@ #elif defined(VGA_s390x) || defined(VGA_arm) # define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 1) & VG_TT_FAST_MASK) -#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32) +#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32) \ + || defined(VGA_mips64) # define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 2) & VG_TT_FAST_MASK) #else diff --git a/coregrind/vgdb.c b/coregrind/vgdb.c index b46c4b9d54..fed0d9217f 100644 --- a/coregrind/vgdb.c +++ b/coregrind/vgdb.c @@ -81,7 +81,7 @@ 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(VGP_mips32_linux) + || defined(VGP_mips32_linux) || defined(VGA_mips64) #define PTRACEINVOKER #else I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c @@ -926,6 +926,8 @@ Bool invoke_gdbserver (int pid) sp = user_mod.regs.gprs[15]; #elif defined(VGA_mips32) sp = user_mod.regs[29*2]; +#elif defined(VGA_mips64) + sp = user_mod.regs[29]; #else I_die_here : (sp) architecture missing in vgdb.c #endif @@ -1011,6 +1013,8 @@ Bool invoke_gdbserver (int pid) user_mod.regs[34*2+1] = 0; user_mod.regs[25*2] = shared32->invoke_gdbserver; user_mod.regs[25*2+1] = 0; +#elif defined(VGA_mips64) + assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe #else I_die_here : architecture missing in vgdb.c #endif @@ -1092,6 +1096,13 @@ Bool invoke_gdbserver (int pid) user_mod.regs.psw.addr = shared64->invoke_gdbserver; #elif defined(VGA_mips32) assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe +#elif defined(VGA_mips64) + /* put check arg in register 4 */ + user_mod.regs[4] = check; + /* put NULL return address in ra */ + user_mod.regs[31] = bad_return; + user_mod.regs[34] = shared64->invoke_gdbserver; + user_mod.regs[25] = shared64->invoke_gdbserver; #else I_die_here: architecture missing in vgdb.c #endif diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h index b8a59f661e..9362e82455 100644 --- a/drd/drd_bitmap.h +++ b/drd/drd_bitmap.h @@ -139,7 +139,8 @@ Addr make_address(const UWord a1, const UWord a0) #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \ || defined(VGA_mips32) #define BITS_PER_BITS_PER_UWORD 5 -#elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x) +#elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x) \ + || defined(VGA_mips64) #define BITS_PER_BITS_PER_UWORD 6 #else #error Unknown platform. diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c index 4172c44eee..289f3a0435 100644 --- a/drd/drd_clientreq.c +++ b/drd/drd_clientreq.c @@ -69,7 +69,7 @@ void DRD_(clientreq_init)(void) * DRD's handler for Valgrind client requests. The code below handles both * DRD's public and tool-internal client requests. */ -#if defined(VGP_mips32_linux) +#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) /* There is a cse related issue in gcc for MIPS. Optimization level has to be lowered, so cse related optimizations are not included. */ diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c index ddfad819fc..e2f0e0b5a2 100644 --- a/drd/drd_load_store.c +++ b/drd/drd_load_store.c @@ -51,6 +51,8 @@ #define STACK_POINTER_OFFSET OFFSET_s390x_r15 #elif defined(VGA_mips32) #define STACK_POINTER_OFFSET OFFSET_mips32_r29 +#elif defined(VGA_mips64) +#define STACK_POINTER_OFFSET OFFSET_mips64_r29 #else #error Unknown architecture. #endif diff --git a/drd/drd_thread.c b/drd/drd_thread.c index 160ce07cf1..1fead7e3d1 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -597,7 +597,7 @@ Bool DRD_(thread_get_joinable)(const DrdThreadId tid) } /** Store the thread mode: joinable or detached. */ -#if defined(VGP_mips32_linux) +#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) /* There is a cse related issue in gcc for MIPS. Optimization level has to be lowered, so cse related optimizations are not included.*/ diff --git a/include/Makefile.am b/include/Makefile.am index 41defb8ceb..358ee10a16 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -49,6 +49,7 @@ nobase_pkginclude_HEADERS = \ vki/vki-posixtypes-arm-linux.h \ vki/vki-posixtypes-s390x-linux.h \ vki/vki-posixtypes-mips32-linux.h \ + vki/vki-posixtypes-mips64-linux.h \ vki/vki-amd64-linux.h \ vki/vki-ppc32-linux.h \ vki/vki-ppc64-linux.h \ @@ -56,6 +57,7 @@ nobase_pkginclude_HEADERS = \ vki/vki-arm-linux.h \ vki/vki-s390x-linux.h \ vki/vki-mips32-linux.h \ + vki/vki-mips64-linux.h \ vki/vki-scnums-amd64-linux.h \ vki/vki-scnums-ppc32-linux.h \ vki/vki-scnums-ppc64-linux.h \ @@ -63,5 +65,6 @@ nobase_pkginclude_HEADERS = \ vki/vki-scnums-arm-linux.h \ vki/vki-scnums-s390x-linux.h \ vki/vki-scnums-mips32-linux.h \ + vki/vki-scnums-mips64-linux.h \ vki/vki-scnums-darwin.h \ vki/vki-xen.h diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h index 92c06972e5..22e2461d00 100644 --- a/include/pub_tool_basics.h +++ b/include/pub_tool_basics.h @@ -269,10 +269,10 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { #undef VG_LITTLEENDIAN #if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \ - || (defined(VGA_mips32) && defined (_MIPSEL)) + || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEL)) # define VG_LITTLEENDIAN 1 #elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \ - || (defined(VGA_mips32) && defined (_MIPSEB)) + || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEB)) # define VG_BIGENDIAN 1 #else # error Unknown arch @@ -283,7 +283,7 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { # 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_mips32) || defined(VGA_mips64) # define VG_REGPARM(n) /* */ #else # error Unknown arch diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index e52e47cc5f..99aae0317d 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -91,6 +91,12 @@ # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0 +#elif defined(VGP_mips64_linux) +# define VG_MIN_INSTR_SZB 4 +# define VG_MAX_INSTR_SZB 4 +# define VG_CLREQ_SZB 20 +# define VG_STACK_REDZONE_SZB 0 + #else # error Unknown platform #endif diff --git a/include/pub_tool_vkiscnums_asm.h b/include/pub_tool_vkiscnums_asm.h index dece742b02..3e907e702b 100644 --- a/include/pub_tool_vkiscnums_asm.h +++ b/include/pub_tool_vkiscnums_asm.h @@ -54,6 +54,9 @@ #elif defined(VGP_mips32_linux) # include "vki/vki-scnums-mips32-linux.h" +#elif defined(VGP_mips64_linux) +# include "vki/vki-scnums-mips64-linux.h" + #elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) # include "vki/vki-scnums-darwin.h" diff --git a/include/valgrind.h b/include/valgrind.h index 0f2f96951e..320683eeab 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -118,6 +118,7 @@ #undef PLAT_arm_linux #undef PLAT_s390x_linux #undef PLAT_mips32_linux +#undef PLAT_mips64_linux #if defined(__APPLE__) && defined(__i386__) @@ -140,7 +141,11 @@ #elif defined(__linux__) && defined(__s390__) && defined(__s390x__) # define PLAT_s390x_linux 1 #elif defined(__linux__) && defined(__mips__) +#if (__mips==64) +# define PLAT_mips64_linux 1 +#else # define PLAT_mips32_linux 1 +#endif #else /* If we're not compiling for our target platform, don't generate any inline asms. */ @@ -763,7 +768,7 @@ typedef "move %0, $11\n\t" /*result*/ \ : "=r" (_zzq_result) \ : "r" (_zzq_default), "r" (&_zzq_args[0]) \ - : "cc","memory", "t3", "t4"); \ + : "$11", "$12"); \ _zzq_result; \ }) @@ -776,7 +781,7 @@ typedef "move %0, $11" /*result*/ \ : "=r" (__addr) \ : \ - : "cc", "memory" , "t3" \ + : "$11" \ ); \ _zzq_orig->nraddr = __addr; \ } @@ -796,6 +801,75 @@ typedef #endif /* PLAT_mips32_linux */ +/* ------------------------- mips64-linux ---------------- */ + +#if defined(PLAT_mips64_linux) + +typedef + struct { + unsigned long long nraddr; /* where's the code? */ + } + OrigFn; + +/* dsll $0,$0, 3 + * dsll $0,$0, 13 + * dsll $0,$0, 29 + * dsll $0,$0, 19*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \ + "dsll $0,$0,29 ; dsll $0,$0,19\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("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = client_request ( $12 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "$11", "$12"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned long long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* $11 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "$11"); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir $25 */ \ + "or $15, $15, $15\n\t" + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or $11, $11, $11\n\t" \ + ); \ + } while (0) + +#endif /* PLAT_mips64_linux */ + /* Insert assembly code for other platforms here... */ #endif /* NVALGRIND */ @@ -3881,7 +3955,7 @@ typedef #endif /* PLAT_s390x_linux */ -/* ------------------------- mips-linux ------------------------- */ +/* ------------------------- mips32-linux ----------------------- */ #if defined(PLAT_mips32_linux) @@ -3901,19 +3975,19 @@ typedef _argvec[0] = (unsigned long)_orig.nraddr; \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "subu $29, $29, 16 \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "subu $29, $29, 16 \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 16\n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ "addu $29, $29, 8 \n\t" \ - "move %0, $v0\n" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -3927,20 +4001,20 @@ typedef _argvec[1] = (unsigned long)(arg1); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ "subu $29, $29, 16 \n\t" \ - "lw $a0, 4(%1) \n\t" /* arg1*/ \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "lw $4, 4(%1) \n\t" /* arg1*/ \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 16 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ "addu $29, $29, 8 \n\t" \ - "move %0, $v0\n" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -3955,21 +4029,21 @@ typedef _argvec[2] = (unsigned long)(arg2); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ "subu $29, $29, 16 \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 16 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ "addu $29, $29, 8 \n\t" \ - "move %0, $v0\n" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -3985,22 +4059,22 @@ typedef _argvec[3] = (unsigned long)(arg3); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ "subu $29, $29, 16 \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 16 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ "addu $29, $29, 8 \n\t" \ - "move %0, $v0\n" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4017,23 +4091,23 @@ typedef _argvec[4] = (unsigned long)(arg4); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ "subu $29, $29, 16 \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 16 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ "addu $29, $29, 8 \n\t" \ - "move %0, $v0\n" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4051,25 +4125,25 @@ typedef _argvec[5] = (unsigned long)(arg5); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 24\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 24\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ "addu $29, $29, 24 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4087,28 +4161,28 @@ typedef _argvec[6] = (unsigned long)(arg6); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 32\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ "nop\n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $4, 20($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 32 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4129,29 +4203,29 @@ typedef _argvec[7] = (unsigned long)(arg7); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 32\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 32\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 32 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 32 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4173,31 +4247,31 @@ typedef _argvec[8] = (unsigned long)(arg8); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 40\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 32(%1) \n\t" \ - "sw $a0, 28($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 40 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4220,33 +4294,33 @@ typedef _argvec[9] = (unsigned long)(arg9); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 40\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 32(%1) \n\t" \ - "sw $a0, 28($sp) \n\t" \ - "lw $a0, 36(%1) \n\t" \ - "sw $a0, 32($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 40\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 40 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 40 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4270,35 +4344,35 @@ typedef _argvec[10] = (unsigned long)(arg10); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 48\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 32(%1) \n\t" \ - "sw $a0, 28($sp) \n\t" \ - "lw $a0, 36(%1) \n\t" \ - "sw $a0, 32($sp) \n\t" \ - "lw $a0, 40(%1) \n\t" \ - "sw $a0, 36($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 48 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4324,37 +4398,37 @@ typedef _argvec[11] = (unsigned long)(arg11); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 48\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 32(%1) \n\t" \ - "sw $a0, 28($sp) \n\t" \ - "lw $a0, 36(%1) \n\t" \ - "sw $a0, 32($sp) \n\t" \ - "lw $a0, 40(%1) \n\t" \ - "sw $a0, 36($sp) \n\t" \ - "lw $a0, 44(%1) \n\t" \ - "sw $a0, 40($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 48\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 48 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 48 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) @@ -4381,45 +4455,462 @@ typedef _argvec[12] = (unsigned long)(arg12); \ __asm__ volatile( \ "subu $29, $29, 8 \n\t" \ - "sw $gp, 0($sp) \n\t" \ - "sw $ra, 4($sp) \n\t" \ - "lw $a0, 20(%1) \n\t" \ - "subu $sp, $sp, 56\n\t" \ - "sw $a0, 16($sp) \n\t" \ - "lw $a0, 24(%1) \n\t" \ - "sw $a0, 20($sp) \n\t" \ - "lw $a0, 28(%1) \n\t" \ - "sw $a0, 24($sp) \n\t" \ - "lw $a0, 32(%1) \n\t" \ - "sw $a0, 28($sp) \n\t" \ - "lw $a0, 36(%1) \n\t" \ - "sw $a0, 32($sp) \n\t" \ - "lw $a0, 40(%1) \n\t" \ - "sw $a0, 36($sp) \n\t" \ - "lw $a0, 44(%1) \n\t" \ - "sw $a0, 40($sp) \n\t" \ - "lw $a0, 48(%1) \n\t" \ - "sw $a0, 44($sp) \n\t" \ - "lw $a0, 4(%1) \n\t" \ - "lw $a1, 8(%1) \n\t" \ - "lw $a2, 12(%1) \n\t" \ - "lw $a3, 16(%1) \n\t" \ - "lw $t9, 0(%1) \n\t" /* target->t9 */ \ + "sw $28, 0($29) \n\t" \ + "sw $31, 4($29) \n\t" \ + "lw $4, 20(%1) \n\t" \ + "subu $29, $29, 56\n\t" \ + "sw $4, 16($29) \n\t" \ + "lw $4, 24(%1) \n\t" \ + "sw $4, 20($29) \n\t" \ + "lw $4, 28(%1) \n\t" \ + "sw $4, 24($29) \n\t" \ + "lw $4, 32(%1) \n\t" \ + "sw $4, 28($29) \n\t" \ + "lw $4, 36(%1) \n\t" \ + "sw $4, 32($29) \n\t" \ + "lw $4, 40(%1) \n\t" \ + "sw $4, 36($29) \n\t" \ + "lw $4, 44(%1) \n\t" \ + "sw $4, 40($29) \n\t" \ + "lw $4, 48(%1) \n\t" \ + "sw $4, 44($29) \n\t" \ + "lw $4, 4(%1) \n\t" \ + "lw $5, 8(%1) \n\t" \ + "lw $6, 12(%1) \n\t" \ + "lw $7, 16(%1) \n\t" \ + "lw $25, 0(%1) \n\t" /* target->t9 */ \ VALGRIND_CALL_NOREDIR_T9 \ - "addu $sp, $sp, 56 \n\t" \ - "lw $gp, 0($sp) \n\t" \ - "lw $ra, 4($sp) \n\t" \ - "addu $sp, $sp, 8 \n\t" \ - "move %0, $v0\n" \ + "addu $29, $29, 56 \n\t" \ + "lw $28, 0($29) \n\t" \ + "lw $31, 4($29) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $2\n" \ : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ ); \ lval = (__typeof__(lval)) _res; \ } while (0) #endif /* PLAT_mips32_linux */ +/* ------------------------- mips64-linux ------------------------- */ + +#if defined(PLAT_mips64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ +"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ +"$25", "$31" + +/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned + long) == 4. */ + +#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( \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + 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( \ + "ld $4, 8(%1)\n\t" /* arg1*/ \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + 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( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + 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( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + 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( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1) \n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + "dsubu $29, $29, 8\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 8\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + "dsubu $29, $29, 16\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 16\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + "dsubu $29, $29, 24\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 24\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ + arg6,arg7,arg8,arg9,arg10, \ + arg11,arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + 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); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + "dsubu $29, $29, 32\n\t" \ + "ld $4, 72(%1)\n\t" \ + "sd $4, 0($29)\n\t" \ + "ld $4, 80(%1)\n\t" \ + "sd $4, 8($29)\n\t" \ + "ld $4, 88(%1)\n\t" \ + "sd $4, 16($29)\n\t" \ + "ld $4, 96(%1)\n\t" \ + "sd $4, 24($29)\n\t" \ + "ld $4, 8(%1)\n\t" \ + "ld $5, 16(%1)\n\t" \ + "ld $6, 24(%1)\n\t" \ + "ld $7, 32(%1)\n\t" \ + "ld $8, 40(%1)\n\t" \ + "ld $9, 48(%1)\n\t" \ + "ld $10, 56(%1)\n\t" \ + "ld $11, 64(%1)\n\t" \ + "ld $25, 0(%1)\n\t" /* target->t9 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "daddu $29, $29, 32\n\t" \ + "move %0, $2\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "r" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips64_linux */ + /* ------------------------------------------------------------------ */ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ @@ -4913,5 +5404,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) #undef PLAT_arm_linux #undef PLAT_s390x_linux #undef PLAT_mips32_linux +#undef PLAT_mips64_linux #endif /* __VALGRIND_H */ diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index f789aa7837..a1a05d1aa7 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -93,6 +93,8 @@ # include "vki-posixtypes-s390x-linux.h" #elif defined(VGA_mips32) # include "vki-posixtypes-mips32-linux.h" +#elif defined(VGA_mips64) +# include "vki-posixtypes-mips64-linux.h" #else # error Unknown platform #endif @@ -215,6 +217,8 @@ typedef unsigned int vki_uint; # include "vki-s390x-linux.h" #elif defined(VGA_mips32) # include "vki-mips32-linux.h" +#elif defined(VGA_mips64) +# include "vki-mips64-linux.h" #else # error Unknown platform #endif diff --git a/include/vki/vki-mips64-linux.h b/include/vki/vki-mips64-linux.h new file mode 100644 index 0000000000..2b65fe50fc --- /dev/null +++ b/include/vki/vki-mips64-linux.h @@ -0,0 +1,994 @@ + +/*--------------------------------------------------------------------*/ +/*--- mips/Linux-specific kernel interface. vki-mips64-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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. +*/ + +#ifndef __VKI_MIPS64_LINUX_H +#define __VKI_MIPS64_LINUX_H + +#include + +// mips endian +#if defined (_MIPSEL) +#define VKI_LITTLE_ENDIAN 1 +#elif defined (_MIPSEB) +#define VKI_BIG_ENDIAN 1 +#endif + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/cachectl.h +//---------------------------------------------------------------------- + +#define VKI_ICACHE (1<<0) /* flush instruction cache */ +#define VKI_DCACHE (1<<1) /* writeback and flush data cache */ +#define VKI_BCACHE (VKI_ICACHE | VKI_DCACHE) /* flush both caches */ + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/mips-mips/types.h +//---------------------------------------------------------------------- + +typedef __signed__ char __vki_s8; +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 char vki_s8; +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; + +#if (_MIPS_SZLONG == 64) +typedef __signed__ long __vki_s64; +typedef unsigned long __vki_u64; +#else +typedef __signed__ long long __vki_s64; +typedef unsigned long long __vki_u64; +#endif + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/page.h +//---------------------------------------------------------------------- + +/* PAGE_SHIFT determines the page size */ +#define VKI_PAGE_SHIFT MIPS_PAGE_SHIFT +#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_PAGE_MASK (~(VKI_PAGE_SIZE-1)) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/arch/mips/include/asm/shmparam.h +//---------------------------------------------------------------------- + +#define VKI_SHMLBA VKI_PAGE_SIZE + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/signal.h +//---------------------------------------------------------------------- + +#define VKI_MINSIGSTKSZ 2048 + +#define VKI_SIG_BLOCK 1 /* for blocking signals */ +#define VKI_SIG_UNBLOCK 2 /* for unblocking signals */ +#define VKI_SIG_SETMASK 3 /* for setting the signal mask */ + +/* Type of a signal handler. */ +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 */ +#define VKI_SIG_ERR ((__vki_sighandler_t)-1) /* error return from signal */ + +#define _VKI_NSIG 128 +#define _VKI_NSIG_BPW 64 +#define _VKI_NSIG_WORDS (_VKI_NSIG / _VKI_NSIG_BPW) + +typedef unsigned long vki_old_sigset_t; /* at least 32 bits */ + +typedef struct { + unsigned long sig[_VKI_NSIG_WORDS]; +} vki_sigset_t; + +#define VKI_SIGHUP 1 /* Hangup (POSIX). */ +#define VKI_SIGINT 2 /* Interrupt (ANSI). */ +#define VKI_SIGQUIT 3 /* Quit (POSIX). */ +#define VKI_SIGILL 4 /* Illegal instruction (ANSI). */ +#define VKI_SIGTRAP 5 /* Trace trap (POSIX). */ +#define VKI_SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define VKI_SIGABRT VKI_SIGIOT /* Abort (ANSI). */ +#define VKI_SIGEMT 7 +#define VKI_SIGFPE 8 /* Floating-point exception (ANSI). */ +#define VKI_SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define VKI_SIGBUS 10 /* BUS error (4.2 BSD). */ +#define VKI_SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define VKI_SIGSYS 12 +#define VKI_SIGPIPE 13 /* Broken pipe (POSIX). */ +#define VKI_SIGALRM 14 /* Alarm clock (POSIX). */ +#define VKI_SIGTERM 15 /* Termination (ANSI). */ +#define VKI_SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define VKI_SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define VKI_SIGCHLD 18 /* Child status has changed (POSIX). */ +#define VKI_SIGCLD VKI_SIGCHLD /* Same as SIGCHLD (System V). */ +#define VKI_SIGPWR 19 /* Power failure restart (System V). */ +#define VKI_SIGWINCH 20 /* Window size change (4.3 BSD, Sun). */ +#define VKI_SIGURG 21 /* Urgent condition on socket. */ +#define VKI_SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define VKI_SIGPOLL VKI_SIGIO /* Pollable event occurred (System V).*/ +#define VKI_SIGSTOP 23 /* Stop, unblockable (POSIX). */ +#define VKI_SIGTSTP 24 /* Keyboard stop (POSIX). */ +#define VKI_SIGCONT 25 /* Continue (POSIX). */ +#define VKI_SIGTTIN 26 /* Background read from tty (POSIX). */ +#define VKI_SIGTTOU 27 /* Background write to tty (POSIX). */ +#define VKI_SIGVTALRM 28 /* Virtual alarm clock (4.2 BSD). */ +#define VKI_SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */ +#define VKI_SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */ +#define VKI_SIGXFSZ 31 /* File size limit exceeded (4.2 BSD).*/ + +/* These should not be considered constants from userland. */ +#define VKI_SIGRTMIN 32 +// [[This was (_NSIG-1) in 2.4.X... not sure if it matters.]] +#define VKI_SIGRTMAX (_VKI_NSIG - 1) + +#define VKI_SA_ONSTACK 0x08000000u +#define VKI_SA_RESETHAND 0x80000000u +#define VKI_SA_RESTART 0x10000000u +#define VKI_SA_SIGINFO 0x00000008u +#define VKI_SA_NODEFER 0x40000000u +#define VKI_SA_NOCLDWAIT 0x00010000u +#define VKI_SA_NOCLDSTOP 0x00000001u + +#define VKI_SA_NOMASK VKI_SA_NODEFER +#define VKI_SA_ONESHOT VKI_SA_RESETHAND +//#define VKI_SA_INTERRUPT 0x20000000 /* dummy -- ignored */ + +#define VKI_SA_RESTORER 0x04000000 + +#define VKI_SS_ONSTACK 1 +#define VKI_SS_DISABLE 2 + +struct vki_old_sigaction { + // [[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.]] + unsigned long sa_flags; + __vki_sighandler_t ksa_handler; + vki_old_sigset_t sa_mask; + __vki_sigrestore_t sa_restorer; +}; + +struct vki_sigaction { + unsigned int sa_flags; + __vki_sighandler_t sa_handler; + vki_sigset_t sa_mask; +}; + + +struct vki_sigaction_base { + // [[See comment about extra 'k' above]] + unsigned int sa_flags; + __vki_sighandler_t ksa_handler; + vki_sigset_t sa_mask; // mask last for extensibility + __vki_sigrestore_t sa_restorer; +}; + +/* 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; + vki_size_t ss_size; + int ss_flags; +} vki_stack_t; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/sigcontext.h +//---------------------------------------------------------------------- + +struct _vki_fpreg { + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _vki_fpxreg { + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _vki_xmmreg { + unsigned long element[4]; +}; + +struct _vki_fpstate { + /* Regular FPU environment */ + unsigned long cw; + unsigned long sw; + unsigned long tag; + unsigned long ipoff; + unsigned long cssel; + unsigned long dataoff; + unsigned long datasel; + struct _vki_fpreg _st[8]; + unsigned short status; + unsigned short magic; /* 0xffff = regular FPU data only */ + + /* FXSR FPU environment */ + unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */ + unsigned long mxcsr; + unsigned long reserved; + struct _vki_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ + struct _vki_xmmreg _xmm[8]; + unsigned long padding[56]; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/sigcontext.h +//---------------------------------------------------------------------- +struct vki_sigcontext { + __vki_u64 sc_regs[32]; + __vki_u64 sc_fpregs[32]; + __vki_u64 sc_mdhi; + __vki_u64 sc_hi1; + __vki_u64 sc_hi2; + __vki_u64 sc_hi3; + __vki_u64 sc_mdlo; + __vki_u64 sc_lo1; + __vki_u64 sc_lo2; + __vki_u64 sc_lo3; + __vki_u64 sc_pc; + __vki_u64 sc_fpc_csr; + __vki_u64 sc_used_math; + __vki_u64 sc_dsp; + __vki_u64 sc_reserved; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/mman.h +//---------------------------------------------------------------------- + +#define VKI_PROT_NONE 0x0 /* No page permissions */ +#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_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 0x001 /* Share changes */ +#define VKI_MAP_PRIVATE 0x002 /* Changes are private */ +//#define VKI_MAP_TYPE 0x0f /* Mask for type of mapping */ +#define VKI_MAP_FIXED 0x010 /* Interpret addr exactly */ + +#define VKI_MAP_NORESERVE 0x0400 /* don't reserve swap pages */ + +/* These are linux-specific */ +#define VKI_MAP_NORESERVE 0x0400 /* don't check for reservations */ +#define VKI_MAP_ANONYMOUS 0x0800 /* don't use a file */ +#define VKI_MAP_GROWSDOWN 0x1000 /* stack-like segment */ +#define VKI_MAP_DENYWRITE 0x2000 /* ETXTBSY */ +#define VKI_MAP_EXECUTABLE 0x4000 /* mark it as an executable */ +#define VKI_MAP_LOCKED 0x8000 /* pages are locked */ +#define VKI_MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +#define VKI_MAP_NONBLOCK 0x20000 /* do not block on IO */ + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/fcntl.h +//---------------------------------------------------------------------- + +#define VKI_O_RDONLY 00 +#define VKI_O_WRONLY 01 +#define VKI_O_RDWR 02 +#define VKI_O_ACCMODE 03 + +#define VKI_O_CREAT 0x0100 /* not fcntl */ +#define VKI_O_EXCL 0x0400 /* not fcntl */ + +#define VKI_O_TRUNC 0x0200 /* not fcntl */ + +#define VKI_O_APPEND 0x0008 +#define VKI_O_NONBLOCK 0x0080 +#define VKI_O_LARGEFILE 0x2000 + +#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 14 +#define VKI_F_SETLK 6 +#define VKI_F_SETLKW 7 + +#define VKI_F_SETOWN 24 /* for sockets. */ +#define VKI_F_GETOWN 23 /* 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_GETLK64 33 /* using 'struct flock64' */ +#define VKI_F_SETLK64 34 +#define VKI_F_SETLKW64 35 + +/* for F_[GET|SET]FL */ +#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +#define VKI_F_LINUX_SPECIFIC_BASE 1024 + +struct vki_f_owner_ex { + int type; + __vki_kernel_pid_t pid; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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 5 /* max number of open files */ + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/socket.h +//---------------------------------------------------------------------- + +#define VKI_SOL_SOCKET 0xffff +#define VKI_SO_TYPE 0x1008 + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-i386/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-2.6.35.9/include/asm-mips/stat.h +//---------------------------------------------------------------------- + +struct vki_stat { + unsigned int st_dev; + unsigned int st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long st_ino; + + int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + unsigned int st_rdev; + unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */ + + long st_size; + + /* + * Actually this should be timestruc_t st_atime, st_mtime and st_ctime + * but we don't have it under Linux. + */ + unsigned int st_atime; + unsigned int st_atime_nsec; /* Reserved for st_atime expansion */ + + unsigned int st_mtime; + unsigned int st_mtime_nsec; /* Reserved for st_mtime expansion */ + + unsigned int st_ctime; + unsigned int st_ctime_nsec; /* Reserved for st_ctime expansion */ + + unsigned int st_blksize; + unsigned int st_pad2; + + long long st_blocks; +}; + +struct vki_stat64 { + unsigned long st_dev; + unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long long st_ino; + + int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + unsigned long st_rdev; + unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + + long long st_size; + + /* + * Actually this should be timestruc_t st_atime, st_mtime and st_ctime + * but we don't have it under Linux. + */ + unsigned long st_atime; + unsigned long st_atime_nsec; /* Reserved for st_atime expansion */ + + unsigned long st_mtime; + unsigned long st_mtime_nsec; /* Reserved for st_mtime expansion */ + + unsigned long st_ctime; + unsigned long st_ctime_nsec; /* Reserved for st_ctime expansion */ + + unsigned long st_blksize; + unsigned long st_pad2; + + long long st_blocks; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/statfs.h +//---------------------------------------------------------------------- + +struct vki_statfs { + __vki_u32 f_type; +#define f_fstyp f_type + __vki_u32 f_bsize; + __vki_u32 f_frsize; + __vki_u32 f_blocks; + __vki_u32 f_bfree; + __vki_u32 f_files; + __vki_u32 f_ffree; + __vki_u32 f_bavail; + __vki_kernel_fsid_t f_fsid; + __vki_u32 f_namelen; + __vki_u32 f_spare[6]; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/termios.h +//---------------------------------------------------------------------- + +struct vki_winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +#define NCCS 23 +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 */ + char c_line; /* line discipline */ + unsigned char c_cc[NCCS]; /* control characters */ +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/termbits.h +//---------------------------------------------------------------------- + +typedef unsigned char vki_cc_t; +typedef unsigned long vki_speed_t; +typedef unsigned long vki_tcflag_t; + +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[NCCS]; /* control characters */ +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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_NRMASK ((1 << _VKI_IOC_NRBITS)-1) +#define _VKI_IOC_TYPEMASK ((1 << _VKI_IOC_TYPEBITS)-1) +#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 1U +#define _VKI_IOC_WRITE 2U +#define _VKI_IOC_READ 4U + +#define _VKI_IOC(dir,type,nr,size) \ + (((dir) << _VKI_IOC_DIRSHIFT) | \ + ((type) << _VKI_IOC_TYPESHIFT) | \ + ((nr) << _VKI_IOC_NRSHIFT) | \ + ((size) << _VKI_IOC_SIZESHIFT)) + +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __VKI_invalid_size_argument_for_IOC; +/* used to create numbers */ +#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), \ + (_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr), \ + (_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type), \ + (nr),(_VKI_IOC_TYPECHECK(size))) + +/* used to decode ioctl numbers.. */ +#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK) +#define _VKI_IOC_TYPE(nr) (((nr) >> _VKI_IOC_TYPESHIFT) & _VKI_IOC_TYPEMASK) +#define _VKI_IOC_NR(nr) (((nr) >> _VKI_IOC_NRSHIFT) & _VKI_IOC_NRMASK) +#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK) + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/ioctls.h +//---------------------------------------------------------------------- + +#define VKI_TCGETA 0x5401 +#define VKI_TCSETA 0x5402 /* Clashes with SNDCTL_TMR_START + sound ioctl */ +#define VKI_TCSETAW 0x5403 +#define VKI_TCSETAF 0x5404 + +#define VKI_TCSBRK 0x5405 +#define VKI_TCXONC 0x5406 +#define VKI_TCFLSH 0x5407 + +#define VKI_TCGETS 0x540d +#define VKI_TCSETS 0x540e +#define VKI_TCSETSW 0x540f +#define VKI_TCSETSF 0x5410 + +#define VKI_TIOCEXCL 0x740d /* set exclusive use of tty */ +#define VKI_TIOCNXCL 0x740e /* reset exclusive use of tty */ +#define VKI_TIOCOUTQ 0x7472 /* output queue size */ +#define VKI_TIOCSTI 0x5472 /* simulate terminal input */ +#define VKI_TIOCMGET 0x741d /* get all modem bits */ +#define VKI_TIOCMBIS 0x741b /* bis modem bits */ +#define VKI_TIOCMBIC 0x741c /* bic modem bits */ +#define VKI_TIOCMSET 0x741a /* set all modem bits */ +#define VKI_TIOCPKT 0x5470 /* pty: set/clear packet mode */ +#define VKI_TIOCPKT_DATA 0x00 /* data packet */ +#define VKI_TIOCPKT_FLUSHREAD 0x01 /* flush packet */ +#define VKI_TIOCPKT_FLUSHWRITE 0x02 /* flush packet */ +#define VKI_TIOCPKT_STOP 0x04 /* stop output */ +#define VKI_TIOCPKT_START 0x08 /* start output */ +#define VKI_TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ +#define VKI_TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ + +/* set window size */ +#define VKI_TIOCSWINSZ _VKI_IOW('t', 103, struct vki_winsize) +/* get window size */ +#define VKI_TIOCGWINSZ _VKI_IOR('t', 104, struct vki_winsize) +#define VKI_TIOCNOTTY 0x5471 /* void tty association */ +#define VKI_TIOCSETD 0x7401 +#define VKI_TIOCGETD 0x7400 + +#define VKI_FIOCLEX 0x6601 +#define VKI_FIONCLEX 0x6602 +#define VKI_FIOASYNC 0x667d +#define VKI_FIONBIO 0x667e +#define VKI_FIOQSIZE 0x667f + +#define VKI_TIOCGLTC 0x7474 /* get special local chars */ +#define VKI_TIOCSLTC 0x7475 /* set special local chars */ +#define VKI_TIOCSPGRP _VKI_IOW('t', 118, int) /* set pgrp of tty */ +#define VKI_TIOCGPGRP _VKI_IOR('t', 119, int) /* get pgrp of tty */ +#define VKI_TIOCCONS _VKI_IOW('t', 120, int) /* become virtual + console */ + +#define VKI_FIONREAD 0x467f +#define VKI_TIOCINQ FIONREAD + +#define VKI_TIOCGETP 0x7408 +#define VKI_TIOCSETP 0x7409 +#define VKI_TIOCSETN 0x740a /* TIOCSETP wo flush */ + +#define VKI_TIOCSBRK 0x5427 /* BSD compatibility */ +#define VKI_TIOCCBRK 0x5428 /* BSD compatibility */ +#define VKI_TIOCGSID 0x7416 /* Return the session ID of FD */ +#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int) /* Get Pty + Number (of pty-mux device) */ +#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int) /* Lock/unlock Pty */ + +/* I hope the range from 0x5480 on is free ... */ +#define VKI_TIOCSCTTY 0x5480 /* become controlling tty */ +#define VKI_TIOCGSOFTCAR 0x5481 +#define VKI_TIOCSSOFTCAR 0x5482 +#define VKI_TIOCLINUX 0x5483 +#define VKI_TIOCGSERIAL 0x5484 +#define VKI_TIOCSSERIAL 0x5485 +#define VKI_TCSBRKP 0x5486 /* Needed for POSIX tcsendbreak() */ +#define VKI_TIOCSERCONFIG 0x5488 +#define VKI_TIOCSERGWILD 0x5489 +#define VKI_TIOCSERSWILD 0x548a +#define VKI_TIOCGLCKTRMIOS 0x548b +#define VKI_TIOCSLCKTRMIOS 0x548c +#define VKI_TIOCSERGSTRUCT 0x548d /* For debugging only */ +#define VKI_TIOCSERGETLSR 0x548e /* Get line status register */ +#define VKI_TIOCSERGETMULTI 0x548f /* Get multiport config */ +#define VKI_TIOCSERSETMULTI 0x5490 /* Set multiport config */ +#define VKI_TIOCMIWAIT 0x5491 /* wait for a change on serial input + line(s) */ +#define VKI_TIOCGICOUNT 0x5492 /* read serial port inline interrupt + counts */ +#define VKI_TIOCGHAYESESP 0x5493 /* Get Hayes ESP configuration */ +#define VKI_TIOCSHAYESESP 0x5494 /* Set Hayes ESP configuration */ + +//---------------------------------------------------------------------- +// From asm-generic/poll.h +//---------------------------------------------------------------------- + +/* These are specified by iBCS2 */ +#define VKI_POLLIN 0x0001 + +struct vki_pollfd { + int fd; + short events; + short revents; +}; +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/elf.h +//---------------------------------------------------------------------- + +#define VKI_ELF_NGREG 45 /* includes nip, msr, lr, etc. */ +#define VKI_ELF_NFPREG 33 /* includes fpscr */ + +typedef unsigned long vki_elf_greg_t; +typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG]; + +typedef double vki_elf_fpreg_t; +typedef vki_elf_fpreg_t vki_elf_fpregset_t[VKI_ELF_NFPREG]; + +typedef struct vki_user_fxsr_struct vki_elf_fpxregset_t; + +#define VKI_AT_SYSINFO 32 +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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; /* mask last for extensibility */ +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/ipcbuf.h +//---------------------------------------------------------------------- + +struct vki_ipc64_perm { + __vki_kernel_key_t key; + __vki_kernel_uid_t uid; + __vki_kernel_gid_t gid; + __vki_kernel_uid_t cuid; + __vki_kernel_gid_t cgid; + __vki_kernel_mode_t mode; + unsigned short seq; + unsigned short __pad1; + unsigned long __unused1; + unsigned long __unused2; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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 __unused1; + unsigned long __unused2; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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-2.6.35.9/include/asm-mips/ipc.h +//---------------------------------------------------------------------- + +struct vki_ipc_kludge { + struct vki_msgbuf __user *msgp; + long msgtyp; +}; + +#define VKI_SEMOP 1 +#define VKI_SEMGET 2 +#define VKI_SEMCTL 3 +#define VKI_SEMTIMEDOP 4 +#define VKI_MSGSND 11 +#define VKI_MSGRCV 12 +#define VKI_MSGGET 13 +#define VKI_MSGCTL 14 +#define VKI_SHMAT 21 +#define VKI_SHMDT 22 +#define VKI_SHMGET 23 +#define VKI_SHMCTL 24 + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-mips/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 __unused1; + unsigned long __unused2; +}; + +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-2.6.35.9/include/asm-mips/ptrace.h +//---------------------------------------------------------------------- + +struct vki_pt_regs { +#ifdef CONFIG_32BIT + /* Pad bytes for argument save space on the stack. */ + unsigned long pad0[6]; +#endif + + /* Saved main processor registers. */ + unsigned long regs[32]; + + /* Saved special registers. */ + unsigned long cp0_status; + unsigned long hi; + unsigned long lo; +#ifdef CONFIG_CPU_HAS_SMARTMIPS + unsigned long acx; +#endif + unsigned long cp0_badvaddr; + unsigned long cp0_cause; + unsigned long cp0_epc; +#ifdef CONFIG_MIPS_MT_SMTC + unsigned long cp0_tcstatus; +#endif /* CONFIG_MIPS_MT_SMTC */ +#ifdef CONFIG_CPU_CAVIUM_OCTEON + unsigned long long mpl[3]; /* MTM{0,1,2} */ + unsigned long long mtp[3]; /* MTP{0,1,2} */ +#endif +} __attribute__ ((aligned (8))); + + +#define vki_user_regs_struct vki_pt_regs + +#define MIPS_lo lo +#define MIPS_hi hi +#define MIPS_r31 regs[31] +#define MIPS_r30 regs[30] +#define MIPS_r29 regs[29] +#define MIPS_r28 regs[28] +#define MIPS_r27 regs[27] +#define MIPS_r26 regs[26] +#define MIPS_r25 regs[25] +#define MIPS_r24 regs[24] +#define MIPS_r23 regs[23] +#define MIPS_r22 regs[22] +#define MIPS_r21 regs[21] +#define MIPS_r20 regs[20] +#define MIPS_r19 regs[19] +#define MIPS_r18 regs[18] +#define MIPS_r17 regs[17] +#define MIPS_r16 regs[16] +#define MIPS_r15 regs[15] +#define MIPS_r14 regs[14] +#define MIPS_r13 regs[13] +#define MIPS_r12 regs[12] +#define MIPS_r11 regs[11] +#define MIPS_r10 regs[10] +#define MIPS_r9 regs[9] +#define MIPS_r8 regs[8] +#define MIPS_r7 regs[7] +#define MIPS_r6 regs[6] +#define MIPS_r5 regs[5] +#define MIPS_r4 regs[4] +#define MIPS_r3 regs[3] +#define MIPS_r2 regs[2] +#define MIPS_r1 regs[1] +#define MIPS_r0 regs[0] + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-i386/ptrace.h +//---------------------------------------------------------------------- + +#define VKI_PTRACE_GETREGS 12 +#define VKI_PTRACE_SETREGS 13 +#define VKI_PTRACE_GETFPREGS 14 +#define VKI_PTRACE_SETFPREGS 15 +#define VKI_PTRACE_GETFPXREGS 18 +#define VKI_PTRACE_SETFPXREGS 19 + +/* Calls to trace a 64bit program from a 32bit program. */ +#define VKI_PTRACE_PEEKTEXT_3264 0xc0 +#define VKI_PTRACE_PEEKDATA_3264 0xc1 +#define VKI_PTRACE_POKETEXT_3264 0xc2 +#define VKI_PTRACE_POKEDATA_3264 0xc3 +#define VKI_PTRACE_GET_THREAD_AREA_3264 0xc4s + +//---------------------------------------------------------------------- +// From linux-2.6.35.9/include/asm-generic/siginfo.h +//---------------------------------------------------------------------- + +#define HAVE_ARCH_SIGINFO_T +typedef union vki_sigval { + int sival_int; + void __user *sival_ptr; +} vki_sigval_t; + +#ifndef __VKI_ARCH_SI_PREAMBLE_SIZE +#define __VKI_ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#endif + +#define VKI_SI_MAX_SIZE 128 + +#ifndef VKI_SI_PAD_SIZE +#define VKI_SI_PAD_SIZE ((VKI_SI_MAX_SIZE - __VKI_ARCH_SI_PREAMBLE_SIZE) / sizeof(int)) +#endif + +#ifndef __VKI_ARCH_SI_UID_T +#define __VKI_ARCH_SI_UID_T vki_uid_t +#endif + +#ifndef __VKI_ARCH_SI_BAND_T +#define __VKI_ARCH_SI_BAND_T long +#endif + +typedef struct vki_siginfo { + int si_signo; + int si_code; + int si_errno; + int __pad0[VKI_SI_MAX_SIZE / sizeof(int) - VKI_SI_PAD_SIZE - 3]; + + union { + int _pad[VKI_SI_PAD_SIZE]; + + /* kill() */ + struct { + vki_pid_t _pid; /* sender's pid */ + __VKI_ARCH_SI_UID_T _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + vki_timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof( __VKI_ARCH_SI_UID_T) - sizeof(int)]; + vki_sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + vki_pid_t _pid; /* sender's pid */ + __VKI_ARCH_SI_UID_T _uid; /* sender's uid */ + vki_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + vki_pid_t _pid; /* which child */ + __VKI_ARCH_SI_UID_T _uid; /* sender's uid */ + int _status; /* exit code */ + vki_clock_t _utime; + vki_clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { + vki_pid_t _pid; /* which child */ + vki_clock_t _utime; + int _status; /* exit code */ + vki_clock_t _stime; + } _irix_sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + void __user *_addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_TRAPNO + int _trapno; /* TRAP # which caused the signal */ +#endif + } _sigfault; + + /* SIGPOLL, SIGXFSZ (To do ...) */ + struct { + __VKI_ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} vki_siginfo_t; + +//---------------------------------------------------------------------- +// From linux-2.6.35.5/include/asm/break.h +//---------------------------------------------------------------------- +#define VKI_BRK_OVERFLOW 6 /* Overflow check */ +#define VKI_BRK_DIVZERO 7 /* Divide by zero check */ + +#endif // __VKI_MIPS64_LINUX_H + +/*--------------------------------------------------------------------*/ +/*--- end vki-mips64-linux.h ---*/ +/*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-posixtypes-mips64-linux.h b/include/vki/vki-posixtypes-mips64-linux.h new file mode 100644 index 0000000000..9f446fcc43 --- /dev/null +++ b/include/vki/vki-posixtypes-mips64-linux.h @@ -0,0 +1,87 @@ + +/*--------------------------------------------------------------------*/ +/*--- mips/Linux-specific kernel interface: posix types. ---*/ +/*--- vki-posixtypes-mips64-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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. +*/ + +#ifndef __VKI_POSIXTYPES_MIPS64_LINUX_H +#define __VKI_POSIXTYPES_MIPS64_LINUX_H + +typedef unsigned long __vki_kernel_ino_t; +typedef unsigned int __vki_kernel_mode_t; +#if (_MIPS_SZLONG == 32) +typedef unsigned long __vki_kernel_nlink_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned int __vki_kernel_nlink_t; +#endif +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; +#if (_MIPS_SZLONG == 32) +typedef unsigned int __vki_kernel_size_t; +typedef int __vki_kernel_ssize_t; +typedef int __vki_kernel_ptrdiff_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned long __vki_kernel_size_t; +typedef long __vki_kernel_ssize_t; +typedef long __vki_kernel_ptrdiff_t; +#endif +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 long __vki_kernel_daddr_t; +typedef char * __vki_kernel_caddr_t; + +typedef unsigned short __vki_kernel_uid16_t; +typedef unsigned short __vki_kernel_gid16_t; +typedef unsigned int __vki_kernel_uid32_t; +typedef unsigned int __vki_kernel_gid32_t; +typedef __vki_kernel_uid_t __vki_kernel_old_uid_t; +typedef __vki_kernel_gid_t __vki_kernel_old_gid_t; +typedef unsigned int __vki_kernel_old_dev_t; + +typedef long long __vki_kernel_loff_t; + +typedef struct { +#if (_MIPS_SZLONG == 32) + long val[2]; +#endif +#if (_MIPS_SZLONG == 64) + int val[2]; +#endif +} __vki_kernel_fsid_t; + +#endif // __VKI_POSIXTYPES_MIPS64_LINUX_H + +/*--------------------------------------------------------------------*/ +/*--- end vki-posixtypes-mips-linux.h ---*/ +/*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-scnums-mips64-linux.h b/include/vki/vki-scnums-mips64-linux.h new file mode 100644 index 0000000000..b08483886a --- /dev/null +++ b/include/vki/vki-scnums-mips64-linux.h @@ -0,0 +1,338 @@ + +/*--------------------------------------------------------------------*/ +/*--- System call numbers for mips-linux. ---*/ +/*--- vki-scnums-mips64-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2010-2013 RT-RK + mips-valgrind@rt-rk.com + + 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_MIPS64_LINUX_H +#define __VKI_SCNUMS_MIPS64_LINUX_H + +/* + * Linux 64-bit syscalls are in the range from 5000 to 5999. + */ +#define __NR_Linux 5000 +#define __NR_read (__NR_Linux + 0) +#define __NR_write (__NR_Linux + 1) +#define __NR_open (__NR_Linux + 2) +#define __NR_close (__NR_Linux + 3) +#define __NR_stat (__NR_Linux + 4) +#define __NR_fstat (__NR_Linux + 5) +#define __NR_lstat (__NR_Linux + 6) +#define __NR_poll (__NR_Linux + 7) +#define __NR_lseek (__NR_Linux + 8) +#define __NR_mmap (__NR_Linux + 9) +#define __NR_mprotect (__NR_Linux + 10) +#define __NR_munmap (__NR_Linux + 11) +#define __NR_brk (__NR_Linux + 12) +#define __NR_rt_sigaction (__NR_Linux + 13) +#define __NR_rt_sigprocmask (__NR_Linux + 14) +#define __NR_ioctl (__NR_Linux + 15) +#define __NR_pread64 (__NR_Linux + 16) +#define __NR_pwrite64 (__NR_Linux + 17) +#define __NR_readv (__NR_Linux + 18) +#define __NR_writev (__NR_Linux + 19) +#define __NR_access (__NR_Linux + 20) +#define __NR_pipe (__NR_Linux + 21) +#define __NR__newselect (__NR_Linux + 22) +#define __NR_sched_yield (__NR_Linux + 23) +#define __NR_mremap (__NR_Linux + 24) +#define __NR_msync (__NR_Linux + 25) +#define __NR_mincore (__NR_Linux + 26) +#define __NR_madvise (__NR_Linux + 27) +#define __NR_shmget (__NR_Linux + 28) +#define __NR_shmat (__NR_Linux + 29) +#define __NR_shmctl (__NR_Linux + 30) +#define __NR_dup (__NR_Linux + 31) +#define __NR_dup2 (__NR_Linux + 32) +#define __NR_pause (__NR_Linux + 33) +#define __NR_nanosleep (__NR_Linux + 34) +#define __NR_getitimer (__NR_Linux + 35) +#define __NR_setitimer (__NR_Linux + 36) +#define __NR_alarm (__NR_Linux + 37) +#define __NR_getpid (__NR_Linux + 38) +#define __NR_sendfile (__NR_Linux + 39) +#define __NR_socket (__NR_Linux + 40) +#define __NR_connect (__NR_Linux + 41) +#define __NR_accept (__NR_Linux + 42) +#define __NR_sendto (__NR_Linux + 43) +#define __NR_recvfrom (__NR_Linux + 44) +#define __NR_sendmsg (__NR_Linux + 45) +#define __NR_recvmsg (__NR_Linux + 46) +#define __NR_shutdown (__NR_Linux + 47) +#define __NR_bind (__NR_Linux + 48) +#define __NR_listen (__NR_Linux + 49) +#define __NR_getsockname (__NR_Linux + 50) +#define __NR_getpeername (__NR_Linux + 51) +#define __NR_socketpair (__NR_Linux + 52) +#define __NR_setsockopt (__NR_Linux + 53) +#define __NR_getsockopt (__NR_Linux + 54) +#define __NR_clone (__NR_Linux + 55) +#define __NR_fork (__NR_Linux + 56) +#define __NR_execve (__NR_Linux + 57) +#define __NR_exit (__NR_Linux + 58) +#define __NR_wait4 (__NR_Linux + 59) +#define __NR_kill (__NR_Linux + 60) +#define __NR_uname (__NR_Linux + 61) +#define __NR_semget (__NR_Linux + 62) +#define __NR_semop (__NR_Linux + 63) +#define __NR_semctl (__NR_Linux + 64) +#define __NR_shmdt (__NR_Linux + 65) +#define __NR_msgget (__NR_Linux + 66) +#define __NR_msgsnd (__NR_Linux + 67) +#define __NR_msgrcv (__NR_Linux + 68) +#define __NR_msgctl (__NR_Linux + 69) +#define __NR_fcntl (__NR_Linux + 70) +#define __NR_flock (__NR_Linux + 71) +#define __NR_fsync (__NR_Linux + 72) +#define __NR_fdatasync (__NR_Linux + 73) +#define __NR_truncate (__NR_Linux + 74) +#define __NR_ftruncate (__NR_Linux + 75) +#define __NR_getdents (__NR_Linux + 76) +#define __NR_getcwd (__NR_Linux + 77) +#define __NR_chdir (__NR_Linux + 78) +#define __NR_fchdir (__NR_Linux + 79) +#define __NR_rename (__NR_Linux + 80) +#define __NR_mkdir (__NR_Linux + 81) +#define __NR_rmdir (__NR_Linux + 82) +#define __NR_creat (__NR_Linux + 83) +#define __NR_link (__NR_Linux + 84) +#define __NR_unlink (__NR_Linux + 85) +#define __NR_symlink (__NR_Linux + 86) +#define __NR_readlink (__NR_Linux + 87) +#define __NR_chmod (__NR_Linux + 88) +#define __NR_fchmod (__NR_Linux + 89) +#define __NR_chown (__NR_Linux + 90) +#define __NR_fchown (__NR_Linux + 91) +#define __NR_lchown (__NR_Linux + 92) +#define __NR_umask (__NR_Linux + 93) +#define __NR_gettimeofday (__NR_Linux + 94) +#define __NR_getrlimit (__NR_Linux + 95) +#define __NR_getrusage (__NR_Linux + 96) +#define __NR_sysinfo (__NR_Linux + 97) +#define __NR_times (__NR_Linux + 98) +#define __NR_ptrace (__NR_Linux + 99) +#define __NR_getuid (__NR_Linux + 100) +#define __NR_syslog (__NR_Linux + 101) +#define __NR_getgid (__NR_Linux + 102) +#define __NR_setuid (__NR_Linux + 103) +#define __NR_setgid (__NR_Linux + 104) +#define __NR_geteuid (__NR_Linux + 105) +#define __NR_getegid (__NR_Linux + 106) +#define __NR_setpgid (__NR_Linux + 107) +#define __NR_getppid (__NR_Linux + 108) +#define __NR_getpgrp (__NR_Linux + 109) +#define __NR_setsid (__NR_Linux + 110) +#define __NR_setreuid (__NR_Linux + 111) +#define __NR_setregid (__NR_Linux + 112) +#define __NR_getgroups (__NR_Linux + 113) +#define __NR_setgroups (__NR_Linux + 114) +#define __NR_setresuid (__NR_Linux + 115) +#define __NR_getresuid (__NR_Linux + 116) +#define __NR_setresgid (__NR_Linux + 117) +#define __NR_getresgid (__NR_Linux + 118) +#define __NR_getpgid (__NR_Linux + 119) +#define __NR_setfsuid (__NR_Linux + 120) +#define __NR_setfsgid (__NR_Linux + 121) +#define __NR_getsid (__NR_Linux + 122) +#define __NR_capget (__NR_Linux + 123) +#define __NR_capset (__NR_Linux + 124) +#define __NR_rt_sigpending (__NR_Linux + 125) +#define __NR_rt_sigtimedwait (__NR_Linux + 126) +#define __NR_rt_sigqueueinfo (__NR_Linux + 127) +#define __NR_rt_sigsuspend (__NR_Linux + 128) +#define __NR_sigaltstack (__NR_Linux + 129) +#define __NR_utime (__NR_Linux + 130) +#define __NR_mknod (__NR_Linux + 131) +#define __NR_personality (__NR_Linux + 132) +#define __NR_ustat (__NR_Linux + 133) +#define __NR_statfs (__NR_Linux + 134) +#define __NR_fstatfs (__NR_Linux + 135) +#define __NR_sysfs (__NR_Linux + 136) +#define __NR_getpriority (__NR_Linux + 137) +#define __NR_setpriority (__NR_Linux + 138) +#define __NR_sched_setparam (__NR_Linux + 139) +#define __NR_sched_getparam (__NR_Linux + 140) +#define __NR_sched_setscheduler (__NR_Linux + 141) +#define __NR_sched_getscheduler (__NR_Linux + 142) +#define __NR_sched_get_priority_max (__NR_Linux + 143) +#define __NR_sched_get_priority_min (__NR_Linux + 144) +#define __NR_sched_rr_get_interval (__NR_Linux + 145) +#define __NR_mlock (__NR_Linux + 146) +#define __NR_munlock (__NR_Linux + 147) +#define __NR_mlockall (__NR_Linux + 148) +#define __NR_munlockall (__NR_Linux + 149) +#define __NR_vhangup (__NR_Linux + 150) +#define __NR_pivot_root (__NR_Linux + 151) +#define __NR__sysctl (__NR_Linux + 152) +#define __NR_prctl (__NR_Linux + 153) +#define __NR_adjtimex (__NR_Linux + 154) +#define __NR_setrlimit (__NR_Linux + 155) +#define __NR_chroot (__NR_Linux + 156) +#define __NR_sync (__NR_Linux + 157) +#define __NR_acct (__NR_Linux + 158) +#define __NR_settimeofday (__NR_Linux + 159) +#define __NR_mount (__NR_Linux + 160) +#define __NR_umount2 (__NR_Linux + 161) +#define __NR_swapon (__NR_Linux + 162) +#define __NR_swapoff (__NR_Linux + 163) +#define __NR_reboot (__NR_Linux + 164) +#define __NR_sethostname (__NR_Linux + 165) +#define __NR_setdomainname (__NR_Linux + 166) +#define __NR_create_module (__NR_Linux + 167) +#define __NR_init_module (__NR_Linux + 168) +#define __NR_delete_module (__NR_Linux + 169) +#define __NR_get_kernel_syms (__NR_Linux + 170) +#define __NR_query_module (__NR_Linux + 171) +#define __NR_quotactl (__NR_Linux + 172) +#define __NR_nfsservctl (__NR_Linux + 173) +#define __NR_getpmsg (__NR_Linux + 174) +#define __NR_putpmsg (__NR_Linux + 175) +#define __NR_afs_syscall (__NR_Linux + 176) +#define __NR_reserved177 (__NR_Linux + 177) +#define __NR_gettid (__NR_Linux + 178) +#define __NR_readahead (__NR_Linux + 179) +#define __NR_setxattr (__NR_Linux + 180) +#define __NR_lsetxattr (__NR_Linux + 181) +#define __NR_fsetxattr (__NR_Linux + 182) +#define __NR_getxattr (__NR_Linux + 183) +#define __NR_lgetxattr (__NR_Linux + 184) +#define __NR_fgetxattr (__NR_Linux + 185) +#define __NR_listxattr (__NR_Linux + 186) +#define __NR_llistxattr (__NR_Linux + 187) +#define __NR_flistxattr (__NR_Linux + 188) +#define __NR_removexattr (__NR_Linux + 189) +#define __NR_lremovexattr (__NR_Linux + 190) +#define __NR_fremovexattr (__NR_Linux + 191) +#define __NR_tkill (__NR_Linux + 192) +#define __NR_reserved193 (__NR_Linux + 193) +#define __NR_futex (__NR_Linux + 194) +#define __NR_sched_setaffinity (__NR_Linux + 195) +#define __NR_sched_getaffinity (__NR_Linux + 196) +#define __NR_cacheflush (__NR_Linux + 197) +#define __NR_cachectl (__NR_Linux + 198) +#define __NR_sysmips (__NR_Linux + 199) +#define __NR_io_setup (__NR_Linux + 200) +#define __NR_io_destroy (__NR_Linux + 201) +#define __NR_io_getevents (__NR_Linux + 202) +#define __NR_io_submit (__NR_Linux + 203) +#define __NR_io_cancel (__NR_Linux + 204) +#define __NR_exit_group (__NR_Linux + 205) +#define __NR_lookup_dcookie (__NR_Linux + 206) +#define __NR_epoll_create (__NR_Linux + 207) +#define __NR_epoll_ctl (__NR_Linux + 208) +#define __NR_epoll_wait (__NR_Linux + 209) +#define __NR_remap_file_pages (__NR_Linux + 210) +#define __NR_rt_sigreturn (__NR_Linux + 211) +#define __NR_set_tid_address (__NR_Linux + 212) +#define __NR_restart_syscall (__NR_Linux + 213) +#define __NR_semtimedop (__NR_Linux + 214) +#define __NR_fadvise64 (__NR_Linux + 215) +#define __NR_timer_create (__NR_Linux + 216) +#define __NR_timer_settime (__NR_Linux + 217) +#define __NR_timer_gettime (__NR_Linux + 218) +#define __NR_timer_getoverrun (__NR_Linux + 219) +#define __NR_timer_delete (__NR_Linux + 220) +#define __NR_clock_settime (__NR_Linux + 221) +#define __NR_clock_gettime (__NR_Linux + 222) +#define __NR_clock_getres (__NR_Linux + 223) +#define __NR_clock_nanosleep (__NR_Linux + 224) +#define __NR_tgkill (__NR_Linux + 225) +#define __NR_utimes (__NR_Linux + 226) +#define __NR_mbind (__NR_Linux + 227) +#define __NR_get_mempolicy (__NR_Linux + 228) +#define __NR_set_mempolicy (__NR_Linux + 229) +#define __NR_mq_open (__NR_Linux + 230) +#define __NR_mq_unlink (__NR_Linux + 231) +#define __NR_mq_timedsend (__NR_Linux + 232) +#define __NR_mq_timedreceive (__NR_Linux + 233) +#define __NR_mq_notify (__NR_Linux + 234) +#define __NR_mq_getsetattr (__NR_Linux + 235) +#define __NR_vserver (__NR_Linux + 236) +#define __NR_waitid (__NR_Linux + 237) +/* #define __NR_sys_setaltroot (__NR_Linux + 238) */ +#define __NR_add_key (__NR_Linux + 239) +#define __NR_request_key (__NR_Linux + 240) +#define __NR_keyctl (__NR_Linux + 241) +#define __NR_set_thread_area (__NR_Linux + 242) +#define __NR_inotify_init (__NR_Linux + 243) +#define __NR_inotify_add_watch (__NR_Linux + 244) +#define __NR_inotify_rm_watch (__NR_Linux + 245) +#define __NR_migrate_pages (__NR_Linux + 246) +#define __NR_openat (__NR_Linux + 247) +#define __NR_mkdirat (__NR_Linux + 248) +#define __NR_mknodat (__NR_Linux + 249) +#define __NR_fchownat (__NR_Linux + 250) +#define __NR_futimesat (__NR_Linux + 251) +#define __NR_newfstatat (__NR_Linux + 252) +#define __NR_unlinkat (__NR_Linux + 253) +#define __NR_renameat (__NR_Linux + 254) +#define __NR_linkat (__NR_Linux + 255) +#define __NR_symlinkat (__NR_Linux + 256) +#define __NR_readlinkat (__NR_Linux + 257) +#define __NR_fchmodat (__NR_Linux + 258) +#define __NR_faccessat (__NR_Linux + 259) +#define __NR_pselect6 (__NR_Linux + 260) +#define __NR_ppoll (__NR_Linux + 261) +#define __NR_unshare (__NR_Linux + 262) +#define __NR_splice (__NR_Linux + 263) +#define __NR_sync_file_range (__NR_Linux + 264) +#define __NR_tee (__NR_Linux + 265) +#define __NR_vmsplice (__NR_Linux + 266) +#define __NR_move_pages (__NR_Linux + 267) +#define __NR_set_robust_list (__NR_Linux + 268) +#define __NR_get_robust_list (__NR_Linux + 269) +#define __NR_kexec_load (__NR_Linux + 270) +#define __NR_getcpu (__NR_Linux + 271) +#define __NR_epoll_pwait (__NR_Linux + 272) +#define __NR_ioprio_set (__NR_Linux + 273) +#define __NR_ioprio_get (__NR_Linux + 274) +#define __NR_utimensat (__NR_Linux + 275) +#define __NR_signalfd (__NR_Linux + 276) +#define __NR_timerfd (__NR_Linux + 277) +#define __NR_eventfd (__NR_Linux + 278) +#define __NR_fallocate (__NR_Linux + 279) +#define __NR_timerfd_create (__NR_Linux + 280) +#define __NR_timerfd_gettime (__NR_Linux + 281) +#define __NR_timerfd_settime (__NR_Linux + 282) +#define __NR_signalfd4 (__NR_Linux + 283) +#define __NR_eventfd2 (__NR_Linux + 284) +#define __NR_epoll_create1 (__NR_Linux + 285) +#define __NR_dup3 (__NR_Linux + 286) +#define __NR_pipe2 (__NR_Linux + 287) +#define __NR_inotify_init1 (__NR_Linux + 288) +#define __NR_preadv (__NR_Linux + 289) +#define __NR_pwritev (__NR_Linux + 290) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291) +#define __NR_perf_event_open (__NR_Linux + 292) +#define __NR_accept4 (__NR_Linux + 293) + +#endif /* __VKI_SCNUMS_MIPS64_LINUX_H */ + +/*--------------------------------------------------------------------*/ +/*--- end vki-scnums-mips64-linux.h ---*/ +/*--------------------------------------------------------------------*/ diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c index a205b299af..c6f41f4bf2 100644 --- a/memcheck/mc_machine.c +++ b/memcheck/mc_machine.c @@ -81,6 +81,11 @@ # define MC_SIZEOF_GUEST_STATE sizeof(VexGuestMIPS32State) #endif +#if defined(VGA_mips64) +# include "libvex_guest_mips64.h" +# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestMIPS64State) +#endif + static inline Bool host_is_big_endian ( void ) { UInt x = 0x11223344; return 0x1122 == *(UShort*)(&x); @@ -1059,6 +1064,85 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB ) offset,szB); tl_assert(0); # undef GOF +# undef SZB + + /* --------------------- mips64 --------------------- */ + +# elif defined(VGA_mips64) + +# define GOF(_fieldname) \ + (offsetof(VexGuestMIPS64State,guest_##_fieldname)) +# define SZB(_fieldname) \ + (sizeof(((VexGuestMIPS64State*)0)->guest_##_fieldname)) + + Int o = offset; + Int sz = szB; + tl_assert(sz > 0); +#if defined (VG_LITTLEENDIAN) + tl_assert(host_is_little_endian()); +#elif defined (VG_BIGENDIAN) + tl_assert(host_is_big_endian()); +#endif + + if (o >= GOF(r0) && sz <= 8 && o <= (GOF(r31) + 8 - sz)) + return GOF(r0) + ((o-GOF(r0)) & -8) ; + + if (o == GOF(PC) && sz == 8) return -1; /* slot unused */ + + if (o == GOF(HI) && sz == 8) return o; + if (o == GOF(LO) && sz == 8) return o; + + if (o == GOF(FIR) && sz == 4) return -1; /* slot unused */ + if (o == GOF(FCCR) && sz == 4) return -1; /* slot unused */ + if (o == GOF(FEXR) && sz == 4) return -1; /* slot unused */ + if (o == GOF(FENR) && sz == 4) return -1; /* slot unused */ + if (o == GOF(FCSR) && sz == 4) return -1; /* slot unused */ + if (o == GOF(ULR) && sz == 8) return o; + + if (o == GOF(EMNOTE) && sz == 4) return -1; /* slot unused */ + if (o == GOF(TISTART) && sz == 4) return -1; /* slot unused */ + if (o == GOF(TILEN) && sz == 4) return -1; /* slot unused */ + if (o == GOF(NRADDR) && sz == 4) return -1; /* slot unused */ + + if (o >= GOF(f0) && o+sz <= GOF(f0) +SZB(f0)) return GOF(f0); + if (o >= GOF(f1) && o+sz <= GOF(f1) +SZB(f1)) return GOF(f1); + if (o >= GOF(f2) && o+sz <= GOF(f2) +SZB(f2)) return GOF(f2); + if (o >= GOF(f3) && o+sz <= GOF(f3) +SZB(f3)) return GOF(f3); + if (o >= GOF(f4) && o+sz <= GOF(f4) +SZB(f4)) return GOF(f4); + if (o >= GOF(f5) && o+sz <= GOF(f5) +SZB(f5)) return GOF(f5); + if (o >= GOF(f6) && o+sz <= GOF(f6) +SZB(f6)) return GOF(f6); + if (o >= GOF(f7) && o+sz <= GOF(f7) +SZB(f7)) return GOF(f7); + if (o >= GOF(f8) && o+sz <= GOF(f8) +SZB(f8)) return GOF(f8); + if (o >= GOF(f9) && o+sz <= GOF(f9) +SZB(f9)) return GOF(f9); + if (o >= GOF(f10) && o+sz <= GOF(f10)+SZB(f10)) return GOF(f10); + if (o >= GOF(f11) && o+sz <= GOF(f11)+SZB(f11)) return GOF(f11); + if (o >= GOF(f12) && o+sz <= GOF(f12)+SZB(f12)) return GOF(f12); + if (o >= GOF(f13) && o+sz <= GOF(f13)+SZB(f13)) return GOF(f13); + if (o >= GOF(f14) && o+sz <= GOF(f14)+SZB(f14)) return GOF(f14); + if (o >= GOF(f15) && o+sz <= GOF(f15)+SZB(f15)) return GOF(f15); + if (o >= GOF(f16) && o+sz <= GOF(f16)+SZB(f16)) return GOF(f16); + if (o >= GOF(f17) && o+sz <= GOF(f17)+SZB(f17)) return GOF(f17); + if (o >= GOF(f18) && o+sz <= GOF(f18)+SZB(f18)) return GOF(f18); + if (o >= GOF(f19) && o+sz <= GOF(f19)+SZB(f19)) return GOF(f19); + if (o >= GOF(f20) && o+sz <= GOF(f20)+SZB(f20)) return GOF(f20); + if (o >= GOF(f21) && o+sz <= GOF(f21)+SZB(f21)) return GOF(f21); + if (o >= GOF(f22) && o+sz <= GOF(f22)+SZB(f22)) return GOF(f22); + if (o >= GOF(f23) && o+sz <= GOF(f23)+SZB(f23)) return GOF(f23); + if (o >= GOF(f24) && o+sz <= GOF(f24)+SZB(f24)) return GOF(f24); + if (o >= GOF(f25) && o+sz <= GOF(f25)+SZB(f25)) return GOF(f25); + if (o >= GOF(f26) && o+sz <= GOF(f26)+SZB(f26)) return GOF(f26); + if (o >= GOF(f27) && o+sz <= GOF(f27)+SZB(f27)) return GOF(f27); + if (o >= GOF(f28) && o+sz <= GOF(f28)+SZB(f28)) return GOF(f28); + if (o >= GOF(f29) && o+sz <= GOF(f29)+SZB(f29)) return GOF(f29); + if (o >= GOF(f30) && o+sz <= GOF(f30)+SZB(f30)) return GOF(f30); + if (o >= GOF(f31) && o+sz <= GOF(f31)+SZB(f31)) return GOF(f31); + + if ((o > GOF(NRADDR)) && (o <= GOF(NRADDR) +12 )) return -1; + + VG_(printf)("MC_(get_otrack_shadow_offset)(mips)(off=%d,sz=%d)\n", + offset,szB); + tl_assert(0); +# undef GOF # undef SZB # else @@ -1162,6 +1246,12 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr ) VG_(printf)("\n"); tl_assert(0); + /* --------------------- mips64 --------------------- */ +# elif defined(VGA_mips64) + VG_(printf)("get_reg_array_equiv_int_type(mips64): unhandled: "); + ppIRRegArray(arr); + VG_(printf)("\n"); + tl_assert(0); # else # error "FIXME: not implemented for this architecture" # endif diff --git a/tests/arch_test.c b/tests/arch_test.c index b3740b589e..849af6e8c7 100644 --- a/tests/arch_test.c +++ b/tests/arch_test.c @@ -30,6 +30,7 @@ char* all_archs[] = { "arm", "s390x", "mips32", + "mips64", NULL }; @@ -62,6 +63,9 @@ static Bool go(char* arch) #elif defined(VGP_mips32_linux) if ( 0 == strcmp( arch, "mips32" ) ) return True; +#elif defined(VGP_mips64_linux) + if ( 0 == strcmp( arch, "mips64" ) ) return True; + #else # error Unknown platform #endif // VGP_* diff --git a/tests/platform_test b/tests/platform_test index 400fd37341..43275c8b3f 100644 --- a/tests/platform_test +++ b/tests/platform_test @@ -13,7 +13,7 @@ all_platforms= all_platforms="$all_platforms x86-linux amd64-linux ppc32-linux ppc64-linux" all_platforms="$all_platforms arm-linux" -all_platforms="$all_platforms s390x-linux mips32-linux" +all_platforms="$all_platforms s390x-linux mips32-linux mips64-linux" all_platforms="$all_platforms x86-darwin amd64-darwin" if [ $# -ne 2 ] ; then