From: Julian Seward Date: Thu, 7 Jun 2012 09:13:21 +0000 (+0000) Subject: Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic, X-Git-Tag: svn/VALGRIND_3_8_0~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e344c57f6b038a76464e18d7f5b0e8d6e6b4448;p=thirdparty%2Fvalgrind.git Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic, mips-valgrind@rt-rk.com, Bug 270777. Valgrind: changes to existing files. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12616 --- diff --git a/Makefile.all.am b/Makefile.all.am index 439aacd755..bcca5ff60a 100644 --- a/Makefile.all.am +++ b/Makefile.all.am @@ -172,6 +172,10 @@ AM_FLAG_M3264_S390X_LINUX = @FLAG_M64@ AM_CFLAGS_S390X_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) -fomit-frame-pointer AM_CCASFLAGS_S390X_LINUX = @FLAG_M64@ -g -mzarch -march=z900 +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 + # Flags for the primary target. These must be used to build the # regtests and performance tests. In fact, these must be used to @@ -202,4 +206,5 @@ PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 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@ diff --git a/Makefile.tool.am b/Makefile.tool.am index 7924b1bb28..6f5a6eab53 100644 --- a/Makefile.tool.am +++ b/Makefile.tool.am @@ -59,6 +59,11 @@ TOOL_LDFLAGS_X86_DARWIN = \ TOOL_LDFLAGS_AMD64_DARWIN = \ $(TOOL_LDFLAGS_COMMON_DARWIN) -arch x86_64 +# MIPS Linux default start symbol is __start, not _start like on x86 or amd +TOOL_LDFLAGS_MIPS32_LINUX = \ + -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ + @FLAG_M32@ + # On Android we must ask for non-executable stack, not sure why. if VGCONF_PLATFORMS_INCLUDE_ARM_LINUX if VGCONF_PLATVARIANT_IS_ANDROID @@ -103,6 +108,8 @@ LIBREPLACEMALLOC_AMD64_DARWIN = \ LIBREPLACEMALLOC_S390X_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-s390x-linux.a +LIBREPLACEMALLOC_MIPS32_LINUX = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips32-linux.a LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \ -Wl,--whole-archive \ @@ -140,6 +147,11 @@ LIBREPLACEMALLOC_LDFLAGS_S390X_LINUX = \ $(LIBREPLACEMALLOC_S390X_LINUX) \ -Wl,--no-whole-archive +LIBREPLACEMALLOC_LDFLAGS_MIPS32_LINUX = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_MIPS32_LINUX) \ + -Wl,--no-whole-archive + #---------------------------------------------------------------------------- # General stuff #---------------------------------------------------------------------------- diff --git a/Makefile.vex.am b/Makefile.vex.am index 0071634d36..db162769f1 100644 --- a/Makefile.vex.am +++ b/Makefile.vex.am @@ -25,6 +25,7 @@ pkginclude_HEADERS = \ pub/libvex_guest_ppc64.h \ pub/libvex_guest_arm.h \ pub/libvex_guest_s390x.h \ + pub/libvex_guest_mips32.h \ pub/libvex_s390x_common.h \ pub/libvex_ir.h \ pub/libvex_trc_values.h @@ -41,6 +42,7 @@ noinst_HEADERS = \ priv/guest_ppc_defs.h \ priv/guest_arm_defs.h \ priv/guest_s390_defs.h \ + priv/guest_mips_defs.h \ priv/host_generic_regs.h \ priv/host_generic_simd64.h \ priv/host_generic_simd128.h \ @@ -49,7 +51,8 @@ noinst_HEADERS = \ priv/host_ppc_defs.h \ priv/host_arm_defs.h \ priv/host_s390_defs.h \ - priv/host_s390_disasm.h + priv/host_s390_disasm.h \ + priv/host_mips_defs.h BUILT_SOURCES = pub/libvex_guest_offsets.h CLEANFILES = pub/libvex_guest_offsets.h @@ -64,7 +67,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \ pub/libvex_guest_ppc32.h \ pub/libvex_guest_ppc64.h \ pub/libvex_guest_arm.h \ - pub/libvex_guest_s390x.h + pub/libvex_guest_s390x.h \ + pub/libvex_guest_mips32.h rm -f auxprogs/genoffsets.s $(CC) $(CFLAGS) \ $(LIBVEX_CFLAGS) \ @@ -106,6 +110,8 @@ LIBVEX_SOURCES_COMMON = \ priv/guest_arm_toIR.c \ priv/guest_s390_helpers.c \ priv/guest_s390_toIR.c \ + priv/guest_mips_helpers.c \ + priv/guest_mips_toIR.c \ priv/host_generic_regs.c \ priv/host_generic_simd64.c \ priv/host_generic_simd128.c \ @@ -120,7 +126,9 @@ LIBVEX_SOURCES_COMMON = \ priv/host_arm_isel.c \ priv/host_s390_defs.c \ priv/host_s390_isel.c \ - priv/host_s390_disasm.c + priv/host_s390_disasm.c \ + priv/host_mips_defs.c \ + priv/host_mips_isel.c LIBVEX_CFLAGS = \ -Wbad-function-cast \ diff --git a/cachegrind/Makefile.am b/cachegrind/Makefile.am index 0b6879c95b..f22fe17307 100644 --- a/cachegrind/Makefile.am +++ b/cachegrind/Makefile.am @@ -46,7 +46,8 @@ CACHEGRIND_SOURCES_COMMON = \ cg-ppc32.c \ cg-ppc64.c \ cg-arm.c \ - cg-s390x.c + cg-s390x.c \ + cg-mips32.c cachegrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \ $(CACHEGRIND_SOURCES_COMMON) diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c index 1db7fb592a..462977aee5 100644 --- a/cachegrind/cg_branchpred.c +++ b/cachegrind/cg_branchpred.c @@ -44,7 +44,8 @@ /* 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) +#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm) \ + || defined(VGA_mips32) # define N_IADDR_LO_ZERO_BITS 2 #elif defined(VGA_x86) || defined(VGA_amd64) # define N_IADDR_LO_ZERO_BITS 0 diff --git a/cachegrind/tests/filter_stderr b/cachegrind/tests/filter_stderr index d6800cd651..2d38fb31d1 100755 --- a/cachegrind/tests/filter_stderr +++ b/cachegrind/tests/filter_stderr @@ -20,4 +20,5 @@ sed "/warning: L3 cache found, using its data for the LL simulation./d" | sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" | sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" | sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d" | +sed "/Warning: Cannot auto-detect cache config on MIPS.., using one or more defaults/d" | sed "/warning: pretending that LL cache has associativity .*$/d" diff --git a/callgrind/Makefile.am b/callgrind/Makefile.am index 7cb6807fc3..ae4ff4fc69 100644 --- a/callgrind/Makefile.am +++ b/callgrind/Makefile.am @@ -50,7 +50,8 @@ CALLGRIND_SOURCES_COMMON = \ ../cachegrind/cg-ppc32.c \ ../cachegrind/cg-ppc64.c \ ../cachegrind/cg-arm.c \ - ../cachegrind/cg-s390x.c + ../cachegrind/cg-s390x.c \ + ../cachegrind/cg-mips32.c CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind diff --git a/callgrind/tests/filter_stderr b/callgrind/tests/filter_stderr index 9664d518c5..9acedd3c24 100755 --- a/callgrind/tests/filter_stderr +++ b/callgrind/tests/filter_stderr @@ -29,4 +29,5 @@ sed "/warning: L3 cache found, using its data for the LL simulation./d" | sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" | sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" | sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d" | +sed "/Warning: Cannot auto-detect cache config on MIPS.., using one or more defaults/d" | sed "/warning: pretending that LL cache has associativity .*$/d" diff --git a/configure.in b/configure.in index ed6be2a82e..954df7c965 100644 --- a/configure.in +++ b/configure.in @@ -189,6 +189,21 @@ case "${host_cpu}" in ARCH_MAX="arm" ;; + mips) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; + + mipsel) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; + + mipsisa32r2) + AC_MSG_RESULT([ok (${host_cpu})]) + ARCH_MAX="mips32" + ;; + *) AC_MSG_RESULT([no (${host_cpu})]) AC_MSG_ERROR([Unsupported host architecture. Sorry]) @@ -535,6 +550,17 @@ case "$ARCH_MAX-$VGCONF_OS" in valt_load_address_sec_inner="0xUNSET" AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) ;; + mips32-linux) + VGCONF_ARCH_PRI="mips32" + VGCONF_PLATFORM_PRI_CAPS="MIPS32_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})]) + AC_MSG_RESULT([ok (${host_cpu}-${host_os})]) + ;; *) VGCONF_ARCH_PRI="unknown" VGCONF_ARCH_SEC="unknown" @@ -570,6 +596,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM, test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX ) 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 ) # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these # become defined. @@ -588,6 +616,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM_LINUX, AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX, test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_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_X86_DARWIN, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \ @@ -605,7 +635,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX, -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ - -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX) + -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX) AM_CONDITIONAL(VGCONF_OS_IS_DARWIN, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_DARWIN) @@ -653,6 +684,62 @@ else fi +#---------------------------------------------------------------------------- +# Define MIPS_PAGE_SHIFT (--with-pagesize) +#---------------------------------------------------------------------------- +AC_ARG_WITH(pagesize, + [ --with-pagesize= override detected page size (4, 16 or 64)], + [psize=$withval], + [psize=0] +) + +if test "$psize" = "0"; then + psizer=`getconf PAGESIZE` + let "psize=${psizer}/1024" +fi + +if test "$psize" = "4"; then + AC_DEFINE([MIPS_PAGE_SHIFT], 12, [configured page size 4k]) +elif test "$psize" = "16"; then + AC_DEFINE([MIPS_PAGE_SHIFT], 14, [configured page size 16k]) +elif test "$psize" = "64"; then + AC_DEFINE([MIPS_PAGE_SHIFT], 16, [configured page size 64k]) +else + AC_DEFINE([MIPS_PAGE_SHIFT], 12, [configured default page size 4k]) +fi +AC_MSG_RESULT([checking for Pagesize... ${psize}k]) + +#---------------------------------------------------------------------------- +# Define shm_align for MIPS (--shared-memory-alignment) +#---------------------------------------------------------------------------- +AC_ARG_WITH(alignment, + [ --with-alignment= shared memory alignment for MIPS], + [align=$withval], + [align=-1] +) + +mod=`expr $align % 1024` + +let "psz=psize*1024*2" + +if test "$align" = "-1"; then + AC_DEFINE([SHM_ALIGNMENT], 2*(1UL << MIPS_PAGE_SHIFT), + [configured memory alignment 2*PAGE_SIZE]) + AC_MSG_RESULT([checking for shared memory alignment... 2*PAGE_SIZE]) +elif test "$mod" = "0"; then + if test $align -lt $psz; + then + AC_MSG_ERROR([Alignment must be >= PAGE_SIZE]) + else + AC_DEFINE_UNQUOTED([SHM_ALIGNMENT], ${align}, + [configured memory alignment 2*PAGE_SIZE]) + AC_MSG_RESULT([checking for shared memory alignment... ${align}]) + fi +else + AC_MSG_ERROR([Alignment % 1024 must be zero]) +fi + + #---------------------------------------------------------------------------- # Extra fine-tuning of installation directories #---------------------------------------------------------------------------- @@ -1799,7 +1886,8 @@ MPI_CC="mpicc" 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 ; then + -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX ; then mflag_primary=$FLAG_M32 elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ @@ -2244,6 +2332,7 @@ AC_CONFIG_FILES([ none/tests/x86/Makefile none/tests/arm/Makefile none/tests/s390x/Makefile + none/tests/mips32/Makefile none/tests/linux/Makefile none/tests/darwin/Makefile none/tests/x86-linux/Makefile diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index efb4de34de..68b8ed2937 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -301,6 +301,7 @@ COREGRIND_SOURCES_COMMON = \ m_dispatch/dispatch-ppc64-linux.S \ m_dispatch/dispatch-arm-linux.S \ m_dispatch/dispatch-s390x-linux.S \ + m_dispatch/dispatch-mips32-linux.S \ m_dispatch/dispatch-x86-darwin.S \ m_dispatch/dispatch-amd64-darwin.S \ m_gdbserver/m_gdbserver.c \ @@ -318,6 +319,7 @@ COREGRIND_SOURCES_COMMON = \ m_gdbserver/valgrind-low-ppc32.c \ m_gdbserver/valgrind-low-ppc64.c \ m_gdbserver/valgrind-low-s390x.c \ + m_gdbserver/valgrind-low-mips32.c \ m_gdbserver/version.c \ m_initimg/initimg-linux.c \ m_initimg/initimg-darwin.c \ @@ -337,6 +339,7 @@ COREGRIND_SOURCES_COMMON = \ m_sigframe/sigframe-ppc64-linux.c \ m_sigframe/sigframe-arm-linux.c \ m_sigframe/sigframe-s390x-linux.c \ + m_sigframe/sigframe-mips32-linux.c \ m_sigframe/sigframe-x86-darwin.c \ m_sigframe/sigframe-amd64-darwin.c \ m_syswrap/syscall-x86-linux.S \ @@ -345,6 +348,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syscall-ppc64-linux.S \ m_syswrap/syscall-arm-linux.S \ m_syswrap/syscall-s390x-linux.S \ + m_syswrap/syscall-mips32-linux.S \ m_syswrap/syscall-x86-darwin.S \ m_syswrap/syscall-amd64-darwin.S \ m_syswrap/syswrap-main.c \ @@ -358,6 +362,7 @@ COREGRIND_SOURCES_COMMON = \ m_syswrap/syswrap-ppc64-linux.c \ m_syswrap/syswrap-arm-linux.c \ m_syswrap/syswrap-s390x-linux.c \ + m_syswrap/syswrap-mips32-linux.c \ m_syswrap/syswrap-x86-darwin.c \ m_syswrap/syswrap-amd64-darwin.c \ m_ume/elf.c \ @@ -532,7 +537,18 @@ GDBSERVER_XML_FILES = \ m_gdbserver/s390x-generic.xml \ m_gdbserver/s390x-linux64-valgrind-s1.xml \ m_gdbserver/s390x-linux64-valgrind-s2.xml \ - m_gdbserver/s390x-linux64.xml + m_gdbserver/s390x-linux64.xml \ + m_gdbserver/mips-cp0-valgrind-s1.xml \ + m_gdbserver/mips-cp0-valgrind-s2.xml \ + m_gdbserver/mips-cp0.xml \ + m_gdbserver/mips-cpu-valgrind-s1.xml \ + m_gdbserver/mips-cpu-valgrind-s2.xml \ + m_gdbserver/mips-cpu.xml \ + m_gdbserver/mips-linux.xml \ + 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 # 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 6a200c3e67..a9ad1e39cf 100644 --- a/coregrind/launcher-linux.c +++ b/coregrind/launcher-linux.c @@ -179,6 +179,12 @@ static const char *select_platform(const char *clientname) ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { platform = "arm-linux"; } + else + if (ehdr->e_machine == EM_MIPS && + (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || + ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { + platform = "mips32-linux"; + } } else if (header[EI_DATA] == ELFDATA2MSB) { if (ehdr->e_machine == EM_PPC && @@ -186,6 +192,12 @@ static const char *select_platform(const char *clientname) ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { platform = "ppc32-linux"; } + else + if (ehdr->e_machine == EM_MIPS && + (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || + ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { + platform = "mips32-linux"; + } } } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) { @@ -284,7 +296,8 @@ int main(int argc, char** argv, char** envp) (0==strcmp(VG_PLATFORM,"ppc32-linux")) || (0==strcmp(VG_PLATFORM,"ppc64-linux")) || (0==strcmp(VG_PLATFORM,"arm-linux")) || - (0==strcmp(VG_PLATFORM,"s390x-linux"))) + (0==strcmp(VG_PLATFORM,"s390x-linux")) || + (0==strcmp(VG_PLATFORM,"mips32-linux"))) default_platform = VG_PLATFORM; else barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM); diff --git a/coregrind/link_tool_exe_linux.in b/coregrind/link_tool_exe_linux.in index 6de2562f45..a47747be84 100644 --- a/coregrind/link_tool_exe_linux.in +++ b/coregrind/link_tool_exe_linux.in @@ -68,7 +68,18 @@ my $cc = $ARGV[1]; # so, build up the complete command here: # 'cc' -static -Ttext='ala' 'restargs' -my $cmd="$cc -static -Wl,-Ttext=$ala"; +# For mips we need to use "--section-start=.reginfo=$ala" because +# "--section-start=.reginfo=$ala" will put all the sections to the +# specificed address ($ala) +my $x=`$cc -v 2>&1 | grep Target | sed 's/Target: //g'`; +my $arch=substr($x, 0, index($x, '-')); +my $cmd; + +if (($arch eq 'mips') || ($arch eq 'mipsel')) { + $cmd = "$cc -static -Wl,--section-start=.reginfo=$ala"; +} else { + $cmd = "$cc -static -Wl,-Ttext=$ala"; +} # Add the rest of the parameters foreach my $n (2 .. $#ARGV) { diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index 7f7717c5ec..6a65610cbe 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -159,7 +159,7 @@ 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_s390x_linux) || defined(VGP_mips32_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 9980501b52..0695a66b1a 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) + #if defined(VGA_arm) || defined(VGA_mips32) aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); #else aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE); diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c index 745bd7ee69..ddfe2ba713 100644 --- a/coregrind/m_coredump/coredump-elf.c +++ b/coregrind/m_coredump/coredump-elf.c @@ -375,6 +375,15 @@ static void fill_prstatus(const ThreadState *tst, DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); # undef DO regs->orig_gpr2 = arch->vex.guest_r2; +#elif defined(VGP_mips32_linux) +# define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n + DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); + 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; #else # error Unknown ELF platform #endif @@ -455,6 +464,13 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) 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); # undef DO +#elif defined(VGP_mips32_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 bb559f4103..c08b5a78ec 100644 --- a/coregrind/m_debugger.c +++ b/coregrind/m_debugger.c @@ -307,6 +307,43 @@ static Int ptrace_setregs(Int pid, VexGuestArchState* vex) return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid, &pa, NULL); +#elif defined(VGP_mips32_linux) + struct vki_user_regs_struct regs; + VG_(memset)(®s, 0, sizeof(regs)); + regs.MIPS_r0 = vex->guest_r0; + regs.MIPS_r1 = vex->guest_r1; + regs.MIPS_r2 = vex->guest_r2; + regs.MIPS_r3 = vex->guest_r3; + regs.MIPS_r4 = vex->guest_r4; + regs.MIPS_r5 = vex->guest_r5; + regs.MIPS_r6 = vex->guest_r6; + regs.MIPS_r7 = vex->guest_r7; + regs.MIPS_r8 = vex->guest_r8; + regs.MIPS_r9 = vex->guest_r9; + regs.MIPS_r10 = vex->guest_r10; + regs.MIPS_r11 = vex->guest_r11; + regs.MIPS_r12 = vex->guest_r12; + regs.MIPS_r13 = vex->guest_r13; + regs.MIPS_r14 = vex->guest_r14; + regs.MIPS_r15 = vex->guest_r15; + regs.MIPS_r16 = vex->guest_r16; + regs.MIPS_r17 = vex->guest_r17; + regs.MIPS_r18 = vex->guest_r18; + regs.MIPS_r19 = vex->guest_r19; + regs.MIPS_r20 = vex->guest_r20; + regs.MIPS_r21 = vex->guest_r21; + regs.MIPS_r22 = vex->guest_r22; + regs.MIPS_r23 = vex->guest_r23; + regs.MIPS_r24 = vex->guest_r24; + regs.MIPS_r25 = vex->guest_r25; + regs.MIPS_r26 = vex->guest_r26; + regs.MIPS_r27 = vex->guest_r27; + regs.MIPS_r28 = vex->guest_r28; + regs.MIPS_r29 = vex->guest_r29; + regs.MIPS_r30 = vex->guest_r30; + regs.MIPS_r31 = vex->guest_r31; + return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, ®s); + #else # error Unknown arch #endif diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c index 03af598b1f..5999f2eb52 100644 --- a/coregrind/m_debuginfo/d3basics.c +++ b/coregrind/m_debuginfo/d3basics.c @@ -410,6 +410,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs ) # elif defined(VGP_s390x_linux) if (regno == 15) { *a = regs->sp; return True; } if (regno == 11) { *a = regs->fp; return True; } +# elif defined(VGP_mips32_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 fa08d8ed63..99389c296d 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -792,7 +792,7 @@ 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) +# if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) is_rx_map = seg->hasR && seg->hasX; is_rw_map = seg->hasR && seg->hasW; # elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) @@ -1516,6 +1516,22 @@ Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf ) /*offsetP*/NULL ); } +/* mips-linux only: find the offset of current address. This is needed for + stack unwinding for MIPS. +*/ +Bool VG_(get_inst_offset_in_function)( Addr a, + /*OUT*/PtrdiffT* offset ) +{ + Char fnname[64]; + return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False, + /*below-main-renaming*/False, + a, fnname, 64, + /*match_anywhere_in_sym*/True, + /*show offset?*/True, + /*data syms only please*/True, + offset ); +} + Vg_FnNameKind VG_(get_fnname_kind) ( Char* name ) { if (VG_STREQ("main", name)) { @@ -2040,6 +2056,11 @@ 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) + case Creg_IA_IP: return eec->uregs->pc; + case Creg_IA_SP: return eec->uregs->sp; + case Creg_IA_BP: return eec->uregs->fp; + case Creg_MIPS_RA: return eec->uregs->ra; # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else # error "Unsupported arch" @@ -2268,6 +2289,16 @@ static Addr compute_cfa ( D3UnwindRegs* uregs, case CFIC_IA_BPREL: cfa = cfsi->cfa_off + uregs->fp; break; +# elif defined(VGA_mips32) + case CFIC_IA_SPREL: + cfa = cfsi->cfa_off + uregs->sp; + break; + case CFIR_SAME: + cfa = uregs->fp; + break; + case CFIC_IA_BPREL: + cfa = cfsi->cfa_off + uregs->fp; + break; # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else # error "Unsupported arch" @@ -2362,6 +2393,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, ipHere = uregsHere->r15; # elif defined(VGA_s390x) ipHere = uregsHere->ia; +# elif defined(VGA_mips32) + ipHere = uregsHere->pc; # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else # error "Unknown arch" @@ -2438,6 +2471,10 @@ 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) + 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); # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else # error "Unknown arch" diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index 53ca0d2c12..193b154bc2 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -257,6 +257,21 @@ typedef Int fp_off; } DiCfSI; +#elif defined(VGA_mips32) +typedef + struct { + Addr base; + UInt len; + UChar cfa_how; /* a CFIC_ value */ + UChar ra_how; /* a CFIR_ value */ + UChar sp_how; /* a CFIR_ value */ + UChar fp_how; /* a CFIR_ value */ + Int cfa_off; + Int ra_off; + Int sp_off; + Int fp_off; + } + DiCfSI; #else # error "Unknown arch" #endif @@ -288,7 +303,8 @@ typedef Creg_ARM_R12, Creg_ARM_R15, Creg_ARM_R14, - Creg_S390_R14 + Creg_S390_R14, + Creg_MIPS_RA } CfiReg; diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 36a6698503..9329fa2d9a 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -1843,6 +1843,10 @@ void ML_(read_debuginfo_dwarf1) ( # define FP_REG 11 // sometimes s390 has a frame pointer in r11 # define SP_REG 15 // stack is always r15 # define RA_REG_DEFAULT 14 // the return address is in r14 +#elif defined(VGP_mips32_linux) +# define FP_REG 30 +# define SP_REG 29 +# define RA_REG_DEFAULT 31 #else # error "Unknown platform" #endif @@ -1851,7 +1855,8 @@ void ML_(read_debuginfo_dwarf1) ( arm-linux (320) seems ludicrously high, but the ARM IHI 0040A page 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) +#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ + || defined(VGP_mips32_linux) # define N_CFI_REGS 72 #elif defined(VGP_arm_linux) # define N_CFI_REGS 320 @@ -2155,7 +2160,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, else 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) +# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ + || defined(VGA_mips32) si->cfa_how = CFIC_IA_SPREL; # elif defined(VGA_arm) si->cfa_how = CFIC_ARM_R13REL; @@ -2166,7 +2172,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, else 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) +# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \ + || defined(VGA_mips32) si->cfa_how = CFIC_IA_BPREL; # elif defined(VGA_arm) si->cfa_how = CFIC_ARM_R12REL; @@ -2367,6 +2374,50 @@ static Bool summarise_context( /*OUT*/DiCfSI* si, return True; +# elif defined(VGA_mips32) + + /* --- entire tail of this fn specialised for mips --- */ + + SUMMARISE_HOW(si->ra_how, si->ra_off, + ctxs->reg[ctx->ra_reg] ); + SUMMARISE_HOW(si->fp_how, si->fp_off, + ctxs->reg[FP_REG] ); + SUMMARISE_HOW(si->sp_how, si->sp_off, + ctxs->reg[SP_REG] ); + si->sp_how = CFIR_CFAREL; + si->sp_off = 0; + + if (si->fp_how == CFIR_UNKNOWN) + si->fp_how = CFIR_SAME; + if (si->cfa_how == CFIR_UNKNOWN) { + si->cfa_how = CFIC_IA_SPREL; + si->cfa_off = 160; + } + if (si->ra_how == CFIR_UNKNOWN) { + if (!debuginfo->cfsi_exprs) + debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc), + "di.ccCt.2a", + ML_(dinfo_free), + sizeof(CfiExpr) ); + si->ra_how = CFIR_EXPR; + si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs, + Creg_MIPS_RA); + } + + if (si->ra_how == CFIR_SAME) + { why = 3; goto failed; } + + if (loc_start >= ctx->loc) + { why = 4; goto failed; } + if (ctx->loc - loc_start > 10000000 /* let's say */) + { why = 5; goto failed; } + + si->base = loc_start + ctx->initloc; + si->len = (UInt)(ctx->loc - loc_start); + + return True; + + # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else @@ -2449,6 +2500,13 @@ 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) + if (dwreg == SP_REG) + return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP ); + if (dwreg == FP_REG) + return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP ); + if (dwreg == srcuc->ra_reg) + return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); # elif defined(VGA_ppc32) || defined(VGA_ppc64) # else # error "Unknown arch" diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index 99b213c88d..1654097fdd 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -2307,8 +2307,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, case DW_ATE_unsigned: case DW_ATE_unsigned_char: case DW_ATE_UTF: /* since DWARF4, e.g. char16_t from C++ */ case DW_ATE_boolean:/* FIXME - is this correct? */ + case DW_ATE_unsigned_fixed: typeE.Te.TyBase.enc = 'U'; break; case DW_ATE_signed: case DW_ATE_signed_char: + case DW_ATE_signed_fixed: typeE.Te.TyBase.enc = 'S'; break; case DW_ATE_float: typeE.Te.TyBase.enc = 'F'; break; diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index 3a701224c3..40f5eea6ff 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -1955,7 +1955,8 @@ 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_arm_linux) || defined (VGP_s390x_linux) \ + || defined(VGP_mips32_linux) /* Accept .plt where mapped as rx (code) */ if (0 == VG_(strcmp)(name, ".plt")) { if (inrx && size > 0 && !di->plt_present) { diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index b90b2e721a..a5fe07f007 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) +# elif defined(VGA_s390x) || defined(VGA_mips32) VG_(printf)(" SP="); SHOW_HOW(si->sp_how, si->sp_off); VG_(printf)(" FP="); @@ -629,6 +629,7 @@ static void ppCfiReg ( CfiReg reg ) case Creg_ARM_R12: VG_(printf)("R12"); break; case Creg_ARM_R15: VG_(printf)("R15"); break; case Creg_ARM_R14: VG_(printf)("R14"); break; + case Creg_MIPS_RA: VG_(printf)("RA"); break; default: vg_assert(0); } } diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c index 44f7376f7a..8e1c032742 100644 --- a/coregrind/m_debuglog.c +++ b/coregrind/m_debuglog.c @@ -388,6 +388,43 @@ static UInt local_sys_getpid ( void ) return (UInt)(__res); } +#elif defined(VGP_mips32_linux) +static UInt local_sys_write_stderr ( HChar* buf, Int n ) +{ + volatile Int block[2]; + block[0] = (Int)buf; + block[1] = n; + __asm__ volatile ( + "li $4, 2\n\t" /* stderr */ + "lw $5, 0(%0)\n\t" /* buf */ + "lw $6, 4(%0)\n\t" /* n */ + "move $7, $0\n\t" + "li $2, %1\n\t" /* set v0 = __NR_write */ + "syscall\n\t" /* write() */ + "nop\n\t" + : + : "r" (block), "n" (__NR_write) + : "2", "4", "5", "6", "7" + ); + if (block[0] < 0) + block[0] = -1; + return (UInt)block[0]; +} + +static UInt local_sys_getpid ( void ) +{ + UInt __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 __res; +} + #else # error Unknown platform diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c index 905efb929f..6117fcee62 100644 --- a/coregrind/m_gdbserver/target.c +++ b/coregrind/m_gdbserver/target.c @@ -618,6 +618,8 @@ void valgrind_initialize_target(void) ppc64_init_architecture(&the_low_target); #elif defined(VGA_s390x) s390x_init_architecture(&the_low_target); +#elif defined(VGA_mips32) + s390x_init_architecture(&the_low_target); #else architecture missing in target.c valgrind_initialize_target #endif diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h index 29dafcdd82..0348895d63 100644 --- a/coregrind/m_gdbserver/valgrind_low.h +++ b/coregrind/m_gdbserver/valgrind_low.h @@ -73,5 +73,6 @@ extern void arm_init_architecture (struct valgrind_target_ops *target); extern void ppc32_init_architecture (struct valgrind_target_ops *target); extern void ppc64_init_architecture (struct valgrind_target_ops *target); extern void s390x_init_architecture (struct valgrind_target_ops *target); +extern void mips32_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 b752f01aad..8acc7b0f51 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -1081,6 +1081,20 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8); return; +# elif defined(VGP_mips32_linux) + vg_assert(0 == sizeof(VexGuestMIPS32State) % 16); + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestMIPS32_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS32State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS32State)); + + 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 1f5b95cc61..a8e7e11a7c 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -152,6 +152,31 @@ (srP)->misc.S390X.r_fp = fp; \ (srP)->misc.S390X.r_lr = lr; \ } +#elif defined(VGP_mips32_linux) +# define GET_STARTREGS(srP) \ + { UInt 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.MIPS32.r30 = (ULong)fp; \ + (srP)->misc.MIPS32.r31 = (ULong)ra; \ + (srP)->misc.MIPS32.r28 = (ULong)gp; \ + } #else # error Unknown platform #endif diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 4bc07cbe38..e8368b3225 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -194,7 +194,17 @@ Int VG_(write) ( Int fd, const void* buf, Int count) Int VG_(pipe) ( Int fd[2] ) { -# if defined(VGO_linux) +# if defined(VGP_mips32_linux) + /* __NR_pipe has a strange return convention on mips32-linux. */ + SysRes res = VG_(do_syscall0)(__NR_pipe); + if (!sr_isError(res)) { + fd[0] = (Int)sr_Res(res); + fd[1] = (Int)sr_ResEx(res); + return 0; + } else { + return -1; + } +# elif defined(VGO_linux) SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); return sr_isError(res) ? -1 : 0; # elif defined(VGO_darwin) @@ -596,6 +606,16 @@ 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 + 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 + 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) res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); @@ -837,7 +857,8 @@ Int VG_(socket) ( Int domain, Int type, Int protocol ) res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (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_mips32_linux) SysRes res; res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); return sr_isError(res) ? -1 : sr_Res(res); @@ -875,7 +896,8 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (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_mips32_linux) SysRes res; res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); return sr_isError(res) ? -1 : sr_Res(res); @@ -913,7 +935,8 @@ Int VG_(write_socket)( Int sd, void *msg, Int count ) res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (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_mips32_linux) SysRes res; res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, VKI_MSG_NOSIGNAL, 0,0); @@ -932,7 +955,8 @@ Int VG_(write_socket)( Int sd, void *msg, Int count ) Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) { # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ - || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) + || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \ + || defined(VGP_mips32_linux) SysRes res; UWord args[3]; args[0] = sd; @@ -961,7 +985,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) { # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ - || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) + || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \ + || defined(VGP_mips32_linux) SysRes res; UWord args[3]; args[0] = sd; @@ -1002,7 +1027,8 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (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_mips32_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 21fee60b89..6f0c71b387 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -549,7 +549,8 @@ Int VG_(getgroups)( Int size, UInt* list ) # elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \ || defined(VGP_arm_linux) \ - || defined(VGO_darwin) || defined(VGP_s390x_linux) + || defined(VGO_darwin) || defined(VGP_s390x_linux) \ + || defined(VGP_mips32_linux) SysRes sres; sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list); if (sr_isError(sres)) @@ -764,6 +765,11 @@ void VG_(invalidate_icache) ( void *ptr, SizeT nbytes ) Addr endaddr = startaddr + nbytes; VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr); +# elif defined(VGA_mips32) + SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr, + (UWord) nbytes, (UWord) 3); + vg_assert( sres._isError == 0 ); + # else # error "Unknown ARCH" # endif diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 9980640ddf..047c508555 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -103,6 +103,15 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs, = VG_(threads)[tid].arch.vex.guest_r11; regs->misc.S390X.r_lr = VG_(threads)[tid].arch.vex.guest_r14; +# elif defined(VGA_mips32) + regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC; + regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29; + regs->misc.MIPS32.r30 + = VG_(threads)[tid].arch.vex.guest_r30; + regs->misc.MIPS32.r31 + = VG_(threads)[tid].arch.vex.guest_r31; + regs->misc.MIPS32.r28 + = VG_(threads)[tid].arch.vex.guest_r28; # else # error "Unknown arch" # endif @@ -132,6 +141,9 @@ 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) + VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res; # else # error "Unknown plat" # endif @@ -282,6 +294,39 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, HChar*, Addr)) (*f)(tid, "r13", vex->guest_r13); (*f)(tid, "r14", vex->guest_r14); (*f)(tid, "r15", vex->guest_r15); +#elif defined(VGA_mips32) + (*f)(tid, "r0" , vex->guest_r0 ); + (*f)(tid, "r1" , vex->guest_r1 ); + (*f)(tid, "r2" , vex->guest_r2 ); + (*f)(tid, "r3" , vex->guest_r3 ); + (*f)(tid, "r4" , vex->guest_r4 ); + (*f)(tid, "r5" , vex->guest_r5 ); + (*f)(tid, "r6" , vex->guest_r6 ); + (*f)(tid, "r7" , vex->guest_r7 ); + (*f)(tid, "r8" , vex->guest_r8 ); + (*f)(tid, "r9" , vex->guest_r9 ); + (*f)(tid, "r10", vex->guest_r10); + (*f)(tid, "r11", vex->guest_r11); + (*f)(tid, "r12", vex->guest_r12); + (*f)(tid, "r13", vex->guest_r13); + (*f)(tid, "r14", vex->guest_r14); + (*f)(tid, "r15", vex->guest_r15); + (*f)(tid, "r16", vex->guest_r16); + (*f)(tid, "r17", vex->guest_r17); + (*f)(tid, "r18", vex->guest_r18); + (*f)(tid, "r19", vex->guest_r19); + (*f)(tid, "r20", vex->guest_r20); + (*f)(tid, "r21", vex->guest_r21); + (*f)(tid, "r22", vex->guest_r22); + (*f)(tid, "r23", vex->guest_r23); + (*f)(tid, "r24", vex->guest_r24); + (*f)(tid, "r25", vex->guest_r25); + (*f)(tid, "r26", vex->guest_r26); + (*f)(tid, "r27", vex->guest_r27); + (*f)(tid, "r28", vex->guest_r28); + (*f)(tid, "r29", vex->guest_r29); + (*f)(tid, "r30", vex->guest_r30); + (*f)(tid, "r31", vex->guest_r31); #else # error Unknown arch #endif @@ -389,7 +434,7 @@ Int VG_(machine_arm_archlevel) = 4; /* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL testing, so we need a VG_MINIMAL_JMP_BUF. */ #if defined(VGA_ppc32) || defined(VGA_ppc64) \ - || defined(VGA_arm) || defined(VGA_s390x) + || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32) #include "pub_tool_libcsetjmp.h" static VG_MINIMAL_JMP_BUF(env_unsup_insn); static void handler_unsup_insn ( Int x ) { @@ -568,6 +613,64 @@ static UInt VG_(get_machine_model)(void) #endif /* VGA_s390x */ +#ifdef VGA_mips32 + +/* 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"; + Int n, fh; + SysRes fd; + SizeT num_bytes, file_buf_size; + HChar *file_buf; + + /* Slurp contents of /proc/cpuinfo into FILE_BUF */ + fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR ); + if ( sr_isError(fd) ) return -1; + + fh = sr_Res(fd); + + /* Determine the size of /proc/cpuinfo. + Work around broken-ness in /proc file system implementation. + fstat returns a zero size for /proc/cpuinfo although it is + claimed to be a regular file. */ + num_bytes = 0; + file_buf_size = 1000; + file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1); + while (42) { + n = VG_(read)(fh, file_buf, file_buf_size); + if (n < 0) break; + + num_bytes += n; + if (n < file_buf_size) break; /* reached EOF */ + } + + if (n < 0) num_bytes = 0; /* read error; ignore contents */ + + if (num_bytes > file_buf_size) { + VG_(free)( file_buf ); + VG_(lseek)( fh, 0, VKI_SEEK_SET ); + file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 ); + n = VG_(read)( fh, file_buf, num_bytes ); + if (n < 0) num_bytes = 0; + } + + file_buf[num_bytes] = '\0'; + VG_(close)(fh); + + /* Parse file */ + if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL) + return VEX_PRID_COMP_BROADCOM; + if (VG_(strstr) (file_buf, search_MIPS_str) != NULL) + return VEX_PRID_COMP_MIPS; + + /* Did not find string in the proc file. */ + return -1; +} + +#endif + /* Determine what insn set and insn set variant the host has, and record it. To be called once at system startup. Returns False if this a CPU incapable of running Valgrind. */ @@ -1249,6 +1352,17 @@ Bool VG_(machine_get_hwcaps)( void ) return True; } +#elif defined(VGA_mips32) + { + va = VexArchMIPS32; + UInt model = VG_(get_machine_model)(); + if (model== -1) + return False; + + vai.hwcaps = model; + return True; + } + #else # error "Unknown arch" #endif @@ -1370,6 +1484,11 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void ) assume we always do. */ return 16; +# elif defined(VGA_mips32) + /* The guest state implies 4, but that can't really be true, can + it? */ + return 8; + # else # error "Unknown arch" # endif @@ -1383,7 +1502,7 @@ 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_s390x_linux) || defined(VGP_mips32_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 71065ce399..7a35112eca 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -1539,8 +1539,10 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) // p: logging, plausible-stack //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Starting the address space manager\n"); - vg_assert(VKI_PAGE_SIZE == 4096 || VKI_PAGE_SIZE == 65536); - vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536); + vg_assert(VKI_PAGE_SIZE == 4096 || VKI_PAGE_SIZE == 65536 + || VKI_PAGE_SIZE == 16384); + vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536 + || VKI_MAX_PAGE_SIZE == 16384); vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE); vg_assert(VKI_PAGE_SIZE == (1 << VKI_PAGE_SHIFT)); vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT)); @@ -1894,6 +1896,8 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) iters = 5; # elif defined(VGP_s390x_linux) iters = 10; +# elif defined(VGP_mips32_linux) + iters = 10; # elif defined(VGO_darwin) iters = 3; # else @@ -2473,6 +2477,10 @@ static void final_tidyup(ThreadId tid) # if defined(VGP_ppc64_linux) VG_(threads)[tid].arch.vex.guest_GPR2 = r2; # endif + /* mips-linux note: we need to set t9 */ +# if defined(VGP_mips32_linux) + VG_(threads)[tid].arch.vex.guest_r25 = __libc_freeres_wrapper; +# endif /* Block all blockable signals by copying the real block state into the thread's block state*/ @@ -2761,6 +2769,50 @@ asm("\n" "\t.word "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n" "\t.word "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n" ); +#elif defined(VGP_mips32_linux) +asm("\n" + "\t.type _gp_disp,@object\n" + ".text\n" + "\t.globl __start\n" + "\t.type __start,@function\n" + "__start:\n" + + "\tbal 1f\n" + "\tnop\n" + + "1:\n" + + "\tlui $28, %hi(_gp_disp)\n" + "\taddiu $28, $28, %lo(_gp_disp)\n" + "\taddu $28, $28, $31\n" + /* t1/$9 <- Addr(interim_stack) */ + "\tlui $9, %hi(vgPlain_interim_stack)\n" + /* t1/$9 <- Addr(interim_stack) */ + "\taddiu $9, %lo(vgPlain_interim_stack)\n" + + + "\tli $10, "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n" + "\tli $11, "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n" + + "\taddu $9, $9, $10\n" + "\taddu $9, $9, $11\n" + "\tli $12, 0xFFFFFFF0\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 $25, %hi(_start_in_C_linux)\n" + "\taddiu $25, %lo(_start_in_C_linux)\n" + + "\tbal _start_in_C_linux\n" + "\tbreak 0x7\n" + ".previous\n" +); #else # error "Unknown linux platform" #endif diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index fd24c1a025..50e00ac781 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -1358,6 +1358,17 @@ void VG_(redir_initialise) ( void ) # elif defined(VGP_s390x_linux) /* nothing so far */ +# elif defined(VGP_mips32_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_(mips32_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 4c7ef60fcd..93fa109356 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -780,6 +780,10 @@ static void do_pre_run_checks ( ThreadState* tst ) # if defined(VGA_s390x) /* no special requirements */ # endif + +# if defined(VGA_mips32) + /* no special requirements */ +# endif } // NO_VGDB_POLL value ensures vgdb is not polled, while @@ -1557,6 +1561,9 @@ 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) +# define VG_CLREQ_ARGS guest_r12 +# define VG_CLREQ_RET guest_r11 #else # error Unknown arch #endif diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 81a53b1f65..9ef6b852a5 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -516,6 +516,25 @@ typedef struct SigQueue { (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14]; \ } +#elif defined(VGP_mips32_linux) +# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)(((uc)->uc_mcontext.sc_pc))) +# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)((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_mips32_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.MIPS32.r30 = (uc)->uc_mcontext.sc_regs[30]; \ + (srP)->misc.MIPS32.r31 = (uc)->uc_mcontext.sc_regs[31]; \ + (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \ + } + #else # error Unknown platform @@ -849,6 +868,14 @@ extern void my_sigreturn(void); " svc " #name "\n" \ ".previous\n" +#elif defined(VGP_mips32_linux) +# define _MY_SIGRETURN(name) \ + ".text\n" \ + "my_sigreturn:\n" \ + " li $2, " #name "\n" /* apparently $2 is v0 */ \ + " syscall\n" \ + ".previous\n" + #else # error Unknown platform #endif @@ -891,7 +918,8 @@ static void handle_SCSS_change ( Bool force_update ) ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; # if !defined(VGP_ppc32_linux) && \ - !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) + !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_mips32_linux) ksa.sa_restorer = my_sigreturn; # endif /* Re above ifdef (also the assertion below), PaulM says: @@ -924,7 +952,8 @@ static void handle_SCSS_change ( Bool force_update ) vg_assert(ksa_old.sa_flags == skss_old.skss_per_sig[sig].skss_flags); # if !defined(VGP_ppc32_linux) && \ - !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) + !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_mips32_linux) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif @@ -1855,6 +1884,27 @@ void VG_(synth_sigtrap)(ThreadId tid) info.si_signo = VKI_SIGTRAP; info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */ +# if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) + /* This is for teq on mips. Teq on mips for ins: 0xXXX1f4 + * cases VKI_SIGFPE not VKI_SIGTRAP + */ + // JRS 2012-Jun-06: commented out until we know we need it + // This isn't a clean solution; need something that avoids looking + // at the guest code. + //UInt *ins = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4); + //UInt tcode = (((*ins) >> 6) & ((1 << 10) - 1)); + //if (tcode == VKI_BRK_OVERFLOW || tcode == VKI_BRK_DIVZERO) { + // if (tcode == VKI_BRK_DIVZERO) + // info.si_code = VKI_FPE_INTDIV; + // else + // info.si_code = VKI_FPE_INTOVF; + // info.si_signo = VKI_SIGFPE; + // info.si_errno = 0; + // info.VKI_SIGINFO_si_addr + // = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4); + //} +# endif + # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number for a breakpoint trap... */ diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index bb76931402..19b347b8bd 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -668,7 +668,9 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, #endif /* ------------------------ s390x ------------------------- */ + #if defined(VGP_s390x_linux) + UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /*OUT*/Addr* ips, UInt max_n_ips, /*OUT*/Addr* sps, /*OUT*/Addr* fps, @@ -744,8 +746,157 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, n_found = i; return n_found; } + #endif +/* ------------------------ mips 32------------------------- */ + +#if defined(VGP_mips32_linux) + +UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, + /*OUT*/Addr* ips, UInt max_n_ips, + /*OUT*/Addr* sps, /*OUT*/Addr* fps, + UnwindStartRegs* startRegs, + Addr fp_max_orig ) +{ + Bool debug = False; + Int i; + Addr fp_max; + UInt n_found = 0; + + vg_assert(sizeof(Addr) == sizeof(UWord)); + vg_assert(sizeof(Addr) == sizeof(void*)); + + D3UnwindRegs uregs; + uregs.pc = startRegs->r_pc; + uregs.sp = startRegs->r_sp; + Addr fp_min = uregs.sp; + + uregs.fp = startRegs->misc.MIPS32.r30; + uregs.ra = startRegs->misc.MIPS32.r31; + + /* 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 + when FP is not a reasonable stack location. */ + + fp_max = VG_PGROUNDUP(fp_max_orig); + if (fp_max >= sizeof(Addr)) + fp_max -= sizeof(Addr); + + if (debug) + VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, " + "fp_max=0x%lx pc=0x%lx sp=0x%lx fp=0x%lx\n", + max_n_ips, fp_min, fp_max_orig, fp_max, + uregs.pc, uregs.sp, uregs.fp); + + if (sps) sps[0] = uregs.sp; + if (fps) fps[0] = uregs.fp; + ips[0] = uregs.pc; + i = 1; + + /* Loop unwinding the stack. */ + + while (True) { + if (debug) { + VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx, ra: 0x%lx\n", + i, uregs.pc, uregs.sp, uregs.ra); + } + if (i >= max_n_ips) + break; + + if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) { + if (debug) + VG_(printf)("USING CFI: pc: 0x%lx, sp: 0x%lx, ra: 0x%lx\n", + uregs.pc, uregs.sp, uregs.ra); + if (0 == uregs.pc || 1 == uregs.pc) break; + if (sps) sps[i] = uregs.sp; + if (fps) fps[i] = uregs.fp; + ips[i++] = uregs.pc - 4; + uregs.pc = uregs.pc - 4; + continue; + } + + int seen_sp_adjust = 0; + long frame_offset = 0; + PtrdiffT offset; + if (VG_(get_inst_offset_in_function)(uregs.pc, &offset)) { + Addr start_pc = uregs.pc - offset; + Addr limit_pc = uregs.pc; + Addr cur_pc; + 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); + if(debug) + VG_(printf)("cur_pc: 0x%lx, inst: 0x%lx\n", cur_pc, inst); + + /* 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 */ + || high_word == 0x67bd) { /* daddiu $sp,$sp,-i */ + if (low_word & 0x8000) /* negative stack adjustment? */ + frame_offset += 0x10000 - low_word; + else + /* Exit loop if a positive stack adjustment is found, which + usually means that the stack cleanup code in the function + epilogue is reached. */ + break; + seen_sp_adjust = 1; + } + } + if(debug) + VG_(printf)("offset: 0x%lx\n", frame_offset); + } + if (seen_sp_adjust) { + if (0 == uregs.pc || 1 == uregs.pc) break; + if (uregs.pc == uregs.ra - 8) break; + if (sps) { + sps[i] = uregs.sp + frame_offset; + } + uregs.sp = uregs.sp + frame_offset; + + if (fps) { + fps[i] = fps[0]; + uregs.fp = fps[0]; + } + if (0 == uregs.ra || 1 == uregs.ra) break; + uregs.pc = uregs.ra - 8; + ips[i++] = uregs.ra - 8; + continue; + } + + if (i == 1) { + if (sps) { + sps[i] = sps[0]; + uregs.sp = sps[0]; + } + if (fps) { + fps[i] = fps[0]; + uregs.fp = fps[0]; + } + if (0 == uregs.ra || 1 == uregs.ra) break; + uregs.pc = uregs.ra - 8; + ips[i++] = uregs.ra - 8; + continue; + } + /* No luck. We have to give up. */ + break; + } + + n_found = i; + return n_found; +} + +#endif + + /*------------------------------------------------------------*/ /*--- ---*/ /*--- END platform-dependent unwinder worker functions ---*/ diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c index 05083d5ef0..a52aeb0aae 100644 --- a/coregrind/m_syscall.c +++ b/coregrind/m_syscall.c @@ -62,6 +62,7 @@ SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = val >= -4095 && val <= -1; if (res._isError) { res._val = (UInt)(-val); @@ -74,6 +75,7 @@ SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { /* Similarly .. */ SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = val >= -4095 && val <= -1; if (res._isError) { res._val = (ULong)(-val); @@ -87,6 +89,7 @@ SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) { /* Note this must be in the bottom bit of the second arg */ SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = (cr0so & 1) != 0; res._val = val; return res; @@ -95,6 +98,7 @@ SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) { /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */ SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = (cr0so & 1) != 0; res._val = val; return res; @@ -102,6 +106,7 @@ SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) { SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = val >= -4095 && val <= -1; if (res._isError) { res._val = -val; @@ -113,6 +118,7 @@ SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) { SysRes VG_(mk_SysRes_arm_linux) ( Int val ) { SysRes res; + res._valEx = 0; /* unused except on mips-linux */ res._isError = val >= -4095 && val <= -1; if (res._isError) { res._val = (UInt)(-val); @@ -122,9 +128,19 @@ SysRes VG_(mk_SysRes_arm_linux) ( Int val ) { return res; } +/* MIPS uses a3 != 0 to flag an error */ +SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) { + SysRes res; + res._isError = (a3 != (UWord)0); + res._val = v0; + res._valEx = v1; + return res; +} + /* Generic constructors. */ SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes r; + r._valEx = 0; /* unused except on mips-linux */ r._isError = True; r._val = err; return r; @@ -132,6 +148,7 @@ SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes VG_(mk_SysRes_Success) ( UWord res ) { SysRes r; + r._valEx = 0; /* unused except on mips-linux */ r._isError = False; r._val = res; return r; @@ -575,6 +592,40 @@ static UWord do_syscall_WRK ( return (UWord) (__svcres); } +#elif defined(VGP_mips32_linux) +/* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack. + + The syscall number goes in v0. The args are passed to the syscall in + the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention. + + (a3 != 0) flags an error. + We return the syscall return value in v0. + MIPS version +*/ +extern int do_syscall_WRK ( + int a1, int a2, int a3, + int a4, int a5, int a6, int syscall_no, UWord *err, + UWord *valHi, UWord* valLo + ); +asm( +".globl do_syscall_WRK\n" +".ent do_syscall_WRK\n" +".text\n" +"do_syscall_WRK:\n" +" lw $2, 24($29)\n" +" syscall\n" +" lw $8, 28($29)\n" +" sw $7, ($8)\n" +" lw $8, 32($29)\n" +" sw $3, ($8)\n" // store valHi +" lw $8, 36($29)\n" +" sw $2, ($8)\n" // store valLo +" jr $31\n" +" nop\n" +".previous\n" +".end do_syscall_WRK\n" +); + #else # error Unknown platform #endif @@ -682,6 +733,13 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, } return VG_(mk_SysRes_s390x_linux)( val ); + +#elif defined(VGP_mips32_linux) + UWord err = 0; + UWord valHi = 0; + 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 ); #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 8069cbdb64..9040148cff 100644 --- a/coregrind/m_syswrap/priv_types_n_macros.h +++ b/coregrind/m_syswrap/priv_types_n_macros.h @@ -98,6 +98,15 @@ typedef Int o_arg6; Int uu_arg7; Int uu_arg8; +# elif defined(VGP_mips32_linux) + Int o_arg1; + Int o_arg2; + Int o_arg3; + Int o_arg4; + Int s_arg5; + Int s_arg6; + Int uu_arg7; + Int uu_arg8; # elif defined(VGP_x86_darwin) Int s_arg1; Int s_arg2; @@ -167,6 +176,16 @@ typedef fixed sized table exposed to the caller, but that's too inflexible; hence now use a function which can do arbitrary messing around to find the required entry. */ +#if defined(VGP_mips32_linux) + /* Up to 6 parameters, 4 in registers 2 on stack. */ +# define PRA1(s,t,a) PRRAn(1,s,t,a) +# define PRA2(s,t,a) PRRAn(2,s,t,a) +# define PRA3(s,t,a) PRRAn(3,s,t,a) +# define PRA4(s,t,a) PRRAn(4,s,t,a) +# define PRA5(s,t,a) PSRAn(5,s,t,a) +# define PRA6(s,t,a) PSRAn(6,s,t,a) + +#endif #if defined(VGO_linux) extern SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno ); @@ -359,7 +378,16 @@ static inline UWord getERR ( SyscallStatus* st ) { PRAn == "pre-read-argument" */ -#if defined(VGO_linux) +#if defined(VGP_mips32_linux) + /* Up to 6 parameters, 4 in registers 2 on stack. */ +# define PRA1(s,t,a) PRRAn(1,s,t,a) +# define PRA2(s,t,a) PRRAn(2,s,t,a) +# define PRA3(s,t,a) PRRAn(3,s,t,a) +# define PRA4(s,t,a) PRRAn(4,s,t,a) +# define PRA5(s,t,a) PSRAn(5,s,t,a) +# define PRA6(s,t,a) PSRAn(6,s,t,a) + +#elif defined(VGO_linux) && !defined(VGP_mips32_linux) /* Up to 6 parameters, all in registers. */ # define PRA1(s,t,a) PRRAn(1,s,t,a) # define PRA2(s,t,a) PRRAn(2,s,t,a) @@ -480,6 +508,18 @@ static inline UWord getERR ( SyscallStatus* st ) { since the least significant parts of the guest register are stored in memory at the highest address. */ +#if (defined(VGP_mips32_linux) && defined (_MIPSEB)) + #define PSRAn_BE(n,s,t,a) \ + do { \ + Addr next = layout->s_arg##n + sizeof(UWord) + \ + VG_(threads)[tid].arch.vex.guest_r29; \ + vg_assert(sizeof(t) <= sizeof(UWord)); \ + VG_(tdict).track_pre_mem_read( \ + Vg_CoreSysCallArgInMem, tid, s"("#a")", \ + next-sizeof(t), sizeof(t) \ + ); \ + } while (0) +#else #define PSRAn_BE(n,s,t,a) \ do { \ Addr next = layout->o_arg##n + sizeof(UWord) + \ @@ -490,6 +530,7 @@ static inline UWord getERR ( SyscallStatus* st ) { next-sizeof(t), sizeof(t) \ ); \ } while (0) +#endif #if defined(VG_BIGENDIAN) # define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a) diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 62eb3bf63a..7d97b6f800 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -271,6 +271,17 @@ 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) + asm volatile ( + "sw %1, %0\n\t" /* set tst->status = VgTs_Empty */ + "li $2, %2\n\t" /* set v0 = __NR_exit */ + "lw $4, %3\n\t" /* set a0 = tst->os_state.exitcode */ + "syscall\n\t" /* exit(tst->os_state.exitcode) */ + "nop" + : "=m" (tst->status) + : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode) + : "cc", "memory" , "v0", "a0" + ); #else # error Unknown platform #endif @@ -414,7 +425,7 @@ 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_arm_linux) || defined(VGP_mips32_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 991e009861..8c31dd1b0e 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -68,6 +68,7 @@ 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) 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 @@ -462,6 +463,27 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, canonical->arg7 = 0; canonical->arg8 = 0; +#elif defined(VGP_mips32_linux) + VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; + canonical->sysno = gst->guest_r2; // v0 + if (canonical->sysno != __NR_syscall) { + 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 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp) + canonical->arg6 = *((UInt*) (gst->guest_r29 + 20)); // 20(sp) + } else { + // Fixme hack handle syscall() + canonical->sysno = gst->guest_r4; // a0 + canonical->arg1 = gst->guest_r5; // a1 + canonical->arg2 = gst->guest_r6; // a2 + canonical->arg3 = gst->guest_r7; // a3 + canonical->arg4 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp) + canonical->arg5 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP/sp) + canonical->arg6 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP/sp) + } + #elif defined(VGP_x86_darwin) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; UWord *stack = (UWord *)gst->guest_ESP; @@ -695,6 +717,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, gst->guest_r6 = canonical->arg5; gst->guest_r7 = canonical->arg6; +#elif defined(VGP_mips32_linux) + VexGuestMIPS32State* gst = (VexGuestMIPS32State*)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; + *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp) + *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp) + #else # error "putSyscallArgsIntoGuestState: unknown arch" #endif @@ -733,6 +765,14 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 ); canonical->what = SsComplete; +# elif defined(VGP_mips32_linux) + VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; + UInt v0 = gst->guest_r2; // v0 + UInt v1 = gst->guest_r3; // v1 + UInt a3 = gst->guest_r7; // a3 + canonical->sres = VG_(mk_SysRes_mips32_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; @@ -965,6 +1005,24 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, gst->guest_r2 = sr_Res(canonical->sres); } +# elif defined(VGP_mips32_linux) + VexGuestMIPS32State* gst = (VexGuestMIPS32State*)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_mips32_r2, sizeof(UWord) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_mips32_r3, sizeof(UWord) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_mips32_r7, sizeof(UWord) ); + # else # error "putSyscallStatusIntoGuestState: unknown arch" # endif @@ -1033,6 +1091,17 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->uu_arg7 = -1; /* impossible value */ layout->uu_arg8 = -1; /* impossible value */ +#elif defined(VGP_mips32_linux) + layout->o_sysno = OFFSET_mips32_r2; + layout->o_arg1 = OFFSET_mips32_r4; + layout->o_arg2 = OFFSET_mips32_r5; + layout->o_arg3 = OFFSET_mips32_r6; + layout->o_arg4 = OFFSET_mips32_r7; + layout->s_arg5 = sizeof(UWord) * 4; + layout->s_arg6 = sizeof(UWord) * 5; + 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 @@ -1887,11 +1956,45 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) vg_assert(p[0] == 0x0A); } + +#elif defined(VGP_mips32_linux) + + arch->vex.guest_PC -= 4; // sizeof(mips instr) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + syscall == 00 00 00 0C + big endian + syscall == 0C 00 00 00 + */ + { + UChar *p = (UChar *)(arch->vex.guest_PC); +# 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", + 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", + 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); +# else +# error "Unknown endianness" +# endif + } + #else # error "ML_(fixup_guest_state_to_restart_syscall): unknown plat" #endif } + /* Fix up the guest state when a syscall is interrupted by a signal and so has been forced to return 'sysret'. @@ -1902,7 +2005,7 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) 1. unblock signals 2. perform syscall - 3. save result to guest state (EAX, RAX, R3+CR0.SO) + 3. save result to guest state (EAX, RAX, R3+CR0.SO, R0, V0) 4. re-block signals If a signal diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index 73ef862597..d10b8407ea 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -1021,6 +1021,64 @@ VG_(s390x_linux_SUBST_FOR_rt_sigreturn): VG_(trampoline_stuff_end): .fill 2048, 2, 0x0000 +/*---------------------- mips32-linux ----------------------*/ +#else +#if defined(VGP_mips32_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_(mips32_linux_SUBST_FOR_sigreturn) +VG_(mips32_linux_SUBST_FOR_sigreturn): + li $v0,__NR_sigreturn + syscall + nop + .long 0 /*illegal insn*/ + +.global VG_(mips32_linux_SUBST_FOR_rt_sigreturn) +VG_(mips32_linux_SUBST_FOR_rt_sigreturn): + li $v0,__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_(mips32_linux_REDIR_FOR_strlen) +.type VG_(mips32_linux_REDIR_FOR_strlen), @function +VG_(mips32_linux_REDIR_FOR_strlen): + li $v0, 0 + //la $a0, string + j strlen_cond + strlen_loop: + addi $v0, $v0, 1 + addi $a0, $a0, 1 + strlen_cond: + lbu $t0, ($a0) + bne $t0, $zero, strlen_loop + jr $ra + +.size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen) + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + + +# undef UD2_16 +# undef UD2_64 +# undef UD2_256 +# undef UD2_1024 +# undef UD2_PAGE + /*---------------- unknown ----------------*/ #else # error Unknown platform @@ -1032,6 +1090,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 d0551019e0..fc6fa6287c 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -726,7 +726,7 @@ void log_bytes ( HChar* bytes, Int nbytes ) static Bool translations_allowable_from_seg ( NSegment const* seg ) { -# if defined(VGA_x86) || defined(VGA_s390x) +# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) Bool allowR = True; # else Bool allowR = False; @@ -1188,6 +1188,12 @@ 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. + VgCallbackClosure* closure = (VgCallbackClosure*)closureV; + Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25); + addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) ); +# endif # if defined(VG_PLAT_USES_PPCTOC) { VgCallbackClosure* closure = (VgCallbackClosure*)closureV; addStmtToIRSB( @@ -1224,6 +1230,11 @@ 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 )) ); +# endif # if defined(VGP_ppc64_linux) addStmtToIRSB( bb, diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h index 150d3be1e2..39b5ae7b74 100644 --- a/coregrind/pub_core_aspacemgr.h +++ b/coregrind/pub_core_aspacemgr.h @@ -343,7 +343,8 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, // stacks. The address space manager provides and suitably // protects such stacks. -#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ + || defined(VGP_mips32_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 f0861d4ce2..63db17f41e 100644 --- a/coregrind/pub_core_basics.h +++ b/coregrind/pub_core_basics.h @@ -60,6 +60,8 @@ # include "libvex_guest_arm.h" #elif defined(VGA_s390x) # include "libvex_guest_s390x.h" +#elif defined(VGA_mips32) +# include "libvex_guest_mips32.h" #else # error Unknown arch #endif @@ -83,8 +85,8 @@ typedef struct { - ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15 */ - ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13 */ + ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc */ + ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp */ union { struct { UInt r_ebp; @@ -108,6 +110,11 @@ typedef ULong r_fp; ULong r_lr; } S390X; + struct { + UInt r30; /* Stack frame pointer or subroutine variable */ + UInt r31; /* Return address of the last subroutine call */ + UInt r28; + } MIPS32; } misc; } UnwindStartRegs; diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index fa1b129550..8655260729 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -93,6 +93,12 @@ Bool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf ); extern Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf ); +/* mips-linux only: find the offset of current address. This is needed for + stack unwinding for MIPS. +*/ +extern +Bool VG_(get_inst_offset_in_function)( Addr a, /*OUT*/PtrdiffT* offset ); + /* Use DWARF2/3 CFA information to do one step of stack unwinding. D3UnwindRegs holds the current register values, and is @@ -114,6 +120,10 @@ typedef typedef struct { Addr ia; Addr sp; Addr fp; Addr lr;} D3UnwindRegs; +#elif defined(VGA_mips32) +typedef + struct { Addr pc; Addr sp; Addr fp; Addr ra; } + D3UnwindRegs; #else # error "Unsupported arch" #endif diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h index b76f395f9b..4b3ad6c9c1 100644 --- a/coregrind/pub_core_machine.h +++ b/coregrind/pub_core_machine.h @@ -75,6 +75,17 @@ # define VG_ELF_MACHINE EM_S390 # define VG_ELF_CLASS ELFCLASS64 # undef VG_PLAT_USES_PPCTOC +#elif defined(VGP_mips32_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 ELFCLASS32 +# undef VG_PLAT_USES_PPCTOC #else # error Unknown platform #endif @@ -104,6 +115,10 @@ # define VG_STACK_PTR guest_SP # define VG_FRAME_PTR guest_FP # define VG_FPC_REG guest_fpc +#elif defined(VGA_mips32) +# 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 c192f19f5e..508b9f3fa5 100644 --- a/coregrind/pub_core_mallocfree.h +++ b/coregrind/pub_core_mallocfree.h @@ -80,6 +80,7 @@ typedef Int ArenaId; defined(VGP_ppc32_linux) || \ defined(VGP_ppc64_linux) || \ defined(VGP_s390x_linux) || \ + defined(VGP_mips32_linux) || \ defined(VGP_x86_darwin) || \ defined(VGP_amd64_darwin) # define VG_MIN_MALLOC_SZB 16 diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h index 1b6d35fcc9..2902001b04 100644 --- a/coregrind/pub_core_syscall.h +++ b/coregrind/pub_core_syscall.h @@ -79,6 +79,8 @@ extern SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr, extern SysRes VG_(mk_SysRes_amd64_darwin)( UChar scclass, Bool isErr, ULong wHI, ULong wLO ); 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_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 ccb41a1b6b..2e80f87bf0 100644 --- a/coregrind/pub_core_threadstate.h +++ b/coregrind/pub_core_threadstate.h @@ -87,6 +87,8 @@ typedef typedef VexGuestARMState VexGuestArchState; #elif defined(VGA_s390x) typedef VexGuestS390XState VexGuestArchState; +#elif defined(VGA_mips32) + typedef VexGuestMIPS32State VexGuestArchState; #else # error Unknown architecture #endif diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 4e8779226d..765c7f6a0b 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -127,6 +127,12 @@ extern Addr VG_(s390x_linux_SUBST_FOR_sigreturn); extern Addr VG_(s390x_linux_SUBST_FOR_rt_sigreturn); #endif +#if defined(VGP_mips32_linux) +extern Addr VG_(mips32_linux_SUBST_FOR_sigreturn); +extern Addr VG_(mips32_linux_SUBST_FOR_rt_sigreturn); +extern UInt VG_(mips32_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 00adced522..12b02de774 100644 --- a/coregrind/pub_core_transtab_asm.h +++ b/coregrind/pub_core_transtab_asm.h @@ -62,7 +62,7 @@ #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) +#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32) # 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 46b2cfd688..c0f1d815f0 100644 --- a/coregrind/vgdb.c +++ b/coregrind/vgdb.c @@ -80,7 +80,8 @@ can be "waken up". PTRACEINVOKER implies some architecture specific code and/or some OS specific code. */ #if defined(VGA_arm) || defined(VGA_x86) || defined(VGA_amd64) \ - || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) + || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \ + || defined(VGP_mips32_linux) #define PTRACEINVOKER #else I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c @@ -923,6 +924,8 @@ Bool invoke_gdbserver (int pid) sp = user_mod.regs.gpr[1]; #elif defined(VGA_s390x) sp = user_mod.regs.gprs[15]; +#elif defined(VGA_mips32) + sp = user_mod.regs[29]; #else I_die_here : (sp) architecture missing in vgdb.c #endif @@ -995,6 +998,12 @@ Bool invoke_gdbserver (int pid) #elif defined(VGA_s390x) XERROR(0, "(fn32) s390x has no 32bits implementation"); +#elif defined(VGA_mips32) + /* put check arg in register 0 */ + user_mod.regs[4] = check; + /* put NULL return address in ra */ + user_mod.regs[31] = bad_return; + user_mod.regs[25] = shared32->invoke_gdbserver; #else I_die_here : architecture missing in vgdb.c #endif @@ -1074,6 +1083,8 @@ Bool invoke_gdbserver (int pid) user_mod.regs.gprs[15] = sp; /* set program counter */ 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 #else I_die_here: architecture missing in vgdb.c #endif diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h index 372c787326..5cc6d481f8 100644 --- a/drd/drd_bitmap.h +++ b/drd/drd_bitmap.h @@ -136,7 +136,8 @@ Addr make_address(const UWord a1, const UWord a0) #define BITS_PER_UWORD (8U * sizeof(UWord)) /** Log2 of BITS_PER_UWORD. */ -#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) +#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) #define BITS_PER_BITS_PER_UWORD 6 diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c index be16544785..42ab3b970c 100644 --- a/drd/drd_clientreq.c +++ b/drd/drd_clientreq.c @@ -69,6 +69,12 @@ 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) + /* There is a cse related issue in gcc for MIPS. Optimization level + has to be lowered, so cse related optimizations are not + included. */ + __attribute__((optimize("O1"))) +#endif static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret) { UWord result = 0; diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c index 3d99112f1f..7dc8a9ffb8 100644 --- a/drd/drd_load_store.c +++ b/drd/drd_load_store.c @@ -49,6 +49,8 @@ #define STACK_POINTER_OFFSET OFFSET_arm_R13 #elif defined(VGA_s390x) #define STACK_POINTER_OFFSET OFFSET_s390x_r15 +#elif defined(VGA_mips32) +#define STACK_POINTER_OFFSET OFFSET_mips32_r29 #else #error Unknown architecture. #endif diff --git a/drd/drd_thread.c b/drd/drd_thread.c index c2f1a85b33..6e2dd41967 100644 --- a/drd/drd_thread.c +++ b/drd/drd_thread.c @@ -597,6 +597,12 @@ Bool DRD_(thread_get_joinable)(const DrdThreadId tid) } /** Store the thread mode: joinable or detached. */ +#if defined(VGP_mips32_linux) + /* There is a cse related issue in gcc for MIPS. Optimization level + has to be lowered, so cse related optimizations are not + included.*/ + __attribute__((optimize("O1"))) +#endif void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable) { tl_assert(0 <= (int)tid && tid < DRD_N_THREADS diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c index af3fa043e4..cd58cef0f7 100644 --- a/helgrind/tests/annotate_hbefore.c +++ b/helgrind/tests/annotate_hbefore.c @@ -186,6 +186,38 @@ UWord do_acasW(UWord* addr, UWord expected, UWord nyu ) return cc == 0; } +#elif defined(VGA_mips32) + +// mips +/* return 1 if success, 0 if failure */ +UWord do_acasW ( UWord* addr, UWord expected, UWord nyu ) +{ + UWord old, success; + UWord block[3] = { (UWord)addr, nyu, expected}; + + __asm__ __volatile__( + ".set noreorder" "\n\t" + "lw $t0, 0(%1)" "\n\t" + "lw $t2, 8(%1)" "\n\t" + "lw $t3, 4(%1)" "\n\t" + "ll $t1, 0($t0)" "\n\t" + "bne $t1, $t2, exit_0" "\n\t" + "sc $t3, 0($t0)" "\n\t" + "move %0, $t3" "\n\t" + "b exit" "\n\t" + "nop" "\n\t" + "exit_0:" "\n\t" + "move %0, $0" "\n\t" + "exit:" "\n\t" + : /*out*/ "=r"(success) + : /*in*/ "r"(&block[0]) + : /*trash*/ "t0", "t1", "t2", "t3", "memory" + ); + + assert(success == 0 || success == 1); + return success; +} + #endif void atomic_incW ( UWord* w ) diff --git a/helgrind/tests/tc07_hbl1.c b/helgrind/tests/tc07_hbl1.c index e5b11c44c3..92c74e018f 100644 --- a/helgrind/tests/tc07_hbl1.c +++ b/helgrind/tests/tc07_hbl1.c @@ -14,6 +14,7 @@ #undef PLAT_ppc64_linux #undef PLAT_arm_linux #undef PLAT_s390x_linux +#undef PLAT_mips32_linux #if defined(__APPLE__) && defined(__i386__) # define PLAT_x86_darwin 1 @@ -31,6 +32,8 @@ # define PLAT_arm_linux 1 #elif defined(__linux__) && defined(__s390x__) # define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) +# define PLAT_mips32_linux 1 #endif #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \ @@ -71,6 +74,20 @@ " jl 1b\n" \ : "+m" (_lval) :: "cc", "1","2" \ ) +#elif defined(PLAT_mips32_linux) +# define INC(_lval,_lqual) \ + __asm__ __volatile__ ( \ + "1:\n" \ + " move $8, %0\n" \ + " ll $9, 0($8)\n" \ + " addiu $9, $9, 1\n" \ + " sc $9, 0($8)\n" \ + " li $10, 1\n" \ + " bne $9, $10, 1b\n" \ + " nop\n" \ + : /*out*/ : /*in*/ "r"(&(_lval)) \ + : /*trash*/ "$8", "$9", "$10", "cc", "memory" \ + ) #else # error "Fix Me for this platform" #endif diff --git a/helgrind/tests/tc08_hbl2.c b/helgrind/tests/tc08_hbl2.c index 8cc682b74e..b39f9ee711 100644 --- a/helgrind/tests/tc08_hbl2.c +++ b/helgrind/tests/tc08_hbl2.c @@ -30,6 +30,7 @@ #undef PLAT_ppc64_linux #undef PLAT_arm_linux #undef PLAT_s390x_linux +#undef PLAT_mips32_linux #if defined(__APPLE__) && defined(__i386__) # define PLAT_x86_darwin 1 @@ -47,6 +48,8 @@ # define PLAT_arm_linux 1 #elif defined(__linux__) && defined(__s390x__) # define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) +# define PLAT_mips32_linux 1 #endif @@ -88,6 +91,19 @@ " jl 1b\n" \ : "+m" (_lval) :: "cc", "0","1" \ ) +#elif defined(PLAT_mips32_linux) +# define INC(_lval,_lqual) \ + __asm__ __volatile__ ( \ + "L1xyzzy1" _lqual":\n" \ + " move $8, %0\n" \ + " ll $9, 0($t0)\n" \ + " addi $9, $9, 1\n" \ + " sc $9, 0($t0)\n" \ + " li $10, 1\n" \ + " bne $9, $10, L1xyzzy1" _lqual \ + : /*out*/ : /*in*/ "r"(&(_lval)) \ + : /*trash*/ "$8", "$9", "$10", "cc", "memory" \ + ) #else # error "Fix Me for this platform" #endif diff --git a/helgrind/tests/tc11_XCHG.c b/helgrind/tests/tc11_XCHG.c index ac85d8280e..fadc774fba 100644 --- a/helgrind/tests/tc11_XCHG.c +++ b/helgrind/tests/tc11_XCHG.c @@ -17,6 +17,7 @@ #undef PLAT_ppc64_linux #undef PLAT_arm_linux #undef PLAT_s390x_linux +#undef PLAT_mips32_linux #if defined(__APPLE__) && defined(__i386__) # define PLAT_x86_darwin 1 @@ -34,6 +35,8 @@ # define PLAT_arm_linux 1 #elif defined(__linux__) && defined(__s390x__) # define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) +# define PLAT_mips32_linux 1 #endif @@ -71,6 +74,22 @@ # define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \ XCHG_M_R(_addr,_lval) +#elif defined(PLAT_mips32_linux) || defined(PLAT_mips64_linux) +# define XCHG_M_R(_addr,_lval) \ + __asm__ __volatile__( \ + "move $12, %2\n" \ + "move $13, %1\n" \ + "ll $14, 0($13)\n" \ + "sc $12, 0($13)\n" \ + "move %0, $14\n" \ + : /*out*/ "=r"(_lval) \ + : /*in*/ "r"(&_addr), "r"(_lval) \ + : "$12", "$13", "$14", "memory", "cc" \ + ) + +# define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \ + XCHG_M_R(_addr,_lval) + #elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) \ || defined(PLAT_arm_linux) # if defined(HAVE_BUILTIN_ATOMIC) diff --git a/include/Makefile.am b/include/Makefile.am index 851649251f..ade27c2244 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -49,16 +49,19 @@ nobase_pkginclude_HEADERS = \ vki/vki-posixtypes-x86-linux.h \ vki/vki-posixtypes-arm-linux.h \ vki/vki-posixtypes-s390x-linux.h \ + vki/vki-posixtypes-mips32-linux.h \ vki/vki-amd64-linux.h \ vki/vki-ppc32-linux.h \ vki/vki-ppc64-linux.h \ vki/vki-x86-linux.h \ vki/vki-arm-linux.h \ vki/vki-s390x-linux.h \ + vki/vki-mips32-linux.h \ vki/vki-scnums-amd64-linux.h \ vki/vki-scnums-ppc32-linux.h \ vki/vki-scnums-ppc64-linux.h \ vki/vki-scnums-x86-linux.h \ vki/vki-scnums-arm-linux.h \ vki/vki-scnums-s390x-linux.h \ + vki/vki-scnums-mips32-linux.h \ vki/vki-scnums-darwin.h diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h index ae7bae69f4..5b387e8935 100644 --- a/include/pub_tool_basics.h +++ b/include/pub_tool_basics.h @@ -163,6 +163,7 @@ typedef UInt ThreadId; typedef struct { UWord _val; + UWord _valEx; // only used on mips-linux Bool _isError; } SysRes; @@ -197,6 +198,9 @@ static inline Bool sr_isError ( SysRes sr ) { static inline UWord sr_Res ( SysRes sr ) { return sr._isError ? 0 : sr._val; } +static inline UWord sr_ResEx ( SysRes sr ) { + return sr._isError ? 0 : sr._valEx; +} static inline UWord sr_ResHI ( SysRes sr ) { return 0; } @@ -264,9 +268,11 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { #undef VG_BIGENDIAN #undef VG_LITTLEENDIAN -#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) +#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \ + || (defined(VGA_mips32) && defined (_MIPSEL)) # define VG_LITTLEENDIAN 1 -#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) +#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \ + || (defined(VGA_mips32) && defined (_MIPSEB)) # define VG_BIGENDIAN 1 #else # error Unknown arch @@ -276,7 +282,8 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { #if defined(VGA_x86) # 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_ppc64) || defined(VGA_arm) || defined(VGA_s390x) \ + || defined(VGA_mips32) # define VG_REGPARM(n) /* */ #else # error Unknown arch diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index 6b30e69b10..55fd2fb31c 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -83,6 +83,12 @@ # define VG_CLREQ_SZB 19 # define VG_STACK_REDZONE_SZB 128 +#elif defined(VGP_mips32_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 018cb19bf9..649c7aafa9 100644 --- a/include/pub_tool_vkiscnums_asm.h +++ b/include/pub_tool_vkiscnums_asm.h @@ -51,6 +51,9 @@ #elif defined(VGP_arm_linux) # include "vki/vki-scnums-arm-linux.h" +#elif defined(VGP_mips32_linux) +# include "vki/vki-scnums-mips32-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 d10a5132f7..afb4681dbf 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -117,6 +117,7 @@ #undef PLAT_ppc64_linux #undef PLAT_arm_linux #undef PLAT_s390x_linux +#undef PLAT_mips32_linux #if defined(__APPLE__) && defined(__i386__) @@ -138,6 +139,8 @@ # define PLAT_arm_linux 1 #elif defined(__linux__) && defined(__s390__) && defined(__s390x__) # define PLAT_s390x_linux 1 +#elif defined(__linux__) && defined(__mips__) +# define PLAT_mips32_linux 1 #else /* If we're not compiling for our target platform, don't generate any inline asms. */ @@ -665,6 +668,70 @@ typedef #endif /* PLAT_s390x_linux */ +/* ------------------------- mips32-linux ---------------- */ + +#if defined(PLAT_mips32_linux) + +typedef + struct { + unsigned int nraddr; /* where's the code? */ + } + OrigFn; + +/* .word 0x342 + * .word 0x742 + * .word 0xC2 + * .word 0x4C2*/ +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "srl $0, $0, 13\n\t" \ + "srl $0, $0, 29\n\t" \ + "srl $0, $0, 3\n\t" \ + "srl $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 int _zzq_args[6]; \ + volatile unsigned int _zzq_result; \ + _zzq_args[0] = (unsigned int)(_zzq_request); \ + _zzq_args[1] = (unsigned int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned int)(_zzq_arg5); \ + __asm__ volatile("move $11, %1\n\t" /*default*/ \ + "move $12, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* T3 = client_request ( T4 ) */ \ + "or $13, $13, $13\n\t" \ + "move %0, $11\n\t" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "cc","memory", "t3", "t4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + volatile unsigned int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %t9 = guest_NRADDR */ \ + "or $14, $14, $14\n\t" \ + "move %0, $11" /*result*/ \ + : "=r" (__addr) \ + : \ + : "cc", "memory" , "t3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_CALL_NOREDIR_T9 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* call-noredir *%t9 */ \ + "or $15, $15, $15\n\t" +#endif /* PLAT_mips32_linux */ + /* Insert assembly code for other platforms here... */ #endif /* NVALGRIND */ @@ -3589,6 +3656,545 @@ typedef #endif /* PLAT_s390x_linux */ +/* ------------------------- mips-linux ------------------------- */ + +#if defined(PLAT_mips32_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( \ + "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 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16\n\t" \ + "lw $gp, 0($sp) \n\t" \ + "lw $ra, 4($sp) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $v0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 $a0, 4(%1) \n\t" /* arg1*/ \ + "lw $t9, 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" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $v0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 $a0, 4(%1) \n\t" \ + "lw $a1, 8(%1) \n\t" \ + "lw $t9, 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" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $v0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 $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 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $gp, 0($sp) \n\t" \ + "lw $ra, 4($sp) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $v0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 $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 */ \ + VALGRIND_CALL_NOREDIR_T9 \ + "addu $29, $29, 16 \n\t" \ + "lw $gp, 0($sp) \n\t" \ + "lw $ra, 4($sp) \n\t" \ + "addu $29, $29, 8 \n\t" \ + "move %0, $v0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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" \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "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( \ + "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 */ \ + 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" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_mips32_linux */ + /* ------------------------------------------------------------------ */ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ @@ -4068,5 +4674,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) #undef PLAT_ppc64_linux #undef PLAT_arm_linux #undef PLAT_s390x_linux +#undef PLAT_mips32_linux #endif /* __VALGRIND_H */ diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index d73b04439b..ec91c9f8bb 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -91,6 +91,8 @@ # include "vki-posixtypes-arm-linux.h" #elif defined(VGA_s390x) # include "vki-posixtypes-s390x-linux.h" +#elif defined(VGA_mips32) +# include "vki-posixtypes-mips32-linux.h" #else # error Unknown platform #endif @@ -211,6 +213,8 @@ typedef unsigned int vki_uint; # include "vki-arm-linux.h" #elif defined(VGA_s390x) # include "vki-s390x-linux.h" +#elif defined(VGA_mips32) +# include "vki-mips32-linux.h" #else # error Unknown platform #endif @@ -383,6 +387,8 @@ struct vki_sched_param { // From linux-2.6.8.1/include/asm-generic/siginfo.h //---------------------------------------------------------------------- +// Some archs, such as MIPS, have non-standard vki_siginfo. +#ifndef HAVE_ARCH_SIGINFO_T typedef union vki_sigval { int sival_int; void __user *sival_ptr; @@ -462,6 +468,7 @@ typedef struct vki_siginfo { } _sigpoll; } _sifields; } vki_siginfo_t; +#endif #define __VKI_SI_FAULT 0 diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c index 5bee6c2247..2df3a587e6 100644 --- a/memcheck/mc_machine.c +++ b/memcheck/mc_machine.c @@ -76,6 +76,11 @@ # define MC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState) #endif +#if defined(VGA_mips32) +# include "libvex_guest_mips32.h" +# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestMIPS32State) +#endif + static inline Bool host_is_big_endian ( void ) { UInt x = 0x11223344; return 0x1122 == *(UShort*)(&x); @@ -937,6 +942,117 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB ) offset,szB); tl_assert(0); # undef GOF +# undef SZB + + /* --------------------- mips32 --------------------- */ + +# elif defined(VGA_mips32) + +# define GOF(_fieldname) \ + (offsetof(VexGuestMIPS32State,guest_##_fieldname)) +# define SZB(_fieldname) \ + (sizeof(((VexGuestMIPS32State*)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()); +# else +# error "Unknown endianness" +# endif + + if (o == GOF(r0) && sz == 4) return o; + if (o == GOF(r1) && sz == 4) return o; + if (o == GOF(r2) && sz == 4) return o; + if (o == GOF(r3) && sz == 4) return o; + if (o == GOF(r4) && sz == 4) return o; + if (o == GOF(r5) && sz == 4) return o; + if (o == GOF(r6) && sz == 4) return o; + if (o == GOF(r7) && sz == 4) return o; + if (o == GOF(r8) && sz == 4) return o; + if (o == GOF(r9) && sz == 4) return o; + if (o == GOF(r10) && sz == 4) return o; + if (o == GOF(r11) && sz == 4) return o; + if (o == GOF(r12) && sz == 4) return o; + if (o == GOF(r13) && sz == 4) return o; + if (o == GOF(r14) && sz == 4) return o; + if (o == GOF(r15) && sz == 4) return o; + if (o == GOF(r16) && sz == 4) return o; + if (o == GOF(r17) && sz == 4) return o; + if (o == GOF(r18) && sz == 4) return o; + if (o == GOF(r19) && sz == 4) return o; + if (o == GOF(r20) && sz == 4) return o; + if (o == GOF(r21) && sz == 4) return o; + if (o == GOF(r22) && sz == 4) return o; + if (o == GOF(r23) && sz == 4) return o; + if (o == GOF(r24) && sz == 4) return o; + if (o == GOF(r25) && sz == 4) return o; + if (o == GOF(r26) && sz == 4) return o; + if (o == GOF(r27) && sz == 4) return o; + if (o == GOF(r28) && sz == 4) return o; + if (o == GOF(r29) && sz == 4) return o; + if (o == GOF(r30) && sz == 4) return o; + if (o == GOF(r31) && sz == 4) return o; + if (o == GOF(PC) && sz == 4) return -1; /* slot unused */ + + if (o == GOF(HI) && sz == 4) return o; + if (o == GOF(LO) && sz == 4) 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 == 4) return -1; + + if (o == GOF(EMWARN) && 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; /*padding registers*/ + + VG_(printf)("MC_(get_otrack_shadow_offset)(mips)(off=%d,sz=%d)\n", + offset,szB); + tl_assert(0); +# undef GOF # undef SZB # else @@ -1022,7 +1138,6 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr ) /* --------------------- arm --------------------- */ # elif defined(VGA_arm) - VG_(printf)("get_reg_array_equiv_int_type(arm): unhandled: "); ppIRRegArray(arr); VG_(printf)("\n"); @@ -1033,6 +1148,14 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr ) /* Should never het here because s390x does not use Ist_PutI and Iex_GetI. */ tl_assert(0); + +/* --------------------- mips32 --------------------- */ +# elif defined(VGA_mips32) + VG_(printf)("get_reg_array_equiv_int_type(mips32): unhandled: "); + ppIRRegArray(arr); + VG_(printf)("\n"); + tl_assert(0); + # else # error "FIXME: not implemented for this architecture" # endif diff --git a/memcheck/tests/atomic_incs.c b/memcheck/tests/atomic_incs.c index 80cf810fe7..ac1e775caf 100644 --- a/memcheck/tests/atomic_incs.c +++ b/memcheck/tests/atomic_incs.c @@ -110,6 +110,48 @@ __attribute__((noinline)) void atomic_add_8bit ( char* p, int n ) : "+m" (*p), "+m" (dummy) : "d" (n) : "cc", "memory", "0", "1"); +#elif defined(VGA_mips32) +#if defined (_MIPSEL) + unsigned int block[3] + = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF }; + do { + __asm__ __volatile__( + "move $t0, %0" "\n\t" + "lw $t1, 0($t0)" "\n\t" // p + "lw $t2, 4($t0)" "\n\t" // n + "ll $t3, 0($t1)" "\n\t" + "addu $t3, $t3, $t2" "\n\t" + "andi $t3, $t3, 0xFF" "\n\t" + "sc $t3, 0($t1)" "\n\t" + "sw $t3, 8($t0)" "\n\t" + : /*out*/ + : /*in*/ "r"(&block[0]) + : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3" + ); + } while (block[2] != 1); +#elif defined (_MIPSEB) + unsigned int block[3] + = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF }; + do { + __asm__ __volatile__( + "move $t0, %0" "\n\t" + "lw $t1, 0($t0)" "\n\t" // p + "lw $t2, 4($t0)" "\n\t" // n + "li $t4, 0x000000FF" "\n\t" + "ll $t3, 0($t1)" "\n\t" + "addu $t3, $t3, $t2" "\n\t" + "and $t3, $t3, $t4" "\n\t" + "wsbh $t4, $t3" "\n\t" + "rotr $t4, $t4, 16" "\n\t" + "or $t3, $t4, $t3" "\n\t" + "sc $t3, 0($t1)" "\n\t" + "sw $t3, 8($t0)" "\n\t" + : /*out*/ + : /*in*/ "r"(&block[0]) + : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3", "t4" + ); + } while (block[2] != 1); +#endif #else # error "Unsupported arch" #endif @@ -203,6 +245,43 @@ __attribute__((noinline)) void atomic_add_16bit ( short* p, int n ) : "+m" (*p), "+m" (dummy) : "d" (n) : "cc", "memory", "0", "1"); +#elif defined(VGA_mips32) +#if defined (_MIPSEL) + unsigned int block[3] + = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF }; + do { + __asm__ __volatile__( + "move $t0, %0" "\n\t" + "lw $t1, 0($t0)" "\n\t" // p + "lw $t2, 4($t0)" "\n\t" // n + "ll $t3, 0($t1)" "\n\t" + "addu $t3, $t3, $t2" "\n\t" + "andi $t3, $t3, 0xFFFF" "\n\t" + "sc $t3, 0($t1)" "\n\t" + "sw $t3, 8($t0)" "\n\t" + : /*out*/ + : /*in*/ "r"(&block[0]) + : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3" + ); + } while (block[2] != 1); +#elif defined (_MIPSEB) + unsigned int block[3] + = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF }; + do { + __asm__ __volatile__( + "move $t0, %0" "\n\t" + "lw $t1, 0($t0)" "\n\t" // p + "li $t2, 32694" "\n\t" // n + "li $t3, 0x1" "\n\t" + "sll $t2, $t2, 16" "\n\t" + "sw $t2, 0($t1)" "\n\t" + "sw $t3, 8($t0)" "\n\t" + : /*out*/ + : /*in*/ "r"(&block[0]) + : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3" + ); + } while (block[2] != 1); +#endif #else # error "Unsupported arch" #endif @@ -289,6 +368,23 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n ) : "+m" (*p) : "d" (n) : "cc", "memory", "0", "1"); +#elif defined(VGA_mips32) + unsigned int block[3] + = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF }; + do { + __asm__ __volatile__( + "move $t0, %0" "\n\t" + "lw $t1, 0($t0)" "\n\t" // p + "lw $t2, 4($t0)" "\n\t" // n + "ll $t3, 0($t1)" "\n\t" + "addu $t3, $t3, $t2" "\n\t" + "sc $t3, 0($t1)" "\n\t" + "sw $t3, 8($t0)" "\n\t" + : /*out*/ + : /*in*/ "r"(&block[0]) + : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3" + ); + } while (block[2] != 1); #else # error "Unsupported arch" #endif @@ -296,7 +392,7 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n ) __attribute__((noinline)) void atomic_add_64bit ( long long int* p, int n ) { -#if defined(VGA_x86) || defined(VGA_ppc32) +#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) /* do nothing; is not supported */ #elif defined(VGA_amd64) // this is a bit subtle. It relies on the fact that, on a 64-bit platform, diff --git a/memcheck/tests/memalign_test.c b/memcheck/tests/memalign_test.c index a9c8784cc8..38e165d425 100644 --- a/memcheck/tests/memalign_test.c +++ b/memcheck/tests/memalign_test.c @@ -10,7 +10,7 @@ int main ( void ) int i; unsigned long pszB = sysconf(_SC_PAGE_SIZE); assert(sizeof(long) == sizeof(void*)); - assert(pszB == 4096 || pszB == 65536); + assert(pszB == 4096 || pszB == 16384 || pszB == 65536); for (i = 0; i < 10; i++) { a[i] = valloc(11111 * (i+1)); diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index 2f16f5b6fc..0fee10d730 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -22,6 +22,9 @@ endif if VGCONF_ARCHS_INCLUDE_S390X SUBDIRS += s390x endif +if VGCONF_ARCHS_INCLUDE_MIPS32 +SUBDIRS += mips32 +endif # OS-specific tests if VGCONF_OS_IS_LINUX @@ -36,7 +39,7 @@ if VGCONF_PLATFORMS_INCLUDE_X86_LINUX SUBDIRS += x86-linux endif -DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x linux darwin x86-linux . +DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x mips32 linux darwin x86-linux . dist_noinst_SCRIPTS = \ filter_cmdline0 \ diff --git a/none/tests/allexec_prepare_prereq b/none/tests/allexec_prepare_prereq index 0cd17382ef..d1fa03c832 100755 --- a/none/tests/allexec_prepare_prereq +++ b/none/tests/allexec_prepare_prereq @@ -32,5 +32,6 @@ pair x86 amd64 pair ppc32 ppc64 pair s390x_unexisting_in_32bits s390x pair arm arm_unexisting_in_64bits +pair mips32 mips_unexisting_in_64bits exit 0 diff --git a/tests/arch_test.c b/tests/arch_test.c index 6f3d944e29..b3740b589e 100644 --- a/tests/arch_test.c +++ b/tests/arch_test.c @@ -29,6 +29,7 @@ char* all_archs[] = { "ppc64", "arm", "s390x", + "mips32", NULL }; @@ -58,6 +59,9 @@ static Bool go(char* arch) #elif defined(VGP_arm_linux) if ( 0 == strcmp( arch, "arm" ) ) return True; +#elif defined(VGP_mips32_linux) + if ( 0 == strcmp( arch, "mips32" ) ) return True; + #else # error Unknown platform #endif // VGP_* diff --git a/tests/platform_test b/tests/platform_test index 7fbf05a342..400fd37341 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" +all_platforms="$all_platforms s390x-linux mips32-linux" all_platforms="$all_platforms x86-darwin amd64-darwin" if [ $# -ne 2 ] ; then diff --git a/tests/sys_mman.h b/tests/sys_mman.h index 7ac64d54c4..c059308c12 100644 --- a/tests/sys_mman.h +++ b/tests/sys_mman.h @@ -21,7 +21,7 @@ static void* get_unmapped_page(void) void* ptr; int r; long pagesz = sysconf(_SC_PAGE_SIZE); - assert(pagesz == 4096 || pagesz == 65536); + assert(pagesz == 4096 || pagesz == 16384 || pagesz == 65536); ptr = mmap(0, pagesz, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); assert(ptr != (void*)-1); r = munmap(ptr, pagesz);