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

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
marcel 2003-05-15 05:04:44 +00:00
commit 54ea024a38
29 changed files with 5320 additions and 0 deletions

View File

@ -0,0 +1,64 @@
# Makefile for IPF unwind express library, libuwx.
#
# To build a cross-unwind library (i.e., one hosted on a
# non-IPF, non-HP-UX system), omit the "self" callbacks
# and the dependency on libuca by setting SELFOBJS and
# SELFLIBS to empty strings.
AR = ar
RANLIB = :
# OTHERCFLAGS = -DDISABLE_TRACE # Disables trace output
# OTHERCFLAGS = +DD64 # Builds 64-bit library
OTHERCFLAGS =
CFLAGS = +W944 -O $(OTHERCFLAGS)
OBJS = uwx_bstream.o uwx_context.o uwx_env.o uwx_scoreboard.o \
uwx_step.o uwx_str.o uwx_swap.o uwx_trace.o uwx_uinfo.o \
uwx_utable.o
# SELFOBJS = # For cross-unwind library
SELFOBJS = uwx_self.o uwx_self_context.o uwx_ttrace.o
# SELFLIBS = # For cross-unwind library
SELFLIBS = -luca
libuwx.a: $(OBJS) $(SELFOBJS)
$(AR) rv libuwx.a $?
$(RANLIB) libuwx.a
libuwx.so: $(OBJS) $(SELFOBJS)
ld -b -o libuwx.so $(OBJS) $(SELFOBJS) $(SELFLIBS)
libuwx.sl: $(OBJS) $(SELFOBJS)
ld -b -o libuwx.sl $(OBJS) $(SELFOBJS) $(SELFLIBS)
uwx_bstream.o: uwx.h uwx_env.h uwx_bstream.h
uwx_context.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_trace.h
uwx_env.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_str.h uwx_trace.h
uwx_scoreboard.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_trace.h
uwx_step.o: uwx.h uwx_env.h uwx_context.h uwx_utable.h \
uwx_uinfo.h uwx_scoreboard.h uwx_str.h uwx_trace.h
uwx_str.o: uwx.h uwx_env.h uwx_str.h
uwx_swap.o: uwx.h uwx_env.h uwx_swap.h
uwx_trace.o: uwx.h uwx_env.h uwx_uinfo.h uwx_scoreboard.h uwx_trace.h
uwx_uinfo.o: uwx.h uwx_env.h uwx_uinfo.h uwx_utable.h \
uwx_scoreboard.h uwx_bstream.h uwx_trace.h
uwx_utable.o: uwx.h uwx_env.h uwx_utable.h uwx_swap.h uwx_trace.h
uwx_self.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_self.h
uwx_self_context.o: uwx_self_context.s
$(CC) -c $(CFLAGS) -o uwx_self_context.o uwx_self_context.s
uwx_ttrace.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_ttrace.h

View File

@ -0,0 +1,247 @@
/*
* 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.
*/
#ifndef _KERNEL
#include <stdlib.h>
#include <inttypes.h>
#else
#include <sys/param.h>
#include <sys/systm.h>
#endif
/* 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);
/* Allocate and initialize an unwind environment */
extern struct uwx_env *uwx_init(void);
/* Free an unwind environment */
extern 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);
/* Copy-in callback */
typedef int (*copyin_cb)(
int request, /* request code (see below) */
char *loc, /* local (destination) address */
uint64_t rem, /* remote (source) address */
int len, /* number of bytes to copy */
intptr_t tok); /* callback token */
/* Lookup IP callback */
typedef int (*lookupip_cb)(
int request, /* request code (see below) */
uint64_t ip, /* IP of current frame */
intptr_t tok, /* callback token */
uint64_t **vecp); /* parameter vector (in/out) */
/* Register copy-in and lookup IP callbacks */
extern 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(
struct uwx_env *env, /* unwind environment */
uint64_t ip, /* IP (instruction pointer) */
uint64_t sp, /* SP (stack pointer) */
uint64_t bsp, /* BSP (backing store pointer) */
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(
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(
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);
/* Step one frame */
extern int uwx_step(struct uwx_env *env);
/* Get symbol information, if available, for current frame */
extern 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(
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(
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(
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);
/* Return status codes for uwx_ APIs */
#define UWX_OK 0
#define UWX_BOTTOM 1 /* Hit bottom of stack */
#define UWX_ABI_FRAME 2 /* Hit ABI-dependent frame */
#define UWX_ERR_NOENV (-1) /* No uwx_env allocated */
#define UWX_ERR_IPNOTFOUND (-2) /* Lookup IP c/b returned NOTFOUND */
#define UWX_ERR_LOOKUPERR (-3) /* Lookup IP c/b returned ERR */
#define UWX_ERR_BADKEY (-4) /* Bad result vector key */
#define UWX_ERR_COPYIN_UTBL (-5) /* Error reading unwind table */
#define UWX_ERR_COPYIN_UINFO (-6) /* Error reading unwind info */
#define UWX_ERR_COPYIN_MSTK (-7) /* Error reading memory stack */
#define UWX_ERR_COPYIN_RSTK (-8) /* Error reading register stack */
#define UWX_ERR_COPYIN_REG (-9) /* Error reading context register */
#define UWX_ERR_NOUENTRY (-10) /* No unwind table entry for ip */
#define UWX_ERR_NOUDESC (-11) /* No unwind descriptor covers ip */
#define UWX_ERR_BADUDESC (-12) /* Bad unwind descriptor */
#define UWX_ERR_NOMEM (-13) /* Out of memory */
#define UWX_ERR_PROLOG_UF (-14) /* Prologue underflow */
#define UWX_ERR_UNDEFLABEL (-15) /* Undefined label in copy_state */
#define UWX_ERR_BADREGID (-16) /* Bad register identifier */
#define UWX_ERR_CANTUNWIND (-17) /* Can't unwind */
#define UWX_ERR_NOCALLBACKS (-18) /* No callbacks registered */
#define UWX_ERR_NOCONTEXT (-19) /* Context not initialized */
/* Request codes for copyin callback */
#define UWX_COPYIN_UINFO 1 /* Reading unwind info */
#define UWX_COPYIN_MSTACK 2 /* Reading memory stack */
#define UWX_COPYIN_RSTACK 3 /* Reading RSE backing store */
#define UWX_COPYIN_REG 4 /* Reading initial register state */
/* Request codes for lookup IP callback */
#define UWX_LKUP_LOOKUP 1 /* Lookup IP */
#define UWX_LKUP_FREE 2 /* Free result vector */
#define UWX_LKUP_SYMBOLS 3 /* Lookup symbolic information */
/* Return status codes for lookup IP callback */
#define UWX_LKUP_NOTFOUND 0 /* IP not found */
#define UWX_LKUP_ERR 1 /* Other error */
#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 */
/* The lookup IP callback receives a parameter vector, and returns */
/* one on success. This vector is a series of key/value pairs; each */
/* even-numbered slot is a key, and each odd-numbered slot is a */
/* corresponding value. The vector is terminated by a pair whose */
/* key is 0. */
#define UWX_KEY_END 0 /* End of vector */
/* Keys passed to lookup IP callback */
#define UWX_KEY_PREDS 1 /* Predicate registers */
/* 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_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. */
#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 */
/* Register identifiers */
/* For use in UWX_LKUP_FDESC result vectors and context access APIs. */
/* "no spill info": These regs aren't spilled directly, so */
/* result vectors must not describe these registers. */
/* The result vector must describe the related register or */
/* pseudo register instead (ip:rp, sp:psp, bsp/cfm:pfs). */
/* "pseudo register": Not a machine register, but treated as */
/* one for unwind purposes. */
#define UWX_REG_IP 0 /* ip (no spill info) */
#define UWX_REG_SP 1 /* sp (no spill info) */
#define UWX_REG_BSP 2 /* ar.bsp (no spill info) */
#define UWX_REG_CFM 3 /* cfm (no spill info) */
#define UWX_REG_RP 4 /* rp (pseudo-register) */
#define UWX_REG_PSP 5 /* psp (pseudo-register) */
#define UWX_REG_PFS 6 /* ar.pfs */
#define UWX_REG_PREDS 7 /* p0 - p63 */
#define UWX_REG_PRIUNAT 8 /* primary unat (pseudo-register) */
#define UWX_REG_BSPSTORE 9 /* ar.bspstore */
#define UWX_REG_RNAT 10 /* ar.rnat */
#define UWX_REG_UNAT 11 /* ar.unat */
#define UWX_REG_FPSR 12 /* ar.fpsr */
#define UWX_REG_LC 13 /* ar.lc */
#define UWX_REG_GR(gr) (0x100 | (gr))
#define UWX_REG_FR(fr) (0x200 | (fr))
#define UWX_REG_BR(br) (0x300 | (br))
/* Values corresponding to UWX_KEY_SPILL keys indicate the disposition */
/* of the spilled register -- either in the memory stack or in another */
/* register. The PSP register may also have a disposition of "SPPLUS", */
/* indicating that its value is SP plus a fixed constant. */
#define UWX_DISP_NONE 0 /* Not spilled */
#define UWX_DISP_SPPLUS(k) (1 | (k)) /* PSP = SP+constant */
#define UWX_DISP_SPREL(disp) (2 | (disp)) /* Spilled at [SP+disp] */
#define UWX_DISP_PSPREL(disp) (3 | (disp)) /* Spilled at [PSP+16-disp] */
#define UWX_DISP_REG(reg) (4 | ((reg) << 4)) /* Saved to another reg. */
/* The uwx_get_spill_loc() routine returns a spill location for a */
/* given register in the current context. It will return a disposition */
/* code of UWX_DISP_NONE, UWX_DISP_REG(reg), or one of the following */
/* to indicate that the spilled value can be found in the memory */
/* stack or the register stack backing store. */
#define UWX_DISP_MSTK(addr) (5 | (addr)) /* Spilled in mem. stack */
#define UWX_DISP_RSTK(addr) (6 | (addr)) /* Spilled in reg. stack */
/* Extract the disposition code, offset, address, or register id */
/* from a disposition returned from uwx_get_spill_loc(). */
/* Compare the extracted disp code against UWX_DISP_REG(0), etc. */
#define UWX_GET_DISP_CODE(disp) ((int)(disp) & 0x07)
#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)

View File

@ -0,0 +1,179 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_bstream.h"
/* uwx_init_bstream: initialize a byte stream for reading */
void uwx_init_bstream(
struct uwx_bstream *bstream,
struct uwx_env *env,
uint64_t source,
unsigned int len,
int request)
{
bstream->buf = 0;
if (env->remote) {
bstream->source = source;
bstream->bufp = (unsigned char *) &bstream->buf;
bstream->nbuf = 0;
bstream->copyin = env->copyin;
bstream->cb_token = env->cb_token;
bstream->request = request;
}
else {
bstream->source = 0;
bstream->bufp = (unsigned char *) source;
bstream->nbuf = len;
bstream->copyin = 0;
bstream->cb_token = 0;
bstream->request = 0;
}
bstream->ntotal = len;
bstream->peekc = -1;
}
/* uwx_get_byte: read the next byte from the byte stream */
int uwx_get_byte(struct uwx_bstream *bstream)
{
int len;
int n;
int b;
if (bstream->peekc >= 0) {
b = bstream->peekc;
bstream->peekc = -1;
return b;
}
if (bstream->ntotal <= 0)
return -1;
if (bstream->nbuf <= 0) {
if (bstream->source & 0x7)
len = sizeof(uint32_t);
else
len = sizeof(uint64_t);
n = (*bstream->copyin)(bstream->request, (char *)&bstream->buf,
bstream->source, len, bstream->cb_token);
if (n != len)
return -1;
bstream->bufp = (unsigned char *) &bstream->buf;
bstream->nbuf = n;
bstream->source += n;
}
b = *bstream->bufp++;
bstream->nbuf--;
bstream->ntotal--;
return b;
}
/* uwx_unget_byte: push a byte back onto the byte stream */
int uwx_unget_byte(struct uwx_bstream *bstream, int b)
{
bstream->peekc = b;
return 0;
}
/* uwx_get_uleb128: read a ULEB128 value from the byte stream */
int uwx_get_uleb128(struct uwx_bstream *bstream, uint64_t *valp)
{
uint64_t val;
int i;
int b;
b = uwx_get_byte(bstream);
val = (uint64_t)(b & 0x7f) << 56;
for (i = 0; i < 8; i++) {
val = val >> 7;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 56;
}
}
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 63;
}
if (b & 0x80)
return -1;
*valp = val;
return 0;
}
#if 0
int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp)
{
uint64_t val;
int b;
b = uwx_get_byte(bstream);
val = b & 0x7f;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 7;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 14;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 21;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 28;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 35;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 42;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 49;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 56;
if (b & 0x80) {
b = uwx_get_byte(bstream);
val |= (uint64_t)(b & 0x7f) << 63;
if (b & 0x80)
return -1;
}
}
}
}
}
}
}
}
}
*valp = val;
return 0;
}
#endif

View File

@ -0,0 +1,57 @@
/*
* 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.
*/
struct uwx_bstream {
copyin_cb copyin;
intptr_t cb_token;
uint64_t source;
uint64_t buf;
unsigned char *bufp;
int nbuf;
unsigned int ntotal;
int request;
int peekc;
};
/* uwx_init_bstream: initialize a byte stream for reading */
extern void uwx_init_bstream(
struct uwx_bstream *bstream,
struct uwx_env *env,
uint64_t source,
unsigned int len,
int request);
/* uwx_get_byte: read the next byte from the byte stream */
extern int uwx_get_byte(struct uwx_bstream *bstream);
/* uwx_unget_byte: push a byte back onto the byte stream */
extern int uwx_unget_byte(struct uwx_bstream *bstream, int b);
/* uwx_get_uleb128: read a ULEB128 value from the byte stream */
extern int uwx_get_uleb128(struct uwx_bstream *bstream, uint64_t *val);

View File

@ -0,0 +1,329 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_context.h"
#include "uwx_scoreboard.h"
#include "uwx_trace.h"
int uwx_init_context(
struct uwx_env *env,
uint64_t ip,
uint64_t sp,
uint64_t bsp,
uint64_t cfm)
{
int i;
if (env == 0)
return UWX_ERR_NOENV;
env->context.special[UWX_REG_IP] = ip;
env->context.special[UWX_REG_SP] = sp;
env->context.special[UWX_REG_BSP] = bsp;
env->context.special[UWX_REG_CFM] = cfm;
for (i = UWX_REG_RP; i < NSPECIALREG; i++)
env->context.special[i] = 0;
for (i = 0; i < NPRESERVEDGR; i++)
env->context.gr[i] = 0;
env->context.valid_regs = VALID_BASIC4;
env->rstate = 0;
(void)uwx_init_history(env);
return UWX_OK;
}
int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
{
int status;
int sor;
int rrb_gr;
uint64_t bsp;
int n;
if (env == 0)
return UWX_ERR_NOENV;
status = UWX_OK;
if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
*valp = env->context.special[regid];
else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
(env->context.valid_regs &
(1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
*valp = env->context.gr[regid - UWX_REG_GR(4)];
else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
if (env->copyin == 0)
return UWX_ERR_NOCALLBACKS;
bsp = env->context.special[UWX_REG_BSP];
TRACE_C_GET_REG(regid, bsp)
regid -= UWX_REG_GR(32);
sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
if (sor != 0 && rrb_gr != 0 && regid < sor) {
TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
regid = (regid + rrb_gr) % sor;
}
bsp = uwx_add_to_bsp(bsp, regid);
n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
bsp, DWORDSZ, env->cb_token);
if (n != DWORDSZ)
status = UWX_ERR_COPYIN_RSTK;
}
else if (regid == UWX_REG_GR(0))
*valp = 0;
else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
(env->context.valid_regs &
(1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
*valp = env->context.br[regid - UWX_REG_BR(1)];
else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(5) &&
(env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
}
else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_BR(31) &&
(env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
}
else if ( (regid < NSPECIALREG) ||
(regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
if (env->copyin == 0)
return UWX_ERR_NOCALLBACKS;
n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
regid, DWORDSZ, env->cb_token);
if (n != DWORDSZ)
status = UWX_ERR_COPYIN_REG;
}
else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(127)) {
if (env->copyin == 0)
return UWX_ERR_NOCALLBACKS;
n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
regid, 2*DWORDSZ, env->cb_token);
if (n != 2*DWORDSZ)
status = UWX_ERR_COPYIN_REG;
}
else if (regid == UWX_REG_FR(0)) {
valp[0] = 0;
valp[1] = 0;
}
else if (regid == UWX_REG_FR(1)) {
valp[0] = 0x000000000000ffffULL;
valp[1] = 0x8000000000000000ULL;
}
else
status = UWX_ERR_BADREGID;
return status;
}
int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
{
int status;
int sor;
int rrb_gr;
uint64_t bsp;
uint64_t natcollp;
uint64_t natcoll;
int n;
if (env == 0)
return UWX_ERR_NOENV;
status = UWX_OK;
if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
(env->context.valid_regs &
(1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
*natp = (env->context.special[UWX_REG_PRIUNAT] >>
(regid - UWX_REG_GR(4)) ) & 0x01;
}
else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
if (env->copyin == 0)
return UWX_ERR_NOCALLBACKS;
bsp = env->context.special[UWX_REG_BSP];
regid -= UWX_REG_GR(32);
sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
if (sor != 0 && rrb_gr != 0 && regid < sor) {
regid = (regid + rrb_gr) % sor;
}
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_RNAT, DWORDSZ, env->cb_token);
else
n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
bsp, DWORDSZ, env->cb_token);
if (n != DWORDSZ)
return UWX_ERR_COPYIN_RSTK;
*natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
}
else if (regid == UWX_REG_GR(0))
*natp = 0;
else
status = UWX_ERR_BADREGID;
return status;
}
int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
{
int status;
int sor;
int rrb_gr;
uint64_t bsp;
if (env == 0)
return UWX_ERR_NOENV;
status = UWX_OK;
if (regid < NSPECIALREG)
*dispp = env->history.special[regid];
else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
*dispp = env->history.gr[regid - UWX_REG_GR(4)];
else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
bsp = env->context.special[UWX_REG_BSP];
regid -= UWX_REG_GR(32);
sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
if (sor != 0 && rrb_gr != 0 && regid < sor)
regid = (regid + rrb_gr) % sor;
bsp = uwx_add_to_bsp(bsp, regid);
*dispp = UWX_DISP_RSTK(bsp);
}
else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
*dispp = env->history.br[regid - UWX_REG_BR(1)];
else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
*dispp = env->history.fr[regid - UWX_REG_FR(2)];
else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
*dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
(regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
*dispp = UWX_DISP_REG(regid);
else
status = UWX_ERR_BADREGID;
return status;
}
int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
{
int status;
if (env == 0)
return UWX_ERR_NOENV;
if (regid < NSPECIALREG) {
env->context.special[regid] = val;
env->context.valid_regs |= 1 << regid;
status = UWX_OK;
}
else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
env->context.gr[regid - UWX_REG_GR(4)] = val;
env->context.valid_regs |=
1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
status = UWX_OK;
}
else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
status = UWX_ERR_BADREGID;
}
else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
env->context.br[regid - UWX_REG_BR(1)] = val;
env->context.valid_regs |=
1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
status = UWX_OK;
}
else
status = UWX_ERR_BADREGID;
return status;
}
int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
{
if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
regid -= UWX_REG_FR(2);
else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
regid -= UWX_REG_FR(16) - 4;
else
return UWX_ERR_BADREGID;
env->context.fr[regid].part0 = val[0];
env->context.fr[regid].part1 = val[1];
env->context.valid_frs |= 1 << regid;
env->nsbreg = NSBREG;
return UWX_OK;
}
uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
{
int bias;
/*
* Here's a picture of the backing store as modeled in
* the computations below. "X" marks NaT collections at
* every 0x1f8 mod 0x200 address.
*
* To make the NaT adjustments easier, we bias the current bsp
* by enough slots to place it at the previous NaT collection.
* Then we need to add the bias to the number of slots,
* then add 1 for every 63 slots to account for NaT collections.
* Then we can remove the bias again and add the adjusted
* number of slots to the bsp.
*
* 0 1f8 3f8
* +---------------------------------------------------------------+
* | X X|
* +---------------------------------------------------------------+
* <-------- bias -------->
* <--- 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.
*
* 0 1f8 3f8
* +---------------------------------------------------------------+
* | X X|
* +---------------------------------------------------------------+
* <------- 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;
}
return bsp + nslots * DWORDSZ;
}

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
extern uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots);

View File

@ -0,0 +1,168 @@
/*
* 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.
*/
#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_str.h"
#include "uwx_trace.h"
alloc_cb uwx_allocate_cb = 0;
free_cb uwx_free_cb = 0;
int uwx_register_alloc_cb(alloc_cb alloc, free_cb free)
{
uwx_allocate_cb = alloc;
uwx_free_cb = free;
return UWX_OK;
}
int uwx_init_history(struct uwx_env *env)
{
int i;
if (env == 0)
return UWX_ERR_NOENV;
for (i = 0; i < NSPECIALREG; i++)
env->history.special[i] = UWX_DISP_REG(i);;
for (i = 0; i < NPRESERVEDGR; i++)
env->history.gr[i] = UWX_DISP_REG(UWX_REG_GR(4+i));
for (i = 0; i < NPRESERVEDBR; i++)
env->history.br[i] = UWX_DISP_REG(UWX_REG_BR(1+i));
for (i = 0; i < 4; i++)
env->history.fr[i] = UWX_DISP_REG(UWX_REG_FR(2+i));
for ( ; i < NPRESERVEDFR; i++)
env->history.fr[i] = UWX_DISP_REG(UWX_REG_FR(12+i));
return UWX_OK;
}
struct uwx_env *uwx_init()
{
int i;
struct uwx_env *env;
if (uwx_allocate_cb == 0)
env = (struct uwx_env *) malloc(sizeof(struct uwx_env));
else
env = (struct uwx_env *) (*uwx_allocate_cb)(sizeof(struct uwx_env));
if (env != 0) {
env->context.valid_regs = 0;
env->context.valid_frs = 0;
for (i = 0; i < NSPECIALREG; i++)
env->context.special[i] = 0;
for (i = 0; i < NPRESERVEDGR; i++)
env->context.gr[i] = 0;
for (i = 0; i < NPRESERVEDBR; i++)
env->context.br[i] = 0;
for (i = 0; i < NPRESERVEDFR; i++) {
env->context.fr[i].part0 = 0;
env->context.fr[i].part1 = 0;
}
env->rstate = 0;
env->function_offset = 0;
(void)uwx_init_history(env);
env->allocate_cb = uwx_allocate_cb;
env->free_cb = uwx_free_cb;
env->free_scoreboards = 0;
env->used_scoreboards = 0;
env->labeled_scoreboards = 0;
(void)uwx_init_str_pool(env);
env->module_name = 0;
env->function_name = 0;
env->cb_token = 0;
env->copyin = 0;
env->lookupip = 0;
env->remote = 0;
env->byte_swap = 0;
env->abi_context = 0;
env->nsbreg = NSBREG_NOFR;
env->nscoreboards = 0;
env->trace = 0;
TRACE_INIT
for (i = 0; i < NSCOREBOARDS; i++)
(void) uwx_alloc_scoreboard(env);
}
return env;
}
int uwx_set_remote(struct uwx_env *env, int is_big_endian_target)
{
int is_big_endian_host;
char *p;
if (env == 0)
return UWX_ERR_NOENV;
env->remote = 1;
is_big_endian_host = 1;
p = (char *)&is_big_endian_host;
*p = 0;
if (is_big_endian_target == is_big_endian_host)
env->byte_swap = 0;
else
env->byte_swap = 1;
return UWX_OK;
}
int uwx_register_callbacks(
struct uwx_env *env,
intptr_t tok,
copyin_cb copyin,
lookupip_cb lookupip)
{
if (env == 0)
return UWX_ERR_NOENV;
env->cb_token = tok;
env->copyin = copyin;
env->lookupip = lookupip;
return UWX_OK;
}
int uwx_get_abi_context_code(struct uwx_env *env)
{
if (env == 0)
return UWX_ERR_NOENV;
return env->abi_context;
}
int uwx_free(struct uwx_env *env)
{
if (env != 0) {
uwx_free_scoreboards(env);
uwx_free_str_pool(env);
if (env->free_cb == 0)
free((void *)env);
else
(*env->free_cb)((void *)env);
}
return UWX_OK;
}

View File

@ -0,0 +1,100 @@
/*
* 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.
*/
#include "uwx.h"
#define WORDSZ 4
#define DWORDSZ 8
#define BUNDLESZ 16
#define SLOTSPERBUNDLE 3
#define UNWIND_TBL_32BIT 0x8000000000000000LL
#define UNW_VER(x) ((x) >> 48)
#define UNW_FLAG_MASK 0x0000ffff00000000LL
#define UNW_FLAG_EHANDLER 0x0000000100000000LL
#define UNW_FLAG_UHANDLER 0x0000000200000000LL
#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffLL)
struct uwx_scoreboard;
#define NSCOREBOARDS 8 /* Initial allocation of scoreboards */
#define NSPECIALREG 14
#define NPRESERVEDGR 4
#define NPRESERVEDBR 5
#define NPRESERVEDFR 20
struct uwx_fpreg {
uint64_t part0;
uint64_t part1;
};
struct uwx_context {
unsigned int valid_regs;
unsigned int valid_frs;
uint64_t special[NSPECIALREG];
uint64_t gr[NPRESERVEDGR];
uint64_t br[NPRESERVEDBR];
struct uwx_fpreg fr[NPRESERVEDFR];
};
#define VALID_GR_SHIFT NSPECIALREG
#define VALID_BR_SHIFT (NSPECIALREG + NPRESERVEDGR)
#define VALID_BASIC4 0x0f /* IP, SP, BSP, PFS */
struct uwx_history {
uint64_t special[NSPECIALREG];
uint64_t gr[NPRESERVEDGR];
uint64_t br[NPRESERVEDBR];
uint64_t fr[NPRESERVEDFR];
};
struct uwx_str_pool;
struct uwx_env {
struct uwx_context context;
uint64_t *rstate;
int64_t function_offset;
struct uwx_history history;
alloc_cb allocate_cb;
free_cb free_cb;
struct uwx_scoreboard *free_scoreboards;
struct uwx_scoreboard *used_scoreboards;
struct uwx_scoreboard *labeled_scoreboards;
struct uwx_str_pool *string_pool;
char *module_name;
char *function_name;
intptr_t cb_token;
copyin_cb copyin;
lookupip_cb lookupip;
int remote;
int byte_swap;
int abi_context;
int nsbreg;
int nscoreboards;
int trace;
};
extern alloc_cb uwx_allocate_cb;
extern free_cb uwx_free_cb;

View File

@ -0,0 +1,277 @@
/*
* 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.
*/
#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"
struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
{
struct uwx_scoreboard *sb;
int i;
if (env->free_scoreboards != 0) {
sb = env->free_scoreboards;
env->free_scoreboards = sb->nextfree;
TRACE_B_REUSE(sb->id)
}
else {
if (env->allocate_cb == 0)
sb = (struct uwx_scoreboard *)
malloc(sizeof(struct uwx_scoreboard));
else
sb = (struct uwx_scoreboard *)
(*env->allocate_cb)(sizeof(struct uwx_scoreboard));
if (sb == 0)
return 0;
sb->id = env->nscoreboards++;
sb->nextused = env->used_scoreboards;
env->used_scoreboards = sb;
TRACE_B_ALLOC(sb->id)
}
sb->nextstack = 0;
sb->nextlabel = 0;
for (i = 0; i < env->nsbreg; i++)
sb->rstate[i] = UWX_DISP_NONE;
sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0));
sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_PFS);
sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_UNAT);
sb->label = 0;
return sb;
}
static
void uwx_reclaim_scoreboards(struct uwx_env *env)
{
struct uwx_scoreboard *sb;
env->free_scoreboards = 0;
for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) {
sb->nextfree = env->free_scoreboards;
env->free_scoreboards = sb;
}
env->labeled_scoreboards = 0;
}
struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env)
{
struct uwx_scoreboard *sb;
uwx_reclaim_scoreboards(env);
sb = uwx_alloc_scoreboard(env);
return sb;
}
struct uwx_scoreboard *uwx_new_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *prevsb)
{
int i;
struct uwx_scoreboard *sb;
sb = uwx_alloc_scoreboard(env);
if (sb == 0)
return 0;
sb->nextstack = prevsb;
for (i = 0; i < env->nsbreg; i++)
sb->rstate[i] = prevsb->rstate[i];
return sb;
}
struct uwx_scoreboard *uwx_pop_scoreboards(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int ecount)
{
struct uwx_scoreboard *next;
while (ecount > 0) {
next = sb->nextstack;
TRACE_B_POP(sb->id)
sb->nextstack = 0;
sb->nextfree = env->free_scoreboards;
env->free_scoreboards = sb;
sb = next;
if (sb == 0)
return 0;
ecount--;
}
return sb;
}
int uwx_label_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int label)
{
struct uwx_scoreboard *new;
struct uwx_scoreboard *back;
struct uwx_scoreboard *next;
int i;
TRACE_B_LABEL(label)
/* Copy the current stack, storing reverse links */
/* in the "nextstack" field. */
back = 0;
new = 0;
while (sb != 0) {
TRACE_B_LABEL_COPY(sb->id)
new = uwx_alloc_scoreboard(env);
if (new == 0)
return UWX_ERR_NOMEM;
new->nextstack = back;
for (i = 0; i < env->nsbreg; i++)
new->rstate[i] = sb->rstate[i];
sb = sb->nextstack;
back = new;
}
/* The "new" pointer now points to the bottom of the new stack, */
/* and the "nextstack" links lead towards the top. */
/* Now go back down the stack, reversing the stack links to their */
/* proper direction. */
back = 0;
while (new != 0) {
next = new->nextstack;
new->nextstack = back;
TRACE_B_LABEL_REVERSE(back, new)
back = new;
new = next;
}
/* The "back" pointer now points to the top of the stack. */
back->label = label;
back->nextlabel = env->labeled_scoreboards;
env->labeled_scoreboards = back;
return UWX_OK;
}
int uwx_copy_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int label)
{
struct uwx_scoreboard *next;
struct uwx_scoreboard *next2;
struct uwx_scoreboard *lsb;
struct uwx_scoreboard *new;
struct uwx_scoreboard *back;
int i;
TRACE_B_COPY(label, sb->id)
/* Free the existing stack. */
next = sb->nextstack;
while (next != 0) {
TRACE_B_COPY_FREE(next->id)
next2 = next->nextstack;
next->nextstack = 0;
next->nextfree = env->free_scoreboards;
env->free_scoreboards = next;
next = next2;
}
/* Find the scoreboard with the requested label. */
for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) {
if (lsb->label == label)
break;
}
if (lsb == 0)
return UWX_ERR_UNDEFLABEL;
TRACE_B_COPY_FOUND(lsb->id)
/* Copy the labeled scoreboard. */
sb->nextstack = 0;
sb->nextlabel = 0;
for (i = 0; i < env->nsbreg; i++)
sb->rstate[i] = lsb->rstate[i];
sb->label = 0;
/* 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);
if (new == 0)
return UWX_ERR_NOMEM;
new->nextstack = back;
for (i = 0; i < env->nsbreg; i++)
new->rstate[i] = next->rstate[i];
back = new;
}
/* The "new" pointer now points to the bottom of the new stack, */
/* and the "nextstack" links lead towards the top. */
/* Now go back down the stack, reversing the nextstack links to their */
/* proper direction. */
back = 0;
while (new != 0) {
next = new->nextstack;
new->nextstack = back;
TRACE_B_COPY_REVERSE(back, new)
back = new;
new = next;
}
return UWX_OK;
}
void uwx_free_scoreboards(struct uwx_env *env)
{
struct uwx_scoreboard *sb;
struct uwx_scoreboard *next;
for (sb = env->used_scoreboards; sb != 0; sb = next) {
TRACE_B_FREE(sb->id)
next = sb->nextused;
if (env->free_cb == 0)
free((void *)sb);
else
(*env->free_cb)((void *)sb);
}
env->free_scoreboards = 0;
env->used_scoreboards = 0;
env->labeled_scoreboards = 0;
}

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
#define NSB_SPECIAL 9
#define NSB_GR 4
#define NSB_BR 5
#define NSB_FR 20
#define SBREG_RP 0
#define SBREG_PSP 1
#define SBREG_PFS 2
#define SBREG_PREDS 3
#define SBREG_UNAT 4
#define SBREG_PRIUNAT 5
#define SBREG_RNAT 6
#define SBREG_LC 7
#define SBREG_FPSR 8
#define SBREG_GR (0 + NSB_SPECIAL)
#define SBREG_BR (SBREG_GR + NSB_GR)
#define SBREG_FR (SBREG_BR + NSB_BR)
#define NSBREG_NOFR (NSB_SPECIAL + NSB_GR + NSB_BR)
#define NSBREG (NSB_SPECIAL + NSB_GR + NSB_BR + NSB_FR)
struct uwx_scoreboard {
struct uwx_scoreboard *nextused;
struct uwx_scoreboard *nextfree;
struct uwx_scoreboard *nextstack;
struct uwx_scoreboard *nextlabel;
uint64_t rstate[NSBREG];
int label;
int id;
};
extern struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env);
extern struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env);
extern struct uwx_scoreboard *uwx_new_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *prevsb);
extern struct uwx_scoreboard *uwx_pop_scoreboards(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int ecount);
extern int uwx_label_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int label);
extern int uwx_copy_scoreboard(
struct uwx_env *env,
struct uwx_scoreboard *sb,
int label);
extern void uwx_free_scoreboards(struct uwx_env *env);

View File

@ -0,0 +1,261 @@
/*
* 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.
*/
#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"
#include "uwx_trace.h"
#include "uwx_self.h"
#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */
struct uwx_self_info {
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 uwx_self_info *uwx_self_init_info(struct uwx_env *env)
{
struct uwx_self_info *info;
if (env->allocate_cb == 0)
info = (struct uwx_self_info *)
malloc(sizeof(struct uwx_self_info));
else
info = (struct uwx_self_info *)
(*env->allocate_cb)(sizeof(struct uwx_self_info));
if (info == 0)
return 0;
info->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;
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;
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_ar(ucontext, 17, &bsp);
status = __uc_get_ar(ucontext, 18, &info->bspstore);
status = __uc_get_ar(ucontext, 66, &ec);
status = __uc_get_cfm(ucontext, &cfm);
cfm |= ec << 52;
if (reason != 0)
bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
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;
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_PFS:
status = __uc_get_ar(info->ucontext, 64, dp);
break;
case UWX_REG_PREDS:
status = __uc_get_prs(info->ucontext, dp);
break;
case UWX_REG_RNAT:
status = __uc_get_ar(info->ucontext, 19, dp);
break;
case UWX_REG_UNAT:
status = __uc_get_ar(info->ucontext, 36, dp);
break;
case UWX_REG_FPSR:
status = __uc_get_ar(info->ucontext, 40, dp);
break;
case UWX_REG_LC:
status = __uc_get_ar(info->ucontext, 65, dp);
break;
default:
return 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;
}
return len;
}
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 handle;
struct load_module_desc desc;
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 {
handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0);
if (handle == 0)
return UWX_LKUP_ERR;
unwind_base = (uint64_t *) desc.unwind_base;
TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base)
i = 0;
rvec = info->rvec;
rvec[i++] = UWX_KEY_TBASE;
rvec[i++] = desc.text_base;
rvec[i++] = UWX_KEY_UFLAGS;
rvec[i++] = unwind_base[0];
rvec[i++] = UWX_KEY_USTART;
rvec[i++] = desc.text_base + unwind_base[1];
rvec[i++] = UWX_KEY_UEND;
rvec[i++] = desc.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;
}
}

View File

@ -0,0 +1,57 @@
/*
* 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.
*/
#ifndef _KERNEL
#include <signal.h>
#endif
struct uwx_self_info;
extern struct uwx_self_info *uwx_self_init_info(struct uwx_env *env);
extern int uwx_self_free_info(struct uwx_self_info *info);
extern int uwx_self_init_context(struct uwx_env *env);
extern 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(
struct uwx_env *env,
struct uwx_self_info *info);
extern int uwx_self_copyin(
int request,
char *loc,
uint64_t rem,
int len,
intptr_t tok);
extern int uwx_self_lookupip(
int request,
uint64_t ip,
intptr_t tok,
uint64_t **resultp);
#define UWX_SELF_ERR_BADABICONTEXT (-101)

View File

@ -0,0 +1,153 @@
/*
* 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.
*/
#ifdef _LP64
#define SWIZZLE add
#define STPTR st8
#else
#define SWIZZLE addp4
#define STPTR st4
#endif
rRP = r14
rPFS = r15
rUNAT = r16
rRNAT = r17
rENV0 = r18
rENV1 = r19
rENV2 = r20
rNSLOT = r21
rBSP = r22
rPBSP = r23
rRSC = r24
rNATP = r25
rBIAS = r26
rRSC0 = r27
rTMP1 = r28
rTMP2 = r29
rTMP3 = r30
rTMP4 = r31
rTMP5 = r8
.text
.proc uwx_self_init_context
.global uwx_self_init_context
uwx_self_init_context:
.prologue
alloc rPFS = ar.pfs, 1, 0, 0, 0
mov rUNAT = ar.unat
.body
SWIZZLE rENV0 = r0, r32 // rENV0 = &env
;;
flushrs
extr.u rNSLOT = rPFS, 7, 7 // nslots = pfs.sol
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]
;;
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
mov rTMP2 = b2
;;
st8.spill [rENV1] = r6, 16 // env+136: r6
st8.spill [rENV2] = r7, 16 // env+144: r7
mov rTMP3 = b3
;;
st8 [rENV1] = rTMP1, 16 // env+152: b1
st8 [rENV2] = rTMP2, 16 // env+160: b2
mov rTMP1 = b4
;;
st8 [rENV1] = rTMP3, 16 // env+168: b3
st8 [rENV2] = rTMP1, 16 // env+176: b4
mov rTMP2 = b5
;;
st8 [rENV1] = rTMP2 // env+184: 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
;;
mov ar.rsc = rRSC // restore ar.rsc
mov rBSP = ar.bsp
add rTMP3 = 120, rENV0 // spill_loc = &env->context.gr[0]
;;
mov rTMP2 = ar.unat
nop
extr.u rTMP3 = rTMP3, 3, 6 // bitpos = spill_loc{8:3}
;;
or rNATP = rBSP, rNATP // natp = bsp | 0x1f8
sub rTMP4 = 64, rTMP3 // (64 - bitpos)
shr rTMP5 = rTMP2, rTMP3 // (unat >> bitpos)
;;
sub rBIAS = rNATP, rBSP // bias = (natp - bsp) ...
nop
shl rTMP2 = rTMP2, rTMP4 // (unat << (64 - bitpos))
;;
or rTMP2 = rTMP2, rTMP5 // rotate_right(unat, bitpos)
extr.u rBIAS = rBIAS, 3, 6 // ... div 8
mov rTMP4 = pr
;;
st8 [rENV0] = rTMP1, 16 // env+0: valid_regs mask
st8 [rENV1] = rRP, 24 // env+8: ip (my rp)
add rBIAS = rNSLOT, rBIAS // bias += nslots
;;
cmp.lt p6, p0 = 63, rBIAS // if (63 < bias) ...
cmp.lt p7, p0 = 126, rBIAS // if (126 < bias) ...
nop
;;
st8 [rENV0] = r12, 48 // env+16: sp
st8 [rENV1] = rPFS, 40 // env+32: cfm (my pfs)
(p6) add rNSLOT = 1, rNSLOT // ... nslots++
;;
st8 [rENV0] = rTMP4, 24 // env+64: preds
st8 [rENV1] = rTMP2, 24 // env+72: priunat
(p7) add rNSLOT = 1, rNSLOT // ... nslots++
;;
st8 [rENV0] = rRNAT, -64 // env+88: rnat
st8 [rENV1] = rUNAT, 8 // env+96: unat
dep.z rTMP3 = rNSLOT, 3, 7 // (nslots << 3)
;;
sub rPBSP = rBSP, rTMP3 // prev_bsp = bsp - (nslots << 3)
mov rTMP3 = ar.fpsr
mov rTMP1 = ar.lc
;;
st8 [rENV0] = rPBSP // env+24: bsp (my prev bsp)
st8 [rENV1] = rTMP3, 8 // env+104: fpsr
add rENV2 = 320, rENV2 // rENV2 = &env->context.rstate
;;
st8 [rENV1] = rTMP1 // env+112: lc
STPTR [rENV2] = r0 // env+512: env->rstate = 0
nop
;;
mov ar.unat = rUNAT
mov ret0 = r0 // return UWX_OK
br.ret.sptk b0
.endp

View File

@ -0,0 +1,525 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_context.h"
#include "uwx_utable.h"
#include "uwx_uinfo.h"
#include "uwx_scoreboard.h"
#include "uwx_str.h"
#include "uwx_trace.h"
/*
* uwx_step.c
*
* This file contains the routines for stepping from one frame
* into its callers frame. The context for the current frame
* is maintained inside the current unwind environment
* (struct uwx_env), and is updated with each call to
* uwx_step() to refer to the previous frame.
*/
/* Forward Declarations */
int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate);
int uwx_restore_reg(struct uwx_env *env, uint64_t rstate,
uint64_t *valp, uint64_t *histp);
int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat);
/* uwx_get_frame_info: Gets unwind info for current frame */
static
int uwx_get_frame_info(struct uwx_env *env)
{
int i;
int status;
int cbstatus;
uint64_t *uvec;
uint64_t *rstate;
struct uwx_utable_entry uentry;
uint64_t uvecout[4];
if (env == 0)
return UWX_ERR_NOENV;
if (env->copyin == 0 || env->lookupip == 0)
return UWX_ERR_NOCALLBACKS;
if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
return UWX_ERR_NOCONTEXT;
env->function_offset = -1LL;
env->function_name = 0;
env->module_name = 0;
uwx_reset_str_pool(env);
/* Use the lookup IP callback routine to find out about the */
/* current IP. If the predicate registers are valid, pass them */
/* in the uvec. */
i = 0;
if (env->context.valid_regs & (1 << UWX_REG_PREDS)) {
uvecout[i++] = UWX_KEY_PREDS;
uvecout[i++] = env->context.special[UWX_REG_PREDS];
}
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);
/* If NOTFOUND, there's nothing we can do but return an error. */
if (cbstatus == UWX_LKUP_NOTFOUND) {
status = UWX_ERR_IPNOTFOUND;
}
/* If the callback returns an unwind table, we need to */
/* search the table for an unwind entry that describes the */
/* code region of interest, then decode the unwind information */
/* associated with that unwind table entry, and store the */
/* resulting register state array in the unwind environment */
/* 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);
if (status == UWX_OK)
status = uwx_decode_uinfo(env, &uentry, &rstate);
else if (status == UWX_ERR_NOUENTRY)
status = uwx_default_rstate(env, &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 */
/* let it free any memory it allocated. */
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 (status == UWX_OK)
env->rstate = rstate;
}
/* Any other return from the callback is an error. */
else {
status = UWX_ERR_LOOKUPERR;
}
return status;
}
/* uwx_get_sym_info: Gets symbolic info from current frame */
int uwx_get_sym_info(
struct uwx_env *env,
char **modp,
char **symp,
uint64_t *offsetp)
{
int status;
int cbstatus;
uint64_t ip;
uint64_t *uvec;
uint64_t uvecout[2];
int i;
if (env == 0)
return UWX_ERR_NOENV;
if (env->copyin == 0 || env->lookupip == 0)
return UWX_ERR_NOCALLBACKS;
if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
return UWX_ERR_NOCONTEXT;
/* If we haven't already obtained the frame info for the */
/* current frame, get it now. */
if (env->rstate == 0) {
status = uwx_get_frame_info(env);
if (status != UWX_OK)
return status;
}
/* Get the symbolic information from the lookup IP callback. */
if (env->function_name == 0) {
ip = env->context.special[UWX_REG_IP];
i = 0;
if (env->function_offset >= 0) {
uvecout[i++] = UWX_KEY_FUNCSTART;
uvecout[i++] = ip - env->function_offset;
}
uvecout[i++] = UWX_KEY_END;
uvecout[i++] = 0;
uvec = uvecout;
cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS,
env->context.special[UWX_REG_IP], env->cb_token, &uvec);
if (cbstatus == UWX_LKUP_SYMINFO) {
for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
switch ((int)uvec[i]) {
case UWX_KEY_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 = ip - uvec[i+1];
break;
}
}
(void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
}
}
*modp = env->module_name;
*symp = env->function_name;
*offsetp = env->function_offset;
return UWX_OK;
}
/* uwx_step: Steps from the current frame to the previous frame */
int uwx_step(struct uwx_env *env)
{
int i;
int status;
int pfs_sol;
int dispcode;
uint64_t val;
uint64_t fval[2];
uint64_t hist;
uint64_t tempgr[NPRESERVEDGR];
int needpriunat;
int unat;
int tempnat;
if (env == 0)
return UWX_ERR_NOENV;
if (env->copyin == 0 || env->lookupip == 0)
return UWX_ERR_NOCALLBACKS;
if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
return UWX_ERR_NOCONTEXT;
/* If we haven't already obtained the frame info for the */
/* current frame, get it now. */
if (env->rstate == 0) {
status = uwx_get_frame_info(env);
if (status != UWX_OK)
return status;
}
TRACE_S_STEP(env->rstate)
/* Complete the current context by restoring the current values */
/* of psp, rp, and pfs. */
if (env->rstate[SBREG_PSP] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_PSP], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_PSP] = val;
env->history.special[UWX_REG_PSP] = hist;
TRACE_S_RESTORE_REG("PSP", env->rstate[SBREG_PSP], val)
}
if (env->rstate[SBREG_RP] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_RP], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_RP] = val;
env->history.special[UWX_REG_RP] = hist;
TRACE_S_RESTORE_REG("RP", env->rstate[SBREG_RP], val)
}
if (env->rstate[SBREG_PFS] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_PFS], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_PFS] = val;
env->history.special[UWX_REG_PFS] = hist;
TRACE_S_RESTORE_REG("PFS", env->rstate[SBREG_PFS], val)
}
/* Check for bottom of stack (rp == 0). */
if (env->context.special[UWX_REG_RP] == 0)
return UWX_BOTTOM;
/* Find where the primary unat is saved, get a copy. */
/* Then, as we restore the GRs, we'll merge the NaT bits into the */
/* priunat register in the context. */
/* (Make sure we need it, though, before we try to get it, */
/* because the attempt to get it might invoke the copy-in callback. */
/* We don't need the priunat unless one of GR 4-7 was */
/* saved to the memory stack.) */
needpriunat = 0;
for (i = 0; i < NSB_GR; i++) {
dispcode = UWX_GET_DISP_CODE(env->rstate[SBREG_GR + i]);
if (dispcode == UWX_DISP_SPREL(0) || dispcode == UWX_DISP_PSPREL(0))
needpriunat = 1;
}
unat = 0;
if (needpriunat && env->rstate[SBREG_PRIUNAT] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_PRIUNAT], &val, &hist);
if (status != UWX_OK)
return status;
unat = (int) val;
env->history.special[UWX_REG_PRIUNAT] = hist;
TRACE_S_RESTORE_REG("PRIUNAT", env->rstate[SBREG_PRIUNAT], val)
}
/* Retrieve saved values of the preserved GRs into temporaries. */
tempnat = (int) env->context.special[UWX_REG_PRIUNAT];
for (i = 0; i < NSB_GR; i++) {
if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) {
status = uwx_restore_reg(env,
env->rstate[SBREG_GR + i], &val, &hist);
if (status != UWX_OK)
return status;
tempgr[i] = val;
if (uwx_restore_nat(env, env->rstate[SBREG_GR + i], unat))
tempnat |= 1 << i;
else
tempnat &= ~(1 << i);
env->history.gr[i] = hist;
env->context.valid_regs |= 1 << (i + VALID_GR_SHIFT);
TRACE_S_RESTORE_GR(i, env->rstate[SBREG_GR + i], val)
}
}
/* Now we have everything we need to step back to the previous frame. */
/* Restore preserved BRs. */
for (i = 0; i < NSB_BR; i++) {
if (env->rstate[SBREG_BR + i] != UWX_DISP_NONE) {
status = uwx_restore_reg(env,
env->rstate[SBREG_BR + i], &val, &hist);
if (status != UWX_OK)
return status;
env->context.br[i] = val;
env->history.br[i] = hist;
env->context.valid_regs |= 1 << (i + VALID_BR_SHIFT);
TRACE_S_RESTORE_BR(i, env->rstate[SBREG_BR + i], val)
}
}
/* Restore preserved FRs. */
if (env->nsbreg == NSBREG) {
for (i = 0; i < NSB_FR; i++) {
if (env->rstate[SBREG_FR + i] != UWX_DISP_NONE) {
status = uwx_restore_reg(env,
env->rstate[SBREG_FR + i], fval, &hist);
if (status != UWX_OK)
return status;
env->context.fr[i].part0 = fval[0];
env->context.fr[i].part1 = fval[1];
env->history.fr[i] = hist;
env->context.valid_frs |= 1 << i;
TRACE_S_RESTORE_FR(i, env->rstate[SBREG_FR + i], fval)
}
}
}
/* Restore other preserved regs. */
if (env->rstate[SBREG_PREDS] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_PREDS], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_PREDS] = val;
env->history.special[UWX_REG_PREDS] = hist;
env->context.valid_regs |= 1 << UWX_REG_PREDS;
TRACE_S_RESTORE_REG("PREDS", env->rstate[SBREG_PREDS], val)
}
if (env->rstate[SBREG_RNAT] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_RNAT], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_RNAT] = val;
env->history.special[UWX_REG_RNAT] = hist;
env->context.valid_regs |= 1 << UWX_REG_RNAT;
TRACE_S_RESTORE_REG("RNAT", env->rstate[SBREG_RNAT], val)
}
if (env->rstate[SBREG_UNAT] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_UNAT], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_UNAT] = val;
env->history.special[UWX_REG_UNAT] = hist;
env->context.valid_regs |= 1 << UWX_REG_UNAT;
TRACE_S_RESTORE_REG("UNAT", env->rstate[SBREG_UNAT], val)
}
if (env->rstate[SBREG_FPSR] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_FPSR], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_FPSR] = val;
env->history.special[UWX_REG_FPSR] = hist;
env->context.valid_regs |= 1 << UWX_REG_FPSR;
TRACE_S_RESTORE_REG("FPSR", env->rstate[SBREG_FPSR], val)
}
if (env->rstate[SBREG_LC] != UWX_DISP_NONE) {
status = uwx_restore_reg(env, env->rstate[SBREG_LC], &val, &hist);
if (status != UWX_OK)
return status;
env->context.special[UWX_REG_LC] = val;
env->history.special[UWX_REG_LC] = hist;
env->context.valid_regs |= 1 << UWX_REG_LC;
TRACE_S_RESTORE_REG("LC", env->rstate[SBREG_LC], val)
}
/* Restore preserved GRs from temporaries. */
for (i = 0; i < NSB_GR; i++) {
if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE)
env->context.gr[i] = tempgr[i];
}
env->context.special[UWX_REG_PRIUNAT] = tempnat;
/* Restore the frame markers. */
env->context.special[UWX_REG_IP] = env->context.special[UWX_REG_RP];
env->history.special[UWX_REG_IP] = env->history.special[UWX_REG_RP];
env->context.special[UWX_REG_SP] = env->context.special[UWX_REG_PSP];
env->history.special[UWX_REG_SP] = env->history.special[UWX_REG_PSP];
pfs_sol = ((unsigned int)env->context.special[UWX_REG_PFS] >> 7) & 0x7f;
env->context.special[UWX_REG_BSP] = uwx_add_to_bsp(
env->context.special[UWX_REG_BSP],
-pfs_sol);
env->context.special[UWX_REG_CFM] = env->context.special[UWX_REG_PFS];
env->history.special[UWX_REG_CFM] = env->history.special[UWX_REG_PFS];
env->context.special[UWX_REG_RP] = 0;
/* The frame info for the new frame isn't yet available. */
env->rstate = 0;
return UWX_OK;
}
/* uwx_decode_uvec: Converts the update vector into a register state array */
int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate)
{
while (*uvec != 0) {
switch ((int)*uvec++) {
case UWX_KEY_CONTEXT:
env->abi_context = (int)(*uvec++);
return UWX_ABI_FRAME;
default:
return UWX_ERR_CANTUNWIND;
}
}
return UWX_OK;
}
/* uwx_restore_reg: Restores a register according to the scoreboard */
#define COPYIN_MSTACK_8(dest, src) \
(env->remote? \
(*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \
DWORDSZ, env->cb_token) : \
(*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
int uwx_restore_reg(struct uwx_env *env, uint64_t rstate,
uint64_t *valp, uint64_t *histp)
{
int status;
uint64_t p;
int n;
int regid;
status = UWX_OK;
switch (UWX_GET_DISP_CODE(rstate)) {
case UWX_DISP_SPPLUS(0):
*valp = env->context.special[UWX_REG_SP] +
UWX_GET_DISP_OFFSET(rstate);
*histp = UWX_DISP_NONE;
break;
case UWX_DISP_SPREL(0):
p = env->context.special[UWX_REG_SP] +
UWX_GET_DISP_OFFSET(rstate);
n = COPYIN_MSTACK_8((char *)valp, p);
if (n != DWORDSZ)
status = UWX_ERR_COPYIN_MSTK;
*histp = UWX_DISP_MSTK(p);
break;
case UWX_DISP_PSPREL(0):
p = env->context.special[UWX_REG_PSP] + 16 -
UWX_GET_DISP_OFFSET(rstate);
n = COPYIN_MSTACK_8((char *)valp, p);
if (n != DWORDSZ)
status = UWX_ERR_COPYIN_MSTK;
*histp = UWX_DISP_MSTK(p);
break;
case UWX_DISP_REG(0):
regid = UWX_GET_DISP_REGID(rstate);
status = uwx_get_reg(env, regid, valp);
(void) uwx_get_spill_loc(env, regid, histp);
break;
}
return status;
}
/* uwx_restore_nat: Returns the saved NaT bit for a preserved GR */
int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat)
{
int nat;
uint64_t p;
nat = 0;
switch (UWX_GET_DISP_CODE(rstate)) {
case UWX_DISP_SPREL(0):
p = env->context.special[UWX_REG_SP] +
UWX_GET_DISP_OFFSET(rstate);
nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01;
break;
case UWX_DISP_PSPREL(0):
p = env->context.special[UWX_REG_PSP] + 16 -
UWX_GET_DISP_OFFSET(rstate);
nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01;
break;
case UWX_DISP_REG(0):
(void) uwx_get_nat(env, UWX_GET_DISP_REGID(rstate), &nat);
break;
}
return nat;
}

View File

@ -0,0 +1,122 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_str.h"
#ifdef _KERNEL
#define free(p) /* nullified */
#define malloc(sz) NULL
#endif
/*
* uwx_str.c
*
* This file contains the routines for maintaining a string
* pool for the unwind environment. We preallocate enough
* space for most purposes so that no memory allocation is
* necessary during a normal unwind. If we do need more,
* we use the allocate callback, if one is provided.
*
* The string pool is reused with each call to step(),
* and is completely freed when the unwind environment is
* freed.
*/
int uwx_init_str_pool(struct uwx_env *env)
{
if (env->allocate_cb == 0)
env->string_pool = (struct uwx_str_pool *)
malloc(sizeof(struct uwx_str_pool));
else
env->string_pool = (struct uwx_str_pool *)
(*env->allocate_cb)(sizeof(struct uwx_str_pool));
if (env->string_pool == 0)
return UWX_ERR_NOMEM;
env->string_pool->next = 0;
env->string_pool->size = STRPOOLSIZE;
env->string_pool->used = 0;
return UWX_OK;
}
void uwx_free_str_pool(struct uwx_env *env)
{
struct uwx_str_pool *pool;
struct uwx_str_pool *next;
for (pool = env->string_pool; pool != 0; pool = next) {
next = pool->next;
if (env->free_cb == 0)
free(pool);
else
(*env->free_cb)(pool);
}
}
char *uwx_alloc_str(struct uwx_env *env, char *str)
{
int len;
int size;
struct uwx_str_pool *pool;
struct uwx_str_pool *prev;
char *p;
len = strlen(str) + 1;
prev = 0;
for (pool = env->string_pool; pool != 0; pool = pool->next) {
prev = pool;
if (pool->size - pool->used >= len)
break;
}
if (pool == 0) {
size = STRPOOLSIZE;
if (len > size)
size = len;
size += sizeof(struct uwx_str_pool) - STRPOOLSIZE;
if (env->allocate_cb == 0)
pool = (struct uwx_str_pool *) malloc(size);
else
pool = (struct uwx_str_pool *) (*env->allocate_cb)(size);
if (env->string_pool == 0)
return 0;
pool->next = 0;
pool->size = size;
pool->used = 0;
prev->next = pool;
}
p = pool->pool + pool->used;
strcpy(p, str);
pool->used += len;
return p;
}
void uwx_reset_str_pool(struct uwx_env *env)
{
struct uwx_str_pool *pool;
for (pool = env->string_pool; pool != 0; pool = pool->next)
pool->used = 0;
}

View File

@ -0,0 +1,35 @@
/*
* 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.
*/
#define STRPOOLSIZE 400
struct uwx_str_pool {
struct uwx_str_pool *next;
int size;
int used;
char pool[STRPOOLSIZE];
};
extern int uwx_init_str_pool(struct uwx_env *env);
extern void uwx_free_str_pool(struct uwx_env *env);
extern char *uwx_alloc_str(struct uwx_env *env, char *str);
extern void uwx_reset_str_pool(struct uwx_env *env);

View File

@ -0,0 +1,68 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_swap.h"
void uwx_swap4(uint32_t *w)
{
unsigned char *p;
unsigned char t[4];
p = (unsigned char *) w;
t[0] = p[0];
t[1] = p[1];
t[2] = p[2];
t[3] = p[3];
p[0] = t[3];
p[1] = t[2];
p[2] = t[1];
p[3] = t[0];
}
void uwx_swap8(uint64_t *dw)
{
unsigned char *p;
unsigned char t[8];
p = (unsigned char *) dw;
t[0] = p[0];
t[1] = p[1];
t[2] = p[2];
t[3] = p[3];
t[4] = p[4];
t[5] = p[5];
t[6] = p[6];
t[7] = p[7];
p[0] = t[7];
p[1] = t[6];
p[2] = t[5];
p[3] = t[4];
p[4] = t[3];
p[5] = t[2];
p[6] = t[1];
p[7] = t[0];
}

View File

@ -0,0 +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.
*/
extern void uwx_swap4(uint32_t *w);
extern void uwx_swap8(uint64_t *dw);

View File

@ -0,0 +1,138 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_uinfo.h"
#include "uwx_scoreboard.h"
#include "uwx_trace.h"
void uwx_trace_init(struct uwx_env *env)
{
char *tstr;
tstr = getenv("UWX_TRACE");
if (tstr != NULL) {
while (*tstr != '\0') {
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;
case 'r': env->trace |= UWX_TRACE_RSTATE; break;
case 's': env->trace |= UWX_TRACE_STEP; break;
case 'c': env->trace |= UWX_TRACE_CONTEXT; break;
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");
fprintf(stderr, " b: scoreboard management\n");
fprintf(stderr, " r: register state vector\n");
fprintf(stderr, " s: step\n");
fprintf(stderr, " c: context\n");
fprintf(stderr, " C: copyin callback\n");
fprintf(stderr, " L: lookup ip callback\n");
exit(1);
#endif
}
tstr++;
}
}
}
char *uwx_sb_rnames[] = {
"RP", "PSP", "PFS",
"PREDS", "UNAT", "PRIUNAT", "RNAT", "LC", "FPSR",
"GR4", "GR5", "GR6", "GR7",
"BR1", "BR2", "BR3", "BR4", "BR5",
"FR2", "FR3", "FR4", "FR5",
"FR16", "FR17", "FR18", "FR19",
"FR20", "FR21", "FR22", "FR23",
"FR24", "FR25", "FR26", "FR27",
"FR28", "FR29", "FR30", "FR31",
};
void uwx_dump_rstate(int regid, uint64_t rstate)
{
int reg;
if (rstate == UWX_DISP_NONE)
return;
printf(" %-7s", uwx_sb_rnames[regid]);
switch (UWX_GET_DISP_CODE(rstate)) {
case UWX_DISP_NONE:
printf(" unchanged\n");
break;
case UWX_DISP_SPPLUS(0):
printf(" SP + %d\n", (int)rstate & ~0x07);
break;
case UWX_DISP_SPREL(0):
printf(" [SP + %d]\n", (int)rstate & ~0x07);
break;
case UWX_DISP_PSPREL(0):
printf(" [PSP + 16 - %d]\n", (int)rstate & ~0x07);
break;
case UWX_DISP_REG(0):
reg = UWX_GET_DISP_REGID(rstate);
if (reg == UWX_REG_PFS)
printf(" [AR.PFS]\n");
else if (reg == UWX_REG_UNAT)
printf(" [AR.UNAT]\n");
else if (reg >= UWX_REG_GR(0) && reg < UWX_REG_GR(128))
printf(" [GR%d]\n", reg - UWX_REG_GR(0));
else if (reg >= UWX_REG_FR(0) && reg < UWX_REG_FR(128))
printf(" [FR%d]\n", reg - UWX_REG_FR(0));
else if (reg >= UWX_REG_BR(0) && reg < UWX_REG_BR(8))
printf(" [BR%d]\n", reg - UWX_REG_BR(0));
else
printf(" [reg %d]\n", reg);
break;
default:
printf(" <%08llx>\n", (unsigned long long)rstate);
break;
}
}
void uwx_dump_scoreboard(
struct uwx_scoreboard *scoreboard,
int nsbreg,
struct uwx_rhdr *rhdr,
int cur_slot,
int ip_slot)
{
int i;
if (rhdr->is_prologue)
printf(" Prologue region (start = %d, length = %d)\n",
(int)cur_slot, (int)rhdr->rlen);
else
printf(" Body region (start = %d, length = %d, ecount = %d)\n",
cur_slot, (int)rhdr->rlen, rhdr->ecount);
if (ip_slot < rhdr->rlen)
printf(" IP is in this region (offset = %d)\n", ip_slot);
for (i = 0; i < nsbreg; i++)
uwx_dump_rstate(i, scoreboard->rstate[i]);
}

View File

@ -0,0 +1,348 @@
/*
* 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.
*/
#define UWX_TRACE_SB 1 /* UWX_TRACE=b: scoreboard mgmt */
#define UWX_TRACE_UINFO 2 /* UWX_TRACE=i: unwind info */
#define UWX_TRACE_RSTATE 4 /* UWX_TRACE=r: reg state vector */
#define UWX_TRACE_STEP 8 /* UWX_TRACE=s: step */
#define UWX_TRACE_UTABLE 16 /* UWX_TRACE=t: unwind tbl search */
#define UWX_TRACE_CONTEXT 32 /* UWX_TRACE=c: context */
#define UWX_TRACE_COPYIN 64 /* UWX_TRACE=C: copyin callback */
#define UWX_TRACE_LOOKUPIP 128 /* UWX_TRACE=L: lookupip callback */
#ifdef DISABLE_TRACE
#define TRACE_INIT
#define TRACE_B_REUSE(id)
#define TRACE_B_ALLOC(id)
#define TRACE_B_POP(id)
#define TRACE_B_LABEL(label)
#define TRACE_B_LABEL_COPY(id)
#define TRACE_B_LABEL_REVERSE(back, new)
#define TRACE_B_COPY(label, id)
#define TRACE_B_COPY_FREE(id)
#define TRACE_B_COPY_FOUND(id)
#define TRACE_B_COPY_COPY(id)
#define TRACE_B_COPY_REVERSE(back, new)
#define TRACE_B_FREE(id)
#define TRACE_I_DECODE_RHDR_1(name, b0)
#define TRACE_I_DECODE_RHDR_1L(name, b0, val)
#define TRACE_I_DECODE_RHDR_2L(name, b0, b1, val)
#define TRACE_I_DECODE_PROLOGUE_1(name, b0)
#define TRACE_I_DECODE_PROLOGUE_1L(name, b0, val)
#define TRACE_I_DECODE_PROLOGUE_1LL(name, b0, val1, val2)
#define TRACE_I_DECODE_PROLOGUE_2(name, b0, b1)
#define TRACE_I_DECODE_PROLOGUE_2L(name, b0, b1, parm1)
#define TRACE_I_DECODE_PROLOGUE_3(name, b0, b1, b2)
#define TRACE_I_DECODE_PROLOGUE_4(name, b0, b1, b2, b3)
#define TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base)
#define TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask)
#define TRACE_I_DECODE_PROLOGUE_NSPILL(ngr)
#define TRACE_I_DECODE_BODY_1(name, b0)
#define TRACE_I_DECODE_BODY_1L(name, b0, parm1)
#define TRACE_I_DECODE_BODY_1LL(name, b0, parm1, parm2)
#define TRACE_R_UIB(uentry, ulen)
#define TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
#define TRACE_S_STEP(rstate)
#define TRACE_S_RESTORE_REG(regname, rstate, val)
#define TRACE_S_RESTORE_GR(regid, rstate, val)
#define TRACE_S_RESTORE_BR(regid, rstate, val)
#define TRACE_S_RESTORE_FR(regid, rstate, val)
#define TRACE_T_SEARCH32(ip)
#define TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end)
#define TRACE_C_GET_REG(regid, bsp)
#define TRACE_C_ROTATE_GR(regid, sor, rrb_gr, newregid)
#define TRACE_SELF_COPYIN4(rem, len, wp)
#define TRACE_SELF_COPYIN8(rem, len, dp)
#define TRACE_SELF_LOOKUP(ip)
#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base)
#else /* not TRACE_DISABLED */
extern void uwx_trace_init(struct uwx_env *env);
extern void uwx_dump_rstate(int regid, uint64_t rstate);
struct uwx_rhdr;
extern void uwx_dump_scoreboard(
struct uwx_scoreboard *scoreboard,
int nsbreg,
struct uwx_rhdr *rhdr,
int cur_slot,
int ip_slot);
#define TRACE_INIT uwx_trace_init(env);
#define TRACE_B_REUSE(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_alloc_scoreboard: reuse id %d\n", (id));
#define TRACE_B_ALLOC(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_alloc_scoreboard: alloc id %d\n", (id));
#define TRACE_B_POP(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_pop_scoreboards: free id %d\n", (id));
#define TRACE_B_LABEL(label) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_label_scoreboard: label %d\n", (label));
#define TRACE_B_LABEL_COPY(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_label_scoreboard: copy id %d\n", (id));
#define TRACE_B_LABEL_REVERSE(back, new) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_label_scoreboard: reverse link %d -> %d\n", \
(new)->id, ((back) == 0) ? -1 : (back)->id);
#define TRACE_B_COPY(label, id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_copy_scoreboard: label %d, cur sb id %d\n", (label), (id));
#define TRACE_B_COPY_FREE(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_copy_scoreboard: free id %d\n", (id));
#define TRACE_B_COPY_FOUND(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_copy_scoreboard: found id %d\n", (id));
#define TRACE_B_COPY_COPY(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_copy_scoreboard: copy id %d\n", (id));
#define TRACE_B_COPY_REVERSE(back, new) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_copy_scoreboard: reverse link %d -> %d\n", \
(new)->id, ((back) == 0) ? -1 : (back)->id);
#define TRACE_B_FREE(id) \
if (env->trace & UWX_TRACE_SB) \
printf("uwx_free_scoreboards: free id %d\n", (id));
#define TRACE_I_DECODE_RHDR_1(name, b0) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_rhdr: %02x %s\n", \
(b0), (name));
#define TRACE_I_DECODE_RHDR_1L(name, b0, val) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_rhdr: %02x %08x %s\n", \
(b0), (int)(val), (name));
#define TRACE_I_DECODE_RHDR_2L(name, b0, b1, val) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_rhdr: %02x %02x %08x %s\n", \
(b0), (b1), (int)(val), (name));
#define TRACE_I_DECODE_PROLOGUE_1(name, b0) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %s\n", \
(b0), (name));
#define TRACE_I_DECODE_PROLOGUE_1L(name, b0, val) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %08x %s\n", \
(b0), (int)(val), (name));
#define TRACE_I_DECODE_PROLOGUE_1LL(name, b0, val1, val2) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %08x %08x %s\n", \
(b0), (int)(val1), (int)(val2), (name));
#define TRACE_I_DECODE_PROLOGUE_2(name, b0, b1) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %02x %s\n", \
(b0), (b1), (name));
#define TRACE_I_DECODE_PROLOGUE_2L(name, b0, b1, val) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %02x %08x %s\n", \
(b0), (b1), (int)(val), (name));
#define TRACE_I_DECODE_PROLOGUE_3(name, b0, b1, b2) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %02x %02x %s\n", \
(b0), (b1), (b2), (name));
#define TRACE_I_DECODE_PROLOGUE_4(name, b0, b1, b2, b3) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: %02x %02x %02x %02x %s\n", \
(b0), (b1), (b2), (b3), (name));
#define TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: spill base = %08x\n", (int)(spill_base));
#define TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: gr_mem_mask = %02x; gr_gr_mask = %02x\n", \
(gr_mem_mask), (gr_gr_mask));
#define TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_prologue: ngr = %d\n", (ngr));
#define TRACE_I_DECODE_BODY_1(name, b0) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_body: %02x %s\n", \
(b0), (name));
#define TRACE_I_DECODE_BODY_1L(name, b0, val) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_body: %02x %08x %s\n", \
(b0), (int)(val), (name));
#define TRACE_I_DECODE_BODY_1LL(name, b0, val1, val2) \
if (env->trace & UWX_TRACE_UINFO) \
printf("uwx_decode_body: %02x %08x %08x %s\n", \
(b0), (int)(val1), (int)(val2), (name));
#define TRACE_R_UIB(uentry, ulen) \
if (env->trace & UWX_TRACE_RSTATE) \
printf("Unwind info block (flags = %08x %08x, ulen = %d)\n", \
(unsigned int)((uentry)->unwind_flags >> 32), \
(unsigned int)(uentry)->unwind_flags, \
(ulen));
#define TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) \
if (env->trace & UWX_TRACE_RSTATE) \
uwx_dump_scoreboard(scoreboard, env->nsbreg, \
&(rhdr), cur_slot, ip_slot);
#define TRACE_S_STEP(rstate) \
if (env->trace & UWX_TRACE_STEP) { \
printf("uwx_step:\n"); \
uwx_dump_rstate(SBREG_RP, (rstate)[SBREG_RP]); \
uwx_dump_rstate(SBREG_PSP, (rstate)[SBREG_PSP]); \
uwx_dump_rstate(SBREG_PFS, (rstate)[SBREG_PFS]); \
}
#define TRACE_S_RESTORE_REG(regname, rstate, val) \
if (env->trace & UWX_TRACE_STEP) \
printf(" restore %-7s (rstate = %08x %08x) = %08x %08x\n", \
regname, \
(unsigned int) ((rstate) >> 32), \
(unsigned int) (rstate), \
(unsigned int) ((val) >> 32), \
(unsigned int) (val));
#define TRACE_S_RESTORE_GR(regid, rstate, val) \
if (env->trace & UWX_TRACE_STEP) \
printf(" restore GR%d (rstate = %08x %08x) = %08x %08x\n", \
(regid) + 4, \
(unsigned int) ((rstate) >> 32), \
(unsigned int) (rstate), \
(unsigned int) ((val) >> 32), \
(unsigned int) (val));
#define TRACE_S_RESTORE_BR(regid, rstate, val) \
if (env->trace & UWX_TRACE_STEP) \
printf(" restore BR%d (rstate = %08x %08x) = %08x %08x\n", \
(regid) + 1, \
(unsigned int) ((rstate) >> 32), \
(unsigned int) (rstate), \
(unsigned int) ((val) >> 32), \
(unsigned int) (val));
#define TRACE_S_RESTORE_FR(regid, rstate, fval) \
if (env->trace & UWX_TRACE_STEP) \
printf(" restore FR%d (rstate = %08x %08x) = %08x %08x %08x %08x\n", \
(regid) + 1, \
(unsigned int) ((rstate) >> 32), \
(unsigned int) (rstate), \
(unsigned int) ((fval[0]) >> 32), \
(unsigned int) (fval[0]), \
(unsigned int) ((fval[1]) >> 32), \
(unsigned int) (fval[1]));
#define TRACE_T_SEARCH32(ip) \
if (env->trace & UWX_TRACE_UTABLE) \
printf("uwx_search_utable32 (relative ip = %08x)\n", (ip));
#define TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end) \
if (env->trace & UWX_TRACE_UTABLE) \
printf(" lb/ub = %d/%d, mid = %d, start/end = %08x %08x\n", \
lb, ub, mid, code_start, code_end);
#define TRACE_C_GET_REG(regid, bsp) \
if (env->trace & UWX_TRACE_CONTEXT) \
printf("uwx_get_reg (gr%d, bsp = %08x %08x)\n", \
(regid) - UWX_REG_GR(0), \
(unsigned int) ((bsp) >> 32), \
(unsigned int) (bsp));
#define TRACE_C_ROTATE_GR(regid, sor, rrb_gr, newregid) \
if (env->trace & UWX_TRACE_CONTEXT) \
printf("uwx_get_reg (gr%d, sor = %d, rrb = %d) --> gr%d\n", \
(regid) + 32, \
(sor), \
(rrb_gr), \
(newregid) + 32);
#define TRACE_SELF_COPYIN4(rem, len, wp) \
if (info->trace & UWX_TRACE_COPYIN) \
printf("copyin (rem = %08x %08x, len = %d, val = %08x)\n", \
(unsigned int) ((rem) >> 32), \
(unsigned int) (rem), \
(len), *(wp));
#define TRACE_SELF_COPYIN8(rem, len, dp) \
if (info->trace & UWX_TRACE_COPYIN) \
printf("copyin (rem = %08x %08x, len = %d, val = %08x %08x)\n", \
(unsigned int) ((rem) >> 32), \
(unsigned int) (rem), \
(len), \
((unsigned int *)(dp))[0], \
((unsigned int *)(dp))[1]);
#define TRACE_SELF_LOOKUP(ip) \
if (info->trace & UWX_TRACE_LOOKUPIP) \
printf("Lookup IP callback: ip = %08x %08x\n", \
(unsigned int) ((ip) >> 32), \
(unsigned int) (ip));
#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base) \
if (info->trace & UWX_TRACE_LOOKUPIP) { \
printf(" text base: %08x %08x\n", \
(unsigned int) ((text_base) >> 32), \
(unsigned int) (text_base)); \
printf(" unwind base: %08x %08x\n", \
(unsigned int) ((uint64_t)(unwind_base) >> 32), \
(unsigned int) (unwind_base)); \
printf(" unwind flags: %08x %08x\n", \
(unsigned int) ((unwind_base)[0] >> 32), \
(unsigned int) (unwind_base)[0]); \
printf(" unwind start: %08x %08x\n", \
(unsigned int) (((text_base)+(unwind_base)[1]) >> 32), \
(unsigned int) ((text_base)+(unwind_base)[1])); \
printf(" unwind end: %08x %08x\n", \
(unsigned int) (((text_base)+(unwind_base)[2]) >> 32), \
(unsigned int) ((text_base)+(unwind_base)[2])); \
}
#endif /* TRACE_DISABLED */

View File

@ -0,0 +1,365 @@
/*
* 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.
*/
#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"
#include "uwx_trace.h"
#include "uwx_ttrace.h"
struct uwx_ttrace_info {
uint64_t bspstore;
uint64_t load_map;
uint64_t rvec[10];
alloc_cb allocate_cb;
free_cb free_cb;
int have_ucontext;
pid_t pid;
lwpid_t lwpid;
int trace;
ucontext_t ucontext;
};
void *uwx_ttrace_memcpy(void *buffer, uint64_t ptr, size_t bufsiz, int ident)
{
uint64_t *dest;
uint64_t val;
int status;
status = ttrace(TT_PROC_RDDATA, (pid_t)ident,
0, ptr, bufsiz, (uint64_t)buffer);
if (status != 0)
return NULL;
return buffer;
}
struct uwx_ttrace_info *uwx_ttrace_init_info(
struct uwx_env *env,
pid_t pid,
lwpid_t lwpid,
uint64_t load_map)
{
struct uwx_ttrace_info *info;
if (env->allocate_cb == 0)
info = (struct uwx_ttrace_info *)
malloc(sizeof(struct uwx_ttrace_info));
else
info = (struct uwx_ttrace_info *)
(*env->allocate_cb)(sizeof(struct uwx_ttrace_info));
if (info == 0)
return 0;
info->bspstore = 0;
info->load_map = load_map;
info->allocate_cb = env->allocate_cb;
info->free_cb = env->free_cb;
info->have_ucontext = 0;
info->pid = pid;
info->lwpid = lwpid;
info->trace = env->trace;
return info;
}
int uwx_ttrace_free_info(struct uwx_ttrace_info *info)
{
if (info->free_cb == 0)
free((void *)info);
else
(*info->free_cb)((void *)info);
return UWX_OK;
}
int uwx_ttrace_init_context(struct uwx_env *env, struct uwx_ttrace_info *info)
{
uint64_t reason;
uint64_t ip;
uint64_t sp;
uint64_t bsp;
uint64_t cfm;
uint64_t ec;
int status;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__reason, (uint64_t)8, (uint64_t)&reason);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__ip, (uint64_t)8, (uint64_t)&ip);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__r12, (uint64_t)8, (uint64_t)&sp);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__ar_bsp, (uint64_t)8, (uint64_t)&bsp);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__ar_bspstore, (uint64_t)8, (uint64_t)&info->bspstore);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__cfm, (uint64_t)8, (uint64_t)&cfm);
if (status != 0)
return UWX_TT_ERR_TTRACE;
status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
(uint64_t)__ar_ec, (uint64_t)8, (uint64_t)&ec);
if (status != 0)
return UWX_TT_ERR_TTRACE;
cfm |= ec << 52;
if (reason != 0)
bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
return uwx_init_context(env, ip, sp, bsp, cfm);
}
int uwx_ttrace_init_from_sigcontext(
struct uwx_env *env,
struct uwx_ttrace_info *info,
uint64_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;
info->have_ucontext = 1;
uwx_ttrace_memcpy(&info->ucontext,
ucontext,
sizeof(__uc_misc_t),
info->pid);
uwx_ttrace_memcpy(&info->ucontext.__uc_mcontext,
(uint64_t) &((ucontext_t *)ucontext)->__uc_mcontext,
sizeof(mcontext_t),
info->pid);
status = __uc_get_reason(&info->ucontext, &reason);
status = __uc_get_ip(&info->ucontext, &ip);
status = __uc_get_grs(&info->ucontext, 12, 1, &sp, &nat);
status = __uc_get_ar(&info->ucontext, 17, &bsp);
status = __uc_get_ar(&info->ucontext, 18, &info->bspstore);
status = __uc_get_ar(&info->ucontext, 66, &ec);
status = __uc_get_cfm(&info->ucontext, &cfm);
cfm |= ec << 52;
if (reason != 0)
bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
uwx_init_context(env, ip, sp, bsp, cfm);
return UWX_OK;
}
int uwx_ttrace_do_context_frame(
struct uwx_env *env,
struct uwx_ttrace_info *info)
{
int abi_context;
int status;
uint64_t ucontext;
abi_context = uwx_get_abi_context_code(env);
if (abi_context != 0x0101) /* abi = HP-UX, context = 1 */
return UWX_TT_ERR_BADABICONTEXT;
status = uwx_get_reg(env, UWX_REG_GR(32), &ucontext);
if (status != 0)
return status;
return uwx_ttrace_init_from_sigcontext(env, info, ucontext);
}
int uwx_ttrace_copyin(
int request,
char *loc,
uint64_t rem,
int len,
intptr_t tok)
{
int status;
int regid;
unsigned int nat;
struct uwx_ttrace_info *info = (struct uwx_ttrace_info *) tok;
unsigned long *wp;
uint64_t *dp;
int ttreg;
dp = (uint64_t *) loc;
if (request == UWX_COPYIN_UINFO) {
if (len == 4) {
status = ttrace(TT_PROC_RDTEXT, info->pid,
0, rem, 4, (uint64_t)loc);
wp = (unsigned long *) loc;
TRACE_SELF_COPYIN4(rem, len, wp)
}
else if (len == 8) {
status = ttrace(TT_PROC_RDTEXT, info->pid,
0, rem, 8, (uint64_t)loc);
TRACE_SELF_COPYIN4(rem, len, dp)
}
else
return 0;
}
else if (request == UWX_COPYIN_MSTACK && len == 8) {
status = ttrace(TT_PROC_RDDATA, info->pid, 0, rem, 8, (uint64_t)loc);
TRACE_SELF_COPYIN4(rem, len, dp)
}
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)
}
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) {
regid = (int)rem;
if (info->have_ucontext) {
if (regid < UWX_REG_GR(0)) {
switch (regid) {
case UWX_REG_PFS:
status = __uc_get_ar(&info->ucontext, 64, dp);
break;
case UWX_REG_PREDS:
status = __uc_get_prs(&info->ucontext, dp);
break;
case UWX_REG_RNAT:
status = __uc_get_ar(&info->ucontext, 19, dp);
break;
case UWX_REG_UNAT:
status = __uc_get_ar(&info->ucontext, 36, dp);
break;
case UWX_REG_FPSR:
status = __uc_get_ar(&info->ucontext, 40, dp);
break;
case UWX_REG_LC:
status = __uc_get_ar(&info->ucontext, 65, dp);
break;
default:
return 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);
}
}
else {
if (regid < UWX_REG_GR(0)) {
switch (regid) {
case UWX_REG_PFS:
ttreg = __ar_pfs;
break;
case UWX_REG_PREDS:
ttreg = __pr;
break;
case UWX_REG_RNAT:
ttreg = __ar_rnat;
break;
case UWX_REG_UNAT:
ttreg = __ar_unat;
break;
case UWX_REG_FPSR:
ttreg = __ar_fpsr;
break;
case UWX_REG_LC:
ttreg = __ar_lc;
break;
default:
return 0;
}
}
else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) {
ttreg = regid - UWX_REG_GR(1) + __r1;
}
else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) {
ttreg = regid - UWX_REG_BR(0) + __b0;
}
else
return 0;
status == ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
ttreg, 8, (uint64_t)loc);
}
if (status != 0)
return 0;
}
return len;
}
int uwx_ttrace_lookupip(
int request,
uint64_t ip,
intptr_t tok,
uint64_t **resultp)
{
struct uwx_ttrace_info *info = (struct uwx_ttrace_info *) tok;
UINT64 handle;
struct load_module_desc desc;
uint64_t *unwind_base;
uint64_t *rvec;
int i;
if (request == UWX_LKUP_LOOKUP) {
TRACE_SELF_LOOKUP(ip)
handle = dlmodinfo((unsigned long) ip, &desc, sizeof(desc),
uwx_ttrace_memcpy, info->pid, info->load_map);
if (handle == 0)
return UWX_LKUP_ERR;
unwind_base = (uint64_t *) desc.unwind_base;
TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base)
i = 0;
rvec = info->rvec;
rvec[i++] = UWX_KEY_TBASE;
rvec[i++] = desc.text_base;
rvec[i++] = UWX_KEY_UFLAGS;
rvec[i++] = unwind_base[0];
rvec[i++] = UWX_KEY_USTART;
rvec[i++] = desc.text_base + unwind_base[1];
rvec[i++] = UWX_KEY_UEND;
rvec[i++] = desc.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;
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.
*/
#ifndef _KERNEL
#include <signal.h>
#endif
struct uwx_ttrace_info;
extern struct uwx_ttrace_info *uwx_ttrace_init_info(
struct uwx_env *env,
pid_t pid,
lwpid_t lwpid,
uint64_t load_map);
extern int uwx_ttrace_free_info(struct uwx_ttrace_info *info);
extern int uwx_ttrace_init_context(
struct uwx_env *env,
struct uwx_ttrace_info *info);
extern int uwx_ttrace_init_from_sigcontext(
struct uwx_env *env,
struct uwx_ttrace_info *info,
uint64_t ucontext);
extern int uwx_ttrace_do_context_frame(
struct uwx_env *env,
struct uwx_ttrace_info *info);
extern int uwx_ttrace_copyin(
int request,
char *loc,
uint64_t rem,
int len,
intptr_t tok);
extern int uwx_ttrace_lookupip(
int request,
uint64_t ip,
intptr_t tok,
uint64_t **resultp);
#define UWX_TT_ERR_BADABICONTEXT (-101)
#define UWX_TT_ERR_TTRACE (-102)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
/*
* 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.
*/
struct uwx_utable_entry;
extern int uwx_decode_uinfo(
struct uwx_env *env,
struct uwx_utable_entry *uentry,
uint64_t **rstatep);
extern int uwx_default_rstate(
struct uwx_env *env,
uint64_t **rstatep);
/* Region header record */
struct uwx_rhdr {
int is_prologue; /* true if prologue region */
unsigned int rlen; /* length of region (# instruction slots) */
int mask; /* register save mask */
int grsave; /* first gr used for saving */
unsigned int ecount; /* epilogue count (0 = no epilogue) */
unsigned int epilogue_t; /* epilogue "t" value */
};
struct uwx_bstream;
extern int uwx_decode_rhdr(
struct uwx_env *env,
struct uwx_bstream *bstream,
struct uwx_rhdr *rhdr);
extern int uwx_decode_prologue(
struct uwx_env *env,
struct uwx_bstream *bstream,
struct uwx_scoreboard *scoreboard,
struct uwx_rhdr *rhdr,
int ip_slot);
extern int uwx_decode_body(
struct uwx_env *env,
struct uwx_bstream *bstream,
struct uwx_scoreboard *scoreboard,
struct uwx_rhdr *rhdr,
int ip_slot);

View File

@ -0,0 +1,255 @@
/*
* 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.
*/
#include "uwx_env.h"
#include "uwx_utable.h"
#include "uwx_swap.h"
#include "uwx_trace.h"
/*
* uwx_utable.c
*
* This file contains the routines for searching an unwind table.
* The main entry point, uwx_search_utable(), gets the
* necessary information from the lookup ip callback's result
* vector, determines whether the table is 32-bit or 64-bit,
* then invokes the binary search routine for that format.
*/
/* Forward declarations */
int uwx_search_utable32(
struct uwx_env *env,
uint32_t text_base,
uint32_t unwind_start,
uint32_t unwind_end,
struct uwx_utable_entry *uentry);
int uwx_search_utable64(
struct uwx_env *env,
uint64_t text_base,
uint64_t unwind_start,
uint64_t unwind_end,
struct uwx_utable_entry *uentry);
/* uwx_search_utable: Searches an unwind table for IP in current context */
int uwx_search_utable(
struct uwx_env *env,
uint64_t *uvec,
struct uwx_utable_entry *uentry)
{
uint64_t text_base = 0;
uint64_t unwind_flags;
uint64_t unwind_start = 0;
uint64_t unwind_end = 0;
int keys;
int status;
/* Get unwind table information from the result vector. */
/* Make sure all three required values are given. */
keys = 0;
unwind_flags = 0;
while (*uvec != 0) {
switch ((int)*uvec++) {
case UWX_KEY_TBASE:
keys |= 1;
text_base = *uvec++;
break;
case UWX_KEY_UFLAGS:
unwind_flags = *uvec++;
break;
case UWX_KEY_USTART:
keys |= 2;
unwind_start = *uvec++;
break;
case UWX_KEY_UEND:
keys |= 4;
unwind_end = *uvec++;
break;
default:
return UWX_ERR_BADKEY;
}
}
if (keys != 7)
return UWX_ERR_BADKEY;
/* Copy the unwind flags into the unwind entry. */
/* (uwx_decode_uinfo needs to know whether it's 32-bit or 64-bit.) */
uentry->unwind_flags = unwind_flags;
/* Call the appropriate binary search routine. */
if (unwind_flags & UNWIND_TBL_32BIT)
status = uwx_search_utable32(env,
(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);
return status;
}
/* uwx_search_utable32: Binary search of 32-bit unwind table */
#define COPYIN_UINFO_4(dest, src) \
(env->remote? \
(*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
WORDSZ, env->cb_token) : \
(*(uint32_t *)(dest) = *(uint32_t *)(src), WORDSZ) )
int uwx_search_utable32(
struct uwx_env *env,
uint32_t text_base,
uint32_t unwind_start,
uint32_t unwind_end,
struct uwx_utable_entry *uentry)
{
int lb;
int ub;
int mid = 0;
int len;
uint32_t ip;
uint32_t code_start;
uint32_t code_end;
uint32_t unwind_info;
/* 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;
TRACE_T_SEARCH32(ip)
/* Standard binary search. */
/* Might modify this to do interpolation in the future. */
lb = 0;
ub = (unwind_end - unwind_start) / (3 * WORDSZ);
while (ub > lb) {
mid = (lb + ub) / 2;
len = COPYIN_UINFO_4((char *)&code_start,
(intptr_t)(unwind_start+mid*3*WORDSZ));
len += COPYIN_UINFO_4((char *)&code_end,
(intptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ));
if (len != 2 * WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap) {
uwx_swap4(&code_start);
uwx_swap4(&code_end);
}
TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end)
if (ip >= code_end)
lb = mid + 1;
else if (ip < code_start)
ub = mid;
else
break;
}
if (ub <= lb)
return UWX_ERR_NOUENTRY;
len = COPYIN_UINFO_4((char *)&unwind_info,
(intptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ));
if (len != WORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap)
uwx_swap4(&unwind_info);
uentry->code_start = text_base + code_start;
uentry->code_end = text_base + code_end;
uentry->unwind_info = text_base + unwind_info;
return UWX_OK;
}
/* uwx_search_utable64: Binary search of 64-bit unwind table */
#define COPYIN_UINFO_8(dest, src) \
(env->remote? \
(*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
DWORDSZ, env->cb_token) : \
(*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
int uwx_search_utable64(
struct uwx_env *env,
uint64_t text_base,
uint64_t unwind_start,
uint64_t unwind_end,
struct uwx_utable_entry *uentry)
{
int lb;
int ub;
int mid = 0;
int len;
uint64_t ip;
uint64_t code_start;
uint64_t code_end;
uint64_t unwind_info;
/* 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;
/* Standard binary search. */
/* Might modify this to do interpolation in the future. */
lb = 0;
ub = (unwind_end - unwind_start) / (3 * DWORDSZ);
while (ub > lb) {
mid = (lb + ub) / 2;
len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ);
len += COPYIN_UINFO_8((char *)&code_end,
unwind_start+mid*3*DWORDSZ+DWORDSZ);
if (len != 2 * DWORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap) {
uwx_swap8(&code_start);
uwx_swap8(&code_end);
}
if (ip >= code_end)
lb = mid + 1;
else if (ip < code_start)
ub = mid;
else
break;
}
if (ub <= lb)
return UWX_ERR_NOUENTRY;
len = COPYIN_UINFO_8((char *)&unwind_info,
unwind_start+mid*3*DWORDSZ+2*DWORDSZ);
if (len != DWORDSZ)
return UWX_ERR_COPYIN_UTBL;
if (env->byte_swap)
uwx_swap8(&unwind_info);
uentry->code_start = text_base + code_start;
uentry->code_end = text_base + code_end;
uentry->unwind_info = text_base + unwind_info;
return UWX_OK;
}

View File

@ -0,0 +1,33 @@
/*
* 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.
*/
struct uwx_utable_entry {
uint64_t code_start;
uint64_t code_end;
uint64_t unwind_info;
uint64_t unwind_flags;
};
extern int uwx_search_utable(
struct uwx_env *env,
uint64_t *uvec,
struct uwx_utable_entry *uentry);

View File

@ -0,0 +1,13 @@
UWXINCDIR = ../include
UWXLIBDIR = ../lib/ipf32
CFLAGS = -O -I $(UWXINCDIR)
LDFLAGS = -L $(UWXLIBDIR)
dumpmyself: dumpmyself.o dump_context.o
$(CC) -o dumpmyself $(LDFLAGS) dumpmyself.o dump_context.o -luwx
dumpmyself.o: $(UWXINCDIR)/uwx.h $(UWXINCDIR)/uwx_self.h
dump_context.o:

View File

@ -0,0 +1,70 @@
/*
* 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.
*/
#include <stdio.h>
#include <inttypes.h>
void dump_context(uint64_t *context)
{
int i, j;
uint64_t val;
static char *names[] = {
"ip", "sp", "bsp", "cfm",
"rp", "psp", "pfs", "preds",
"priunat", "bspstore", "rnat", "unat",
"fpsr", "lc",
"gr4", "gr5", "gr6", "gr7",
"br1", "br2", "br3", "br4", "br5"
};
static int order[] = {
0, 14,
1, 15,
2, 16,
3, 17,
7, 18,
8, 19,
10, 20,
11, 21,
12, 22,
13, -1
};
for (i = 0; i < 20; i += 2) {
j = order[i];
if (j >= 0) {
val = context[j+1];
printf(" %-8s %08x %08x", names[j],
(unsigned int)(val >> 32),
(unsigned int)val);
}
else
printf(" ");
j = order[i+1];
if (j >= 0) {
val = context[j+1];
printf(" %-8s %08x %08x", names[j],
(unsigned int)(val >> 32),
(unsigned int)val);
}
putchar('\n');
}
}

View File

@ -0,0 +1,101 @@
/*
* 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.
*/
#include "uwx.h"
#include "uwx_self.h"
struct uwx_env *uenv;
struct uwx_self_info *cbinfo;
extern int uwx_get_frame_info(struct uwx_env *uenv);
extern void dump_context(uint64_t *context);
int main(int argc, char **argv)
{
int status;
unsigned int *wp;
uenv = uwx_init();
printf("uwx_init returned %08x\n", uenv);
cbinfo = uwx_self_init_info(uenv);
status = uwx_register_callbacks(
uenv,
(intptr_t)cbinfo,
uwx_self_copyin,
uwx_self_lookupip);
printf("uwx_register_callbacks returned %d\n", status);
uwx_self_init_context(uenv);
printf("In main():\n");
dump_context((uint64_t *)uenv);
(void) f1();
uwx_free(uenv);
return 0;
}
int f1(void)
{
uwx_self_init_context(uenv);
printf("In f1():\n");
dump_context((uint64_t *)uenv);
return f2();
}
int f2(void)
{
uwx_self_init_context(uenv);
printf("In f2():\n");
dump_context((uint64_t *)uenv);
return f3();
}
int f3(void)
{
uwx_self_init_context(uenv);
printf("In f3():\n");
dump_context((uint64_t *)uenv);
return f4();
}
int f4(void)
{
int status;
int foo[10];
f5(foo);
uwx_self_init_context(uenv);
printf("In f4():\n");
dump_context((uint64_t *)uenv);
for (;;) {
status = uwx_step(uenv);
printf("uwx_step returned %d\n", status);
if (status != UWX_OK)
break;
printf("After step:\n");
dump_context((uint64_t *)uenv);
}
return 0;
}
int f5(int *foo)
{
foo[0] = 0;
return 0;
}