stack_machdep.c revision 331722
1/*- 2 * Copyright (c) 2005 Antoine Brodin 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/mips/mips/stack_machdep.c 331722 2018-03-29 02:50:57Z eadler $"); 29 30#include <sys/types.h> 31#include <sys/systm.h> 32#include <sys/param.h> 33#include <sys/proc.h> 34#include <sys/stack.h> 35 36#include <machine/mips_opcode.h> 37 38#include <machine/pcb.h> 39#include <machine/regnum.h> 40 41static u_register_t 42stack_register_fetch(u_register_t sp, u_register_t stack_pos) 43{ 44 u_register_t * stack = 45 ((u_register_t *)(intptr_t)sp + (size_t)stack_pos/sizeof(u_register_t)); 46 47 return *stack; 48} 49 50static void 51stack_capture(struct stack *st, u_register_t pc, u_register_t sp) 52{ 53 u_register_t ra = 0, i, stacksize; 54 short ra_stack_pos = 0; 55 InstFmt insn; 56 57 stack_zero(st); 58 59 for (;;) { 60 stacksize = 0; 61 if (pc <= (u_register_t)(intptr_t)btext) 62 break; 63 for (i = pc; i >= (u_register_t)(intptr_t)btext; i -= sizeof (insn)) { 64 bcopy((void *)(intptr_t)i, &insn, sizeof insn); 65 switch (insn.IType.op) { 66 case OP_ADDI: 67 case OP_ADDIU: 68 case OP_DADDI: 69 case OP_DADDIU: 70 if (insn.IType.rs != SP || insn.IType.rt != SP) 71 break; 72 stacksize = -(short)insn.IType.imm; 73 break; 74 75 case OP_SW: 76 case OP_SD: 77 if (insn.IType.rs != SP || insn.IType.rt != RA) 78 break; 79 ra_stack_pos = (short)insn.IType.imm; 80 break; 81 default: 82 break; 83 } 84 85 if (stacksize) 86 break; 87 } 88 89 if (stack_put(st, pc) == -1) 90 break; 91 92 for (i = pc; !ra; i += sizeof (insn)) { 93 bcopy((void *)(intptr_t)i, &insn, sizeof insn); 94 95 switch (insn.IType.op) { 96 case OP_SPECIAL: 97 if((insn.RType.func == OP_JR)) 98 { 99 if (ra >= (u_register_t)(intptr_t)btext) 100 break; 101 if (insn.RType.rs != RA) 102 break; 103 ra = stack_register_fetch(sp, 104 ra_stack_pos); 105 if (!ra) 106 goto done; 107 ra -= 8; 108 } 109 break; 110 default: 111 break; 112 } 113 /* eret */ 114 if (insn.word == 0x42000018) 115 goto done; 116 } 117 118 if (pc == ra && stacksize == 0) 119 break; 120 121 sp += stacksize; 122 pc = ra; 123 ra = 0; 124 } 125done: 126 return; 127} 128 129void 130stack_save_td(struct stack *st, struct thread *td) 131{ 132 u_register_t pc, sp; 133 134 if (TD_IS_SWAPPED(td)) 135 panic("stack_save_td: swapped"); 136 if (TD_IS_RUNNING(td)) 137 panic("stack_save_td: running"); 138 139 pc = td->td_pcb->pcb_regs.pc; 140 sp = td->td_pcb->pcb_regs.sp; 141 stack_capture(st, pc, sp); 142} 143 144int 145stack_save_td_running(struct stack *st, struct thread *td) 146{ 147 148 return (EOPNOTSUPP); 149} 150 151void 152stack_save(struct stack *st) 153{ 154 u_register_t pc, sp; 155 156 if (curthread == NULL) 157 panic("stack_save: curthread == NULL"); 158 159 pc = curthread->td_pcb->pcb_regs.pc; 160 sp = curthread->td_pcb->pcb_regs.sp; 161 stack_capture(st, pc, sp); 162} 163