-/* src/vm/jit/x86_64/md.c - machine dependent x86_64 Linux functions
+/* src/vm/jit/s390/md.c - machine dependent s390 Linux functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes: Edwin Steiner
-
- $Id: md.c 8097 2007-06-17 14:50:16Z pm $
-
*/
+
#define _GNU_SOURCE
#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include <stdlib.h>
#include <ucontext.h>
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/abi.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/stacktrace.h"
int i;
u1 *pv;
methodinfo *m;
-
+
union {
u8 l;
fpreg_t fr;
if (pv == NULL) {
log_println("No java method found at location.");
} else {
- m = ((codeinfo *)(pv + CodeinfoPointer))->m;
+ m = (*(codeinfo **)(pv + CodeinfoPointer))->m;
log_println(
"Java method: class %s, method %s, descriptor %s.",
- utf_bytes(m->class->name), utf_bytes(m->name), utf_bytes(m->descriptor)
+ m->class->name->text, m->name->text, m->descriptor->text
);
}
void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- mcontext_t *_mc;
- u1 *pv;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
- s4 type;
- ptrint val;
- java_objectheader *e;
- s4 base;
- s4 is_null;
+ stackframeinfo sfi;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ int type;
+ intptr_t val;
+ void *p;
+ s4 base;
+ s4 is_null;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
switch (xpc[0]) {
case 0x58: /* L */
case 0x50: /* ST */
+ case 0x55: /* CL (array size check on NULL array) */
base = (xpc[2] >> 4) & 0xF;
if (base == 0) {
is_null = 1;
is_null = 0;
}
break;
+ default:
+ is_null = 0;
+ break;
}
if (! is_null) {
type = EXCEPTION_HARDWARE_NULLPOINTER;
val = 0;
- e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+ /* create stackframeinfo */
+
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
- _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
- _mc->gregs[REG_ITMP1_XPTR] = (ptrint) e;
- _mc->psw.addr = (ptrint) asm_handle_exception;
+ /* Handle the type. */
+
+ p = signal_handle(xpc, type, val);
+
+ /* remove stackframeinfo */
+
+ stacktrace_remove_stackframeinfo(&sfi);
+
+ if (p != NULL) {
+ _mc->gregs[REG_ITMP1_XPTR] = (intptr_t) p;
+ _mc->gregs[REG_ITMP2_XPC] = (intptr_t) xpc;
+ _mc->psw.addr = (intptr_t) asm_handle_exception;
+ }
+ else {
+ _mc->psw.addr = (intptr_t) xpc;
+ }
}
-void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p) {
- ucontext_t *_uc;
- mcontext_t *_mc;
- u1 *xpc;
- u1 *ra;
- u1 *pv;
- u1 *sp;
- s4 type;
- ptrint val;
- java_objectheader *e;
- s4 reg;
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ stackframeinfo sfi;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *xpc;
+ u1 *ra;
+ u1 *pv;
+ u1 *sp;
+ int type;
+ intptr_t val;
+ void *p;
+ s4 reg;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
sp = (u1 *)_mc->gregs[REG_SP];
val = (ptrint)_mc->gregs[reg];
- e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+ /* create stackframeinfo */
+
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+
+ /* Handle the type. */
- _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e;
- _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc;
- _mc->psw.addr = (ptrint) asm_handle_exception;
+ p = signal_handle(xpc, type, val);
+ /* remove stackframeinfo */
+
+ stacktrace_remove_stackframeinfo(&sfi);
+
+ if (p != NULL) {
+ _mc->gregs[REG_ITMP1_XPTR] = (intptr_t) p;
+ _mc->gregs[REG_ITMP2_XPC] = (intptr_t) xpc;
+ _mc->psw.addr = (intptr_t) asm_handle_exception;
+ }
+ else {
+ _mc->psw.addr = (intptr_t) xpc;
+ }
} else {
#if !defined(NDEBUG)
md_dump_context(xpc, _mc);
void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- mcontext_t *_mc;
- u1 *pv;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
- u1 *pc;
- s4 r1, r2;
- s4 type;
- ptrint val;
- java_objectheader *e;
+ stackframeinfo sfi;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ u1 *pc;
+ int r1, r2;
+ int type;
+ intptr_t val;
+ void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
(_mc->gregs[r1 + 1] == 0x80000000) &&
(_mc->gregs[r2] == 0xFFFFFFFF)
) {
- /* handle special case */
+ /* handle special case 0x80000000 / 0xFFFFFFFF that fails on hardware */
/* next instruction */
pc = (u1 *)_mc->psw.addr;
/* reminder */
_mc->psw.addr = (ptrint) pc;
return;
- } else if (_mc->gregs[r2] == 0) {
+ }
+ else if (_mc->gregs[r2] == 0) {
/* division by 0 */
pv = (u1 *)_mc->gregs[REG_PV] - N_PV_OFFSET;
type = EXCEPTION_HARDWARE_ARITHMETIC;
val = 0;
- e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+ /* create stackframeinfo */
+
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+
+ /* Handle the type. */
+
+ p = signal_handle(xpc, type, val);
+
+ /* remove stackframeinfo */
- _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e;
- _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc;
- _mc->psw.addr = (ptrint) asm_handle_exception;
+ stacktrace_remove_stackframeinfo(&sfi);
+
+ _mc->gregs[REG_ITMP1_XPTR] = (intptr_t) p;
+ _mc->gregs[REG_ITMP2_XPC] = (intptr_t) xpc;
+ _mc->psw.addr = (intptr_t) asm_handle_exception;
return;
}
/* on S390 the return address is located on the top of the stackframe */
- ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P));
+ ra = *((u1 **) (sp + framesize - 8));
return ra;
}
offset = *((u2 *)(ra + 2)) & 0xFFF;
+ /* return NULL if no mptr was specified (used for replacement) */
+
+ if (mptr == NULL)
+ return NULL;
+
/* add offset to method pointer */
pa = mptr + offset;
Patch the given replacement point.
*******************************************************************************/
-#if 0
-void md_patch_replacement_point(rplpoint *rp)
+#if defined(ENABLE_REPLACEMENT)
+void md_patch_replacement_point(codeinfo *code, s4 index, rplpoint *rp, u1 *savedmcode)
{
- u8 mcode;
+ assert(0);
+}
+#endif
- /* XXX this is probably unsafe! */
+void md_handle_exception(int32_t *regs, int64_t *fregs, int32_t *out) {
+
+ uint8_t *xptr;
+ uint8_t *xpc;
+ uint8_t *sp;
+ uint8_t *pv;
+ uint8_t *ra;
+ uint8_t *handler;
+ int32_t framesize;
+ int32_t intsave;
+ int32_t fltsave;
+ int64_t *savearea;
+ int i;
+ int reg;
+ int loops = 0;
- /* save the current machine code */
- mcode = *(u8*)rp->pc;
+ /* get registers */
- /* write spinning instruction */
- *(u2*)(rp->pc) = 0xebfe;
+ xptr = *(uint8_t **)(regs + REG_ITMP1_XPTR);
+ xpc = *(uint8_t **)(regs + REG_ITMP2_XPC);
+ sp = *(uint8_t **)(regs + REG_SP);
- /* write 5th byte */
- rp->pc[4] = (rp->mcode >> 32);
- /* write first word */
- *(u4*)(rp->pc) = (u4) rp->mcode;
+ /* initialize number of calle saved int regs to restore to 0 */
+ out[0] = 0;
- /* store saved mcode */
- rp->mcode = mcode;
-
-#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
- {
- u1* u1ptr = rp->pc;
- DISASSINSTR(u1ptr);
- fflush(stdout);
- }
-#endif
-
- /* XXX if required asm_cacheflush(rp->pc,8); */
+ /* initialize number of calle saved flt regs to restore to 0 */
+ out[1] = 0;
+
+ do {
+
+ ++loops;
+
+ pv = codegen_get_pv_from_pc(xpc);
+
+ handler = exceptions_handle_exception(xptr, xpc, pv, sp);
+
+ if (handler == NULL) {
+
+ /* exception was not handled
+ * get values of calee saved registers and remove stack frame
+ */
+
+ /* read stuff from data segment */
+
+ framesize = *(int32_t *)(pv + FrameSize);
+
+ intsave = *(int32_t *)(pv + IntSave);
+ if (intsave > out[0]) {
+ out[0] = intsave;
+ }
+
+ fltsave = *(int32_t *)(pv + FltSave);
+ if (fltsave > out[1]) {
+ out[1] = fltsave;
+ }
+
+ /* pointer to register save area */
+
+ savearea = (int64_t *)(sp + framesize - 8);
+
+ /* return address */
+
+ ra = *(uint8_t **)(sp + framesize - 8);
+
+ /* restore saved registers */
+
+ for (i = 0; i < intsave; ++i) {
+ --savearea;
+ reg = abi_registers_integer_saved[INT_SAV_CNT - 1 - i];
+ regs[reg] = *(int32_t *)(savearea);
+ }
+
+ for (i = 0; i < fltsave; ++i) {
+ --savearea;
+ reg = abi_registers_float_saved[FLT_SAV_CNT - 1 - i];
+ fregs[reg] = *savearea;
+ }
+
+ /* remove stack frame */
+
+ sp += framesize;
+
+ /* new xpc is call before return address */
+
+ xpc = ra;
+
+ } else {
+ xpc = handler;
+ }
+ } while (handler == NULL);
+
+ /* write new values for registers */
+
+ *(uint8_t **)(regs + REG_ITMP1_XPTR) = xptr;
+ *(uint8_t **)(regs + REG_ITMP2_XPC) = xpc;
+ *(uint8_t **)(regs + REG_SP) = sp;
+ *(uint8_t **)(regs + REG_PV) = pv - 0XFFC;
+
+ /* maybe leaf flag */
+
+ out[2] = (loops == 1);
}
-#endif
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where