diff options
author | marcel <marcel@FreeBSD.org> | 2003-05-15 05:04:44 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-05-15 05:04:44 +0000 |
commit | 1edc7465a0eedb6ceb50376d0ef2bcd13a40e03d (patch) | |
tree | 3f5df6e13c7fb693b40b2b9c2206dc4cd8e0f381 /sys/contrib/ia64 | |
download | FreeBSD-src-1edc7465a0eedb6ceb50376d0ef2bcd13a40e03d.zip FreeBSD-src-1edc7465a0eedb6ceb50376d0ef2bcd13a40e03d.tar.gz |
This is beta4 of libuwx; an ia64 stack unwinder. This code is made
available by Hewlett-Packard under the MIT license. The unwinder is
small, clean and fast and needed little adaptation for use in the
kernel.
This import has embedded in it the changes needed to make it build
in a kernel environment.
To optimize the common case, the kernel will minimize the number
of registers saved by not saving the preserved registers. In case
access to preserved registers is needed (signal handling, ptrace)
the kernel will unwind to the context of the syscall or exception.
For this we need an unwinder.
Approved by: re (blanket)
Diffstat (limited to 'sys/contrib/ia64')
29 files changed, 5320 insertions, 0 deletions
diff --git a/sys/contrib/ia64/libuwx/src/Makefile b/sys/contrib/ia64/libuwx/src/Makefile new file mode 100644 index 0000000..f0f0871 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/Makefile @@ -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 diff --git a/sys/contrib/ia64/libuwx/src/uwx.h b/sys/contrib/ia64/libuwx/src/uwx.h new file mode 100644 index 0000000..82a264b --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx.h @@ -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) diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.c b/sys/contrib/ia64/libuwx/src/uwx_bstream.c new file mode 100644 index 0000000..6ebe8c4 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.c @@ -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 diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.h b/sys/contrib/ia64/libuwx/src/uwx_bstream.h new file mode 100644 index 0000000..1a64e89 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.c b/sys/contrib/ia64/libuwx/src/uwx_context.c new file mode 100644 index 0000000..9da3db3 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_context.c @@ -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; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.h b/sys/contrib/ia64/libuwx/src/uwx_context.h new file mode 100644 index 0000000..5f80bf0 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_context.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.c b/sys/contrib/ia64/libuwx/src/uwx_env.c new file mode 100644 index 0000000..406d156 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_env.c @@ -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; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.h b/sys/contrib/ia64/libuwx/src/uwx_env.h new file mode 100644 index 0000000..4f662e4 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_env.h @@ -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; diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c new file mode 100644 index 0000000..fe37559 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c @@ -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; +} + diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h new file mode 100644 index 0000000..ff2b4b8 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.c b/sys/contrib/ia64/libuwx/src/uwx_self.c new file mode 100644 index 0000000..d1c080e --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_self.c @@ -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; + } +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.h b/sys/contrib/ia64/libuwx/src/uwx_self.h new file mode 100644 index 0000000..b916235 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_self.h @@ -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) diff --git a/sys/contrib/ia64/libuwx/src/uwx_self_context.s b/sys/contrib/ia64/libuwx/src/uwx_self_context.s new file mode 100644 index 0000000..fb89e76 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_self_context.s @@ -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 + diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.c b/sys/contrib/ia64/libuwx/src/uwx_step.c new file mode 100644 index 0000000..fcbbb5d --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_step.c @@ -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; +} + diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.c b/sys/contrib/ia64/libuwx/src/uwx_str.c new file mode 100644 index 0000000..9ad1ec3 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_str.c @@ -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; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.h b/sys/contrib/ia64/libuwx/src/uwx_str.h new file mode 100644 index 0000000..98f7516 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_str.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.c b/sys/contrib/ia64/libuwx/src/uwx_swap.c new file mode 100644 index 0000000..237bd90 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_swap.c @@ -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]; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.h b/sys/contrib/ia64/libuwx/src/uwx_swap.h new file mode 100644 index 0000000..edceaaf --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_swap.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.c b/sys/contrib/ia64/libuwx/src/uwx_trace.c new file mode 100644 index 0000000..695192a --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_trace.c @@ -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]); +} + diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.h b/sys/contrib/ia64/libuwx/src/uwx_trace.h new file mode 100644 index 0000000..4b8cdaa --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_trace.h @@ -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 */ + diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.c b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c new file mode 100644 index 0000000..a506ed0 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c @@ -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; + } +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.h b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h new file mode 100644 index 0000000..232afea --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h @@ -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) diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c new file mode 100644 index 0000000..1244026 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c @@ -0,0 +1,1103 @@ +/* + * 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_utable.h" +#include "uwx_scoreboard.h" +#include "uwx_bstream.h" +#include "uwx_trace.h" +#include "uwx_swap.h" + +int uwx_count_ones(unsigned int mask); + +/* + * uwx_uinfo.c + * + * This file contains the routines for reading and decoding + * the unwind information block. + * + * The main entry point, uwx_decode_uinfo(), is given a pointer + * to an unwind table entry and a pointer (passed by reference) + * to be filled in with a pointer to an update vector. It will + * read and decode the unwind descriptors contained in the + * unwind information block, then build the register state array, + * which describes the actions necessary to step from the current + * frame to the previous one. + */ + +#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) ) + +#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) ) + + +/* uwx_default_rstate: Returns the default register state for a leaf routine */ + +int uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep) +{ + struct uwx_scoreboard *sb; + + sb = uwx_init_scoreboards(env); + *rstatep = sb->rstate; + return UWX_OK; +} + + +/* uwx_decode_uinfo: Decodes unwind info region */ + +int uwx_decode_uinfo( + struct uwx_env *env, + struct uwx_utable_entry *uentry, + uint64_t **rstatep) +{ + uint64_t uinfohdr; + unsigned int ulen; + int len; + struct uwx_bstream bstream; + struct uwx_scoreboard *scoreboard; + int ip_slot; + int cur_slot; + int status; + struct uwx_rhdr rhdr; + + /* Remember the offset from the start of the function */ + /* to the current IP. This helps the client find */ + /* the symbolic information. */ + + env->function_offset = env->context.special[UWX_REG_IP] - + uentry->code_start; + + /* Read the unwind info header using the copyin callback. */ + /* (If we're reading a 32-bit unwind table, we need to */ + /* read the header as two 32-bit pieces to preserve the */ + /* guarantee that we always call copyin for aligned */ + /* 4-byte or 8-byte chunks.) */ + /* Then compute the length of the unwind descriptor */ + /* region and initialize a byte stream to read it. */ + + if (uentry->unwind_flags & UNWIND_TBL_32BIT) { + len = COPYIN_UINFO_4((char *)&uinfohdr, uentry->unwind_info); + len += COPYIN_UINFO_4((char *)&uinfohdr + WORDSZ, + uentry->unwind_info + WORDSZ); + } + else + len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info); + if (len != DWORDSZ) + return UWX_ERR_COPYIN_UINFO; + if (env->byte_swap) + uwx_swap8(&uinfohdr); + if (uentry->unwind_flags & UNWIND_TBL_32BIT) + ulen = UNW_LENGTH(uinfohdr) * WORDSZ; + else + ulen = UNW_LENGTH(uinfohdr) * DWORDSZ; + uwx_init_bstream(&bstream, env, + uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO); + + TRACE_R_UIB(uentry, ulen) + + /* Create an initial scoreboard for tracking the unwind state. */ + + scoreboard = uwx_init_scoreboards(env); + + /* Prepare to read and decode the unwind regions described */ + /* by the unwind info block. Find the target "ip" slot */ + /* relative to the beginning of the region. The lower 4 bits */ + /* of the actual IP encode the slot number within a bundle. */ + + cur_slot = 0; + ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL) + - uentry->code_start) + / BUNDLESZ * SLOTSPERBUNDLE + + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f); + + /* Loop over the regions in the unwind info block. */ + + for (;;) { + + /* Decode the next region header. */ + /* We have an error if we reach the end of the info block, */ + /* since we should have found our target ip slot by then. */ + /* We also have an error if the next byte isn't a region */ + /* header record. */ + + status = uwx_decode_rhdr(env, &bstream, &rhdr); + if (status != UWX_OK) + return status; + + /* If a prologue region, get a new scoreboard, pushing */ + /* the previous one onto the prologue stack. Then read */ + /* and decode the prologue region records. */ + + if (rhdr.is_prologue) { + scoreboard = uwx_new_scoreboard(env, scoreboard); + if (scoreboard == 0) + return UWX_ERR_NOMEM; + status = uwx_decode_prologue(env, &bstream, + scoreboard, &rhdr, ip_slot); + } + + /* If a body region, read and decode the body region */ + /* records. If the body has an epilogue count, */ + /* uwx_decode_body will note that in the region header */ + /* record for use at the bottom of the loop. */ + + else { + status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot); + } + + if (status != UWX_OK) + return status; + + TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) + + /* If the target ip slot is within this region, we're done. */ + /* Return the scoreboard's register state array. */ + + if (ip_slot < rhdr.rlen) { + *rstatep = scoreboard->rstate; + return UWX_OK; + } + + /* Otherwise, update the current ip slot, pop the */ + /* scoreboard stack based on the epilogue count, */ + /* and loop back around for the next region. */ + + cur_slot += rhdr.rlen; + ip_slot -= rhdr.rlen; + if (rhdr.ecount > 0) { + scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount); + if (scoreboard == 0) + return UWX_ERR_PROLOG_UF; + } + } + /*NOTREACHED*/ +} + + +/* uwx_decode_rhdr: Decodes a region header record */ + +int uwx_decode_rhdr( + struct uwx_env *env, + struct uwx_bstream *bstream, + struct uwx_rhdr *rhdr) +{ + int b0; + int b1; + uint64_t val; + int status; + + /* Get the first byte of the next descriptor record. */ + b0 = uwx_get_byte(bstream); + if (b0 < 0) + return UWX_ERR_NOUDESC; + + /* Initialize region header record. */ + + rhdr->is_prologue = 0; + rhdr->rlen = 0; + rhdr->mask = 0; + rhdr->grsave = 0; + rhdr->ecount = 0; + + /* Format R1 */ + + if (b0 < 0x40) { + if ((b0 & 0x20) == 0) { + TRACE_I_DECODE_RHDR_1("(R1) prologue", b0) + rhdr->is_prologue = 1; + } + else + TRACE_I_DECODE_RHDR_1("(R1) body", b0) + rhdr->rlen = b0 & 0x1f; + } + + /* Format R2 */ + + else if (b0 < 0x60) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + status = uwx_get_uleb128(bstream, &val); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val) + rhdr->is_prologue = 1; + rhdr->rlen = (unsigned int) val; + rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7); + rhdr->grsave = b1 & 0x7f; + } + + /* Format R3 */ + + else if (b0 < 0x80) { + status = uwx_get_uleb128(bstream, &val); + if (status != 0) + return UWX_ERR_BADUDESC; + if ((b0 & 0x03) == 0) { + TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val) + rhdr->is_prologue = 1; + } + else + TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val) + rhdr->rlen = (unsigned int) val; + } + + /* Otherwise, not a region header record. */ + + else { + TRACE_I_DECODE_RHDR_1("(?)", b0) + return UWX_ERR_BADUDESC; + } + + return UWX_OK; +} + + +/* uwx_decode_prologue: Decodes a prologue region */ + +int uwx_decode_prologue( + struct uwx_env *env, + struct uwx_bstream *bstream, + struct uwx_scoreboard *scoreboard, + struct uwx_rhdr *rhdr, + int ip_slot) +{ + int status; + int reg; + int mask; + int b0; + int b1; + int b2; + int b3; + int r; + int t; + int i; + uint64_t parm1; + uint64_t parm2; + uint64_t newrstate[NSBREG]; + int tspill[NSBREG]; + int priunat_mem_rstate; + int t_priunat_mem; + unsigned int gr_mem_mask; + unsigned int br_mem_mask; + unsigned int fr_mem_mask; + unsigned int gr_gr_mask; + unsigned int br_gr_mask; + int ngr; + int nbr; + int nfr; + unsigned int spill_base; + unsigned int gr_base; + unsigned int br_base; + unsigned int fr_base; + + /* Initialize an array of register states from the current */ + /* scoreboard, along with a parallel array of spill times. */ + /* We use this as a temporary scoreboard, then update the */ + /* real scoreboard at the end of the procedure. */ + /* We initialize the spill time to (rhdr.rlen - 1) so that */ + /* spills without a "when" descriptor will take effect */ + /* at the end of the prologue region. */ + /* (Boundary condition: all actions in a zero-length prologue */ + /* will appear to have happened in the instruction slot */ + /* immediately preceding the prologue.) */ + + for (i = 0; i < env->nsbreg; i++) { + newrstate[i] = scoreboard->rstate[i]; + tspill[i] = rhdr->rlen - 1; + } + priunat_mem_rstate = UWX_DISP_NONE; + t_priunat_mem = rhdr->rlen - 1; + + fr_mem_mask = 0; + gr_mem_mask = 0; + br_mem_mask = 0; + gr_gr_mask = 0; + br_gr_mask = 0; + nfr = 0; + ngr = 0; + nbr = 0; + spill_base = 0; + + /* If prologue_gr header record supplied mask and grsave, */ + /* record these in the scoreboard. */ + + reg = rhdr->grsave; + mask = rhdr->mask; + if (mask & 0x8) { + newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + if (mask & 0x4) { + newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + if (mask & 0x2) { + newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + if (mask & 0x1) { + newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + + /* Read prologue descriptor records until */ + /* we hit another region header. */ + + for (;;) { + + b0 = uwx_get_byte(bstream); + + if (b0 < 0x80) { + /* Return the last byte read to the byte stream, since it's */ + /* really the first byte of the next region header record. */ + if (b0 >= 0) + (void) uwx_unget_byte(bstream, b0); + break; + } + + switch ((b0 & 0x70) >> 4) { + + case 0: /* 1000 xxxx */ + case 1: /* 1001 xxxx */ + /* Format P1 (br_mem) */ + TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0) + br_mem_mask = b0 & 0x1f; + break; + + case 2: /* 1010 xxxx */ + /* Format P2 (br_gr) */ + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1) + mask = ((b0 & 0x0f) << 1) | (b1 >> 7); + reg = b1 & 0x7f; + br_gr_mask = mask; + for (i = 0; i < NSB_BR && mask != 0; i++) { + if (mask & 0x01) { + newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + mask = mask >> 1; + } + break; + + case 3: /* 1011 xxxx */ + /* Format P3 */ + if (b0 < 0xb8) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + r = ((b0 & 0x3) << 1) | (b1 >> 7); + reg = b1 & 0x7f; + switch (r) { + case 0: /* psp_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1) + newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 1: /* rp_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1) + newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 2: /* pfs_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1) + newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 3: /* preds_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1) + newrstate[SBREG_PREDS] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 4: /* unat_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1) + newrstate[SBREG_UNAT] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 5: /* lc_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1) + newrstate[SBREG_LC] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 6: /* rp_br */ + TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1) + scoreboard->rstate[SBREG_RP] = + UWX_DISP_REG(UWX_REG_BR(reg)); + break; + case 7: /* rnat_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1) + newrstate[SBREG_RNAT] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 8: /* bsp_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 9: /* bspstore_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1) + /* Don't track BSPSTORE yet */ + return UWX_ERR_CANTUNWIND; + break; + case 10: /* fpsr_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1) + newrstate[SBREG_FPSR] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + case 11: /* priunat_gr */ + TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1) + newrstate[SBREG_PRIUNAT] = + UWX_DISP_REG(UWX_REG_GR(reg)); + break; + default: + TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1) + return UWX_ERR_BADUDESC; + } + } + + /* Format P4 (spill_mask) */ + else if (b0 == 0xb8) { + TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0) + /* The spill_mask descriptor is followed by */ + /* an imask field whose length is determined */ + /* by the region length: there are two mask */ + /* bits per instruction slot in the region. */ + /* We decode these bits two at a time, counting */ + /* the number of FRs, GRs, and BRs that are */ + /* saved up to the slot of interest. Other */ + /* descriptors describe which sets of these */ + /* registers are spilled, and we put those */ + /* two pieces of information together at the */ + /* end of the main loop. */ + t = 0; + while (t < rhdr->rlen) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + for (i = 0; i < 4 && (t + i) < ip_slot; i++) { + switch (b1 & 0xc0) { + case 0x00: break; + case 0x40: nfr++; break; + case 0x80: ngr++; break; + case 0xc0: nbr++; break; + } + b1 = b1 << 2; + } + t += 4; + } + } + + /* Format P5 (frgr_mem) */ + else if (b0 == 0xb9) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + b3 = uwx_get_byte(bstream); + if (b3 < 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3) + gr_mem_mask = b1 >> 4; + fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3; + } + + /* Invalid descriptor record */ + else { + TRACE_I_DECODE_PROLOGUE_1("(?)", b0) + return UWX_ERR_BADUDESC; + } + + break; + + case 4: /* 1100 xxxx */ + /* Format P6 (fr_mem) */ + TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0) + fr_mem_mask = b0 & 0x0f; + break; + + case 5: /* 1101 xxxx */ + /* Format P6 (gr_mem) */ + TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0) + gr_mem_mask = b0 & 0x0f; + break; + + case 6: /* 1110 xxxx */ + /* Format P7 */ + r = b0 & 0xf; + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + switch (r) { + case 0: /* mem_stack_f */ + status = uwx_get_uleb128(bstream, &parm2); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2) + newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16); + tspill[SBREG_PSP] = (int) parm1; + break; + case 1: /* mem_stack_v */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1) + tspill[SBREG_PSP] = (int) parm1; + break; + case 2: /* spill_base */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1) + spill_base = 4 * (unsigned int) parm1; + break; + case 3: /* psp_sprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1) + newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4); + break; + case 4: /* rp_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1) + tspill[SBREG_RP] = (int) parm1; + break; + case 5: /* rp_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1) + newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 6: /* pfs_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1) + tspill[SBREG_PFS] = (int) parm1; + break; + case 7: /* pfs_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1) + newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 8: /* preds_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1) + tspill[SBREG_PREDS] = (int) parm1; + break; + case 9: /* preds_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1) + newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 10: /* lc_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1) + tspill[SBREG_LC] = (int) parm1; + break; + case 11: /* lc_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1) + newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 12: /* unat_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1) + tspill[SBREG_UNAT] = (int) parm1; + break; + case 13: /* unat_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1) + newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 14: /* fpsr_when */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1) + tspill[SBREG_FPSR] = (int) parm1; + break; + case 15: /* fpsr_psprel */ + TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1) + newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4); + break; + } + break; + + case 7: /* 1111 xxxx */ + /* Format P8 */ + if (b0 == 0xf0) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + switch (b1) { + case 1: /* rp_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1) + newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4); + break; + case 2: /* pfs_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1) + newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4); + break; + case 3: /* preds_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1) + newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4); + break; + case 4: /* lc_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1) + newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4); + break; + case 5: /* unat_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1) + newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4); + break; + case 6: /* fpsr_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1) + newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4); + break; + case 7: /* bsp_when */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 8: /* bsp_psprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 9: /* bsp_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 10: /* bspstore_when */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 11: /* bspstore_psprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 12: /* bspstore_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1) + /* Don't track BSP yet */ + return UWX_ERR_CANTUNWIND; + break; + case 13: /* rnat_when */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1) + tspill[SBREG_RNAT] = (int) parm1; + break; + case 14: /* rnat_psprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1) + newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4); + break; + case 15: /* rnat_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1) + newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4); + break; + case 16: /* priunat_when_gr */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1) + tspill[SBREG_PRIUNAT] = (int) parm1; + break; + case 17: /* priunat_psprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1) + priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4); + break; + case 18: /* priunat_sprel */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1) + priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4); + break; + case 19: /* priunat_when_mem */ + TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1) + t_priunat_mem = (int) parm1; + break; + default: + TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1) + return UWX_ERR_BADUDESC; + } + } + + /* Format P9 (gr_gr) */ + else if (b0 == 0xf1) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2) + mask = b1 & 0x0f; + reg = b2 & 0x7f; + gr_gr_mask = mask; + for (i = 0; i < NSB_GR && mask != 0; i++) { + if (mask & 0x01) { + newrstate[SBREG_GR + i] = + UWX_DISP_REG(UWX_REG_GR(reg)); + reg++; + } + mask = mask >> 1; + } + } + + /* Format X1 */ + else if (b0 == 0xf9) { + TRACE_I_DECODE_PROLOGUE_1("(X1)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X2 */ + else if (b0 == 0xfa) { + TRACE_I_DECODE_PROLOGUE_1("(X2)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X3 */ + else if (b0 == 0xfb) { + TRACE_I_DECODE_PROLOGUE_1("(X3)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X4 */ + else if (b0 == 0xfc) { + TRACE_I_DECODE_PROLOGUE_1("(X4)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + b3 = uwx_get_byte(bstream); + if (b3 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format P10 */ + else if (b0 == 0xff) { + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2) + env->abi_context = (b1 << 8) | b2; + return UWX_ABI_FRAME; + } + + /* Invalid descriptor record */ + else { + TRACE_I_DECODE_PROLOGUE_1("(?)", b0) + return UWX_ERR_BADUDESC; + } + break; + } + } + + /* Process the masks of spilled GRs, FRs, and BRs to */ + /* determine when and where each register was saved. */ + + fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask); + br_base = fr_base + 8 * uwx_count_ones(br_mem_mask); + gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask); + TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) + TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) + TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) + for (i = 0; ngr > 0 && i <= NSB_GR; i++) { + if (gr_mem_mask & 1) { + newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base); + tspill[SBREG_GR + i] = 0; + gr_base -= 8; + ngr--; + } + else if (gr_gr_mask & 1) { + tspill[SBREG_GR + i] = 0; + ngr--; + } + gr_gr_mask = gr_gr_mask >> 1; + gr_mem_mask = gr_mem_mask >> 1; + } + for (i = 0; nbr > 0 && i <= NSB_BR; i++) { + if (br_mem_mask & 1) { + newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base); + tspill[SBREG_BR + i] = 0; + br_base -= 8; + nbr--; + } + else if (br_gr_mask & 1) { + tspill[SBREG_BR + i] = 0; + nbr--; + } + br_gr_mask = br_gr_mask >> 1; + br_mem_mask = br_mem_mask >> 1; + } + for (i = 0; nfr > 0 && i <= NSB_FR; i++) { + if (fr_mem_mask & 1) { + newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base); + tspill[SBREG_FR + i] = 0; + fr_base -= 8; + nfr--; + } + fr_mem_mask = fr_mem_mask >> 1; + } + + /* Update the scoreboard. */ + + for (i = 0; i < env->nsbreg; i++) { + if (ip_slot > tspill[i]) + scoreboard->rstate[i] = newrstate[i]; + } + if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem) + scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate; + + return UWX_OK; +} + +int uwx_count_ones(unsigned int mask) +{ + mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1); + mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2); + mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4); + mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8); + return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16); +} + +/* uwx_decode_body: Decodes a body region */ + +int uwx_decode_body( + struct uwx_env *env, + struct uwx_bstream *bstream, + struct uwx_scoreboard *scoreboard, + struct uwx_rhdr *rhdr, + int ip_slot) +{ + int status; + int b0; + int b1; + int b2; + int b3; + int label; + int ecount; + int i; + uint64_t parm1; + uint64_t parm2; + uint64_t newrstate[NSBREG]; + int tspill[NSBREG]; + int t_sp_restore; + + /* Initialize an array of register states from the current */ + /* scoreboard, along with a parallel array of spill times. */ + /* We use this as a temporary scoreboard, then update the */ + /* real scoreboard at the end of the procedure. */ + /* We initialize the spill time to (rhdr.rlen - 1) so that */ + /* spills without a "when" descriptor will take effect */ + /* at the end of the prologue region. */ + /* (Boundary condition: all actions in a zero-length prologue */ + /* will appear to have happened in the instruction slot */ + /* immediately preceding the prologue.) */ + + for (i = 0; i < env->nsbreg; i++) { + newrstate[i] = scoreboard->rstate[i]; + tspill[i] = rhdr->rlen - 1; + } + t_sp_restore = rhdr->rlen - 1; + + /* Read body descriptor records until */ + /* we hit another region header. */ + + for (;;) { + + b0 = uwx_get_byte(bstream); + + if (b0 < 0x80) { + /* Return the last byte read to the byte stream, since it's */ + /* really the first byte of the next region header record. */ + if (b0 >= 0) + (void) uwx_unget_byte(bstream, b0); + break; + } + + /* Format B1 (label_state) */ + if (b0 < 0xa0) { + TRACE_I_DECODE_BODY_1("(B1) label_state", b0) + label = b0 & 0x1f; + status = uwx_label_scoreboard(env, scoreboard, label); + if (status != UWX_OK) + return (status); + } + + /* Format B1 (copy_state) */ + else if (b0 < 0xc0) { + TRACE_I_DECODE_BODY_1("(B1) copy_state", b0) + label = b0 & 0x1f; + status = uwx_copy_scoreboard(env, scoreboard, label); + if (status != UWX_OK) + return (status); + for (i = 0; i < env->nsbreg; i++) { + newrstate[i] = scoreboard->rstate[i]; + tspill[i] = rhdr->rlen; + } + } + + /* Format B2 (epilogue) */ + else if (b0 < 0xe0) { + ecount = b0 & 0x1f; + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1) + rhdr->ecount = ecount + 1; + t_sp_restore = rhdr->rlen - (unsigned int) parm1; + } + + /* Format B3 (epilogue) */ + else if (b0 == 0xe0) { + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + status = uwx_get_uleb128(bstream, &parm2); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2) + t_sp_restore = rhdr->rlen - (unsigned int) parm1; + rhdr->ecount = (unsigned int) parm2 + 1; + } + + /* Format B4 (label_state) */ + else if (b0 == 0xf0) { + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1) + label = (int) parm1; + status = uwx_label_scoreboard(env, scoreboard, label); + if (status != UWX_OK) + return (status); + } + + /* Format B4 (copy_state) */ + else if (b0 == 0xf8) { + status = uwx_get_uleb128(bstream, &parm1); + if (status != 0) + return UWX_ERR_BADUDESC; + TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1) + label = (int) parm1; + status = uwx_copy_scoreboard(env, scoreboard, label); + if (status != UWX_OK) + return (status); + for (i = 0; i < env->nsbreg; i++) { + newrstate[i] = scoreboard->rstate[i]; + tspill[i] = rhdr->rlen; + } + } + + /* Format X1 */ + else if (b0 == 0xf9) { + TRACE_I_DECODE_BODY_1("(X1)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X2 */ + else if (b0 == 0xfa) { + TRACE_I_DECODE_BODY_1("(X2)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X3 */ + else if (b0 == 0xfb) { + TRACE_I_DECODE_BODY_1("(X3)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Format X4 */ + else if (b0 == 0xfc) { + TRACE_I_DECODE_BODY_1("(X4)", b0) + b1 = uwx_get_byte(bstream); + if (b1 < 0) + return UWX_ERR_BADUDESC; + b2 = uwx_get_byte(bstream); + if (b2 < 0) + return UWX_ERR_BADUDESC; + b3 = uwx_get_byte(bstream); + if (b3 < 0) + return UWX_ERR_BADUDESC; + /* Don't support X-format descriptors yet */ + return UWX_ERR_CANTUNWIND; + } + + /* Invalid descriptor record */ + else { + TRACE_I_DECODE_BODY_1("(?)", b0) + return UWX_ERR_BADUDESC; + } + } + + /* Update the scoreboard. */ + + for (i = 0; i < env->nsbreg; i++) { + if (ip_slot > tspill[i]) + scoreboard->rstate[i] = newrstate[i]; + } + + /* If we've passed the point in the epilogue where sp */ + /* is restored, update the scoreboard entry for PSP */ + /* and reset any entries for registers saved in memory. */ + + if (ip_slot > t_sp_restore) { + scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); + for (i = 0; i < env->nsbreg; i++) { + if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) || + UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0)) + scoreboard->rstate[i] = UWX_DISP_NONE; + } + } + + return UWX_OK; +} + diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.h b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h new file mode 100644 index 0000000..b1fbdd9 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.c b/sys/contrib/ia64/libuwx/src/uwx_utable.c new file mode 100644 index 0000000..517f4dd --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.c @@ -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; +} diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.h b/sys/contrib/ia64/libuwx/src/uwx_utable.h new file mode 100644 index 0000000..a6b09a3 --- /dev/null +++ b/sys/contrib/ia64/libuwx/src/uwx_utable.h @@ -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); diff --git a/sys/contrib/ia64/libuwx/test/Makefile b/sys/contrib/ia64/libuwx/test/Makefile new file mode 100644 index 0000000..040d17b --- /dev/null +++ b/sys/contrib/ia64/libuwx/test/Makefile @@ -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: diff --git a/sys/contrib/ia64/libuwx/test/dump_context.c b/sys/contrib/ia64/libuwx/test/dump_context.c new file mode 100644 index 0000000..4084c26 --- /dev/null +++ b/sys/contrib/ia64/libuwx/test/dump_context.c @@ -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'); + } +} diff --git a/sys/contrib/ia64/libuwx/test/dumpmyself.c b/sys/contrib/ia64/libuwx/test/dumpmyself.c new file mode 100644 index 0000000..696798a --- /dev/null +++ b/sys/contrib/ia64/libuwx/test/dumpmyself.c @@ -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; +} |