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 | 54ea024a387cfbfd748ad1d2b2ccf18959a4f9da (patch) | |
tree | a4cf90ce9948f9ea926188d00fcf376fd3332a75 /sys/contrib | |
parent | ac48fcc177e0c1e9f20f76f4a6a9ec833537a1e3 (diff) | |
parent | 1edc7465a0eedb6ceb50376d0ef2bcd13a40e03d (diff) | |
download | FreeBSD-src-54ea024a387cfbfd748ad1d2b2ccf18959a4f9da.zip FreeBSD-src-54ea024a387cfbfd748ad1d2b2ccf18959a4f9da.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r115013,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys/contrib')
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; +} |