breakpoint.c revision 5b4f4673ac4baf825eb5250049b97c9de1a1530a
1/* IA64 breakpoint support. Much of this clagged from gdb 2 * -Ian Wienand <ianw@gelato.unsw.edu.au> 10/3/2005 3 */ 4 5#include <sys/ptrace.h> 6#include <string.h> 7#include <assert.h> 8 9#include "breakpoint.h" 10#include "debug.h" 11 12static long long 13extract_bit_field(char *bundle, int from, int len) { 14 long long result = 0LL; 15 int to = from + len; 16 int from_byte = from / 8; 17 int to_byte = to / 8; 18 unsigned char *b = (unsigned char *)bundle; 19 unsigned char c; 20 int lshift; 21 int i; 22 23 c = b[from_byte]; 24 if (from_byte == to_byte) 25 c = ((unsigned char)(c << (8 - to % 8))) >> (8 - to % 8); 26 result = c >> (from % 8); 27 lshift = 8 - (from % 8); 28 29 for (i = from_byte + 1; i < to_byte; i++) { 30 result |= ((long long)b[i]) << lshift; 31 lshift += 8; 32 } 33 34 if (from_byte < to_byte && (to % 8 != 0)) { 35 c = b[to_byte]; 36 c = ((unsigned char)(c << (8 - to % 8))) >> (8 - to % 8); 37 result |= ((long long)c) << lshift; 38 } 39 40 return result; 41} 42 43/* Replace the specified bits in an instruction bundle */ 44static void 45replace_bit_field(char *bundle, long long val, int from, int len) { 46 int to = from + len; 47 int from_byte = from / 8; 48 int to_byte = to / 8; 49 unsigned char *b = (unsigned char *)bundle; 50 unsigned char c; 51 52 if (from_byte == to_byte) { 53 unsigned char left, right; 54 c = b[from_byte]; 55 left = (c >> (to % 8)) << (to % 8); 56 right = 57 ((unsigned char)(c << (8 - from % 8))) >> (8 - from % 8); 58 c = (unsigned char)(val & 0xff); 59 c = (unsigned char)(c << (from % 8 + 8 - to % 8)) >> (8 - 60 to % 8); 61 c |= right | left; 62 b[from_byte] = c; 63 } else { 64 int i; 65 c = b[from_byte]; 66 c = ((unsigned char)(c << (8 - from % 8))) >> (8 - from % 8); 67 c = c | (val << (from % 8)); 68 b[from_byte] = c; 69 val >>= 8 - from % 8; 70 71 for (i = from_byte + 1; i < to_byte; i++) { 72 c = val & 0xff; 73 val >>= 8; 74 b[i] = c; 75 } 76 77 if (to % 8 != 0) { 78 unsigned char cv = (unsigned char)val; 79 c = b[to_byte]; 80 c = c >> (to % 8) << (to % 8); 81 c |= ((unsigned char)(cv << (8 - to % 8))) >> (8 - 82 to % 8); 83 b[to_byte] = c; 84 } 85 } 86} 87 88/* Return the contents of slot N (for N = 0, 1, or 2) in 89 and instruction bundle */ 90static long long 91slotN_contents(char *bundle, int slotnum) { 92 return extract_bit_field(bundle, 5 + 41 * slotnum, 41); 93} 94 95/* Store an instruction in an instruction bundle */ 96 97static void 98replace_slotN_contents(char *bundle, long long instr, int slotnum) { 99 replace_bit_field(bundle, instr, 5 + 41 * slotnum, 41); 100} 101 102typedef enum instruction_type { 103 A, /* Integer ALU ; I-unit or M-unit */ 104 I, /* Non-ALU integer; I-unit */ 105 M, /* Memory ; M-unit */ 106 F, /* Floating-point ; F-unit */ 107 B, /* Branch ; B-unit */ 108 L, /* Extended (L+X) ; I-unit */ 109 X, /* Extended (L+X) ; I-unit */ 110 undefined /* undefined or reserved */ 111} instruction_type; 112 113static enum instruction_type template_encoding_table[32][3] = { 114 {M, I, I}, /* 00 */ 115 {M, I, I}, /* 01 */ 116 {M, I, I}, /* 02 */ 117 {M, I, I}, /* 03 */ 118 {M, L, X}, /* 04 */ 119 {M, L, X}, /* 05 */ 120 {undefined, undefined, undefined}, /* 06 */ 121 {undefined, undefined, undefined}, /* 07 */ 122 {M, M, I}, /* 08 */ 123 {M, M, I}, /* 09 */ 124 {M, M, I}, /* 0A */ 125 {M, M, I}, /* 0B */ 126 {M, F, I}, /* 0C */ 127 {M, F, I}, /* 0D */ 128 {M, M, F}, /* 0E */ 129 {M, M, F}, /* 0F */ 130 {M, I, B}, /* 10 */ 131 {M, I, B}, /* 11 */ 132 {M, B, B}, /* 12 */ 133 {M, B, B}, /* 13 */ 134 {undefined, undefined, undefined}, /* 14 */ 135 {undefined, undefined, undefined}, /* 15 */ 136 {B, B, B}, /* 16 */ 137 {B, B, B}, /* 17 */ 138 {M, M, B}, /* 18 */ 139 {M, M, B}, /* 19 */ 140 {undefined, undefined, undefined}, /* 1A */ 141 {undefined, undefined, undefined}, /* 1B */ 142 {M, F, B}, /* 1C */ 143 {M, F, B}, /* 1D */ 144 {undefined, undefined, undefined}, /* 1E */ 145 {undefined, undefined, undefined}, /* 1F */ 146}; 147 148union bundle_t { 149 char cbundle[16]; 150 unsigned long ubundle[2]; 151}; 152 153void 154arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp) 155{ 156 157 unsigned long addr = (unsigned long)sbp->addr; 158 union bundle_t bundle; 159 int slotnum = (int)(addr & 0x0f) & 0x3; 160 long long instr; 161 int template; 162 163 debug(1, "Enable Breakpoint at %p)", sbp->addr); 164 165 assert(slotnum <= 2); 166 167 addr &= ~0x0f; 168 bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0); 169 bundle.ubundle[1] = ptrace(PTRACE_PEEKTEXT, pid, addr + 8, 0); 170 171 /* Check for L type instruction in 2nd slot, if present then 172 bump up the slot number to the 3rd slot */ 173 template = extract_bit_field(bundle.cbundle, 0, 5); 174 if (slotnum == 1 && template_encoding_table[template][1] == L) { 175 slotnum = 2; 176 } 177 178 instr = slotN_contents(bundle.cbundle, slotnum); 179 180 memcpy(sbp->orig_value, &instr, sizeof(instr)); 181 182 replace_slotN_contents(bundle.cbundle, 0x00002000040LL, slotnum); 183 184 ptrace(PTRACE_POKETEXT, pid, addr, bundle.ubundle[0]); 185 ptrace(PTRACE_POKETEXT, pid, addr + 8, bundle.ubundle[1]); 186 187} 188 189void 190arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp) 191{ 192 193 unsigned long addr = (unsigned long)sbp->addr; 194 int slotnum = (int)(addr & 0x0f) & 0x3; 195 union bundle_t bundle; 196 unsigned long instr; 197 198 debug(1, "Disable Breakpoint at %p", sbp->addr); 199 200 addr &= ~0x0f; 201 202 bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0); 203 bundle.ubundle[1] = ptrace(PTRACE_PEEKTEXT, pid, addr + 8, 0); 204 205 memcpy(&instr, sbp->orig_value, sizeof(instr)); 206 207 replace_slotN_contents(bundle.cbundle, instr, slotnum); 208 ptrace(PTRACE_POKETEXT, pid, addr, bundle.ubundle[0]); 209 ptrace(PTRACE_POKETEXT, pid, addr + 8, bundle.ubundle[1]); 210} 211