uwx.h revision 129059
1/* 2Copyright (c) 2003 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#ifndef __UWX_INCLUDED 26#define __UWX_INCLUDED 1 27 28#ifndef _KERNEL 29#include <stdlib.h> 30#include <inttypes.h> 31#else 32#include <sys/param.h> 33#include <sys/systm.h> 34#endif 35 36#if defined(__cplusplus) 37#define __EXTERN_C extern "C" 38#else 39#define __EXTERN_C extern 40#endif 41 42#define UWX_VERSION 1 /* Version id for callback interfaces */ 43 44/* Unwind environment structure (opaque) */ 45struct uwx_env; 46 47/* Allocate and free callbacks */ 48typedef void *(*alloc_cb)(size_t size); 49typedef void (*free_cb)(void *ptr); 50__EXTERN_C int uwx_register_alloc_cb(alloc_cb alloc, free_cb free); 51 52/* Allocate and initialize an unwind environment */ 53__EXTERN_C struct uwx_env *uwx_init(void); 54 55/* Free an unwind environment */ 56__EXTERN_C int uwx_free(struct uwx_env *env); 57 58/* Put unwind express into cross-process mode */ 59__EXTERN_C int uwx_set_remote(struct uwx_env *env, int is_big_endian_target); 60 61/* Copy-in callback */ 62typedef int (*copyin_cb)( 63 int request, /* request code (see below) */ 64 char *loc, /* local (destination) address */ 65 uint64_t rem, /* remote (source) address */ 66 int len, /* number of bytes to copy */ 67 intptr_t tok); /* callback token */ 68 69/* Lookup IP callback */ 70typedef int (*lookupip_cb)( 71 int request, /* request code (see below) */ 72 uint64_t ip, /* IP of current frame */ 73 intptr_t tok, /* callback token */ 74 uint64_t **vecp); /* parameter vector (in/out) */ 75 76/* Register copy-in and lookup IP callbacks */ 77__EXTERN_C int uwx_register_callbacks( 78 struct uwx_env *env, /* unwind environment */ 79 intptr_t tok, /* callback token */ 80 copyin_cb copyin, /* copy-in callback */ 81 lookupip_cb lookupip); /* lookup IP callback */ 82 83/* Initialize a context with the basic info needed to start an unwind */ 84__EXTERN_C int uwx_init_context( 85 struct uwx_env *env, /* unwind environment */ 86 uint64_t ip, /* IP (instruction pointer) */ 87 uint64_t sp, /* SP (stack pointer) */ 88 uint64_t bsp, /* BSP (backing store pointer) */ 89 uint64_t cfm); /* CFM (current frame marker) */ 90 91/* Set the value of a specific register in the current context (non fp) */ 92__EXTERN_C int uwx_set_reg( 93 struct uwx_env *env, /* unwind environment */ 94 int regid, /* register id (see below) */ 95 uint64_t val); /* register value */ 96 97/* Set the value of a floating-point register in the current context */ 98__EXTERN_C int uwx_set_fr( 99 struct uwx_env *env, /* unwind environment */ 100 int regid, /* register id (see below) */ 101 uint64_t *val); /* register value (ptr to 16 bytes) */ 102 /* (memory spill format) */ 103 104/* Initialize the unwind history */ 105__EXTERN_C int uwx_init_history(struct uwx_env *env); 106 107/* Step one frame */ 108__EXTERN_C int uwx_step(struct uwx_env *env); 109 110/* Get symbol information, if available, for current frame */ 111__EXTERN_C int uwx_get_sym_info( 112 struct uwx_env *env, /* unwind environment */ 113 char **modp, /* load module name (out) */ 114 char **symp, /* function name (out) */ 115 uint64_t *offsetp); /* offset from start of function (out) */ 116 117/* Get the value of a register from the current context */ 118__EXTERN_C int uwx_get_reg( 119 struct uwx_env *env, /* unwind environment */ 120 int regid, /* register id (see below) */ 121 uint64_t *valp); /* register value (out) */ 122 123/* Get the NaT bit of a GR from the current context */ 124__EXTERN_C int uwx_get_nat( 125 struct uwx_env *env, /* unwind environment */ 126 int regid, /* register id (see below) */ 127 int *natp); /* NaT value (out: 0 or 1) */ 128 129/* Get the spill location for a register in the current context */ 130__EXTERN_C int uwx_get_spill_loc( 131 struct uwx_env *env, /* unwind environment */ 132 int regid, /* register id (see below) */ 133 uint64_t *dispp); /* disposition code (see below) (out) */ 134 135/* Get the ABI context code (if uwx_step returned UWX_ABI_FRAME) */ 136__EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); 137 138/* Return status codes for uwx_ APIs */ 139#define UWX_OK 0 140#define UWX_BOTTOM 1 /* Hit bottom of stack */ 141#define UWX_ABI_FRAME 2 /* Hit ABI-dependent frame */ 142#define UWX_ERR_NOENV (-1) /* No uwx_env allocated */ 143#define UWX_ERR_IPNOTFOUND (-2) /* Lookup IP c/b returned NOTFOUND */ 144#define UWX_ERR_LOOKUPERR (-3) /* Lookup IP c/b returned ERR */ 145#define UWX_ERR_BADKEY (-4) /* Bad result vector key */ 146#define UWX_ERR_COPYIN_UTBL (-5) /* Error reading unwind table */ 147#define UWX_ERR_COPYIN_UINFO (-6) /* Error reading unwind info */ 148#define UWX_ERR_COPYIN_MSTK (-7) /* Error reading memory stack */ 149#define UWX_ERR_COPYIN_RSTK (-8) /* Error reading register stack */ 150#define UWX_ERR_COPYIN_REG (-9) /* Error reading context register */ 151#define UWX_ERR_NOUENTRY (-10) /* No unwind table entry for ip */ 152#define UWX_ERR_NOUDESC (-11) /* No unwind descriptor covers ip */ 153#define UWX_ERR_BADUDESC (-12) /* Bad unwind descriptor */ 154#define UWX_ERR_NOMEM (-13) /* Out of memory */ 155#define UWX_ERR_PROLOG_UF (-14) /* Prologue underflow */ 156#define UWX_ERR_UNDEFLABEL (-15) /* Undefined label in copy_state */ 157#define UWX_ERR_BADREGID (-16) /* Bad register identifier */ 158#define UWX_ERR_CANTUNWIND (-17) /* Can't unwind */ 159#define UWX_ERR_NOCALLBACKS (-18) /* No callbacks registered */ 160#define UWX_ERR_NOCONTEXT (-19) /* Context not initialized */ 161 162/* Request codes for copyin callback */ 163#define UWX_COPYIN_UINFO 1 /* Reading unwind info */ 164#define UWX_COPYIN_MSTACK 2 /* Reading memory stack */ 165#define UWX_COPYIN_RSTACK 3 /* Reading RSE backing store */ 166#define UWX_COPYIN_REG 4 /* Reading initial register state */ 167 168/* Request codes for lookup IP callback */ 169#define UWX_LKUP_LOOKUP 1 /* Lookup IP */ 170#define UWX_LKUP_FREE 2 /* Free result vector */ 171#define UWX_LKUP_SYMBOLS 3 /* Lookup symbolic information */ 172 173/* Return status codes for lookup IP callback */ 174#define UWX_LKUP_NOTFOUND 0 /* IP not found */ 175#define UWX_LKUP_ERR 1 /* Other error */ 176#define UWX_LKUP_UTABLE 2 /* Returned ref to unwind table */ 177#define UWX_LKUP_FDESC 3 /* Returned frame description */ 178#define UWX_LKUP_SYMINFO 4 /* Returned symbolic information */ 179#define UWX_LKUP_REMAP 5 /* Returned remapped IP */ 180#define UWX_LKUP_UINFO 6 /* Returned unw info block ptr */ 181 182/* The lookup IP callback receives a parameter vector, and returns */ 183/* one on success. This vector is a series of key/value pairs; each */ 184/* even-numbered slot is a key, and each odd-numbered slot is a */ 185/* corresponding value. The vector is terminated by a pair whose */ 186/* key is 0. */ 187#define UWX_KEY_END 0 /* End of vector */ 188 189/* Keys passed to lookup IP callback */ 190#define UWX_KEY_PREDS 1 /* Predicate registers */ 191#define UWX_KEY_VERSION 2 /* Version id of unwind engine */ 192/* UWX_KEY_FUNCSTART (below) may also be passed with the UWX_LKUP_SYMINFO */ 193/* request. */ 194 195/* Keys returned with UWX_LKUP_UTABLE */ 196/* These key/value pairs describe the unwind table corresponding */ 197/* to the load module in which the current IP resides. */ 198#define UWX_KEY_TBASE 1 /* Base address of text seg */ 199#define UWX_KEY_UFLAGS 2 /* Unwind flags (optional) */ 200#define UWX_KEY_USTART 3 /* Base of unwind tbl */ 201#define UWX_KEY_UEND 4 /* End of unwind tbl */ 202 203/* Keys returned with UWX_LKUP_FDESC */ 204/* These key/value pairs describe the state of the frame at the */ 205/* given IP. They are typically used for dynamically-generated code. */ 206/* If UWX_KEY_CONTEXT is returned, it must be the only key returned. */ 207#define UWX_KEY_FSIZE 1 /* Frame size */ 208#define UWX_KEY_SPILL(reg_id) (2 | ((reg_id) << 4)) /* Reg spilled */ 209#define UWX_KEY_CONTEXT 3 /* ABI-dep. context */ 210 211/* Keys returned with UWX_LKUP_REMAP */ 212#define UWX_KEY_NEWIP 5 /* Remapped IP */ 213 214/* Keys returned with UWX_LKUP_UINFO */ 215/* Use UWX_KEY_FUNCSTART for the start address of the function */ 216/* Use UWX_KEY_UFLAGS for the unwind flags (optional) */ 217#define UWX_KEY_UINFO 6 /* Address of unwind info block */ 218 219/* Keys returned with UWX_LKUP_SYMINFO */ 220/* These keys may be returned with UWX_LKUP_FDESC or UWX_LKUP_UINFO, */ 221/* if the information is cheap to obtain. */ 222#define UWX_KEY_MODULE 17 /* Name of load module */ 223#define UWX_KEY_FUNC 18 /* Name of function */ 224#define UWX_KEY_FUNCSTART 19 /* Address of start of function */ 225 226/* Register identifiers */ 227/* For use in UWX_LKUP_FDESC result vectors and context access APIs. */ 228/* "no spill info": These regs aren't spilled directly, so */ 229/* result vectors must not describe these registers. */ 230/* The result vector must describe the related register or */ 231/* pseudo register instead (ip:rp, sp:psp, bsp/cfm:pfs). */ 232/* "pseudo register": Not a machine register, but treated as */ 233/* one for unwind purposes. */ 234#define UWX_REG_IP 0 /* ip (no spill info) */ 235#define UWX_REG_SP 1 /* sp (no spill info) */ 236#define UWX_REG_BSP 2 /* ar.bsp (no spill info) */ 237#define UWX_REG_CFM 3 /* cfm (no spill info) */ 238#define UWX_REG_RP 4 /* rp (pseudo-register) */ 239#define UWX_REG_PSP 5 /* psp (pseudo-register) */ 240#define UWX_REG_PFS 6 /* pfs (pseudo-register) */ 241#define UWX_REG_PREDS 7 /* p0 - p63 */ 242#define UWX_REG_PRIUNAT 8 /* primary unat (pseudo-register) */ 243#define UWX_REG_AR_BSPSTORE 9 /* ar.bspstore */ 244#define UWX_REG_AR_RNAT 10 /* ar.rnat */ 245#define UWX_REG_AR_UNAT 11 /* ar.unat */ 246#define UWX_REG_AR_FPSR 12 /* ar.fpsr */ 247#define UWX_REG_AR_LC 13 /* ar.lc */ 248#define UWX_REG_AR_PFS 14 /* ar.pfs */ 249#define UWX_REG_GR(gr) (0x100 | (gr)) 250#define UWX_REG_FR(fr) (0x200 | (fr)) 251#define UWX_REG_BR(br) (0x300 | (br)) 252 253/* for backwards compatibility with previous releases... */ 254#define UWX_REG_BSPSTORE UWX_REG_AR_BSPSTORE 255#define UWX_REG_RNAT UWX_REG_AR_RNAT 256#define UWX_REG_UNAT UWX_REG_AR_UNAT 257#define UWX_REG_FPSR UWX_REG_AR_FPSR 258#define UWX_REG_LC UWX_REG_AR_LC 259 260/* Values corresponding to UWX_KEY_SPILL keys indicate the disposition */ 261/* of the spilled register -- either in the memory stack or in another */ 262/* register. The PSP register may also have a disposition of "SPPLUS", */ 263/* indicating that its value is SP plus a fixed constant. */ 264#define UWX_DISP_NONE 0 /* Not spilled */ 265#define UWX_DISP_SPPLUS(k) (1 | (k)) /* PSP = SP+constant */ 266#define UWX_DISP_SPREL(disp) (2 | (disp)) /* Spilled at [SP+disp] */ 267#define UWX_DISP_PSPREL(disp) (3 | (disp)) /* Spilled at [PSP+16-disp] */ 268#define UWX_DISP_REG(reg) (4 | ((reg) << 4)) /* Saved to another reg. */ 269 270/* The uwx_get_spill_loc() routine returns a spill location for a */ 271/* given register in the current context. It will return a disposition */ 272/* code of UWX_DISP_NONE, UWX_DISP_REG(reg), or one of the following */ 273/* to indicate that the spilled value can be found in the memory */ 274/* stack or the register stack backing store. */ 275#define UWX_DISP_MSTK(addr) (5 | (addr)) /* Spilled in mem. stack */ 276#define UWX_DISP_RSTK(addr) (6 | (addr)) /* Spilled in reg. stack */ 277 278/* Extract the disposition code, offset, address, or register id */ 279/* from a disposition returned from uwx_get_spill_loc(). */ 280/* Compare the extracted disp code against UWX_DISP_REG(0), etc. */ 281#define UWX_GET_DISP_CODE(disp) ((int)(disp) & 0x07) 282#define UWX_GET_DISP_OFFSET(disp) ((disp) & ~(uint64_t)0x07) 283#define UWX_GET_DISP_ADDR(disp) ((disp) & ~(uint64_t)0x07) 284#define UWX_GET_DISP_REGID(disp) ((int)(disp) >> 4) 285 286#undef __EXTERN_C 287 288#if defined(__cplusplus) 289 290class UnwindExpress { 291 292public: 293 294 UnwindExpress() { 295 env = uwx_init(); 296 } 297 298 ~UnwindExpress() { 299 if (env != 0) 300 uwx_free(env); 301 env = 0; 302 } 303 304 int init_context(uint64_t ip, uint64_t sp, uint64_t bsp, uint64_t cfm) { 305 return uwx_init_context(env, ip, sp, bsp, cfm); 306 } 307 308 int init_history() { 309 return uwx_init_history(env); 310 } 311 312 int set_reg(int regid, uint64_t val) { 313 return uwx_set_reg(env, regid, val); 314 } 315 316 int set_fr(int regid, uint64_t *valp) { 317 return uwx_set_fr(env, regid, valp); 318 } 319 320 int step() { 321 return uwx_step(env); 322 } 323 324 int get_sym_info(char **modp, char **symp, uint64_t *offsetp) { 325 return uwx_get_sym_info(env, modp, symp, offsetp); 326 } 327 328 int get_reg(int regid, uint64_t *valp) { 329 return uwx_get_reg(env, regid, valp); 330 } 331 332 int get_nat(int regid, int *natp) { 333 return uwx_get_nat(env, regid, natp); 334 } 335 336 int get_spill_loc(int regid, uint64_t *dispp) { 337 return uwx_get_spill_loc(env, regid, dispp); 338 } 339 340 int get_abi_context_code() { 341 return uwx_get_abi_context_code(env); 342 } 343 344 struct uwx_env *get_env() { 345 return env; 346 } 347 348protected: 349 350 struct uwx_env *env; 351 352}; 353 354#endif /* __cplusplus */ 355 356#endif /* __UWX_INCLUDED */ 357