Update to BETA 7. Besides C++ support, which is irrelevant to us,

this version mostly has bugs fixes.
This commit is contained in:
Marcel Moolenaar 2004-05-09 03:06:25 +00:00
parent c2b1cc6d02
commit 9cc6463a07
18 changed files with 1274 additions and 191 deletions

View File

@ -0,0 +1,352 @@
Only in /sys/contrib/ia64/libuwx/src: CVS
diff -u ./uwx.h /sys/contrib/ia64/libuwx/src/uwx.h
--- ./uwx.h Tue Apr 27 10:42:48 2004
+++ /sys/contrib/ia64/libuwx/src/uwx.h Thu May 6 18:10:15 2004
@@ -25,8 +25,13 @@
#ifndef __UWX_INCLUDED
#define __UWX_INCLUDED 1
+#ifndef _KERNEL
#include <stdlib.h>
#include <inttypes.h>
+#else
+#include <sys/param.h>
+#include <sys/systm.h>
+#endif
#if defined(__cplusplus)
#define __EXTERN_C extern "C"
diff -u ./uwx_bstream.c /sys/contrib/ia64/libuwx/src/uwx_bstream.c
--- ./uwx_bstream.c Tue Apr 27 10:42:52 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_bstream.c Thu May 6 18:12:11 2004
@@ -64,8 +64,6 @@
int len;
int n;
int b;
- uint32_t *wp;
- uint64_t *dp;
if (bstream->peekc >= 0) {
b = bstream->peekc;
@@ -131,6 +129,7 @@
return 0;
}
+#if 0
int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp)
{
uint64_t val;
@@ -179,3 +178,4 @@
*valp = val;
return 0;
}
+#endif
diff -u ./uwx_context.c /sys/contrib/ia64/libuwx/src/uwx_context.c
--- ./uwx_context.c Tue Apr 27 10:42:52 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_context.c Thu May 6 19:04:36 2004
@@ -200,7 +200,6 @@
int sor;
int rrb_gr;
uint64_t bsp;
- int n;
if (env == 0)
return UWX_ERR_NOENV;
@@ -274,7 +273,6 @@
int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
{
- int status;
if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
regid -= UWX_REG_FR(2);
@@ -340,6 +338,7 @@
return bsp + nslots * DWORDSZ;
}
+#if 0
int uwx_selftest_bsp_arithmetic()
{
int i;
@@ -398,3 +397,4 @@
return failed;
}
+#endif
diff -u ./uwx_env.c /sys/contrib/ia64/libuwx/src/uwx_env.c
--- ./uwx_env.c Tue Apr 27 10:42:53 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_env.c Thu May 6 21:31:55 2004
@@ -22,13 +22,21 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef _KERNEL
#include <stdlib.h>
+#endif
#include "uwx_env.h"
#include "uwx_scoreboard.h"
#include "uwx_str.h"
#include "uwx_trace.h"
+#ifdef _KERNEL
+static struct uwx_env uwx_env;
+#define free(p) /* nullified */
+#define malloc(sz) ((sz == sizeof(uwx_env)) ? &uwx_env : NULL)
+#endif
+
alloc_cb uwx_allocate_cb = 0;
free_cb uwx_free_cb = 0;
@@ -64,7 +72,6 @@
{
int i;
struct uwx_env *env;
- char *tstr;
if (uwx_allocate_cb == 0)
env = (struct uwx_env *) malloc(sizeof(struct uwx_env));
diff -u ./uwx_scoreboard.c /sys/contrib/ia64/libuwx/src/uwx_scoreboard.c
--- ./uwx_scoreboard.c Tue Apr 27 10:42:53 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_scoreboard.c Thu May 6 21:29:25 2004
@@ -22,12 +22,41 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef _KERNEL
#include <stdlib.h>
+#endif
#include "uwx_env.h"
#include "uwx_scoreboard.h"
#include "uwx_trace.h"
+#ifdef _KERNEL
+static unsigned short uwx_allocated;
+static struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3];
+
+static void
+free(struct uwx_scoreboard *p)
+{
+ int idx = p - uwx_scoreboard;
+ uwx_allocated &= ~(1 << idx);
+}
+
+static struct uwx_scoreboard *
+malloc(size_t sz)
+{
+ int idx;
+ if (sz != sizeof(struct uwx_scoreboard))
+ return (NULL);
+ for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) {
+ if ((uwx_allocated & (1 << idx)) == 0) {
+ uwx_allocated |= 1 << idx;
+ return (uwx_scoreboard + idx);
+ }
+ }
+ return (NULL);
+}
+#endif
+
struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
{
@@ -66,6 +95,7 @@
return sb;
}
+static
void uwx_reclaim_scoreboards(struct uwx_env *env)
{
struct uwx_scoreboard *sb;
@@ -140,6 +170,7 @@
/* in the "nextstack" field. */
back = 0;
+ new = 0;
while (sb != 0) {
TRACE_B_LABEL_COPY(sb->id)
new = uwx_alloc_scoreboard(env);
@@ -223,6 +254,7 @@
/* Now copy its stack, storing reverse links in the nextstack field. */
back = sb;
+ new = 0;
for (next = lsb->nextstack; next != 0; next = next->nextstack) {
TRACE_B_COPY_COPY(next->id)
new = uwx_alloc_scoreboard(env);
diff -u ./uwx_step.c /sys/contrib/ia64/libuwx/src/uwx_step.c
--- ./uwx_step.c Tue Apr 27 10:42:54 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_step.c Thu May 6 18:32:03 2004
@@ -66,7 +66,7 @@
/* uwx_get_frame_info: Gets unwind info for current frame */
-
+static
int uwx_get_frame_info(struct uwx_env *env)
{
int i;
@@ -77,7 +77,6 @@
uint64_t *uvec;
uint64_t *rstate;
struct uwx_utable_entry uentry;
- uint64_t uinfop;
uint64_t uvecout[UVECSIZE];
if (env->copyin == 0 || env->lookupip == 0)
diff -u ./uwx_step.h /sys/contrib/ia64/libuwx/src/uwx_step.h
--- ./uwx_step.h Tue Apr 27 10:42:50 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_step.h Thu May 6 18:45:59 2004
@@ -25,4 +25,6 @@
#define UVECSIZE 20 /* Size of uvec supplied by unwind engine */
/* for callback's use. */
+extern int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok,
+ uint64_t **vecp, size_t uvecsize);
extern int uwx_restore_markers(struct uwx_env *env);
diff -u ./uwx_str.c /sys/contrib/ia64/libuwx/src/uwx_str.c
--- ./uwx_str.c Tue Apr 27 10:42:55 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_str.c Thu May 6 21:02:58 2004
@@ -25,6 +25,12 @@
#include "uwx_env.h"
#include "uwx_str.h"
+#ifdef _KERNEL
+static struct uwx_str_pool uwx_str_pool;
+#define free(p) /* nullified */
+#define malloc(sz) ((sz == sizeof(uwx_str_pool)) ? &uwx_str_pool : NULL)
+#endif
+
/*
* uwx_str.c
*
diff -u ./uwx_trace.c /sys/contrib/ia64/libuwx/src/uwx_trace.c
--- ./uwx_trace.c Tue Apr 27 10:42:55 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_trace.c Thu May 6 18:36:02 2004
@@ -27,6 +27,8 @@
#include "uwx_scoreboard.h"
#include "uwx_trace.h"
+#ifdef UWX_TRACE_ENABLE
+
void uwx_trace_init(struct uwx_env *env)
{
char *tstr;
@@ -34,7 +36,7 @@
tstr = getenv("UWX_TRACE");
if (tstr != NULL) {
while (*tstr != '\0') {
- switch (*tstr++) {
+ switch (*tstr) {
case 'i': env->trace |= UWX_TRACE_UINFO; break;
case 't': env->trace |= UWX_TRACE_UTABLE; break;
case 'b': env->trace |= UWX_TRACE_SB; break;
@@ -44,6 +46,9 @@
case 'C': env->trace |= UWX_TRACE_COPYIN; break;
case 'L': env->trace |= UWX_TRACE_LOOKUPIP; break;
case '?':
+#ifdef _KERNEL
+ printf("UWX_TRACE flag `%c' unknown.\n", *tstr);
+#else
fprintf(stderr, "UWX_TRACE flags:\n");
fprintf(stderr, " i: unwind info\n");
fprintf(stderr, " t: unwind table searching\n");
@@ -54,7 +59,9 @@
fprintf(stderr, " C: copyin callback\n");
fprintf(stderr, " L: lookup ip callback\n");
exit(1);
+#endif
}
+ tstr++;
}
}
}
@@ -107,7 +114,7 @@
printf(" [reg %d]\n", reg);
break;
default:
- printf(" <%08x>\n", rstate);
+ printf(" <%08llx>\n", (unsigned long long)rstate);
break;
}
}
@@ -133,3 +140,4 @@
uwx_dump_rstate(i, scoreboard->rstate[i]);
}
+#endif /* UWX_TRACE_ENABLE */
diff -u ./uwx_uinfo.c /sys/contrib/ia64/libuwx/src/uwx_uinfo.c
--- ./uwx_uinfo.c Tue Apr 27 10:42:56 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_uinfo.c Thu May 6 18:46:51 2004
@@ -28,6 +28,7 @@
#include "uwx_scoreboard.h"
#include "uwx_bstream.h"
#include "uwx_trace.h"
+#include "uwx_swap.h"
int uwx_count_ones(unsigned int mask);
diff -u ./uwx_utable.c /sys/contrib/ia64/libuwx/src/uwx_utable.c
--- ./uwx_utable.c Tue Apr 27 10:42:56 2004
+++ /sys/contrib/ia64/libuwx/src/uwx_utable.c Thu May 6 18:58:55 2004
@@ -76,7 +76,10 @@
/* Make sure all three required values are given. */
keys = 0;
+ text_base = 0;
unwind_flags = 0;
+ unwind_start = 0;
+ unwind_end = 0;
while (*uvec != 0) {
switch ((int)*uvec++) {
case UWX_KEY_TBASE:
@@ -139,7 +142,6 @@
uint32_t unwind_end,
struct uwx_utable_entry *uentry)
{
- int status;
int lb;
int ub;
int mid;
@@ -160,11 +162,13 @@
lb = 0;
ub = (unwind_end - unwind_start) / (3 * WORDSZ);
+ mid = 0;
while (ub > lb) {
mid = (lb + ub) / 2;
- len = COPYIN_UINFO_4((char *)&code_start, unwind_start+mid*3*WORDSZ);
+ len = COPYIN_UINFO_4((char *)&code_start,
+ (uintptr_t)(unwind_start+mid*3*WORDSZ));
len += COPYIN_UINFO_4((char *)&code_end,
- unwind_start+mid*3*WORDSZ+WORDSZ);
+ (uintptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ));
if (len != 2 * WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap) {
@@ -182,7 +186,7 @@
if (ub <= lb)
return UWX_ERR_NOUENTRY;
len = COPYIN_UINFO_4((char *)&unwind_info,
- unwind_start+mid*3*WORDSZ+2*WORDSZ);
+ (uintptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ));
if (len != WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap)
@@ -210,7 +214,6 @@
uint64_t unwind_end,
struct uwx_utable_entry *uentry)
{
- int status;
int lb;
int ub;
int mid;
@@ -229,6 +232,7 @@
lb = 0;
ub = (unwind_end - unwind_start) / (3 * DWORDSZ);
+ mid = 0;
while (ub > lb) {
mid = (lb + ub) / 2;
len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ);

View File

@ -22,6 +22,9 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __UWX_INCLUDED
#define __UWX_INCLUDED 1
#ifndef _KERNEL
#include <stdlib.h>
#include <inttypes.h>
@ -30,22 +33,30 @@ OTHER DEALINGS IN THE SOFTWARE.
#include <sys/systm.h>
#endif
#if defined(__cplusplus)
#define __EXTERN_C extern "C"
#else
#define __EXTERN_C extern
#endif
#define UWX_VERSION 1 /* Version id for callback interfaces */
/* Unwind environment structure (opaque) */
struct uwx_env;
/* Allocate and free callbacks */
typedef void *(*alloc_cb)(size_t size);
typedef void (*free_cb)(void *ptr);
extern int uwx_register_alloc_cb(alloc_cb alloc, free_cb free);
__EXTERN_C int uwx_register_alloc_cb(alloc_cb alloc, free_cb free);
/* Allocate and initialize an unwind environment */
extern struct uwx_env *uwx_init(void);
__EXTERN_C struct uwx_env *uwx_init(void);
/* Free an unwind environment */
extern int uwx_free(struct uwx_env *env);
__EXTERN_C int uwx_free(struct uwx_env *env);
/* Put unwind express into cross-process mode */
extern int uwx_set_remote(struct uwx_env *env, int is_big_endian_target);
__EXTERN_C int uwx_set_remote(struct uwx_env *env, int is_big_endian_target);
/* Copy-in callback */
typedef int (*copyin_cb)(
@ -63,14 +74,14 @@ typedef int (*lookupip_cb)(
uint64_t **vecp); /* parameter vector (in/out) */
/* Register copy-in and lookup IP callbacks */
extern int uwx_register_callbacks(
__EXTERN_C int uwx_register_callbacks(
struct uwx_env *env, /* unwind environment */
intptr_t tok, /* callback token */
copyin_cb copyin, /* copy-in callback */
lookupip_cb lookupip); /* lookup IP callback */
/* Initialize a context with the basic info needed to start an unwind */
extern int uwx_init_context(
__EXTERN_C int uwx_init_context(
struct uwx_env *env, /* unwind environment */
uint64_t ip, /* IP (instruction pointer) */
uint64_t sp, /* SP (stack pointer) */
@ -78,51 +89,51 @@ extern int uwx_init_context(
uint64_t cfm); /* CFM (current frame marker) */
/* Set the value of a specific register in the current context (non fp) */
extern int uwx_set_reg(
__EXTERN_C int uwx_set_reg(
struct uwx_env *env, /* unwind environment */
int regid, /* register id (see below) */
uint64_t val); /* register value */
/* Set the value of a floating-point register in the current context */
extern int uwx_set_fr(
__EXTERN_C int uwx_set_fr(
struct uwx_env *env, /* unwind environment */
int regid, /* register id (see below) */
uint64_t *val); /* register value (ptr to 16 bytes) */
/* (memory spill format) */
/* Initialize the unwind history */
extern int uwx_init_history(struct uwx_env *env);
__EXTERN_C int uwx_init_history(struct uwx_env *env);
/* Step one frame */
extern int uwx_step(struct uwx_env *env);
__EXTERN_C int uwx_step(struct uwx_env *env);
/* Get symbol information, if available, for current frame */
extern int uwx_get_sym_info(
__EXTERN_C int uwx_get_sym_info(
struct uwx_env *env, /* unwind environment */
char **modp, /* load module name (out) */
char **symp, /* function name (out) */
uint64_t *offsetp); /* offset from start of function (out) */
/* Get the value of a register from the current context */
extern int uwx_get_reg(
__EXTERN_C int uwx_get_reg(
struct uwx_env *env, /* unwind environment */
int regid, /* register id (see below) */
uint64_t *valp); /* register value (out) */
/* Get the NaT bit of a GR from the current context */
extern int uwx_get_nat(
__EXTERN_C int uwx_get_nat(
struct uwx_env *env, /* unwind environment */
int regid, /* register id (see below) */
int *natp); /* NaT value (out: 0 or 1) */
/* Get the spill location for a register in the current context */
extern int uwx_get_spill_loc(
__EXTERN_C int uwx_get_spill_loc(
struct uwx_env *env, /* unwind environment */
int regid, /* register id (see below) */
uint64_t *dispp); /* disposition code (see below) (out) */
/* Get the ABI context code (if uwx_step returned UWX_ABI_FRAME) */
extern int uwx_get_abi_context_code(struct uwx_env *env);
__EXTERN_C int uwx_get_abi_context_code(struct uwx_env *env);
/* Return status codes for uwx_ APIs */
#define UWX_OK 0
@ -165,6 +176,8 @@ extern int uwx_get_abi_context_code(struct uwx_env *env);
#define UWX_LKUP_UTABLE 2 /* Returned ref to unwind table */
#define UWX_LKUP_FDESC 3 /* Returned frame description */
#define UWX_LKUP_SYMINFO 4 /* Returned symbolic information */
#define UWX_LKUP_REMAP 5 /* Returned remapped IP */
#define UWX_LKUP_UINFO 6 /* Returned unw info block ptr */
/* The lookup IP callback receives a parameter vector, and returns */
/* one on success. This vector is a series of key/value pairs; each */
@ -175,26 +188,40 @@ extern int uwx_get_abi_context_code(struct uwx_env *env);
/* Keys passed to lookup IP callback */
#define UWX_KEY_PREDS 1 /* Predicate registers */
#define UWX_KEY_VERSION 2 /* Version id of unwind engine */
/* UWX_KEY_FUNCSTART (below) may also be passed with the UWX_LKUP_SYMINFO */
/* request. */
/* Keys returned with UWX_LKUP_UTABLE */
/* These key/value pairs describe the unwind table corresponding */
/* to the load module in which the current IP resides. */
#define UWX_KEY_TBASE 1 /* Base address of text seg */
#define UWX_KEY_UFLAGS 2 /* Unwind flags */
#define UWX_KEY_UFLAGS 2 /* Unwind flags (optional) */
#define UWX_KEY_USTART 3 /* Base of unwind tbl */
#define UWX_KEY_UEND 4 /* End of unwind tbl */
/* Keys returned with UWX_LKUP_FDESC */
/* These key/value pairs describe the state of the frame at the */
/* given IP. They are typically used for dynamically-generated code. */
/* If UWX_KEY_CONTEXT is returned, it must be the only key returned. */
#define UWX_KEY_FSIZE 1 /* Frame size */
#define UWX_KEY_SPILL(reg_id) (2 | ((reg_id) << 4)) /* Reg spilled */
#define UWX_KEY_CONTEXT 3 /* ABI-dep. context */
/* Keys returned with UWX_LKUP_FDESC or UWX_LKUP_SYMINFO */
#define UWX_KEY_MODULE 5 /* Name of load module */
#define UWX_KEY_FUNC 6 /* Name of function */
#define UWX_KEY_FUNCSTART 7 /* Address of start of function */
/* Keys returned with UWX_LKUP_REMAP */
#define UWX_KEY_NEWIP 5 /* Remapped IP */
/* Keys returned with UWX_LKUP_UINFO */
/* Use UWX_KEY_FUNCSTART for the start address of the function */
/* Use UWX_KEY_UFLAGS for the unwind flags (optional) */
#define UWX_KEY_UINFO 6 /* Address of unwind info block */
/* Keys returned with UWX_LKUP_SYMINFO */
/* These keys may be returned with UWX_LKUP_FDESC or UWX_LKUP_UINFO, */
/* if the information is cheap to obtain. */
#define UWX_KEY_MODULE 17 /* Name of load module */
#define UWX_KEY_FUNC 18 /* Name of function */
#define UWX_KEY_FUNCSTART 19 /* Address of start of function */
/* Register identifiers */
/* For use in UWX_LKUP_FDESC result vectors and context access APIs. */
@ -255,3 +282,75 @@ extern int uwx_get_abi_context_code(struct uwx_env *env);
#define UWX_GET_DISP_OFFSET(disp) ((disp) & ~(uint64_t)0x07)
#define UWX_GET_DISP_ADDR(disp) ((disp) & ~(uint64_t)0x07)
#define UWX_GET_DISP_REGID(disp) ((int)(disp) >> 4)
#undef __EXTERN_C
#if defined(__cplusplus)
class UnwindExpress {
public:
UnwindExpress() {
env = uwx_init();
}
~UnwindExpress() {
if (env != 0)
uwx_free(env);
env = 0;
}
int init_context(uint64_t ip, uint64_t sp, uint64_t bsp, uint64_t cfm) {
return uwx_init_context(env, ip, sp, bsp, cfm);
}
int init_history() {
return uwx_init_history(env);
}
int set_reg(int regid, uint64_t val) {
return uwx_set_reg(env, regid, val);
}
int set_fr(int regid, uint64_t *valp) {
return uwx_set_fr(env, regid, valp);
}
int step() {
return uwx_step(env);
}
int get_sym_info(char **modp, char **symp, uint64_t *offsetp) {
return uwx_get_sym_info(env, modp, symp, offsetp);
}
int get_reg(int regid, uint64_t *valp) {
return uwx_get_reg(env, regid, valp);
}
int get_nat(int regid, int *natp) {
return uwx_get_nat(env, regid, natp);
}
int get_spill_loc(int regid, uint64_t *dispp) {
return uwx_get_spill_loc(env, regid, dispp);
}
int get_abi_context_code() {
return uwx_get_abi_context_code(env);
}
struct uwx_env *get_env() {
return env;
}
protected:
struct uwx_env *env;
};
#endif /* __cplusplus */
#endif /* __UWX_INCLUDED */

View File

@ -181,11 +181,7 @@ int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
}
bsp = uwx_add_to_bsp(bsp, regid);
natcollp = bsp | 0x01f8;
if (natcollp >= bsp)
n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
(uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token);
else
n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
bsp, DWORDSZ, env->cb_token);
if (n != DWORDSZ)
return UWX_ERR_COPYIN_RSTK;
@ -319,28 +315,86 @@ uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
* bsp
* <------- adjusted (nslots + bias) ------->
* When subtracting from bsp, we bias the bsp in the opposite
* direction so that it is at the next NaT collection.
* When subtracting from bsp, we avoid depending on the sign of
* the quotient by adding 63*8 before division and subtracting 8
* after division. (Assumes that we will never be called upon
* to subtract more than 504 slots from bsp.)
*
* 0 1f8 3f8
* +---------------------------------------------------------------+
* | X X|
* +---------------------------------------------------------------+
* <------- bias ------->
* <--- nslots --->
* ^
* |
* bsp
* <------ adjusted (nslots + bias) ------>
* <-- bias -->
* <--- |nslots| --->
* ^
* |
* bsp
* <----------------->
* adjusted |nslots + bias|
*/
if (nslots > 0) {
bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
nslots += (nslots + bias) / 63;
}
else if (nslots < 0) {
bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
nslots -= (-nslots + bias) / 63;
}
bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
nslots += (nslots + bias + 63*8) / 63 - 8;
return bsp + nslots * DWORDSZ;
}
#if 0
int uwx_selftest_bsp_arithmetic()
{
int i;
int j;
int r;
uint64_t bstore[161];
uint64_t *bsp;
uint64_t *p;
int failed = 0;
printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore);
r = 0;
bsp = bstore;
for (i = 0; i < 161; i++) {
if (((unsigned int)bsp & 0x1f8) == 0x1f8)
*bsp++ = 1000 + r;
else
*bsp++ = r++;
}
printf("uwx_selftest_bsp_arithmetic: plus tests...\n");
bsp = bstore;
for (i = 0; i < 64; i++) {
r = (int)*bsp;
if (r >= 1000)
r -= 1000;
for (j = 0; j < 96; j++) {
p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, j);
if (*p != (r + j)) {
failed++;
printf("%d [%08lx] + %d -> %08lx ",
i, (unsigned int)bsp, j, (unsigned int)p);
printf("(read %d instead of %d)\n", (int)*p, r + j);
}
}
bsp++;
}
printf("uwx_selftest_bsp_arithmetic: minus tests...\n");
bsp = &bstore[161];
for (i = 63; i >= 0; i--) {
bsp--;
r = (int)*bsp;
if (r >= 1000)
r -= 1000;
for (j = 0; j < 96; j++) {
p = (uint64_t *)uwx_add_to_bsp((uint64_t)bsp, -j);
if (*p != (r - j)) {
failed++;
printf("%d [%08lx] - %d -> %08lx ",
i, (unsigned int)bsp, j, (unsigned int)p);
printf("(read %d instead of %d)\n", (int)*p, r - j);
}
}
}
return failed;
}
#endif

View File

@ -24,9 +24,6 @@ OTHER DEALINGS IN THE SOFTWARE.
#ifndef _KERNEL
#include <stdlib.h>
#else
#define free(p) /* nullified */
#define malloc(sz) NULL
#endif
#include "uwx_env.h"
@ -34,6 +31,12 @@ OTHER DEALINGS IN THE SOFTWARE.
#include "uwx_str.h"
#include "uwx_trace.h"
#ifdef _KERNEL
static struct uwx_env uwx_env;
#define free(p) /* nullified */
#define malloc(sz) ((sz == sizeof(uwx_env)) ? &uwx_env : NULL)
#endif
alloc_cb uwx_allocate_cb = 0;
free_cb uwx_free_cb = 0;
@ -88,6 +91,7 @@ struct uwx_env *uwx_init()
env->context.fr[i].part1 = 0;
}
env->rstate = 0;
env->remapped_ip = 0;
env->function_offset = 0;
(void)uwx_init_history(env);
env->allocate_cb = uwx_allocate_cb;

View File

@ -78,6 +78,7 @@ struct uwx_str_pool;
struct uwx_env {
struct uwx_context context;
uint64_t *rstate;
uint64_t remapped_ip;
int64_t function_offset;
struct uwx_history history;
alloc_cb allocate_cb;

View File

@ -24,15 +24,39 @@ OTHER DEALINGS IN THE SOFTWARE.
#ifndef _KERNEL
#include <stdlib.h>
#else
#define free(p) /* nullified */
#define malloc(sz) NULL
#endif
#include "uwx_env.h"
#include "uwx_scoreboard.h"
#include "uwx_trace.h"
#ifdef _KERNEL
static unsigned short uwx_allocated;
static struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3];
static void
free(struct uwx_scoreboard *p)
{
int idx = p - uwx_scoreboard;
uwx_allocated &= ~(1 << idx);
}
static struct uwx_scoreboard *
malloc(size_t sz)
{
int idx;
if (sz != sizeof(struct uwx_scoreboard))
return (NULL);
for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) {
if ((uwx_allocated & (1 << idx)) == 0) {
uwx_allocated |= 1 << idx;
return (uwx_scoreboard + idx);
}
}
return (NULL);
}
#endif
struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
{

View File

@ -0,0 +1,336 @@
/*
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <crt0.h>
#include <dlfcn.h>
#include <sys/uc_access.h>
#include "uwx_env.h"
#include "uwx_context.h"
#include "uwx_trace.h"
#include "uwx_self.h"
#define MODULE_CACHE_SIZE 10
#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */
struct uwx_self_module_info {
uint64_t text_base;
uint64_t text_size;
uint64_t *unwind_base;
uint64_t last_access;
char *name;
struct uwx_self_module_info *next;
};
struct uwx_self_info {
struct uwx_env *env;
ucontext_t *ucontext;
uint64_t bspstore;
uint64_t rvec[10];
uint64_t sendsig_start;
uint64_t sendsig_end;
alloc_cb allocate_cb;
free_cb free_cb;
int trace;
struct load_module_desc desc;
struct uwx_self_module_info *module_cache;
};
struct uwx_self_info *uwx_self_init_info(struct uwx_env *env)
{
struct uwx_self_info *info;
struct uwx_self_module_info *modules;
size_t size;
size = sizeof(struct uwx_self_info) +
MODULE_CACHE_SIZE * sizeof(struct uwx_self_module_info);
if (env->allocate_cb == 0)
info = (struct uwx_self_info *) malloc(size);
else
info = (struct uwx_self_info *) (*env->allocate_cb)(size);
if (info == 0)
return 0;
modules = (struct uwx_self_module_info *) (info + 1);
info->env = env;
info->ucontext = 0;
info->bspstore = 0;
info->sendsig_start = __load_info->li_sendsig_txt;
info->sendsig_end = __load_info->li_sendsig_txt +
__load_info->li_sendsig_tsz;
info->allocate_cb = env->allocate_cb;
info->free_cb = env->free_cb;
info->trace = env->trace;
info->module_cache = modules;
for (i = 0; i < MODULE_CACHE_SIZE; i++) {
modules[i].text_base = 0;
modules[i].text_size = 0;
modules[i].unwind_base = 0;
modules[i].last_access = 0;
modules[i].name = 0;
modules[i].next = 0;
}
return info;
}
int uwx_self_free_info(struct uwx_self_info *info)
{
if (info->free_cb == 0)
free((void *)info);
else
(*info->free_cb)((void *)info);
return UWX_OK;
}
int uwx_self_init_from_sigcontext(
struct uwx_env *env,
struct uwx_self_info *info,
ucontext_t *ucontext)
{
int status;
uint16_t reason;
uint64_t ip;
uint64_t sp;
uint64_t bsp;
uint64_t cfm;
unsigned int nat;
uint64_t ec;
int adj;
info->ucontext = ucontext;
status = __uc_get_reason(ucontext, &reason);
status = __uc_get_ip(ucontext, &ip);
status = __uc_get_grs(ucontext, 12, 1, &sp, &nat);
status = __uc_get_cfm(ucontext, &cfm);
#ifdef NEW_UC_GET_AR
status = __uc_get_ar_bsp(ucontext, &bsp);
status = __uc_get_ar_bspstore(ucontext, &info->bspstore);
status = __uc_get_ar_ec(ucontext, &ec);
#else
status = __uc_get_ar(ucontext, 17, &bsp);
status = __uc_get_ar(ucontext, 18, &info->bspstore);
status = __uc_get_ar(ucontext, 66, &ec);
#endif
/* The returned bsp needs to be adjusted. */
/* For interrupt frames, where bsp was advanced by a cover */
/* instruction, subtract sof (size of frame). For non-interrupt */
/* frames, where bsp was advanced by br.call, subtract sol */
/* (size of locals). */
if (reason != 0)
adj = (unsigned int)cfm & 0x7f; /* interrupt frame */
else
adj = ((unsigned int)cfm >> 7) & 0x7f; /* non-interrupt frame */
bsp = uwx_add_to_bsp(bsp, -adj);
cfm |= ec << 52;
uwx_init_context(env, ip, sp, bsp, cfm);
return UWX_OK;
}
int uwx_self_do_context_frame(
struct uwx_env *env,
struct uwx_self_info *info)
{
int abi_context;
int status;
uint64_t ucontext;
abi_context = uwx_get_abi_context_code(env);
if (abi_context != UWX_ABI_HPUX_SIGCONTEXT)
return UWX_SELF_ERR_BADABICONTEXT;
status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext);
if (status != 0)
return status;
return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext);
}
int uwx_self_copyin(
int request,
char *loc,
uint64_t rem,
int len,
intptr_t tok)
{
int status;
int regid;
unsigned int nat;
struct uwx_self_info *info = (struct uwx_self_info *) tok;
unsigned long *wp;
uint64_t *dp;
status = -1;
dp = (uint64_t *) loc;
switch (request) {
case UWX_COPYIN_UINFO:
case UWX_COPYIN_MSTACK:
if (len == 4) {
wp = (unsigned long *) loc;
*wp = *(unsigned long *)rem;
TRACE_SELF_COPYIN4(rem, len, wp)
status = 0;
}
else if (len == 8) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN8(rem, len, dp)
status = 0;
}
break;
case UWX_COPYIN_RSTACK:
if (len == 8) {
if (info->ucontext == 0 && rem == (info->bspstore | 0x1f8)) {
*dp = info->env->context.special[UWX_REG_AR_RNAT];
status = 0;
}
else if (info->ucontext == 0 || rem < info->bspstore) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN8(rem, len, dp)
status = 0;
}
else {
status = __uc_get_rsebs(info->ucontext,
(uint64_t *)rem, 1, dp);
}
}
break;
case UWX_COPYIN_REG:
regid = (int)rem;
if (info->ucontext != 0) {
if (len == 8) {
if (rem == UWX_REG_PREDS)
status = __uc_get_prs(info->ucontext, dp);
else if (rem == UWX_REG_AR_PFS)
status = __uc_get_ar(info->ucontext, 64, dp);
else if (rem == UWX_REG_AR_RNAT)
status = __uc_get_ar(info->ucontext, 19, dp);
else if (rem == UWX_REG_AR_UNAT)
status = __uc_get_ar(info->ucontext, 36, dp);
else if (rem == UWX_REG_AR_FPSR)
status = __uc_get_ar(info->ucontext, 40, dp);
else if (rem == UWX_REG_AR_LC)
status = __uc_get_ar(info->ucontext, 65, dp);
else if (regid >= UWX_REG_GR(1) &&
regid <= UWX_REG_GR(31))
status = __uc_get_grs(info->ucontext,
regid - UWX_REG_GR(0), 1, dp, &nat);
else if (regid >= UWX_REG_BR(0) &&
regid <= UWX_REG_BR(7))
status = __uc_get_brs(info->ucontext,
regid - UWX_REG_BR(0), 1, dp);
}
else if (len == 16) {
if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
status = __uc_get_frs(info->ucontext,
regid - UWX_REG_FR(0), 1, (fp_regval_t *)dp);
}
}
}
break;
}
if (status != 0)
return 0;
return len;
}
int uwx_self_find_module(
uint64_t ip,
struct uwx_self_info *info,
uint64_t *text_base,
uint64_t **unwind_base)
{
UINT64 handle;
/* Search our cache for the module containing the IP */
/* Not in the cache -- call dlmodinfo */
handle = dlmodinfo(ip, &info->desc, sizeof(info->desc), 0, 0, 0);
if (handle == 0)
return UWX_ERR_IPNOTFOUND;
/* Store it in the cache */
*text_base = info->desc.text_base;
*unwind_base = (uint64_t *) info->desc.unwind_base;
return UWX_OK;
}
int uwx_self_lookupip(
int request,
uint64_t ip,
intptr_t tok,
uint64_t **resultp)
{
struct uwx_self_info *info = (struct uwx_self_info *) tok;
uint64_t text_base;
uint64_t *unwind_base;
uint64_t *rvec;
int i;
if (request == UWX_LKUP_LOOKUP) {
TRACE_SELF_LOOKUP(ip)
if (ip >= info->sendsig_start && ip < info->sendsig_end) {
i = 0;
rvec = info->rvec;
rvec[i++] = UWX_KEY_CONTEXT;
rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT;
rvec[i++] = 0;
rvec[i++] = 0;
*resultp = rvec;
return UWX_LKUP_FDESC;
}
else {
if (uwx_self_find_module(ip, info,
&text_base, &unwind_base) != UWX_OK)
return UWX_LKUP_ERR;
TRACE_SELF_LOOKUP_DESC(text_base, unwind_base)
i = 0;
rvec = info->rvec;
rvec[i++] = UWX_KEY_TBASE;
rvec[i++] = text_base;
rvec[i++] = UWX_KEY_UFLAGS;
rvec[i++] = unwind_base[0];
rvec[i++] = UWX_KEY_USTART;
rvec[i++] = text_base + unwind_base[1];
rvec[i++] = UWX_KEY_UEND;
rvec[i++] = text_base + unwind_base[2];
rvec[i++] = 0;
rvec[i++] = 0;
*resultp = rvec;
return UWX_LKUP_UTABLE;
}
}
else if (request == UWX_LKUP_FREE) {
return 0;
}
else if (request == UWX_LKUP_SYMBOLS) {
return UWX_LKUP_ERR;
}
}

View File

@ -22,12 +22,10 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _KERNEL
#include <stdlib.h>
#include <crt0.h>
#include <dlfcn.h>
#include <sys/uc_access.h>
#endif
#include "uwx_env.h"
#include "uwx_context.h"
@ -37,6 +35,7 @@ OTHER DEALINGS IN THE SOFTWARE.
#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */
struct uwx_self_info {
struct uwx_env *env;
ucontext_t *ucontext;
uint64_t bspstore;
uint64_t rvec[10];
@ -60,6 +59,7 @@ struct uwx_self_info *uwx_self_init_info(struct uwx_env *env)
if (info == 0)
return 0;
info->env = env;
info->ucontext = 0;
info->bspstore = 0;
info->sendsig_start = __load_info->li_sendsig_txt;
@ -155,72 +155,78 @@ int uwx_self_copyin(
unsigned long *wp;
uint64_t *dp;
status = -1;
dp = (uint64_t *) loc;
if (request == UWX_COPYIN_UINFO ||
request == UWX_COPYIN_MSTACK) {
if (len == 4) {
wp = (unsigned long *) loc;
*wp = *(unsigned long *)rem;
TRACE_SELF_COPYIN4(rem, len, wp)
}
else if (len == 8) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN4(rem, len, dp)
}
else
return 0;
}
else if (request == UWX_COPYIN_RSTACK && len == 8) {
if (info->ucontext == 0 || rem < info->bspstore) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN4(rem, len, dp)
}
else {
status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp);
if (status != 0)
return 0;
}
}
else if (request == UWX_COPYIN_REG && len == 8) {
if (info->ucontext == 0)
return 0;
regid = (int)rem;
if (rem < UWX_REG_GR(0)) {
switch (regid) {
case UWX_REG_PREDS:
status = __uc_get_prs(info->ucontext, dp);
break;
case UWX_REG_AR_PFS:
status = __uc_get_ar(info->ucontext, 64, dp);
break;
case UWX_REG_AR_RNAT:
status = __uc_get_ar(info->ucontext, 19, dp);
break;
case UWX_REG_AR_UNAT:
status = __uc_get_ar(info->ucontext, 36, dp);
break;
case UWX_REG_AR_FPSR:
status = __uc_get_ar(info->ucontext, 40, dp);
break;
case UWX_REG_AR_LC:
status = __uc_get_ar(info->ucontext, 65, dp);
break;
default:
return 0;
switch (request) {
case UWX_COPYIN_UINFO:
case UWX_COPYIN_MSTACK:
if (len == 4) {
wp = (unsigned long *) loc;
*wp = *(unsigned long *)rem;
TRACE_SELF_COPYIN4(rem, len, wp)
status = 0;
}
}
else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) {
status = __uc_get_grs(info->ucontext,
regid - UWX_REG_GR(0), 1, dp, &nat);
}
else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) {
status = __uc_get_brs(info->ucontext,
regid - UWX_REG_BR(0), 1, dp);
}
if (status != 0)
return 0;
else if (len == 8) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN8(rem, len, dp)
status = 0;
}
break;
case UWX_COPYIN_RSTACK:
if (len == 8) {
if (info->ucontext == 0 && rem == (info->bspstore | 0x1f8)) {
*dp = info->env->context.special[UWX_REG_AR_RNAT];
status = 0;
}
else if (info->ucontext == 0 || rem < info->bspstore) {
*dp = *(uint64_t *)rem;
TRACE_SELF_COPYIN8(rem, len, dp)
status = 0;
}
else {
status = __uc_get_rsebs(info->ucontext,
(uint64_t *)rem, 1, dp);
}
}
break;
case UWX_COPYIN_REG:
regid = (int)rem;
if (info->ucontext != 0) {
if (len == 8) {
if (rem == UWX_REG_PREDS)
status = __uc_get_prs(info->ucontext, dp);
else if (rem == UWX_REG_AR_PFS)
status = __uc_get_ar(info->ucontext, 64, dp);
else if (rem == UWX_REG_AR_RNAT)
status = __uc_get_ar(info->ucontext, 19, dp);
else if (rem == UWX_REG_AR_UNAT)
status = __uc_get_ar(info->ucontext, 36, dp);
else if (rem == UWX_REG_AR_FPSR)
status = __uc_get_ar(info->ucontext, 40, dp);
else if (rem == UWX_REG_AR_LC)
status = __uc_get_ar(info->ucontext, 65, dp);
else if (regid >= UWX_REG_GR(1) &&
regid <= UWX_REG_GR(31))
status = __uc_get_grs(info->ucontext,
regid - UWX_REG_GR(0), 1, dp, &nat);
else if (regid >= UWX_REG_BR(0) &&
regid <= UWX_REG_BR(7))
status = __uc_get_brs(info->ucontext,
regid - UWX_REG_BR(0), 1, dp);
}
else if (len == 16) {
if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
status = __uc_get_frs(info->ucontext,
regid - UWX_REG_FR(0), 1, (fp_regval_t *)dp);
}
}
}
break;
}
if (status != 0)
return 0;
return len;
}

View File

@ -22,38 +22,91 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _KERNEL
#ifndef __UWX_SELF_INCLUDED
#define __UWX_SELF_INCLUDED 1
#include <signal.h>
#ifndef __UWX_INCLUDED
#include "uwx.h"
#endif /* __UWX_INCLUDED */
#if defined(__cplusplus)
#define __EXTERN_C extern "C"
#else
#define __EXTERN_C extern
#endif
struct uwx_self_info;
extern struct uwx_self_info *uwx_self_init_info(struct uwx_env *env);
__EXTERN_C struct uwx_self_info *uwx_self_init_info(struct uwx_env *env);
extern int uwx_self_free_info(struct uwx_self_info *info);
__EXTERN_C int uwx_self_free_info(struct uwx_self_info *info);
extern int uwx_self_init_context(struct uwx_env *env);
__EXTERN_C int uwx_self_init_context(struct uwx_env *env);
extern int uwx_self_init_from_sigcontext(
__EXTERN_C int uwx_self_init_from_sigcontext(
struct uwx_env *env,
struct uwx_self_info *info,
ucontext_t *ucontext);
extern int uwx_self_do_context_frame(
__EXTERN_C int uwx_self_do_context_frame(
struct uwx_env *env,
struct uwx_self_info *info);
extern int uwx_self_copyin(
__EXTERN_C int uwx_self_copyin(
int request,
char *loc,
uint64_t rem,
int len,
intptr_t tok);
extern int uwx_self_lookupip(
__EXTERN_C int uwx_self_lookupip(
int request,
uint64_t ip,
intptr_t tok,
uint64_t **resultp);
#define UWX_SELF_ERR_BADABICONTEXT (-101)
#undef __EXTERN_C
#if defined(__cplusplus)
class UnwindExpressSelf : public UnwindExpress {
public:
UnwindExpressSelf() {
info = uwx_self_init_info(env);
(void)uwx_register_callbacks(env, (intptr_t)info,
uwx_self_copyin, uwx_self_lookupip);
}
~UnwindExpressSelf() {
if (info != 0)
uwx_self_free_info(info);
info = 0;
}
int init_context() {
return uwx_self_init_context(env);
}
int init_context(ucontext_t *ucontext) {
return uwx_self_init_from_sigcontext(env, info, ucontext);
}
int do_context_frame() {
return uwx_self_do_context_frame(env, info);
}
protected:
struct uwx_self_info *info;
};
#endif /* __cplusplus */
#endif /* __UWX_SELF_INCLUDED */

View File

@ -1,24 +1,24 @@
/*
* Copyright (c) 2002,2003 Hewlett-Packard Company
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
// Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#ifdef _LP64
#define SWIZZLE add
@ -48,6 +48,21 @@ rTMP3 = r30
rTMP4 = r31
rTMP5 = r8
VALID_IP = 1
VALID_SP = 1 << 1
VALID_BSP = 1 << 2
VALID_CFM = 1 << 3
VALID_PREDS = 1 << 7
VALID_RNAT = 1 << 10
VALID_UNAT = 1 << 11
VALID_FPSR = 1 << 12
VALID_LC = 1 << 13
VALID_GRS = 0xf << 16
VALID_BRS = 0x1f << 20
VALID_BASIC4 = VALID_IP | VALID_SP | VALID_BSP | VALID_CFM
VALID_SPEC = VALID_PREDS | VALID_RNAT | VALID_UNAT | VALID_FPSR | VALID_LC
VALID_BITS = (VALID_BASIC4 | VALID_SPEC | VALID_GRS | VALID_BRS) << 32
.text
.proc uwx_self_init_context
.global uwx_self_init_context
@ -63,40 +78,42 @@ uwx_self_init_context:
mov rRP = b0
;;
mov rRSC = ar.rsc
add rENV1 = 120, rENV0 // rENV1 = &env->context.gr[0]
add rENV2 = 128, rENV0 // rENV2 = &env->context.gr[1]
add rENV1 = 136, rENV0 // rENV1 = &env->context.gr[0]
add rENV2 = 144, rENV0 // rENV2 = &env->context.gr[1]
;;
and rRSC0 = -4, rRSC // clear ar.rsc.mode
adds rNATP = 0x1f8, r0
mov rTMP1 = b1
;;
st8.spill [rENV1] = r4, 16 // env+120: r4
st8.spill [rENV2] = r5, 16 // env+128: r5
st8.spill [rENV1] = r4, 16 // env+136: r4
st8.spill [rENV2] = r5, 16 // env+144: r5
mov rTMP2 = b2
;;
st8.spill [rENV1] = r6, 16 // env+136: r6
st8.spill [rENV2] = r7, 16 // env+144: r7
st8.spill [rENV1] = r6, 16 // env+152: r6
st8.spill [rENV2] = r7, 16 // env+160: r7
mov rTMP3 = b3
;;
st8 [rENV1] = rTMP1, 16 // env+152: b1
st8 [rENV2] = rTMP2, 16 // env+160: b2
st8 [rENV1] = rTMP1, 16 // env+168: b1
st8 [rENV2] = rTMP2, 16 // env+176: b2
mov rTMP1 = b4
;;
st8 [rENV1] = rTMP3, 16 // env+168: b3
st8 [rENV2] = rTMP1, 16 // env+176: b4
st8 [rENV1] = rTMP3, 16 // env+184: b3
st8 [rENV2] = rTMP1, 16 // env+192: b4
mov rTMP2 = b5
;;
st8 [rENV1] = rTMP2 // env+184: b5
st8 [rENV1] = rTMP2 // env+200: b5
mov ar.rsc = rRSC0 // enforced lazy mode
add rENV1 = 8, rENV0
;;
mov rRNAT = ar.rnat // get copy of ar.rnat
movl rTMP1 = 0x7fec8f00000000 // valid_regs: ip, sp, bsp, cfm,
// preds, rnat, unat, lc, grs, brs
movl rTMP1 = VALID_BITS // valid_regs: ip, sp, bsp, cfm,
// preds, rnat, unat, fpsr,
// lc, grs, brs
// = 0x1ff3c8f00000000
;;
mov ar.rsc = rRSC // restore ar.rsc
mov rBSP = ar.bsp
add rTMP3 = 120, rENV0 // spill_loc = &env->context.gr[0]
add rTMP3 = 136, rENV0 // spill_loc = &env->context.gr[0]
;;
mov rTMP2 = ar.unat
nop
@ -143,7 +160,7 @@ uwx_self_init_context:
add rENV2 = 320, rENV2 // rENV2 = &env->context.rstate
;;
st8 [rENV1] = rTMP1 // env+112: lc
STPTR [rENV2] = r0 // env+512: env->rstate = 0
STPTR [rENV2] = r0 // env+528: env->rstate = 0
nop
;;
mov ar.unat = rUNAT

View File

@ -52,6 +52,19 @@ int uwx_restore_freg(struct uwx_env *env, uint64_t rstate,
int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat);
/* uwx_lookupip_hook: Hook routine so dynamic instrumentation */
/* tools can intercept Lookup IP events. When not */
/* intercepted, it just returns "Not found", so that */
/* the callback routine is invoked. */
/*ARGSUSED*/
int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp,
size_t uvecsize)
{
return UWX_LKUP_NOTFOUND;
}
/* uwx_get_frame_info: Gets unwind info for current frame */
static
int uwx_get_frame_info(struct uwx_env *env)
@ -59,10 +72,12 @@ int uwx_get_frame_info(struct uwx_env *env)
int i;
int status;
int cbstatus;
int cbcalled = 0;
uint64_t ip;
uint64_t *uvec;
uint64_t *rstate;
struct uwx_utable_entry uentry;
uint64_t uvecout[4];
uint64_t uvecout[UVECSIZE];
if (env->copyin == 0 || env->lookupip == 0)
return UWX_ERR_NOCALLBACKS;
@ -76,7 +91,14 @@ int uwx_get_frame_info(struct uwx_env *env)
/* current IP. If the predicate registers are valid, pass them */
/* in the uvec. */
/* When self-unwinding, we call a hook routine before the */
/* callback. If the application is running under control of */
/* a dynamic instrumentation tool, that tool will have an */
/* opportunity to intercept lookup IP requests. */
i = 0;
uvecout[i++] = UWX_KEY_VERSION;
uvecout[i++] = UWX_VERSION;
if (env->context.valid_regs & (1 << UWX_REG_PREDS)) {
uvecout[i++] = UWX_KEY_PREDS;
uvecout[i++] = env->context.special[UWX_REG_PREDS];
@ -84,8 +106,52 @@ int uwx_get_frame_info(struct uwx_env *env)
uvecout[i++] = UWX_KEY_END;
uvecout[i++] = 0;
uvec = uvecout;
cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP,
env->context.special[UWX_REG_IP], env->cb_token, &uvec);
cbstatus = UWX_LKUP_NOTFOUND;
ip = env->context.special[UWX_REG_IP];
env->remapped_ip = ip;
/* Call the hook routine. */
if (env->remote == 0)
cbstatus = uwx_lookupip_hook(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec,
sizeof(uvecout));
/* If the hook routine remapped the IP, use the new IP for */
/* the callback instead of the original IP. */
if (cbstatus == UWX_LKUP_REMAP) {
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
switch ((int)uvec[i]) {
case UWX_KEY_NEWIP:
ip = uvec[i+1];
break;
}
}
env->remapped_ip = ip;
}
/* Now call the callback routine unless the hook routine gave */
/* us all the info. */
if (cbstatus == UWX_LKUP_NOTFOUND || cbstatus == UWX_LKUP_REMAP) {
cbcalled = 1;
cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec);
}
/* If the callback routine remapped the IP, call it one more time */
/* with the new IP. */
if (cbstatus == UWX_LKUP_REMAP) {
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
switch ((int)uvec[i]) {
case UWX_KEY_NEWIP:
ip = uvec[i+1];
break;
}
}
env->remapped_ip = ip;
cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec);
}
/* If NOTFOUND, there's nothing we can do but return an error. */
@ -101,8 +167,9 @@ int uwx_get_frame_info(struct uwx_env *env)
/* block. */
else if (cbstatus == UWX_LKUP_UTABLE) {
status = uwx_search_utable(env, uvec, &uentry);
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
status = uwx_search_utable(env, ip, uvec, &uentry);
if (cbcalled)
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
if (status == UWX_OK)
status = uwx_decode_uinfo(env, &uentry, &rstate);
else if (status == UWX_ERR_NOUENTRY)
@ -111,6 +178,42 @@ int uwx_get_frame_info(struct uwx_env *env)
env->rstate = rstate;
}
/* If the callback returns an unwind info block, we can */
/* proceed directly to decoding the unwind information. */
else if (cbstatus == UWX_LKUP_UINFO) {
uentry.code_start = 0;
uentry.code_end = 0;
uentry.unwind_info = 0;
uentry.unwind_flags = 0;
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
switch ((int)uvec[i]) {
case UWX_KEY_UFLAGS:
uentry.unwind_flags = uvec[i+1];
break;
case UWX_KEY_UINFO:
uentry.unwind_info = uvec[i+1];
break;
case UWX_KEY_MODULE:
env->module_name =
uwx_alloc_str(env, (char *)(uvec[i+1]));
break;
case UWX_KEY_FUNC:
env->function_name =
uwx_alloc_str(env, (char *)(uvec[i+1]));
break;
case UWX_KEY_FUNCSTART:
uentry.code_start = uvec[i+1];
break;
}
}
if (cbcalled)
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
status = uwx_decode_uinfo(env, &uentry, &rstate);
if (status == UWX_OK)
env->rstate = rstate;
}
/* If the callback returns a frame description (in the form */
/* of an update vector), convert the update vector into a */
/* register state array, then invoke the callback again to */
@ -118,7 +221,8 @@ int uwx_get_frame_info(struct uwx_env *env)
else if (cbstatus == UWX_LKUP_FDESC) {
status = uwx_decode_uvec(env, uvec, &rstate);
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
if (cbcalled)
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
if (status == UWX_OK)
env->rstate = rstate;
}
@ -216,7 +320,7 @@ int uwx_get_sym_info(
/* Get the symbolic information from the lookup IP callback. */
if (env->function_name == 0) {
ip = env->context.special[UWX_REG_IP];
ip = env->remapped_ip;
i = 0;
if (env->function_offset >= 0) {
uvecout[i++] = UWX_KEY_FUNCSTART;
@ -225,8 +329,7 @@ int uwx_get_sym_info(
uvecout[i++] = UWX_KEY_END;
uvecout[i++] = 0;
uvec = uvecout;
cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS,
env->context.special[UWX_REG_IP], env->cb_token, &uvec);
cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS, ip, env->cb_token, &uvec);
if (cbstatus == UWX_LKUP_SYMINFO) {
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
@ -456,16 +559,35 @@ int uwx_step(struct uwx_env *env)
int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate)
{
while (*uvec != 0) {
switch ((int)*uvec++) {
int i;
int status;
status = uwx_default_rstate(env, rstate);
if (status != UWX_OK)
return status;
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
switch ((int)uvec[i]) {
case UWX_KEY_CONTEXT:
env->abi_context = (int)(*uvec++);
return UWX_ABI_FRAME;
env->abi_context = (int)(uvec[i+1]);
status = UWX_ABI_FRAME;
break;
case UWX_KEY_MODULE:
env->module_name =
uwx_alloc_str(env, (char *)(uvec[i+1]));
break;
case UWX_KEY_FUNC:
env->function_name =
uwx_alloc_str(env, (char *)(uvec[i+1]));
break;
case UWX_KEY_FUNCSTART:
env->function_offset = env->remapped_ip - uvec[i+1];
break;
default:
return UWX_ERR_CANTUNWIND;
}
}
return UWX_OK;
return status;
}

View File

@ -22,4 +22,9 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#define UVECSIZE 20 /* Size of uvec supplied by unwind engine */
/* for callback's use. */
extern int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok,
uint64_t **vecp, size_t uvecsize);
extern int uwx_restore_markers(struct uwx_env *env);

View File

@ -26,8 +26,9 @@ OTHER DEALINGS IN THE SOFTWARE.
#include "uwx_str.h"
#ifdef _KERNEL
static struct uwx_str_pool uwx_str_pool;
#define free(p) /* nullified */
#define malloc(sz) NULL
#define malloc(sz) ((sz == sizeof(uwx_str_pool)) ? &uwx_str_pool : NULL)
#endif
/*

View File

@ -22,13 +22,11 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _KERNEL
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/ttrace.h>
#include <sys/uc_access.h>
#include <machine/sys/uregs.h>
#endif
#include "uwx_env.h"
#include "uwx_context.h"
@ -238,7 +236,11 @@ int uwx_ttrace_copyin(
else if (request == UWX_COPYIN_RSTACK && len == 8) {
if (info->have_ucontext == 0 || rem < info->bspstore) {
status = ttrace(TT_PROC_RDDATA, info->pid, 0, rem, 8, (uint64_t)loc);
TRACE_SELF_COPYIN4(rem, len, dp)
TRACE_SELF_COPYIN8(rem, len, dp)
}
else if (info->have_ucontext == 0) {
status = ttrace(TT_LWP_RDRSEBS, info->pid, info->lwpid, rem, 8, (uint64_t)loc);
TRACE_SELF_COPYIN8(rem, len, dp)
}
else {
status = __uc_get_rsebs(&info->ucontext, (uint64_t *)rem, 1, dp);

View File

@ -22,9 +22,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _KERNEL
#include <signal.h>
#endif
struct uwx_ttrace_info;

View File

@ -93,8 +93,7 @@ int uwx_decode_uinfo(
/* to the current IP. This helps the client find */
/* the symbolic information. */
env->function_offset = env->context.special[UWX_REG_IP] -
uentry->code_start;
env->function_offset = env->remapped_ip - uentry->code_start;
/* Read the unwind info header using the copyin callback. */
/* (If we're reading a 32-bit unwind table, we need to */
@ -420,7 +419,7 @@ int uwx_decode_prologue(
b1 = uwx_get_byte(bstream);
if (b1 < 0)
return UWX_ERR_BADUDESC;
r = ((b0 & 0x3) << 1) | (b1 >> 7);
r = ((b0 & 0x7) << 1) | (b1 >> 7);
reg = b1 & 0x7f;
switch (r) {
case 0: /* psp_gr */

View File

@ -42,6 +42,7 @@ OTHER DEALINGS IN THE SOFTWARE.
int uwx_search_utable32(
struct uwx_env *env,
uint32_t ip,
uint32_t text_base,
uint32_t unwind_start,
uint32_t unwind_end,
@ -49,6 +50,7 @@ int uwx_search_utable32(
int uwx_search_utable64(
struct uwx_env *env,
uint64_t ip,
uint64_t text_base,
uint64_t unwind_start,
uint64_t unwind_end,
@ -59,13 +61,14 @@ int uwx_search_utable64(
int uwx_search_utable(
struct uwx_env *env,
uint64_t ip,
uint64_t *uvec,
struct uwx_utable_entry *uentry)
{
uint64_t text_base = 0;
uint64_t text_base;
uint64_t unwind_flags;
uint64_t unwind_start = 0;
uint64_t unwind_end = 0;
uint64_t unwind_start;
uint64_t unwind_end;
int keys;
int status;
@ -73,7 +76,10 @@ int uwx_search_utable(
/* Make sure all three required values are given. */
keys = 0;
text_base = 0;
unwind_flags = 0;
unwind_start = 0;
unwind_end = 0;
while (*uvec != 0) {
switch ((int)*uvec++) {
case UWX_KEY_TBASE:
@ -107,13 +113,14 @@ int uwx_search_utable(
if (unwind_flags & UNWIND_TBL_32BIT)
status = uwx_search_utable32(env,
(uint32_t) ip,
(uint32_t) text_base,
(uint32_t) unwind_start,
(uint32_t) unwind_end,
uentry);
else
status = uwx_search_utable64(env,
text_base, unwind_start, unwind_end, uentry);
ip, text_base, unwind_start, unwind_end, uentry);
return status;
}
@ -129,6 +136,7 @@ int uwx_search_utable(
int uwx_search_utable32(
struct uwx_env *env,
uint32_t ip,
uint32_t text_base,
uint32_t unwind_start,
uint32_t unwind_end,
@ -136,9 +144,8 @@ int uwx_search_utable32(
{
int lb;
int ub;
int mid = 0;
int mid;
int len;
uint32_t ip;
uint32_t code_start;
uint32_t code_end;
uint32_t unwind_info;
@ -146,7 +153,7 @@ int uwx_search_utable32(
/* Since the unwind table uses segment-relative offsets, convert */
/* the IP in the current context to a segment-relative offset. */
ip = env->context.special[UWX_REG_IP] - text_base;
ip -= text_base;
TRACE_T_SEARCH32(ip)
@ -155,12 +162,13 @@ int uwx_search_utable32(
lb = 0;
ub = (unwind_end - unwind_start) / (3 * WORDSZ);
mid = 0;
while (ub > lb) {
mid = (lb + ub) / 2;
len = COPYIN_UINFO_4((char *)&code_start,
(intptr_t)(unwind_start+mid*3*WORDSZ));
(uintptr_t)(unwind_start+mid*3*WORDSZ));
len += COPYIN_UINFO_4((char *)&code_end,
(intptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ));
(uintptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ));
if (len != 2 * WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap) {
@ -178,7 +186,7 @@ int uwx_search_utable32(
if (ub <= lb)
return UWX_ERR_NOUENTRY;
len = COPYIN_UINFO_4((char *)&unwind_info,
(intptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ));
(uintptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ));
if (len != WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap)
@ -200,6 +208,7 @@ int uwx_search_utable32(
int uwx_search_utable64(
struct uwx_env *env,
uint64_t ip,
uint64_t text_base,
uint64_t unwind_start,
uint64_t unwind_end,
@ -207,9 +216,8 @@ int uwx_search_utable64(
{
int lb;
int ub;
int mid = 0;
int mid;
int len;
uint64_t ip;
uint64_t code_start;
uint64_t code_end;
uint64_t unwind_info;
@ -217,13 +225,14 @@ int uwx_search_utable64(
/* Since the unwind table uses segment-relative offsets, convert */
/* the IP in the current context to a segment-relative offset. */
ip = env->context.special[UWX_REG_IP] - text_base;
ip -= text_base;
/* Standard binary search. */
/* Might modify this to do interpolation in the future. */
lb = 0;
ub = (unwind_end - unwind_start) / (3 * DWORDSZ);
mid = 0;
while (ub > lb) {
mid = (lb + ub) / 2;
len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ);

View File

@ -31,5 +31,6 @@ struct uwx_utable_entry {
extern int uwx_search_utable(
struct uwx_env *env,
uint64_t ip,
uint64_t *uvec,
struct uwx_utable_entry *uentry);