Home | History | Annotate | Download | only in tests
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2003 Hewlett-Packard Co
      3 	Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4 
      5 This file is part of libunwind.
      6 
      7 Copyright (c) 2003 Hewlett-Packard Co.
      8 
      9 Permission is hereby granted, free of charge, to any person obtaining
     10 a copy of this software and associated documentation files (the
     11 "Software"), to deal in the Software without restriction, including
     12 without limitation the rights to use, copy, modify, merge, publish,
     13 distribute, sublicense, and/or sell copies of the Software, and to
     14 permit persons to whom the Software is furnished to do so, subject to
     15 the following conditions:
     16 
     17 The above copyright notice and this permission notice shall be
     18 included in all copies or substantial portions of the Software.
     19 
     20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     27 
     28 /* This test program checks whether proc_info lookup failures are
     29    cached.  They must NOT be cached because it could otherwise turn
     30    temporary failures into permanent ones.  Furthermore, we allow apps
     31    to return -UNW_ESTOPUNWIND to terminate unwinding (though this
     32    feature is deprecated and dynamic unwind info should be used
     33    instead).  */
     34 
     35 #include <stdio.h>
     36 #include <string.h>
     37 
     38 #include <libunwind.h>
     39 #include "compiler.h"
     40 
     41 int errors;
     42 
     43 #define panic(args...)					\
     44 	{ ++errors; fprintf (stderr, args); return -1; }
     45 
     46 static int
     47 find_proc_info (unw_addr_space_t as UNUSED,
     48                 unw_word_t ip UNUSED,
     49                 unw_proc_info_t *pip UNUSED,
     50                 int need_unwind_info UNUSED,
     51                 void *arg UNUSED)
     52 {
     53   return -UNW_ESTOPUNWIND;
     54 }
     55 
     56 static int
     57 access_mem (unw_addr_space_t as UNUSED,
     58             unw_word_t addr UNUSED,
     59             unw_word_t *valp, int write,
     60             void *arg UNUSED)
     61 {
     62   if (!write)
     63     *valp = 0;
     64   return 0;
     65 }
     66 
     67 static int
     68 access_reg (unw_addr_space_t as UNUSED,
     69             unw_regnum_t regnum UNUSED,
     70             unw_word_t *valp, int write,
     71             void *arg UNUSED)
     72 {
     73   if (!write)
     74     *valp = 32;
     75   return 0;
     76 }
     77 
     78 static int
     79 access_fpreg (unw_addr_space_t as UNUSED,
     80               unw_regnum_t regnum UNUSED,
     81               unw_fpreg_t *valp, int write,
     82               void *arg UNUSED)
     83 {
     84   if (!write)
     85     memset (valp, 0, sizeof (*valp));
     86   return 0;
     87 }
     88 
     89 static int
     90 get_dyn_info_list_addr (unw_addr_space_t as UNUSED,
     91                         unw_word_t *dilap UNUSED,
     92                         void *arg UNUSED)
     93 {
     94   return -UNW_ENOINFO;
     95 }
     96 
     97 static void
     98 put_unwind_info (unw_addr_space_t as UNUSED,
     99                  unw_proc_info_t *pi UNUSED,
    100                  void *arg UNUSED)
    101 {
    102   ++errors;
    103   fprintf (stderr, "%s() got called!\n", __FUNCTION__);
    104 }
    105 
    106 static int
    107 resume (unw_addr_space_t as UNUSED,
    108         unw_cursor_t *reg UNUSED,
    109         void *arg UNUSED)
    110 {
    111   panic ("%s() got called!\n", __FUNCTION__);
    112 }
    113 
    114 static int
    115 get_proc_name (unw_addr_space_t as UNUSED,
    116                unw_word_t ip UNUSED,
    117                char *buf UNUSED,
    118                size_t buf_len UNUSED,
    119                unw_word_t *offp UNUSED,
    120                void *arg UNUSED)
    121 {
    122   panic ("%s() got called!\n", __FUNCTION__);
    123 }
    124 
    125 int
    126 main (int argc, char **argv)
    127 {
    128   unw_accessors_t acc;
    129   unw_addr_space_t as;
    130   int ret, verbose = 0;
    131   unw_cursor_t c;
    132 
    133   if (argc > 1 && strcmp (argv[1], "-v") == 0)
    134     verbose = 1;
    135 
    136   memset (&acc, 0, sizeof (acc));
    137   acc.find_proc_info = find_proc_info;
    138   acc.put_unwind_info = put_unwind_info;
    139   acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
    140   acc.access_mem = access_mem;
    141   acc.access_reg = access_reg;
    142   acc.access_fpreg = access_fpreg;
    143   acc.resume = resume;
    144   acc.get_proc_name = get_proc_name;
    145 
    146   as = unw_create_addr_space (&acc, 0);
    147   if (!as)
    148     panic ("unw_create_addr_space() failed\n");
    149 
    150   unw_set_caching_policy (as, UNW_CACHE_GLOBAL);
    151 
    152   ret = unw_init_remote (&c, as, NULL);
    153   if (ret < 0)
    154     panic ("unw_init_remote() returned %d instead of 0\n", ret);
    155 
    156   ret = unw_step (&c);
    157   if (ret != -UNW_ESTOPUNWIND)
    158     panic ("First call to unw_step() returned %d instead of %d\n",
    159 	   ret, -UNW_ESTOPUNWIND);
    160 
    161   ret = unw_step (&c);
    162   if (ret != -UNW_ESTOPUNWIND)
    163     panic ("Second call to unw_step() returned %d instead of %d\n",
    164 	   ret, -UNW_ESTOPUNWIND);
    165 
    166   unw_destroy_addr_space (as);
    167 
    168   if (verbose)
    169     printf ("SUCCESS\n");
    170   return 0;
    171 }
    172