5 #include "../memcheck.h"
8 #include <sys/syscall.h>
10 typedef unsigned int UInt
;
11 typedef unsigned long UWord
;
12 typedef unsigned long long int ULong
;
14 // Below code is copied from m_syscall.c
15 // Refer to this file for syscall convention.
16 #if defined(VGP_x86_linux)
17 extern UWord
do_syscall_WRK (UWord syscall_no
,
18 UWord a1
, UWord a2
, UWord a3
,
19 UWord a4
, UWord a5
, UWord a6
23 ".globl do_syscall_WRK\n"
29 " movl 16+ 4(%esp),%eax\n"
30 " movl 16+ 8(%esp),%ebx\n"
31 " movl 16+12(%esp),%ecx\n"
32 " movl 16+16(%esp),%edx\n"
33 " movl 16+20(%esp),%esi\n"
34 " movl 16+24(%esp),%edi\n"
35 " movl 16+28(%esp),%ebp\n"
45 #elif defined(VGP_amd64_linux)
46 extern UWord
do_syscall_WRK (
48 UWord a1
, UWord a2
, UWord a3
,
49 UWord a4
, UWord a5
, UWord a6
53 ".globl do_syscall_WRK\n"
61 " movq 8(%rsp), %r9\n" /* last arg from stack */
67 #elif defined(VGP_ppc32_linux)
68 extern ULong
do_syscall_WRK (
70 UWord a1
, UWord a2
, UWord a3
,
71 UWord a4
, UWord a5
, UWord a6
75 ".globl do_syscall_WRK\n"
84 " sc\n" /* syscall: sets %cr0.so on error */
85 " mfcr 4\n" /* %cr -> low word of return var */
86 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
87 " blr\n" /* and return */
91 #elif defined(VGP_arm_linux)
92 extern UWord
do_syscall_WRK (
93 UWord a1
, UWord a2
, UWord a3
,
94 UWord a4
, UWord a5
, UWord a6
,
99 ".globl do_syscall_WRK\n"
101 " push {r4, r5, r7}\n"
102 " ldr r4, [sp, #12]\n"
103 " ldr r5, [sp, #16]\n"
104 " ldr r7, [sp, #20]\n"
106 " pop {r4, r5, r7}\n"
111 #elif defined(VGP_s390x_linux)
112 UWord
do_syscall_WRK (
114 UWord arg1
, UWord arg2
, UWord arg3
,
115 UWord arg4
, UWord arg5
, UWord arg6
118 register UWord __arg1
asm("2") = arg1
;
119 register UWord __arg2
asm("3") = arg2
;
120 register UWord __arg3
asm("4") = arg3
;
121 register UWord __arg4
asm("5") = arg4
;
122 register UWord __arg5
asm("6") = arg5
;
123 register UWord __arg6
asm("7") = arg6
;
124 register ULong __svcres
asm("2");
126 __asm__
__volatile__ (
137 : "1", "cc", "memory");
139 return (UWord
) (__svcres
);
142 #elif defined(VGP_mips64_linux)
143 extern UWord
do_syscall_WRK (
145 UWord a1
, UWord a2
, UWord a3
,
146 UWord a4
, UWord a5
, UWord a6
150 __asm__
__volatile__ (
156 "move $8, %6\n\t" /* We use numbers because some compilers */
157 "move $9, %7\n\t" /* don't recognize $a4 and $a5 */
161 : "r"(syscall_no
), "r"(a1
), "r"(a2
), "r"(a3
),
162 "r"(a4
), "r"(a5
), "r"(a6
)
163 : "v0", "v1", "a0", "a1", "a2", "a3", "$8", "$9");
166 #elif defined(VGP_tilegx_linux)
167 extern UWord
do_syscall_WRK (
169 UWord a1
, UWord a2
, UWord a3
,
170 UWord a4
, UWord a5
, UWord a6
174 __asm__
__volatile__ (
185 : "r"(syscall_no
), "r"(a1
), "r"(a2
), "r"(a3
),
186 "r"(a4
), "r"(a5
), "r"(a6
)
187 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r10");
191 #elif defined(VGP_x86_solaris)
193 do_syscall_WRK(UWord a1
, UWord a2
, UWord a3
,
194 UWord a4
, UWord a5
, UWord a6
,
200 ".globl do_syscall_WRK\n"
202 " movl 40(%esp), %ecx\n" /* assume syscall success */
204 " movl 36(%esp), %eax\n"
206 " jnc 1f\n" /* jump if success */
207 " movl 40(%esp), %ecx\n" /* syscall failed - set *errflag */
213 #elif defined(VGP_amd64_solaris)
215 do_syscall_WRK(UWord a1
, UWord a2
, UWord a3
,
216 UWord a4
, UWord a5
, UWord a6
,
222 ".globl do_syscall_WRK\n"
224 " movq %rcx, %r10\n" /* pass rcx in r10 instead */
225 " movq 32(%rsp), %rcx\n" /* assume syscall success */
227 " movq 24(%rsp), %rax\n"
229 " jnc 1f\n" /* jump if success */
230 " movq 32(%rsp), %rcx\n" /* syscall failed - set *errflag */
237 // Ensure the file compiles even if the syscall nr is not defined.
238 #ifndef __NR_mprotect
239 #define __NR_mprotect 0
241 UWord
do_syscall_WRK (UWord syscall_no
,
242 UWord a1
, UWord a2
, UWord a3
,
243 UWord a4
, UWord a5
, UWord a6
246 // not implemented. vgtest prereq should avoid this to be called.
254 int mprotect_result
= 0;
255 static void non_simd_mprotect (long tid
, void* addr
, long len
)
257 #if defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
259 mprotect_result
= do_syscall_WRK((UWord
) addr
, len
, PROT_NONE
,
260 0, 0, 0, 0, 0, SYS_mprotect
,
263 mprotect_result
= -1;
265 mprotect_result
= do_syscall_WRK(__NR_mprotect
,
266 (UWord
) addr
, len
, PROT_NONE
,
274 #define RNDPAGEDOWN(a) ((long)a & ~(pagesize-1))
276 const int nr_ptr
= (10000 * 4)/sizeof(char*);
278 b10
= calloc (nr_ptr
* sizeof(char*), 1);
279 for (i
= 0; i
< nr_ptr
; i
++)
281 b10
[4000] = malloc (1000);
283 fprintf(stderr
, "expecting no leaks\n");
285 VALGRIND_DO_LEAK_CHECK
;
287 // make b10[4000] undefined. This should create a leak.
288 (void) VALGRIND_MAKE_MEM_UNDEFINED (&b10
[4000], sizeof(char*));
289 fprintf(stderr
, "expecting a leak\n");
291 VALGRIND_DO_LEAK_CHECK
;
293 // make b10[4000] defined again.
294 (void) VALGRIND_MAKE_MEM_DEFINED (&b10
[4000], sizeof(char*));
296 // now make some bricolage to have some pages around b10[4000]
297 // unreadable. The leak check should recover from that
298 // thanks to a SEGV handler and a setjmp/longjmp.
299 // This setjmp/longjmp is useful if there is a desync between
300 // the aspacemgr and the real pages mapping.
301 // To have such a discrepancy, we resort on a non SIMD call
302 // to mprotect the pages : as this syscall will not be seen
303 // by Valgrind core, the aspacemgr will not get a chance
304 // to stay synchronised.
305 pagesize
= sysconf(_SC_PAGE_SIZE
);
307 perror ("sysconf failed");
309 if (RUNNING_ON_VALGRIND
)
310 (void) VALGRIND_NON_SIMD_CALL2(non_simd_mprotect
, RNDPAGEDOWN(&b10
[4000]), 2 * pagesize
);
312 mprotect_result
= mprotect((void*) RNDPAGEDOWN(&b10
[4000]), 2 * pagesize
, PROT_NONE
);
313 fprintf(stderr
, "mprotect result %d\n", mprotect_result
);
315 fprintf(stderr
, "expecting a leak again\n");
317 VALGRIND_DO_LEAK_CHECK
;
319 if (RUNNING_ON_VALGRIND
)
320 (void) VALGRIND_NON_SIMD_CALL2(non_simd_mprotect
,
321 RNDPAGEDOWN(&b10
[0]),
322 RNDPAGEDOWN(&(b10
[nr_ptr
-1]))
323 - RNDPAGEDOWN(&(b10
[0])));
325 mprotect_result
= mprotect((void*) RNDPAGEDOWN(&b10
[0]),
326 RNDPAGEDOWN(&(b10
[nr_ptr
-1]))
327 - RNDPAGEDOWN(&(b10
[0])),
329 fprintf(stderr
, "full mprotect result %d\n", mprotect_result
);
331 fprintf(stderr
, "expecting a leak again after full mprotect\n");
333 VALGRIND_DO_LEAK_CHECK
;
335 fprintf(stderr
, "finished\n");
340 DECLARE_LEAK_COUNTERS
;
342 GET_INITIAL_LEAK_COUNTS
;
344 f(); // see leak-cases.c
347 GET_FINAL_LEAK_COUNTS
;
349 PRINT_LEAK_COUNTS(stderr
);