1 
2 /*--------------------------------------------------------------------*/
3 /*--- Process-related libc stuff.                     m_libcproc.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2000-2015 Julian Seward
11       jseward@acm.org
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26    02111-1307, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 #include "pub_core_basics.h"
32 #include "pub_core_machine.h"    // For VG_(machine_get_VexArchInfo)
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h"
37 #include "pub_core_libcfile.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcproc.h"
40 #include "pub_core_libcsignal.h"
41 #include "pub_core_seqmatch.h"
42 #include "pub_core_mallocfree.h"
43 #include "pub_core_syscall.h"
44 #include "pub_core_xarray.h"
45 #include "pub_core_clientstate.h"
46 
47 #if defined(VGO_darwin)
48 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
49 #include <mach/mach.h>   /* mach_thread_self */
50 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
51 #endif
52 
53 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
54    of syscalls rather than the vanilla version, if a _nocancel version
55    is available.  See docs/internals/Darwin-notes.txt for the reason
56    why. */
57 
58 /* ---------------------------------------------------------------------
59    Command line and environment stuff
60    ------------------------------------------------------------------ */
61 
62 /* As deduced from sp_at_startup, the client's argc, argv[] and
63    envp[] as extracted from the client's stack at startup-time. */
64 HChar** VG_(client_envp) = NULL;
65 
66 /* Path to library directory */
67 const HChar *VG_(libdir) = VG_LIBDIR;
68 
69 const HChar *VG_(LD_PRELOAD_var_name) =
70 #if defined(VGO_linux) || defined(VGO_solaris)
71    "LD_PRELOAD";
72 #elif defined(VGO_darwin)
73    "DYLD_INSERT_LIBRARIES";
74 #else
75 #  error Unknown OS
76 #endif
77 
78 /* We do getenv without libc's help by snooping around in
79    VG_(client_envp) as determined at startup time. */
VG_(getenv)80 HChar *VG_(getenv)(const HChar *varname)
81 {
82    Int i, n;
83    vg_assert( VG_(client_envp) );
84    n = VG_(strlen)(varname);
85    for (i = 0; VG_(client_envp)[i] != NULL; i++) {
86       HChar* s = VG_(client_envp)[i];
87       if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
88          return & s[n+1];
89       }
90    }
91    return NULL;
92 }
93 
94 /* If free_fn is not NULL, it is called on "unset" environment variable. */
VG_(env_unsetenv)95 void  VG_(env_unsetenv) ( HChar **env, const HChar *varname,
96                           void (*free_fn) (void *) )
97 {
98    HChar **from, **to;
99    vg_assert(env);
100    vg_assert(varname);
101    to = NULL;
102    Int len = VG_(strlen)(varname);
103 
104    for (from = to = env; from && *from; from++) {
105       if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
106 	 *to = *from;
107 	 to++;
108       } else if (free_fn != NULL) {
109          free_fn(*from);
110       }
111    }
112    *to = *from;
113 }
114 
115 /* set the environment; returns the old env if a new one was allocated */
VG_(env_setenv)116 HChar **VG_(env_setenv) ( HChar ***envp, const HChar* varname,
117                           const HChar *val )
118 {
119    HChar **env = (*envp);
120    HChar **cpp;
121    Int len = VG_(strlen)(varname);
122    HChar *valstr = VG_(malloc)("libcproc.es.1", len + VG_(strlen)(val) + 2);
123    HChar **oldenv = NULL;
124 
125    VG_(sprintf)(valstr, "%s=%s", varname, val);
126 
127    for (cpp = env; cpp && *cpp; cpp++) {
128       if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
129 	 *cpp = valstr;
130 	 return oldenv;
131       }
132    }
133 
134    if (env == NULL) {
135       env = VG_(malloc)("libcproc.es.2", sizeof(HChar *) * 2);
136       env[0] = valstr;
137       env[1] = NULL;
138 
139       *envp = env;
140 
141    }  else {
142       Int envlen = (cpp-env) + 2;
143       HChar **newenv = VG_(malloc)("libcproc.es.3", envlen * sizeof(HChar *));
144 
145       for (cpp = newenv; *env; )
146 	 *cpp++ = *env++;
147       *cpp++ = valstr;
148       *cpp++ = NULL;
149 
150       oldenv = *envp;
151 
152       *envp = newenv;
153    }
154 
155    return oldenv;
156 }
157 
158 
159 /* Walk through a colon-separated environment variable, and remove the
160    entries which match remove_pattern.  It slides everything down over
161    the removed entries, and pads the remaining space with '\0'.  It
162    modifies the entries in place (in the client address space), but it
163    shouldn't matter too much, since we only do this just before an
164    execve().
165 
166    This is also careful to mop up any excess ':'s, since empty strings
167    delimited by ':' are considered to be '.' in a path.
168 */
mash_colon_env(HChar * varp,const HChar * remove_pattern)169 static void mash_colon_env(HChar *varp, const HChar *remove_pattern)
170 {
171    HChar *const start = varp;
172    HChar *entry_start = varp;
173    HChar *output = varp;
174 
175    if (varp == NULL)
176       return;
177 
178    while(*varp) {
179       if (*varp == ':') {
180 	 HChar prev;
181 	 Bool match;
182 
183 	 /* This is a bit subtle: we want to match against the entry
184 	    we just copied, because it may have overlapped with
185 	    itself, junking the original. */
186 
187 	 prev = *output;
188 	 *output = '\0';
189 
190 	 match = VG_(string_match)(remove_pattern, entry_start);
191 
192 	 *output = prev;
193 
194 	 if (match) {
195 	    output = entry_start;
196 	    varp++;			/* skip ':' after removed entry */
197 	 } else
198 	    entry_start = output+1;	/* entry starts after ':' */
199       }
200 
201       if (*varp)
202          *output++ = *varp++;
203    }
204 
205    /* make sure last entry is nul terminated */
206    *output = '\0';
207 
208    /* match against the last entry */
209    if (VG_(string_match)(remove_pattern, entry_start)) {
210       output = entry_start;
211       if (output > start) {
212 	 /* remove trailing ':' */
213 	 output--;
214 	 vg_assert(*output == ':');
215       }
216    }
217 
218    /* pad out the left-overs with '\0' */
219    while(output < varp)
220       *output++ = '\0';
221 }
222 
223 
224 /* Removes all the Valgrind-added stuff from the passed environment.  Used
225    when starting child processes, so they don't see that added stuff.
226    If the ro_strings option is set to True then all strings referenced by envp
227    are considered read-only, which means they will be duplicated before they
228    are modified.
229    If free_fn is not NULL, it is called on "unset" environment variables. */
VG_(env_remove_valgrind_env_stuff)230 void VG_(env_remove_valgrind_env_stuff)(HChar** envp, Bool ro_strings,
231                                         void (*free_fn) (void *) )
232 {
233    Int i;
234    HChar* ld_preload_str = NULL;
235    HChar* ld_library_path_str = NULL;
236    HChar* dyld_insert_libraries_str = NULL;
237    HChar* buf;
238 
239    // Find LD_* variables
240    // DDD: should probably conditionally compiled some of this:
241    // - LD_LIBRARY_PATH is universal?
242    // - LD_PRELOAD is on Linux, not on Darwin, not sure about AIX
243    // - DYLD_INSERT_LIBRARIES and DYLD_SHARED_REGION are Darwin-only
244    for (i = 0; envp[i] != NULL; i++) {
245       if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
246          if (ro_strings)
247             envp[i] = VG_(strdup)("libcproc.erves.1", envp[i]);
248          ld_preload_str = &envp[i][11];
249       }
250       if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0) {
251          if (ro_strings)
252             envp[i] = VG_(strdup)("libcproc.erves.2", envp[i]);
253          ld_library_path_str = &envp[i][16];
254       }
255       if (VG_(strncmp)(envp[i], "DYLD_INSERT_LIBRARIES=", 22) == 0) {
256          if (ro_strings)
257             envp[i] = VG_(strdup)("libcproc.erves.3", envp[i]);
258          dyld_insert_libraries_str = &envp[i][22];
259       }
260    }
261 
262    buf = VG_(malloc)("libcproc.erves.4", VG_(strlen)(VG_(libdir)) + 20);
263 
264    // Remove Valgrind-specific entries from LD_*.
265    VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
266    mash_colon_env(ld_preload_str, buf);
267    mash_colon_env(dyld_insert_libraries_str, buf);
268    VG_(sprintf)(buf, "%s*", VG_(libdir));
269    mash_colon_env(ld_library_path_str, buf);
270 
271    // Remove VALGRIND_LAUNCHER variable.
272    VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER, free_fn);
273 
274    // Remove DYLD_SHARED_REGION variable.
275    VG_(env_unsetenv)(envp, "DYLD_SHARED_REGION", free_fn);
276 
277    // XXX if variable becomes empty, remove it completely?
278 
279    VG_(free)(buf);
280 }
281 
282 /* Resolves filename of VG_(cl_exec_fd) and copies it to the buffer.
283    Buffer must not be NULL and buf_size must be at least 1.
284    If buffer is not large enough it is terminated with '\0' only
285    when 'terminate_with_NUL == True'. */
VG_(client_fname)286 void VG_(client_fname)(HChar *buffer, SizeT buf_size, Bool terminate_with_NUL)
287 {
288    vg_assert(buffer != NULL);
289    vg_assert(buf_size >= 1);
290 
291    const HChar *name;
292    if (VG_(resolve_filename)(VG_(cl_exec_fd), &name)) {
293       const HChar *n = name + VG_(strlen)(name) - 1;
294 
295       while (n > name && *n != '/')
296          n--;
297       if (n != name)
298          n++;
299 
300       VG_(strncpy)(buffer, n, buf_size);
301       if (terminate_with_NUL)
302          buffer[buf_size - 1] = '\0';
303    } else {
304       buffer[0] = '\0';
305    }
306 }
307 
add_string(HChar * buffer,SizeT * buf_size,const HChar * string)308 static Bool add_string(HChar *buffer, SizeT *buf_size, const HChar *string)
309 {
310    SizeT len = VG_(strlen)(string);
311    VG_(strncat)(buffer, string, *buf_size);
312    if (len >= *buf_size - 1) {
313       *buf_size = 0;
314       return False;
315    } else {
316       *buf_size -= len;
317       return True;
318    }
319 }
320 
321 /* Concatenates client exename and command line arguments into
322    the buffer. Buffer must not be NULL and buf_size must be
323    at least 1. Buffer is always terminated with '\0'. */
VG_(client_cmd_and_args)324 void VG_(client_cmd_and_args)(HChar *buffer, SizeT buf_size)
325 {
326    vg_assert(buffer != NULL);
327    vg_assert(buf_size >= 1);
328 
329    buffer[0] = '\0';
330 
331    if (add_string(buffer, &buf_size, VG_(args_the_exename)) == False)
332       return;
333 
334    Int i;
335    for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++) {
336       if (add_string(buffer, &buf_size, " ") == False)
337          return;
338 
339       HChar *arg = *(HChar **) VG_(indexXA)(VG_(args_for_client), i);
340       if (add_string(buffer, &buf_size, arg) == False)
341          return;
342    }
343 }
344 
345 /* ---------------------------------------------------------------------
346    Various important syscall wrappers
347    ------------------------------------------------------------------ */
348 
VG_(waitpid)349 Int VG_(waitpid)(Int pid, Int *status, Int options)
350 {
351 #  if defined(VGO_linux)
352    SysRes res = VG_(do_syscall4)(__NR_wait4,
353                                  pid, (UWord)status, options, 0);
354    return sr_isError(res) ? -1 : sr_Res(res);
355 #  elif defined(VGO_darwin)
356    SysRes res = VG_(do_syscall4)(__NR_wait4_nocancel,
357                                  pid, (UWord)status, options, 0);
358    return sr_isError(res) ? -1 : sr_Res(res);
359 #  elif defined(VGO_solaris)
360    SysRes res;
361    vki_idtype_t idtype;
362    vki_id_t id;
363    vki_siginfo_t info;
364 
365    /* We need to do a lot of work here. */
366 
367    if (pid > 0) {
368       idtype = VKI_P_PID;
369       id = pid;
370    }
371    else if (pid < -1) {
372       idtype = VKI_P_PGID;
373       id = -pid;
374    }
375    else if (pid == -1) {
376       idtype = VKI_P_ALL;
377       id = 0;
378    }
379    else {
380       idtype = VKI_P_PGID;
381       res = VG_(do_syscall0)(__NR_getpid);
382       id = sr_ResHI(res);
383    }
384 
385    options |= VKI_WEXITED | VKI_WTRAPPED;
386 
387    res = VG_(do_syscall4)(__NR_waitsys, idtype, id, (UWord)&info, options);
388    if (sr_isError(res))
389       return -1;
390 
391    if (status) {
392       Int s = info.si_status & 0xff;
393 
394       switch (info.si_code) {
395          case VKI_CLD_EXITED:
396             s <<= 8;
397             break;
398          case VKI_CLD_DUMPED:
399             s |= VKI_WCOREFLG;
400             break;
401          case VKI_CLD_KILLED:
402             break;
403          case VKI_CLD_TRAPPED:
404          case VKI_CLD_STOPPED:
405             s <<= 8;
406             s |= VKI_WSTOPFLG;
407             break;
408          case VKI_CLD_CONTINUED:
409             s = VKI_WCONTFLG;
410             break;
411       }
412       *status = s;
413    }
414 
415    return info.si_pid;
416 #  else
417 #    error Unknown OS
418 #  endif
419 }
420 
421 /* clone the environment */
VG_(env_clone)422 HChar **VG_(env_clone) ( HChar **oldenv )
423 {
424    HChar **oldenvp;
425    HChar **newenvp;
426    HChar **newenv;
427    Int  envlen;
428 
429    vg_assert(oldenv);
430    for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
431 
432    envlen = oldenvp - oldenv + 1;
433 
434    newenv = VG_(malloc)("libcproc.ec.1", envlen * sizeof(HChar *));
435 
436    oldenvp = oldenv;
437    newenvp = newenv;
438 
439    while (oldenvp && *oldenvp) {
440       *newenvp++ = *oldenvp++;
441    }
442 
443    *newenvp = *oldenvp;
444 
445    return newenv;
446 }
447 
VG_(execv)448 void VG_(execv) ( const HChar* filename, const HChar** argv )
449 {
450    HChar** envp;
451    SysRes res;
452 
453    /* restore the DATA rlimit for the child */
454    VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
455 
456    envp = VG_(env_clone)(VG_(client_envp));
457    VG_(env_remove_valgrind_env_stuff)( envp, True /*ro_strings*/, NULL );
458 
459    res = VG_(do_syscall3)(__NR_execve,
460                           (UWord)filename, (UWord)argv, (UWord)envp);
461 
462    VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res));
463 }
464 
465 /* Spawns a new child. Uses either spawn syscall or fork+execv combo. */
VG_(spawn)466 Int VG_(spawn) ( const HChar *filename, const HChar **argv )
467 {
468    vg_assert(filename != NULL);
469    vg_assert(argv != NULL);
470 
471 #  if defined(VGO_solaris) && defined(SOLARIS_SPAWN_SYSCALL)
472    HChar **envp = VG_(env_clone)(VG_(client_envp));
473    for (HChar **p = envp; *p != NULL; p++) {
474       *p = VG_(strdup)("libcproc.s.1", *p);
475    }
476    VG_(env_remove_valgrind_env_stuff)(envp, /* ro_strings */ False, VG_(free));
477 
478    /* Now combine argv and argp into argenv. */
479    SizeT argenv_size = 1 + 1;
480    for (const HChar **p = argv; *p != NULL; p++) {
481       argenv_size += VG_(strlen)(*p) + 2;
482    }
483    for (HChar **p = envp; *p != NULL; p++) {
484       argenv_size += VG_(strlen)(*p) + 2;
485    }
486 
487    HChar *argenv = VG_(malloc)("libcproc.s.2", argenv_size);
488    HChar *current = argenv;
489 #  define COPY_CHAR_TO_ARGENV(dst, character)  \
490       do {                                     \
491          *(dst) = character;                   \
492          (dst) += 1;                           \
493       } while (0)
494 #  define COPY_STRING_TO_ARGENV(dst, src)        \
495       do {                                       \
496          COPY_CHAR_TO_ARGENV(dst, '\1');         \
497          SizeT src_len = VG_(strlen)((src)) + 1; \
498          VG_(memcpy)((dst), (src), src_len);     \
499          (dst) += src_len;                       \
500       } while (0)
501 
502    for (const HChar **p = argv; *p != NULL; p++) {
503       COPY_STRING_TO_ARGENV(current, *p);
504    }
505    COPY_CHAR_TO_ARGENV(current, '\0');
506    for (HChar **p = envp; *p != NULL; p++) {
507       COPY_STRING_TO_ARGENV(current, *p);
508    }
509    COPY_CHAR_TO_ARGENV(current, '\0');
510    vg_assert(current == argenv + argenv_size);
511 #  undef COPY_CHAR_TO_ARGENV
512 #  undef COPY_STRING_TOARGENV
513 
514    /* HACK: Temporarily restore the DATA rlimit for spawned child. */
515    VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
516 
517    SysRes res = VG_(do_syscall5)(__NR_spawn, (UWord) filename, (UWord) NULL, 0,
518                                  (UWord) argenv, argenv_size);
519 
520    /* Restore DATA rlimit back to its previous value set in m_main.c. */
521    struct vki_rlimit zero = { 0, 0 };
522    zero.rlim_max = VG_(client_rlimit_data).rlim_max;
523    VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
524 
525    VG_(free)(argenv);
526    for (HChar **p = envp; *p != NULL; p++) {
527       VG_(free)(*p);
528    }
529    VG_(free)(envp);
530 
531    if (sr_isError(res))
532       return -1;
533    return sr_Res(res);
534 
535 #  else
536 
537    Int pid = VG_(fork)();
538    if (pid < 0)
539       return -1;
540    if (pid == 0) {
541       /* child */
542       VG_(execv)(argv[0], argv);
543 
544       /* If we're still alive here, execv failed. */
545       VG_(exit)(1);
546    } else {
547       return pid;
548    }
549 #  endif /* VGO_solaris && SOLARIS_SPAWN_SYSCALL */
550 }
551 
552 /* Return -1 if error, else 0.  NOTE does not indicate return code of
553    child! */
VG_(system)554 Int VG_(system) ( const HChar* cmd )
555 {
556    Int pid;
557    if (cmd == NULL)
558       return 1;
559 
560    const HChar *argv[4] = { "/bin/sh", "-c", cmd, 0 };
561    pid = VG_(spawn)(argv[0], argv);
562    if (pid < 0)
563       return -1;
564 
565    vg_assert(pid > 0);
566    /* parent */
567    /* We have to set SIGCHLD to its default behaviour in order that
568       VG_(waitpid) works (at least on AIX).  According to the Linux
569       man page for waitpid:
570 
571       POSIX.1-2001 specifies that if the disposition of SIGCHLD is
572       set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD
573       (see sigaction(2)), then children that terminate do not
574       become zombies and a call to wait() or waitpid() will block
575       until all children have terminated, and then fail with errno
576       set to ECHILD.  (The original POSIX standard left the
577       behaviour of setting SIGCHLD to SIG_IGN unspecified.)
578    */
579    Int ir, zzz;
580    vki_sigaction_toK_t sa, sa2;
581    vki_sigaction_fromK_t saved_sa;
582    VG_(memset)( &sa, 0, sizeof(sa) );
583    VG_(sigemptyset)(&sa.sa_mask);
584    sa.ksa_handler = VKI_SIG_DFL;
585    sa.sa_flags    = 0;
586    ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
587    vg_assert(ir == 0);
588 
589    zzz = VG_(waitpid)(pid, NULL, 0);
590 
591    VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 );
592    ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL);
593    vg_assert(ir == 0);
594    return zzz == -1 ? -1 : 0;
595 }
596 
VG_(sysctl)597 Int VG_(sysctl)(Int *name, UInt namelen, void *oldp, SizeT *oldlenp, void *newp, SizeT newlen)
598 {
599    SysRes res;
600 #  if defined(VGO_darwin)
601    res = VG_(do_syscall6)(__NR___sysctl,
602                            (UWord)name, namelen, (UWord)oldp, (UWord)oldlenp, (UWord)newp, newlen);
603 #  else
604    res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
605 #  endif
606    return sr_isError(res) ? -1 : sr_Res(res);
607 }
608 
609 /* ---------------------------------------------------------------------
610    Resource limits
611    ------------------------------------------------------------------ */
612 
613 /* Support for getrlimit. */
VG_(getrlimit)614 Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
615 {
616    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
617    /* res = getrlimit( resource, rlim ); */
618 #  ifdef __NR_ugetrlimit
619    res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
620 #  endif
621    if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
622       res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
623    return sr_isError(res) ? -1 : sr_Res(res);
624 }
625 
626 
627 /* Support for setrlimit. */
VG_(setrlimit)628 Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
629 {
630    SysRes res;
631    /* res = setrlimit( resource, rlim ); */
632    res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
633    return sr_isError(res) ? -1 : sr_Res(res);
634 }
635 
636 /* Support for prctl. */
VG_(prctl)637 Int VG_(prctl) (Int option,
638                 ULong arg2, ULong arg3, ULong arg4, ULong arg5)
639 {
640    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
641 #  if defined(VGO_linux)
642    /* res = prctl( option, arg2, arg3, arg4, arg5 ); */
643    res = VG_(do_syscall5)(__NR_prctl, (UWord) option,
644                           (UWord) arg2, (UWord) arg3, (UWord) arg4,
645                           (UWord) arg5);
646 #  endif
647 
648    return sr_isError(res) ? -1 : sr_Res(res);
649 }
650 
651 /* ---------------------------------------------------------------------
652    pids, etc
653    ------------------------------------------------------------------ */
654 
VG_(gettid)655 Int VG_(gettid)(void)
656 {
657 #  if defined(VGO_linux)
658    SysRes res = VG_(do_syscall0)(__NR_gettid);
659 
660    if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) {
661       HChar pid[16];
662       /*
663        * The gettid system call does not exist. The obvious assumption
664        * to make at this point would be that we are running on an older
665        * system where the getpid system call actually returns the ID of
666        * the current thread.
667        *
668        * Unfortunately it seems that there are some systems with a kernel
669        * where getpid has been changed to return the ID of the thread group
670        * leader but where the gettid system call has not yet been added.
671        *
672        * So instead of calling getpid here we use readlink to see where
673        * the /proc/self link is pointing...
674        */
675 
676 #     if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
677       res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
678                              (UWord)"/proc/self",
679                              (UWord)pid, sizeof(pid));
680 #     else
681       res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
682                              (UWord)pid, sizeof(pid));
683 #     endif
684       if (!sr_isError(res) && sr_Res(res) > 0) {
685          HChar* s;
686          pid[sr_Res(res)] = '\0';
687          res = VG_(mk_SysRes_Success)(  VG_(strtoll10)(pid, &s) );
688          if (*s != '\0') {
689             VG_(message)(Vg_DebugMsg,
690                "Warning: invalid file name linked to by /proc/self: %s\n",
691                pid);
692          }
693       }
694    }
695 
696    return sr_Res(res);
697 
698 #  elif defined(VGO_darwin)
699    // Darwin's gettid syscall is something else.
700    // Use Mach thread ports for lwpid instead.
701    return mach_thread_self();
702 
703 #  elif defined(VGO_solaris)
704    SysRes res = VG_(do_syscall0)(__NR_lwp_self);
705    return sr_Res(res);
706 
707 #  else
708 #    error "Unknown OS"
709 #  endif
710 }
711 
712 /* You'd be amazed how many places need to know the current pid. */
VG_(getpid)713 Int VG_(getpid) ( void )
714 {
715    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
716    return sr_Res( VG_(do_syscall0)(__NR_getpid) );
717 }
718 
VG_(getpgrp)719 Int VG_(getpgrp) ( void )
720 {
721    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
722 #  if defined(VGO_linux) || defined(VGO_darwin)
723    return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
724 #  elif defined(VGO_solaris)
725    /* Uses the shared pgrpsys syscall, 0 for the getpgrp variant. */
726    return sr_Res( VG_(do_syscall1)(__NR_pgrpsys, 0) );
727 #  else
728 #    error Unknown OS
729 #  endif
730 }
731 
VG_(getppid)732 Int VG_(getppid) ( void )
733 {
734    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
735 #  if defined(VGO_linux) || defined(VGO_darwin)
736    return sr_Res( VG_(do_syscall0)(__NR_getppid) );
737 #  elif defined(VGO_solaris)
738    /* Uses the shared getpid/getppid syscall, val2 contains a parent pid. */
739    return sr_ResHI( VG_(do_syscall0)(__NR_getpid) );
740 #  else
741 #    error Unknown OS
742 #  endif
743 }
744 
VG_(geteuid)745 Int VG_(geteuid) ( void )
746 {
747    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
748 #  if defined(VGO_linux) || defined(VGO_darwin)
749    {
750 #     if defined(__NR_geteuid32)
751       // We use the 32-bit version if it's supported.  Otherwise, IDs greater
752       // than 65536 cause problems, as bug #151209 showed.
753       return sr_Res( VG_(do_syscall0)(__NR_geteuid32) );
754 #     else
755       return sr_Res( VG_(do_syscall0)(__NR_geteuid) );
756 #     endif
757    }
758 #  elif defined(VGO_solaris)
759    /* Uses the shared getuid/geteuid syscall, val2 contains the effective
760       uid. */
761    return sr_ResHI( VG_(do_syscall0)(__NR_getuid) );
762 #  else
763 #    error Unknown OS
764 #  endif
765 }
766 
VG_(getegid)767 Int VG_(getegid) ( void )
768 {
769 #  if defined(VGO_linux) || defined(VGO_darwin)
770    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
771 #    if defined(__NR_getegid32)
772    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
773    // than 65536 cause problems, as bug #151209 showed.
774    return sr_Res( VG_(do_syscall0)(__NR_getegid32) );
775 #    else
776    return sr_Res( VG_(do_syscall0)(__NR_getegid) );
777 #    endif
778 
779 #  elif defined(VGO_solaris)
780    /* Uses the shared getgid/getegid syscall, val2 contains the effective
781       gid. */
782    return sr_ResHI( VG_(do_syscall0)(__NR_getgid) );
783 #  else
784 #    error Unknown OS
785 #  endif
786 }
787 
788 /* Get supplementary groups into list[0 .. size-1].  Returns the
789    number of groups written, or -1 if error.  Note that in order to be
790    portable, the groups are 32-bit unsigned ints regardless of the
791    platform.
792    As a special case, if size == 0 the function returns the number of
793    groups leaving list untouched. */
VG_(getgroups)794 Int VG_(getgroups)( Int size, UInt* list )
795 {
796    if (size < 0) return -1;
797 
798 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
799       || defined(VGP_mips64_linux) || defined(VGP_tilegx_linux)
800    Int    i;
801    SysRes sres;
802    UShort list16[size];
803    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
804    if (sr_isError(sres))
805       return -1;
806    if (size != 0) {
807       for (i = 0; i < sr_Res(sres); i++)
808          list[i] = (UInt)list16[i];
809    }
810    return sr_Res(sres);
811 
812 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
813         || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)  \
814         || defined(VGO_darwin) || defined(VGP_s390x_linux)    \
815         || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) \
816         || defined(VGO_solaris)
817    SysRes sres;
818    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
819    if (sr_isError(sres))
820       return -1;
821    return sr_Res(sres);
822 
823 #  else
824 #     error "VG_(getgroups): needs implementation on this platform"
825 #  endif
826 }
827 
828 /* ---------------------------------------------------------------------
829    Process tracing
830    ------------------------------------------------------------------ */
831 
VG_(ptrace)832 Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
833 {
834    SysRes res;
835 #  if defined(VGO_linux) || defined(VGO_darwin)
836    res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
837 #  elif defined(VGO_solaris)
838    /* There is no ptrace syscall on Solaris.  Such requests has to be
839       implemented using the /proc interface.  Callers of VG_(ptrace) should
840       ensure that this function is not reached on Solaris, i.e. they must
841       provide a special code for Solaris for whatever feature they provide. */
842    I_die_here;
843 #  else
844 #    error Unknown OS
845 #  endif
846    if (sr_isError(res))
847       return -1;
848    return sr_Res(res);
849 }
850 
851 /* ---------------------------------------------------------------------
852    Fork
853    ------------------------------------------------------------------ */
854 
VG_(fork)855 Int VG_(fork) ( void )
856 {
857 #  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
858    SysRes res;
859    res = VG_(do_syscall5)(__NR_clone, VKI_SIGCHLD,
860                           (UWord)NULL, (UWord)NULL, (UWord)NULL, (UWord)NULL);
861    if (sr_isError(res))
862       return -1;
863    return sr_Res(res);
864 
865 #  elif defined(VGO_linux)
866    SysRes res;
867    res = VG_(do_syscall0)(__NR_fork);
868    if (sr_isError(res))
869       return -1;
870    return sr_Res(res);
871 
872 #  elif defined(VGO_darwin)
873    SysRes res;
874    res = VG_(do_syscall0)(__NR_fork); /* __NR_fork is UX64 */
875    if (sr_isError(res))
876       return -1;
877    /* on success: wLO = child pid; wHI = 1 for child, 0 for parent */
878    if (sr_ResHI(res) != 0) {
879       return 0;  /* this is child: return 0 instead of child pid */
880    }
881    return sr_Res(res);
882 
883 #  elif defined(VGO_solaris)
884    /* Using fork() on Solaris is not really the best thing to do. Solaris
885       does not do memory overcommitment so fork() can fail if there is not
886       enough memory to copy the current process into a new one.
887       Prefer to use VG_(spawn)() over VG_(fork)() + VG_(execv)(). */
888    SysRes res;
889    res = VG_(do_syscall2)(__NR_forksys, 0 /*subcode (fork)*/, 0 /*flags*/);
890    if (sr_isError(res))
891       return -1;
892    /* On success:
893         val = a pid of the child in the parent, a pid of the parent in the
894               child,
895         val2 = 0 in the parent process, 1 in the child process. */
896    if (sr_ResHI(res) != 0) {
897       return 0;
898    }
899    return sr_Res(res);
900 
901 #  else
902 #    error "Unknown OS"
903 #  endif
904 }
905 
906 /* ---------------------------------------------------------------------
907    Timing stuff
908    ------------------------------------------------------------------ */
909 
VG_(read_millisecond_timer)910 UInt VG_(read_millisecond_timer) ( void )
911 {
912    /* 'now' and 'base' are in microseconds */
913    static ULong base = 0;
914    ULong  now;
915 
916 #  if defined(VGO_linux) || defined(VGO_solaris)
917    { SysRes res;
918      struct vki_timespec ts_now;
919      res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC,
920                             (UWord)&ts_now);
921      if (sr_isError(res) == 0) {
922         now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000;
923      } else {
924        struct vki_timeval tv_now;
925        /* Note: On Solaris, this syscall takes only one parameter but the
926           extra dummy one does not cause any harm. */
927        res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
928        vg_assert(! sr_isError(res));
929        now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
930      }
931    }
932 
933 #  elif defined(VGO_darwin)
934    // Weird: it seems that gettimeofday() doesn't fill in the timeval, but
935    // rather returns the tv_sec as the low 32 bits of the result and the
936    // tv_usec as the high 32 bits of the result.  (But the timeval cannot be
937    // NULL!)  See bug 200990.
938    { SysRes res;
939      struct vki_timeval tv_now = { 0, 0 };
940      res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
941      vg_assert(! sr_isError(res));
942      now = sr_Res(res) * 1000000ULL + sr_ResHI(res);
943    }
944 
945 #  else
946 #    error "Unknown OS"
947 #  endif
948 
949    /* COMMON CODE */
950    if (base == 0)
951       base = now;
952 
953    return (now - base) / 1000;
954 }
955 
VG_(gettimeofday)956 Int VG_(gettimeofday)(struct vki_timeval *tv, struct vki_timezone *tz)
957 {
958    SysRes res;
959    res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)tv, (UWord)tz);
960 
961    if (! sr_isError(res)) return 0;
962 
963    /* Make sure, argument values are determinstic upon failure */
964    if (tv) *tv = (struct vki_timeval){ .tv_sec = 0, .tv_usec = 0 };
965    if (tz) *tz = (struct vki_timezone){ .tz_minuteswest = 0, .tz_dsttime = 0 };
966 
967    return -1;
968 }
969 
970 
971 /* ---------------------------------------------------------------------
972    atfork()
973    ------------------------------------------------------------------ */
974 
975 struct atfork {
976    vg_atfork_t  pre;
977    vg_atfork_t  parent;
978    vg_atfork_t  child;
979 };
980 
981 #define VG_MAX_ATFORK 10
982 
983 static struct atfork atforks[VG_MAX_ATFORK];
984 static Int n_atfork = 0;
985 
VG_(atfork)986 void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
987 {
988    Int i;
989 
990    for (i = 0; i < n_atfork; i++) {
991       if (atforks[i].pre == pre &&
992           atforks[i].parent == parent &&
993           atforks[i].child == child)
994          return;
995    }
996 
997    if (n_atfork >= VG_MAX_ATFORK)
998       VG_(core_panic)(
999          "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
1000 
1001    atforks[n_atfork].pre    = pre;
1002    atforks[n_atfork].parent = parent;
1003    atforks[n_atfork].child  = child;
1004 
1005    n_atfork++;
1006 }
1007 
VG_(do_atfork_pre)1008 void VG_(do_atfork_pre)(ThreadId tid)
1009 {
1010    Int i;
1011 
1012    for (i = 0; i < n_atfork; i++)
1013       if (atforks[i].pre != NULL)
1014          (*atforks[i].pre)(tid);
1015 }
1016 
VG_(do_atfork_parent)1017 void VG_(do_atfork_parent)(ThreadId tid)
1018 {
1019    Int i;
1020 
1021    for (i = 0; i < n_atfork; i++)
1022       if (atforks[i].parent != NULL)
1023          (*atforks[i].parent)(tid);
1024 }
1025 
VG_(do_atfork_child)1026 void VG_(do_atfork_child)(ThreadId tid)
1027 {
1028    Int i;
1029 
1030    for (i = 0; i < n_atfork; i++)
1031       if (atforks[i].child != NULL)
1032          (*atforks[i].child)(tid);
1033 }
1034 
1035 
1036 /* ---------------------------------------------------------------------
1037    icache invalidation
1038    ------------------------------------------------------------------ */
1039 
VG_(invalidate_icache)1040 void VG_(invalidate_icache) ( void *ptr, SizeT nbytes )
1041 {
1042    if (nbytes == 0) return;    // nothing to do
1043 
1044    // Get cache info
1045    VexArchInfo vai;
1046    VG_(machine_get_VexArchInfo)(NULL, &vai);
1047 
1048    // If I-caches are coherent, nothing needs to be done here
1049    if (vai.hwcache_info.icaches_maintain_coherence) return;
1050 
1051 #  if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
1052    Addr startaddr = (Addr) ptr;
1053    Addr endaddr   = startaddr + nbytes;
1054    Addr cls;
1055    Addr addr;
1056 
1057    cls = vai.ppc_icache_line_szB;
1058 
1059    /* Stay sane .. */
1060    vg_assert(cls == 16 || cls == 32 || cls == 64 || cls == 128);
1061 
1062    startaddr &= ~(cls - 1);
1063    for (addr = startaddr; addr < endaddr; addr += cls) {
1064       __asm__ __volatile__("dcbst 0,%0" : : "r" (addr));
1065    }
1066    __asm__ __volatile__("sync");
1067    for (addr = startaddr; addr < endaddr; addr += cls) {
1068       __asm__ __volatile__("icbi 0,%0" : : "r" (addr));
1069    }
1070    __asm__ __volatile__("sync; isync");
1071 
1072 #  elif defined(VGP_arm_linux)
1073    /* ARM cache flushes are privileged, so we must defer to the kernel. */
1074    Addr startaddr = (Addr) ptr;
1075    Addr endaddr   = startaddr + nbytes;
1076    VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr);
1077 
1078 #  elif defined(VGP_arm64_linux)
1079    // This arm64_linux section of this function VG_(invalidate_icache)
1080    // is copied from
1081    // https://github.com/armvixl/vixl/blob/master/src/a64/cpu-a64.cc
1082    // which has the following copyright notice:
1083    /*
1084    Copyright 2013, ARM Limited
1085    All rights reserved.
1086 
1087    Redistribution and use in source and binary forms, with or without
1088    modification, are permitted provided that the following conditions are met:
1089 
1090    * Redistributions of source code must retain the above copyright notice,
1091      this list of conditions and the following disclaimer.
1092    * Redistributions in binary form must reproduce the above copyright notice,
1093      this list of conditions and the following disclaimer in the documentation
1094      and/or other materials provided with the distribution.
1095    * Neither the name of ARM Limited nor the names of its contributors may be
1096      used to endorse or promote products derived from this software without
1097      specific prior written permission.
1098 
1099    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
1100    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1101    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1102    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
1103    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1104    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1105    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1106    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1107    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1108    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1109    */
1110 
1111    // Ask what the I and D line sizes are
1112    UInt cache_type_register;
1113    // Copy the content of the cache type register to a core register.
1114    __asm__ __volatile__ ("mrs %[ctr], ctr_el0" // NOLINT
1115                          : [ctr] "=r" (cache_type_register));
1116 
1117    const Int kDCacheLineSizeShift = 16;
1118    const Int kICacheLineSizeShift = 0;
1119    const UInt kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;
1120    const UInt kICacheLineSizeMask = 0xf << kICacheLineSizeShift;
1121 
1122    // The cache type register holds the size of the I and D caches as a power of
1123    // two.
1124    const UInt dcache_line_size_power_of_two =
1125        (cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;
1126    const UInt icache_line_size_power_of_two =
1127        (cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;
1128 
1129    const UInt dcache_line_size_ = 4 * (1 << dcache_line_size_power_of_two);
1130    const UInt icache_line_size_ = 4 * (1 << icache_line_size_power_of_two);
1131 
1132    Addr start = (Addr)ptr;
1133    // Sizes will be used to generate a mask big enough to cover a pointer.
1134    Addr dsize = (Addr)dcache_line_size_;
1135    Addr isize = (Addr)icache_line_size_;
1136 
1137    // Cache line sizes are always a power of 2.
1138    Addr dstart = start & ~(dsize - 1);
1139    Addr istart = start & ~(isize - 1);
1140    Addr end    = start + nbytes;
1141 
1142    __asm__ __volatile__ (
1143      // Clean every line of the D cache containing the target data.
1144      "0: \n\t"
1145      // dc : Data Cache maintenance
1146      // c : Clean
1147      // va : by (Virtual) Address
1148      // u : to the point of Unification
1149      // The point of unification for a processor is the point by which the
1150      // instruction and data caches are guaranteed to see the same copy of a
1151      // memory location. See ARM DDI 0406B page B2-12 for more information.
1152      "dc cvau, %[dline] \n\t"
1153      "add %[dline], %[dline], %[dsize] \n\t"
1154      "cmp %[dline], %[end] \n\t"
1155      "b.lt 0b \n\t"
1156      // Barrier to make sure the effect of the code above is visible to the rest
1157      // of the world.
1158      // dsb : Data Synchronisation Barrier
1159      // ish : Inner SHareable domain
1160      // The point of unification for an Inner Shareable shareability domain is
1161      // the point by which the instruction and data caches of all the processors
1162      // in that Inner Shareable shareability domain are guaranteed to see the
1163      // same copy of a memory location. See ARM DDI 0406B page B2-12 for more
1164      // information.
1165      "dsb ish \n\t"
1166      // Invalidate every line of the I cache containing the target data.
1167      "1: \n\t"
1168      // ic : instruction cache maintenance
1169      // i : invalidate
1170      // va : by address
1171      // u : to the point of unification
1172      "ic ivau, %[iline] \n\t"
1173      "add %[iline], %[iline], %[isize] \n\t"
1174      "cmp %[iline], %[end] \n\t"
1175      "b.lt 1b \n\t"
1176      // Barrier to make sure the effect of the code above is visible to the rest
1177      // of the world.
1178      "dsb ish \n\t"
1179      // Barrier to ensure any prefetching which happened before this code is
1180      // discarded.
1181      // isb : Instruction Synchronisation Barrier
1182      "isb \n\t"
1183      : [dline] "+r" (dstart),
1184        [iline] "+r" (istart)
1185      : [dsize] "r" (dsize),
1186        [isize] "r" (isize),
1187        [end] "r" (end)
1188      // This code does not write to memory but without the dependency gcc might
1189      // move this code before the code is generated.
1190      : "cc", "memory"
1191    );
1192 
1193 #  elif defined(VGA_mips32) || defined(VGA_mips64)
1194    SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr,
1195                                  (UWord) nbytes, (UWord) 3);
1196    vg_assert( !sr_isError(sres) );
1197 
1198 #  elif defined(VGA_tilegx)
1199    const HChar *start, *end;
1200 
1201    /* L1 ICache is 32KB. cacheline size is 64 bytes. */
1202    if (nbytes > 0x8000) nbytes = 0x8000;
1203 
1204    start = (const HChar *)((unsigned long)ptr & -64ULL);
1205    end = (const HChar*)ptr + nbytes - 1;
1206 
1207    __insn_mf();
1208 
1209    do {
1210      const HChar* p;
1211      for (p = start; p <= end; p += 64)
1212        __insn_icoh(p);
1213    } while (0);
1214 
1215    __insn_drain();
1216 
1217 #  endif
1218 }
1219 
1220 
1221 /* ---------------------------------------------------------------------
1222    dcache flushing
1223    ------------------------------------------------------------------ */
1224 
VG_(flush_dcache)1225 void VG_(flush_dcache) ( void *ptr, SizeT nbytes )
1226 {
1227    /* Currently this is only required on ARM64. */
1228 #  if defined(VGA_arm64)
1229    Addr startaddr = (Addr) ptr;
1230    Addr endaddr   = startaddr + nbytes;
1231    Addr cls;
1232    Addr addr;
1233 
1234    ULong ctr_el0;
1235    __asm__ __volatile__ ("mrs %0, ctr_el0" : "=r"(ctr_el0));
1236    cls = 4 * (1ULL << (0xF & (ctr_el0 >> 16)));
1237 
1238    /* Stay sane .. */
1239    vg_assert(cls == 64);
1240 
1241    startaddr &= ~(cls - 1);
1242    for (addr = startaddr; addr < endaddr; addr += cls) {
1243       __asm__ __volatile__("dc cvau, %0" : : "r" (addr));
1244    }
1245    __asm__ __volatile__("dsb ish");
1246 #  endif
1247 }
1248 
1249 /*--------------------------------------------------------------------*/
1250 /*--- end                                                          ---*/
1251 /*--------------------------------------------------------------------*/
1252