/* * find all asm level function returns and forcibly set the highest bit of the return address */ static unsigned int execute_kernexec_retaddr(void) { rtx insn; // 1. find function returns for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) { // rtl match: (jump_insn 41 40 42 2 (return) fptr.c:42 634 {return_internal} (nil)) // (jump_insn 12 9 11 2 (parallel [ (return) (unspec [ (0) ] UNSPEC_REP) ]) fptr.c:46 635 {return_internal_long} (nil)) // (jump_insn 97 96 98 6 (simple_return) fptr.c:50 -1 (nil) -> simple_return) rtx body; // is it a retn if (!JUMP_P(insn)) continue; body = PATTERN(insn); if (GET_CODE(body) == PARALLEL) body = XVECEXP(body, 0, 0); if (!ANY_RETURN_P(body)) continue; kernexec_instrument_retaddr(insn); } // print_simple_rtl(stderr, get_insns()); // print_rtl(stderr, get_insns()); return 0; }
enum rtx_code classify_insn (rtx x) { if (LABEL_P (x)) return CODE_LABEL; if (GET_CODE (x) == CALL) return CALL_INSN; if (ANY_RETURN_P (x)) return JUMP_INSN; if (GET_CODE (x) == SET) { if (GET_CODE (SET_DEST (x)) == PC) return JUMP_INSN; else if (GET_CODE (SET_SRC (x)) == CALL) return CALL_INSN; else return INSN; } if (GET_CODE (x) == PARALLEL) { int j; bool has_return_p = false; for (j = XVECLEN (x, 0) - 1; j >= 0; j--) if (GET_CODE (XVECEXP (x, 0, j)) == CALL) return CALL_INSN; else if (ANY_RETURN_P (XVECEXP (x, 0, j))) has_return_p = true; else if (GET_CODE (XVECEXP (x, 0, j)) == SET && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC) return JUMP_INSN; else if (GET_CODE (XVECEXP (x, 0, j)) == SET && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) return CALL_INSN; if (has_return_p) return JUMP_INSN; } #ifdef GENERATOR_FILE if (GET_CODE (x) == MATCH_OPERAND || GET_CODE (x) == MATCH_OPERATOR || GET_CODE (x) == MATCH_PARALLEL || GET_CODE (x) == MATCH_OP_DUP || GET_CODE (x) == MATCH_DUP || GET_CODE (x) == PARALLEL) return UNKNOWN; #endif return INSN; }