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