2 /*--------------------------------------------------------------------*/
3 /*--- The address space manager: stuff common to all platforms ---*/
5 /*--- m_aspacemgr-common.c ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Valgrind, a dynamic binary instrumentation
12 Copyright (C) 2006-2013 OpenWorks LLP
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30 The GNU General Public License is contained in the file COPYING.
33 /* *************************************************************
34 DO NOT INCLUDE ANY OTHER FILES HERE.
35 ADD NEW INCLUDES ONLY TO priv_aspacemgr.h
36 AND THEN ONLY AFTER READING DIRE WARNINGS THERE TOO.
37 ************************************************************* */
39 #include "priv_aspacemgr.h"
43 /*-----------------------------------------------------------------*/
45 /*--- Stuff to make aspacem almost completely independent of ---*/
46 /*--- the rest of Valgrind. ---*/
48 /*-----------------------------------------------------------------*/
50 //--------------------------------------------------------------
51 // Simple assert and assert-like fns, which avoid dependence on
52 // m_libcassert, and hence on the entire debug-info reader swamp
54 __attribute__ ((noreturn
))
55 void ML_(am_exit
)( Int status
)
57 VG_(exit_now
) (status
);
60 void ML_(am_barf
) ( const HChar
* what
)
62 VG_(debugLog
)(0, "aspacem", "Valgrind: FATAL: %s\n", what
);
63 VG_(debugLog
)(0, "aspacem", "Exiting now.\n");
67 void ML_(am_barf_toolow
) ( const HChar
* what
)
69 VG_(debugLog
)(0, "aspacem",
70 "Valgrind: FATAL: %s is too low.\n", what
);
71 VG_(debugLog
)(0, "aspacem", " Increase it and rebuild. "
76 void ML_(am_assert_fail
)( const HChar
* expr
,
81 VG_(debugLog
)(0, "aspacem",
82 "Valgrind: FATAL: aspacem assertion failed:\n");
83 VG_(debugLog
)(0, "aspacem", " %s\n", expr
);
84 VG_(debugLog
)(0, "aspacem", " at %s:%d (%s)\n", file
,line
,fn
);
85 VG_(debugLog
)(0, "aspacem", "Exiting now.\n");
89 Int
ML_(am_getpid
)( void )
91 SysRes sres
= VG_(do_syscall0
)(__NR_getpid
);
92 aspacem_assert(!sr_isError(sres
));
97 //--------------------------------------------------------------
98 // A simple sprintf implementation, so as to avoid dependence on
101 static void local_add_to_aspacem_sprintf_buf ( HChar c
, void *p
)
103 HChar
** aspacem_sprintf_ptr
= p
;
104 *(*aspacem_sprintf_ptr
)++ = c
;
108 UInt
local_vsprintf ( HChar
* buf
, const HChar
*format
, va_list vargs
)
111 HChar
*aspacem_sprintf_ptr
= buf
;
113 ret
= VG_(debugLog_vprintf
)
114 ( local_add_to_aspacem_sprintf_buf
,
115 &aspacem_sprintf_ptr
, format
, vargs
);
116 local_add_to_aspacem_sprintf_buf('\0', &aspacem_sprintf_ptr
);
121 UInt
ML_(am_sprintf
) ( HChar
* buf
, const HChar
*format
, ... )
126 va_start(vargs
,format
);
127 ret
= local_vsprintf(buf
, format
, vargs
);
134 //--------------------------------------------------------------
135 // Direct access to a handful of syscalls. This avoids dependence on
136 // m_libc*. THESE DO NOT UPDATE THE aspacem-internal DATA
137 // STRUCTURES (SEGMENT ARRAY). DO NOT USE THEM UNLESS YOU KNOW WHAT
140 /* --- Pertaining to mappings --- */
142 /* Note: this is VG_, not ML_. */
143 SysRes
VG_(am_do_mmap_NO_NOTIFY
)( Addr start
, SizeT length
, UInt prot
,
144 UInt flags
, Int fd
, Off64T offset
)
147 aspacem_assert(VG_IS_PAGE_ALIGNED(offset
));
149 # if defined(VGP_arm64_linux)
150 res
= VG_(do_syscall6
)(__NR3264_mmap
, (UWord
)start
, length
,
151 prot
, flags
, fd
, offset
);
152 # elif defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
153 || defined(VGP_arm_linux)
154 /* mmap2 uses 4096 chunks even if actual page size is bigger. */
155 aspacem_assert((offset
% 4096) == 0);
156 res
= VG_(do_syscall6
)(__NR_mmap2
, (UWord
)start
, length
,
157 prot
, flags
, fd
, offset
/ 4096);
158 # elif defined(VGP_amd64_linux) \
159 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
160 || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
161 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
162 || defined(VGP_tilegx_linux)
163 res
= VG_(do_syscall6
)(__NR_mmap
, (UWord
)start
, length
,
164 prot
, flags
, fd
, offset
);
165 # elif defined(VGP_x86_darwin)
166 if (fd
== 0 && (flags
& VKI_MAP_ANONYMOUS
)) {
167 fd
= -1; // MAP_ANON with fd==0 is EINVAL
169 res
= VG_(do_syscall7
)(__NR_mmap
, (UWord
)start
, length
,
170 prot
, flags
, fd
, offset
& 0xffffffff, offset
>> 32);
171 # elif defined(VGP_amd64_darwin)
172 if (fd
== 0 && (flags
& VKI_MAP_ANONYMOUS
)) {
173 fd
= -1; // MAP_ANON with fd==0 is EINVAL
175 res
= VG_(do_syscall6
)(__NR_mmap
, (UWord
)start
, length
,
176 prot
, flags
, (UInt
)fd
, offset
);
177 # elif defined(VGP_x86_solaris)
178 /* MAP_ANON with fd==0 is EINVAL. */
179 if (fd
== 0 && (flags
& VKI_MAP_ANONYMOUS
))
181 res
= VG_(do_syscall7
)(__NR_mmap64
, (UWord
)start
, length
, prot
, flags
,
182 (UInt
)fd
, offset
& 0xffffffff, offset
>> 32);
183 # elif defined(VGP_amd64_solaris)
184 /* MAP_ANON with fd==0 is EINVAL. */
185 if (fd
== 0 && (flags
& VKI_MAP_ANONYMOUS
))
187 res
= VG_(do_syscall6
)(__NR_mmap
, (UWord
)start
, length
, prot
, flags
,
190 # error Unknown platform
196 SysRes
local_do_mprotect_NO_NOTIFY(Addr start
, SizeT length
, UInt prot
)
198 return VG_(do_syscall3
)(__NR_mprotect
, (UWord
)start
, length
, prot
);
201 SysRes
ML_(am_do_munmap_NO_NOTIFY
)(Addr start
, SizeT length
)
203 return VG_(do_syscall2
)(__NR_munmap
, (UWord
)start
, length
);
207 /* The following are used only to implement mremap(). */
209 SysRes
ML_(am_do_extend_mapping_NO_NOTIFY
)(
215 /* Extend the mapping old_addr .. old_addr+old_len-1 to have length
216 new_len, WITHOUT moving it. If it can't be extended in place,
218 # if defined(VGO_linux)
219 return VG_(do_syscall5
)(
221 old_addr
, old_len
, new_len
,
222 0/*flags, meaning: must be at old_addr, else FAIL */,
223 0/*new_addr, is ignored*/
230 SysRes
ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY
)(
231 Addr old_addr
, Addr old_len
,
232 Addr new_addr
, Addr new_len
235 /* Move the mapping old_addr .. old_addr+old_len-1 to the new
236 location and with the new length. Only needs to handle the case
237 where the two areas do not overlap, neither length is zero, and
238 all args are page aligned. */
239 # if defined(VGO_linux)
240 return VG_(do_syscall5
)(
242 old_addr
, old_len
, new_len
,
243 VKI_MREMAP_MAYMOVE
|VKI_MREMAP_FIXED
/*move-or-fail*/,
253 /* --- Pertaining to files --- */
255 SysRes
ML_(am_open
) ( const HChar
* pathname
, Int flags
, Int mode
)
257 # if defined(VGP_arm64_linux)
258 /* ARM64 wants to use __NR_openat rather than __NR_open. */
259 SysRes res
= VG_(do_syscall4
)(__NR_openat
,
260 VKI_AT_FDCWD
, (UWord
)pathname
, flags
, mode
);
261 # elif defined(VGP_tilegx_linux)
262 SysRes res
= VG_(do_syscall4
)(__NR_openat
, VKI_AT_FDCWD
, (UWord
)pathname
,
264 # elif defined(VGO_linux) || defined(VGO_darwin)
265 SysRes res
= VG_(do_syscall3
)(__NR_open
, (UWord
)pathname
, flags
, mode
);
266 # elif defined(VGO_solaris)
267 SysRes res
= VG_(do_syscall4
)(__NR_openat
, VKI_AT_FDCWD
, (UWord
)pathname
,
275 Int
ML_(am_read
) ( Int fd
, void* buf
, Int count
)
277 SysRes res
= VG_(do_syscall3
)(__NR_read
, fd
, (UWord
)buf
, count
);
278 return sr_isError(res
) ? -1 : sr_Res(res
);
281 void ML_(am_close
) ( Int fd
)
283 (void)VG_(do_syscall1
)(__NR_close
, fd
);
286 Int
ML_(am_readlink
)(const HChar
* path
, HChar
* buf
, UInt bufsiz
)
289 # if defined(VGP_arm64_linux)
290 res
= VG_(do_syscall4
)(__NR_readlinkat
, VKI_AT_FDCWD
,
291 (UWord
)path
, (UWord
)buf
, bufsiz
);
292 # elif defined(VGP_tilegx_linux)
293 res
= VG_(do_syscall4
)(__NR_readlinkat
, VKI_AT_FDCWD
, (UWord
)path
,
295 # elif defined(VGO_linux) || defined(VGO_darwin)
296 res
= VG_(do_syscall3
)(__NR_readlink
, (UWord
)path
, (UWord
)buf
, bufsiz
);
297 # elif defined(VGO_solaris)
298 res
= VG_(do_syscall4
)(__NR_readlinkat
, VKI_AT_FDCWD
, (UWord
)path
,
303 return sr_isError(res
) ? -1 : sr_Res(res
);
306 Int
ML_(am_fcntl
) ( Int fd
, Int cmd
, Addr arg
)
308 # if defined(VGO_linux) || defined(VGO_solaris)
309 SysRes res
= VG_(do_syscall3
)(__NR_fcntl
, fd
, cmd
, arg
);
310 # elif defined(VGO_darwin)
311 SysRes res
= VG_(do_syscall3
)(__NR_fcntl_nocancel
, fd
, cmd
, arg
);
315 return sr_isError(res
) ? -1 : sr_Res(res
);
318 /* Get the dev, inode and mode info for a file descriptor, if
319 possible. Returns True on success. */
320 Bool
ML_(am_get_fd_d_i_m
)( Int fd
,
322 /*OUT*/ULong
* ino
, /*OUT*/UInt
* mode
)
324 # if defined(VGO_linux) || defined(VGO_darwin)
327 # if defined(VGO_linux) && defined(__NR_fstat64)
328 /* Try fstat64 first as it can cope with minor and major device
329 numbers outside the 0-255 range and it works properly for x86
330 binaries on amd64 systems where fstat seems to be broken. */
331 struct vki_stat64 buf64
;
332 res
= VG_(do_syscall2
)(__NR_fstat64
, fd
, (UWord
)&buf64
);
333 if (!sr_isError(res
)) {
334 *dev
= (ULong
)buf64
.st_dev
;
335 *ino
= (ULong
)buf64
.st_ino
;
336 *mode
= (UInt
) buf64
.st_mode
;
340 res
= VG_(do_syscall2
)(__NR_fstat
, fd
, (UWord
)&buf
);
341 if (!sr_isError(res
)) {
342 *dev
= (ULong
)buf
.st_dev
;
343 *ino
= (ULong
)buf
.st_ino
;
344 *mode
= (UInt
) buf
.st_mode
;
348 # elif defined(VGO_solaris)
349 # if defined(VGP_x86_solaris)
350 struct vki_stat64 buf64
;
351 SysRes res
= VG_(do_syscall4
)(__NR_fstatat64
, fd
, 0, (UWord
)&buf64
, 0);
352 # elif defined(VGP_amd64_solaris)
353 struct vki_stat buf64
;
354 SysRes res
= VG_(do_syscall4
)(__NR_fstatat
, fd
, 0, (UWord
)&buf64
, 0);
356 # error "Unknown platform"
358 if (!sr_isError(res
)) {
359 *dev
= (ULong
)buf64
.st_dev
;
360 *ino
= (ULong
)buf64
.st_ino
;
361 *mode
= (UInt
) buf64
.st_mode
;
370 Bool
ML_(am_resolve_filename
) ( Int fd
, /*OUT*/HChar
* buf
, Int nbuf
)
372 #if defined(VGO_linux)
374 HChar tmp
[64]; // large enough
375 for (i
= 0; i
< nbuf
; i
++) buf
[i
] = 0;
376 ML_(am_sprintf
)(tmp
, "/proc/self/fd/%d", fd
);
377 if (ML_(am_readlink
)(tmp
, buf
, nbuf
) > 0 && buf
[0] == '/')
382 #elif defined(VGO_darwin)
383 HChar tmp
[VKI_MAXPATHLEN
+1];
384 if (0 == ML_(am_fcntl
)(fd
, VKI_F_GETPATH
, (UWord
)tmp
)) {
386 VG_(strncpy
)( buf
, tmp
, nbuf
< sizeof(tmp
) ? nbuf
: sizeof(tmp
) );
389 if (tmp
[0] == '/') return True
;
393 #elif defined(VGO_solaris)
396 for (i
= 0; i
< nbuf
; i
++) buf
[i
] = 0;
397 ML_(am_sprintf
)(tmp
, "/proc/self/path/%d", fd
);
398 if (ML_(am_readlink
)(tmp
, buf
, nbuf
) > 0 && buf
[0] == '/')
411 /*-----------------------------------------------------------------*/
413 /*--- Manage stacks for Valgrind itself. ---*/
415 /*-----------------------------------------------------------------*/
418 // We use a fake size of 1. A bigger size is allocated
419 // by VG_(am_alloc_VgStack).
422 /* Allocate and initialise a VgStack (anonymous valgrind space).
423 Protect the stack active area and the guard areas appropriately.
424 Returns NULL on failure, else the address of the bottom of the
425 stack. On success, also sets *initial_sp to what the stack pointer
428 VgStack
* VG_(am_alloc_VgStack
)( /*OUT*/Addr
* initial_sp
)
436 /* Allocate the stack. */
437 szB
= VG_STACK_GUARD_SZB
438 + VG_(clo_valgrind_stacksize
) + VG_STACK_GUARD_SZB
;
440 sres
= VG_(am_mmap_anon_float_valgrind
)( szB
);
441 if (sr_isError(sres
))
444 stack
= (VgStack
*)(Addr
)sr_Res(sres
);
446 aspacem_assert(VG_IS_PAGE_ALIGNED(szB
));
447 aspacem_assert(VG_IS_PAGE_ALIGNED(stack
));
449 /* Protect the guard areas. */
450 sres
= local_do_mprotect_NO_NOTIFY(
452 VG_STACK_GUARD_SZB
, VKI_PROT_NONE
454 if (sr_isError(sres
)) goto protect_failed
;
455 VG_(am_notify_mprotect
)(
456 (Addr
) &stack
->bytes
[0],
457 VG_STACK_GUARD_SZB
, VKI_PROT_NONE
460 sres
= local_do_mprotect_NO_NOTIFY(
461 (Addr
) &stack
->bytes
[VG_STACK_GUARD_SZB
+ VG_(clo_valgrind_stacksize
)],
462 VG_STACK_GUARD_SZB
, VKI_PROT_NONE
464 if (sr_isError(sres
)) goto protect_failed
;
465 VG_(am_notify_mprotect
)(
466 (Addr
) &stack
->bytes
[VG_STACK_GUARD_SZB
+ VG_(clo_valgrind_stacksize
)],
467 VG_STACK_GUARD_SZB
, VKI_PROT_NONE
470 /* Looks good. Fill the active area with junk so we can later
471 tell how much got used. */
473 p
= (UInt
*)&stack
->bytes
[VG_STACK_GUARD_SZB
];
474 for (i
= 0; i
< VG_(clo_valgrind_stacksize
)/sizeof(UInt
); i
++)
477 *initial_sp
= (Addr
)&stack
->bytes
[VG_STACK_GUARD_SZB
+ VG_(clo_valgrind_stacksize
)];
479 *initial_sp
&= ~((Addr
)0x1F); /* 32-align it */
481 VG_(debugLog
)( 1,"aspacem",
482 "allocated valgrind thread stack at 0x%llx size %d\n",
483 (ULong
)(Addr
)stack
, szB
);
484 ML_(am_do_sanity_check
)();
488 /* The stack was allocated, but we can't protect it. Unmap it and
489 return NULL (failure). */
490 (void)ML_(am_do_munmap_NO_NOTIFY
)( (Addr
)stack
, szB
);
491 ML_(am_do_sanity_check
)();
496 /* Figure out how many bytes of the stack's active area have not
497 been used. Used for estimating if we are close to overflowing it. */
499 SizeT
VG_(am_get_VgStack_unused_szB
)( const VgStack
* stack
, SizeT limit
)
504 p
= (const UInt
*)&stack
->bytes
[VG_STACK_GUARD_SZB
];
505 for (i
= 0; i
< VG_(clo_valgrind_stacksize
)/sizeof(UInt
); i
++) {
506 if (p
[i
] != 0xDEADBEEF)
508 if (i
* sizeof(UInt
) >= limit
)
512 return i
* sizeof(UInt
);
516 /*--------------------------------------------------------------------*/
518 /*--------------------------------------------------------------------*/