Skip to content

Commit 98b54aa

Browse files
committed
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>
1 parent 23bbd8e commit 98b54aa

2 files changed

Lines changed: 26 additions & 31 deletions

File tree

include/linux/kgdb.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc);
207207

208208
/* Optional functions. */
209209
extern int kgdb_validate_break_address(unsigned long addr);
210-
extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
211-
extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
210+
extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
211+
extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
212212

213213
/**
214214
* kgdb_arch_late - Perform any architecture specific initalization.

kernel/debug/debug_core.c

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -161,37 +161,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup);
161161
* Weak aliases for breakpoint management,
162162
* can be overriden by architectures when needed:
163163
*/
164-
int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
164+
int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
165165
{
166166
int err;
167167

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);
169170
if (err)
170171
return err;
171-
172-
return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
173-
BREAK_INSTR_SIZE);
172+
err = probe_kernel_write((char *)bpt->bpt_addr,
173+
arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
174+
return err;
174175
}
175176

176-
int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
177+
int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
177178
{
178-
return probe_kernel_write((char *)addr,
179-
(char *)bundle, BREAK_INSTR_SIZE);
179+
return probe_kernel_write((char *)bpt->bpt_addr,
180+
(char *)bpt->saved_instr, BREAK_INSTR_SIZE);
180181
}
181182

182183
int __weak kgdb_validate_break_address(unsigned long addr)
183184
{
184-
char tmp_variable[BREAK_INSTR_SIZE];
185+
struct kgdb_bkpt tmp;
185186
int err;
186-
/* Validate setting the breakpoint and then removing it. In the
187+
/* Validate setting the breakpoint and then removing it. If the
187188
* remove fails, the kernel needs to emit a bad message because we
188189
* are deep trouble not being able to put things back the way we
189190
* found them.
190191
*/
191-
err = kgdb_arch_set_breakpoint(addr, tmp_variable);
192+
tmp.bpt_addr = addr;
193+
err = kgdb_arch_set_breakpoint(&tmp);
192194
if (err)
193195
return err;
194-
err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
196+
err = kgdb_arch_remove_breakpoint(&tmp);
195197
if (err)
196198
printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
197199
"memory destroyed at: %lx", addr);
@@ -235,7 +237,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
235237
*/
236238
int dbg_activate_sw_breakpoints(void)
237239
{
238-
unsigned long addr;
239240
int error;
240241
int ret = 0;
241242
int i;
@@ -244,16 +245,15 @@ int dbg_activate_sw_breakpoints(void)
244245
if (kgdb_break[i].state != BP_SET)
245246
continue;
246247

247-
addr = kgdb_break[i].bpt_addr;
248-
error = kgdb_arch_set_breakpoint(addr,
249-
kgdb_break[i].saved_instr);
248+
error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
250249
if (error) {
251250
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);
253253
continue;
254254
}
255255

256-
kgdb_flush_swbreak_addr(addr);
256+
kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
257257
kgdb_break[i].state = BP_ACTIVE;
258258
}
259259
return ret;
@@ -302,23 +302,21 @@ int dbg_set_sw_break(unsigned long addr)
302302

303303
int dbg_deactivate_sw_breakpoints(void)
304304
{
305-
unsigned long addr;
306305
int error;
307306
int ret = 0;
308307
int i;
309308

310309
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
311310
if (kgdb_break[i].state != BP_ACTIVE)
312311
continue;
313-
addr = kgdb_break[i].bpt_addr;
314-
error = kgdb_arch_remove_breakpoint(addr,
315-
kgdb_break[i].saved_instr);
312+
error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
316313
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);
318316
ret = error;
319317
}
320318

321-
kgdb_flush_swbreak_addr(addr);
319+
kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
322320
kgdb_break[i].state = BP_SET;
323321
}
324322
return ret;
@@ -352,20 +350,17 @@ int kgdb_isremovedbreak(unsigned long addr)
352350

353351
int dbg_remove_all_break(void)
354352
{
355-
unsigned long addr;
356353
int error;
357354
int i;
358355

359356
/* Clear memory breakpoints. */
360357
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
361358
if (kgdb_break[i].state != BP_ACTIVE)
362359
goto setundefined;
363-
addr = kgdb_break[i].bpt_addr;
364-
error = kgdb_arch_remove_breakpoint(addr,
365-
kgdb_break[i].saved_instr);
360+
error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
366361
if (error)
367362
printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
368-
addr);
363+
kgdb_break[i].bpt_addr);
369364
setundefined:
370365
kgdb_break[i].state = BP_UNDEFINED;
371366
}

0 commit comments

Comments
 (0)