uwx_self.c revision 120925
1115013Smarcel/* 2115013Smarcel * Copyright (c) 2002,2003 Hewlett-Packard Company 3115013Smarcel * 4115013Smarcel * Permission is hereby granted, free of charge, to any person obtaining a 5115013Smarcel * copy of this software and associated documentation files (the "Software"), 6115013Smarcel * to deal in the Software without restriction, including without limitation 7115013Smarcel * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8115013Smarcel * and/or sell copies of the Software, and to permit persons to whom the 9115013Smarcel * Software is furnished to do so, subject to the following conditions: 10115013Smarcel * 11115013Smarcel * The above copyright notice and this permission notice shall be included 12115013Smarcel * in all copies or substantial portions of the Software. 13115013Smarcel * 14115013Smarcel * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15115013Smarcel * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16115013Smarcel * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17115013Smarcel * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18115013Smarcel * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19115013Smarcel * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20115013Smarcel * DEALINGS IN THE SOFTWARE. 21115013Smarcel */ 22115013Smarcel 23115013Smarcel#ifndef _KERNEL 24115013Smarcel#include <stdlib.h> 25115013Smarcel#include <crt0.h> 26115013Smarcel#include <dlfcn.h> 27115013Smarcel#include <sys/uc_access.h> 28115013Smarcel#endif 29115013Smarcel 30115013Smarcel#include "uwx_env.h" 31115013Smarcel#include "uwx_context.h" 32115013Smarcel#include "uwx_trace.h" 33115013Smarcel#include "uwx_self.h" 34115013Smarcel 35115013Smarcel#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */ 36115013Smarcel 37115013Smarcelstruct uwx_self_info { 38115013Smarcel ucontext_t *ucontext; 39115013Smarcel uint64_t bspstore; 40115013Smarcel uint64_t rvec[10]; 41115013Smarcel uint64_t sendsig_start; 42115013Smarcel uint64_t sendsig_end; 43115013Smarcel alloc_cb allocate_cb; 44115013Smarcel free_cb free_cb; 45115013Smarcel int trace; 46115013Smarcel}; 47115013Smarcel 48115013Smarcelstruct uwx_self_info *uwx_self_init_info(struct uwx_env *env) 49115013Smarcel{ 50115013Smarcel struct uwx_self_info *info; 51115013Smarcel 52115013Smarcel if (env->allocate_cb == 0) 53115013Smarcel info = (struct uwx_self_info *) 54115013Smarcel malloc(sizeof(struct uwx_self_info)); 55115013Smarcel else 56115013Smarcel info = (struct uwx_self_info *) 57115013Smarcel (*env->allocate_cb)(sizeof(struct uwx_self_info)); 58115013Smarcel if (info == 0) 59115013Smarcel return 0; 60115013Smarcel 61115013Smarcel info->ucontext = 0; 62115013Smarcel info->bspstore = 0; 63115013Smarcel info->sendsig_start = __load_info->li_sendsig_txt; 64115013Smarcel info->sendsig_end = __load_info->li_sendsig_txt + 65115013Smarcel __load_info->li_sendsig_tsz; 66115013Smarcel info->allocate_cb = env->allocate_cb; 67115013Smarcel info->free_cb = env->free_cb; 68115013Smarcel info->trace = env->trace; 69115013Smarcel return info; 70115013Smarcel} 71115013Smarcel 72115013Smarcelint uwx_self_free_info(struct uwx_self_info *info) 73115013Smarcel{ 74115013Smarcel if (info->free_cb == 0) 75115013Smarcel free((void *)info); 76115013Smarcel else 77115013Smarcel (*info->free_cb)((void *)info); 78115013Smarcel return UWX_OK; 79115013Smarcel} 80115013Smarcel 81115013Smarcelint uwx_self_init_from_sigcontext( 82115013Smarcel struct uwx_env *env, 83115013Smarcel struct uwx_self_info *info, 84115013Smarcel ucontext_t *ucontext) 85115013Smarcel{ 86115013Smarcel int status; 87115013Smarcel uint16_t reason; 88115013Smarcel uint64_t ip; 89115013Smarcel uint64_t sp; 90115013Smarcel uint64_t bsp; 91115013Smarcel uint64_t cfm; 92115013Smarcel unsigned int nat; 93115013Smarcel uint64_t ec; 94120925Smarcel int adj; 95115013Smarcel 96115013Smarcel info->ucontext = ucontext; 97115013Smarcel status = __uc_get_reason(ucontext, &reason); 98115013Smarcel status = __uc_get_ip(ucontext, &ip); 99115013Smarcel status = __uc_get_grs(ucontext, 12, 1, &sp, &nat); 100120925Smarcel status = __uc_get_cfm(ucontext, &cfm); 101120925Smarcel#ifdef NEW_UC_GET_AR 102120925Smarcel status = __uc_get_ar_bsp(ucontext, &bsp); 103120925Smarcel status = __uc_get_ar_bspstore(ucontext, &info->bspstore); 104120925Smarcel status = __uc_get_ar_ec(ucontext, &ec); 105120925Smarcel#else 106115013Smarcel status = __uc_get_ar(ucontext, 17, &bsp); 107115013Smarcel status = __uc_get_ar(ucontext, 18, &info->bspstore); 108115013Smarcel status = __uc_get_ar(ucontext, 66, &ec); 109120925Smarcel#endif 110120925Smarcel /* The returned bsp needs to be adjusted. */ 111120925Smarcel /* For interrupt frames, where bsp was advanced by a cover */ 112120925Smarcel /* instruction, subtract sof (size of frame). For non-interrupt */ 113120925Smarcel /* frames, where bsp was advanced by br.call, subtract sol */ 114120925Smarcel /* (size of locals). */ 115120925Smarcel if (reason != 0) 116120925Smarcel adj = (unsigned int)cfm & 0x7f; /* interrupt frame */ 117120925Smarcel else 118120925Smarcel adj = ((unsigned int)cfm >> 7) & 0x7f; /* non-interrupt frame */ 119120925Smarcel bsp = uwx_add_to_bsp(bsp, -adj); 120115013Smarcel cfm |= ec << 52; 121115013Smarcel uwx_init_context(env, ip, sp, bsp, cfm); 122115013Smarcel return UWX_OK; 123115013Smarcel} 124115013Smarcel 125115013Smarcelint uwx_self_do_context_frame( 126115013Smarcel struct uwx_env *env, 127115013Smarcel struct uwx_self_info *info) 128115013Smarcel{ 129115013Smarcel int abi_context; 130115013Smarcel int status; 131115013Smarcel uint64_t ucontext; 132115013Smarcel 133115013Smarcel abi_context = uwx_get_abi_context_code(env); 134115013Smarcel if (abi_context != UWX_ABI_HPUX_SIGCONTEXT) 135115013Smarcel return UWX_SELF_ERR_BADABICONTEXT; 136115013Smarcel status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext); 137115013Smarcel if (status != 0) 138115013Smarcel return status; 139115013Smarcel return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext); 140115013Smarcel} 141115013Smarcel 142115013Smarcelint uwx_self_copyin( 143115013Smarcel int request, 144115013Smarcel char *loc, 145115013Smarcel uint64_t rem, 146115013Smarcel int len, 147115013Smarcel intptr_t tok) 148115013Smarcel{ 149115013Smarcel int status; 150115013Smarcel int regid; 151115013Smarcel unsigned int nat; 152115013Smarcel struct uwx_self_info *info = (struct uwx_self_info *) tok; 153115013Smarcel unsigned long *wp; 154115013Smarcel uint64_t *dp; 155115013Smarcel 156115013Smarcel dp = (uint64_t *) loc; 157115013Smarcel 158115013Smarcel if (request == UWX_COPYIN_UINFO || 159115013Smarcel request == UWX_COPYIN_MSTACK) { 160115013Smarcel if (len == 4) { 161115013Smarcel wp = (unsigned long *) loc; 162115013Smarcel *wp = *(unsigned long *)rem; 163115013Smarcel TRACE_SELF_COPYIN4(rem, len, wp) 164115013Smarcel } 165115013Smarcel else if (len == 8) { 166115013Smarcel *dp = *(uint64_t *)rem; 167115013Smarcel TRACE_SELF_COPYIN4(rem, len, dp) 168115013Smarcel } 169115013Smarcel else 170115013Smarcel return 0; 171115013Smarcel } 172115013Smarcel else if (request == UWX_COPYIN_RSTACK && len == 8) { 173115013Smarcel if (info->ucontext == 0 || rem < info->bspstore) { 174115013Smarcel *dp = *(uint64_t *)rem; 175115013Smarcel TRACE_SELF_COPYIN4(rem, len, dp) 176115013Smarcel } 177115013Smarcel else { 178115013Smarcel status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp); 179115013Smarcel if (status != 0) 180115013Smarcel return 0; 181115013Smarcel } 182115013Smarcel } 183115013Smarcel else if (request == UWX_COPYIN_REG && len == 8) { 184115013Smarcel if (info->ucontext == 0) 185115013Smarcel return 0; 186115013Smarcel regid = (int)rem; 187115013Smarcel if (rem < UWX_REG_GR(0)) { 188115013Smarcel switch (regid) { 189115013Smarcel case UWX_REG_PREDS: 190115013Smarcel status = __uc_get_prs(info->ucontext, dp); 191115013Smarcel break; 192120925Smarcel case UWX_REG_AR_PFS: 193120925Smarcel status = __uc_get_ar(info->ucontext, 64, dp); 194120925Smarcel break; 195120925Smarcel case UWX_REG_AR_RNAT: 196115013Smarcel status = __uc_get_ar(info->ucontext, 19, dp); 197115013Smarcel break; 198120925Smarcel case UWX_REG_AR_UNAT: 199115013Smarcel status = __uc_get_ar(info->ucontext, 36, dp); 200115013Smarcel break; 201120925Smarcel case UWX_REG_AR_FPSR: 202115013Smarcel status = __uc_get_ar(info->ucontext, 40, dp); 203115013Smarcel break; 204120925Smarcel case UWX_REG_AR_LC: 205115013Smarcel status = __uc_get_ar(info->ucontext, 65, dp); 206115013Smarcel break; 207115013Smarcel default: 208115013Smarcel return 0; 209115013Smarcel } 210115013Smarcel } 211115013Smarcel else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) { 212115013Smarcel status = __uc_get_grs(info->ucontext, 213115013Smarcel regid - UWX_REG_GR(0), 1, dp, &nat); 214115013Smarcel } 215115013Smarcel else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) { 216115013Smarcel status = __uc_get_brs(info->ucontext, 217115013Smarcel regid - UWX_REG_BR(0), 1, dp); 218115013Smarcel } 219115013Smarcel if (status != 0) 220115013Smarcel return 0; 221115013Smarcel } 222115013Smarcel return len; 223115013Smarcel} 224115013Smarcel 225115013Smarcel 226115013Smarcelint uwx_self_lookupip( 227115013Smarcel int request, 228115013Smarcel uint64_t ip, 229115013Smarcel intptr_t tok, 230115013Smarcel uint64_t **resultp) 231115013Smarcel{ 232115013Smarcel struct uwx_self_info *info = (struct uwx_self_info *) tok; 233115013Smarcel UINT64 handle; 234115013Smarcel struct load_module_desc desc; 235115013Smarcel uint64_t *unwind_base; 236115013Smarcel uint64_t *rvec; 237115013Smarcel int i; 238115013Smarcel 239115013Smarcel if (request == UWX_LKUP_LOOKUP) { 240115013Smarcel TRACE_SELF_LOOKUP(ip) 241115013Smarcel if (ip >= info->sendsig_start && ip < info->sendsig_end) { 242115013Smarcel i = 0; 243115013Smarcel rvec = info->rvec; 244115013Smarcel rvec[i++] = UWX_KEY_CONTEXT; 245115013Smarcel rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT; 246115013Smarcel rvec[i++] = 0; 247115013Smarcel rvec[i++] = 0; 248115013Smarcel *resultp = rvec; 249115013Smarcel return UWX_LKUP_FDESC; 250115013Smarcel } 251115013Smarcel else { 252115013Smarcel handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0); 253115013Smarcel if (handle == 0) 254115013Smarcel return UWX_LKUP_ERR; 255115013Smarcel unwind_base = (uint64_t *) desc.unwind_base; 256115013Smarcel TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base) 257115013Smarcel i = 0; 258115013Smarcel rvec = info->rvec; 259115013Smarcel rvec[i++] = UWX_KEY_TBASE; 260115013Smarcel rvec[i++] = desc.text_base; 261115013Smarcel rvec[i++] = UWX_KEY_UFLAGS; 262115013Smarcel rvec[i++] = unwind_base[0]; 263115013Smarcel rvec[i++] = UWX_KEY_USTART; 264115013Smarcel rvec[i++] = desc.text_base + unwind_base[1]; 265115013Smarcel rvec[i++] = UWX_KEY_UEND; 266115013Smarcel rvec[i++] = desc.text_base + unwind_base[2]; 267115013Smarcel rvec[i++] = 0; 268115013Smarcel rvec[i++] = 0; 269115013Smarcel *resultp = rvec; 270115013Smarcel return UWX_LKUP_UTABLE; 271115013Smarcel } 272115013Smarcel } 273115013Smarcel else if (request == UWX_LKUP_FREE) { 274115013Smarcel return 0; 275115013Smarcel } 276115013Smarcel} 277