1
2/*--------------------------------------------------------------------*/
3/*--- Types and macros for writing syscall wrappers.               ---*/
4/*---                                        priv_types_n_macros.h ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2000-2011 Julian Seward
12      jseward@acm.org
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31
32#ifndef __PRIV_TYPES_N_MACROS_H
33#define __PRIV_TYPES_N_MACROS_H
34
35/* requires #include "pub_core_options.h" */
36/* requires #include "pub_core_signals.h" */
37
38/* This header defines types and macros which are useful for writing
39   syscall wrappers.  It does not give prototypes for any such
40   headers, though: that is the job of the priv_syswrap-*.h headers.
41   This header gets included in any file which defines or declares
42   wrappers, and as such should only contain stuff which is relevant
43   to all such files.
44*/
45
46/* ---------------------------------------------------------------------
47   Types that are used in syscall wrappers.
48   ------------------------------------------------------------------ */
49
50/* Arguments for a syscall. */
51typedef
52   struct SyscallArgs {
53      Word sysno;
54      UWord arg1;
55      UWord arg2;
56      UWord arg3;
57      UWord arg4;
58      UWord arg5;
59      UWord arg6;
60      UWord arg7;
61      UWord arg8;
62   }
63   SyscallArgs;
64
65/* Current status of a syscall being done on behalf of the client. */
66typedef
67   struct SyscallStatus {
68      enum {
69         /* call is complete, result is in 'res' */
70         SsComplete=1,
71         /* syscall not yet completed; must be handed to the kernel */
72         SsHandToKernel,
73         /* not currently handling a syscall for this thread */
74         SsIdle
75      } what;
76      SysRes sres; /* only meaningful for .what == SsComplete */
77   }
78   SyscallStatus;
79
80/* Guest state layout info for syscall args. */
81typedef
82   struct {
83      // Note that, depending on the platform, arguments may be found in
84      // registers or on the stack.  (See the comment at the top of
85      // syswrap-main.c for per-platform details.)  For register arguments
86      // (which have o_arg field names) the o_arg value is the offset into
87      // the vex register state.  For stack arguments (which have s_arg
88      // field names), the s_arg value is the offset from the stack pointer.
89      Int o_sysno;
90#     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
91         || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
92         || defined(VGP_arm_linux) || defined(VGP_s390x_linux)
93      Int o_arg1;
94      Int o_arg2;
95      Int o_arg3;
96      Int o_arg4;
97      Int o_arg5;
98      Int o_arg6;
99      Int uu_arg7;
100      Int uu_arg8;
101#     elif defined(VGP_x86_darwin)
102      Int s_arg1;
103      Int s_arg2;
104      Int s_arg3;
105      Int s_arg4;
106      Int s_arg5;
107      Int s_arg6;
108      Int s_arg7;
109      Int s_arg8;
110#     elif defined(VGP_amd64_darwin)
111      Int o_arg1;
112      Int o_arg2;
113      Int o_arg3;
114      Int o_arg4;
115      Int o_arg5;
116      Int o_arg6;
117      Int s_arg7;
118      Int s_arg8;
119#     else
120#       error "Unknown platform"
121#     endif
122   }
123   SyscallArgLayout;
124
125/* Flags describing syscall wrappers */
126#define SfMayBlock      (1 << 1) /* may block                         */
127#define SfPostOnFail    (1 << 2) /* call POST() function on failure   */
128#define SfPollAfter     (1 << 3) /* poll for signals on completion    */
129#define SfYieldAfter    (1 << 4) /* yield on completion               */
130#define SfNoWriteResult (1 << 5) /* don't write result to guest state */
131
132
133/* ---------------------------------------------------------------------
134   The syscall table.
135   ------------------------------------------------------------------ */
136
137typedef
138   struct {
139      void (*before) ( ThreadId,
140                       SyscallArgLayout*,
141                       /*MOD*/SyscallArgs*,
142                       /*OUT*/SyscallStatus*,
143                       /*OUT*/UWord*
144                     );
145
146      void (*after)  ( ThreadId,
147                       SyscallArgs*,
148                       SyscallStatus*
149                     );
150   }
151   SyscallTableEntry;
152
153/* Syscall table entries bind __NR_xxx syscall numbers to the PRE/POST
154   wrappers for the relevant syscall used in the OS kernel for that
155   number.  Note that the constant names don't always match the
156   wrapper names in a straightforward way.  For example, on x86/Linux:
157
158      __NR_lchown       --> sys_lchown16()
159      __NR_lchown32     --> sys_lchown()
160      __NR_select       --> old_select()
161      __NR__newselect   --> sys_select()
162*/
163
164
165/* A function to find the syscall table entry for a given sysno.  If
166   none is found, return NULL.  This used to be done with a single
167   fixed sized table exposed to the caller, but that's too inflexible;
168   hence now use a function which can do arbitrary messing around to
169   find the required entry. */
170#if defined(VGO_linux)
171extern
172SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno );
173
174#elif defined(VGO_darwin)
175/* XXX: Darwin still uses the old scheme of exposing the table
176   array(s) and size(s) directly to syswrap-main.c.  This should be
177   fixed. */
178
179extern const SyscallTableEntry ML_(syscall_table)[];
180extern const UInt ML_(syscall_table_size);
181
182#else
183#  error Unknown OS
184#endif
185
186/* ---------------------------------------------------------------------
187   Declaring and defining wrappers.
188   ------------------------------------------------------------------ */
189
190/* Templates for generating the PRE and POST macros -- that is, the
191   formal parameter lists for the definitions of wrapper functions.
192
193   Since these names exist in the global namespace, 'auxstr' should
194   give an auxiliary string, eg, "generic", "x86_linux", "linux", etc,
195   that ensures the names won't clash with other wrappers.
196
197   You should create corresponding global declarations using
198   DECL_TEMPLATE (indirectly) below.
199
200   Note.  The silly name "arrghs" is used rather than just "args"
201   because a few wrappers declare the name "args" themselves, and
202   renaming those decls can change the name that comes out in error
203   messages (on scalar arg checks).  Hence rename this instead.
204*/
205
206#define DEFN_PRE_TEMPLATE(auxstr, name)                          \
207   void vgSysWrap_##auxstr##_##name##_before                     \
208                                 ( ThreadId tid,                 \
209                                   SyscallArgLayout* layout,     \
210                                   /*MOD*/SyscallArgs* arrghs,   \
211                                   /*OUT*/SyscallStatus* status, \
212                                   /*OUT*/UWord* flags           \
213                                 )
214
215#define DEFN_POST_TEMPLATE(auxstr, name)                         \
216   void vgSysWrap_##auxstr##_##name##_after                      \
217                                 ( ThreadId tid,                 \
218                                   SyscallArgs* arrghs,          \
219                                   SyscallStatus* status         \
220                                 )
221
222
223/* This macro generates declarations (prototypes) for wrappers.  It
224   declares both the pre-wrapper and the post-wrapper, even though the
225   post-wrapper may not actually exist.
226*/
227#define DECL_TEMPLATE(auxstr, name)                              \
228   extern                                                        \
229   void vgSysWrap_##auxstr##_##name##_before                     \
230                                 ( ThreadId tid,                 \
231                                   SyscallArgLayout* layout,     \
232                                   /*MOD*/SyscallArgs* arrghs,   \
233                                   /*OUT*/SyscallStatus* status, \
234                                   /*OUT*/UWord* flags           \
235                                 );                              \
236   extern                                                        \
237   void vgSysWrap_##auxstr##_##name##_after                      \
238                                 ( ThreadId tid,                 \
239                                   SyscallArgs* arrghs,          \
240                                   SyscallStatus* status         \
241                                 );
242
243
244
245/* Macros for conveniently generating entries in the syscall
246   tables.  This first pair are not used directly. */
247
248#define WRAPPER_ENTRY_X_(auxstr, sysno, name) \
249   [sysno] = { vgSysWrap_##auxstr##_##name##_before, NULL }
250#define WRAPPER_ENTRY_XY(auxstr, sysno, name) \
251   [sysno] = { vgSysWrap_##auxstr##_##name##_before, \
252               vgSysWrap_##auxstr##_##name##_after }
253
254#define WRAPPER_PRE_NAME(auxstr, name) \
255    vgSysWrap_##auxstr##_##name##_before
256#define WRAPPER_POST_NAME(auxstr, name) \
257    vgSysWrap_##auxstr##_##name##_after
258
259/* Add a generic wrapper to a syscall table. */
260#if defined(VGO_linux)
261#  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, sysno, name)
262#  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, sysno, name)
263#elif defined(VGO_darwin)
264#  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
265#  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
266#else
267#  error Unknown OS
268#endif
269
270/* Add a Linux-specific, arch-independent wrapper to a syscall
271   table. */
272#define LINX_(sysno, name)    WRAPPER_ENTRY_X_(linux, sysno, name)
273#define LINXY(sysno, name)    WRAPPER_ENTRY_XY(linux, sysno, name)
274
275
276/* ---------------------------------------------------------------------
277   Macros useful for writing wrappers concisely.  These refer to the
278   parameters declared by DEFN_{PRE,POST}_TEMPLATE and so in a way do
279   not help clarity of understanding.  But they are just too useful to
280   omit.
281   ------------------------------------------------------------------ */
282
283/* Reference to the syscall's arguments -- the ones which the
284   pre-wrapper may have modified, not the original copy. */
285#define SYSNO  (arrghs->sysno)
286#define ARG1   (arrghs->arg1)
287#define ARG2   (arrghs->arg2)
288#define ARG3   (arrghs->arg3)
289#define ARG4   (arrghs->arg4)
290#define ARG5   (arrghs->arg5)
291#define ARG6   (arrghs->arg6)
292#define ARG7   (arrghs->arg7)
293#define ARG8   (arrghs->arg8)
294
295/* Reference to the syscall's current result status/value.  General
296   paranoia all round. */
297#define SUCCESS       (status->what == SsComplete && !sr_isError(status->sres))
298#define FAILURE       (status->what == SsComplete &&  sr_isError(status->sres))
299#define SWHAT         (status->what)
300#define RES           (getRES(status))
301#define RESHI         (getRESHI(status))
302#define ERR           (getERR(status))
303
304static inline UWord getRES ( SyscallStatus* st ) {
305   vg_assert(st->what == SsComplete);
306   vg_assert(!sr_isError(st->sres));
307   return sr_Res(st->sres);
308}
309
310static inline UWord getRESHI ( SyscallStatus* st ) {
311   vg_assert(st->what == SsComplete);
312   vg_assert(!sr_isError(st->sres));
313   return sr_ResHI(st->sres);
314}
315
316static inline UWord getERR ( SyscallStatus* st ) {
317   vg_assert(st->what == SsComplete);
318   vg_assert(sr_isError(st->sres));
319   return sr_Err(st->sres);
320}
321
322
323/* Set the current result status/value in various ways. */
324#define SET_STATUS_Success(zzz)                      \
325   do { status->what = SsComplete;                   \
326        status->sres = VG_(mk_SysRes_Success)(zzz);  \
327   } while (0)
328
329#define SET_STATUS_Failure(zzz)                      \
330   do { Word wzz = (Word)(zzz);                      \
331        /* Catch out wildly bogus error values. */   \
332        vg_assert(wzz >= 0 && wzz < 10000);          \
333        status->what = SsComplete;                   \
334        status->sres = VG_(mk_SysRes_Error)(wzz);    \
335   } while (0)
336
337#define SET_STATUS_from_SysRes(zzz)                  \
338   do {                                              \
339     status->what = SsComplete;                      \
340     status->sres = (zzz);                           \
341   } while (0)
342
343
344#define PRINT(format, args...)                       \
345   if (VG_(clo_trace_syscalls))                      \
346      VG_(printf)(format, ## args)
347
348#define FUSE_COMPATIBLE_MAY_BLOCK()                       \
349   if (VG_(strstr)(VG_(clo_sim_hints),"fuse-compatible")) \
350      *flags |= SfMayBlock
351
352
353/* Macros used to tell tools about uses of scalar arguments.  Note,
354   these assume little-endianness.  These can only be used in
355   pre-wrappers, and they refer to the layout parameter passed in. */
356/* PRRSN == "pre-register-read-sysno"
357   PRRAn == "pre-register-read-argument"
358   PSRAn == "pre-stack-read-argument"
359   PRAn  == "pre-read-argument"
360*/
361
362#if defined(VGO_linux)
363   /* Up to 6 parameters, all in registers. */
364#  define PRA1(s,t,a) PRRAn(1,s,t,a)
365#  define PRA2(s,t,a) PRRAn(2,s,t,a)
366#  define PRA3(s,t,a) PRRAn(3,s,t,a)
367#  define PRA4(s,t,a) PRRAn(4,s,t,a)
368#  define PRA5(s,t,a) PRRAn(5,s,t,a)
369#  define PRA6(s,t,a) PRRAn(6,s,t,a)
370
371#elif defined(VGP_x86_darwin)
372   /* Up to 8 parameters, all on the stack. */
373#  define PRA1(s,t,a) PSRAn(1,s,t,a)
374#  define PRA2(s,t,a) PSRAn(2,s,t,a)
375#  define PRA3(s,t,a) PSRAn(3,s,t,a)
376#  define PRA4(s,t,a) PSRAn(4,s,t,a)
377#  define PRA5(s,t,a) PSRAn(5,s,t,a)
378#  define PRA6(s,t,a) PSRAn(6,s,t,a)
379#  define PRA7(s,t,a) PSRAn(7,s,t,a)
380#  define PRA8(s,t,a) PSRAn(8,s,t,a)
381
382#elif defined(VGP_amd64_darwin)
383   /* Up to 8 parameters, 6 in registers, 2 on the stack. */
384#  define PRA1(s,t,a) PRRAn(1,s,t,a)
385#  define PRA2(s,t,a) PRRAn(2,s,t,a)
386#  define PRA3(s,t,a) PRRAn(3,s,t,a)
387#  define PRA4(s,t,a) PRRAn(4,s,t,a)
388#  define PRA5(s,t,a) PRRAn(5,s,t,a)
389#  define PRA6(s,t,a) PRRAn(6,s,t,a)
390#  define PRA7(s,t,a) PSRAn(7,s,t,a)
391#  define PRA8(s,t,a) PSRAn(8,s,t,a)
392
393#else
394#  error Unknown platform
395#endif
396
397
398/* Tell the tool that the syscall number is being read. */
399#define PRRSN \
400      VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \
401                                    layout->o_sysno, sizeof(UWord));
402
403/* REGISTER PARAMETERS */
404
405/* PRRAn: Tell the tool that the register holding the n-th syscall
406   argument is being read, at type 't' which must be at most the size
407   of a register but can be smaller.  In the latter case we need to be
408   careful about endianness. */
409
410/* little-endian: the part of the guest state being read is
411      let here = offset_of_reg
412      in  [here .. here + sizeof(t) - 1]
413   since the least significant parts of the guest register are stored
414   in memory at the lowest address.
415*/
416#define PRRAn_LE(n,s,t,a)                          \
417   do {                                            \
418      Int here = layout->o_arg##n;                 \
419      vg_assert(sizeof(t) <= sizeof(UWord));       \
420      vg_assert(here >= 0);                        \
421      VG_(tdict).track_pre_reg_read(               \
422         Vg_CoreSysCall, tid, s"("#a")",           \
423         here, sizeof(t)                           \
424      );                                           \
425   } while (0)
426
427/* big-endian: the part of the guest state being read is
428      let next = offset_of_reg + sizeof(reg)
429      in  [next - sizeof(t) .. next - 1]
430   since the least significant parts of the guest register are stored
431   in memory at the highest address.
432*/
433#define PRRAn_BE(n,s,t,a)                          \
434   do {                                            \
435      Int here = layout->o_arg##n;                 \
436      Int next = layout->o_arg##n + sizeof(UWord); \
437      vg_assert(sizeof(t) <= sizeof(UWord));       \
438      vg_assert(here >= 0);                        \
439      VG_(tdict).track_pre_reg_read(               \
440         Vg_CoreSysCall, tid, s"("#a")",           \
441         next-sizeof(t), sizeof(t)                 \
442      );                                           \
443   } while (0)
444
445#if defined(VG_BIGENDIAN)
446#  define PRRAn(n,s,t,a) PRRAn_BE(n,s,t,a)
447#elif defined(VG_LITTLEENDIAN)
448#  define PRRAn(n,s,t,a) PRRAn_LE(n,s,t,a)
449#else
450#  error "Unknown endianness"
451#endif
452
453
454/* STACK PARAMETERS */
455
456/* PSRAn: Tell the tool that the memory holding the n-th syscall
457   argument is being read, at type 't' which must be at most the size
458   of a register but can be smaller.  In the latter case we need to be
459   careful about endianness. */
460
461/* little-endian: the part of the guest state being read is
462      let here = offset_of_reg
463      in  [here .. here + sizeof(t) - 1]
464   since the least significant parts of the guest register are stored
465   in memory at the lowest address.
466*/
467#define PSRAn_LE(n,s,t,a)                          \
468   do {                                            \
469      Addr here = layout->s_arg##n + VG_(get_SP)(tid); \
470      vg_assert(sizeof(t) <= sizeof(UWord));       \
471      VG_(tdict).track_pre_mem_read(               \
472         Vg_CoreSysCallArgInMem, tid, s"("#a")",   \
473         here, sizeof(t)                           \
474      );                                           \
475   } while (0)
476
477/* big-endian: the part of the guest state being read is
478      let next = offset_of_reg + sizeof(reg)
479      in  [next - sizeof(t) .. next - 1]
480   since the least significant parts of the guest register are stored
481   in memory at the highest address.
482*/
483#define PSRAn_BE(n,s,t,a)                                         \
484   do {                                                           \
485      Addr next = layout->o_arg##n + sizeof(UWord) +              \
486                  VG_(threads)[tid].arch.vex.VG_STACK_PTR;        \
487      vg_assert(sizeof(t) <= sizeof(UWord));                      \
488      VG_(tdict).track_pre_mem_read(                              \
489         Vg_CoreSysCallArgInMem, tid, s"("#a")",                  \
490         next-sizeof(t), sizeof(t)                                \
491      );                                                          \
492   } while (0)
493
494#if defined(VG_BIGENDIAN)
495#  define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
496#elif defined(VG_LITTLEENDIAN)
497#  define PSRAn(n,s,t,a) PSRAn_LE(n,s,t,a)
498#else
499#  error "Unknown endianness"
500#endif
501
502
503#define PRE_REG_READ0(tr, s) \
504   if (VG_(tdict).track_pre_reg_read) { \
505      PRRSN; \
506   }
507#define PRE_REG_READ1(tr, s, t1, a1) \
508   if (VG_(tdict).track_pre_reg_read) { \
509      PRRSN; \
510      PRA1(s,t1,a1);                            \
511   }
512#define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
513   if (VG_(tdict).track_pre_reg_read) { \
514      PRRSN; \
515      PRA1(s,t1,a1); PRA2(s,t2,a2);           \
516   }
517#define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
518   if (VG_(tdict).track_pre_reg_read) { \
519      PRRSN; \
520      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
521   }
522#define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
523   if (VG_(tdict).track_pre_reg_read) { \
524      PRRSN; \
525      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
526      PRA4(s,t4,a4);                                    \
527   }
528#define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
529   if (VG_(tdict).track_pre_reg_read) { \
530      PRRSN; \
531      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
532      PRA4(s,t4,a4); PRA5(s,t5,a5);                   \
533   }
534#define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
535   if (VG_(tdict).track_pre_reg_read) { \
536      PRRSN; \
537      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
538      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
539   }
540#define PRE_REG_READ7(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7) \
541   if (VG_(tdict).track_pre_reg_read) { \
542      PRRSN; \
543      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
544      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
545      PRA7(s,t7,a7);                                     \
546   }
547
548#define PRE_REG_READ8(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7, t8, a8) \
549   if (VG_(tdict).track_pre_reg_read) { \
550      PRRSN; \
551      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
552      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
553      PRA7(s,t7,a7); PRA8(s,t8,a8);                    \
554   }
555
556#define PRE_MEM_READ(zzname, zzaddr, zzlen) \
557   VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
558
559#define PRE_MEM_RASCIIZ(zzname, zzaddr) \
560   VG_TRACK( pre_mem_read_asciiz, Vg_CoreSysCall, tid, zzname, zzaddr)
561
562#define PRE_MEM_WRITE(zzname, zzaddr, zzlen) \
563   VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
564
565#define POST_MEM_WRITE(zzaddr, zzlen) \
566   VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, zzaddr, zzlen)
567
568
569#define PRE_FIELD_READ(zzname, zzfield) \
570    PRE_MEM_READ(zzname, (UWord)&zzfield, sizeof(zzfield))
571
572#define PRE_FIELD_WRITE(zzname, zzfield) \
573    PRE_MEM_WRITE(zzname, (UWord)&zzfield, sizeof(zzfield))
574
575#define POST_FIELD_WRITE(zzfield) \
576    POST_MEM_WRITE((UWord)&zzfield, sizeof(zzfield))
577
578
579#endif   // __PRIV_TYPES_N_MACROS_H
580
581/*--------------------------------------------------------------------*/
582/*--- end                                                          ---*/
583/*--------------------------------------------------------------------*/
584