diff options
author | marcel <marcel@FreeBSD.org> | 2004-05-09 03:06:25 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2004-05-09 03:06:25 +0000 |
commit | 7cd85074fc21d582d1f2d0173488ff53eac25027 (patch) | |
tree | 239185e3379b0daf241c1024d60e955f5be059e6 /sys/contrib | |
parent | 02de288baa42c7ed6df99d0272fe1e2c776cf55a (diff) | |
parent | 19196476e422744cdc330364d34cbd42882b0953 (diff) | |
download | FreeBSD-src-7cd85074fc21d582d1f2d0173488ff53eac25027.zip FreeBSD-src-7cd85074fc21d582d1f2d0173488ff53eac25027.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r129059,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys/contrib')
-rw-r--r-- | sys/contrib/ia64/libuwx/src.diff | 352 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx.h | 139 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_context.c | 94 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_env.c | 10 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_env.h | 1 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_scoreboard.c | 30 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_self-new.c | 336 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_self.c | 134 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_self.h | 69 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_self_context.s | 89 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_step.c | 150 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_step.h | 5 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_str.c | 3 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_ttrace.c | 8 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_ttrace.h | 2 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_uinfo.c | 5 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_utable.c | 35 | ||||
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_utable.h | 1 |
18 files changed, 1273 insertions, 190 deletions
diff --git a/sys/contrib/ia64/libuwx/src.diff b/sys/contrib/ia64/libuwx/src.diff new file mode 100644 index 0000000..7f5c849 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src.diff @@ -0,0 +1,352 @@ +Only in /sys/contrib/ia64/libuwx/src: CVS +diff -u ./uwx.h /sys/contrib/ia64/libuwx/src/uwx.h +--- ./uwx.h Tue Apr 27 10:42:48 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx.h Thu May 6 18:10:15 2004 +@@ -25,8 +25,13 @@ + #ifndef __UWX_INCLUDED + #define __UWX_INCLUDED 1 + ++#ifndef _KERNEL + #include <stdlib.h> + #include <inttypes.h> ++#else ++#include <sys/param.h> ++#include <sys/systm.h> ++#endif + + #if defined(__cplusplus) + #define __EXTERN_C extern "C" +diff -u ./uwx_bstream.c /sys/contrib/ia64/libuwx/src/uwx_bstream.c +--- ./uwx_bstream.c Tue Apr 27 10:42:52 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_bstream.c Thu May 6 18:12:11 2004 +@@ -64,8 +64,6 @@ + int len; + int n; + int b; +- uint32_t *wp; +- uint64_t *dp; + + if (bstream->peekc >= 0) { + b = bstream->peekc; +@@ -131,6 +129,7 @@ + return 0; + } + ++#if 0 + int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp) + { + uint64_t val; +@@ -179,3 +178,4 @@ + *valp = val; + return 0; + } ++#endif +diff -u ./uwx_context.c /sys/contrib/ia64/libuwx/src/uwx_context.c +--- ./uwx_context.c Tue Apr 27 10:42:52 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_context.c Thu May 6 19:04:36 2004 +@@ -200,7 +200,6 @@ + int sor; + int rrb_gr; + uint64_t bsp; +- int n; + + if (env == 0) + return UWX_ERR_NOENV; +@@ -274,7 +273,6 @@ + + int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) + { +- int status; + + if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) + regid -= UWX_REG_FR(2); +@@ -340,6 +338,7 @@ + return bsp + nslots * DWORDSZ; + } + ++#if 0 + int uwx_selftest_bsp_arithmetic() + { + int i; +@@ -398,3 +397,4 @@ + + return failed; + } ++#endif +diff -u ./uwx_env.c /sys/contrib/ia64/libuwx/src/uwx_env.c +--- ./uwx_env.c Tue Apr 27 10:42:53 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_env.c Thu May 6 21:31:55 2004 +@@ -22,13 +22,21 @@ + OTHER DEALINGS IN THE SOFTWARE. + */ + ++#ifndef _KERNEL + #include <stdlib.h> ++#endif + + #include "uwx_env.h" + #include "uwx_scoreboard.h" + #include "uwx_str.h" + #include "uwx_trace.h" + ++#ifdef _KERNEL ++static struct uwx_env uwx_env; ++#define free(p) /* nullified */ ++#define malloc(sz) ((sz == sizeof(uwx_env)) ? &uwx_env : NULL) ++#endif ++ + alloc_cb uwx_allocate_cb = 0; + free_cb uwx_free_cb = 0; + +@@ -64,7 +72,6 @@ + { + int i; + struct uwx_env *env; +- char *tstr; + + if (uwx_allocate_cb == 0) + env = (struct uwx_env *) malloc(sizeof(struct uwx_env)); +diff -u ./uwx_scoreboard.c /sys/contrib/ia64/libuwx/src/uwx_scoreboard.c +--- ./uwx_scoreboard.c Tue Apr 27 10:42:53 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_scoreboard.c Thu May 6 21:29:25 2004 +@@ -22,12 +22,41 @@ + OTHER DEALINGS IN THE SOFTWARE. + */ + ++#ifndef _KERNEL + #include <stdlib.h> ++#endif + + #include "uwx_env.h" + #include "uwx_scoreboard.h" + #include "uwx_trace.h" + ++#ifdef _KERNEL ++static unsigned short uwx_allocated; ++static struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3]; ++ ++static void ++free(struct uwx_scoreboard *p) ++{ ++ int idx = p - uwx_scoreboard; ++ uwx_allocated &= ~(1 << idx); ++} ++ ++static struct uwx_scoreboard * ++malloc(size_t sz) ++{ ++ int idx; ++ if (sz != sizeof(struct uwx_scoreboard)) ++ return (NULL); ++ for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) { ++ if ((uwx_allocated & (1 << idx)) == 0) { ++ uwx_allocated |= 1 << idx; ++ return (uwx_scoreboard + idx); ++ } ++ } ++ return (NULL); ++} ++#endif ++ + + struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env) + { +@@ -66,6 +95,7 @@ + return sb; + } + ++static + void uwx_reclaim_scoreboards(struct uwx_env *env) + { + struct uwx_scoreboard *sb; +@@ -140,6 +170,7 @@ + /* in the "nextstack" field. */ + + back = 0; ++ new = 0; + while (sb != 0) { + TRACE_B_LABEL_COPY(sb->id) + new = uwx_alloc_scoreboard(env); +@@ -223,6 +254,7 @@ + /* Now copy its stack, storing reverse links in the nextstack field. */ + + back = sb; ++ new = 0; + for (next = lsb->nextstack; next != 0; next = next->nextstack) { + TRACE_B_COPY_COPY(next->id) + new = uwx_alloc_scoreboard(env); +diff -u ./uwx_step.c /sys/contrib/ia64/libuwx/src/uwx_step.c +--- ./uwx_step.c Tue Apr 27 10:42:54 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_step.c Thu May 6 18:32:03 2004 +@@ -66,7 +66,7 @@ + + + /* uwx_get_frame_info: Gets unwind info for current frame */ +- ++static + int uwx_get_frame_info(struct uwx_env *env) + { + int i; +@@ -77,7 +77,6 @@ + uint64_t *uvec; + uint64_t *rstate; + struct uwx_utable_entry uentry; +- uint64_t uinfop; + uint64_t uvecout[UVECSIZE]; + + if (env->copyin == 0 || env->lookupip == 0) +diff -u ./uwx_step.h /sys/contrib/ia64/libuwx/src/uwx_step.h +--- ./uwx_step.h Tue Apr 27 10:42:50 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_step.h Thu May 6 18:45:59 2004 +@@ -25,4 +25,6 @@ + #define UVECSIZE 20 /* Size of uvec supplied by unwind engine */ + /* for callback's use. */ + ++extern int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, ++ uint64_t **vecp, size_t uvecsize); + extern int uwx_restore_markers(struct uwx_env *env); +diff -u ./uwx_str.c /sys/contrib/ia64/libuwx/src/uwx_str.c +--- ./uwx_str.c Tue Apr 27 10:42:55 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_str.c Thu May 6 21:02:58 2004 +@@ -25,6 +25,12 @@ + #include "uwx_env.h" + #include "uwx_str.h" + ++#ifdef _KERNEL ++static struct uwx_str_pool uwx_str_pool; ++#define free(p) /* nullified */ ++#define malloc(sz) ((sz == sizeof(uwx_str_pool)) ? &uwx_str_pool : NULL) ++#endif ++ + /* + * uwx_str.c + * +diff -u ./uwx_trace.c /sys/contrib/ia64/libuwx/src/uwx_trace.c +--- ./uwx_trace.c Tue Apr 27 10:42:55 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_trace.c Thu May 6 18:36:02 2004 +@@ -27,6 +27,8 @@ + #include "uwx_scoreboard.h" + #include "uwx_trace.h" + ++#ifdef UWX_TRACE_ENABLE ++ + void uwx_trace_init(struct uwx_env *env) + { + char *tstr; +@@ -34,7 +36,7 @@ + tstr = getenv("UWX_TRACE"); + if (tstr != NULL) { + while (*tstr != '\0') { +- switch (*tstr++) { ++ switch (*tstr) { + case 'i': env->trace |= UWX_TRACE_UINFO; break; + case 't': env->trace |= UWX_TRACE_UTABLE; break; + case 'b': env->trace |= UWX_TRACE_SB; break; +@@ -44,6 +46,9 @@ + case 'C': env->trace |= UWX_TRACE_COPYIN; break; + case 'L': env->trace |= UWX_TRACE_LOOKUPIP; break; + case '?': ++#ifdef _KERNEL ++ printf("UWX_TRACE flag `%c' unknown.\n", *tstr); ++#else + fprintf(stderr, "UWX_TRACE flags:\n"); + fprintf(stderr, " i: unwind info\n"); + fprintf(stderr, " t: unwind table searching\n"); +@@ -54,7 +59,9 @@ + fprintf(stderr, " C: copyin callback\n"); + fprintf(stderr, " L: lookup ip callback\n"); + exit(1); ++#endif + } ++ tstr++; + } + } + } +@@ -107,7 +114,7 @@ + printf(" [reg %d]\n", reg); + break; + default: +- printf(" <%08x>\n", rstate); ++ printf(" <%08llx>\n", (unsigned long long)rstate); + break; + } + } +@@ -133,3 +140,4 @@ + uwx_dump_rstate(i, scoreboard->rstate[i]); + } + ++#endif /* UWX_TRACE_ENABLE */ +diff -u ./uwx_uinfo.c /sys/contrib/ia64/libuwx/src/uwx_uinfo.c +--- ./uwx_uinfo.c Tue Apr 27 10:42:56 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_uinfo.c Thu May 6 18:46:51 2004 +@@ -28,6 +28,7 @@ + #include "uwx_scoreboard.h" + #include "uwx_bstream.h" + #include "uwx_trace.h" ++#include "uwx_swap.h" + + int uwx_count_ones(unsigned int mask); + +diff -u ./uwx_utable.c /sys/contrib/ia64/libuwx/src/uwx_utable.c +--- ./uwx_utable.c Tue Apr 27 10:42:56 2004 ++++ /sys/contrib/ia64/libuwx/src/uwx_utable.c Thu May 6 18:58:55 2004 +@@ -76,7 +76,10 @@ + /* Make sure all three required values are given. */ + + keys = 0; ++ text_base = 0; + unwind_flags = 0; ++ unwind_start = 0; ++ unwind_end = 0; + while (*uvec != 0) { + switch ((int)*uvec++) { + case UWX_KEY_TBASE: +@@ -139,7 +142,6 @@ + uint32_t unwind_end, + struct uwx_utable_entry *uentry) + { +- int status; + int lb; + int ub; + int mid; +@@ -160,11 +162,13 @@ + + lb = 0; + ub = (unwind_end - unwind_start) / (3 * WORDSZ); ++ mid = 0; + while (ub > lb) { + mid = (lb + ub) / 2; +- len = COPYIN_UINFO_4((char *)&code_start, unwind_start+mid*3*WORDSZ); ++ len = COPYIN_UINFO_4((char *)&code_start, ++ (uintptr_t)(unwind_start+mid*3*WORDSZ)); + len += COPYIN_UINFO_4((char *)&code_end, +- unwind_start+mid*3*WORDSZ+WORDSZ); ++ (uintptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ)); + if (len != 2 * WORDSZ) + return UWX_ERR_COPYIN_UTBL; + if (env->byte_swap) { +@@ -182,7 +186,7 @@ + if (ub <= lb) + return UWX_ERR_NOUENTRY; + len = COPYIN_UINFO_4((char *)&unwind_info, +- unwind_start+mid*3*WORDSZ+2*WORDSZ); ++ (uintptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ)); + if (len != WORDSZ) + return UWX_ERR_COPYIN_UTBL; + if (env->byte_swap) +@@ -210,7 +214,6 @@ + uint64_t unwind_end, + struct uwx_utable_entry *uentry) + { +- int status; + int lb; + int ub; + int mid; +@@ -229,6 +232,7 @@ + + lb = 0; + ub = (unwind_end - unwind_start) / (3 * DWORDSZ); ++ mid = 0; + while (ub > lb) { + mid = (lb + ub) / 2; + len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ); diff --git a/sys/contrib/ia64/libuwx/src/uwx.h b/sys/contrib/ia64/libuwx/src/uwx.h index a2d318d..9adcfb9 100644 --- a/sys/contrib/ia64/libuwx/src/uwx.h +++ b/sys/contrib/ia64/libuwx/src/uwx.h @@ -22,6 +22,9 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifndef __UWX_INCLUDED +#define __UWX_INCLUDED 1 + #ifndef _KERNEL #include <stdlib.h> #include <inttypes.h> @@ -30,22 +33,30 @@ OTHER DEALINGS IN THE SOFTWARE. #include <sys/systm.h> #endif +#if defined(__cplusplus) +#define __EXTERN_C extern "C" +#else +#define __EXTERN_C extern +#endif + +#define UWX_VERSION 1 /* Version id for callback interfaces */ + /* Unwind environment structure (opaque) */ struct uwx_env; /* Allocate and free callbacks */ typedef void *(*alloc_cb)(size_t size); typedef void (*free_cb)(void *ptr); -extern int uwx_register_alloc_cb(alloc_cb alloc, free_cb free); +__EXTERN_C int uwx_register_alloc_cb(alloc_cb alloc, free_cb free); /* Allocate and initialize an unwind environment */ -extern struct uwx_env *uwx_init(void); +__EXTERN_C struct uwx_env *uwx_init(void); /* Free an unwind environment */ -extern int uwx_free(struct uwx_env *env); +__EXTERN_C int uwx_free(struct uwx_env *env); /* Put unwind express into cross-process mode */ -extern int uwx_set_remote(struct uwx_env *env, int is_big_endian_target); +__EXTERN_C int uwx_set_remote(struct uwx_env *env, int is_big_endian_target); /* Copy-in callback */ typedef int (*copyin_cb)( @@ -63,14 +74,14 @@ typedef int (*lookupip_cb)( uint64_t **vecp); /* parameter vector (in/out) */ /* Register copy-in and lookup IP callbacks */ -extern int uwx_register_callbacks( +__EXTERN_C int uwx_register_callbacks( struct uwx_env *env, /* unwind environment */ intptr_t tok, /* callback token */ copyin_cb copyin, /* copy-in callback */ lookupip_cb lookupip); /* lookup IP callback */ /* Initialize a context with the basic info needed to start an unwind */ -extern int uwx_init_context( +__EXTERN_C int uwx_init_context( struct uwx_env *env, /* unwind environment */ uint64_t ip, /* IP (instruction pointer) */ uint64_t sp, /* SP (stack pointer) */ @@ -78,51 +89,51 @@ extern int uwx_init_context( uint64_t cfm); /* CFM (current frame marker) */ /* Set the value of a specific register in the current context (non fp) */ -extern int uwx_set_reg( +__EXTERN_C int uwx_set_reg( struct uwx_env *env, /* unwind environment */ int regid, /* register id (see below) */ uint64_t val); /* register value */ /* Set the value of a floating-point register in the current context */ -extern int uwx_set_fr( +__EXTERN_C int uwx_set_fr( struct uwx_env *env, /* unwind environment */ int regid, /* register id (see below) */ uint64_t *val); /* register value (ptr to 16 bytes) */ /* (memory spill format) */ /* Initialize the unwind history */ -extern int uwx_init_history(struct uwx_env *env); +__EXTERN_C int uwx_init_history(struct uwx_env *env); /* Step one frame */ -extern int uwx_step(struct uwx_env *env); +__EXTERN_C int uwx_step(struct uwx_env *env); /* Get symbol information, if available, for current frame */ -extern int uwx_get_sym_info( +__EXTERN_C int uwx_get_sym_info( struct uwx_env *env, /* unwind environment */ char **modp, /* load module name (out) */ char **symp, /* function name (out) */ uint64_t *offsetp); /* offset from start of function (out) */ /* Get the value of a register from the current context */ -extern int uwx_get_reg( +__EXTERN_C int uwx_get_reg( struct uwx_env *env, /* unwind environment */ int regid, /* register id (see below) */ uint64_t *valp); /* register value (out) */ /* Get the NaT bit of a GR from the current context */ -extern int uwx_get_nat( +__EXTERN_C int uwx_get_nat( struct uwx_env *env, /* unwind environment */ int regid, /* register id (see below) */ int *natp); /* NaT value (out: 0 or 1) */ /* Get the spill location for a register in the current context */ -extern int uwx_get_spill_loc( +__EXTERN_C int uwx_get_spill_loc( struct uwx_env *env, /* unwind environment */ int regid, /* register id (see below) */ uint64_t *dispp); /* disposition code (see below) (out) */ /* Get the ABI context code (if uwx_step returned UWX_ABI_FRAME) */ -extern int uwx_get_abi_context_code(struct uwx_env *env); +__EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); /* Return status codes for uwx_ APIs */ #define UWX_OK 0 @@ -165,6 +176,8 @@ extern int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_LKUP_UTABLE 2 /* Returned ref to unwind table */ #define UWX_LKUP_FDESC 3 /* Returned frame description */ #define UWX_LKUP_SYMINFO 4 /* Returned symbolic information */ +#define UWX_LKUP_REMAP 5 /* Returned remapped IP */ +#define UWX_LKUP_UINFO 6 /* Returned unw info block ptr */ /* The lookup IP callback receives a parameter vector, and returns */ /* one on success. This vector is a series of key/value pairs; each */ @@ -175,26 +188,40 @@ extern int uwx_get_abi_context_code(struct uwx_env *env); /* Keys passed to lookup IP callback */ #define UWX_KEY_PREDS 1 /* Predicate registers */ +#define UWX_KEY_VERSION 2 /* Version id of unwind engine */ +/* UWX_KEY_FUNCSTART (below) may also be passed with the UWX_LKUP_SYMINFO */ +/* request. */ /* Keys returned with UWX_LKUP_UTABLE */ /* These key/value pairs describe the unwind table corresponding */ /* to the load module in which the current IP resides. */ #define UWX_KEY_TBASE 1 /* Base address of text seg */ -#define UWX_KEY_UFLAGS 2 /* Unwind flags */ +#define UWX_KEY_UFLAGS 2 /* Unwind flags (optional) */ #define UWX_KEY_USTART 3 /* Base of unwind tbl */ #define UWX_KEY_UEND 4 /* End of unwind tbl */ /* Keys returned with UWX_LKUP_FDESC */ /* These key/value pairs describe the state of the frame at the */ /* given IP. They are typically used for dynamically-generated code. */ +/* If UWX_KEY_CONTEXT is returned, it must be the only key returned. */ #define UWX_KEY_FSIZE 1 /* Frame size */ #define UWX_KEY_SPILL(reg_id) (2 | ((reg_id) << 4)) /* Reg spilled */ #define UWX_KEY_CONTEXT 3 /* ABI-dep. context */ -/* Keys returned with UWX_LKUP_FDESC or UWX_LKUP_SYMINFO */ -#define UWX_KEY_MODULE 5 /* Name of load module */ -#define UWX_KEY_FUNC 6 /* Name of function */ -#define UWX_KEY_FUNCSTART 7 /* Address of start of function */ +/* Keys returned with UWX_LKUP_REMAP */ +#define UWX_KEY_NEWIP 5 /* Remapped IP */ + +/* Keys returned with UWX_LKUP_UINFO */ +/* Use UWX_KEY_FUNCSTART for the start address of the function */ +/* Use UWX_KEY_UFLAGS for the unwind flags (optional) */ +#define UWX_KEY_UINFO 6 /* Address of unwind info block */ + +/* Keys returned with UWX_LKUP_SYMINFO */ +/* These keys may be returned with UWX_LKUP_FDESC or UWX_LKUP_UINFO, */ +/* if the information is cheap to obtain. */ +#define UWX_KEY_MODULE 17 /* Name of load module */ +#define UWX_KEY_FUNC 18 /* Name of function */ +#define UWX_KEY_FUNCSTART 19 /* Address of start of function */ /* Register identifiers */ /* For use in UWX_LKUP_FDESC result vectors and context access APIs. */ @@ -255,3 +282,75 @@ extern int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_GET_DISP_OFFSET(disp) ((disp) & ~(uint64_t)0x07) #define UWX_GET_DISP_ADDR(disp) ((disp) & ~(uint64_t)0x07) #define UWX_GET_DISP_REGID(disp) ((int)(disp) >> 4) + +#undef __EXTERN_C + +#if defined(__cplusplus) + +class UnwindExpress { + +public: + + UnwindExpress() { + env = uwx_init(); + } + + ~UnwindExpress() { + if (env != 0) + uwx_free(env); + env = 0; + } + + int init_context(uint64_t ip, uint64_t sp, uint64_t bsp, uint64_t cfm) { + return uwx_init_context(env, ip, sp, bsp, cfm); + } + + int init_history() { + return uwx_init_history(env); + } + + int set_reg(int regid, uint64_t val) { + return uwx_set_reg(env, regid, val); + } + + int set_fr(int regid, uint64_t *valp) { + return uwx_set_fr(env, regid, valp); + } + + int step() { + return uwx_step(env); + } + + int get_sym_info(char **modp, char **symp, uint64_t *offsetp) { + return uwx_get_sym_info(env, modp, symp, offsetp); + } + + int get_reg(int regid, uint64_t *valp) { + return uwx_get_reg(env, regid, valp); + } + + int get_nat(int regid, int *natp) { + return uwx_get_nat(env, regid, natp); + } + + int get_spill_loc(int regid, uint64_t *dispp) { + return uwx_get_spill_loc(env, regid, dispp); + } + + int get_abi_context_code() { + return uwx_get_abi_context_code(env); + } + + struct uwx_env *get_env() { + return env; + } + +protected: + + struct uwx_env *env; + +}; + +#endif /* __cplusplus */ + +#endif /* __UWX_INCLUDED */ diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.c b/sys/contrib/ia64/libuwx/src/uwx_context.c index 01b594d..68e65e7 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_context.c +++ b/sys/contrib/ia64/libuwx/src/uwx_context.c @@ -181,11 +181,7 @@ int uwx_get_nat(struct uwx_env *env, int regid, int *natp) } bsp = uwx_add_to_bsp(bsp, regid); natcollp = bsp | 0x01f8; - if (natcollp >= bsp) - n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll, - (uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token); - else - n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, + n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, bsp, DWORDSZ, env->cb_token); if (n != DWORDSZ) return UWX_ERR_COPYIN_RSTK; @@ -319,28 +315,86 @@ uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) * bsp * <------- adjusted (nslots + bias) -------> - * When subtracting from bsp, we bias the bsp in the opposite - * direction so that it is at the next NaT collection. + * When subtracting from bsp, we avoid depending on the sign of + * the quotient by adding 63*8 before division and subtracting 8 + * after division. (Assumes that we will never be called upon + * to subtract more than 504 slots from bsp.) * * 0 1f8 3f8 * +---------------------------------------------------------------+ * | X X| * +---------------------------------------------------------------+ - * <------- bias -------> - * <--- nslots ---> - * ^ - * | - * bsp - * <------ adjusted (nslots + bias) ------> + * <-- bias --> + * <--- |nslots| ---> + * ^ + * | + * bsp + * <-----------------> + * adjusted |nslots + bias| */ - if (nslots > 0) { - bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; - nslots += (nslots + bias) / 63; + bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; + nslots += (nslots + bias + 63*8) / 63 - 8; + return bsp + nslots * DWORDSZ; +} + +#if 0 +int uwx_selftest_bsp_arithmetic() +{ + int i; + int j; + int r; + uint64_t bstore[161]; + uint64_t *bsp; + uint64_t *p; + int failed = 0; + + printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore); + r = 0; + bsp = bstore; + for (i = 0; i < 161; i++) { + if (((unsigned int)bsp & 0x1f8) == 0x1f8) + *bsp++ = 1000 + r; + else + *bsp++ = r++; } - else if (nslots < 0) { - bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ; - nslots -= (-nslots + bias) / 63; + + printf("uwx_selftest_bsp_arithmetic: plus tests...\n"); + bsp = bstore; + for (i = 0; i < 64; i++) { + r = (int)*bsp; + if (r >= 1000) + r -= 1000; + for (j = 0; j < 96; j++) { + p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, j); + if (*p != (r + j)) { + failed++; + printf("%d [%08lx] + %d -> %08lx ", + i, (unsigned int)bsp, j, (unsigned int)p); + printf("(read %d instead of %d)\n", (int)*p, r + j); + } + } + bsp++; } - return bsp + nslots * DWORDSZ; + + printf("uwx_selftest_bsp_arithmetic: minus tests...\n"); + bsp = &bstore[161]; + for (i = 63; i >= 0; i--) { + bsp--; + r = (int)*bsp; + if (r >= 1000) + r -= 1000; + for (j = 0; j < 96; j++) { + p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, -j); + if (*p != (r - j)) { + failed++; + printf("%d [%08lx] - %d -> %08lx ", + i, (unsigned int)bsp, j, (unsigned int)p); + printf("(read %d instead of %d)\n", (int)*p, r - j); + } + } + } + + return failed; } +#endif diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.c b/sys/contrib/ia64/libuwx/src/uwx_env.c index aa2c4a0..4149a27 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_env.c +++ b/sys/contrib/ia64/libuwx/src/uwx_env.c @@ -24,9 +24,6 @@ OTHER DEALINGS IN THE SOFTWARE. #ifndef _KERNEL #include <stdlib.h> -#else -#define free(p) /* nullified */ -#define malloc(sz) NULL #endif #include "uwx_env.h" @@ -34,6 +31,12 @@ OTHER DEALINGS IN THE SOFTWARE. #include "uwx_str.h" #include "uwx_trace.h" +#ifdef _KERNEL +static struct uwx_env uwx_env; +#define free(p) /* nullified */ +#define malloc(sz) ((sz == sizeof(uwx_env)) ? &uwx_env : NULL) +#endif + alloc_cb uwx_allocate_cb = 0; free_cb uwx_free_cb = 0; @@ -88,6 +91,7 @@ struct uwx_env *uwx_init() env->context.fr[i].part1 = 0; } env->rstate = 0; + env->remapped_ip = 0; env->function_offset = 0; (void)uwx_init_history(env); env->allocate_cb = uwx_allocate_cb; diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.h b/sys/contrib/ia64/libuwx/src/uwx_env.h index f730bdd..2451239 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_env.h +++ b/sys/contrib/ia64/libuwx/src/uwx_env.h @@ -78,6 +78,7 @@ struct uwx_str_pool; struct uwx_env { struct uwx_context context; uint64_t *rstate; + uint64_t remapped_ip; int64_t function_offset; struct uwx_history history; alloc_cb allocate_cb; diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c index bee0706..ee58880 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c +++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c @@ -24,15 +24,39 @@ OTHER DEALINGS IN THE SOFTWARE. #ifndef _KERNEL #include <stdlib.h> -#else -#define free(p) /* nullified */ -#define malloc(sz) NULL #endif #include "uwx_env.h" #include "uwx_scoreboard.h" #include "uwx_trace.h" +#ifdef _KERNEL +static unsigned short uwx_allocated; +static struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3]; + +static void +free(struct uwx_scoreboard *p) +{ + int idx = p - uwx_scoreboard; + uwx_allocated &= ~(1 << idx); +} + +static struct uwx_scoreboard * +malloc(size_t sz) +{ + int idx; + if (sz != sizeof(struct uwx_scoreboard)) + return (NULL); + for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) { + if ((uwx_allocated & (1 << idx)) == 0) { + uwx_allocated |= 1 << idx; + return (uwx_scoreboard + idx); + } + } + return (NULL); +} +#endif + struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env) { diff --git a/sys/contrib/ia64/libuwx/src/uwx_self-new.c b/sys/contrib/ia64/libuwx/src/uwx_self-new.c new file mode 100644 index 0000000..64c6ac6 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_self-new.c @@ -0,0 +1,336 @@ +/* +Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <stdlib.h> +#include <crt0.h> +#include <dlfcn.h> +#include <sys/uc_access.h> + +#include "uwx_env.h" +#include "uwx_context.h" +#include "uwx_trace.h" +#include "uwx_self.h" + +#define MODULE_CACHE_SIZE 10 + +#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */ + +struct uwx_self_module_info { + uint64_t text_base; + uint64_t text_size; + uint64_t *unwind_base; + uint64_t last_access; + char *name; + struct uwx_self_module_info *next; +}; + +struct uwx_self_info { + struct uwx_env *env; + ucontext_t *ucontext; + uint64_t bspstore; + uint64_t rvec[10]; + uint64_t sendsig_start; + uint64_t sendsig_end; + alloc_cb allocate_cb; + free_cb free_cb; + int trace; + struct load_module_desc desc; + struct uwx_self_module_info *module_cache; +}; + +struct uwx_self_info *uwx_self_init_info(struct uwx_env *env) +{ + struct uwx_self_info *info; + struct uwx_self_module_info *modules; + size_t size; + + size = sizeof(struct uwx_self_info) + + MODULE_CACHE_SIZE * sizeof(struct uwx_self_module_info); + + if (env->allocate_cb == 0) + info = (struct uwx_self_info *) malloc(size); + else + info = (struct uwx_self_info *) (*env->allocate_cb)(size); + if (info == 0) + return 0; + + modules = (struct uwx_self_module_info *) (info + 1); + + info->env = env; + info->ucontext = 0; + info->bspstore = 0; + info->sendsig_start = __load_info->li_sendsig_txt; + info->sendsig_end = __load_info->li_sendsig_txt + + __load_info->li_sendsig_tsz; + info->allocate_cb = env->allocate_cb; + info->free_cb = env->free_cb; + info->trace = env->trace; + info->module_cache = modules; + + for (i = 0; i < MODULE_CACHE_SIZE; i++) { + modules[i].text_base = 0; + modules[i].text_size = 0; + modules[i].unwind_base = 0; + modules[i].last_access = 0; + modules[i].name = 0; + modules[i].next = 0; + } + + return info; +} + +int uwx_self_free_info(struct uwx_self_info *info) +{ + if (info->free_cb == 0) + free((void *)info); + else + (*info->free_cb)((void *)info); + return UWX_OK; +} + +int uwx_self_init_from_sigcontext( + struct uwx_env *env, + struct uwx_self_info *info, + ucontext_t *ucontext) +{ + int status; + uint16_t reason; + uint64_t ip; + uint64_t sp; + uint64_t bsp; + uint64_t cfm; + unsigned int nat; + uint64_t ec; + int adj; + + info->ucontext = ucontext; + status = __uc_get_reason(ucontext, &reason); + status = __uc_get_ip(ucontext, &ip); + status = __uc_get_grs(ucontext, 12, 1, &sp, &nat); + status = __uc_get_cfm(ucontext, &cfm); +#ifdef NEW_UC_GET_AR + status = __uc_get_ar_bsp(ucontext, &bsp); + status = __uc_get_ar_bspstore(ucontext, &info->bspstore); + status = __uc_get_ar_ec(ucontext, &ec); +#else + status = __uc_get_ar(ucontext, 17, &bsp); + status = __uc_get_ar(ucontext, 18, &info->bspstore); + status = __uc_get_ar(ucontext, 66, &ec); +#endif + /* The returned bsp needs to be adjusted. */ + /* For interrupt frames, where bsp was advanced by a cover */ + /* instruction, subtract sof (size of frame). For non-interrupt */ + /* frames, where bsp was advanced by br.call, subtract sol */ + /* (size of locals). */ + if (reason != 0) + adj = (unsigned int)cfm & 0x7f; /* interrupt frame */ + else + adj = ((unsigned int)cfm >> 7) & 0x7f; /* non-interrupt frame */ + bsp = uwx_add_to_bsp(bsp, -adj); + cfm |= ec << 52; + uwx_init_context(env, ip, sp, bsp, cfm); + return UWX_OK; +} + +int uwx_self_do_context_frame( + struct uwx_env *env, + struct uwx_self_info *info) +{ + int abi_context; + int status; + uint64_t ucontext; + + abi_context = uwx_get_abi_context_code(env); + if (abi_context != UWX_ABI_HPUX_SIGCONTEXT) + return UWX_SELF_ERR_BADABICONTEXT; + status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext); + if (status != 0) + return status; + return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext); +} + +int uwx_self_copyin( + int request, + char *loc, + uint64_t rem, + int len, + intptr_t tok) +{ + int status; + int regid; + unsigned int nat; + struct uwx_self_info *info = (struct uwx_self_info *) tok; + unsigned long *wp; + uint64_t *dp; + + status = -1; + + dp = (uint64_t *) loc; + + switch (request) { + case UWX_COPYIN_UINFO: + case UWX_COPYIN_MSTACK: + if (len == 4) { + wp = (unsigned long *) loc; + *wp = *(unsigned long *)rem; + TRACE_SELF_COPYIN4(rem, len, wp) + status = 0; + } + else if (len == 8) { + *dp = *(uint64_t *)rem; + TRACE_SELF_COPYIN8(rem, len, dp) + status = 0; + } + break; + case UWX_COPYIN_RSTACK: + if (len == 8) { + if (info->ucontext == 0 && rem == (info->bspstore | 0x1f8)) { + *dp = info->env->context.special[UWX_REG_AR_RNAT]; + status = 0; + } + else if (info->ucontext == 0 || rem < info->bspstore) { + *dp = *(uint64_t *)rem; + TRACE_SELF_COPYIN8(rem, len, dp) + status = 0; + } + else { + status = __uc_get_rsebs(info->ucontext, + (uint64_t *)rem, 1, dp); + } + } + break; + case UWX_COPYIN_REG: + regid = (int)rem; + if (info->ucontext != 0) { + if (len == 8) { + if (rem == UWX_REG_PREDS) + status = __uc_get_prs(info->ucontext, dp); + else if (rem == UWX_REG_AR_PFS) + status = __uc_get_ar(info->ucontext, 64, dp); + else if (rem == UWX_REG_AR_RNAT) + status = __uc_get_ar(info->ucontext, 19, dp); + else if (rem == UWX_REG_AR_UNAT) + status = __uc_get_ar(info->ucontext, 36, dp); + else if (rem == UWX_REG_AR_FPSR) + status = __uc_get_ar(info->ucontext, 40, dp); + else if (rem == UWX_REG_AR_LC) + status = __uc_get_ar(info->ucontext, 65, dp); + else if (regid >= UWX_REG_GR(1) && + regid <= UWX_REG_GR(31)) + status = __uc_get_grs(info->ucontext, + regid - UWX_REG_GR(0), 1, dp, &nat); + else if (regid >= UWX_REG_BR(0) && + regid <= UWX_REG_BR(7)) + status = __uc_get_brs(info->ucontext, + regid - UWX_REG_BR(0), 1, dp); + } + else if (len == 16) { + if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) { + status = __uc_get_frs(info->ucontext, + regid - UWX_REG_FR(0), 1, (fp_regval_t *)dp); + } + } + } + break; + } + if (status != 0) + return 0; + return len; +} + +int uwx_self_find_module( + uint64_t ip, + struct uwx_self_info *info, + uint64_t *text_base, + uint64_t **unwind_base) +{ + UINT64 handle; + + /* Search our cache for the module containing the IP */ + + /* Not in the cache -- call dlmodinfo */ + + handle = dlmodinfo(ip, &info->desc, sizeof(info->desc), 0, 0, 0); + if (handle == 0) + return UWX_ERR_IPNOTFOUND; + + /* Store it in the cache */ + + *text_base = info->desc.text_base; + *unwind_base = (uint64_t *) info->desc.unwind_base; + return UWX_OK; +} + +int uwx_self_lookupip( + int request, + uint64_t ip, + intptr_t tok, + uint64_t **resultp) +{ + struct uwx_self_info *info = (struct uwx_self_info *) tok; + uint64_t text_base; + uint64_t *unwind_base; + uint64_t *rvec; + int i; + + if (request == UWX_LKUP_LOOKUP) { + TRACE_SELF_LOOKUP(ip) + if (ip >= info->sendsig_start && ip < info->sendsig_end) { + i = 0; + rvec = info->rvec; + rvec[i++] = UWX_KEY_CONTEXT; + rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT; + rvec[i++] = 0; + rvec[i++] = 0; + *resultp = rvec; + return UWX_LKUP_FDESC; + } + else { + if (uwx_self_find_module(ip, info, + &text_base, &unwind_base) != UWX_OK) + return UWX_LKUP_ERR; + TRACE_SELF_LOOKUP_DESC(text_base, unwind_base) + i = 0; + rvec = info->rvec; + rvec[i++] = UWX_KEY_TBASE; + rvec[i++] = text_base; + rvec[i++] = UWX_KEY_UFLAGS; + rvec[i++] = unwind_base[0]; + rvec[i++] = UWX_KEY_USTART; + rvec[i++] = text_base + unwind_base[1]; + rvec[i++] = UWX_KEY_UEND; + rvec[i++] = text_base + unwind_base[2]; + rvec[i++] = 0; + rvec[i++] = 0; + *resultp = rvec; + return UWX_LKUP_UTABLE; + } + } + else if (request == UWX_LKUP_FREE) { + return 0; + } + else if (request == UWX_LKUP_SYMBOLS) { + return UWX_LKUP_ERR; + } +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.c b/sys/contrib/ia64/libuwx/src/uwx_self.c index f5b1276..af2e36f 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self.c +++ b/sys/contrib/ia64/libuwx/src/uwx_self.c @@ -22,12 +22,10 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _KERNEL #include <stdlib.h> #include <crt0.h> #include <dlfcn.h> #include <sys/uc_access.h> -#endif #include "uwx_env.h" #include "uwx_context.h" @@ -37,6 +35,7 @@ OTHER DEALINGS IN THE SOFTWARE. #define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */ struct uwx_self_info { + struct uwx_env *env; ucontext_t *ucontext; uint64_t bspstore; uint64_t rvec[10]; @@ -60,6 +59,7 @@ struct uwx_self_info *uwx_self_init_info(struct uwx_env *env) if (info == 0) return 0; + info->env = env; info->ucontext = 0; info->bspstore = 0; info->sendsig_start = __load_info->li_sendsig_txt; @@ -155,72 +155,78 @@ int uwx_self_copyin( unsigned long *wp; uint64_t *dp; + status = -1; + dp = (uint64_t *) loc; - if (request == UWX_COPYIN_UINFO || - request == UWX_COPYIN_MSTACK) { - if (len == 4) { - wp = (unsigned long *) loc; - *wp = *(unsigned long *)rem; - TRACE_SELF_COPYIN4(rem, len, wp) - } - else if (len == 8) { - *dp = *(uint64_t *)rem; - TRACE_SELF_COPYIN4(rem, len, dp) - } - else - return 0; - } - else if (request == UWX_COPYIN_RSTACK && len == 8) { - if (info->ucontext == 0 || rem < info->bspstore) { - *dp = *(uint64_t *)rem; - TRACE_SELF_COPYIN4(rem, len, dp) - } - else { - status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp); - if (status != 0) - return 0; - } - } - else if (request == UWX_COPYIN_REG && len == 8) { - if (info->ucontext == 0) - return 0; - regid = (int)rem; - if (rem < UWX_REG_GR(0)) { - switch (regid) { - case UWX_REG_PREDS: - status = __uc_get_prs(info->ucontext, dp); - break; - case UWX_REG_AR_PFS: - status = __uc_get_ar(info->ucontext, 64, dp); - break; - case UWX_REG_AR_RNAT: - status = __uc_get_ar(info->ucontext, 19, dp); - break; - case UWX_REG_AR_UNAT: - status = __uc_get_ar(info->ucontext, 36, dp); - break; - case UWX_REG_AR_FPSR: - status = __uc_get_ar(info->ucontext, 40, dp); - break; - case UWX_REG_AR_LC: - status = __uc_get_ar(info->ucontext, 65, dp); - break; - default: - return 0; + switch (request) { + case UWX_COPYIN_UINFO: + case UWX_COPYIN_MSTACK: + if (len == 4) { + wp = (unsigned long *) loc; + *wp = *(unsigned long *)rem; + TRACE_SELF_COPYIN4(rem, len, wp) + status = 0; } - } - else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) { - status = __uc_get_grs(info->ucontext, - regid - UWX_REG_GR(0), 1, dp, &nat); - } - else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) { - status = __uc_get_brs(info->ucontext, - regid - UWX_REG_BR(0), 1, dp); - } - if (status != 0) - return 0; + else if (len == 8) { + *dp = *(uint64_t *)rem; + TRACE_SELF_COPYIN8(rem, len, dp) + status = 0; + } + break; + case UWX_COPYIN_RSTACK: + if (len == 8) { + if (info->ucontext == 0 && rem == (info->bspstore | 0x1f8)) { + *dp = info->env->context.special[UWX_REG_AR_RNAT]; + status = 0; + } + else if (info->ucontext == 0 || rem < info->bspstore) { + *dp = *(uint64_t *)rem; + TRACE_SELF_COPYIN8(rem, len, dp) + status = 0; + } + else { + status = __uc_get_rsebs(info->ucontext, + (uint64_t *)rem, 1, dp); + } + } + break; + case UWX_COPYIN_REG: + regid = (int)rem; + if (info->ucontext != 0) { + if (len == 8) { + if (rem == UWX_REG_PREDS) + status = __uc_get_prs(info->ucontext, dp); + else if (rem == UWX_REG_AR_PFS) + status = __uc_get_ar(info->ucontext, 64, dp); + else if (rem == UWX_REG_AR_RNAT) + status = __uc_get_ar(info->ucontext, 19, dp); + else if (rem == UWX_REG_AR_UNAT) + status = __uc_get_ar(info->ucontext, 36, dp); + else if (rem == UWX_REG_AR_FPSR) + status = __uc_get_ar(info->ucontext, 40, dp); + else if (rem == UWX_REG_AR_LC) + status = __uc_get_ar(info->ucontext, 65, dp); + else if (regid >= UWX_REG_GR(1) && + regid <= UWX_REG_GR(31)) + status = __uc_get_grs(info->ucontext, + regid - UWX_REG_GR(0), 1, dp, &nat); + else if (regid >= UWX_REG_BR(0) && + regid <= UWX_REG_BR(7)) + status = __uc_get_brs(info->ucontext, + regid - UWX_REG_BR(0), 1, dp); + } + else if (len == 16) { + if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) { + status = __uc_get_frs(info->ucontext, + regid - UWX_REG_FR(0), 1, (fp_regval_t *)dp); + } + } + } + break; } + if (status != 0) + return 0; return len; } diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.h b/sys/contrib/ia64/libuwx/src/uwx_self.h index e324d0d..0590ade 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self.h +++ b/sys/contrib/ia64/libuwx/src/uwx_self.h @@ -22,38 +22,91 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _KERNEL +#ifndef __UWX_SELF_INCLUDED +#define __UWX_SELF_INCLUDED 1 + #include <signal.h> + +#ifndef __UWX_INCLUDED +#include "uwx.h" +#endif /* __UWX_INCLUDED */ + +#if defined(__cplusplus) +#define __EXTERN_C extern "C" +#else +#define __EXTERN_C extern #endif struct uwx_self_info; -extern struct uwx_self_info *uwx_self_init_info(struct uwx_env *env); +__EXTERN_C struct uwx_self_info *uwx_self_init_info(struct uwx_env *env); -extern int uwx_self_free_info(struct uwx_self_info *info); +__EXTERN_C int uwx_self_free_info(struct uwx_self_info *info); -extern int uwx_self_init_context(struct uwx_env *env); +__EXTERN_C int uwx_self_init_context(struct uwx_env *env); -extern int uwx_self_init_from_sigcontext( +__EXTERN_C int uwx_self_init_from_sigcontext( struct uwx_env *env, struct uwx_self_info *info, ucontext_t *ucontext); -extern int uwx_self_do_context_frame( +__EXTERN_C int uwx_self_do_context_frame( struct uwx_env *env, struct uwx_self_info *info); -extern int uwx_self_copyin( +__EXTERN_C int uwx_self_copyin( int request, char *loc, uint64_t rem, int len, intptr_t tok); -extern int uwx_self_lookupip( +__EXTERN_C int uwx_self_lookupip( int request, uint64_t ip, intptr_t tok, uint64_t **resultp); #define UWX_SELF_ERR_BADABICONTEXT (-101) + +#undef __EXTERN_C + +#if defined(__cplusplus) + +class UnwindExpressSelf : public UnwindExpress { + +public: + + UnwindExpressSelf() { + info = uwx_self_init_info(env); + (void)uwx_register_callbacks(env, (intptr_t)info, + uwx_self_copyin, uwx_self_lookupip); + } + + ~UnwindExpressSelf() { + if (info != 0) + uwx_self_free_info(info); + info = 0; + } + + int init_context() { + return uwx_self_init_context(env); + } + + int init_context(ucontext_t *ucontext) { + return uwx_self_init_from_sigcontext(env, info, ucontext); + } + + int do_context_frame() { + return uwx_self_do_context_frame(env, info); + } + +protected: + + struct uwx_self_info *info; + +}; + +#endif /* __cplusplus */ + +#endif /* __UWX_SELF_INCLUDED */ diff --git a/sys/contrib/ia64/libuwx/src/uwx_self_context.s b/sys/contrib/ia64/libuwx/src/uwx_self_context.s index fb89e76..e373c4a 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self_context.s +++ b/sys/contrib/ia64/libuwx/src/uwx_self_context.s @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2002,2003 Hewlett-Packard Company - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ +// Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. #ifdef _LP64 #define SWIZZLE add @@ -48,6 +48,21 @@ rTMP3 = r30 rTMP4 = r31 rTMP5 = r8 +VALID_IP = 1 +VALID_SP = 1 << 1 +VALID_BSP = 1 << 2 +VALID_CFM = 1 << 3 +VALID_PREDS = 1 << 7 +VALID_RNAT = 1 << 10 +VALID_UNAT = 1 << 11 +VALID_FPSR = 1 << 12 +VALID_LC = 1 << 13 +VALID_GRS = 0xf << 16 +VALID_BRS = 0x1f << 20 +VALID_BASIC4 = VALID_IP | VALID_SP | VALID_BSP | VALID_CFM +VALID_SPEC = VALID_PREDS | VALID_RNAT | VALID_UNAT | VALID_FPSR | VALID_LC +VALID_BITS = (VALID_BASIC4 | VALID_SPEC | VALID_GRS | VALID_BRS) << 32 + .text .proc uwx_self_init_context .global uwx_self_init_context @@ -63,40 +78,42 @@ uwx_self_init_context: mov rRP = b0 ;; mov rRSC = ar.rsc - add rENV1 = 120, rENV0 // rENV1 = &env->context.gr[0] - add rENV2 = 128, rENV0 // rENV2 = &env->context.gr[1] + add rENV1 = 136, rENV0 // rENV1 = &env->context.gr[0] + add rENV2 = 144, rENV0 // rENV2 = &env->context.gr[1] ;; and rRSC0 = -4, rRSC // clear ar.rsc.mode adds rNATP = 0x1f8, r0 mov rTMP1 = b1 ;; - st8.spill [rENV1] = r4, 16 // env+120: r4 - st8.spill [rENV2] = r5, 16 // env+128: r5 + st8.spill [rENV1] = r4, 16 // env+136: r4 + st8.spill [rENV2] = r5, 16 // env+144: r5 mov rTMP2 = b2 ;; - st8.spill [rENV1] = r6, 16 // env+136: r6 - st8.spill [rENV2] = r7, 16 // env+144: r7 + st8.spill [rENV1] = r6, 16 // env+152: r6 + st8.spill [rENV2] = r7, 16 // env+160: r7 mov rTMP3 = b3 ;; - st8 [rENV1] = rTMP1, 16 // env+152: b1 - st8 [rENV2] = rTMP2, 16 // env+160: b2 + st8 [rENV1] = rTMP1, 16 // env+168: b1 + st8 [rENV2] = rTMP2, 16 // env+176: b2 mov rTMP1 = b4 ;; - st8 [rENV1] = rTMP3, 16 // env+168: b3 - st8 [rENV2] = rTMP1, 16 // env+176: b4 + st8 [rENV1] = rTMP3, 16 // env+184: b3 + st8 [rENV2] = rTMP1, 16 // env+192: b4 mov rTMP2 = b5 ;; - st8 [rENV1] = rTMP2 // env+184: b5 + st8 [rENV1] = rTMP2 // env+200: b5 mov ar.rsc = rRSC0 // enforced lazy mode add rENV1 = 8, rENV0 ;; mov rRNAT = ar.rnat // get copy of ar.rnat - movl rTMP1 = 0x7fec8f00000000 // valid_regs: ip, sp, bsp, cfm, - // preds, rnat, unat, lc, grs, brs + movl rTMP1 = VALID_BITS // valid_regs: ip, sp, bsp, cfm, + // preds, rnat, unat, fpsr, + // lc, grs, brs + // = 0x1ff3c8f00000000 ;; mov ar.rsc = rRSC // restore ar.rsc mov rBSP = ar.bsp - add rTMP3 = 120, rENV0 // spill_loc = &env->context.gr[0] + add rTMP3 = 136, rENV0 // spill_loc = &env->context.gr[0] ;; mov rTMP2 = ar.unat nop @@ -143,7 +160,7 @@ uwx_self_init_context: add rENV2 = 320, rENV2 // rENV2 = &env->context.rstate ;; st8 [rENV1] = rTMP1 // env+112: lc - STPTR [rENV2] = r0 // env+512: env->rstate = 0 + STPTR [rENV2] = r0 // env+528: env->rstate = 0 nop ;; mov ar.unat = rUNAT diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.c b/sys/contrib/ia64/libuwx/src/uwx_step.c index 6cacfc2..4e44739 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_step.c +++ b/sys/contrib/ia64/libuwx/src/uwx_step.c @@ -52,6 +52,19 @@ int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat); +/* uwx_lookupip_hook: Hook routine so dynamic instrumentation */ +/* tools can intercept Lookup IP events. When not */ +/* intercepted, it just returns "Not found", so that */ +/* the callback routine is invoked. */ + +/*ARGSUSED*/ +int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp, + size_t uvecsize) +{ + return UWX_LKUP_NOTFOUND; +} + + /* uwx_get_frame_info: Gets unwind info for current frame */ static int uwx_get_frame_info(struct uwx_env *env) @@ -59,10 +72,12 @@ int uwx_get_frame_info(struct uwx_env *env) int i; int status; int cbstatus; + int cbcalled = 0; + uint64_t ip; uint64_t *uvec; uint64_t *rstate; struct uwx_utable_entry uentry; - uint64_t uvecout[4]; + uint64_t uvecout[UVECSIZE]; if (env->copyin == 0 || env->lookupip == 0) return UWX_ERR_NOCALLBACKS; @@ -76,7 +91,14 @@ int uwx_get_frame_info(struct uwx_env *env) /* current IP. If the predicate registers are valid, pass them */ /* in the uvec. */ + /* When self-unwinding, we call a hook routine before the */ + /* callback. If the application is running under control of */ + /* a dynamic instrumentation tool, that tool will have an */ + /* opportunity to intercept lookup IP requests. */ + i = 0; + uvecout[i++] = UWX_KEY_VERSION; + uvecout[i++] = UWX_VERSION; if (env->context.valid_regs & (1 << UWX_REG_PREDS)) { uvecout[i++] = UWX_KEY_PREDS; uvecout[i++] = env->context.special[UWX_REG_PREDS]; @@ -84,8 +106,52 @@ int uwx_get_frame_info(struct uwx_env *env) uvecout[i++] = UWX_KEY_END; uvecout[i++] = 0; uvec = uvecout; - cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, - env->context.special[UWX_REG_IP], env->cb_token, &uvec); + cbstatus = UWX_LKUP_NOTFOUND; + ip = env->context.special[UWX_REG_IP]; + env->remapped_ip = ip; + + /* Call the hook routine. */ + + if (env->remote == 0) + cbstatus = uwx_lookupip_hook(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec, + sizeof(uvecout)); + + /* If the hook routine remapped the IP, use the new IP for */ + /* the callback instead of the original IP. */ + + if (cbstatus == UWX_LKUP_REMAP) { + for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { + switch ((int)uvec[i]) { + case UWX_KEY_NEWIP: + ip = uvec[i+1]; + break; + } + } + env->remapped_ip = ip; + } + + /* Now call the callback routine unless the hook routine gave */ + /* us all the info. */ + + if (cbstatus == UWX_LKUP_NOTFOUND || cbstatus == UWX_LKUP_REMAP) { + cbcalled = 1; + cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); + } + + /* If the callback routine remapped the IP, call it one more time */ + /* with the new IP. */ + + if (cbstatus == UWX_LKUP_REMAP) { + for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { + switch ((int)uvec[i]) { + case UWX_KEY_NEWIP: + ip = uvec[i+1]; + break; + } + } + env->remapped_ip = ip; + cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec); + } /* If NOTFOUND, there's nothing we can do but return an error. */ @@ -101,8 +167,9 @@ int uwx_get_frame_info(struct uwx_env *env) /* block. */ else if (cbstatus == UWX_LKUP_UTABLE) { - status = uwx_search_utable(env, uvec, &uentry); - (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); + status = uwx_search_utable(env, ip, uvec, &uentry); + if (cbcalled) + (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); if (status == UWX_OK) status = uwx_decode_uinfo(env, &uentry, &rstate); else if (status == UWX_ERR_NOUENTRY) @@ -111,6 +178,42 @@ int uwx_get_frame_info(struct uwx_env *env) env->rstate = rstate; } + /* If the callback returns an unwind info block, we can */ + /* proceed directly to decoding the unwind information. */ + + else if (cbstatus == UWX_LKUP_UINFO) { + uentry.code_start = 0; + uentry.code_end = 0; + uentry.unwind_info = 0; + uentry.unwind_flags = 0; + for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { + switch ((int)uvec[i]) { + case UWX_KEY_UFLAGS: + uentry.unwind_flags = uvec[i+1]; + break; + case UWX_KEY_UINFO: + uentry.unwind_info = uvec[i+1]; + break; + case UWX_KEY_MODULE: + env->module_name = + uwx_alloc_str(env, (char *)(uvec[i+1])); + break; + case UWX_KEY_FUNC: + env->function_name = + uwx_alloc_str(env, (char *)(uvec[i+1])); + break; + case UWX_KEY_FUNCSTART: + uentry.code_start = uvec[i+1]; + break; + } + } + if (cbcalled) + (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); + status = uwx_decode_uinfo(env, &uentry, &rstate); + if (status == UWX_OK) + env->rstate = rstate; + } + /* If the callback returns a frame description (in the form */ /* of an update vector), convert the update vector into a */ /* register state array, then invoke the callback again to */ @@ -118,7 +221,8 @@ int uwx_get_frame_info(struct uwx_env *env) else if (cbstatus == UWX_LKUP_FDESC) { status = uwx_decode_uvec(env, uvec, &rstate); - (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); + if (cbcalled) + (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); if (status == UWX_OK) env->rstate = rstate; } @@ -216,7 +320,7 @@ int uwx_get_sym_info( /* Get the symbolic information from the lookup IP callback. */ if (env->function_name == 0) { - ip = env->context.special[UWX_REG_IP]; + ip = env->remapped_ip; i = 0; if (env->function_offset >= 0) { uvecout[i++] = UWX_KEY_FUNCSTART; @@ -225,8 +329,7 @@ int uwx_get_sym_info( uvecout[i++] = UWX_KEY_END; uvecout[i++] = 0; uvec = uvecout; - cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS, - env->context.special[UWX_REG_IP], env->cb_token, &uvec); + cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS, ip, env->cb_token, &uvec); if (cbstatus == UWX_LKUP_SYMINFO) { for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { @@ -456,16 +559,35 @@ int uwx_step(struct uwx_env *env) int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate) { - while (*uvec != 0) { - switch ((int)*uvec++) { + int i; + int status; + + status = uwx_default_rstate(env, rstate); + if (status != UWX_OK) + return status; + + for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { + switch ((int)uvec[i]) { case UWX_KEY_CONTEXT: - env->abi_context = (int)(*uvec++); - return UWX_ABI_FRAME; + env->abi_context = (int)(uvec[i+1]); + status = UWX_ABI_FRAME; + break; + case UWX_KEY_MODULE: + env->module_name = + uwx_alloc_str(env, (char *)(uvec[i+1])); + break; + case UWX_KEY_FUNC: + env->function_name = + uwx_alloc_str(env, (char *)(uvec[i+1])); + break; + case UWX_KEY_FUNCSTART: + env->function_offset = env->remapped_ip - uvec[i+1]; + break; default: return UWX_ERR_CANTUNWIND; } } - return UWX_OK; + return status; } diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.h b/sys/contrib/ia64/libuwx/src/uwx_step.h index 6a54132..4c51e9b 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_step.h +++ b/sys/contrib/ia64/libuwx/src/uwx_step.h @@ -22,4 +22,9 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#define UVECSIZE 20 /* Size of uvec supplied by unwind engine */ + /* for callback's use. */ + +extern int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, + uint64_t **vecp, size_t uvecsize); extern int uwx_restore_markers(struct uwx_env *env); diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.c b/sys/contrib/ia64/libuwx/src/uwx_str.c index 4704a75..e8da35e 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_str.c +++ b/sys/contrib/ia64/libuwx/src/uwx_str.c @@ -26,8 +26,9 @@ OTHER DEALINGS IN THE SOFTWARE. #include "uwx_str.h" #ifdef _KERNEL +static struct uwx_str_pool uwx_str_pool; #define free(p) /* nullified */ -#define malloc(sz) NULL +#define malloc(sz) ((sz == sizeof(uwx_str_pool)) ? &uwx_str_pool : NULL) #endif /* diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.c b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c index 37f2e8a..3b4cd55 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_ttrace.c +++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c @@ -22,13 +22,11 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _KERNEL #include <stdlib.h> #include <dlfcn.h> #include <sys/ttrace.h> #include <sys/uc_access.h> #include <machine/sys/uregs.h> -#endif #include "uwx_env.h" #include "uwx_context.h" @@ -238,7 +236,11 @@ int uwx_ttrace_copyin( else if (request == UWX_COPYIN_RSTACK && len == 8) { if (info->have_ucontext == 0 || rem < info->bspstore) { status = ttrace(TT_PROC_RDDATA, info->pid, 0, rem, 8, (uint64_t)loc); - TRACE_SELF_COPYIN4(rem, len, dp) + TRACE_SELF_COPYIN8(rem, len, dp) + } + else if (info->have_ucontext == 0) { + status = ttrace(TT_LWP_RDRSEBS, info->pid, info->lwpid, rem, 8, (uint64_t)loc); + TRACE_SELF_COPYIN8(rem, len, dp) } else { status = __uc_get_rsebs(&info->ucontext, (uint64_t *)rem, 1, dp); diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.h b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h index d85f505..8d50d85 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_ttrace.h +++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h @@ -22,9 +22,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _KERNEL #include <signal.h> -#endif struct uwx_ttrace_info; diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c index bf9530d..bf50d20 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c +++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c @@ -93,8 +93,7 @@ int uwx_decode_uinfo( /* to the current IP. This helps the client find */ /* the symbolic information. */ - env->function_offset = env->context.special[UWX_REG_IP] - - uentry->code_start; + env->function_offset = env->remapped_ip - uentry->code_start; /* Read the unwind info header using the copyin callback. */ /* (If we're reading a 32-bit unwind table, we need to */ @@ -420,7 +419,7 @@ int uwx_decode_prologue( b1 = uwx_get_byte(bstream); if (b1 < 0) return UWX_ERR_BADUDESC; - r = ((b0 & 0x3) << 1) | (b1 >> 7); + r = ((b0 & 0x7) << 1) | (b1 >> 7); reg = b1 & 0x7f; switch (r) { case 0: /* psp_gr */ diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.c b/sys/contrib/ia64/libuwx/src/uwx_utable.c index 9533aec..bedaab7 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_utable.c +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.c @@ -42,6 +42,7 @@ OTHER DEALINGS IN THE SOFTWARE. int uwx_search_utable32( struct uwx_env *env, + uint32_t ip, uint32_t text_base, uint32_t unwind_start, uint32_t unwind_end, @@ -49,6 +50,7 @@ int uwx_search_utable32( int uwx_search_utable64( struct uwx_env *env, + uint64_t ip, uint64_t text_base, uint64_t unwind_start, uint64_t unwind_end, @@ -59,13 +61,14 @@ int uwx_search_utable64( int uwx_search_utable( struct uwx_env *env, + uint64_t ip, uint64_t *uvec, struct uwx_utable_entry *uentry) { - uint64_t text_base = 0; + uint64_t text_base; uint64_t unwind_flags; - uint64_t unwind_start = 0; - uint64_t unwind_end = 0; + uint64_t unwind_start; + uint64_t unwind_end; int keys; int status; @@ -73,7 +76,10 @@ int uwx_search_utable( /* Make sure all three required values are given. */ keys = 0; + text_base = 0; unwind_flags = 0; + unwind_start = 0; + unwind_end = 0; while (*uvec != 0) { switch ((int)*uvec++) { case UWX_KEY_TBASE: @@ -107,13 +113,14 @@ int uwx_search_utable( if (unwind_flags & UNWIND_TBL_32BIT) status = uwx_search_utable32(env, + (uint32_t) ip, (uint32_t) text_base, (uint32_t) unwind_start, (uint32_t) unwind_end, uentry); else status = uwx_search_utable64(env, - text_base, unwind_start, unwind_end, uentry); + ip, text_base, unwind_start, unwind_end, uentry); return status; } @@ -129,6 +136,7 @@ int uwx_search_utable( int uwx_search_utable32( struct uwx_env *env, + uint32_t ip, uint32_t text_base, uint32_t unwind_start, uint32_t unwind_end, @@ -136,9 +144,8 @@ int uwx_search_utable32( { int lb; int ub; - int mid = 0; + int mid; int len; - uint32_t ip; uint32_t code_start; uint32_t code_end; uint32_t unwind_info; @@ -146,7 +153,7 @@ int uwx_search_utable32( /* Since the unwind table uses segment-relative offsets, convert */ /* the IP in the current context to a segment-relative offset. */ - ip = env->context.special[UWX_REG_IP] - text_base; + ip -= text_base; TRACE_T_SEARCH32(ip) @@ -155,12 +162,13 @@ int uwx_search_utable32( lb = 0; ub = (unwind_end - unwind_start) / (3 * WORDSZ); + mid = 0; while (ub > lb) { mid = (lb + ub) / 2; len = COPYIN_UINFO_4((char *)&code_start, - (intptr_t)(unwind_start+mid*3*WORDSZ)); + (uintptr_t)(unwind_start+mid*3*WORDSZ)); len += COPYIN_UINFO_4((char *)&code_end, - (intptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ)); + (uintptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ)); if (len != 2 * WORDSZ) return UWX_ERR_COPYIN_UTBL; if (env->byte_swap) { @@ -178,7 +186,7 @@ int uwx_search_utable32( if (ub <= lb) return UWX_ERR_NOUENTRY; len = COPYIN_UINFO_4((char *)&unwind_info, - (intptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ)); + (uintptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ)); if (len != WORDSZ) return UWX_ERR_COPYIN_UTBL; if (env->byte_swap) @@ -200,6 +208,7 @@ int uwx_search_utable32( int uwx_search_utable64( struct uwx_env *env, + uint64_t ip, uint64_t text_base, uint64_t unwind_start, uint64_t unwind_end, @@ -207,9 +216,8 @@ int uwx_search_utable64( { int lb; int ub; - int mid = 0; + int mid; int len; - uint64_t ip; uint64_t code_start; uint64_t code_end; uint64_t unwind_info; @@ -217,13 +225,14 @@ int uwx_search_utable64( /* Since the unwind table uses segment-relative offsets, convert */ /* the IP in the current context to a segment-relative offset. */ - ip = env->context.special[UWX_REG_IP] - text_base; + ip -= text_base; /* Standard binary search. */ /* Might modify this to do interpolation in the future. */ lb = 0; ub = (unwind_end - unwind_start) / (3 * DWORDSZ); + mid = 0; while (ub > lb) { mid = (lb + ub) / 2; len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ); diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.h b/sys/contrib/ia64/libuwx/src/uwx_utable.h index 67d2087..cf81b07 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_utable.h +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.h @@ -31,5 +31,6 @@ struct uwx_utable_entry { extern int uwx_search_utable( struct uwx_env *env, + uint64_t ip, uint64_t *uvec, struct uwx_utable_entry *uentry); |