root/arch/arm/probes/uprobes/actions-arm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uprobes_substitute_pc
  2. uprobe_set_pc
  3. uprobe_unset_pc
  4. uprobe_aluwrite_pc
  5. uprobe_write_pc
  6. decode_pc_ro
  7. decode_wb_pc
  8. decode_rd12rn16rm0rs8_rwflags
  9. decode_ldr
  10. uprobe_decode_ldmstm

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/types.h>
   8 #include <linux/stddef.h>
   9 #include <linux/wait.h>
  10 #include <linux/uprobes.h>
  11 #include <linux/module.h>
  12 
  13 #include "../decode.h"
  14 #include "../decode-arm.h"
  15 #include "core.h"
  16 
  17 static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
  18 {
  19         probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
  20         probes_opcode_t temp;
  21         probes_opcode_t mask;
  22         int freereg;
  23         u32 free = 0xffff;
  24         u32 regs;
  25 
  26         for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
  27                 if ((regs & 0xf) == REG_TYPE_NONE)
  28                         continue;
  29 
  30                 free &= ~(1 << (insn & 0xf));
  31         }
  32 
  33         /* No PC, no problem */
  34         if (free & (1 << 15))
  35                 return 15;
  36 
  37         if (!free)
  38                 return -1;
  39 
  40         /*
  41          * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
  42          * pick LR instead of R1.
  43          */
  44         freereg = free = fls(free) - 1;
  45 
  46         temp = __mem_to_opcode_arm(*pinsn);
  47         insn = temp;
  48         regs = oregs;
  49         mask = 0xf;
  50 
  51         for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) {
  52                 if ((regs & 0xf) == REG_TYPE_NONE)
  53                         continue;
  54 
  55                 if ((temp & 0xf) != 15)
  56                         continue;
  57 
  58                 insn &= ~mask;
  59                 insn |= free & mask;
  60         }
  61 
  62         *pinsn = __opcode_to_mem_arm(insn);
  63         return freereg;
  64 }
  65 
  66 static void uprobe_set_pc(struct arch_uprobe *auprobe,
  67                           struct arch_uprobe_task *autask,
  68                           struct pt_regs *regs)
  69 {
  70         u32 pcreg = auprobe->pcreg;
  71 
  72         autask->backup = regs->uregs[pcreg];
  73         regs->uregs[pcreg] = regs->ARM_pc + 8;
  74 }
  75 
  76 static void uprobe_unset_pc(struct arch_uprobe *auprobe,
  77                             struct arch_uprobe_task *autask,
  78                             struct pt_regs *regs)
  79 {
  80         /* PC will be taken care of by common code */
  81         regs->uregs[auprobe->pcreg] = autask->backup;
  82 }
  83 
  84 static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe,
  85                                struct arch_uprobe_task *autask,
  86                                struct pt_regs *regs)
  87 {
  88         u32 pcreg = auprobe->pcreg;
  89 
  90         alu_write_pc(regs->uregs[pcreg], regs);
  91         regs->uregs[pcreg] = autask->backup;
  92 }
  93 
  94 static void uprobe_write_pc(struct arch_uprobe *auprobe,
  95                             struct arch_uprobe_task *autask,
  96                             struct pt_regs *regs)
  97 {
  98         u32 pcreg = auprobe->pcreg;
  99 
 100         load_write_pc(regs->uregs[pcreg], regs);
 101         regs->uregs[pcreg] = autask->backup;
 102 }
 103 
 104 enum probes_insn
 105 decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
 106              const struct decode_header *d)
 107 {
 108         struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
 109                                                    asi);
 110         struct decode_emulate *decode = (struct decode_emulate *) d;
 111         u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS;
 112         int reg;
 113 
 114         reg = uprobes_substitute_pc(&auprobe->ixol[0], regs);
 115         if (reg == 15)
 116                 return INSN_GOOD;
 117 
 118         if (reg == -1)
 119                 return INSN_REJECTED;
 120 
 121         auprobe->pcreg = reg;
 122         auprobe->prehandler = uprobe_set_pc;
 123         auprobe->posthandler = uprobe_unset_pc;
 124 
 125         return INSN_GOOD;
 126 }
 127 
 128 enum probes_insn
 129 decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
 130              const struct decode_header *d, bool alu)
 131 {
 132         struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
 133                                                    asi);
 134         enum probes_insn ret = decode_pc_ro(insn, asi, d);
 135 
 136         if (((insn >> 12) & 0xf) == 15)
 137                 auprobe->posthandler = alu ? uprobe_aluwrite_pc
 138                                            : uprobe_write_pc;
 139 
 140         return ret;
 141 }
 142 
 143 enum probes_insn
 144 decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
 145                               struct arch_probes_insn *asi,
 146                               const struct decode_header *d)
 147 {
 148         return decode_wb_pc(insn, asi, d, true);
 149 }
 150 
 151 enum probes_insn
 152 decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi,
 153            const struct decode_header *d)
 154 {
 155         return decode_wb_pc(insn, asi, d, false);
 156 }
 157 
 158 enum probes_insn
 159 uprobe_decode_ldmstm(probes_opcode_t insn,
 160                      struct arch_probes_insn *asi,
 161                      const struct decode_header *d)
 162 {
 163         struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
 164                                                    asi);
 165         unsigned reglist = insn & 0xffff;
 166         int rn = (insn >> 16) & 0xf;
 167         int lbit = insn & (1 << 20);
 168         unsigned used = reglist | (1 << rn);
 169 
 170         if (rn == 15)
 171                 return INSN_REJECTED;
 172 
 173         if (!(used & (1 << 15)))
 174                 return INSN_GOOD;
 175 
 176         if (used & (1 << 14))
 177                 return INSN_REJECTED;
 178 
 179         /* Use LR instead of PC */
 180         insn ^= 0xc000;
 181 
 182         auprobe->pcreg = 14;
 183         auprobe->ixol[0] = __opcode_to_mem_arm(insn);
 184 
 185         auprobe->prehandler = uprobe_set_pc;
 186         if (lbit)
 187                 auprobe->posthandler = uprobe_write_pc;
 188         else
 189                 auprobe->posthandler = uprobe_unset_pc;
 190 
 191         return INSN_GOOD;
 192 }
 193 
 194 const union decode_action uprobes_probes_actions[] = {
 195         [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
 196         [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
 197         [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
 198         [PROBES_MRS] = {.handler = simulate_mrs},
 199         [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
 200         [PROBES_CLZ] = {.handler = probes_simulate_nop},
 201         [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop},
 202         [PROBES_MUL1] = {.handler = probes_simulate_nop},
 203         [PROBES_MUL2] = {.handler = probes_simulate_nop},
 204         [PROBES_SWP] = {.handler = probes_simulate_nop},
 205         [PROBES_LDRSTRD] = {.decoder = decode_pc_ro},
 206         [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro},
 207         [PROBES_LOAD] = {.decoder = decode_ldr},
 208         [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro},
 209         [PROBES_STORE] = {.decoder = decode_pc_ro},
 210         [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
 211         [PROBES_DATA_PROCESSING_REG] = {
 212                 .decoder = decode_rd12rn16rm0rs8_rwflags},
 213         [PROBES_DATA_PROCESSING_IMM] = {
 214                 .decoder = decode_rd12rn16rm0rs8_rwflags},
 215         [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop},
 216         [PROBES_SEV] = {.handler = probes_simulate_nop},
 217         [PROBES_WFE] = {.handler = probes_simulate_nop},
 218         [PROBES_SATURATE] = {.handler = probes_simulate_nop},
 219         [PROBES_REV] = {.handler = probes_simulate_nop},
 220         [PROBES_MMI] = {.handler = probes_simulate_nop},
 221         [PROBES_PACK] = {.handler = probes_simulate_nop},
 222         [PROBES_EXTEND] = {.handler = probes_simulate_nop},
 223         [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop},
 224         [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop},
 225         [PROBES_MUL_ADD] = {.handler = probes_simulate_nop},
 226         [PROBES_BITFIELD] = {.handler = probes_simulate_nop},
 227         [PROBES_BRANCH] = {.handler = simulate_bbl},
 228         [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm}
 229 };

/* [<][>][^][v][top][bottom][index][help] */