ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
callstack.c
Go to the documentation of this file.
1 /*
2  * $Xorg: getretmips.c,v 1.4 2001/02/09 02:06:19 xorgcvs Exp $
3  *
4 Copyright 1992, 1998 The Open Group
5 
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25  *
26  * Author: Keith Packard, MIT X Consortium
27  * cleaned up slighly by emoon and added ee related opcodes and checking.
28  */
29 
30 /* Return stack generation for MIPS processors
31  * This is tricky as MIPS stack frames aren't
32  * easily unrolled -- we look for pc restoration
33  * and stack adjustment instructions beyond the return
34  * address to discover the correct values
35  */
36 
37 /* lw $31,const($sp) is : 100 011 11101 11111 const */
38 /* 1000 1111 1011 1111 */
39 
40 #define RESTORE_RETURNVAL 0x8fbf0000
41 #define RESTORE_RETURNVAL_MASK 0xffff0000
42 
43 /* ld $31,const($sp) is : 110 111 11101 11111 const */
44 /* 1101 1111 1011 1111 */
45 
46 #define RESTORE_RETURNVAL2 0xdfbf0000
47 
48 /* lq $31,const($sp) is : 011110 11101 11111 const */
49 /* ee Related 0111 1011 1011 1111 */
50 
51 #define RESTORE_RETURNVAL3 0x7bbf0000
52 
53 /* addiu $sp, $sp, const is 001 001 11101 11101 const */
54 /* 0010 0111 1011 1101 const */
55 
56 #define ADJUST_STACKP_C 0x27bd0000
57 #define ADJUST_STACKP_C_MASK 0xffff0000
58 
59 /* addu $sp, $sp, $at is 000 000 11101 00001 11101 00000 100 001 */
60 /* 0000 0011 1010 0001 1110 1000 0010 0001 */
61 
62 #define ADJUST_STACKP_V 0x03a1e821
63 #define ADJUST_STACKP_V_MASK 0xffffffff
64 
65 /* lui $at, const is 001 111 00000 00001 const */
66 /* 0011 1100 0000 0001 const */
67 
68 #define SET_UPPER_C 0x3c010000
69 #define SET_UPPER_C_MASK 0xffff0000
70 
71 /* ori $at, $at, const is 001 101 00001 00001 const */
72 /* 0011 0100 0010 0001 const */
73 
74 #define OR_LOWER_C 0x34210000
75 #define OR_LOWER_C_MASK 0xffff0000
76 
77 /* ori $at, $zero, const is 001 101 00000 00001 const */
78 /* 0011 0100 0000 0001 const */
79 
80 #define SET_LOWER_C 0x34010000
81 #define SET_LOWER_C_MASK 0xffff0000
82 
83 /* jr $ra */
84 #define RETURN 0x03e00008
85 
86 #define CALL(f) (0x0c000000 | (((int) (f)) >> 2))
87 
88 /*
89  * This computation is expensive, so we cache the results;
90  * a simple hash function and straight-forward replacement.
91  */
92 
93 #define HASH_SIZE 256
94 
95 typedef struct _returnCache
96 {
97  unsigned int *returnAddress;
98  int raOffset;
99  int spAdjust;
100 } ReturnCacheRec, *ReturnCachePtr;
101 
103 
104 #define HASH(ra) ((((int) (ra)) >> 2) & (HASH_SIZE - 1))
105 
106 typedef int Bool;
107 
108 #ifndef TRUE
109 #define TRUE 1
110 #endif
111 #ifndef FALSE
112 #define FALSE 0
113 #endif
114 
115 extern unsigned int* ps2GetReturnAddress();
116 extern unsigned int* ps2GetStackPointer();
117 extern int main();
118 
119 void ps2GetStackTrace(unsigned int* results,int max)
120 {
121  unsigned int* ra;
122  unsigned int* ra_limit;
123  unsigned int* sp;
124  unsigned int inst;
125  unsigned int mainCall;
126  unsigned short const_upper;
127  unsigned short const_lower;
128  int ra_offset;
129  int sp_adjust;
130  Bool found_ra_offset, found_sp_adjust;
131  Bool found_const_upper, found_const_lower;
132  ReturnCachePtr rc;
133 
136  mainCall = CALL(main);
137 
138  while (ra && max)
139  {
140  rc = &returnCache[HASH(ra)];
141  if (rc->returnAddress != ra)
142  {
143  found_ra_offset = FALSE;
144  found_sp_adjust = FALSE;
145  found_const_upper = FALSE;
146  found_const_lower = FALSE;
147  const_upper = 0;
148  const_lower = 0;
149  rc->returnAddress = ra;
150  ra_limit = (unsigned int *) 0x200000;
151  ra_offset = 0;
152  sp_adjust = -1;
153 
154  while ((!found_ra_offset || !found_sp_adjust) && ra < ra_limit)
155  {
156  inst = *ra;
157  /* look for the offset of the PC in the stack frame */
159  {
160  ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
161  found_ra_offset = TRUE;
162  }
163  else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL2)
164  {
165  ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
166  found_ra_offset = TRUE;
167  }
168  else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL3)
169  {
170  ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
171  found_ra_offset = TRUE;
172  }
173  else if ((inst & ADJUST_STACKP_C_MASK) == ADJUST_STACKP_C)
174  {
175  sp_adjust = inst & ~ADJUST_STACKP_C_MASK;
176  found_sp_adjust = TRUE;
177  }
178  else if ((inst & ADJUST_STACKP_V_MASK) == ADJUST_STACKP_V)
179  {
180  sp_adjust = 0;
181  found_sp_adjust = TRUE;
182  }
183  else if ((inst & SET_UPPER_C_MASK) == SET_UPPER_C)
184  {
185  const_upper = inst & ~SET_UPPER_C_MASK;
186  const_lower = 0;
187  found_const_upper = TRUE;
188  }
189  else if ((inst & OR_LOWER_C_MASK) == OR_LOWER_C)
190  {
191  const_lower = inst & ~OR_LOWER_C_MASK;
192  found_const_lower = TRUE;
193  }
194  else if ((inst & SET_LOWER_C_MASK) == SET_LOWER_C)
195  {
196  const_lower = inst & ~SET_LOWER_C_MASK;
197  const_upper = 0;
198  found_const_lower = TRUE;
199  }
200  else if (inst == RETURN)
201  ra_limit = ra + 2;
202  ra++;
203  }
204 
205  if (sp_adjust == 0 && (found_const_upper || found_const_lower))
206  sp_adjust = (const_upper << 16) | const_lower;
207  rc->raOffset = ra_offset;
208  rc->spAdjust = sp_adjust;
209  }
210  /* if something went wrong, punt */
211  if (rc->spAdjust <= 0)
212  {
213  *results++ = 0;
214  break;
215  }
216 
217  ra = (unsigned int *) sp[rc->raOffset>>2];
218  sp += rc->spAdjust >> 2;
219 
220  if (ra == 0)
221  {
222  *results++ = 0;
223  break;
224  }
225 
226  *results++ = ((unsigned int) ra) - 8;
227  if (ra[-2] == mainCall)
228  {
229  *results++ = 0;
230  break;
231  }
232  max--;
233  }
234 }
235 
#define ra
Definition: as_reg_compat.h:87
#define sp
Definition: as_reg_compat.h:85
static ReturnCacheRec returnCache[HASH_SIZE]
Definition: callstack.c:102
#define ADJUST_STACKP_C
Definition: callstack.c:56
#define ADJUST_STACKP_V_MASK
Definition: callstack.c:63
#define RESTORE_RETURNVAL_MASK
Definition: callstack.c:41
#define CALL(f)
Definition: callstack.c:86
#define RESTORE_RETURNVAL3
Definition: callstack.c:51
#define OR_LOWER_C
Definition: callstack.c:74
#define RESTORE_RETURNVAL2
Definition: callstack.c:46
void ps2GetStackTrace(unsigned int *results, int max)
Definition: callstack.c:119
#define HASH(ra)
Definition: callstack.c:104
#define RETURN
Definition: callstack.c:84
#define RESTORE_RETURNVAL
Definition: callstack.c:40
#define OR_LOWER_C_MASK
Definition: callstack.c:75
#define TRUE
Definition: callstack.c:109
#define FALSE
Definition: callstack.c:112
unsigned int * ps2GetReturnAddress()
#define SET_LOWER_C
Definition: callstack.c:80
unsigned int * ps2GetStackPointer()
#define SET_LOWER_C_MASK
Definition: callstack.c:81
#define SET_UPPER_C_MASK
Definition: callstack.c:69
#define HASH_SIZE
Definition: callstack.c:93
#define ADJUST_STACKP_C_MASK
Definition: callstack.c:57
#define ADJUST_STACKP_V
Definition: callstack.c:62
int main()
Definition: callstacktest.c:45
#define SET_UPPER_C
Definition: callstack.c:68
int Bool
Definition: callstack.c:106
#define max(a, b)
Definition: standard.h:57
unsigned int * returnAddress
Definition: callstack.c:97