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:
commit
50074ddd37
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
44
sys/contrib/ia64/libuwx/src/uwx_self_info.h
Normal file
44
sys/contrib/ia64/libuwx/src/uwx_self_info.h
Normal 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
|
||||
);
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
850
sys/contrib/ia64/libuwx/src/uwx_symbols.c
Normal file
850
sys/contrib/ia64/libuwx/src/uwx_symbols.c
Normal 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;
|
||||
}
|
38
sys/contrib/ia64/libuwx/src/uwx_symbols.h
Normal file
38
sys/contrib/ia64/libuwx/src/uwx_symbols.h
Normal 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);
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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) ||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user