bc3db65a16089be2bc7959d4667e69900429463c
[native_client/nacl-glibc.git] / sysdeps / nacl / nacl_dyncode_valgrind.c
1
2 #include <nacl_dyncode_valgrind.h>
3 #include <nacl_valgrind.h>
4 #include <sys/mman.h>
5
6 #define VG_USERREQ__NACL_MMAP 0x3107
7
8
9 /* Update Valgrind's idea of the nexe's memory layout. Intentionally empty. When
10    running under Valgrind, calls to this function are replaced with calls to the
11    wrapper function (see below).
12    It's important that both functions are visible in the ld.so symbol table.
13
14    Clone_mapping is an address of some other mmap-ed region of the same file. If
15    not NULL, Valgrind will use it to find the binary. */
16 void __nacl_dyncode_map_for_valgrind (
17     void *vma __attribute__((unused)),
18     size_t size __attribute__((unused)),
19     size_t file_offset __attribute__((unused)),
20     void *clone_mapping __attribute__((unused))) {}
21
22
23 void __nacl_data_map_for_valgrind (
24     void *vma __attribute__((unused)),
25     size_t size __attribute__((unused)),
26     size_t file_offset __attribute__((unused)),
27     int fd __attribute__((unused)),
28     int prot __attribute__((unused))) {}
29
30 /* Valgrind wrapper for NaClDyncodeMapForValgrind. This function is only
31    executed if running under Valgrind. */
32 void I_WRAP_SONAME_FNNAME_ZZ(NaClZuZa, ZuZunaclZudyncodeZumapZuforZuvalgrind) (
33     void *vma, size_t size, size_t file_offset, void *clone_mapping) {
34   int res;
35   VALGRIND_DO_CLIENT_REQUEST (res, 0, VG_USERREQ__NACL_MMAP,
36       VALGRIND_SANDBOX_PTR ((size_t)vma),
37       size, file_offset, PROT_READ | PROT_EXEC,
38       VALGRIND_SANDBOX_PTR ((size_t)clone_mapping));
39   (void)res;
40 }
41
42 void I_WRAP_SONAME_FNNAME_ZZ(NaClZuZa, ZuZunaclZudataZumapZuforZuvalgrind) (
43     void *vma, size_t size, size_t file_offset, int fd, int prot) {
44   int res;
45   /* We can not just pass the file descriptor to Valgrind, because their values
46      are different between trusted and untrusted code. Therefore, we create a
47      temporary mapping of the same file and let Valgrind find the file name
48      by examining this mapping. We use PROT_NONE so that Valgrind does not
49      confuse it with the actual RO or RW mapping of the same binary. */
50   size_t alignment_padding = file_offset & (getpagesize() - 1);
51   uint8_t *clone_mapping = __mmap (NULL, getpagesize(),
52                              PROT_NONE, MAP_PRIVATE, fd,
53                              file_offset - alignment_padding);
54   if (clone_mapping == MAP_FAILED)
55     return;
56
57   VALGRIND_DO_CLIENT_REQUEST (res, 0, VG_USERREQ__NACL_MMAP,
58       VALGRIND_SANDBOX_PTR ((size_t)vma),
59       size, file_offset, prot,
60       VALGRIND_SANDBOX_PTR ((size_t)clone_mapping));
61
62   __munmap (clone_mapping, getpagesize());
63   (void)res;
64 }