This commit was generated by cvs2svn to compensate for changes in r160157,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Marcel Moolenaar 2006-07-07 22:59:01 +00:00
commit 50074ddd37
28 changed files with 1908 additions and 347 deletions

View File

@ -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

View File

@ -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 @@ class UnwindExpress {
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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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 */

View File

@ -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) ||

View File

@ -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

View File

@ -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;

View File

@ -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;