aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/debug
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2012-03-21 11:17:03 -0400
committerJason Wessel <jason.wessel@windriver.com>2012-03-29 18:41:25 -0400
commit98b54aa1a2241b59372468bd1e9c2d207bdba54b (patch)
tree0a6cc3bc8426434a176e0fcb3c2da23d383a5a3b /kernel/debug
parent23bbd8e346f1ef3fc1219c79cea53d8d52b207d8 (diff)
kgdb,debug_core: pass the breakpoint struct instead of address and memory
There is extra state information that needs to be exposed in the kgdb_bpt structure for tracking how a breakpoint was installed. The debug_core only uses the the probe_kernel_write() to install breakpoints, but this is not enough for all the archs. Some arch such as x86 need to use text_poke() in order to install a breakpoint into a read only page. Passing the kgdb_bpt structure to kgdb_arch_set_breakpoint() and kgdb_arch_remove_breakpoint() allows other archs to set the type variable which indicates how the breakpoint was installed. Cc: stable@vger.kernel.org # >= 2.6.36 Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug')
-rw-r--r--kernel/debug/debug_core.c53
1 files changed, 24 insertions, 29 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 3f88a45e6f0a..a7e52ca94563 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -161,37 +161,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup);
161 * Weak aliases for breakpoint management, 161 * Weak aliases for breakpoint management,
162 * can be overriden by architectures when needed: 162 * can be overriden by architectures when needed:
163 */ 163 */
164int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) 164int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
165{ 165{
166 int err; 166 int err;
167 167
168 err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); 168 err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
169 BREAK_INSTR_SIZE);
169 if (err) 170 if (err)
170 return err; 171 return err;
171 172 err = probe_kernel_write((char *)bpt->bpt_addr,
172 return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, 173 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
173 BREAK_INSTR_SIZE); 174 return err;
174} 175}
175 176
176int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) 177int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
177{ 178{
178 return probe_kernel_write((char *)addr, 179 return probe_kernel_write((char *)bpt->bpt_addr,
179 (char *)bundle, BREAK_INSTR_SIZE); 180 (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
180} 181}
181 182
182int __weak kgdb_validate_break_address(unsigned long addr) 183int __weak kgdb_validate_break_address(unsigned long addr)
183{ 184{
184 char tmp_variable[BREAK_INSTR_SIZE]; 185 struct kgdb_bkpt tmp;
185 int err; 186 int err;
186 /* Validate setting the breakpoint and then removing it. In the 187 /* Validate setting the breakpoint and then removing it. If the
187 * remove fails, the kernel needs to emit a bad message because we 188 * remove fails, the kernel needs to emit a bad message because we
188 * are deep trouble not being able to put things back the way we 189 * are deep trouble not being able to put things back the way we
189 * found them. 190 * found them.
190 */ 191 */
191 err = kgdb_arch_set_breakpoint(addr, tmp_variable); 192 tmp.bpt_addr = addr;
193 err = kgdb_arch_set_breakpoint(&tmp);
192 if (err) 194 if (err)
193 return err; 195 return err;
194 err = kgdb_arch_remove_breakpoint(addr, tmp_variable); 196 err = kgdb_arch_remove_breakpoint(&tmp);
195 if (err) 197 if (err)
196 printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " 198 printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
197 "memory destroyed at: %lx", addr); 199 "memory destroyed at: %lx", addr);
@@ -235,7 +237,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
235 */ 237 */
236int dbg_activate_sw_breakpoints(void) 238int dbg_activate_sw_breakpoints(void)
237{ 239{
238 unsigned long addr;
239 int error; 240 int error;
240 int ret = 0; 241 int ret = 0;
241 int i; 242 int i;
@@ -244,16 +245,15 @@ int dbg_activate_sw_breakpoints(void)
244 if (kgdb_break[i].state != BP_SET) 245 if (kgdb_break[i].state != BP_SET)
245 continue; 246 continue;
246 247
247 addr = kgdb_break[i].bpt_addr; 248 error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
248 error = kgdb_arch_set_breakpoint(addr,
249 kgdb_break[i].saved_instr);
250 if (error) { 249 if (error) {
251 ret = error; 250 ret = error;
252 printk(KERN_INFO "KGDB: BP install failed: %lx", addr); 251 printk(KERN_INFO "KGDB: BP install failed: %lx",
252 kgdb_break[i].bpt_addr);
253 continue; 253 continue;
254 } 254 }
255 255
256 kgdb_flush_swbreak_addr(addr); 256 kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
257 kgdb_break[i].state = BP_ACTIVE; 257 kgdb_break[i].state = BP_ACTIVE;
258 } 258 }
259 return ret; 259 return ret;
@@ -302,7 +302,6 @@ int dbg_set_sw_break(unsigned long addr)
302 302
303int dbg_deactivate_sw_breakpoints(void) 303int dbg_deactivate_sw_breakpoints(void)
304{ 304{
305 unsigned long addr;
306 int error; 305 int error;
307 int ret = 0; 306 int ret = 0;
308 int i; 307 int i;
@@ -310,15 +309,14 @@ int dbg_deactivate_sw_breakpoints(void)
310 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { 309 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
311 if (kgdb_break[i].state != BP_ACTIVE) 310 if (kgdb_break[i].state != BP_ACTIVE)
312 continue; 311 continue;
313 addr = kgdb_break[i].bpt_addr; 312 error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
314 error = kgdb_arch_remove_breakpoint(addr,
315 kgdb_break[i].saved_instr);
316 if (error) { 313 if (error) {
317 printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); 314 printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
315 kgdb_break[i].bpt_addr);
318 ret = error; 316 ret = error;
319 } 317 }
320 318
321 kgdb_flush_swbreak_addr(addr); 319 kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
322 kgdb_break[i].state = BP_SET; 320 kgdb_break[i].state = BP_SET;
323 } 321 }
324 return ret; 322 return ret;
@@ -352,7 +350,6 @@ int kgdb_isremovedbreak(unsigned long addr)
352 350
353int dbg_remove_all_break(void) 351int dbg_remove_all_break(void)
354{ 352{
355 unsigned long addr;
356 int error; 353 int error;
357 int i; 354 int i;
358 355
@@ -360,12 +357,10 @@ int dbg_remove_all_break(void)
360 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { 357 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
361 if (kgdb_break[i].state != BP_ACTIVE) 358 if (kgdb_break[i].state != BP_ACTIVE)
362 goto setundefined; 359 goto setundefined;
363 addr = kgdb_break[i].bpt_addr; 360 error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
364 error = kgdb_arch_remove_breakpoint(addr,
365 kgdb_break[i].saved_instr);
366 if (error) 361 if (error)
367 printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", 362 printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
368 addr); 363 kgdb_break[i].bpt_addr);
369setundefined: 364setundefined:
370 kgdb_break[i].state = BP_UNDEFINED; 365 kgdb_break[i].state = BP_UNDEFINED;
371 } 366 }