uwx_self.c revision 120925
1/* 2 * Copyright (c) 2002,2003 Hewlett-Packard Company 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23#ifndef _KERNEL 24#include <stdlib.h> 25#include <crt0.h> 26#include <dlfcn.h> 27#include <sys/uc_access.h> 28#endif 29 30#include "uwx_env.h" 31#include "uwx_context.h" 32#include "uwx_trace.h" 33#include "uwx_self.h" 34 35#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */ 36 37struct uwx_self_info { 38 ucontext_t *ucontext; 39 uint64_t bspstore; 40 uint64_t rvec[10]; 41 uint64_t sendsig_start; 42 uint64_t sendsig_end; 43 alloc_cb allocate_cb; 44 free_cb free_cb; 45 int trace; 46}; 47 48struct uwx_self_info *uwx_self_init_info(struct uwx_env *env) 49{ 50 struct uwx_self_info *info; 51 52 if (env->allocate_cb == 0) 53 info = (struct uwx_self_info *) 54 malloc(sizeof(struct uwx_self_info)); 55 else 56 info = (struct uwx_self_info *) 57 (*env->allocate_cb)(sizeof(struct uwx_self_info)); 58 if (info == 0) 59 return 0; 60 61 info->ucontext = 0; 62 info->bspstore = 0; 63 info->sendsig_start = __load_info->li_sendsig_txt; 64 info->sendsig_end = __load_info->li_sendsig_txt + 65 __load_info->li_sendsig_tsz; 66 info->allocate_cb = env->allocate_cb; 67 info->free_cb = env->free_cb; 68 info->trace = env->trace; 69 return info; 70} 71 72int uwx_self_free_info(struct uwx_self_info *info) 73{ 74 if (info->free_cb == 0) 75 free((void *)info); 76 else 77 (*info->free_cb)((void *)info); 78 return UWX_OK; 79} 80 81int uwx_self_init_from_sigcontext( 82 struct uwx_env *env, 83 struct uwx_self_info *info, 84 ucontext_t *ucontext) 85{ 86 int status; 87 uint16_t reason; 88 uint64_t ip; 89 uint64_t sp; 90 uint64_t bsp; 91 uint64_t cfm; 92 unsigned int nat; 93 uint64_t ec; 94 int adj; 95 96 info->ucontext = ucontext; 97 status = __uc_get_reason(ucontext, &reason); 98 status = __uc_get_ip(ucontext, &ip); 99 status = __uc_get_grs(ucontext, 12, 1, &sp, &nat); 100 status = __uc_get_cfm(ucontext, &cfm); 101#ifdef NEW_UC_GET_AR 102 status = __uc_get_ar_bsp(ucontext, &bsp); 103 status = __uc_get_ar_bspstore(ucontext, &info->bspstore); 104 status = __uc_get_ar_ec(ucontext, &ec); 105#else 106 status = __uc_get_ar(ucontext, 17, &bsp); 107 status = __uc_get_ar(ucontext, 18, &info->bspstore); 108 status = __uc_get_ar(ucontext, 66, &ec); 109#endif 110 /* The returned bsp needs to be adjusted. */ 111 /* For interrupt frames, where bsp was advanced by a cover */ 112 /* instruction, subtract sof (size of frame). For non-interrupt */ 113 /* frames, where bsp was advanced by br.call, subtract sol */ 114 /* (size of locals). */ 115 if (reason != 0) 116 adj = (unsigned int)cfm & 0x7f; /* interrupt frame */ 117 else 118 adj = ((unsigned int)cfm >> 7) & 0x7f; /* non-interrupt frame */ 119 bsp = uwx_add_to_bsp(bsp, -adj); 120 cfm |= ec << 52; 121 uwx_init_context(env, ip, sp, bsp, cfm); 122 return UWX_OK; 123} 124 125int uwx_self_do_context_frame( 126 struct uwx_env *env, 127 struct uwx_self_info *info) 128{ 129 int abi_context; 130 int status; 131 uint64_t ucontext; 132 133 abi_context = uwx_get_abi_context_code(env); 134 if (abi_context != UWX_ABI_HPUX_SIGCONTEXT) 135 return UWX_SELF_ERR_BADABICONTEXT; 136 status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext); 137 if (status != 0) 138 return status; 139 return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext); 140} 141 142int uwx_self_copyin( 143 int request, 144 char *loc, 145 uint64_t rem, 146 int len, 147 intptr_t tok) 148{ 149 int status; 150 int regid; 151 unsigned int nat; 152 struct uwx_self_info *info = (struct uwx_self_info *) tok; 153 unsigned long *wp; 154 uint64_t *dp; 155 156 dp = (uint64_t *) loc; 157 158 if (request == UWX_COPYIN_UINFO || 159 request == UWX_COPYIN_MSTACK) { 160 if (len == 4) { 161 wp = (unsigned long *) loc; 162 *wp = *(unsigned long *)rem; 163 TRACE_SELF_COPYIN4(rem, len, wp) 164 } 165 else if (len == 8) { 166 *dp = *(uint64_t *)rem; 167 TRACE_SELF_COPYIN4(rem, len, dp) 168 } 169 else 170 return 0; 171 } 172 else if (request == UWX_COPYIN_RSTACK && len == 8) { 173 if (info->ucontext == 0 || rem < info->bspstore) { 174 *dp = *(uint64_t *)rem; 175 TRACE_SELF_COPYIN4(rem, len, dp) 176 } 177 else { 178 status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp); 179 if (status != 0) 180 return 0; 181 } 182 } 183 else if (request == UWX_COPYIN_REG && len == 8) { 184 if (info->ucontext == 0) 185 return 0; 186 regid = (int)rem; 187 if (rem < UWX_REG_GR(0)) { 188 switch (regid) { 189 case UWX_REG_PREDS: 190 status = __uc_get_prs(info->ucontext, dp); 191 break; 192 case UWX_REG_AR_PFS: 193 status = __uc_get_ar(info->ucontext, 64, dp); 194 break; 195 case UWX_REG_AR_RNAT: 196 status = __uc_get_ar(info->ucontext, 19, dp); 197 break; 198 case UWX_REG_AR_UNAT: 199 status = __uc_get_ar(info->ucontext, 36, dp); 200 break; 201 case UWX_REG_AR_FPSR: 202 status = __uc_get_ar(info->ucontext, 40, dp); 203 break; 204 case UWX_REG_AR_LC: 205 status = __uc_get_ar(info->ucontext, 65, dp); 206 break; 207 default: 208 return 0; 209 } 210 } 211 else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) { 212 status = __uc_get_grs(info->ucontext, 213 regid - UWX_REG_GR(0), 1, dp, &nat); 214 } 215 else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) { 216 status = __uc_get_brs(info->ucontext, 217 regid - UWX_REG_BR(0), 1, dp); 218 } 219 if (status != 0) 220 return 0; 221 } 222 return len; 223} 224 225 226int uwx_self_lookupip( 227 int request, 228 uint64_t ip, 229 intptr_t tok, 230 uint64_t **resultp) 231{ 232 struct uwx_self_info *info = (struct uwx_self_info *) tok; 233 UINT64 handle; 234 struct load_module_desc desc; 235 uint64_t *unwind_base; 236 uint64_t *rvec; 237 int i; 238 239 if (request == UWX_LKUP_LOOKUP) { 240 TRACE_SELF_LOOKUP(ip) 241 if (ip >= info->sendsig_start && ip < info->sendsig_end) { 242 i = 0; 243 rvec = info->rvec; 244 rvec[i++] = UWX_KEY_CONTEXT; 245 rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT; 246 rvec[i++] = 0; 247 rvec[i++] = 0; 248 *resultp = rvec; 249 return UWX_LKUP_FDESC; 250 } 251 else { 252 handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0); 253 if (handle == 0) 254 return UWX_LKUP_ERR; 255 unwind_base = (uint64_t *) desc.unwind_base; 256 TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base) 257 i = 0; 258 rvec = info->rvec; 259 rvec[i++] = UWX_KEY_TBASE; 260 rvec[i++] = desc.text_base; 261 rvec[i++] = UWX_KEY_UFLAGS; 262 rvec[i++] = unwind_base[0]; 263 rvec[i++] = UWX_KEY_USTART; 264 rvec[i++] = desc.text_base + unwind_base[1]; 265 rvec[i++] = UWX_KEY_UEND; 266 rvec[i++] = desc.text_base + unwind_base[2]; 267 rvec[i++] = 0; 268 rvec[i++] = 0; 269 *resultp = rvec; 270 return UWX_LKUP_UTABLE; 271 } 272 } 273 else if (request == UWX_LKUP_FREE) { 274 return 0; 275 } 276} 277