Update to BETA 7. Besides C++ support, which is irrelevant to us,
this version mostly has bugs fixes.
This commit is contained in:
parent
c2b1cc6d02
commit
9cc6463a07
352
sys/contrib/ia64/libuwx/src.diff
Normal file
352
sys/contrib/ia64/libuwx/src.diff
Normal 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);
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
336
sys/contrib/ia64/libuwx/src/uwx_self-new.c
Normal file
336
sys/contrib/ia64/libuwx/src/uwx_self-new.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user