From: Petar Jovanovic Date: Tue, 31 Dec 2019 09:44:42 +0000 (+0000) Subject: mips: Add nanoMIPS support to Valgrind 3/4 X-Git-Tag: VALGRIND_3_16_0~178 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24c1f4ada32ce119dd4b1149c44c5c3d4b7f9b38;p=thirdparty%2Fvalgrind.git mips: Add nanoMIPS support to Valgrind 3/4 Necessary changes to support nanoMIPS on Linux. Part 3/4 - Coregrind and tools changes Patch by Aleksandar Rikalo, Dimitrije Nikolic, Tamara Vlahovic, Nikola Milutinovic and Aleksandra Karadzic. Related KDE issue: #400872. --- diff --git a/Makefile.tool.am b/Makefile.tool.am index 677571fadb..cc2fa0ee6f 100644 --- a/Makefile.tool.am +++ b/Makefile.tool.am @@ -75,6 +75,10 @@ TOOL_LDFLAGS_MIPS32_LINUX = \ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ @FLAG_M32@ +TOOL_LDFLAGS_NANOMIPS_LINUX = \ + -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ + @FLAG_M32@ -Wl,-no-relax + TOOL_LDFLAGS_MIPS64_LINUX = \ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \ @FLAG_M64@ diff --git a/cachegrind/cg_arch.c b/cachegrind/cg_arch.c index 7d03f21ad3..57570dd638 100644 --- a/cachegrind/cg_arch.c +++ b/cachegrind/cg_arch.c @@ -455,7 +455,7 @@ configure_caches(cache_t *I1c, cache_t *D1c, cache_t *LLc, *D1c = (cache_t) { 131072, 8, 256 }; *LLc = (cache_t) { 50331648, 24, 256 }; -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_nanomips) // Set caches to default (for MIPS32-r2(mips 74kc)) *I1c = (cache_t) { 32768, 4, 32 }; diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c index eb7bf99c4f..ba433ec2ce 100644 --- a/cachegrind/cg_branchpred.c +++ b/cachegrind/cg_branchpred.c @@ -43,7 +43,8 @@ /* How many bits at the bottom of an instruction address are guaranteed to be zero? */ #if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ - || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64) + || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \ + || defined(VGA_arm64) # define N_IADDR_LO_ZERO_BITS 2 #elif defined(VGA_x86) || defined(VGA_amd64) # define N_IADDR_LO_ZERO_BITS 0 diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index 7c4c4eb734..0eb3143161 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -2680,7 +2680,7 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot, req.rkind = MAny; req.start = 0; #if defined(VGA_arm) || defined(VGA_arm64) \ - || defined(VGA_mips32) || defined(VGA_mips64) + || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); #else aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE); diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c index fc5da96974..e7aef7fe66 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -1252,6 +1252,10 @@ void VG_(invalidate_icache) ( void *ptr, SizeT nbytes ) (UWord) nbytes, (UWord) 3); vg_assert( !sr_isError(sres) ); +# elif defined(VGA_nanomips) + + __builtin___clear_cache(ptr, (char*)ptr + nbytes); + # endif } diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 4c3e3db177..720fb5f661 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -572,6 +572,22 @@ typedef struct SigQueue { (srP)->misc.MIPS64.r28 = (uc)->uc_mcontext.sc_regs[28]; \ } +#elif defined(VGP_nanomips_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) \ + VG_(mk_SysRes_nanomips_linux)((uc)->uc_mcontext.sc_regs[4]) + +# 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]; \ + } + #elif defined(VGP_x86_solaris) # define VG_UCONTEXT_INSTR_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_EIP]) # define VG_UCONTEXT_STACK_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_UESP]) @@ -985,6 +1001,13 @@ extern void my_sigreturn(void); " syscall\n" \ ".previous\n" +#elif defined(VGP_nanomips_linux) +# define _MY_SIGRETURN(name) \ + ".text\n" \ + "my_sigreturn:\n" \ + " li $t4, " #name "\n" \ + " syscall[32]\n" \ + ".previous\n" #elif defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) /* Not used on Solaris. */ # define _MY_SIGRETURN(name) \ @@ -1084,7 +1107,7 @@ static void handle_SCSS_change ( Bool force_update ) # if !defined(VGP_ppc32_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \ - !defined(VGO_solaris) + !defined(VGP_nanomips_linux) && !defined(VGO_solaris) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); @@ -2174,8 +2197,8 @@ void VG_(synth_sigtrap)(ThreadId tid) // Synthesise a SIGFPE. void VG_(synth_sigfpe)(ThreadId tid, UInt code) { -// Only tested on mips32, mips64, and s390x -#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) +// Only tested on mips32, mips64, s390x and nanomips. +#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) && !defined(VGA_nanomips) vg_assert(0); #else vki_siginfo_t info; @@ -3046,7 +3069,8 @@ void VG_(sigstartup_actions) ( void ) /* Get the old host action */ ret = VG_(sigaction)(i, NULL, &sa); -# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) +# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) \ + || defined(VGP_nanomips_linux) /* apparently we may not even ask about the disposition of these signals, let alone change them */ if (ret != 0 && (i == VKI_SIGKILL || i == VKI_SIGSTOP)) diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c index e4fb70c693..4053d40247 100644 --- a/coregrind/m_syscall.c +++ b/coregrind/m_syscall.c @@ -106,6 +106,13 @@ SysRes VG_(mk_SysRes_SuccessEx) ( UWord res, UWord resEx ) { safely test with -4095. */ +SysRes VG_(mk_SysRes_nanomips_linux) ( UWord a0 ) { + SysRes res; + res._isError = (a0 > 0xFFFFF000ul); + res._val = a0; + return res; +} + SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { SysRes res; res._isError = val >= -4095 && val <= -1; @@ -180,20 +187,30 @@ SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) { } /* Generic constructors. */ +SysRes VG_(mk_SysRes_Success) ( UWord res ) { + SysRes r; + r._isError = False; + r._val = res; + return r; +} + +#if defined(VGP_nanomips_linux) SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes r; r._isError = True; - r._val = err; + r._val = (UWord)(-(Word)err); return r; } - -SysRes VG_(mk_SysRes_Success) ( UWord res ) { +#else +SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes r; - r._isError = False; - r._val = res; + r._isError = True; + r._val = err; return r; } +#endif + #elif defined(VGO_darwin) @@ -824,6 +841,29 @@ asm ( ".previous \n\t" ); +#elif defined(VGP_nanomips_linux) +extern void do_syscall_WRK ( + RegWord a1, RegWord a2, RegWord a3, + RegWord a4, RegWord a5, RegWord a6, + RegWord syscall_no, RegWord *res_a0); +asm ( + ".text \n\t" + ".globl do_syscall_WRK \n\t" + ".type do_syscall_WRK, @function \n\t" + ".set push \n\t" + ".set noreorder \n\t" + "do_syscall_WRK: \n\t" + " save 32, $a7 \n\t" + " move $t4, $a6 \n\t" + " syscall[32] \n\t" + " restore 32, $a7 \n\t" + " sw $a0, 0($a7) \n\t" + " jrc $ra \n\t" + ".size do_syscall_WRK, .-do_syscall_WRK \n\t" + ".set pop \n\t" + ".previous \n\t" +); + #elif defined(VGP_x86_solaris) extern ULong @@ -1039,6 +1079,11 @@ SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3, RegWord A3 = (RegWord)v1_a3[1]; return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 ); +#elif defined(VGP_nanomips_linux) + RegWord reg_a0 = 0; + do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, ®_a0); + return VG_(mk_SysRes_nanomips_linux)(reg_a0); + # elif defined(VGP_x86_solaris) UInt val, val2, err = False; Bool restart; diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index ab96648583..280c48f1b4 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -2733,6 +2733,7 @@ PRE(sys_sync) PRE_REG_READ0(long, "sync"); } +#if !defined(VGP_nanomips_linux) PRE(sys_fstatfs) { FUSE_COMPATIBLE_MAY_BLOCK(); @@ -2760,6 +2761,7 @@ POST(sys_fstatfs64) { POST_MEM_WRITE( ARG3, ARG2 ); } +#endif PRE(sys_getsid) { @@ -3299,6 +3301,7 @@ PRE(sys_fchmod) PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode); } +#if !defined(VGP_nanomips_linux) PRE(sys_newfstat) { FUSE_COMPATIBLE_MAY_BLOCK(); @@ -3311,8 +3314,10 @@ POST(sys_newfstat) { POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); } +#endif -#if !defined(VGO_solaris) && !defined(VGP_arm64_linux) +#if !defined(VGO_solaris) && !defined(VGP_arm64_linux) && \ + !defined(VGP_nanomips_linux) static vki_sigset_t fork_saved_mask; // In Linux, the sys_fork() function varies across architectures, but we @@ -3817,6 +3822,7 @@ PRE(sys_link) PRE_MEM_RASCIIZ( "link(newpath)", ARG2); } +#if !defined(VGP_nanomips_linux) PRE(sys_newlstat) { PRINT("sys_newlstat ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x )", ARG1, @@ -3831,6 +3837,7 @@ POST(sys_newlstat) vg_assert(SUCCESS); POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); } +#endif PRE(sys_mkdir) { @@ -4434,6 +4441,7 @@ PRE(sys_setuid) PRE_REG_READ1(long, "setuid", vki_uid_t, uid); } +#if !defined(VGP_nanomips_linux) PRE(sys_newstat) { FUSE_COMPATIBLE_MAY_BLOCK(); @@ -4476,6 +4484,7 @@ POST(sys_statfs64) { POST_MEM_WRITE( ARG3, ARG2 ); } +#endif PRE(sys_symlink) { diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 6852366dda..87c513a217 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -532,7 +532,7 @@ static SysRes clone_new_thread ( Word (*fn)(void *), ret = do_syscall_clone_nanomips_linux (ML_(start_thread_NORETURN), stack, flags, ctst, child_tidptr, parent_tidptr, NULL); - res = VG_ (mk_SysRes_nanomips_linux) (ret, 0); + res = VG_ (mk_SysRes_nanomips_linux) (ret); #else # error Unknown platform #endif diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 868645e4bc..cdb2663a22 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -1039,8 +1039,7 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, # elif defined(VGP_nanomips_linux) VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; RegWord a0 = gst->guest_r4; // a0 - RegWord a1 = gst->guest_r5; // a1 - canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0, a1); + canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0); canonical->what = SsComplete; # elif defined(VGP_x86_darwin) @@ -1347,11 +1346,8 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid, VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; vg_assert(canonical->what == SsComplete); gst->guest_r4 = canonical->sres._val; - gst->guest_r5 = canonical->sres._valEx; VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, OFFSET_mips32_r4, sizeof(UWord) ); - VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, - OFFSET_mips32_r5, sizeof(UWord) ); # elif defined(VGP_x86_solaris) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; @@ -2480,8 +2476,7 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) vg_assert(p[0] == 0x0A); } -#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ - || defined(VGP_nanomips_linux) +#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) arch->vex.guest_PC -= 4; // sizeof(mips instr) @@ -2513,6 +2508,27 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) # endif } +#elif defined(VGP_nanomips_linux) + { + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + */ + arch->vex.guest_PC -= 2; + /* PC has to be 16-bit aligned. */ + vg_assert((arch->vex.guest_PC & 1) == 0); + + UShort *p = ASSUME_ALIGNED(UShort *, (Addr)(arch->vex.guest_PC)); + + if (((*p) & 0xFFFD) != 0x1008) { + if (((*(p - 1)) & 0xFFFD) != 0x0008) { + VG_(message)(Vg_DebugMsg, + "?! restarting over syscall at %#x %08lx\n", + arch->vex.guest_PC, (UWord)(*p)); + vg_assert(0); + } + arch->vex.guest_PC -= 2; + } + } #elif defined(VGP_x86_solaris) arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall) diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h index 854fca9e2f..49b8586a80 100644 --- a/coregrind/pub_core_syscall.h +++ b/coregrind/pub_core_syscall.h @@ -84,7 +84,7 @@ extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1, UWord a3 ); extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1, ULong a3 ); -extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0, UWord a1 ); +extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0); extern SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 ); extern SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 ); extern SysRes VG_(mk_SysRes_Error) ( UWord val ); diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h index 95253dd6a2..b288bee814 100644 --- a/drd/drd_bitmap.h +++ b/drd/drd_bitmap.h @@ -135,7 +135,8 @@ Addr make_address(const UWord a1, const UWord a0) /** Log2 of BITS_PER_UWORD. */ #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \ - || defined(VGA_mips32) || (defined(VGA_mips64) && defined(VGABI_N32)) + || defined(VGA_mips32) || defined(VGA_nanomips) \ + || (defined(VGA_mips64) && defined(VGABI_N32)) #define BITS_PER_BITS_PER_UWORD 5 #elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ || defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \ diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c index d7b4fdb729..c5b1306a98 100644 --- a/drd/drd_load_store.c +++ b/drd/drd_load_store.c @@ -49,7 +49,7 @@ #define STACK_POINTER_OFFSET OFFSET_arm64_XSP #elif defined(VGA_s390x) #define STACK_POINTER_OFFSET OFFSET_s390x_r15 -#elif defined(VGA_mips32) +#elif defined(VGA_mips32) || defined(VGA_nanomips) #define STACK_POINTER_OFFSET OFFSET_mips32_r29 #elif defined(VGA_mips64) #define STACK_POINTER_OFFSET OFFSET_mips64_r29 diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c index c1031f7229..7a87143b53 100644 --- a/memcheck/mc_machine.c +++ b/memcheck/mc_machine.c @@ -1058,7 +1058,7 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB ) /* --------------------- mips32 --------------------- */ -# elif defined(VGA_mips32) +# elif defined(VGA_mips32) || defined(VGA_nanomips) # define GOF(_fieldname) \ (offsetof(VexGuestMIPS32State,guest_##_fieldname)) @@ -1433,6 +1433,12 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr ) ppIRRegArray(arr); VG_(printf)("\n"); tl_assert(0); +/* --------------------- nanomips ------------------- */ +# elif defined(VGA_nanomips) + VG_(printf)("get_reg_array_equiv_int_type(nanomips): unhandled: "); + ppIRRegArray(arr); + VG_(printf)("\n"); + tl_assert(0); /* --------------------- mips64 --------------------- */ # elif defined(VGA_mips64)