Home | History | Annotate | Download | only in include
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- A minimal setjmp/longjmp facility.     pub_tool_libcsetjmp.h ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2010-2013 Mozilla Inc
     11 
     12    This program is free software; you can redistribute it and/or
     13    modify it under the terms of the GNU General Public License as
     14    published by the Free Software Foundation; either version 2 of the
     15    License, or (at your option) any later version.
     16 
     17    This program is distributed in the hope that it will be useful, but
     18    WITHOUT ANY WARRANTY; without even the implied warranty of
     19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20    General Public License for more details.
     21 
     22    You should have received a copy of the GNU General Public License
     23    along with this program; if not, write to the Free Software
     24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     25    02111-1307, USA.
     26 
     27    The GNU General Public License is contained in the file COPYING.
     28 */
     29 
     30 /* Contributed by Julian Seward <jseward (at) acm.org> */
     31 
     32 #ifndef __PUB_TOOL_LIBCSETJMP_H
     33 #define __PUB_TOOL_LIBCSETJMP_H
     34 
     35 #include "pub_tool_basics.h"   // UWord
     36 
     37 //--------------------------------------------------------------------
     38 // PURPOSE: Provides a minimal setjmp/longjmp facility, that saves/
     39 // restores integer registers, but not necessarily anything more.
     40 //--------------------------------------------------------------------
     41 
     42 
     43 /* This provides an extremely minimal setjmp/longjmp facility, in
     44    which only the host's integer registers are saved/restored.  Or at
     45    least, that is the minimal guaranteed functionality.
     46 
     47    Until Apr 2011 we used __builtin_setjmp and __builtin_longjmp, but
     48    it appears that that is not always correctly implemented.  See
     49    https://bugs.kde.org/show_bug.cgi?id=259977.  So this module wraps
     50    those functions up and facilitates replacing them with our own
     51    implementations where necessary.
     52 */
     53 
     54 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
     55 #include <setjmp.h>
     56 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
     57 
     58 
     59 /* Don't use jmp_buf, __builtin_setjmp or __builtin_longjmp directly.
     60    They don't always work reliably.  Instead use these macros, which
     61    provide the opportunity to supply alternative implementations as
     62    necessary.
     63 
     64    Note that the abstraction is done with macros (ick) rather than
     65    functions and typedefs, since wrapping __builtin_setjmp up in a
     66    second function (eg, VG_(minimal_setjmp)) doesn't seem to work for
     67    whatever reason -- returns via a VG_(minimal_longjmp) go wrong.
     68 
     69    VG_MINIMAL_SETJMP stores the current integer register state in the
     70    supplied argument, and returns zero.  VG_MINIMAL_LONGJMP resumes
     71    with the previously saved state, and returns a nonzero, word-sized
     72    value.  The caller must test all bits of the value in order to make
     73    a zero/non-zero determination.
     74 */
     75 
     76 #if defined(VGP_ppc32_linux)
     77 
     78 #define VG_MINIMAL_JMP_BUF(_name)        UInt _name [32+1+1]
     79 __attribute__((returns_twice))
     80 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
     81 __attribute__((noreturn))
     82 void  VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
     83 
     84 
     85 #elif defined(VGP_ppc64_linux)
     86 
     87 #define VG_MINIMAL_JMP_BUF(_name)        ULong _name [32+1+1]
     88 __attribute__((returns_twice))
     89 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
     90 __attribute__((noreturn))
     91 void  VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
     92 
     93 
     94 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
     95 
     96 #define VG_MINIMAL_JMP_BUF(_name)        ULong _name [16+1]
     97 __attribute__((returns_twice))
     98 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
     99 __attribute__((noreturn))
    100 void  VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
    101 
    102 
    103 #elif defined(VGP_x86_linux) || defined(VGP_x86_darwin)
    104 
    105 #define VG_MINIMAL_JMP_BUF(_name)        UInt _name [8+1]
    106 __attribute__((returns_twice))
    107 __attribute__((regparm(1))) // this is critical; don't delete
    108 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
    109 __attribute__((noreturn))
    110 __attribute__((regparm(1))) // ditto
    111 void  VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
    112 
    113 #elif defined(VGP_mips32_linux)
    114 
    115 #define VG_MINIMAL_JMP_BUF(_name)        UInt _name [8+1+1+1+1]
    116 __attribute__((returns_twice))
    117 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
    118 __attribute__((noreturn))
    119 void  VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
    120 
    121 #else
    122 
    123 /* The default implementation. */
    124 #define VG_MINIMAL_JMP_BUF(_name) jmp_buf _name
    125 #define VG_MINIMAL_SETJMP(_env)   ((UWord)(__builtin_setjmp((_env))))
    126 #define VG_MINIMAL_LONGJMP(_env)  __builtin_longjmp((_env),1)
    127 
    128 #endif
    129 
    130 #endif   // __PUB_TOOL_LIBCSETJMP_H
    131 
    132 /*--------------------------------------------------------------------*/
    133 /*--- end                                    pub_tool_libcsetjmp.h ---*/
    134 /*--------------------------------------------------------------------*/
    135