diff options
author | marcel <marcel@FreeBSD.org> | 2006-07-07 22:59:01 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2006-07-07 22:59:01 +0000 |
commit | 5078ab8b1f387b1f4bbdeff30dd434f85dd0001d (patch) | |
tree | 240bc4af6a6d10dfce481da3f6a40f4cdc724a01 /sys/contrib | |
parent | 706381c9edb26debbdb162225f61f5c25001a71c (diff) | |
parent | f76eeb002a9e48d6300ab1156fba58150e695f91 (diff) | |
download | FreeBSD-src-5078ab8b1f387b1f4bbdeff30dd434f85dd0001d.zip FreeBSD-src-5078ab8b1f387b1f4bbdeff30dd434f85dd0001d.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r160157,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys/contrib')
28 files changed, 1908 insertions, 347 deletions
diff --git a/sys/contrib/ia64/libuwx/src/Makefile b/sys/contrib/ia64/libuwx/src/Makefile index fa5b8f5..7cc0f2d 100644 --- a/sys/contrib/ia64/libuwx/src/Makefile +++ b/sys/contrib/ia64/libuwx/src/Makefile @@ -15,11 +15,12 @@ OTHERCFLAGS = CFLAGS = -O $(OTHERCFLAGS) OBJS = uwx_bstream.o uwx_context.o uwx_env.o uwx_scoreboard.o \ - uwx_step.o uwx_str.o uwx_swap.o uwx_trace.o uwx_uinfo.o \ - uwx_utable.o + uwx_step.o uwx_str.o uwx_swap.o uwx_symbols.o \ + uwx_trace.o uwx_uinfo.o uwx_utable.o # SELFOBJS = # For cross-unwind library -SELFOBJS = uwx_self.o uwx_self_context.o uwx_ttrace.o +# SELFOBJS = uwx_self.o uwx_self_context.o uwx_ttrace.o +SELFOBJS = uwx_self.o uwx_self_context.o # SELFLIBS = # For cross-unwind library SELFLIBS = -luca @@ -34,6 +35,9 @@ libuwx.so: $(OBJS) $(SELFOBJS) libuwx.sl: $(OBJS) $(SELFOBJS) ld -b -o libuwx.sl $(OBJS) $(SELFOBJS) $(SELFLIBS) +clean: + rm -f $(OBJS) $(SELFOBJS) libuwx.a libuwx.so libuwx.sl + uwx_bstream.o: uwx.h uwx_env.h uwx_bstream.h uwx_context.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_step.h uwx_trace.h @@ -49,6 +53,8 @@ uwx_str.o: uwx.h uwx_env.h uwx_str.h uwx_swap.o: uwx.h uwx_env.h uwx_swap.h +uwx_symbols.o: uwx.h uwx_env.h uwx_symbols.h + uwx_trace.o: uwx.h uwx_env.h uwx_uinfo.h uwx_scoreboard.h uwx_trace.h uwx_uinfo.o: uwx.h uwx_env.h uwx_uinfo.h uwx_utable.h \ @@ -56,7 +62,8 @@ uwx_uinfo.o: uwx.h uwx_env.h uwx_uinfo.h uwx_utable.h \ uwx_utable.o: uwx.h uwx_env.h uwx_utable.h uwx_swap.h uwx_trace.h -uwx_self.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_self.h +uwx_self.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_self.h \ + uwx_symbols.h uwx_self_context.o: uwx_self_context.s $(CC) -c $(CFLAGS) -o uwx_self_context.o uwx_self_context.s diff --git a/sys/contrib/ia64/libuwx/src/uwx.h b/sys/contrib/ia64/libuwx/src/uwx.h index 9adcfb9..41d4cca 100644 --- a/sys/contrib/ia64/libuwx/src/uwx.h +++ b/sys/contrib/ia64/libuwx/src/uwx.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -25,13 +25,8 @@ OTHER DEALINGS IN THE SOFTWARE. #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" @@ -39,11 +34,14 @@ OTHER DEALINGS IN THE SOFTWARE. #define __EXTERN_C extern #endif -#define UWX_VERSION 1 /* Version id for callback interfaces */ +#define UWX_VERSION 3 /* Version id for callback interfaces */ /* Unwind environment structure (opaque) */ struct uwx_env; +/* Symbol Cache for uwx_find_symbol (opaque) */ +struct uwx_symbol_cache; + /* Allocate and free callbacks */ typedef void *(*alloc_cb)(size_t size); typedef void (*free_cb)(void *ptr); @@ -58,6 +56,9 @@ __EXTERN_C int uwx_free(struct uwx_env *env); /* Put unwind express into cross-process mode */ __EXTERN_C int uwx_set_remote(struct uwx_env *env, int is_big_endian_target); +/* Put unwind express into reduced-context mode (no floating-point regs) */ +__EXTERN_C int uwx_set_nofr(struct uwx_env *env); + /* Copy-in callback */ typedef int (*copyin_cb)( int request, /* request code (see below) */ @@ -107,6 +108,17 @@ __EXTERN_C int uwx_init_history(struct uwx_env *env); /* Step one frame */ __EXTERN_C int uwx_step(struct uwx_env *env); +/* Get module name and text base, if available, for current frame */ +__EXTERN_C int uwx_get_module_info( + struct uwx_env *env, /* unwind environment */ + char **modp, /* load module name (out) */ + uint64_t *text_base); /* base address of text segment (out) */ + +/* Get function start address for current frame */ +__EXTERN_C int uwx_get_funcstart( + struct uwx_env *env, /* unwind environment */ + uint64_t *funcstart); /* function start address (out) */ + /* Get symbol information, if available, for current frame */ __EXTERN_C int uwx_get_sym_info( struct uwx_env *env, /* unwind environment */ @@ -114,6 +126,22 @@ __EXTERN_C int uwx_get_sym_info( char **symp, /* function name (out) */ uint64_t *offsetp); /* offset from start of function (out) */ +/* Get symbol information, given module name and IP */ +__EXTERN_C int uwx_find_symbol( + struct uwx_env *env, /* unwind environment */ + struct uwx_symbol_cache **cachep, + /* ptr to symbol cache ptr (in/out) */ + char *mod, /* load module name */ + uint64_t relip, /* IP, relative to text segment */ + char **symp, /* function name (out) */ + uint64_t *offsetp); /* offset from start of function (out) */ + +/* Release memory used by symbol cache */ +__EXTERN_C void uwx_release_symbol_cache( + struct uwx_env *env, /* unwind environment */ + struct uwx_symbol_cache *symbol_cache); + /* symbol cache ptr */ + /* Get the value of a register from the current context */ __EXTERN_C int uwx_get_reg( struct uwx_env *env, /* unwind environment */ @@ -135,6 +163,10 @@ __EXTERN_C int uwx_get_spill_loc( /* Get the ABI context code (if uwx_step returned UWX_ABI_FRAME) */ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); +/* Increment/Decrement the bsp by a number of slots */ +/* (accounts for NaT collections) */ +__EXTERN_C uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots); + /* Return status codes for uwx_ APIs */ #define UWX_OK 0 #define UWX_BOTTOM 1 /* Hit bottom of stack */ @@ -158,6 +190,8 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_ERR_CANTUNWIND (-17) /* Can't unwind */ #define UWX_ERR_NOCALLBACKS (-18) /* No callbacks registered */ #define UWX_ERR_NOCONTEXT (-19) /* Context not initialized */ +#define UWX_ERR_UCACCESS (-20) /* Failure in libuca */ +#define UWX_ERR_NOSYM (-21) /* Symbol not found */ /* Request codes for copyin callback */ #define UWX_COPYIN_UINFO 1 /* Reading unwind info */ @@ -169,6 +203,7 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_LKUP_LOOKUP 1 /* Lookup IP */ #define UWX_LKUP_FREE 2 /* Free result vector */ #define UWX_LKUP_SYMBOLS 3 /* Lookup symbolic information */ +#define UWX_LKUP_MODULE 4 /* Get module name */ /* Return status codes for lookup IP callback */ #define UWX_LKUP_NOTFOUND 0 /* IP not found */ @@ -199,11 +234,13 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); #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 */ +#define UWX_KEY_GP 7 /* GP value for module */ /* 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. */ +/* Use UWX_KEY_GP for the module's gp value. */ #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 */ @@ -212,6 +249,7 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_KEY_NEWIP 5 /* Remapped IP */ /* Keys returned with UWX_LKUP_UINFO */ +/* Use UWX_KEY_GP for the module's gp value. */ /* 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 */ @@ -219,6 +257,7 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); /* 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. */ +/* Use UWX_KEY_TBASE for the base of the text segment */ #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 */ @@ -246,6 +285,7 @@ __EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env); #define UWX_REG_AR_FPSR 12 /* ar.fpsr */ #define UWX_REG_AR_LC 13 /* ar.lc */ #define UWX_REG_AR_PFS 14 /* ar.pfs */ +#define UWX_REG_GP 15 /* gp (pseudo-register) */ #define UWX_REG_GR(gr) (0x100 | (gr)) #define UWX_REG_FR(fr) (0x200 | (fr)) #define UWX_REG_BR(br) (0x300 | (br)) @@ -321,10 +361,27 @@ public: return uwx_step(env); } + int get_module_info(char **modp, uint64_t *text_base_p) { + return uwx_get_module_info(env, modp, text_base_p); + } + + int get_funcstart(uint64_t *funcstart) { + return uwx_get_funcstart(env, funcstart); + } + int get_sym_info(char **modp, char **symp, uint64_t *offsetp) { return uwx_get_sym_info(env, modp, symp, offsetp); } + int find_symbol(struct uwx_symbol_cache **cachep, + char *mod, uint64_t relip, char **symp, uint64_t *offsetp) { + return uwx_find_symbol(env, cachep, mod, relip, symp, offsetp); + } + + void release_symbol_cache(struct uwx_symbol_cache *symbol_cache) { + uwx_release_symbol_cache(env, symbol_cache); + } + int get_reg(int regid, uint64_t *valp) { return uwx_get_reg(env, regid, valp); } diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.c b/sys/contrib/ia64/libuwx/src/uwx_bstream.c index 4bc8e42..3a9e6d9 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_bstream.c +++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -46,7 +46,7 @@ void uwx_init_bstream( } else { bstream->source = 0; - bstream->bufp = (unsigned char *) source; + bstream->bufp = (unsigned char *) (intptr_t) source; bstream->nbuf = len; bstream->copyin = 0; bstream->cb_token = 0; @@ -64,6 +64,8 @@ int uwx_get_byte(struct uwx_bstream *bstream) int len; int n; int b; + uint32_t *wp; + uint64_t *dp; if (bstream->peekc >= 0) { b = bstream->peekc; @@ -129,7 +131,6 @@ int uwx_get_uleb128(struct uwx_bstream *bstream, uint64_t *valp) return 0; } -#if 0 int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp) { uint64_t val; @@ -178,4 +179,3 @@ int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp) *valp = val; return 0; } -#endif diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.h b/sys/contrib/ia64/libuwx/src/uwx_bstream.h index 066d946..c2fe5da 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_bstream.h +++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.c b/sys/contrib/ia64/libuwx/src/uwx_context.c index 68e65e7..a7acd72 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_context.c +++ b/sys/contrib/ia64/libuwx/src/uwx_context.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -182,7 +182,7 @@ int uwx_get_nat(struct uwx_env *env, int regid, int *natp) bsp = uwx_add_to_bsp(bsp, regid); natcollp = bsp | 0x01f8; n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, - bsp, DWORDSZ, env->cb_token); + natcollp, DWORDSZ, env->cb_token); if (n != DWORDSZ) return UWX_ERR_COPYIN_RSTK; *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; @@ -200,6 +200,7 @@ int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) int sor; int rrb_gr; uint64_t bsp; + int n; if (env == 0) return UWX_ERR_NOENV; @@ -208,8 +209,17 @@ int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) if (regid == UWX_REG_GR(12)) regid = UWX_REG_SP; - if (regid < NSPECIALREG) + if (regid < NSPECIALREG) { + if (regid == UWX_REG_PSP || regid == UWX_REG_RP || + regid == UWX_REG_PFS) { + if (!(env->context.valid_regs & (1 << regid))) { + status = uwx_restore_markers(env); + if (status != UWX_OK) + return status; + } + } *dispp = env->history.special[regid]; + } else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) *dispp = env->history.gr[regid - UWX_REG_GR(4)]; else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { @@ -273,6 +283,7 @@ int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 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); @@ -313,7 +324,7 @@ uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) * ^ * | * bsp - * <------- adjusted (nslots + bias) -------> + * <------------ nslots + bias -----------> * When subtracting from bsp, we avoid depending on the sign of * the quotient by adding 63*8 before division and subtracting 8 @@ -325,12 +336,12 @@ uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) * | X X| * +---------------------------------------------------------------+ * <-- bias --> - * <--- |nslots| ---> + * <--- (-nslots) ---> * ^ * | * bsp * <-----------------> - * adjusted |nslots + bias| + * -(nslots + bias) */ bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; @@ -338,7 +349,6 @@ uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) return bsp + nslots * DWORDSZ; } -#if 0 int uwx_selftest_bsp_arithmetic() { int i; @@ -366,7 +376,7 @@ int uwx_selftest_bsp_arithmetic() if (r >= 1000) r -= 1000; for (j = 0; j < 96; j++) { - p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, j); + p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j); if (*p != (r + j)) { failed++; printf("%d [%08lx] + %d -> %08lx ", @@ -385,7 +395,7 @@ int uwx_selftest_bsp_arithmetic() if (r >= 1000) r -= 1000; for (j = 0; j < 96; j++) { - p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, -j); + p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j); if (*p != (r - j)) { failed++; printf("%d [%08lx] - %d -> %08lx ", @@ -397,4 +407,3 @@ int uwx_selftest_bsp_arithmetic() return failed; } -#endif diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.h b/sys/contrib/ia64/libuwx/src/uwx_context.h index 2bdedc9..1f172db 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_context.h +++ b/sys/contrib/ia64/libuwx/src/uwx_context.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.c b/sys/contrib/ia64/libuwx/src/uwx_env.c index 4149a27..9e24d9b 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_env.c +++ b/sys/contrib/ia64/libuwx/src/uwx_env.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -22,21 +22,13 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 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; @@ -68,52 +60,97 @@ int uwx_init_history(struct uwx_env *env) return UWX_OK; } -struct uwx_env *uwx_init() +int uwx_init_env(struct uwx_env *env, size_t total_size) { int i; + struct uwx_str_pool *str_pool; + struct uwx_scoreboard *scoreboards; + + str_pool = (struct uwx_str_pool *)(env + 1); + scoreboards = (struct uwx_scoreboard *)(str_pool + 1); + + if (sizeof(struct uwx_env) + sizeof(struct uwx_str_pool) > total_size) + return UWX_ERR_NOMEM; + total_size -= sizeof(struct uwx_env) + sizeof(struct uwx_str_pool); + + env->context.valid_regs = 0; + env->context.valid_frs = 0; + for (i = 0; i < NSPECIALREG; i++) + env->context.special[i] = 0; + for (i = 0; i < NPRESERVEDGR; i++) + env->context.gr[i] = 0; + for (i = 0; i < NPRESERVEDBR; i++) + env->context.br[i] = 0; + for (i = 0; i < NPRESERVEDFR; i++) { + env->context.fr[i].part0 = 0; + env->context.fr[i].part1 = 0; + } + env->rstate = 0; + env->remapped_ip = 0; + env->function_offset = 0; + env->ptr_size = DWORDSZ; + env->uinfo_hdr = 0; + env->uinfo_end = 0; + env->code_start = 0; + env->text_base = 0; + (void)uwx_init_history(env); + if (uwx_allocate_cb != NULL) + env->allocate_cb = uwx_allocate_cb; + else + env->allocate_cb = malloc; + if (uwx_free_cb != NULL) + env->free_cb = uwx_free_cb; + else + env->free_cb = free; + env->free_scoreboards = 0; + env->used_scoreboards = 0; + env->labeled_scoreboards = 0; + (void)uwx_init_str_pool(env, str_pool); + env->module_name = 0; + env->function_name = 0; + env->cb_token = 0; + env->copyin = 0; + env->lookupip = 0; + env->remote = 0; + env->byte_swap = 0; + env->abi_context = 0; + env->nsbreg = NSBREG; + env->nscoreboards = 0; + env->on_heap = 0; + env->trace = 0; + TRACE_INIT + for (i = 0; total_size >= sizeof(struct uwx_scoreboard); i++) { + (void) uwx_prealloc_scoreboard(env, &scoreboards[i]); + total_size -= sizeof(struct uwx_scoreboard); + } + return UWX_OK; +} + +int uwx_set_nofr(struct uwx_env *env) +{ + if (env == 0) + return UWX_ERR_NOENV; + + env->nsbreg = NSBREG_NOFR; + return UWX_OK; +} + +struct uwx_env *uwx_init() +{ struct uwx_env *env; + size_t total_size; + + total_size = sizeof(struct uwx_env) + + sizeof(struct uwx_str_pool) + + NSCOREBOARDS * sizeof(struct uwx_scoreboard); if (uwx_allocate_cb == 0) - env = (struct uwx_env *) malloc(sizeof(struct uwx_env)); + env = (struct uwx_env *) malloc(total_size); else - env = (struct uwx_env *) (*uwx_allocate_cb)(sizeof(struct uwx_env)); + env = (struct uwx_env *) (*uwx_allocate_cb)(total_size); if (env != 0) { - env->context.valid_regs = 0; - env->context.valid_frs = 0; - for (i = 0; i < NSPECIALREG; i++) - env->context.special[i] = 0; - for (i = 0; i < NPRESERVEDGR; i++) - env->context.gr[i] = 0; - for (i = 0; i < NPRESERVEDBR; i++) - env->context.br[i] = 0; - for (i = 0; i < NPRESERVEDFR; i++) { - env->context.fr[i].part0 = 0; - 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; - env->free_cb = uwx_free_cb; - env->free_scoreboards = 0; - env->used_scoreboards = 0; - env->labeled_scoreboards = 0; - (void)uwx_init_str_pool(env); - env->module_name = 0; - env->function_name = 0; - env->cb_token = 0; - env->copyin = 0; - env->lookupip = 0; - env->remote = 0; - env->byte_swap = 0; - env->abi_context = 0; - env->nsbreg = NSBREG_NOFR; - env->nscoreboards = 0; - env->trace = 0; - TRACE_INIT - for (i = 0; i < NSCOREBOARDS; i++) - (void) uwx_alloc_scoreboard(env); + uwx_init_env(env, total_size); + env->on_heap = 1; } return env; } @@ -165,10 +202,12 @@ int uwx_free(struct uwx_env *env) if (env != 0) { uwx_free_scoreboards(env); uwx_free_str_pool(env); - if (env->free_cb == 0) - free((void *)env); - else - (*env->free_cb)((void *)env); + if (env->on_heap) { + if (env->free_cb == 0) + free((void *)env); + else + (*env->free_cb)((void *)env); + } } return UWX_OK; } diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.h b/sys/contrib/ia64/libuwx/src/uwx_env.h index 2451239..71b9d66 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_env.h +++ b/sys/contrib/ia64/libuwx/src/uwx_env.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -80,6 +80,11 @@ struct uwx_env { uint64_t *rstate; uint64_t remapped_ip; int64_t function_offset; + uint64_t ptr_size; + uint64_t uinfo_hdr; + uint64_t uinfo_end; + uint64_t code_start; + uint64_t text_base; struct uwx_history history; alloc_cb allocate_cb; free_cb free_cb; @@ -97,8 +102,10 @@ struct uwx_env { int abi_context; int nsbreg; int nscoreboards; + int on_heap; int trace; }; extern alloc_cb uwx_allocate_cb; extern free_cb uwx_free_cb; +extern int uwx_init_env(struct uwx_env *env, size_t total_size); diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c index ee58880..df8abad 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c +++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -22,42 +22,22 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 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) +void uwx_prealloc_scoreboard(struct uwx_env *env, struct uwx_scoreboard *sb) { - int idx = p - uwx_scoreboard; - uwx_allocated &= ~(1 << idx); + sb->id = env->nscoreboards++; + sb->nextused = env->used_scoreboards; + sb->prealloc = 1; + env->used_scoreboards = sb; + TRACE_B_PREALLOC(sb->id) } -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) { struct uwx_scoreboard *sb; @@ -79,6 +59,7 @@ struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env) return 0; sb->id = env->nscoreboards++; sb->nextused = env->used_scoreboards; + sb->prealloc = 0; env->used_scoreboards = sb; TRACE_B_ALLOC(sb->id) } @@ -95,7 +76,6 @@ struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env) return sb; } -static void uwx_reclaim_scoreboards(struct uwx_env *env) { struct uwx_scoreboard *sb; @@ -170,7 +150,6 @@ int uwx_label_scoreboard( /* in the "nextstack" field. */ back = 0; - new = 0; while (sb != 0) { TRACE_B_LABEL_COPY(sb->id) new = uwx_alloc_scoreboard(env); @@ -254,7 +233,6 @@ int uwx_copy_scoreboard( /* 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); @@ -291,10 +269,12 @@ void uwx_free_scoreboards(struct uwx_env *env) for (sb = env->used_scoreboards; sb != 0; sb = next) { TRACE_B_FREE(sb->id) next = sb->nextused; - if (env->free_cb == 0) - free((void *)sb); - else - (*env->free_cb)((void *)sb); + if (!sb->prealloc) { + if (env->free_cb == 0) + free((void *)sb); + else + (*env->free_cb)((void *)sb); + } } env->free_scoreboards = 0; env->used_scoreboards = 0; diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h index 0122d38..752b8fb 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h +++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -51,8 +51,13 @@ struct uwx_scoreboard { uint64_t rstate[NSBREG]; int label; int id; + int prealloc; }; +extern void uwx_prealloc_scoreboard( + struct uwx_env *env, + struct uwx_scoreboard *sb); + extern struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env); extern struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env); diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.c b/sys/contrib/ia64/libuwx/src/uwx_self.c index af2e36f..5f47205 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self.c +++ b/sys/contrib/ia64/libuwx/src/uwx_self.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -23,6 +23,7 @@ OTHER DEALINGS IN THE SOFTWARE. */ #include <stdlib.h> +#include <string.h> #include <crt0.h> #include <dlfcn.h> #include <sys/uc_access.h> @@ -31,52 +32,49 @@ OTHER DEALINGS IN THE SOFTWARE. #include "uwx_context.h" #include "uwx_trace.h" #include "uwx_self.h" +#include "uwx_self_info.h" #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]; - uint64_t sendsig_start; - uint64_t sendsig_end; - alloc_cb allocate_cb; - free_cb free_cb; - int trace; -}; +void uwx_free_load_module_cache(struct uwx_self_info *info); -struct uwx_self_info *uwx_self_init_info(struct uwx_env *env) +int uwx_self_init_info_block(struct uwx_env *env, struct uwx_self_info *info) { - struct uwx_self_info *info; - - if (env->allocate_cb == 0) - info = (struct uwx_self_info *) - malloc(sizeof(struct uwx_self_info)); - else - info = (struct uwx_self_info *) - (*env->allocate_cb)(sizeof(struct uwx_self_info)); - if (info == 0) - return 0; - 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->on_heap = 0; info->trace = env->trace; + info->load_module_cache = NULL; + + return UWX_OK; +} + +struct uwx_self_info *uwx_self_init_info(struct uwx_env *env) +{ + struct uwx_self_info *info; + + info = (struct uwx_self_info *) + (*env->allocate_cb)(sizeof(struct uwx_self_info)); + if (info == 0) + return 0; + + uwx_self_init_info_block(env, info); + info->on_heap = 1; 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); + int i; + + if (info->load_module_cache != NULL) + uwx_free_load_module_cache(info); + if (info->on_heap) + (*info->env->free_cb)((void *)info); return UWX_OK; } @@ -97,17 +95,37 @@ int uwx_self_init_from_sigcontext( info->ucontext = ucontext; status = __uc_get_reason(ucontext, &reason); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_ip(ucontext, &ip); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_grs(ucontext, 12, 1, &sp, &nat); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_cfm(ucontext, &cfm); + if (status != 0) + return UWX_ERR_UCACCESS; #ifdef NEW_UC_GET_AR status = __uc_get_ar_bsp(ucontext, &bsp); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_ar_bspstore(ucontext, &info->bspstore); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_ar_ec(ucontext, &ec); + if (status != 0) + return UWX_ERR_UCACCESS; #else status = __uc_get_ar(ucontext, 17, &bsp); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_ar(ucontext, 18, &info->bspstore); + if (status != 0) + return UWX_ERR_UCACCESS; status = __uc_get_ar(ucontext, 66, &ec); + if (status != 0) + return UWX_ERR_UCACCESS; #endif /* The returned bsp needs to be adjusted. */ /* For interrupt frames, where bsp was advanced by a cover */ @@ -136,9 +154,10 @@ int uwx_self_do_context_frame( 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) + if (status != UWX_OK) return status; - return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext); + return uwx_self_init_from_sigcontext(env, info, + (ucontext_t *)(intptr_t)ucontext); } int uwx_self_copyin( @@ -164,12 +183,12 @@ int uwx_self_copyin( case UWX_COPYIN_MSTACK: if (len == 4) { wp = (unsigned long *) loc; - *wp = *(unsigned long *)rem; + *wp = *(unsigned long *)(intptr_t)rem; TRACE_SELF_COPYIN4(rem, len, wp) status = 0; } else if (len == 8) { - *dp = *(uint64_t *)rem; + *dp = *(uint64_t *)(intptr_t)rem; TRACE_SELF_COPYIN8(rem, len, dp) status = 0; } @@ -181,13 +200,13 @@ int uwx_self_copyin( status = 0; } else if (info->ucontext == 0 || rem < info->bspstore) { - *dp = *(uint64_t *)rem; + *dp = *(uint64_t *)(intptr_t)rem; TRACE_SELF_COPYIN8(rem, len, dp) status = 0; } else { status = __uc_get_rsebs(info->ucontext, - (uint64_t *)rem, 1, dp); + (uint64_t *)(intptr_t)rem, 1, dp); } } break; @@ -230,6 +249,88 @@ int uwx_self_copyin( return len; } +#define MODULE_CACHE_SIZE 4 + +struct load_module_cache { + int clock; + char *names[MODULE_CACHE_SIZE]; + struct load_module_desc descs[MODULE_CACHE_SIZE]; + struct uwx_symbol_cache *symbol_cache; +}; + +void uwx_free_load_module_cache(struct uwx_self_info *info) +{ + int i; + + for (i = 0; i < MODULE_CACHE_SIZE; i++) { + if (info->load_module_cache->names[i] != NULL) + (*info->env->free_cb)((void *)info->load_module_cache->names[i]); + } + + if (info->load_module_cache->symbol_cache != NULL) + uwx_release_symbol_cache(info->env, + info->load_module_cache->symbol_cache); + + (*info->env->free_cb)((void *)info->load_module_cache); +} + +struct load_module_desc *uwx_get_modinfo( + struct uwx_self_info *info, + uint64_t ip, + char **module_name_p) +{ + int i; + UINT64 handle; + struct load_module_cache *cache; + struct load_module_desc *desc; + char *module_name; + + cache = info->load_module_cache; + if (cache == NULL) { + cache = (struct load_module_cache *) + (*info->env->allocate_cb)(sizeof(struct load_module_cache)); + if (cache == NULL) + return NULL; + for (i = 0; i < MODULE_CACHE_SIZE; i++) { + desc = &cache->descs[i]; + desc->text_base = 0; + desc->text_size = 0; + cache->names[i] = NULL; + } + cache->clock = 0; + cache->symbol_cache = NULL; + info->load_module_cache = cache; + } + for (i = 0; i < MODULE_CACHE_SIZE; i++) { + desc = &cache->descs[i]; + if (ip >= desc->text_base && ip < desc->text_base + desc->text_size) + break; + } + if (i >= MODULE_CACHE_SIZE) { + i = cache->clock; + cache->clock = (cache->clock + 1) % MODULE_CACHE_SIZE; + desc = &cache->descs[i]; + handle = dlmodinfo(ip, desc, sizeof(*desc), 0, 0, 0); + if (handle == 0) + return NULL; + if (cache->names[i] != NULL) + (*info->env->free_cb)(cache->names[i]); + cache->names[i] = NULL; + } + if (module_name_p != NULL) { + if (cache->names[i] == NULL) { + module_name = dlgetname(desc, sizeof(*desc), 0, 0, 0); + if (module_name != NULL) { + cache->names[i] = (char *) + (*info->env->allocate_cb)(strlen(module_name)+1); + if (cache->names[i] != NULL) + strcpy(cache->names[i], module_name); + } + } + *module_name_p = cache->names[i]; + } + return desc; +} int uwx_self_lookupip( int request, @@ -239,10 +340,14 @@ int uwx_self_lookupip( { struct uwx_self_info *info = (struct uwx_self_info *) tok; UINT64 handle; - struct load_module_desc desc; + struct load_module_desc *desc; uint64_t *unwind_base; uint64_t *rvec; + char *module_name; + char *func_name; + uint64_t offset; int i; + int status; if (request == UWX_LKUP_LOOKUP) { TRACE_SELF_LOOKUP(ip) @@ -251,28 +356,31 @@ int uwx_self_lookupip( rvec = info->rvec; rvec[i++] = UWX_KEY_CONTEXT; rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT; - rvec[i++] = 0; + rvec[i++] = UWX_KEY_END; rvec[i++] = 0; *resultp = rvec; return UWX_LKUP_FDESC; } else { - handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0); - if (handle == 0) + desc = uwx_get_modinfo(info, ip, NULL); + if (desc == NULL) return UWX_LKUP_ERR; - unwind_base = (uint64_t *) desc.unwind_base; - TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base) + unwind_base = (uint64_t *) (intptr_t) desc->unwind_base; + TRACE_SELF_LOOKUP_DESC(desc->text_base, + desc->linkage_ptr, unwind_base) i = 0; rvec = info->rvec; rvec[i++] = UWX_KEY_TBASE; - rvec[i++] = desc.text_base; + rvec[i++] = desc->text_base; rvec[i++] = UWX_KEY_UFLAGS; rvec[i++] = unwind_base[0]; rvec[i++] = UWX_KEY_USTART; - rvec[i++] = desc.text_base + unwind_base[1]; + rvec[i++] = desc->text_base + unwind_base[1]; rvec[i++] = UWX_KEY_UEND; - rvec[i++] = desc.text_base + unwind_base[2]; - rvec[i++] = 0; + rvec[i++] = desc->text_base + unwind_base[2]; + rvec[i++] = UWX_KEY_GP; + rvec[i++] = desc->linkage_ptr; + rvec[i++] = UWX_KEY_END; rvec[i++] = 0; *resultp = rvec; return UWX_LKUP_UTABLE; @@ -281,4 +389,54 @@ int uwx_self_lookupip( else if (request == UWX_LKUP_FREE) { return 0; } + else if (request == UWX_LKUP_MODULE) { + desc = uwx_get_modinfo(info, ip, &module_name); + if (desc == NULL) + return UWX_LKUP_ERR; + if (module_name == NULL) + return UWX_LKUP_ERR; + i = 0; + rvec = info->rvec; + rvec[i++] = UWX_KEY_MODULE; + rvec[i++] = (uint64_t)(intptr_t)module_name; + rvec[i++] = UWX_KEY_TBASE; + rvec[i++] = desc->text_base; + rvec[i++] = UWX_KEY_END; + rvec[i++] = 0; + *resultp = rvec; + return UWX_LKUP_SYMINFO; + } + else if (request == UWX_LKUP_SYMBOLS) { + rvec = *resultp; + for (i = 0; rvec[i] != UWX_KEY_END; i += 2) { + if (rvec[i] == UWX_KEY_FUNCSTART) + ip = rvec[i+1]; + } + desc = uwx_get_modinfo(info, ip, &module_name); + if (desc == NULL) + return UWX_LKUP_ERR; + if (module_name == NULL) + return UWX_LKUP_ERR; + status = uwx_find_symbol(info->env, + &info->load_module_cache->symbol_cache, + module_name, ip - desc->text_base, + &func_name, &offset); + i = 0; + rvec = info->rvec; + rvec[i++] = UWX_KEY_MODULE; + rvec[i++] = (uint64_t)(intptr_t)module_name; + rvec[i++] = UWX_KEY_TBASE; + rvec[i++] = desc->text_base; + if (status == UWX_OK) { + rvec[i++] = UWX_KEY_FUNC; + rvec[i++] = (uint64_t)(intptr_t)func_name; + rvec[i++] = UWX_KEY_FUNCSTART; + rvec[i++] = ip - offset; + } + rvec[i++] = UWX_KEY_END; + rvec[i++] = 0; + *resultp = rvec; + return UWX_LKUP_SYMINFO; + } + return UWX_LKUP_ERR; } diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.h b/sys/contrib/ia64/libuwx/src/uwx_self.h index 0590ade..ada3184 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self.h +++ b/sys/contrib/ia64/libuwx/src/uwx_self.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_self_context.s b/sys/contrib/ia64/libuwx/src/uwx_self_context.s index e373c4a..e2986eb 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_self_context.s +++ b/sys/contrib/ia64/libuwx/src/uwx_self_context.s @@ -1,4 +1,4 @@ -// Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +// Copyright (c) 2003-2006 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 @@ -47,23 +47,40 @@ rTMP2 = r29 rTMP3 = r30 rTMP4 = r31 rTMP5 = r8 +rMYPFS = r9 +rPSP = r10 -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 +VALID_IP = 1 +VALID_SP = 1 << 1 +VALID_BSP = 1 << 2 +VALID_CFM = 1 << 3 +VALID_PREDS = 1 << 7 +VALID_PRIUNAT = 1 << 8 +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_PRIUNAT | VALID_RNAT | VALID_UNAT | VALID_FPSR | VALID_LC +VALID_REGS = VALID_BASIC4 | VALID_SPEC | VALID_GRS | VALID_BRS +VALID_FRS = 0xfffff +// valid_regs and valid_frs are separate unsigned int fields. +// In order to store them with a single st8, we need to know +// the endianness. +#ifdef __LITTLE_ENDIAN__ +VALID_BITS = (VALID_FRS << 32) | VALID_REGS +#else +VALID_BITS = (VALID_REGS << 32) | VALID_FRS +#endif .text + +// int uwx_self_init_context(struct uwx_env *env); +// +// Stores a snapshot of the caller's context in the uwx_env structure. + .proc uwx_self_init_context .global uwx_self_init_context uwx_self_init_context: @@ -107,9 +124,9 @@ uwx_self_init_context: ;; mov rRNAT = ar.rnat // get copy of ar.rnat movl rTMP1 = VALID_BITS // valid_regs: ip, sp, bsp, cfm, - // preds, rnat, unat, fpsr, + // preds, priunat, rnat, unat, fpsr, // lc, grs, brs - // = 0x1ff3c8f00000000 + // = 0x1ff3d8f00000000 ;; mov ar.rsc = rRSC // restore ar.rsc mov rBSP = ar.bsp @@ -119,25 +136,24 @@ uwx_self_init_context: nop extr.u rTMP3 = rTMP3, 3, 6 // bitpos = spill_loc{8:3} ;; - or rNATP = rBSP, rNATP // natp = bsp | 0x1f8 + and rBIAS = rBSP, rNATP // bias = (bsp & 0x1f8) ... sub rTMP4 = 64, rTMP3 // (64 - bitpos) shr rTMP5 = rTMP2, rTMP3 // (unat >> bitpos) ;; - sub rBIAS = rNATP, rBSP // bias = (natp - bsp) ... nop + extr.u rBIAS = rBIAS, 3, 6 // ... div 8 shl rTMP2 = rTMP2, rTMP4 // (unat << (64 - bitpos)) ;; or rTMP2 = rTMP2, rTMP5 // rotate_right(unat, bitpos) - extr.u rBIAS = rBIAS, 3, 6 // ... div 8 + nop mov rTMP4 = pr ;; st8 [rENV0] = rTMP1, 16 // env+0: valid_regs mask st8 [rENV1] = rRP, 24 // env+8: ip (my rp) - add rBIAS = rNSLOT, rBIAS // bias += nslots + sub rBIAS = rNSLOT, rBIAS // bias = nslots - bias ;; - cmp.lt p6, p0 = 63, rBIAS // if (63 < bias) ... - cmp.lt p7, p0 = 126, rBIAS // if (126 < bias) ... - nop + cmp.lt p6, p0 = 0, rBIAS // if (0 < bias) ... + cmp.lt p7, p0 = 63, rBIAS // if (63 < bias) ... ;; st8 [rENV0] = r12, 48 // env+16: sp st8 [rENV1] = rPFS, 40 // env+32: cfm (my pfs) @@ -147,24 +163,221 @@ uwx_self_init_context: st8 [rENV1] = rTMP2, 24 // env+72: priunat (p7) add rNSLOT = 1, rNSLOT // ... nslots++ ;; - st8 [rENV0] = rRNAT, -64 // env+88: rnat - st8 [rENV1] = rUNAT, 8 // env+96: unat + st8 [rENV0] = rRNAT, -64 // env+88: ar.rnat + st8 [rENV1] = rUNAT, 8 // env+96: ar.unat dep.z rTMP3 = rNSLOT, 3, 7 // (nslots << 3) ;; sub rPBSP = rBSP, rTMP3 // prev_bsp = bsp - (nslots << 3) mov rTMP3 = ar.fpsr mov rTMP1 = ar.lc ;; - st8 [rENV0] = rPBSP // env+24: bsp (my prev bsp) - st8 [rENV1] = rTMP3, 8 // env+104: fpsr + st8 [rENV0] = rPBSP, 184 // env+24: bsp (my prev bsp) + st8 [rENV1] = rTMP3, 8 // env+104: ar.fpsr add rENV2 = 320, rENV2 // rENV2 = &env->context.rstate ;; - st8 [rENV1] = rTMP1 // env+112: lc + st8 [rENV1] = rTMP1, 112 // env+112: ar.lc STPTR [rENV2] = r0 // env+528: env->rstate = 0 nop ;; + // THIS CODE NEEDS TO BE SCHEDULED!!! + stf.spill [rENV0] = f2, 32 // env+208: f2 + stf.spill [rENV1] = f3, 32 // env+224: f3 + ;; + stf.spill [rENV0] = f4, 32 // env+240: f4 + stf.spill [rENV1] = f5, 32 // env+256: f5 + ;; + stf.spill [rENV0] = f16, 32 // env+272: f16 + stf.spill [rENV1] = f17, 32 // env+288: f17 + ;; + stf.spill [rENV0] = f18, 32 // env+304: f16 + stf.spill [rENV1] = f19, 32 // env+320: f17 + ;; + stf.spill [rENV0] = f20, 32 // env+336: f16 + stf.spill [rENV1] = f21, 32 // env+352: f17 + ;; + stf.spill [rENV0] = f22, 32 // env+368: f16 + stf.spill [rENV1] = f23, 32 // env+384: f17 + ;; + stf.spill [rENV0] = f24, 32 // env+400: f16 + stf.spill [rENV1] = f25, 32 // env+416: f17 + ;; + stf.spill [rENV0] = f26, 32 // env+432: f16 + stf.spill [rENV1] = f27, 32 // env+448: f17 + ;; + stf.spill [rENV0] = f28, 32 // env+464: f16 + stf.spill [rENV1] = f29, 32 // env+480: f17 + ;; + stf.spill [rENV0] = f30, 32 // env+496: f16 + stf.spill [rENV1] = f31, 32 // env+512: f17 + ;; mov ar.unat = rUNAT mov ret0 = r0 // return UWX_OK - br.ret.sptk b0 + br.ret.sptk b0 .endp +// uwx_self_install_context( +// struct uwx_env *env, +// uint64_t r15, +// uint64_t r16, +// uint64_t r17, +// uint64_t r18, +// uint64_t ret +// ); +// +// Installs the given context, and sets the landing pad binding +// registers r15-r18 to the values given. +// Returns the value "ret" to the new context (for testing -- +// when transferring to a landing pad, the new context won't +// care about the return value). + + .proc uwx_self_install_context + .global uwx_self_install_context +uwx_self_install_context: + .prologue + alloc rMYPFS = ar.pfs, 6, 0, 0, 0 + .body + SWIZZLE rENV0 = r0, r32 // rENV0 = &env + ;; + + // THIS CODE NEEDS TO BE SCHEDULED!!! + + // Restore GR 4-7 and ar.unat + add rENV1 = 136, rENV0 // &env->context.gr[0] + add rENV2 = 72, rENV0 // &env->context.priunat + ;; + ld8 rTMP2 = [rENV2], 24 // env+72: priunat + extr.u rTMP3 = rENV1, 3, 6 // bitpos = spill_loc{8:3} + ;; + ld8 rUNAT = [rENV2], 48 // env+96: ar.unat + sub rTMP4 = 64, rTMP3 // (64 - bitpos) + shl rTMP5 = rTMP2, rTMP3 // (unat << bitpos) + ;; + shr rTMP2 = rTMP2, rTMP4 // (unat >> (64 - bitpos)) + ;; + or rTMP2 = rTMP2, rTMP5 // rotate_left(unat, bitpos) + ;; + mov ar.unat = rTMP2 // put priunat in place + ;; + ld8.fill r4 = [rENV1], 16 // env+136: r4 + ld8.fill r5 = [rENV2], 16 // env+144: r5 + ;; + ld8.fill r6 = [rENV1], 16 // env+152: r6 + ld8.fill r7 = [rENV2], 16 // env+160: r7 + ;; + mov ar.unat = rUNAT // restore real ar.unat + + // Restore BR 1-5 + ld8 rTMP1 = [rENV1], 16 // env+168: b1 + ld8 rTMP2 = [rENV2], 16 // env+176: b2 + ;; + ld8 rTMP3 = [rENV1], 16 // env+184: b3 + ld8 rTMP4 = [rENV2], -168 // env+192: b4 + mov b1 = rTMP1 + ;; + ld8 rTMP1 = [rENV1], -168 // env+200: b5 + mov b2 = rTMP2 + mov b3 = rTMP3 + mov b4 = rTMP4 + ;; + mov b5 = rTMP1 + + // Restore ar.bsp, ar.pfs, and ar.rnat + ld8 rPFS = [rENV1], 56 // env+32: cfm (+saved ar.ec) + mov rRSC = ar.rsc + adds rBIAS = 0x1f8, r0 + ;; + flushrs + ld8 rRNAT = [rENV1], -24 // env+88: ar.rnat + ld8 rPBSP = [rENV2], 88 // env+24: prev_bsp + and rRSC0 = -4, rRSC // clear ar.rsc.mode + ;; + mov ar.rsc = rRSC0 // enforced lazy mode + extr.u rNSLOT = rPFS, 7, 7 // nslots = pfs.sol + ;; + invala + and rBIAS = rPBSP, rBIAS // bias = prev_bsp & 0x1f8 ... + ;; + extr.u rBIAS = rBIAS, 3, 6 // ... div 8 + ;; + add rBIAS = rNSLOT, rBIAS // bias += nslots + ;; + cmp.lt p6, p0 = 63, rBIAS // if (63 < bias) ... + cmp.lt p7, p0 = 126, rBIAS // if (126 < bias) ... + ;; +(p6) add rNSLOT = 1, rNSLOT // ... nslots++ + ;; +(p7) add rNSLOT = 1, rNSLOT // ... nslots++ + ;; + dep.z rTMP3 = rNSLOT, 3, 7 // (nslots << 3) + ;; + add rBSP = rPBSP, rTMP3 // bsp = prev_bsp + (nslots << 3) + ;; + mov ar.bspstore = rBSP // restore ar.bsp + ;; + mov ar.rnat = rRNAT // restore ar.rnat + mov ar.pfs = rPFS // restore ar.pfs + ;; + mov ar.rsc = rRSC // restore ar.rsc + + // Restore preds and ar.lc + ld8 rTMP1 = [rENV1], -56 // env+64: preds + ld8 rTMP2 = [rENV2], -96 // env+112: ar.lc + ;; + mov pr = rTMP1 + mov ar.lc = rTMP2 + + // Get previous sp and ip + ld8 rRP = [rENV1], 96 // env+8: ip (my rp) + ld8 rPSP = [rENV2], 112 // env+16: sp + ;; + + // Restore ar.fpsr and gp + ld8 rTMP1 = [rENV1], 104 // env+104: ar.fpsr + ld8 r1 = [rENV2], 96 // env+128: gp + ;; + mov ar.fpsr = rTMP1 // restore ar.fpsr + + // Restore FR 2-5 and 16-31 + ldf.fill f2 = [rENV1], 32 // env+208: f2 + ldf.fill f3 = [rENV2], 32 // env+224: f3 + ;; + ldf.fill f4 = [rENV1], 32 // env+240: f4 + ldf.fill f5 = [rENV2], 32 // env+256: f5 + ;; + ldf.fill f16 = [rENV1], 32 // env+272: f16 + ldf.fill f17 = [rENV2], 32 // env+288: f17 + ;; + ldf.fill f18 = [rENV1], 32 // env+304: f16 + ldf.fill f19 = [rENV2], 32 // env+320: f17 + ;; + ldf.fill f20 = [rENV1], 32 // env+336: f16 + ldf.fill f21 = [rENV2], 32 // env+352: f17 + ;; + ldf.fill f22 = [rENV1], 32 // env+368: f16 + ldf.fill f23 = [rENV2], 32 // env+384: f17 + ;; + ldf.fill f24 = [rENV1], 32 // env+400: f16 + ldf.fill f25 = [rENV2], 32 // env+416: f17 + ;; + ldf.fill f26 = [rENV1], 32 // env+432: f16 + ldf.fill f27 = [rENV2], 32 // env+448: f17 + ;; + ldf.fill f28 = [rENV1], 32 // env+464: f16 + ldf.fill f29 = [rENV2], 32 // env+480: f17 + ;; + ldf.fill f30 = [rENV1], 32 // env+496: f16 + ldf.fill f31 = [rENV2], 32 // env+512: f17 + + // Set landing pad parameter registers + mov r15 = r33 + mov r16 = r34 + mov r17 = r35 + mov r18 = r36 + + // Restore previous sp and Return + mov ret0 = r37 + mov sp = rPSP + mov b0 = rRP + br.ret.sptk b0 + + .endp diff --git a/sys/contrib/ia64/libuwx/src/uwx_self_info.h b/sys/contrib/ia64/libuwx/src/uwx_self_info.h new file mode 100644 index 0000000..1d1cc57 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_self_info.h @@ -0,0 +1,44 @@ +/* +Copyright (c) 2003-2006 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. +*/ + +#define MAX_RVEC_SIZE 12 + +struct load_module_cache; + +struct uwx_self_info { + struct uwx_env *env; + ucontext_t *ucontext; + uint64_t bspstore; + uint64_t rvec[MAX_RVEC_SIZE]; + uint64_t sendsig_start; + uint64_t sendsig_end; + int on_heap; + int trace; + struct load_module_cache *load_module_cache; +}; + +extern int uwx_self_init_info_block( + struct uwx_env *env, + struct uwx_self_info *info + ); diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.c b/sys/contrib/ia64/libuwx/src/uwx_step.c index 4e44739..e20c7c2 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_step.c +++ b/sys/contrib/ia64/libuwx/src/uwx_step.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -66,7 +66,7 @@ int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp, /* uwx_get_frame_info: Gets unwind info for current frame */ -static + int uwx_get_frame_info(struct uwx_env *env) { int i; @@ -77,14 +77,18 @@ int uwx_get_frame_info(struct uwx_env *env) 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) return UWX_ERR_NOCALLBACKS; + env->ptr_size = DWORDSZ; + env->code_start = 0; env->function_offset = -1LL; env->function_name = 0; env->module_name = 0; + env->abi_context = 0; uwx_reset_str_pool(env); /* Use the lookup IP callback routine to find out about the */ @@ -170,9 +174,12 @@ int uwx_get_frame_info(struct uwx_env *env) 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) + if (status == UWX_OK) { + env->ptr_size = uentry.ptr_size; + env->code_start = uentry.code_start; status = uwx_decode_uinfo(env, &uentry, &rstate); - else if (status == UWX_ERR_NOUENTRY) + } + if (status == UWX_ERR_NOUENTRY || status == UWX_ERR_NOUDESC) status = uwx_default_rstate(env, &rstate); if (status == UWX_OK) env->rstate = rstate; @@ -182,6 +189,7 @@ int uwx_get_frame_info(struct uwx_env *env) /* proceed directly to decoding the unwind information. */ else if (cbstatus == UWX_LKUP_UINFO) { + uentry.ptr_size = DWORDSZ; uentry.code_start = 0; uentry.code_end = 0; uentry.unwind_info = 0; @@ -190,26 +198,35 @@ int uwx_get_frame_info(struct uwx_env *env) switch ((int)uvec[i]) { case UWX_KEY_UFLAGS: uentry.unwind_flags = uvec[i+1]; + if (uentry.unwind_flags & UNWIND_TBL_32BIT) + uentry.ptr_size = WORDSZ; break; case UWX_KEY_UINFO: uentry.unwind_info = uvec[i+1]; break; + case UWX_KEY_GP: + uwx_set_reg(env, UWX_REG_GP, uvec[i+1]); + break; case UWX_KEY_MODULE: env->module_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNC: env->function_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNCSTART: uentry.code_start = uvec[i+1]; + env->code_start = uentry.code_start; break; } } + env->ptr_size = uentry.ptr_size; if (cbcalled) (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); status = uwx_decode_uinfo(env, &uentry, &rstate); + if (status == UWX_ERR_NOUDESC) + status = uwx_default_rstate(env, &rstate); if (status == UWX_OK) env->rstate = rstate; } @@ -291,7 +308,104 @@ int uwx_restore_markers(struct uwx_env *env) return UWX_OK; } +/* uwx_get_module_info: Gets module name and text base for current frame */ + +int uwx_get_module_info( + struct uwx_env *env, + char **modp, + uint64_t *text_base) +{ + int i; + int status; + int cbstatus; + uint64_t ip; + uint64_t *uvec; + uint64_t uvecout[UVECSIZE]; + + if (env == 0) + return UWX_ERR_NOENV; + + /* If we haven't already obtained the frame info for the */ + /* current frame, get it now. */ + + if (env->rstate == 0) { + status = uwx_get_frame_info(env); + if (status != UWX_OK) + return status; + } + + /* Get the module name from the lookup IP callback. */ + if (env->module_name == 0) { + ip = env->remapped_ip; + i = 0; + if (env->function_offset >= 0) { + uvecout[i++] = UWX_KEY_FUNCSTART; + uvecout[i++] = ip - env->function_offset; + } + uvecout[i++] = UWX_KEY_END; + uvecout[i++] = 0; + uvec = uvecout; + cbstatus = (*env->lookupip)(UWX_LKUP_MODULE, ip, env->cb_token, &uvec); + + if (cbstatus == UWX_LKUP_SYMINFO) { + for (i = 0; uvec[i] != UWX_KEY_END; i += 2) { + switch ((int)uvec[i]) { + case UWX_KEY_TBASE: + env->text_base = uvec[i+1]; + break; + case UWX_KEY_MODULE: + env->module_name = + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); + break; + case UWX_KEY_FUNC: + env->function_name = + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); + break; + case UWX_KEY_FUNCSTART: + env->function_offset = ip - uvec[i+1]; + break; + } + } + (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec); + } + } + + *modp = env->module_name; + *text_base = env->text_base; + + return UWX_OK; +} + +/* uwx_get_funcstart: Gets start address of function from current frame */ + +int uwx_get_funcstart( + struct uwx_env *env, + uint64_t *funcstart) +{ + int status; + uint64_t *uvec; + uint64_t uvecout[UVECSIZE]; + + if (env == 0) + return UWX_ERR_NOENV; + + /* If we haven't already obtained the frame info for the */ + /* current frame, get it now. */ + + if (env->rstate == 0) { + status = uwx_get_frame_info(env); + if (status != UWX_OK) + return status; + } + + *funcstart = env->remapped_ip - env->function_offset; + + return UWX_OK; +} + /* uwx_get_sym_info: Gets symbolic info from current frame */ +/* (Will make a UWX_LKUP_SYMBOLS callback if info */ +/* was not provided by UWX_LKUP_LOOKUP callback) */ int uwx_get_sym_info( struct uwx_env *env, @@ -303,7 +417,7 @@ int uwx_get_sym_info( int cbstatus; uint64_t ip; uint64_t *uvec; - uint64_t uvecout[2]; + uint64_t uvecout[UVECSIZE]; int i; if (env == 0) @@ -336,11 +450,11 @@ int uwx_get_sym_info( switch ((int)uvec[i]) { case UWX_KEY_MODULE: env->module_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNC: env->function_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNCSTART: env->function_offset = ip - uvec[i+1]; @@ -572,13 +686,16 @@ int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate) env->abi_context = (int)(uvec[i+1]); status = UWX_ABI_FRAME; break; + case UWX_KEY_GP: + uwx_set_reg(env, UWX_REG_GP, uvec[i+1]); + break; case UWX_KEY_MODULE: env->module_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNC: env->function_name = - uwx_alloc_str(env, (char *)(uvec[i+1])); + uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1])); break; case UWX_KEY_FUNCSTART: env->function_offset = env->remapped_ip - uvec[i+1]; @@ -597,7 +714,8 @@ int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate) (env->remote? \ (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ DWORDSZ, env->cb_token) : \ - (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) ) + (*(uint64_t *)(intptr_t)(dest) = \ + *(uint64_t *)(intptr_t)(src), DWORDSZ) ) int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, uint64_t *valp, uint64_t *histp) @@ -644,9 +762,10 @@ int uwx_restore_reg(struct uwx_env *env, uint64_t rstate, (env->remote? \ (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \ 2*DWORDSZ, env->cb_token) : \ - (*(uint64_t *)(dest) = *(uint64_t *)(src), \ - *(uint64_t *)((dest)+8) = *(uint64_t *)((src)+8), \ - 2*DWORDSZ) ) + (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), \ + *(uint64_t *)(intptr_t)((dest)+8) = \ + *(uint64_t *)(intptr_t)((src)+8), \ + 2*DWORDSZ) ) int uwx_restore_freg(struct uwx_env *env, uint64_t rstate, uint64_t *valp, uint64_t *histp) diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.h b/sys/contrib/ia64/libuwx/src/uwx_step.h index 4c51e9b..157395f 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_step.h +++ b/sys/contrib/ia64/libuwx/src/uwx_step.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -25,6 +25,4 @@ 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 e8da35e..fb9e08d 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_str.c +++ b/sys/contrib/ia64/libuwx/src/uwx_str.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -22,15 +22,11 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include <string.h> + #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 * @@ -46,21 +42,16 @@ static struct uwx_str_pool uwx_str_pool; */ -int uwx_init_str_pool(struct uwx_env *env) +int uwx_init_str_pool(struct uwx_env *env, struct uwx_str_pool *pool) { - if (env->allocate_cb == 0) - env->string_pool = (struct uwx_str_pool *) - malloc(sizeof(struct uwx_str_pool)); - else - env->string_pool = (struct uwx_str_pool *) - (*env->allocate_cb)(sizeof(struct uwx_str_pool)); - - if (env->string_pool == 0) + if (pool == 0) return UWX_ERR_NOMEM; - env->string_pool->next = 0; - env->string_pool->size = STRPOOLSIZE; - env->string_pool->used = 0; + pool->next = 0; + pool->size = STRPOOLSIZE; + pool->used = 0; + + env->string_pool = pool; return UWX_OK; } @@ -70,7 +61,11 @@ void uwx_free_str_pool(struct uwx_env *env) struct uwx_str_pool *pool; struct uwx_str_pool *next; - for (pool = env->string_pool; pool != 0; pool = next) { + /* The first pool is preallocated as part of the uwx_env. Don't free it! */ + pool = env->string_pool; + if (pool != 0) + pool = pool->next; + for (; pool != 0; pool = next) { next = pool->next; if (env->free_cb == 0) free(pool); diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.h b/sys/contrib/ia64/libuwx/src/uwx_str.h index f55340e..5e85d6a 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_str.h +++ b/sys/contrib/ia64/libuwx/src/uwx_str.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -22,7 +22,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define STRPOOLSIZE 400 +#define STRPOOLSIZE (400-sizeof(void *)-2*sizeof(int)) struct uwx_str_pool { struct uwx_str_pool *next; @@ -31,7 +31,7 @@ struct uwx_str_pool { char pool[STRPOOLSIZE]; }; -extern int uwx_init_str_pool(struct uwx_env *env); +extern int uwx_init_str_pool(struct uwx_env *env, struct uwx_str_pool *pool); extern void uwx_free_str_pool(struct uwx_env *env); extern char *uwx_alloc_str(struct uwx_env *env, char *str); extern void uwx_reset_str_pool(struct uwx_env *env); diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.c b/sys/contrib/ia64/libuwx/src/uwx_swap.c index 19d57bd..5917393 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_swap.c +++ b/sys/contrib/ia64/libuwx/src/uwx_swap.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.h b/sys/contrib/ia64/libuwx/src/uwx_swap.h index 1eb24d4..70d921c 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_swap.h +++ b/sys/contrib/ia64/libuwx/src/uwx_swap.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_symbols.c b/sys/contrib/ia64/libuwx/src/uwx_symbols.c new file mode 100644 index 0000000..b91c2db --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_symbols.c @@ -0,0 +1,850 @@ +/* +Copyright (c) 2003-2006 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 USE_CLEAN_NAMESPACE +#define fopen _fopen +#define fseek _fseek +#define fread _fread +#define fclose _fclose +#endif /* USE_CLEAN_NAMESPACE */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <elf.h> + +#include "uwx.h" +#include "uwx_env.h" + +#ifdef USE_CLEAN_NAMESPACE +/* + * Moved the defines above the include of stdio.h, + * so we don't need these unless that causes problems + * and we have to move them back down here. + * #define fopen _fopen + * #define fseek _fseek + * #define fread _fread + * #define fclose _fclose + * extern FILE *_fopen(const char *, const char *); + * extern int _fseek(FILE *, long int, int); + * extern size_t _fread(void *, size_t, size_t, FILE *); + * extern int _fclose(FILE *); + */ +#endif /* USE_CLEAN_NAMESPACE */ + +struct uwx_symbol_cache { + char *module_name; + int nsyms; + uint64_t *sym_values; + char **sym_names; + char *strings; +}; + + +int uwx_read_func_symbols( + struct uwx_env *env, + struct uwx_symbol_cache *cache, + char *module_name); + + +int uwx_find_symbol( + struct uwx_env *env, + struct uwx_symbol_cache **symbol_cache_p, + char *module_name, + uint64_t relip, + char **func_name_p, + uint64_t *offset_p) +{ + int status; + int i; + uint64_t offset; + uint64_t best_offset; + char *best_name; + struct symbol *sym; + struct uwx_symbol_cache *cache = NULL; + + /* Allocate a symbol cache on first call */ + if (symbol_cache_p != NULL) + cache = *symbol_cache_p; + if (cache == NULL) { + cache = (struct uwx_symbol_cache *) + (*env->allocate_cb)(sizeof(struct uwx_symbol_cache)); + if (cache == NULL) + return UWX_ERR_NOMEM; + cache->module_name = NULL; + cache->nsyms = 0; + cache->sym_values = NULL; + cache->sym_names = NULL; + cache->strings = NULL; + if (symbol_cache_p != NULL) + *symbol_cache_p = cache; + } + + /* Read function symbols from the object file */ + status = uwx_read_func_symbols(env, cache, module_name); + if (status != UWX_OK) + return status; + + /* Search for best match */ + best_offset = ~(uint64_t)0; + best_name = NULL; + for (i = 0; i < cache->nsyms; i++) { + if (cache->sym_values[i] == relip) { + *func_name_p = cache->sym_names[i]; + *offset_p = 0; + if (symbol_cache_p == NULL) + uwx_release_symbol_cache(env, cache); + return UWX_OK; + } + if (relip > cache->sym_values[i]) { + offset = relip - cache->sym_values[i]; + if (offset < best_offset) { + best_offset = offset; + best_name = cache->sym_names[i]; + } + } + } + if (best_name == NULL) + return UWX_ERR_NOSYM; + + if (symbol_cache_p == NULL) + uwx_release_symbol_cache(env, cache); + + *func_name_p = best_name; + *offset_p = best_offset; + return UWX_OK; +} + + +void uwx_release_symbol_cache( + struct uwx_env *env, + struct uwx_symbol_cache *symbol_cache) +{ + if (symbol_cache->module_name != NULL) + (*env->free_cb)(symbol_cache->module_name); + if (symbol_cache->sym_values != NULL) + (*env->free_cb)(symbol_cache->sym_values); + if (symbol_cache->sym_names != NULL) + (*env->free_cb)(symbol_cache->sym_names); + if (symbol_cache->strings != NULL) + (*env->free_cb)(symbol_cache->strings); + (*env->free_cb)(symbol_cache); +} + + +#define ELF_ERR_NOMEM UWX_ERR_NOMEM /* Out of memory */ +#define ELF_ERR_OPEN UWX_ERR_NOSYM /* Can't open file */ + +#define ELF_ERR_NOHEADER UWX_ERR_NOSYM /* Can't read ELF header */ +#define ELF_ERR_NOTELF UWX_ERR_NOSYM /* Not an ELF file */ +#define ELF_ERR_HEADER_SIZE UWX_ERR_NOSYM /* Invalid e_ehsize */ +#define ELF_ERR_INVALID_CLASS UWX_ERR_NOSYM /* Invalid EI_CLASS */ +#define ELF_ERR_INVALID_DATA UWX_ERR_NOSYM /* Invalid EI_DATA */ + +#define ELF_ERR_READ_SECTHDR UWX_ERR_NOSYM /* Can't read section headers */ +#define ELF_ERR_SECTHDR_SIZE UWX_ERR_NOSYM /* Invalid e_shentsize */ + +#define ELF_ERR_READ_PROGHDR UWX_ERR_NOSYM /* Can't read program headers */ +#define ELF_ERR_PROGHDR_SIZE UWX_ERR_NOSYM /* Invalid e_phentsize */ + +#define ELF_ERR_READ_SECTION UWX_ERR_NOSYM /* Can't read section contents */ + +#define ELF_ERR_READ_SYMTAB UWX_ERR_NOSYM /* Can't read symbol table */ +#define ELF_ERR_SYMTAB_SIZE UWX_ERR_NOSYM /* Invalid sh_entsize for symtab */ + + +struct elf_file { + uint64_t phoff; + uint64_t shoff; + uint64_t text_base; + uint64_t text_end; + alloc_cb allocate_cb; + free_cb free_cb; + const char *filename; + FILE *fd; + struct elf_section *sections; + struct elf_symbol *symbols; + char *symbol_strings; + int native_data; + int source_class; + int source_data; + int ehsize; + int phentsize; + int phnum; + int shentsize; + int shnum; + int nsyms; +}; + +struct elf_section { + uint64_t flags; + uint64_t addr; + uint64_t offset; + uint64_t size; + uint64_t entsize; + char *contents; + struct elf_symbol *symbols; + int type; + int link; + int info; + int nelems; +}; + +struct elf_symbol { + uint64_t value; + char *namep; + int name; + int type; + int shndx; +}; + + +static void elf_swap_bytes(char *buf, char *template) +{ + int i; + int sz; + char temp[16]; + + while (sz = *template++) { + if (sz > 16) + exit(1); + for (i = 0; i < sz; i++) + temp[i] = buf[i]; + for (i = 0; i < sz; i++) + buf[i] = temp[sz-i-1]; + buf += sz; + } +} + + +static int elf_read_section(struct elf_file *ef, int shndx) +{ + struct elf_section *sect; + + if (shndx < 0 || shndx > ef->shnum) + return 0; + + sect = &ef->sections[shndx]; + + /* Return if section has already been read */ + if (sect->contents != NULL) + return 0; + + sect->contents = (*ef->allocate_cb)(sect->size); + if (sect->contents == NULL) + return ELF_ERR_NOMEM; + + fseek(ef->fd, (long)sect->offset, SEEK_SET); + if (fread(sect->contents, 1, sect->size, ef->fd) != sect->size) + return ELF_ERR_READ_SECTION; + + return 0; +} + + +static char template_elf32_sym[] = {4, 4, 4, 1, 1, 2, 0}; +static char template_elf64_sym[] = {4, 1, 1, 2, 8, 8, 0}; + +static int elf_read_symtab_section(struct elf_file *ef, int shndx) +{ + int i; + int nsyms; + long size; + union { + Elf32_Sym sym32; + Elf64_Sym sym64; + } sym; + struct elf_section *sect; + struct elf_symbol *syms; + struct elf_symbol *symp; + char *strtab; + + sect = &ef->sections[shndx]; + + /* Return if section has already been read */ + if (sect->symbols != NULL) + return 0; + + if (ef->source_class == ELFCLASS32) { + if (sect->entsize != sizeof(sym.sym32)) + return ELF_ERR_SYMTAB_SIZE; + } + else { + if (sect->entsize != sizeof(sym.sym64)) + return ELF_ERR_SYMTAB_SIZE; + } + + nsyms = sect->nelems; + syms = (struct elf_symbol *) + (*ef->allocate_cb)(sizeof(struct elf_symbol) * nsyms); + if (syms == NULL) + return ELF_ERR_NOMEM; + + /* Read the symbol table */ + fseek(ef->fd, (long)sect->offset, SEEK_SET); + for (i = 0; i < nsyms; i++) { + + symp = &syms[i]; + + /* Read the next symbol table entry */ + if (fread((char *)&sym, sect->entsize, 1, ef->fd) != 1) { + (*ef->free_cb)(syms); + return ELF_ERR_READ_SYMTAB; + } + + /* Get fields from appropriate structure */ + if (ef->source_class == ELFCLASS32) { + /* Swap bytes if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&sym, template_elf32_sym); + symp->name = sym.sym32.st_name; + symp->type = sym.sym32.st_info & 0x0f; + symp->shndx = sym.sym32.st_shndx; + symp->value = sym.sym32.st_value; + } + else { + /* Swap bytes if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&sym, template_elf64_sym); + symp->name = sym.sym64.st_name; + symp->type = sym.sym64.st_info & 0x0f; + symp->shndx = sym.sym64.st_shndx; + symp->value = sym.sym64.st_value; + } + symp->namep = NULL; + + } + + /* Read the symbol string table and convert section names */ + /* from string table offsets to pointers */ + if (sect->link > 0 && sect->link < ef->shnum) { + if (elf_read_section(ef, sect->link) == 0) { + strtab = ef->sections[sect->link].contents; + for (i = 0; i < nsyms; i++) { + symp = &syms[i]; + symp->namep = strtab + symp->name; + } + ef->symbol_strings = strtab; + ef->sections[sect->link].contents = NULL; + } + } + + sect->symbols = syms; + return 0; +} + + +static char template_elf32_phdr[] = {4, 4, 4, 4, 4, 4, 4, 4, 0}; +static char template_elf64_phdr[] = {4, 4, 8, 8, 8, 8, 8, 8, 0}; + +static int elf_read_prog_hdrs(struct elf_file *ef) +{ + int i; + union { + Elf32_Phdr hdr32; + Elf64_Phdr hdr64; + } header; + uint64_t vaddr; + uint64_t memsz; + uint64_t unwind_base; + int type; + + if (ef->phnum == 0) + return 0; + + if (ef->source_class == ELFCLASS32) { + if (ef->phentsize != sizeof(header.hdr32)) + return ELF_ERR_PROGHDR_SIZE; + } + else { + if (ef->phentsize != sizeof(header.hdr64)) + return ELF_ERR_PROGHDR_SIZE; + } + + /* Look for the PT_IA_64_UNWIND segment */ + /* (That will help us identify the text segment) */ + + fseek(ef->fd, (long)ef->phoff, SEEK_SET); + for (i = 0; i < ef->phnum; i++) { + + /* Read the next program header */ + if (fread((char *)&header, ef->phentsize, 1, ef->fd) != 1) + return ELF_ERR_READ_PROGHDR; + + /* Get fields from appropriate structure */ + if (ef->source_class == ELFCLASS32) { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf32_phdr); + type = header.hdr32.p_type; + vaddr = header.hdr32.p_vaddr; + } + else { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf64_phdr); + type = header.hdr64.p_type; + vaddr = header.hdr64.p_vaddr; + } + + if (type == PT_IA_64_UNWIND) { + unwind_base = vaddr; + break; + } + + } + + /* Now look for the PT_LOAD segment that includes the unwind segment */ + + fseek(ef->fd, (long)ef->phoff, SEEK_SET); + for (i = 0; i < ef->phnum; i++) { + + /* Read the next program header */ + if (fread((char *)&header, ef->phentsize, 1, ef->fd) != 1) + return ELF_ERR_READ_PROGHDR; + + /* Get fields from appropriate structure */ + if (ef->source_class == ELFCLASS32) { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf32_phdr); + type = header.hdr32.p_type; + vaddr = header.hdr32.p_vaddr; + memsz = header.hdr32.p_memsz; + } + else { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf64_phdr); + type = header.hdr64.p_type; + vaddr = header.hdr64.p_vaddr; + memsz = header.hdr64.p_memsz; + } + + if (type == PT_LOAD && + vaddr <= unwind_base && unwind_base < vaddr + memsz) { + ef->text_base = vaddr; + ef->text_end = vaddr + memsz; + break; + } + + } + + return 0; +} + + +static char template_elf32_shdr[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0}; +static char template_elf64_shdr[] = {4, 4, 8, 8, 8, 8, 4, 4, 8, 8, 0}; + +static int elf_read_sect_hdrs(struct elf_file *ef) +{ + int i; + long size; + int err; + union { + Elf32_Shdr hdr32; + Elf64_Shdr hdr64; + } header; + struct elf_section *sect; + char *shstrtab; + + if (ef->source_class == ELFCLASS32) { + if (ef->shentsize != sizeof(header.hdr32)) + return ELF_ERR_SECTHDR_SIZE; + } + else { + if (ef->shentsize != sizeof(header.hdr64)) + return ELF_ERR_SECTHDR_SIZE; + } + + fseek(ef->fd, (long)ef->shoff, SEEK_SET); + ef->sections = (struct elf_section *) + (*ef->allocate_cb)(sizeof(struct elf_section) * ef->shnum); + if (ef->sections == NULL) + return ELF_ERR_NOMEM; + + /* Read the section header table */ + for (i = 0; i < ef->shnum; i++) { + + sect = &ef->sections[i]; + + /* Read the next section header */ + if (fread((char *)&header, ef->shentsize, 1, ef->fd) != 1) { + (*ef->free_cb)(ef->sections); + return ELF_ERR_READ_SECTHDR; + } + + /* Get fields from appropriate structure */ + if (ef->source_class == ELFCLASS32) { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf32_shdr); + sect->type = header.hdr32.sh_type; + sect->flags = header.hdr32.sh_flags; + sect->addr = header.hdr32.sh_addr; + sect->offset = header.hdr32.sh_offset; + sect->size = header.hdr32.sh_size; + sect->link = header.hdr32.sh_link; + sect->info = header.hdr32.sh_info; + sect->entsize = header.hdr32.sh_entsize; + } + else { + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header, template_elf64_shdr); + sect->type = header.hdr64.sh_type; + sect->flags = header.hdr64.sh_flags; + sect->addr = header.hdr64.sh_addr; + sect->offset = header.hdr64.sh_offset; + sect->size = header.hdr64.sh_size; + sect->link = header.hdr64.sh_link; + sect->info = header.hdr64.sh_info; + sect->entsize = header.hdr64.sh_entsize; + } + sect->contents = NULL; + sect->symbols = NULL; + if (sect->entsize > 0) + sect->nelems = sect->size / sect->entsize; + + } + + return 0; +} + + +static char template_elf32_ehdr[] = {2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0}; +static char template_elf64_ehdr[] = {2, 2, 4, 8, 8, 8, 4, 2, 2, 2, 2, 2, 2, 0}; + +static int elf_read_header(struct elf_file *ef) +{ + union { + char ident[EI_NIDENT]; + Elf32_Ehdr hdr32; + Elf64_Ehdr hdr64; + } header; + + /* Read the ELF header */ + fseek(ef->fd, 0L, SEEK_SET); + if (fread((char *)header.ident, EI_NIDENT, 1, ef->fd) != 1) { + return ELF_ERR_NOHEADER; + } + + /* Verify that this is an ELF file */ + if (header.ident[EI_MAG0] != ELFMAG0 || + header.ident[EI_MAG1] != ELFMAG1 || + header.ident[EI_MAG2] != ELFMAG2 || + header.ident[EI_MAG3] != ELFMAG3) { + return ELF_ERR_NOTELF; + } + + /* Get header fields from the byte array e_ident */ + /* (These are independent of EI_CLASS and EI_DATA) */ + ef->source_class = header.ident[EI_CLASS]; + ef->source_data = header.ident[EI_DATA]; + + /* Verify EI_CLASS and EI_DATA */ + if (header.ident[EI_CLASS] != ELFCLASS32 && + header.ident[EI_CLASS] != ELFCLASS64) { + return ELF_ERR_INVALID_CLASS; + } + if (header.ident[EI_DATA] != ELFDATA2LSB && + header.ident[EI_DATA] != ELFDATA2MSB) { + return ELF_ERR_INVALID_DATA; + } + + /* Get remaining header fields from appropriate structure */ + if (ef->source_class == ELFCLASS32) { + if (fread((char *)&header.hdr32 + EI_NIDENT, + sizeof(header.hdr32) - EI_NIDENT, 1, ef->fd) != 1) + return ELF_ERR_NOHEADER; + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header + EI_NIDENT, template_elf32_ehdr); + ef->phoff = header.hdr32.e_phoff; + ef->shoff = header.hdr32.e_shoff; + ef->ehsize = header.hdr32.e_ehsize; + ef->phentsize = header.hdr32.e_phentsize; + ef->phnum = header.hdr32.e_phnum; + ef->shentsize = header.hdr32.e_shentsize; + ef->shnum = header.hdr32.e_shnum; + if (ef->ehsize != sizeof(header.hdr32)) { + return ELF_ERR_HEADER_SIZE; + } + } + else { + if (fread((char *)&header.hdr64 + EI_NIDENT, + sizeof(header.hdr64) - EI_NIDENT, 1, ef->fd) != 1) + return ELF_ERR_NOHEADER; + /* Swap bytes in header fields if necessary */ + if (ef->source_data != ef->native_data) + elf_swap_bytes((char *)&header + EI_NIDENT, template_elf64_ehdr); + ef->phoff = header.hdr64.e_phoff; + ef->shoff = header.hdr64.e_shoff; + ef->ehsize = header.hdr64.e_ehsize; + ef->phentsize = header.hdr64.e_phentsize; + ef->phnum = header.hdr64.e_phnum; + ef->shentsize = header.hdr64.e_shentsize; + ef->shnum = header.hdr64.e_shnum; + if (ef->ehsize != sizeof(header.hdr64)) { + return ELF_ERR_HEADER_SIZE; + } + } + + return 0; +} + + +static struct elf_file *elf_new(struct uwx_env *env) +{ + int native_be; + char *p; + struct elf_file *ef; + + ef = (struct elf_file *)(*env->allocate_cb)(sizeof(struct elf_file)); + if (ef == NULL) + return NULL; + + /* Determine the native byte order */ + p = (char *)&native_be; + native_be = 1; /* Assume big-endian */ + *p = 0; /* Sets be == 0 only if little-endian */ + + ef->allocate_cb = env->allocate_cb; + ef->free_cb = env->free_cb; + ef->filename = NULL; + ef->native_data = (native_be ? ELFDATA2MSB : ELFDATA2LSB); + ef->fd = NULL; + ef->source_class = 0; + ef->source_data = 0; + ef->phoff = 0; + ef->shoff = 0; + ef->text_base = 0; + ef->text_end = 0; + ef->ehsize = 0; + ef->phentsize = 0; + ef->phnum = 0; + ef->shentsize = 0; + ef->shnum = 0; + ef->sections = NULL; + ef->symbols = NULL; + ef->symbol_strings = NULL; + ef->nsyms = 0; + return ef; +} + + +static int elf_open(struct elf_file *ef, const char *filename) +{ + int err; + + ef->filename = filename; + + ef->fd = fopen(filename, "r"); + if (ef->fd == NULL) + return ELF_ERR_OPEN; + + if ((err = elf_read_header(ef)) != 0) + return err; + + if ((err = elf_read_sect_hdrs(ef)) != 0) + return err; + + if ((err = elf_read_prog_hdrs(ef)) != 0) + return err; + + return 0; +} + + +static void elf_free_sections(struct elf_file *ef) +{ + int i; + struct elf_section *sect; + + for (i = 0; i < ef->shnum; i++) { + sect = &ef->sections[i]; + if (sect->contents != NULL) + (*ef->free_cb)(sect->contents); + if ((sect->type == SHT_SYMTAB || sect->type == SHT_DYNSYM) + && sect->symbols != NULL) + (*ef->free_cb)(sect->symbols); + } + (*ef->free_cb)(ef->sections); +} + + +static void elf_close(struct elf_file *ef) +{ + if (ef->fd != NULL) { + fclose(ef->fd); + ef->fd = NULL; + } +} + + +static void elf_free(struct elf_file *ef) +{ + elf_close(ef); + if (ef->sections != NULL) + elf_free_sections(ef); + (*ef->free_cb)(ef); +} + + +static int elf_read_symbols(struct elf_file *ef) +{ + int i; + int err; + struct elf_section *sect; + + for (i = 1; i < ef->shnum; i++) { + sect = &ef->sections[i]; + if (sect->type == SHT_SYMTAB) { + if (elf_read_symtab_section(ef, i) == 0) { + ef->symbols = sect->symbols; + ef->nsyms = sect->nelems; +#ifdef DEBUG_SYMBOLS + printf("Read %d symbols from SHT_SYMTAB section\n", ef->nsyms); +#endif /* DEBUG_SYMBOLS */ + return 0; + } + } + } + for (i = 1; i < ef->shnum; i++) { + sect = &ef->sections[i]; + if (sect->type == SHT_DYNSYM) { + if (elf_read_symtab_section(ef, i) == 0) { + ef->symbols = sect->symbols; + ef->nsyms = sect->nelems; +#ifdef DEBUG_SYMBOLS + printf("Read %d symbols from SHT_DYNSYM section\n", ef->nsyms); +#endif /* DEBUG_SYMBOLS */ + return 0; + } + } + } + return UWX_ERR_NOSYM; +} + + +#define SYM_IS_DEFINED(sym) \ + ((sym)->shndx != SHN_UNDEF) + +#define SYM_IS_IN_TEXT_SEGMENT(value) \ + ((value) >= ef->text_base && (value) < ef->text_end) + +#define SYM_HAS_INTERESTING_TYPE(type) ( \ + (type) == STT_FUNC || \ + (type) == STT_OBJECT || \ + (type) == STT_HP_STUB \ + ) + +#define SYM_IS_INTERESTING(sym) ( \ + SYM_IS_DEFINED(sym) && \ + SYM_IS_IN_TEXT_SEGMENT((sym)->value) && \ + SYM_HAS_INTERESTING_TYPE((sym)->type) \ + ) + +int uwx_read_func_symbols( + struct uwx_env *env, + struct uwx_symbol_cache *cache, + char *module_name) +{ + int i, j; + int status; + struct elf_file *ef; + struct elf_symbol *sym; + int nfuncsyms; + char **names; + uint64_t *values; + + if (module_name != NULL && + cache->module_name != NULL && + strcmp(module_name, cache->module_name) == 0) + return UWX_OK; + + if (cache->sym_names != NULL) + (*env->free_cb)(cache->sym_names); + if (cache->sym_values != NULL) + (*env->free_cb)(cache->sym_values); + if (cache->strings != NULL) + (*env->free_cb)(cache->strings); + + ef = elf_new(env); + if (ef == NULL) + return UWX_ERR_NOMEM; + status = elf_open(ef, module_name); + if (status != 0) + return UWX_ERR_NOSYM; + status = elf_read_symbols(ef); + if (status != 0) + return UWX_ERR_NOSYM; + + nfuncsyms = 0; + for (i = 0; i < ef->nsyms; i++) { + sym = &ef->symbols[i]; + if (SYM_IS_INTERESTING(sym)) + nfuncsyms++; + } + + names = (char **)(*env->allocate_cb)(nfuncsyms * sizeof(char *)); + if (names == NULL) + return UWX_ERR_NOMEM; + values = (uint64_t *)(*env->allocate_cb)(nfuncsyms * sizeof(uint64_t)); + if (values == NULL) + return UWX_ERR_NOMEM; + + j = 0; + for (i = 0; i < ef->nsyms; i++) { + sym = &ef->symbols[i]; + if (SYM_IS_INTERESTING(sym)) { + if (j >= nfuncsyms) /* should not happen! */ + break; + names[j] = sym->namep; + values[j] = sym->value - ef->text_base; + j++; + } + } + + cache->module_name = (char *)(*env->allocate_cb)(strlen(module_name)+1); + if (cache->module_name != NULL) { + strcpy(cache->module_name, module_name); + cache->nsyms = nfuncsyms; + cache->sym_names = names; + cache->sym_values = values; + cache->strings = ef->symbol_strings; + ef->symbol_strings = NULL; + } + + elf_close(ef); + elf_free(ef); + +#ifdef DEBUG_SYMBOLS + printf("Cached %d interesting symbols\n", nfuncsyms); +#endif /* DEBUG_SYMBOLS */ + + return UWX_OK; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_symbols.h b/sys/contrib/ia64/libuwx/src/uwx_symbols.h new file mode 100644 index 0000000..83b0bfe --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_symbols.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 2003-2006 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. +*/ + +struct uwx_env; +struct uwx_symbol_cache; + +extern int uwx_find_symbol( + struct uwx_env *env, + struct uwx_symbol_cache **symbol_cache_p, + char *module_name, + uint64_t relip, + char **func_name_p, + uint64_t *offset_p); + +extern void uwx_release_symbol_cache( + struct uwx_env *env, + struct uwx_symbol_cache *symbol_cache); diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.c b/sys/contrib/ia64/libuwx/src/uwx_trace.c index 11c3db6..10ab55d 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_trace.c +++ b/sys/contrib/ia64/libuwx/src/uwx_trace.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -23,12 +23,11 @@ OTHER DEALINGS IN THE SOFTWARE. */ #include "uwx_env.h" +#include "uwx_utable.h" #include "uwx_uinfo.h" #include "uwx_scoreboard.h" #include "uwx_trace.h" -#ifdef UWX_TRACE_ENABLE - void uwx_trace_init(struct uwx_env *env) { char *tstr; @@ -36,7 +35,7 @@ void uwx_trace_init(struct uwx_env *env) 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; @@ -46,9 +45,6 @@ void uwx_trace_init(struct uwx_env *env) 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"); @@ -59,9 +55,7 @@ void uwx_trace_init(struct uwx_env *env) fprintf(stderr, " C: copyin callback\n"); fprintf(stderr, " L: lookup ip callback\n"); exit(1); -#endif } - tstr++; } } } @@ -84,37 +78,37 @@ void uwx_dump_rstate(int regid, uint64_t rstate) if (rstate == UWX_DISP_NONE) return; - printf(" %-7s", uwx_sb_rnames[regid]); + fprintf(stderr, " %-7s", uwx_sb_rnames[regid]); switch (UWX_GET_DISP_CODE(rstate)) { case UWX_DISP_NONE: - printf(" unchanged\n"); + fprintf(stderr, " unchanged\n"); break; case UWX_DISP_SPPLUS(0): - printf(" SP + %d\n", (int)rstate & ~0x07); + fprintf(stderr, " SP + %d\n", (int)rstate & ~0x07); break; case UWX_DISP_SPREL(0): - printf(" [SP + %d]\n", (int)rstate & ~0x07); + fprintf(stderr, " [SP + %d]\n", (int)rstate & ~0x07); break; case UWX_DISP_PSPREL(0): - printf(" [PSP + 16 - %d]\n", (int)rstate & ~0x07); + fprintf(stderr, " [PSP + 16 - %d]\n", (int)rstate & ~0x07); break; case UWX_DISP_REG(0): reg = UWX_GET_DISP_REGID(rstate); if (reg == UWX_REG_AR_PFS) - printf(" [AR.PFS]\n"); + fprintf(stderr, " AR.PFS\n"); else if (reg == UWX_REG_AR_UNAT) - printf(" [AR.UNAT]\n"); + fprintf(stderr, " AR.UNAT\n"); else if (reg >= UWX_REG_GR(0) && reg < UWX_REG_GR(128)) - printf(" [GR%d]\n", reg - UWX_REG_GR(0)); + fprintf(stderr, " GR%d\n", reg - UWX_REG_GR(0)); else if (reg >= UWX_REG_FR(0) && reg < UWX_REG_FR(128)) - printf(" [FR%d]\n", reg - UWX_REG_FR(0)); + fprintf(stderr, " FR%d\n", reg - UWX_REG_FR(0)); else if (reg >= UWX_REG_BR(0) && reg < UWX_REG_BR(8)) - printf(" [BR%d]\n", reg - UWX_REG_BR(0)); + fprintf(stderr, " BR%d\n", reg - UWX_REG_BR(0)); else - printf(" [reg %d]\n", reg); + fprintf(stderr, " <reg %d>\n", reg); break; default: - printf(" <%08llx>\n", (unsigned long long)rstate); + fprintf(stderr, " <%08x>\n", rstate); break; } } @@ -129,15 +123,35 @@ void uwx_dump_scoreboard( int i; if (rhdr->is_prologue) - printf(" Prologue region (start = %d, length = %d)\n", + fprintf(stderr, " Prologue region (start = %d, length = %d)\n", (int)cur_slot, (int)rhdr->rlen); else - printf(" Body region (start = %d, length = %d, ecount = %d)\n", + fprintf(stderr, " Body region (start = %d, length = %d, ecount = %d)\n", cur_slot, (int)rhdr->rlen, rhdr->ecount); if (ip_slot < rhdr->rlen) - printf(" IP is in this region (offset = %d)\n", ip_slot); + fprintf(stderr, " IP is in this region (offset = %d)\n", ip_slot); for (i = 0; i < nsbreg; i++) uwx_dump_rstate(i, scoreboard->rstate[i]); } -#endif /* UWX_TRACE_ENABLE */ +void uwx_dump_uinfo_block( + struct uwx_utable_entry *uentry, + unsigned int ulen) +{ + int i; + uint32_t *uinfo = (uint32_t *)(intptr_t)uentry->unwind_info; + + ulen += DWORDSZ; /* Include unwind info header */ + if (uentry->unwind_flags & UNWIND_TBL_32BIT) /* and personality routine */ + ulen += WORDSZ; + else + ulen += DWORDSZ; + while (ulen >= WORDSZ) { + fprintf(stderr, " %08lx: ", (unsigned long)uinfo); + for (i = 0; i < 4 * WORDSZ && ulen >= WORDSZ; i += WORDSZ) { + fprintf(stderr, " %08lx", *uinfo++); + ulen -= WORDSZ; + } + fprintf(stderr, "\n"); + } +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.h b/sys/contrib/ia64/libuwx/src/uwx_trace.h index 38a2e9d..741b6d1 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_trace.h +++ b/sys/contrib/ia64/libuwx/src/uwx_trace.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -50,138 +50,146 @@ extern void uwx_dump_scoreboard( #define TRACE_B_REUSE(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_alloc_scoreboard: reuse id %d\n", (id)); + fprintf(stderr, "uwx_alloc_scoreboard: reuse id %d\n", (id)); + +#define TRACE_B_PREALLOC(id) \ + if (env->trace & UWX_TRACE_SB) \ + fprintf(stderr, "uwx_prealloc_scoreboard: prealloc id %d\n", (id)); #define TRACE_B_ALLOC(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_alloc_scoreboard: alloc id %d\n", (id)); + fprintf(stderr, "uwx_alloc_scoreboard: alloc id %d\n", (id)); #define TRACE_B_POP(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_pop_scoreboards: free id %d\n", (id)); + fprintf(stderr, "uwx_pop_scoreboards: free id %d\n", (id)); #define TRACE_B_LABEL(label) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_label_scoreboard: label %d\n", (label)); + fprintf(stderr, "uwx_label_scoreboard: label %d\n", (label)); #define TRACE_B_LABEL_COPY(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_label_scoreboard: copy id %d\n", (id)); + fprintf(stderr, "uwx_label_scoreboard: copy id %d\n", (id)); #define TRACE_B_LABEL_REVERSE(back, new) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_label_scoreboard: reverse link %d -> %d\n", \ + fprintf(stderr, "uwx_label_scoreboard: reverse link %d -> %d\n", \ (new)->id, ((back) == 0) ? -1 : (back)->id); #define TRACE_B_COPY(label, id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_copy_scoreboard: label %d, cur sb id %d\n", (label), (id)); + fprintf(stderr, "uwx_copy_scoreboard: label %d, cur sb id %d\n", (label), (id)); #define TRACE_B_COPY_FREE(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_copy_scoreboard: free id %d\n", (id)); + fprintf(stderr, "uwx_copy_scoreboard: free id %d\n", (id)); #define TRACE_B_COPY_FOUND(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_copy_scoreboard: found id %d\n", (id)); + fprintf(stderr, "uwx_copy_scoreboard: found id %d\n", (id)); #define TRACE_B_COPY_COPY(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_copy_scoreboard: copy id %d\n", (id)); + fprintf(stderr, "uwx_copy_scoreboard: copy id %d\n", (id)); #define TRACE_B_COPY_REVERSE(back, new) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_copy_scoreboard: reverse link %d -> %d\n", \ + fprintf(stderr, "uwx_copy_scoreboard: reverse link %d -> %d\n", \ (new)->id, ((back) == 0) ? -1 : (back)->id); #define TRACE_B_FREE(id) \ if (env->trace & UWX_TRACE_SB) \ - printf("uwx_free_scoreboards: free id %d\n", (id)); + fprintf(stderr, "uwx_free_scoreboards: free id %d\n", (id)); #define TRACE_I_DECODE_RHDR_1(name, b0) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_rhdr: %02x %s\n", \ + fprintf(stderr, "uwx_decode_rhdr: %02x %s\n", \ (b0), (name)); #define TRACE_I_DECODE_RHDR_1L(name, b0, val) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_rhdr: %02x %08x %s\n", \ + fprintf(stderr, "uwx_decode_rhdr: %02x %08x %s\n", \ (b0), (int)(val), (name)); #define TRACE_I_DECODE_RHDR_2L(name, b0, b1, val) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_rhdr: %02x %02x %08x %s\n", \ + fprintf(stderr, "uwx_decode_rhdr: %02x %02x %08x %s\n", \ (b0), (b1), (int)(val), (name)); #define TRACE_I_DECODE_PROLOGUE_1(name, b0) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %s\n", \ (b0), (name)); #define TRACE_I_DECODE_PROLOGUE_1L(name, b0, val) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %08x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %08x %s\n", \ (b0), (int)(val), (name)); #define TRACE_I_DECODE_PROLOGUE_1LL(name, b0, val1, val2) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %08x %08x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %08x %08x %s\n", \ (b0), (int)(val1), (int)(val2), (name)); #define TRACE_I_DECODE_PROLOGUE_2(name, b0, b1) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %02x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %02x %s\n", \ (b0), (b1), (name)); #define TRACE_I_DECODE_PROLOGUE_2L(name, b0, b1, val) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %02x %08x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %02x %08x %s\n", \ (b0), (b1), (int)(val), (name)); #define TRACE_I_DECODE_PROLOGUE_3(name, b0, b1, b2) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %02x %02x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %02x %02x %s\n", \ (b0), (b1), (b2), (name)); #define TRACE_I_DECODE_PROLOGUE_4(name, b0, b1, b2, b3) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: %02x %02x %02x %02x %s\n", \ + fprintf(stderr, "uwx_decode_prologue: %02x %02x %02x %02x %s\n", \ (b0), (b1), (b2), (b3), (name)); #define TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: spill base = %08x\n", (int)(spill_base)); + fprintf(stderr, "uwx_decode_prologue: spill base = %08x\n", (int)(spill_base)); #define TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: gr_mem_mask = %02x; gr_gr_mask = %02x\n", \ + fprintf(stderr, "uwx_decode_prologue: gr_mem_mask = %02x; gr_gr_mask = %02x\n", \ (gr_mem_mask), (gr_gr_mask)); #define TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_prologue: ngr = %d\n", (ngr)); + fprintf(stderr, "uwx_decode_prologue: ngr = %d\n", (ngr)); #define TRACE_I_DECODE_BODY_1(name, b0) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_body: %02x %s\n", \ + fprintf(stderr, "uwx_decode_body: %02x %s\n", \ (b0), (name)); #define TRACE_I_DECODE_BODY_1L(name, b0, val) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_body: %02x %08x %s\n", \ + fprintf(stderr, "uwx_decode_body: %02x %08x %s\n", \ (b0), (int)(val), (name)); #define TRACE_I_DECODE_BODY_1LL(name, b0, val1, val2) \ if (env->trace & UWX_TRACE_UINFO) \ - printf("uwx_decode_body: %02x %08x %08x %s\n", \ + fprintf(stderr, "uwx_decode_body: %02x %08x %08x %s\n", \ (b0), (int)(val1), (int)(val2), (name)); #define TRACE_R_UIB(uentry, ulen) \ - if (env->trace & UWX_TRACE_RSTATE) \ - printf("Unwind info block (flags = %08x %08x, ulen = %d)\n", \ + if (env->trace & UWX_TRACE_RSTATE) { \ + fprintf(stderr, "Unwind info block (info = %08x %08x, flags = %08x %08x, ulen = %d)\n", \ + (unsigned int)((uentry)->unwind_info >> 32), \ + (unsigned int)(uentry)->unwind_info, \ (unsigned int)((uentry)->unwind_flags >> 32), \ (unsigned int)(uentry)->unwind_flags, \ - (ulen)); + (ulen)); \ + if (!env->remote) uwx_dump_uinfo_block(uentry, ulen); \ + } #define TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) \ if (env->trace & UWX_TRACE_RSTATE) \ @@ -190,7 +198,7 @@ extern void uwx_dump_scoreboard( #define TRACE_S_STEP(rstate) \ if (env->trace & UWX_TRACE_STEP) { \ - printf("uwx_restore_markers:\n"); \ + fprintf(stderr, "uwx_restore_markers:\n"); \ uwx_dump_rstate(SBREG_RP, (rstate)[SBREG_RP]); \ uwx_dump_rstate(SBREG_PSP, (rstate)[SBREG_PSP]); \ uwx_dump_rstate(SBREG_PFS, (rstate)[SBREG_PFS]); \ @@ -198,7 +206,7 @@ extern void uwx_dump_scoreboard( #define TRACE_S_RESTORE_REG(regname, rstate, val) \ if (env->trace & UWX_TRACE_STEP) \ - printf(" restore %-7s (rstate = %08x %08x) = %08x %08x\n", \ + fprintf(stderr, " restore %-7s (rstate = %08x %08x) = %08x %08x\n", \ regname, \ (unsigned int) ((rstate) >> 32), \ (unsigned int) (rstate), \ @@ -207,7 +215,7 @@ extern void uwx_dump_scoreboard( #define TRACE_S_RESTORE_GR(regid, rstate, val) \ if (env->trace & UWX_TRACE_STEP) \ - printf(" restore GR%d (rstate = %08x %08x) = %08x %08x\n", \ + fprintf(stderr, " restore GR%d (rstate = %08x %08x) = %08x %08x\n", \ (regid) + 4, \ (unsigned int) ((rstate) >> 32), \ (unsigned int) (rstate), \ @@ -216,7 +224,7 @@ extern void uwx_dump_scoreboard( #define TRACE_S_RESTORE_BR(regid, rstate, val) \ if (env->trace & UWX_TRACE_STEP) \ - printf(" restore BR%d (rstate = %08x %08x) = %08x %08x\n", \ + fprintf(stderr, " restore BR%d (rstate = %08x %08x) = %08x %08x\n", \ (regid) + 1, \ (unsigned int) ((rstate) >> 32), \ (unsigned int) (rstate), \ @@ -225,7 +233,7 @@ extern void uwx_dump_scoreboard( #define TRACE_S_RESTORE_FR(regid, rstate, fval) \ if (env->trace & UWX_TRACE_STEP) \ - printf(" restore FR%d (rstate = %08x %08x) = %08x %08x %08x %08x\n", \ + fprintf(stderr, " restore FR%d (rstate = %08x %08x) = %08x %08x %08x %08x\n", \ (regid) + 1, \ (unsigned int) ((rstate) >> 32), \ (unsigned int) (rstate), \ @@ -236,23 +244,23 @@ extern void uwx_dump_scoreboard( #define TRACE_T_SEARCH32(ip) \ if (env->trace & UWX_TRACE_UTABLE) \ - printf("uwx_search_utable32 (relative ip = %08x)\n", (ip)); + fprintf(stderr, "uwx_search_utable32 (relative ip = %08x)\n", (ip)); #define TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end) \ if (env->trace & UWX_TRACE_UTABLE) \ - printf(" lb/ub = %d/%d, mid = %d, start/end = %08x %08x\n", \ + fprintf(stderr, " lb/ub = %d/%d, mid = %d, start/end = %08x %08x\n", \ lb, ub, mid, code_start, code_end); #define TRACE_C_GET_REG(regid, bsp) \ if (env->trace & UWX_TRACE_CONTEXT) \ - printf("uwx_get_reg (gr%d, bsp = %08x %08x)\n", \ + fprintf(stderr, "uwx_get_reg (gr%d, bsp = %08x %08x)\n", \ (regid) - UWX_REG_GR(0), \ (unsigned int) ((bsp) >> 32), \ (unsigned int) (bsp)); #define TRACE_C_ROTATE_GR(regid, sor, rrb_gr, newregid) \ if (env->trace & UWX_TRACE_CONTEXT) \ - printf("uwx_get_reg (gr%d, sor = %d, rrb = %d) --> gr%d\n", \ + fprintf(stderr, "uwx_get_reg (gr%d, sor = %d, rrb = %d) --> gr%d\n", \ (regid) + 32, \ (sor), \ (rrb_gr), \ @@ -260,14 +268,14 @@ extern void uwx_dump_scoreboard( #define TRACE_SELF_COPYIN4(rem, len, wp) \ if (info->trace & UWX_TRACE_COPYIN) \ - printf("copyin (rem = %08x %08x, len = %d, val = %08x)\n", \ + fprintf(stderr, "copyin (rem = %08x %08x, len = %d, val = %08x)\n", \ (unsigned int) ((rem) >> 32), \ (unsigned int) (rem), \ (len), *(wp)); #define TRACE_SELF_COPYIN8(rem, len, dp) \ if (info->trace & UWX_TRACE_COPYIN) \ - printf("copyin (rem = %08x %08x, len = %d, val = %08x %08x)\n", \ + fprintf(stderr, "copyin (rem = %08x %08x, len = %d, val = %08x %08x)\n", \ (unsigned int) ((rem) >> 32), \ (unsigned int) (rem), \ (len), \ @@ -276,25 +284,28 @@ extern void uwx_dump_scoreboard( #define TRACE_SELF_LOOKUP(ip) \ if (info->trace & UWX_TRACE_LOOKUPIP) \ - printf("Lookup IP callback: ip = %08x %08x\n", \ + fprintf(stderr, "Lookup IP callback: ip = %08x %08x\n", \ (unsigned int) ((ip) >> 32), \ (unsigned int) (ip)); -#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base) \ +#define TRACE_SELF_LOOKUP_DESC(text_base, linkage_ptr, unwind_base) \ if (info->trace & UWX_TRACE_LOOKUPIP) { \ - printf(" text base: %08x %08x\n", \ + fprintf(stderr, " text base: %08x %08x\n", \ (unsigned int) ((text_base) >> 32), \ (unsigned int) (text_base)); \ - printf(" unwind base: %08x %08x\n", \ + fprintf(stderr, " linkage ptr: %08x %08x\n", \ + (unsigned int) ((linkage_ptr) >> 32), \ + (unsigned int) (linkage_ptr)); \ + fprintf(stderr, " unwind base: %08x %08x\n", \ (unsigned int) ((uint64_t)(unwind_base) >> 32), \ (unsigned int) (unwind_base)); \ - printf(" unwind flags: %08x %08x\n", \ + fprintf(stderr, " unwind flags: %08x %08x\n", \ (unsigned int) ((unwind_base)[0] >> 32), \ (unsigned int) (unwind_base)[0]); \ - printf(" unwind start: %08x %08x\n", \ + fprintf(stderr, " unwind start: %08x %08x\n", \ (unsigned int) (((text_base)+(unwind_base)[1]) >> 32), \ (unsigned int) ((text_base)+(unwind_base)[1])); \ - printf(" unwind end: %08x %08x\n", \ + fprintf(stderr, " unwind end: %08x %08x\n", \ (unsigned int) (((text_base)+(unwind_base)[2]) >> 32), \ (unsigned int) ((text_base)+(unwind_base)[2])); \ } @@ -303,6 +314,7 @@ extern void uwx_dump_scoreboard( #define TRACE_INIT #define TRACE_B_REUSE(id) +#define TRACE_B_PREALLOC(id) #define TRACE_B_ALLOC(id) #define TRACE_B_POP(id) #define TRACE_B_LABEL(label) @@ -344,7 +356,7 @@ extern void uwx_dump_scoreboard( #define TRACE_SELF_COPYIN4(rem, len, wp) #define TRACE_SELF_COPYIN8(rem, len, dp) #define TRACE_SELF_LOOKUP(ip) -#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base) +#define TRACE_SELF_LOOKUP_DESC(text_base, linkage_ptr, unwind_base) #endif /* UWX_TRACE_ENABLE */ diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c index bf50d20..1658017 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c +++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -28,7 +28,6 @@ OTHER DEALINGS IN THE SOFTWARE. #include "uwx_scoreboard.h" #include "uwx_bstream.h" #include "uwx_trace.h" -#include "uwx_swap.h" int uwx_count_ones(unsigned int mask); @@ -49,15 +48,15 @@ int uwx_count_ones(unsigned int mask); #define COPYIN_UINFO_4(dest, src) \ (env->remote? \ - (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ + (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ WORDSZ, env->cb_token) : \ - (*(uint32_t *)(dest) = *(uint32_t *)(src), WORDSZ) ) + (*(uint32_t *)(intptr_t)(dest) = *(uint32_t *)(intptr_t)(src), WORDSZ) ) #define COPYIN_UINFO_8(dest, src) \ (env->remote? \ - (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ + (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ DWORDSZ, env->cb_token) : \ - (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) ) + (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), DWORDSZ) ) /* uwx_default_rstate: Returns the default register state for a leaf routine */ @@ -121,6 +120,12 @@ int uwx_decode_uinfo( uwx_init_bstream(&bstream, env, uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO); + /* Save the header and a pointer to the personality routine ptr */ + /* for later use in exception handling. */ + + env->uinfo_hdr = uinfohdr; + env->uinfo_end = uentry->unwind_info + DWORDSZ + ulen; + TRACE_R_UIB(uentry, ulen) /* Create an initial scoreboard for tracking the unwind state. */ @@ -344,9 +349,9 @@ int uwx_decode_prologue( br_mem_mask = 0; gr_gr_mask = 0; br_gr_mask = 0; - nfr = 0; - ngr = 0; - nbr = 0; + nfr = 127; + ngr = 127; + nbr = 127; spill_base = 0; /* If prologue_gr header record supplied mask and grsave, */ @@ -453,6 +458,10 @@ int uwx_decode_prologue( TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1) scoreboard->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(reg)); + if (newrstate[SBREG_RP] == + UWX_DISP_REG(UWX_REG_BR(0))) + newrstate[SBREG_RP] = + UWX_DISP_REG(UWX_REG_BR(reg)); break; case 7: /* rnat_gr */ TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1) @@ -463,12 +472,12 @@ int uwx_decode_prologue( TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 9: /* bspstore_gr */ TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1) /* Don't track BSPSTORE yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 10: /* fpsr_gr */ TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1) newrstate[SBREG_FPSR] = @@ -500,6 +509,9 @@ int uwx_decode_prologue( /* two pieces of information together at the */ /* end of the main loop. */ t = 0; + nfr = 0; + ngr = 0; + nbr = 0; while (t < rhdr->rlen) { b1 = uwx_get_byte(bstream); if (b1 < 0) @@ -669,32 +681,32 @@ int uwx_decode_prologue( TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 8: /* bsp_psprel */ TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 9: /* bsp_sprel */ TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 10: /* bspstore_when */ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 11: /* bspstore_psprel */ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 12: /* bspstore_sprel */ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1) /* Don't track BSP yet */ return UWX_ERR_CANTUNWIND; - break; + /* break; */ case 13: /* rnat_when */ TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1) tspill[SBREG_RNAT] = (int) parm1; @@ -1092,7 +1104,7 @@ int uwx_decode_body( /* is restored, update the scoreboard entry for PSP */ /* and reset any entries for registers saved in memory. */ - if (ip_slot > t_sp_restore) { + if (rhdr->ecount > 0 && ip_slot > t_sp_restore) { scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); for (i = 0; i < env->nsbreg; i++) { if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) || diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.h b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h index bdd05cb..1bb477c 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_uinfo.h +++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.c b/sys/contrib/ia64/libuwx/src/uwx_utable.c index bedaab7..4b73d69 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_utable.c +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -76,15 +76,12 @@ 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: keys |= 1; - text_base = *uvec++; + env->text_base = text_base = *uvec++; break; case UWX_KEY_UFLAGS: unwind_flags = *uvec++; @@ -97,6 +94,9 @@ int uwx_search_utable( keys |= 4; unwind_end = *uvec++; break; + case UWX_KEY_GP: + uwx_set_reg(env, UWX_REG_GP, *uvec++); + break; default: return UWX_ERR_BADKEY; } @@ -134,6 +134,8 @@ int uwx_search_utable( WORDSZ, env->cb_token) : \ (*(uint32_t *)(dest) = *(uint32_t *)(src), WORDSZ) ) +#define SWIZZLE(x) (((uint64_t)((x) & 0xc0000000) << 31) | (x)) + int uwx_search_utable32( struct uwx_env *env, uint32_t ip, @@ -142,6 +144,7 @@ int uwx_search_utable32( uint32_t unwind_end, struct uwx_utable_entry *uentry) { + int status; int lb; int ub; int mid; @@ -162,13 +165,11 @@ 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, - (uintptr_t)(unwind_start+mid*3*WORDSZ)); + len = COPYIN_UINFO_4((char *)&code_start, unwind_start+mid*3*WORDSZ); len += COPYIN_UINFO_4((char *)&code_end, - (uintptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ)); + unwind_start+mid*3*WORDSZ+WORDSZ); if (len != 2 * WORDSZ) return UWX_ERR_COPYIN_UTBL; if (env->byte_swap) { @@ -186,14 +187,15 @@ int uwx_search_utable32( if (ub <= lb) return UWX_ERR_NOUENTRY; len = COPYIN_UINFO_4((char *)&unwind_info, - (uintptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ)); + unwind_start+mid*3*WORDSZ+2*WORDSZ); if (len != WORDSZ) return UWX_ERR_COPYIN_UTBL; if (env->byte_swap) uwx_swap4(&unwind_info); - uentry->code_start = text_base + code_start; - uentry->code_end = text_base + code_end; - uentry->unwind_info = text_base + unwind_info; + uentry->ptr_size = WORDSZ; + uentry->code_start = SWIZZLE(text_base + code_start); + uentry->code_end = SWIZZLE(text_base + code_end); + uentry->unwind_info = SWIZZLE(text_base + unwind_info); return UWX_OK; } @@ -202,9 +204,9 @@ int uwx_search_utable32( #define COPYIN_UINFO_8(dest, src) \ (env->remote? \ - (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ + (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ DWORDSZ, env->cb_token) : \ - (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) ) + (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), DWORDSZ) ) int uwx_search_utable64( struct uwx_env *env, @@ -214,6 +216,7 @@ int uwx_search_utable64( uint64_t unwind_end, struct uwx_utable_entry *uentry) { + int status; int lb; int ub; int mid; @@ -232,7 +235,6 @@ int uwx_search_utable64( 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); @@ -259,6 +261,7 @@ int uwx_search_utable64( return UWX_ERR_COPYIN_UTBL; if (env->byte_swap) uwx_swap8(&unwind_info); + uentry->ptr_size = DWORDSZ; uentry->code_start = text_base + code_start; uentry->code_end = text_base + code_end; uentry->unwind_info = text_base + unwind_info; diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.h b/sys/contrib/ia64/libuwx/src/uwx_utable.h index cf81b07..69f1cc7 100644 --- a/sys/contrib/ia64/libuwx/src/uwx_utable.h +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003 Hewlett-Packard Development Company, L.P. +Copyright (c) 2003-2006 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 @@ -23,6 +23,7 @@ OTHER DEALINGS IN THE SOFTWARE. */ struct uwx_utable_entry { + uint64_t ptr_size; uint64_t code_start; uint64_t code_end; uint64_t unwind_info; |