1/*
| 1/*
|
2Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
| 2Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
|
3Permission is hereby granted, free of charge, to any person 4obtaining a copy of this software and associated documentation 5files (the "Software"), to deal in the Software without 6restriction, including without limitation the rights to use, 7copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following 10conditions: 11 12The above copyright notice and this permission notice shall be 13included in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22OTHER DEALINGS IN THE SOFTWARE. 23*/ 24 25#include "uwx_env.h" 26#include "uwx_context.h" 27#include "uwx_utable.h" 28#include "uwx_uinfo.h" 29#include "uwx_scoreboard.h" 30#include "uwx_str.h" 31#include "uwx_step.h" 32#include "uwx_trace.h" 33 34/* 35 * uwx_step.c 36 * 37 * This file contains the routines for stepping from one frame 38 * into its callers frame. The context for the current frame 39 * is maintained inside the current unwind environment 40 * (struct uwx_env), and is updated with each call to 41 * uwx_step() to refer to the previous frame. 42 */ 43 44 45/* Forward Declarations */ 46 47int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate); 48int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, 49 uint64_t *valp, uint64_t *histp); 50int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, 51 uint64_t *valp, uint64_t *histp); 52int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat); 53 54 55/* uwx_lookupip_hook: Hook routine so dynamic instrumentation */ 56/* tools can intercept Lookup IP events. When not */ 57/* intercepted, it just returns "Not found", so that */ 58/* the callback routine is invoked. */ 59 60/*ARGSUSED*/ 61int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp, 62 size_t uvecsize) 63{ 64 return UWX_LKUP_NOTFOUND; 65} 66 67 68/* uwx_get_frame_info: Gets unwind info for current frame */
| 3Permission is hereby granted, free of charge, to any person 4obtaining a copy of this software and associated documentation 5files (the "Software"), to deal in the Software without 6restriction, including without limitation the rights to use, 7copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following 10conditions: 11 12The above copyright notice and this permission notice shall be 13included in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22OTHER DEALINGS IN THE SOFTWARE. 23*/ 24 25#include "uwx_env.h" 26#include "uwx_context.h" 27#include "uwx_utable.h" 28#include "uwx_uinfo.h" 29#include "uwx_scoreboard.h" 30#include "uwx_str.h" 31#include "uwx_step.h" 32#include "uwx_trace.h" 33 34/* 35 * uwx_step.c 36 * 37 * This file contains the routines for stepping from one frame 38 * into its callers frame. The context for the current frame 39 * is maintained inside the current unwind environment 40 * (struct uwx_env), and is updated with each call to 41 * uwx_step() to refer to the previous frame. 42 */ 43 44 45/* Forward Declarations */ 46 47int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate); 48int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, 49 uint64_t *valp, uint64_t *histp); 50int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, 51 uint64_t *valp, uint64_t *histp); 52int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat); 53 54 55/* uwx_lookupip_hook: Hook routine so dynamic instrumentation */ 56/* tools can intercept Lookup IP events. When not */ 57/* intercepted, it just returns "Not found", so that */ 58/* the callback routine is invoked. */ 59 60/*ARGSUSED*/ 61int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp, 62 size_t uvecsize) 63{ 64 return UWX_LKUP_NOTFOUND; 65} 66 67 68/* uwx_get_frame_info: Gets unwind info for current frame */
|
69static
| 69
|
70int uwx_get_frame_info(struct uwx_env *env) 71{ 72 int i; 73 int status; 74 int cbstatus; 75 int cbcalled = 0; 76 uint64_t ip; 77 uint64_t *uvec; 78 uint64_t *rstate; 79 struct uwx_utable_entry uentry;
| 70int uwx_get_frame_info(struct uwx_env *env) 71{ 72 int i; 73 int status; 74 int cbstatus; 75 int cbcalled = 0; 76 uint64_t ip; 77 uint64_t *uvec; 78 uint64_t *rstate; 79 struct uwx_utable_entry uentry;
|
| 80 uint64_t uinfop;
|
80 uint64_t uvecout[UVECSIZE]; 81 82 if (env->copyin == 0 || env->lookupip == 0) 83 return UWX_ERR_NOCALLBACKS; 84
| 81 uint64_t uvecout[UVECSIZE]; 82 83 if (env->copyin == 0 || env->lookupip == 0) 84 return UWX_ERR_NOCALLBACKS; 85
|
| 86 env->ptr_size = DWORDSZ; 87 env->code_start = 0;
|
85 env->function_offset = -1LL; 86 env->function_name = 0; 87 env->module_name = 0;
| 88 env->function_offset = -1LL; 89 env->function_name = 0; 90 env->module_name = 0;
|
| 91 env->abi_context = 0;
|
88 uwx_reset_str_pool(env); 89 90 /* Use the lookup IP callback routine to find out about the */ 91 /* current IP. If the predicate registers are valid, pass them */ 92 /* in the uvec. */ 93 94 /* When self-unwinding, we call a hook routine before the */ 95 /* callback. If the application is running under control of */ 96 /* a dynamic instrumentation tool, that tool will have an */ 97 /* opportunity to intercept lookup IP requests. */ 98 99 i = 0; 100 uvecout[i++] = UWX_KEY_VERSION; 101 uvecout[i++] = UWX_VERSION; 102 if (env->context.valid_regs & (1 << UWX_REG_PREDS)) { 103 uvecout[i++] = UWX_KEY_PREDS; 104 uvecout[i++] = env->context.special[UWX_REG_PREDS]; 105 } 106 uvecout[i++] = UWX_KEY_END; 107 uvecout[i++] = 0; 108 uvec = uvecout; 109 cbstatus = UWX_LKUP_NOTFOUND; 110 ip = env->context.special[UWX_REG_IP]; 111 env->remapped_ip = ip; 112 113 /* Call the hook routine. */ 114 115 if (env->remote == 0) 116 cbstatus = uwx_lookupip_hook(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec, 117 sizeof(uvecout)); 118 119 /* If the hook routine remapped the IP, use the new IP for */ 120 /* the callback instead of the original IP. */ 121 122 if (cbstatus == UWX_LKUP_REMAP) { 123 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 124 switch ((int)uvec[i]) { 125 case UWX_KEY_NEWIP: 126 ip = uvec[i+1]; 127 break; 128 } 129 } 130 env->remapped_ip = ip; 131 } 132 133 /* Now call the callback routine unless the hook routine gave */ 134 /* us all the info. */ 135 136 if (cbstatus == UWX_LKUP_NOTFOUND || cbstatus == UWX_LKUP_REMAP) { 137 cbcalled = 1; 138 cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); 139 } 140 141 /* If the callback routine remapped the IP, call it one more time */ 142 /* with the new IP. */ 143 144 if (cbstatus == UWX_LKUP_REMAP) { 145 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 146 switch ((int)uvec[i]) { 147 case UWX_KEY_NEWIP: 148 ip = uvec[i+1]; 149 break; 150 } 151 } 152 env->remapped_ip = ip; 153 cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); 154 } 155 156 /* If NOTFOUND, there's nothing we can do but return an error. */ 157 158 if (cbstatus == UWX_LKUP_NOTFOUND) { 159 status = UWX_ERR_IPNOTFOUND; 160 } 161 162 /* If the callback returns an unwind table, we need to */ 163 /* search the table for an unwind entry that describes the */ 164 /* code region of interest, then decode the unwind information */ 165 /* associated with that unwind table entry, and store the */ 166 /* resulting register state array in the unwind environment */ 167 /* block. */ 168 169 else if (cbstatus == UWX_LKUP_UTABLE) { 170 status = uwx_search_utable(env, ip, uvec, &uentry); 171 if (cbcalled) 172 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
| 92 uwx_reset_str_pool(env); 93 94 /* Use the lookup IP callback routine to find out about the */ 95 /* current IP. If the predicate registers are valid, pass them */ 96 /* in the uvec. */ 97 98 /* When self-unwinding, we call a hook routine before the */ 99 /* callback. If the application is running under control of */ 100 /* a dynamic instrumentation tool, that tool will have an */ 101 /* opportunity to intercept lookup IP requests. */ 102 103 i = 0; 104 uvecout[i++] = UWX_KEY_VERSION; 105 uvecout[i++] = UWX_VERSION; 106 if (env->context.valid_regs & (1 << UWX_REG_PREDS)) { 107 uvecout[i++] = UWX_KEY_PREDS; 108 uvecout[i++] = env->context.special[UWX_REG_PREDS]; 109 } 110 uvecout[i++] = UWX_KEY_END; 111 uvecout[i++] = 0; 112 uvec = uvecout; 113 cbstatus = UWX_LKUP_NOTFOUND; 114 ip = env->context.special[UWX_REG_IP]; 115 env->remapped_ip = ip; 116 117 /* Call the hook routine. */ 118 119 if (env->remote == 0) 120 cbstatus = uwx_lookupip_hook(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec, 121 sizeof(uvecout)); 122 123 /* If the hook routine remapped the IP, use the new IP for */ 124 /* the callback instead of the original IP. */ 125 126 if (cbstatus == UWX_LKUP_REMAP) { 127 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 128 switch ((int)uvec[i]) { 129 case UWX_KEY_NEWIP: 130 ip = uvec[i+1]; 131 break; 132 } 133 } 134 env->remapped_ip = ip; 135 } 136 137 /* Now call the callback routine unless the hook routine gave */ 138 /* us all the info. */ 139 140 if (cbstatus == UWX_LKUP_NOTFOUND || cbstatus == UWX_LKUP_REMAP) { 141 cbcalled = 1; 142 cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); 143 } 144 145 /* If the callback routine remapped the IP, call it one more time */ 146 /* with the new IP. */ 147 148 if (cbstatus == UWX_LKUP_REMAP) { 149 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 150 switch ((int)uvec[i]) { 151 case UWX_KEY_NEWIP: 152 ip = uvec[i+1]; 153 break; 154 } 155 } 156 env->remapped_ip = ip; 157 cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); 158 } 159 160 /* If NOTFOUND, there's nothing we can do but return an error. */ 161 162 if (cbstatus == UWX_LKUP_NOTFOUND) { 163 status = UWX_ERR_IPNOTFOUND; 164 } 165 166 /* If the callback returns an unwind table, we need to */ 167 /* search the table for an unwind entry that describes the */ 168 /* code region of interest, then decode the unwind information */ 169 /* associated with that unwind table entry, and store the */ 170 /* resulting register state array in the unwind environment */ 171 /* block. */ 172 173 else if (cbstatus == UWX_LKUP_UTABLE) { 174 status = uwx_search_utable(env, ip, uvec, &uentry); 175 if (cbcalled) 176 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
|
173 if (status == UWX_OK)
| 177 if (status == UWX_OK) { 178 env->ptr_size = uentry.ptr_size; 179 env->code_start = uentry.code_start;
|
174 status = uwx_decode_uinfo(env, &uentry, &rstate);
| 180 status = uwx_decode_uinfo(env, &uentry, &rstate);
|
175 else if (status == UWX_ERR_NOUENTRY)
| 181 } 182 if (status == UWX_ERR_NOUENTRY || status == UWX_ERR_NOUDESC)
|
176 status = uwx_default_rstate(env, &rstate); 177 if (status == UWX_OK) 178 env->rstate = rstate; 179 } 180 181 /* If the callback returns an unwind info block, we can */ 182 /* proceed directly to decoding the unwind information. */ 183 184 else if (cbstatus == UWX_LKUP_UINFO) {
| 183 status = uwx_default_rstate(env, &rstate); 184 if (status == UWX_OK) 185 env->rstate = rstate; 186 } 187 188 /* If the callback returns an unwind info block, we can */ 189 /* proceed directly to decoding the unwind information. */ 190 191 else if (cbstatus == UWX_LKUP_UINFO) {
|
| 192 uentry.ptr_size = DWORDSZ;
|
185 uentry.code_start = 0; 186 uentry.code_end = 0; 187 uentry.unwind_info = 0; 188 uentry.unwind_flags = 0; 189 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 190 switch ((int)uvec[i]) { 191 case UWX_KEY_UFLAGS: 192 uentry.unwind_flags = uvec[i+1];
| 193 uentry.code_start = 0; 194 uentry.code_end = 0; 195 uentry.unwind_info = 0; 196 uentry.unwind_flags = 0; 197 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 198 switch ((int)uvec[i]) { 199 case UWX_KEY_UFLAGS: 200 uentry.unwind_flags = uvec[i+1];
|
| 201 if (uentry.unwind_flags & UNWIND_TBL_32BIT) 202 uentry.ptr_size = WORDSZ;
|
193 break; 194 case UWX_KEY_UINFO: 195 uentry.unwind_info = uvec[i+1]; 196 break;
| 203 break; 204 case UWX_KEY_UINFO: 205 uentry.unwind_info = uvec[i+1]; 206 break;
|
| 207 case UWX_KEY_GP: 208 uwx_set_reg(env, UWX_REG_GP, uvec[i+1]); 209 break;
|
197 case UWX_KEY_MODULE: 198 env->module_name =
| 210 case UWX_KEY_MODULE: 211 env->module_name =
|
199 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 212 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
200 break; 201 case UWX_KEY_FUNC: 202 env->function_name =
| 213 break; 214 case UWX_KEY_FUNC: 215 env->function_name =
|
203 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 216 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
204 break; 205 case UWX_KEY_FUNCSTART: 206 uentry.code_start = uvec[i+1];
| 217 break; 218 case UWX_KEY_FUNCSTART: 219 uentry.code_start = uvec[i+1];
|
| 220 env->code_start = uentry.code_start;
|
207 break; 208 } 209 }
| 221 break; 222 } 223 }
|
| 224 env->ptr_size = uentry.ptr_size;
|
210 if (cbcalled) 211 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 212 status = uwx_decode_uinfo(env, &uentry, &rstate);
| 225 if (cbcalled) 226 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 227 status = uwx_decode_uinfo(env, &uentry, &rstate);
|
| 228 if (status == UWX_ERR_NOUDESC) 229 status = uwx_default_rstate(env, &rstate);
|
213 if (status == UWX_OK) 214 env->rstate = rstate; 215 } 216 217 /* If the callback returns a frame description (in the form */ 218 /* of an update vector), convert the update vector into a */ 219 /* register state array, then invoke the callback again to */ 220 /* let it free any memory it allocated. */ 221 222 else if (cbstatus == UWX_LKUP_FDESC) { 223 status = uwx_decode_uvec(env, uvec, &rstate); 224 if (cbcalled) 225 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 226 if (status == UWX_OK) 227 env->rstate = rstate; 228 } 229 230 /* Any other return from the callback is an error. */ 231 232 else { 233 status = UWX_ERR_LOOKUPERR; 234 } 235 return status; 236} 237 238 239/* uwx_restore_markers: Restores the stack markers -- PSP, RP, PFS */ 240 241int uwx_restore_markers(struct uwx_env *env) 242{ 243 int status; 244 uint64_t val; 245 uint64_t hist; 246 247 if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4) 248 return UWX_ERR_NOCONTEXT; 249 250 /* If we haven't already obtained the frame info for the */ 251 /* current frame, get it now. */ 252 253 if (env->rstate == 0) { 254 status = uwx_get_frame_info(env); 255 if (status != UWX_OK) 256 return status; 257 } 258 259 TRACE_S_STEP(env->rstate) 260 261 if (env->rstate[SBREG_PSP] != UWX_DISP_NONE) { 262 status = uwx_restore_reg(env, env->rstate[SBREG_PSP], &val, &hist); 263 if (status != UWX_OK) 264 return status; 265 env->context.special[UWX_REG_PSP] = val; 266 env->history.special[UWX_REG_PSP] = hist; 267 env->context.valid_regs |= 1 << UWX_REG_PSP; 268 TRACE_S_RESTORE_REG("PSP", env->rstate[SBREG_PSP], val) 269 } 270 271 if (env->rstate[SBREG_RP] != UWX_DISP_NONE) { 272 status = uwx_restore_reg(env, env->rstate[SBREG_RP], &val, &hist); 273 if (status != UWX_OK) 274 return status; 275 env->context.special[UWX_REG_RP] = val; 276 env->history.special[UWX_REG_RP] = hist; 277 env->context.valid_regs |= 1 << UWX_REG_RP; 278 TRACE_S_RESTORE_REG("RP", env->rstate[SBREG_RP], val) 279 } 280 281 if (env->rstate[SBREG_PFS] != UWX_DISP_NONE) { 282 status = uwx_restore_reg(env, env->rstate[SBREG_PFS], &val, &hist); 283 if (status != UWX_OK) 284 return status; 285 env->context.special[UWX_REG_PFS] = val; 286 env->history.special[UWX_REG_PFS] = hist; 287 env->context.valid_regs |= 1 << UWX_REG_PFS; 288 TRACE_S_RESTORE_REG("PFS", env->rstate[SBREG_PFS], val) 289 } 290 291 return UWX_OK; 292} 293
| 230 if (status == UWX_OK) 231 env->rstate = rstate; 232 } 233 234 /* If the callback returns a frame description (in the form */ 235 /* of an update vector), convert the update vector into a */ 236 /* register state array, then invoke the callback again to */ 237 /* let it free any memory it allocated. */ 238 239 else if (cbstatus == UWX_LKUP_FDESC) { 240 status = uwx_decode_uvec(env, uvec, &rstate); 241 if (cbcalled) 242 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 243 if (status == UWX_OK) 244 env->rstate = rstate; 245 } 246 247 /* Any other return from the callback is an error. */ 248 249 else { 250 status = UWX_ERR_LOOKUPERR; 251 } 252 return status; 253} 254 255 256/* uwx_restore_markers: Restores the stack markers -- PSP, RP, PFS */ 257 258int uwx_restore_markers(struct uwx_env *env) 259{ 260 int status; 261 uint64_t val; 262 uint64_t hist; 263 264 if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4) 265 return UWX_ERR_NOCONTEXT; 266 267 /* If we haven't already obtained the frame info for the */ 268 /* current frame, get it now. */ 269 270 if (env->rstate == 0) { 271 status = uwx_get_frame_info(env); 272 if (status != UWX_OK) 273 return status; 274 } 275 276 TRACE_S_STEP(env->rstate) 277 278 if (env->rstate[SBREG_PSP] != UWX_DISP_NONE) { 279 status = uwx_restore_reg(env, env->rstate[SBREG_PSP], &val, &hist); 280 if (status != UWX_OK) 281 return status; 282 env->context.special[UWX_REG_PSP] = val; 283 env->history.special[UWX_REG_PSP] = hist; 284 env->context.valid_regs |= 1 << UWX_REG_PSP; 285 TRACE_S_RESTORE_REG("PSP", env->rstate[SBREG_PSP], val) 286 } 287 288 if (env->rstate[SBREG_RP] != UWX_DISP_NONE) { 289 status = uwx_restore_reg(env, env->rstate[SBREG_RP], &val, &hist); 290 if (status != UWX_OK) 291 return status; 292 env->context.special[UWX_REG_RP] = val; 293 env->history.special[UWX_REG_RP] = hist; 294 env->context.valid_regs |= 1 << UWX_REG_RP; 295 TRACE_S_RESTORE_REG("RP", env->rstate[SBREG_RP], val) 296 } 297 298 if (env->rstate[SBREG_PFS] != UWX_DISP_NONE) { 299 status = uwx_restore_reg(env, env->rstate[SBREG_PFS], &val, &hist); 300 if (status != UWX_OK) 301 return status; 302 env->context.special[UWX_REG_PFS] = val; 303 env->history.special[UWX_REG_PFS] = hist; 304 env->context.valid_regs |= 1 << UWX_REG_PFS; 305 TRACE_S_RESTORE_REG("PFS", env->rstate[SBREG_PFS], val) 306 } 307 308 return UWX_OK; 309} 310
|
| 311/* uwx_get_module_info: Gets module name and text base for current frame */ 312 313int uwx_get_module_info( 314 struct uwx_env *env, 315 char **modp, 316 uint64_t *text_base) 317{ 318 int i; 319 int status; 320 int cbstatus; 321 uint64_t ip; 322 uint64_t *uvec; 323 uint64_t uvecout[UVECSIZE]; 324 325 if (env == 0) 326 return UWX_ERR_NOENV; 327 328 /* If we haven't already obtained the frame info for the */ 329 /* current frame, get it now. */ 330 331 if (env->rstate == 0) { 332 status = uwx_get_frame_info(env); 333 if (status != UWX_OK) 334 return status; 335 } 336 337 /* Get the module name from the lookup IP callback. */ 338 if (env->module_name == 0) { 339 ip = env->remapped_ip; 340 i = 0; 341 if (env->function_offset >= 0) { 342 uvecout[i++] = UWX_KEY_FUNCSTART; 343 uvecout[i++] = ip - env->function_offset; 344 } 345 uvecout[i++] = UWX_KEY_END; 346 uvecout[i++] = 0; 347 uvec = uvecout; 348 cbstatus = (*env->lookupip)(UWX_LKUP_MODULE, ip, env->cb_token, &uvec); 349 350 if (cbstatus == UWX_LKUP_SYMINFO) { 351 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 352 switch ((int)uvec[i]) { 353 case UWX_KEY_TBASE: 354 env->text_base = uvec[i+1]; 355 break; 356 case UWX_KEY_MODULE: 357 env->module_name = 358 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); 359 break; 360 case UWX_KEY_FUNC: 361 env->function_name = 362 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); 363 break; 364 case UWX_KEY_FUNCSTART: 365 env->function_offset = ip - uvec[i+1]; 366 break; 367 } 368 } 369 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 370 } 371 } 372 373 *modp = env->module_name; 374 *text_base = env->text_base; 375 376 return UWX_OK; 377} 378 379/* uwx_get_funcstart: Gets start address of function from current frame */ 380 381int uwx_get_funcstart( 382 struct uwx_env *env, 383 uint64_t *funcstart) 384{ 385 int status; 386 uint64_t *uvec; 387 uint64_t uvecout[UVECSIZE]; 388 389 if (env == 0) 390 return UWX_ERR_NOENV; 391 392 /* If we haven't already obtained the frame info for the */ 393 /* current frame, get it now. */ 394 395 if (env->rstate == 0) { 396 status = uwx_get_frame_info(env); 397 if (status != UWX_OK) 398 return status; 399 } 400 401 *funcstart = env->remapped_ip - env->function_offset; 402 403 return UWX_OK; 404} 405
|
294/* uwx_get_sym_info: Gets symbolic info from current frame */
| 406/* uwx_get_sym_info: Gets symbolic info from current frame */
|
| 407/* (Will make a UWX_LKUP_SYMBOLS callback if info */ 408/* was not provided by UWX_LKUP_LOOKUP callback) */
|
295 296int uwx_get_sym_info( 297 struct uwx_env *env, 298 char **modp, 299 char **symp, 300 uint64_t *offsetp) 301{ 302 int status; 303 int cbstatus; 304 uint64_t ip; 305 uint64_t *uvec;
| 409 410int uwx_get_sym_info( 411 struct uwx_env *env, 412 char **modp, 413 char **symp, 414 uint64_t *offsetp) 415{ 416 int status; 417 int cbstatus; 418 uint64_t ip; 419 uint64_t *uvec;
|
306 uint64_t uvecout[2];
| 420 uint64_t uvecout[UVECSIZE];
|
307 int i; 308 309 if (env == 0) 310 return UWX_ERR_NOENV; 311 312 /* If we haven't already obtained the frame info for the */ 313 /* current frame, get it now. */ 314 315 if (env->rstate == 0) { 316 status = uwx_get_frame_info(env); 317 if (status != UWX_OK) 318 return status; 319 } 320 321 /* Get the symbolic information from the lookup IP callback. */ 322 if (env->function_name == 0) { 323 ip = env->remapped_ip; 324 i = 0; 325 if (env->function_offset >= 0) { 326 uvecout[i++] = UWX_KEY_FUNCSTART; 327 uvecout[i++] = ip - env->function_offset; 328 } 329 uvecout[i++] = UWX_KEY_END; 330 uvecout[i++] = 0; 331 uvec = uvecout; 332 cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS, ip, env->cb_token, &uvec); 333 334 if (cbstatus == UWX_LKUP_SYMINFO) { 335 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 336 switch ((int)uvec[i]) { 337 case UWX_KEY_MODULE: 338 env->module_name =
| 421 int i; 422 423 if (env == 0) 424 return UWX_ERR_NOENV; 425 426 /* If we haven't already obtained the frame info for the */ 427 /* current frame, get it now. */ 428 429 if (env->rstate == 0) { 430 status = uwx_get_frame_info(env); 431 if (status != UWX_OK) 432 return status; 433 } 434 435 /* Get the symbolic information from the lookup IP callback. */ 436 if (env->function_name == 0) { 437 ip = env->remapped_ip; 438 i = 0; 439 if (env->function_offset >= 0) { 440 uvecout[i++] = UWX_KEY_FUNCSTART; 441 uvecout[i++] = ip - env->function_offset; 442 } 443 uvecout[i++] = UWX_KEY_END; 444 uvecout[i++] = 0; 445 uvec = uvecout; 446 cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS, ip, env->cb_token, &uvec); 447 448 if (cbstatus == UWX_LKUP_SYMINFO) { 449 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 450 switch ((int)uvec[i]) { 451 case UWX_KEY_MODULE: 452 env->module_name =
|
339 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 453 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
340 break; 341 case UWX_KEY_FUNC: 342 env->function_name =
| 454 break; 455 case UWX_KEY_FUNC: 456 env->function_name =
|
343 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 457 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
344 break; 345 case UWX_KEY_FUNCSTART: 346 env->function_offset = ip - uvec[i+1]; 347 break; 348 } 349 } 350 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 351 } 352 } 353 354 *modp = env->module_name; 355 *symp = env->function_name; 356 *offsetp = env->function_offset; 357 358 return UWX_OK; 359} 360 361 362/* uwx_step: Steps from the current frame to the previous frame */ 363 364int uwx_step(struct uwx_env *env) 365{ 366 int i; 367 int status; 368 int pfs_sol; 369 int dispcode; 370 uint64_t val; 371 uint64_t fval[2]; 372 uint64_t hist; 373 uint64_t tempgr[NPRESERVEDGR]; 374 int needpriunat; 375 int unat; 376 int tempnat; 377 378 if (env == 0) 379 return UWX_ERR_NOENV; 380 381 /* Complete the current context by restoring the current values */ 382 /* of psp, rp, and pfs. */ 383 384 if (env->rstate == 0 || 385 (env->context.valid_regs & VALID_MARKERS) != VALID_MARKERS) { 386 status = uwx_restore_markers(env); 387 if (status != UWX_OK) 388 return status; 389 } 390 391 /* Check for bottom of stack (rp == 0). */ 392 393 if (env->context.special[UWX_REG_RP] == 0) 394 return UWX_BOTTOM; 395 396 /* Find where the primary unat is saved, get a copy. */ 397 /* Then, as we restore the GRs, we'll merge the NaT bits into the */ 398 /* priunat register in the context. */ 399 /* (Make sure we need it, though, before we try to get it, */ 400 /* because the attempt to get it might invoke the copy-in callback. */ 401 /* We don't need the priunat unless one of GR 4-7 was */ 402 /* saved to the memory stack.) */ 403 404 needpriunat = 0; 405 for (i = 0; i < NSB_GR; i++) { 406 dispcode = UWX_GET_DISP_CODE(env->rstate[SBREG_GR + i]); 407 if (dispcode == UWX_DISP_SPREL(0) || dispcode == UWX_DISP_PSPREL(0)) 408 needpriunat = 1; 409 } 410 unat = 0; 411 if (needpriunat && env->rstate[SBREG_PRIUNAT] != UWX_DISP_NONE) { 412 status = uwx_restore_reg(env, env->rstate[SBREG_PRIUNAT], &val, &hist); 413 if (status != UWX_OK) 414 return status; 415 unat = (int) val; 416 env->history.special[UWX_REG_PRIUNAT] = hist; 417 TRACE_S_RESTORE_REG("PRIUNAT", env->rstate[SBREG_PRIUNAT], val) 418 } 419 420 /* Retrieve saved values of the preserved GRs into temporaries. */ 421 422 tempnat = (int) env->context.special[UWX_REG_PRIUNAT]; 423 for (i = 0; i < NSB_GR; i++) { 424 if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) { 425 status = uwx_restore_reg(env, 426 env->rstate[SBREG_GR + i], &val, &hist); 427 if (status != UWX_OK) 428 return status; 429 tempgr[i] = val; 430 if (uwx_restore_nat(env, env->rstate[SBREG_GR + i], unat)) 431 tempnat |= 1 << i; 432 else 433 tempnat &= ~(1 << i); 434 env->history.gr[i] = hist; 435 env->context.valid_regs |= 1 << (i + VALID_GR_SHIFT); 436 TRACE_S_RESTORE_GR(i, env->rstate[SBREG_GR + i], val) 437 } 438 } 439 440 /* Now we have everything we need to step back to the previous frame. */ 441 442 /* Restore preserved BRs. */ 443 444 for (i = 0; i < NSB_BR; i++) { 445 if (env->rstate[SBREG_BR + i] != UWX_DISP_NONE) { 446 status = uwx_restore_reg(env, 447 env->rstate[SBREG_BR + i], &val, &hist); 448 if (status != UWX_OK) 449 return status; 450 env->context.br[i] = val; 451 env->history.br[i] = hist; 452 env->context.valid_regs |= 1 << (i + VALID_BR_SHIFT); 453 TRACE_S_RESTORE_BR(i, env->rstate[SBREG_BR + i], val) 454 } 455 } 456 457 /* Restore preserved FRs. */ 458 459 if (env->nsbreg == NSBREG) { 460 for (i = 0; i < NSB_FR; i++) { 461 if (env->rstate[SBREG_FR + i] != UWX_DISP_NONE) { 462 status = uwx_restore_freg(env, 463 env->rstate[SBREG_FR + i], fval, &hist); 464 if (status != UWX_OK) 465 return status; 466 env->context.fr[i].part0 = fval[0]; 467 env->context.fr[i].part1 = fval[1]; 468 env->history.fr[i] = hist; 469 env->context.valid_frs |= 1 << i; 470 TRACE_S_RESTORE_FR(i, env->rstate[SBREG_FR + i], fval) 471 } 472 } 473 } 474 475 /* Restore other preserved regs. */ 476 477 if (env->rstate[SBREG_PREDS] != UWX_DISP_NONE) { 478 status = uwx_restore_reg(env, env->rstate[SBREG_PREDS], &val, &hist); 479 if (status != UWX_OK) 480 return status; 481 env->context.special[UWX_REG_PREDS] = val; 482 env->history.special[UWX_REG_PREDS] = hist; 483 env->context.valid_regs |= 1 << UWX_REG_PREDS; 484 TRACE_S_RESTORE_REG("PREDS", env->rstate[SBREG_PREDS], val) 485 } 486 if (env->rstate[SBREG_RNAT] != UWX_DISP_NONE) { 487 status = uwx_restore_reg(env, env->rstate[SBREG_RNAT], &val, &hist); 488 if (status != UWX_OK) 489 return status; 490 env->context.special[UWX_REG_AR_RNAT] = val; 491 env->history.special[UWX_REG_AR_RNAT] = hist; 492 env->context.valid_regs |= 1 << UWX_REG_AR_RNAT; 493 TRACE_S_RESTORE_REG("RNAT", env->rstate[SBREG_RNAT], val) 494 } 495 if (env->rstate[SBREG_UNAT] != UWX_DISP_NONE) { 496 status = uwx_restore_reg(env, env->rstate[SBREG_UNAT], &val, &hist); 497 if (status != UWX_OK) 498 return status; 499 env->context.special[UWX_REG_AR_UNAT] = val; 500 env->history.special[UWX_REG_AR_UNAT] = hist; 501 env->context.valid_regs |= 1 << UWX_REG_AR_UNAT; 502 TRACE_S_RESTORE_REG("UNAT", env->rstate[SBREG_UNAT], val) 503 } 504 if (env->rstate[SBREG_FPSR] != UWX_DISP_NONE) { 505 status = uwx_restore_reg(env, env->rstate[SBREG_FPSR], &val, &hist); 506 if (status != UWX_OK) 507 return status; 508 env->context.special[UWX_REG_AR_FPSR] = val; 509 env->history.special[UWX_REG_AR_FPSR] = hist; 510 env->context.valid_regs |= 1 << UWX_REG_AR_FPSR; 511 TRACE_S_RESTORE_REG("FPSR", env->rstate[SBREG_FPSR], val) 512 } 513 if (env->rstate[SBREG_LC] != UWX_DISP_NONE) { 514 status = uwx_restore_reg(env, env->rstate[SBREG_LC], &val, &hist); 515 if (status != UWX_OK) 516 return status; 517 env->context.special[UWX_REG_AR_LC] = val; 518 env->history.special[UWX_REG_AR_LC] = hist; 519 env->context.valid_regs |= 1 << UWX_REG_AR_LC; 520 TRACE_S_RESTORE_REG("LC", env->rstate[SBREG_LC], val) 521 } 522 523 /* Restore preserved GRs from temporaries. */ 524 525 for (i = 0; i < NSB_GR; i++) { 526 if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) 527 env->context.gr[i] = tempgr[i]; 528 } 529 env->context.special[UWX_REG_PRIUNAT] = tempnat; 530 531 /* Restore the frame markers. */ 532 533 env->context.special[UWX_REG_IP] = env->context.special[UWX_REG_RP]; 534 env->history.special[UWX_REG_IP] = env->history.special[UWX_REG_RP]; 535 536 env->context.special[UWX_REG_SP] = env->context.special[UWX_REG_PSP]; 537 env->history.special[UWX_REG_SP] = env->history.special[UWX_REG_PSP]; 538 539 pfs_sol = ((unsigned int)env->context.special[UWX_REG_PFS] >> 7) & 0x7f; 540 env->context.special[UWX_REG_BSP] = uwx_add_to_bsp( 541 env->context.special[UWX_REG_BSP], 542 -pfs_sol); 543 544 env->context.special[UWX_REG_CFM] = env->context.special[UWX_REG_PFS]; 545 env->history.special[UWX_REG_CFM] = env->history.special[UWX_REG_PFS]; 546 547 env->context.special[UWX_REG_RP] = 0; 548 549 /* The frame info for the new frame isn't yet available. */ 550 551 env->rstate = 0; 552 env->context.valid_regs &= ~VALID_MARKERS; 553 554 return UWX_OK; 555} 556 557 558/* uwx_decode_uvec: Converts the update vector into a register state array */ 559 560int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate) 561{ 562 int i; 563 int status; 564 565 status = uwx_default_rstate(env, rstate); 566 if (status != UWX_OK) 567 return status; 568 569 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 570 switch ((int)uvec[i]) { 571 case UWX_KEY_CONTEXT: 572 env->abi_context = (int)(uvec[i+1]); 573 status = UWX_ABI_FRAME; 574 break;
| 458 break; 459 case UWX_KEY_FUNCSTART: 460 env->function_offset = ip - uvec[i+1]; 461 break; 462 } 463 } 464 (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); 465 } 466 } 467 468 *modp = env->module_name; 469 *symp = env->function_name; 470 *offsetp = env->function_offset; 471 472 return UWX_OK; 473} 474 475 476/* uwx_step: Steps from the current frame to the previous frame */ 477 478int uwx_step(struct uwx_env *env) 479{ 480 int i; 481 int status; 482 int pfs_sol; 483 int dispcode; 484 uint64_t val; 485 uint64_t fval[2]; 486 uint64_t hist; 487 uint64_t tempgr[NPRESERVEDGR]; 488 int needpriunat; 489 int unat; 490 int tempnat; 491 492 if (env == 0) 493 return UWX_ERR_NOENV; 494 495 /* Complete the current context by restoring the current values */ 496 /* of psp, rp, and pfs. */ 497 498 if (env->rstate == 0 || 499 (env->context.valid_regs & VALID_MARKERS) != VALID_MARKERS) { 500 status = uwx_restore_markers(env); 501 if (status != UWX_OK) 502 return status; 503 } 504 505 /* Check for bottom of stack (rp == 0). */ 506 507 if (env->context.special[UWX_REG_RP] == 0) 508 return UWX_BOTTOM; 509 510 /* Find where the primary unat is saved, get a copy. */ 511 /* Then, as we restore the GRs, we'll merge the NaT bits into the */ 512 /* priunat register in the context. */ 513 /* (Make sure we need it, though, before we try to get it, */ 514 /* because the attempt to get it might invoke the copy-in callback. */ 515 /* We don't need the priunat unless one of GR 4-7 was */ 516 /* saved to the memory stack.) */ 517 518 needpriunat = 0; 519 for (i = 0; i < NSB_GR; i++) { 520 dispcode = UWX_GET_DISP_CODE(env->rstate[SBREG_GR + i]); 521 if (dispcode == UWX_DISP_SPREL(0) || dispcode == UWX_DISP_PSPREL(0)) 522 needpriunat = 1; 523 } 524 unat = 0; 525 if (needpriunat && env->rstate[SBREG_PRIUNAT] != UWX_DISP_NONE) { 526 status = uwx_restore_reg(env, env->rstate[SBREG_PRIUNAT], &val, &hist); 527 if (status != UWX_OK) 528 return status; 529 unat = (int) val; 530 env->history.special[UWX_REG_PRIUNAT] = hist; 531 TRACE_S_RESTORE_REG("PRIUNAT", env->rstate[SBREG_PRIUNAT], val) 532 } 533 534 /* Retrieve saved values of the preserved GRs into temporaries. */ 535 536 tempnat = (int) env->context.special[UWX_REG_PRIUNAT]; 537 for (i = 0; i < NSB_GR; i++) { 538 if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) { 539 status = uwx_restore_reg(env, 540 env->rstate[SBREG_GR + i], &val, &hist); 541 if (status != UWX_OK) 542 return status; 543 tempgr[i] = val; 544 if (uwx_restore_nat(env, env->rstate[SBREG_GR + i], unat)) 545 tempnat |= 1 << i; 546 else 547 tempnat &= ~(1 << i); 548 env->history.gr[i] = hist; 549 env->context.valid_regs |= 1 << (i + VALID_GR_SHIFT); 550 TRACE_S_RESTORE_GR(i, env->rstate[SBREG_GR + i], val) 551 } 552 } 553 554 /* Now we have everything we need to step back to the previous frame. */ 555 556 /* Restore preserved BRs. */ 557 558 for (i = 0; i < NSB_BR; i++) { 559 if (env->rstate[SBREG_BR + i] != UWX_DISP_NONE) { 560 status = uwx_restore_reg(env, 561 env->rstate[SBREG_BR + i], &val, &hist); 562 if (status != UWX_OK) 563 return status; 564 env->context.br[i] = val; 565 env->history.br[i] = hist; 566 env->context.valid_regs |= 1 << (i + VALID_BR_SHIFT); 567 TRACE_S_RESTORE_BR(i, env->rstate[SBREG_BR + i], val) 568 } 569 } 570 571 /* Restore preserved FRs. */ 572 573 if (env->nsbreg == NSBREG) { 574 for (i = 0; i < NSB_FR; i++) { 575 if (env->rstate[SBREG_FR + i] != UWX_DISP_NONE) { 576 status = uwx_restore_freg(env, 577 env->rstate[SBREG_FR + i], fval, &hist); 578 if (status != UWX_OK) 579 return status; 580 env->context.fr[i].part0 = fval[0]; 581 env->context.fr[i].part1 = fval[1]; 582 env->history.fr[i] = hist; 583 env->context.valid_frs |= 1 << i; 584 TRACE_S_RESTORE_FR(i, env->rstate[SBREG_FR + i], fval) 585 } 586 } 587 } 588 589 /* Restore other preserved regs. */ 590 591 if (env->rstate[SBREG_PREDS] != UWX_DISP_NONE) { 592 status = uwx_restore_reg(env, env->rstate[SBREG_PREDS], &val, &hist); 593 if (status != UWX_OK) 594 return status; 595 env->context.special[UWX_REG_PREDS] = val; 596 env->history.special[UWX_REG_PREDS] = hist; 597 env->context.valid_regs |= 1 << UWX_REG_PREDS; 598 TRACE_S_RESTORE_REG("PREDS", env->rstate[SBREG_PREDS], val) 599 } 600 if (env->rstate[SBREG_RNAT] != UWX_DISP_NONE) { 601 status = uwx_restore_reg(env, env->rstate[SBREG_RNAT], &val, &hist); 602 if (status != UWX_OK) 603 return status; 604 env->context.special[UWX_REG_AR_RNAT] = val; 605 env->history.special[UWX_REG_AR_RNAT] = hist; 606 env->context.valid_regs |= 1 << UWX_REG_AR_RNAT; 607 TRACE_S_RESTORE_REG("RNAT", env->rstate[SBREG_RNAT], val) 608 } 609 if (env->rstate[SBREG_UNAT] != UWX_DISP_NONE) { 610 status = uwx_restore_reg(env, env->rstate[SBREG_UNAT], &val, &hist); 611 if (status != UWX_OK) 612 return status; 613 env->context.special[UWX_REG_AR_UNAT] = val; 614 env->history.special[UWX_REG_AR_UNAT] = hist; 615 env->context.valid_regs |= 1 << UWX_REG_AR_UNAT; 616 TRACE_S_RESTORE_REG("UNAT", env->rstate[SBREG_UNAT], val) 617 } 618 if (env->rstate[SBREG_FPSR] != UWX_DISP_NONE) { 619 status = uwx_restore_reg(env, env->rstate[SBREG_FPSR], &val, &hist); 620 if (status != UWX_OK) 621 return status; 622 env->context.special[UWX_REG_AR_FPSR] = val; 623 env->history.special[UWX_REG_AR_FPSR] = hist; 624 env->context.valid_regs |= 1 << UWX_REG_AR_FPSR; 625 TRACE_S_RESTORE_REG("FPSR", env->rstate[SBREG_FPSR], val) 626 } 627 if (env->rstate[SBREG_LC] != UWX_DISP_NONE) { 628 status = uwx_restore_reg(env, env->rstate[SBREG_LC], &val, &hist); 629 if (status != UWX_OK) 630 return status; 631 env->context.special[UWX_REG_AR_LC] = val; 632 env->history.special[UWX_REG_AR_LC] = hist; 633 env->context.valid_regs |= 1 << UWX_REG_AR_LC; 634 TRACE_S_RESTORE_REG("LC", env->rstate[SBREG_LC], val) 635 } 636 637 /* Restore preserved GRs from temporaries. */ 638 639 for (i = 0; i < NSB_GR; i++) { 640 if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) 641 env->context.gr[i] = tempgr[i]; 642 } 643 env->context.special[UWX_REG_PRIUNAT] = tempnat; 644 645 /* Restore the frame markers. */ 646 647 env->context.special[UWX_REG_IP] = env->context.special[UWX_REG_RP]; 648 env->history.special[UWX_REG_IP] = env->history.special[UWX_REG_RP]; 649 650 env->context.special[UWX_REG_SP] = env->context.special[UWX_REG_PSP]; 651 env->history.special[UWX_REG_SP] = env->history.special[UWX_REG_PSP]; 652 653 pfs_sol = ((unsigned int)env->context.special[UWX_REG_PFS] >> 7) & 0x7f; 654 env->context.special[UWX_REG_BSP] = uwx_add_to_bsp( 655 env->context.special[UWX_REG_BSP], 656 -pfs_sol); 657 658 env->context.special[UWX_REG_CFM] = env->context.special[UWX_REG_PFS]; 659 env->history.special[UWX_REG_CFM] = env->history.special[UWX_REG_PFS]; 660 661 env->context.special[UWX_REG_RP] = 0; 662 663 /* The frame info for the new frame isn't yet available. */ 664 665 env->rstate = 0; 666 env->context.valid_regs &= ~VALID_MARKERS; 667 668 return UWX_OK; 669} 670 671 672/* uwx_decode_uvec: Converts the update vector into a register state array */ 673 674int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate) 675{ 676 int i; 677 int status; 678 679 status = uwx_default_rstate(env, rstate); 680 if (status != UWX_OK) 681 return status; 682 683 for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { 684 switch ((int)uvec[i]) { 685 case UWX_KEY_CONTEXT: 686 env->abi_context = (int)(uvec[i+1]); 687 status = UWX_ABI_FRAME; 688 break;
|
| 689 case UWX_KEY_GP: 690 uwx_set_reg(env, UWX_REG_GP, uvec[i+1]); 691 break;
|
575 case UWX_KEY_MODULE: 576 env->module_name =
| 692 case UWX_KEY_MODULE: 693 env->module_name =
|
577 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 694 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
578 break; 579 case UWX_KEY_FUNC: 580 env->function_name =
| 695 break; 696 case UWX_KEY_FUNC: 697 env->function_name =
|
581 uwx_alloc_str(env, (char *)(uvec[i+1]));
| 698 uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
|
582 break; 583 case UWX_KEY_FUNCSTART: 584 env->function_offset = env->remapped_ip - uvec[i+1]; 585 break; 586 default: 587 return UWX_ERR_CANTUNWIND; 588 } 589 } 590 return status; 591} 592 593 594/* uwx_restore_reg: Restores a register according to the scoreboard */ 595 596#define COPYIN_MSTACK_8(dest, src) \ 597 (env->remote? \ 598 (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ 599 DWORDSZ, env->cb_token) : \
| 699 break; 700 case UWX_KEY_FUNCSTART: 701 env->function_offset = env->remapped_ip - uvec[i+1]; 702 break; 703 default: 704 return UWX_ERR_CANTUNWIND; 705 } 706 } 707 return status; 708} 709 710 711/* uwx_restore_reg: Restores a register according to the scoreboard */ 712 713#define COPYIN_MSTACK_8(dest, src) \ 714 (env->remote? \ 715 (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ 716 DWORDSZ, env->cb_token) : \
|
600 (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
| 717 (*(uint64_t *)(intptr_t)(dest) = \ 718 *(uint64_t *)(intptr_t)(src), DWORDSZ) )
|
601 602int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, 603 uint64_t *valp, uint64_t *histp) 604{ 605 int status; 606 uint64_t p; 607 int n; 608 int regid; 609 610 status = UWX_OK; 611 612 switch (UWX_GET_DISP_CODE(rstate)) { 613 case UWX_DISP_SPPLUS(0): 614 *valp = env->context.special[UWX_REG_SP] + 615 UWX_GET_DISP_OFFSET(rstate); 616 *histp = UWX_DISP_NONE; 617 break; 618 case UWX_DISP_SPREL(0): 619 p = env->context.special[UWX_REG_SP] + 620 UWX_GET_DISP_OFFSET(rstate); 621 n = COPYIN_MSTACK_8((char *)valp, p); 622 if (n != DWORDSZ) 623 status = UWX_ERR_COPYIN_MSTK; 624 *histp = UWX_DISP_MSTK(p); 625 break; 626 case UWX_DISP_PSPREL(0): 627 p = env->context.special[UWX_REG_PSP] + 16 - 628 UWX_GET_DISP_OFFSET(rstate); 629 n = COPYIN_MSTACK_8((char *)valp, p); 630 if (n != DWORDSZ) 631 status = UWX_ERR_COPYIN_MSTK; 632 *histp = UWX_DISP_MSTK(p); 633 break; 634 case UWX_DISP_REG(0): 635 regid = UWX_GET_DISP_REGID(rstate); 636 status = uwx_get_reg(env, regid, valp); 637 (void) uwx_get_spill_loc(env, regid, histp); 638 break; 639 } 640 return status; 641} 642 643#define COPYIN_MSTACK_16(dest, src) \ 644 (env->remote? \ 645 (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ 646 2*DWORDSZ, env->cb_token) : \
| 719 720int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, 721 uint64_t *valp, uint64_t *histp) 722{ 723 int status; 724 uint64_t p; 725 int n; 726 int regid; 727 728 status = UWX_OK; 729 730 switch (UWX_GET_DISP_CODE(rstate)) { 731 case UWX_DISP_SPPLUS(0): 732 *valp = env->context.special[UWX_REG_SP] + 733 UWX_GET_DISP_OFFSET(rstate); 734 *histp = UWX_DISP_NONE; 735 break; 736 case UWX_DISP_SPREL(0): 737 p = env->context.special[UWX_REG_SP] + 738 UWX_GET_DISP_OFFSET(rstate); 739 n = COPYIN_MSTACK_8((char *)valp, p); 740 if (n != DWORDSZ) 741 status = UWX_ERR_COPYIN_MSTK; 742 *histp = UWX_DISP_MSTK(p); 743 break; 744 case UWX_DISP_PSPREL(0): 745 p = env->context.special[UWX_REG_PSP] + 16 - 746 UWX_GET_DISP_OFFSET(rstate); 747 n = COPYIN_MSTACK_8((char *)valp, p); 748 if (n != DWORDSZ) 749 status = UWX_ERR_COPYIN_MSTK; 750 *histp = UWX_DISP_MSTK(p); 751 break; 752 case UWX_DISP_REG(0): 753 regid = UWX_GET_DISP_REGID(rstate); 754 status = uwx_get_reg(env, regid, valp); 755 (void) uwx_get_spill_loc(env, regid, histp); 756 break; 757 } 758 return status; 759} 760 761#define COPYIN_MSTACK_16(dest, src) \ 762 (env->remote? \ 763 (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ 764 2*DWORDSZ, env->cb_token) : \
|
647 (*(uint64_t *)(dest) = *(uint64_t *)(src), \ 648 *(uint64_t *)((dest)+8) = *(uint64_t *)((src)+8), \ 649 2*DWORDSZ) )
| 765 (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), \ 766 *(uint64_t *)(intptr_t)((dest)+8) = \ 767 *(uint64_t *)(intptr_t)((src)+8), \ 768 2*DWORDSZ) )
|
650 651int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, 652 uint64_t *valp, uint64_t *histp) 653{ 654 int status; 655 uint64_t p; 656 int n; 657 int regid; 658 659 status = UWX_OK; 660 661 switch (UWX_GET_DISP_CODE(rstate)) { 662 case UWX_DISP_SPREL(0): 663 p = env->context.special[UWX_REG_SP] + 664 UWX_GET_DISP_OFFSET(rstate); 665 n = COPYIN_MSTACK_16((char *)valp, p); 666 if (n != 2*DWORDSZ) 667 status = UWX_ERR_COPYIN_MSTK; 668 *histp = UWX_DISP_MSTK(p); 669 break; 670 case UWX_DISP_PSPREL(0): 671 p = env->context.special[UWX_REG_PSP] + 16 - 672 UWX_GET_DISP_OFFSET(rstate); 673 n = COPYIN_MSTACK_16((char *)valp, p); 674 if (n != 2*DWORDSZ) 675 status = UWX_ERR_COPYIN_MSTK; 676 *histp = UWX_DISP_MSTK(p); 677 break; 678 case UWX_DISP_REG(0): 679 regid = UWX_GET_DISP_REGID(rstate); 680 status = uwx_get_reg(env, regid, valp); 681 (void) uwx_get_spill_loc(env, regid, histp); 682 break; 683 } 684 return status; 685} 686 687/* uwx_restore_nat: Returns the saved NaT bit for a preserved GR */ 688 689int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat) 690{ 691 int nat; 692 uint64_t p; 693 694 nat = 0; 695 switch (UWX_GET_DISP_CODE(rstate)) { 696 case UWX_DISP_SPREL(0): 697 p = env->context.special[UWX_REG_SP] + 698 UWX_GET_DISP_OFFSET(rstate); 699 nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01; 700 break; 701 case UWX_DISP_PSPREL(0): 702 p = env->context.special[UWX_REG_PSP] + 16 - 703 UWX_GET_DISP_OFFSET(rstate); 704 nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01; 705 break; 706 case UWX_DISP_REG(0): 707 (void) uwx_get_nat(env, UWX_GET_DISP_REGID(rstate), &nat); 708 break; 709 } 710 return nat; 711} 712
| 769 770int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, 771 uint64_t *valp, uint64_t *histp) 772{ 773 int status; 774 uint64_t p; 775 int n; 776 int regid; 777 778 status = UWX_OK; 779 780 switch (UWX_GET_DISP_CODE(rstate)) { 781 case UWX_DISP_SPREL(0): 782 p = env->context.special[UWX_REG_SP] + 783 UWX_GET_DISP_OFFSET(rstate); 784 n = COPYIN_MSTACK_16((char *)valp, p); 785 if (n != 2*DWORDSZ) 786 status = UWX_ERR_COPYIN_MSTK; 787 *histp = UWX_DISP_MSTK(p); 788 break; 789 case UWX_DISP_PSPREL(0): 790 p = env->context.special[UWX_REG_PSP] + 16 - 791 UWX_GET_DISP_OFFSET(rstate); 792 n = COPYIN_MSTACK_16((char *)valp, p); 793 if (n != 2*DWORDSZ) 794 status = UWX_ERR_COPYIN_MSTK; 795 *histp = UWX_DISP_MSTK(p); 796 break; 797 case UWX_DISP_REG(0): 798 regid = UWX_GET_DISP_REGID(rstate); 799 status = uwx_get_reg(env, regid, valp); 800 (void) uwx_get_spill_loc(env, regid, histp); 801 break; 802 } 803 return status; 804} 805 806/* uwx_restore_nat: Returns the saved NaT bit for a preserved GR */ 807 808int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat) 809{ 810 int nat; 811 uint64_t p; 812 813 nat = 0; 814 switch (UWX_GET_DISP_CODE(rstate)) { 815 case UWX_DISP_SPREL(0): 816 p = env->context.special[UWX_REG_SP] + 817 UWX_GET_DISP_OFFSET(rstate); 818 nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01; 819 break; 820 case UWX_DISP_PSPREL(0): 821 p = env->context.special[UWX_REG_PSP] + 16 - 822 UWX_GET_DISP_OFFSET(rstate); 823 nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01; 824 break; 825 case UWX_DISP_REG(0): 826 (void) uwx_get_nat(env, UWX_GET_DISP_REGID(rstate), &nat); 827 break; 828 } 829 return nat; 830} 831
|