uwx_self.c revision 115013
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 95 info->ucontext = ucontext; 96 status = __uc_get_reason(ucontext, &reason); 97 status = __uc_get_ip(ucontext, &ip); 98 status = __uc_get_grs(ucontext, 12, 1, &sp, &nat); 99 status = __uc_get_ar(ucontext, 17, &bsp); 100 status = __uc_get_ar(ucontext, 18, &info->bspstore); 101 status = __uc_get_ar(ucontext, 66, &ec); 102 status = __uc_get_cfm(ucontext, &cfm); 103 cfm |= ec << 52; 104 if (reason != 0) 105 bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f)); 106 uwx_init_context(env, ip, sp, bsp, cfm); 107 return UWX_OK; 108} 109 110int uwx_self_do_context_frame( 111 struct uwx_env *env, 112 struct uwx_self_info *info) 113{ 114 int abi_context; 115 int status; 116 uint64_t ucontext; 117 118 abi_context = uwx_get_abi_context_code(env); 119 if (abi_context != UWX_ABI_HPUX_SIGCONTEXT) 120 return UWX_SELF_ERR_BADABICONTEXT; 121 status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext); 122 if (status != 0) 123 return status; 124 return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext); 125} 126 127int uwx_self_copyin( 128 int request, 129 char *loc, 130 uint64_t rem, 131 int len, 132 intptr_t tok) 133{ 134 int status; 135 int regid; 136 unsigned int nat; 137 struct uwx_self_info *info = (struct uwx_self_info *) tok; 138 unsigned long *wp; 139 uint64_t *dp; 140 141 dp = (uint64_t *) loc; 142 143 if (request == UWX_COPYIN_UINFO || 144 request == UWX_COPYIN_MSTACK) { 145 if (len == 4) { 146 wp = (unsigned long *) loc; 147 *wp = *(unsigned long *)rem; 148 TRACE_SELF_COPYIN4(rem, len, wp) 149 } 150 else if (len == 8) { 151 *dp = *(uint64_t *)rem; 152 TRACE_SELF_COPYIN4(rem, len, dp) 153 } 154 else 155 return 0; 156 } 157 else if (request == UWX_COPYIN_RSTACK && len == 8) { 158 if (info->ucontext == 0 || rem < info->bspstore) { 159 *dp = *(uint64_t *)rem; 160 TRACE_SELF_COPYIN4(rem, len, dp) 161 } 162 else { 163 status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp); 164 if (status != 0) 165 return 0; 166 } 167 } 168 else if (request == UWX_COPYIN_REG && len == 8) { 169 if (info->ucontext == 0) 170 return 0; 171 regid = (int)rem; 172 if (rem < UWX_REG_GR(0)) { 173 switch (regid) { 174 case UWX_REG_PFS: 175 status = __uc_get_ar(info->ucontext, 64, dp); 176 break; 177 case UWX_REG_PREDS: 178 status = __uc_get_prs(info->ucontext, dp); 179 break; 180 case UWX_REG_RNAT: 181 status = __uc_get_ar(info->ucontext, 19, dp); 182 break; 183 case UWX_REG_UNAT: 184 status = __uc_get_ar(info->ucontext, 36, dp); 185 break; 186 case UWX_REG_FPSR: 187 status = __uc_get_ar(info->ucontext, 40, dp); 188 break; 189 case UWX_REG_LC: 190 status = __uc_get_ar(info->ucontext, 65, dp); 191 break; 192 default: 193 return 0; 194 } 195 } 196 else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) { 197 status = __uc_get_grs(info->ucontext, 198 regid - UWX_REG_GR(0), 1, dp, &nat); 199 } 200 else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) { 201 status = __uc_get_brs(info->ucontext, 202 regid - UWX_REG_BR(0), 1, dp); 203 } 204 if (status != 0) 205 return 0; 206 } 207 return len; 208} 209 210 211int uwx_self_lookupip( 212 int request, 213 uint64_t ip, 214 intptr_t tok, 215 uint64_t **resultp) 216{ 217 struct uwx_self_info *info = (struct uwx_self_info *) tok; 218 UINT64 handle; 219 struct load_module_desc desc; 220 uint64_t *unwind_base; 221 uint64_t *rvec; 222 int i; 223 224 if (request == UWX_LKUP_LOOKUP) { 225 TRACE_SELF_LOOKUP(ip) 226 if (ip >= info->sendsig_start && ip < info->sendsig_end) { 227 i = 0; 228 rvec = info->rvec; 229 rvec[i++] = UWX_KEY_CONTEXT; 230 rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT; 231 rvec[i++] = 0; 232 rvec[i++] = 0; 233 *resultp = rvec; 234 return UWX_LKUP_FDESC; 235 } 236 else { 237 handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0); 238 if (handle == 0) 239 return UWX_LKUP_ERR; 240 unwind_base = (uint64_t *) desc.unwind_base; 241 TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base) 242 i = 0; 243 rvec = info->rvec; 244 rvec[i++] = UWX_KEY_TBASE; 245 rvec[i++] = desc.text_base; 246 rvec[i++] = UWX_KEY_UFLAGS; 247 rvec[i++] = unwind_base[0]; 248 rvec[i++] = UWX_KEY_USTART; 249 rvec[i++] = desc.text_base + unwind_base[1]; 250 rvec[i++] = UWX_KEY_UEND; 251 rvec[i++] = desc.text_base + unwind_base[2]; 252 rvec[i++] = 0; 253 rvec[i++] = 0; 254 *resultp = rvec; 255 return UWX_LKUP_UTABLE; 256 } 257 } 258 else if (request == UWX_LKUP_FREE) { 259 return 0; 260 } 261} 262