1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2003 Hewlett-Packard Co
3 	Contributed by David Mosberger-Tang <davidm@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
find_proc_info(unw_addr_space_t as UNUSED,unw_word_t ip UNUSED,unw_proc_info_t * pip UNUSED,int need_unwind_info UNUSED,void * arg UNUSED)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
access_mem(unw_addr_space_t as UNUSED,unw_word_t addr UNUSED,unw_word_t * valp,int write,void * arg UNUSED)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
access_reg(unw_addr_space_t as UNUSED,unw_regnum_t regnum UNUSED,unw_word_t * valp,int write,void * arg UNUSED)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
access_fpreg(unw_addr_space_t as UNUSED,unw_regnum_t regnum UNUSED,unw_fpreg_t * valp,int write,void * arg UNUSED)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
get_dyn_info_list_addr(unw_addr_space_t as UNUSED,unw_word_t * dilap UNUSED,void * arg UNUSED)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
put_unwind_info(unw_addr_space_t as UNUSED,unw_proc_info_t * pi UNUSED,void * arg UNUSED)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
resume(unw_addr_space_t as UNUSED,unw_cursor_t * reg UNUSED,void * arg UNUSED)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
get_proc_name(unw_addr_space_t as UNUSED,unw_word_t ip UNUSED,char * buf UNUSED,size_t buf_len UNUSED,unw_word_t * offp UNUSED,void * arg UNUSED)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
main(int argc,char ** argv)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