This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
[PATCH 2/2] traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
- From: "Maciej W. Rozycki" <macro at imgtec dot com>
- To: Ralf Baechle <ralf at linux-mips dot org>
- Cc: Pedro Alves <palves at redhat dot com>, Luis Machado <lgustavo at codesourcery dot com>, <linux-mips at linux-mips dot org>, <gdb at sourceware dot org>
- Date: Fri, 4 Mar 2016 01:44:28 +0000
- Subject: [PATCH 2/2] traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 2 dot 00 dot 1603031303500 dot 9427 at tp dot orcam dot me dot uk>
Follow our own rules set in <asm/siginfo.h> for SIGTRAP signals issued
from `do_watch' and `do_trap_or_bp' by setting the signal code to
TRAP_HWBKPT and TRAP_BRKPT respectively, for Watch exceptions and for
those Breakpoint exceptions whose originating BREAK instruction's code
does not have a special meaning. Keep Trap exceptions unaffected as
these are not debug events.
No existing user software is expected to examine signal codes for these
signals as SI_KERNEL has been always used here. This change makes the
MIPS port more like other Linux ports, which reduces the complexity and
provides for performance improvement in GDB.
Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-sigtrap-code.diff
Index: linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/mips-r2-to-r6-emul.h 2016-03-04 00:56:07.699559000 +0000
+++ linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h 2016-03-04 00:59:49.221206000 +0000
@@ -79,7 +79,7 @@ struct r2_decoder_table {
};
-extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
const char *str);
#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
Index: linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/mips-r2-to-r6-emul.c 2016-03-04 00:56:07.701558000 +0000
+++ linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c 2016-03-04 00:59:49.250211000 +0000
@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs,
switch (rt) {
case tgei_op:
if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
- do_trap_or_bp(regs, 0, "TGEI");
+ do_trap_or_bp(regs, 0, 0, "TGEI");
MIPS_R2_STATS(traps);
break;
case tgeiu_op:
if (regs->regs[rs] >= MIPSInst_UIMM(inst))
- do_trap_or_bp(regs, 0, "TGEIU");
+ do_trap_or_bp(regs, 0, 0, "TGEIU");
MIPS_R2_STATS(traps);
break;
case tlti_op:
if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
- do_trap_or_bp(regs, 0, "TLTI");
+ do_trap_or_bp(regs, 0, 0, "TLTI");
MIPS_R2_STATS(traps);
break;
case tltiu_op:
if (regs->regs[rs] < MIPSInst_UIMM(inst))
- do_trap_or_bp(regs, 0, "TLTIU");
+ do_trap_or_bp(regs, 0, 0, "TLTIU");
MIPS_R2_STATS(traps);
break;
case teqi_op:
if (regs->regs[rs] == MIPSInst_SIMM(inst))
- do_trap_or_bp(regs, 0, "TEQI");
+ do_trap_or_bp(regs, 0, 0, "TEQI");
MIPS_R2_STATS(traps);
break;
case tnei_op:
if (regs->regs[rs] != MIPSInst_SIMM(inst))
- do_trap_or_bp(regs, 0, "TNEI");
+ do_trap_or_bp(regs, 0, 0, "TNEI");
MIPS_R2_STATS(traps);
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c 2016-03-04 00:56:37.858781000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c 2016-03-04 00:59:49.253206000 +0000
@@ -56,6 +56,7 @@
#include <asm/pgtable.h>
#include <asm/ptrace.h>
#include <asm/sections.h>
+#include <asm/siginfo.h>
#include <asm/tlbdebug.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *r
exception_exit(prev_state);
}
-void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
const char *str)
{
siginfo_t info = { 0 };
@@ -928,7 +929,13 @@ void do_trap_or_bp(struct pt_regs *regs,
default:
scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
die_if_kernel(b, regs);
- force_sig(SIGTRAP, current);
+ if (si_code) {
+ info.si_signo = SIGTRAP;
+ info.si_code = si_code;
+ force_sig_info(SIGTRAP, &info, current);
+ } else {
+ force_sig(SIGTRAP, current);
+ }
}
}
@@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *re
break;
}
- do_trap_or_bp(regs, bcode, "Break");
+ do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
out:
set_fs(seg);
@@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *re
tcode = (opcode >> 6) & ((1 << 10) - 1);
}
- do_trap_or_bp(regs, tcode, "Trap");
+ do_trap_or_bp(regs, tcode, 0, "Trap");
out:
set_fs(seg);
@@ -1505,6 +1512,7 @@ asmlinkage void do_mdmx(struct pt_regs *
*/
asmlinkage void do_watch(struct pt_regs *regs)
{
+ siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
enum ctx_state prev_state;
u32 cause;
@@ -1525,7 +1533,7 @@ asmlinkage void do_watch(struct pt_regs
if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
mips_read_watch_registers();
local_irq_enable();
- force_sig(SIGTRAP, current);
+ force_sig_info(SIGTRAP, &info, current);
} else {
mips_clear_watch_registers();
local_irq_enable();