## Automatically generated incremental diff
## From: linux-2.6.10-bk4
## To: linux-2.6.10-bk5
## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $
diff -urN linux-2.6.10-bk4/arch/i386/kernel/ptrace.c linux-2.6.10-bk5/arch/i386/kernel/ptrace.c
--- linux-2.6.10-bk4/arch/i386/kernel/ptrace.c 2004-12-24 13:34:29.000000000 -0800
+++ linux-2.6.10-bk5/arch/i386/kernel/ptrace.c 2005-01-02 04:55:14.135194305 -0800
@@ -42,6 +42,12 @@
*/
#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
+static inline struct pt_regs *get_child_regs(struct task_struct *task)
+{
+ void *stack_top = (void *)task->thread.esp0;
+ return stack_top - sizeof(struct pt_regs);
+}
+
/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the TSS.
@@ -138,24 +144,119 @@
return retval;
}
+#define LDT_SEGMENT 4
+
+static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_regs *regs)
+{
+ unsigned long addr, seg;
+
+ addr = regs->eip;
+ seg = regs->xcs & 0xffff;
+ if (regs->eflags & VM_MASK) {
+ addr = (addr & 0xffff) + (seg << 4);
+ return addr;
+ }
+
+ /*
+ * We'll assume that the code segments in the GDT
+ * are all zero-based. That is largely true: the
+ * TLS segments are used for data, and the PNPBIOS
+ * and APM bios ones we just ignore here.
+ */
+ if (seg & LDT_SEGMENT) {
+ u32 *desc;
+ unsigned long base;
+
+ down(&child->mm->context.sem);
+ desc = child->mm->context.ldt + (seg & ~7);
+ base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
+
+ /* 16-bit code segment? */
+ if (!((desc[1] >> 22) & 1))
+ addr &= 0xffff;
+ addr += base;
+ up(&child->mm->context.sem);
+ }
+ return addr;
+}
+
+static inline int is_at_popf(struct task_struct *child, struct pt_regs *regs)
+{
+ int i, copied;
+ unsigned char opcode[16];
+ unsigned long addr = convert_eip_to_linear(child, regs);
+
+ copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
+ for (i = 0; i < copied; i++) {
+ switch (opcode[i]) {
+ /* popf */
+ case 0x9d:
+ return 1;
+ /* opcode and address size prefixes */
+ case 0x66: case 0x67:
+ continue;
+ /* irrelevant prefixes (segment overrides and repeats) */
+ case 0x26: case 0x2e:
+ case 0x36: case 0x3e:
+ case 0x64: case 0x65:
+ case 0xf0: case 0xf2: case 0xf3:
+ continue;
+
+ /*
+ * pushf: NOTE! We should probably not let
+ * the user see the TF bit being set. But
+ * it's more pain than it's worth to avoid
+ * it, and a debugger could emulate this
+ * all in user space if it _really_ cares.
+ */
+ case 0x9c:
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
static void set_singlestep(struct task_struct *child)
{
- long eflags;
+ struct pt_regs *regs = get_child_regs(child);
+ /*
+ * Always set TIF_SINGLESTEP - this guarantees that
+ * we single-step system calls etc.. This will also
+ * cause us to set TF when returning to user mode.
+ */
set_tsk_thread_flag(child, TIF_SINGLESTEP);
- eflags = get_stack_long(child, EFL_OFFSET);
- put_stack_long(child, EFL_OFFSET, eflags | TRAP_FLAG);
+
+ /*
+ * If TF was already set, don't do anything else
+ */
+ if (regs->eflags & TRAP_FLAG)
+ return;
+
+ /* Set TF on the kernel stack.. */
+ regs->eflags |= TRAP_FLAG;
+
+ /*
+ * ..but if TF is changed by the instruction we will trace,
+ * don't mark it as being "us" that set it, so that we
+ * won't clear it by hand later.
+ */
+ if (is_at_popf(child, regs))
+ return;
+
child->ptrace |= PT_DTRACE;
}
static void clear_singlestep(struct task_struct *child)
{
- if (child->ptrace & PT_DTRACE) {
- long eflags;
+ /* Always clear TIF_SINGLESTEP... */
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
- clear_tsk_thread_flag(child, TIF_SINGLESTEP);
- eflags = get_stack_long(child, EFL_OFFSET);
- put_stack_long(child, EFL_OFFSET, eflags & ~TRAP_FLAG);
+ /* But touch TF only if it was set by us.. */
+ if (child->ptrace & PT_DTRACE) {
+ struct pt_regs *regs = get_child_regs(child);
+ regs->eflags &= ~TRAP_FLAG;
child->ptrace &= ~PT_DTRACE;
}
}
@@ -553,6 +654,24 @@
return ret;
}
+void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
+{
+ struct siginfo info;
+
+ tsk->thread.trap_no = 1;
+ tsk->thread.error_code = error_code;
+
+ memset(&info, 0, sizeof(info));
+ info.si_signo = SIGTRAP;
+ info.si_code = TRAP_BRKPT;
+
+ /* User-mode eip? */
+ info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
+
+ /* Send us the fakey SIGTRAP */
+ force_sig_info(SIGTRAP, &info, tsk);
+}
+
/* notification of system call entry/exit
* - triggered by current->work.syscall_trace
*/
@@ -568,15 +687,19 @@
audit_syscall_exit(current, regs->eax);
}
- if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
- !test_thread_flag(TIF_SINGLESTEP))
- return;
if (!(current->ptrace & PT_PTRACED))
return;
+
+ /* Fake a debug trap */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ send_sigtrap(current, regs, 0);
+
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
- !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
diff -urN linux-2.6.10-bk4/arch/i386/kernel/signal.c linux-2.6.10-bk5/arch/i386/kernel/signal.c
--- linux-2.6.10-bk4/arch/i386/kernel/signal.c 2004-12-24 13:34:44.000000000 -0800
+++ linux-2.6.10-bk5/arch/i386/kernel/signal.c 2005-01-02 04:55:14.137194398 -0800
@@ -270,7 +270,6 @@
struct pt_regs *regs, unsigned long mask)
{
int tmp, err = 0;
- unsigned long eflags;
tmp = 0;
__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -292,16 +291,7 @@
err |= __put_user(current->thread.error_code, &sc->err);
err |= __put_user(regs->eip, &sc->eip);
err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
-
- /*
- * Iff TF was set because the program is being single-stepped by a
- * debugger, don't save that information on the signal stack.. We
- * don't want debugging to change state.
- */
- eflags = regs->eflags;
- if (current->ptrace & PT_DTRACE)
- eflags &= ~TF_MASK;
- err |= __put_user(eflags, &sc->eflags);
+ err |= __put_user(regs->eflags, &sc->eflags);
err |= __put_user(regs->esp, &sc->esp_at_signal);
err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
@@ -424,11 +414,9 @@
* The tracer may want to single-step inside the
* handler too.
*/
- if (regs->eflags & TF_MASK) {
- regs->eflags &= ~TF_MASK;
- if (current->ptrace & PT_DTRACE)
- ptrace_notify(SIGTRAP);
- }
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -519,11 +507,9 @@
* The tracer may want to single-step inside the
* handler too.
*/
- if (regs->eflags & TF_MASK) {
- regs->eflags &= ~TF_MASK;
- if (current->ptrace & PT_DTRACE)
- ptrace_notify(SIGTRAP);
- }
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
diff -urN linux-2.6.10-bk4/arch/i386/kernel/traps.c linux-2.6.10-bk5/arch/i386/kernel/traps.c
--- linux-2.6.10-bk4/arch/i386/kernel/traps.c 2005-01-02 04:54:41.578671459 -0800
+++ linux-2.6.10-bk5/arch/i386/kernel/traps.c 2005-01-02 04:55:14.190196877 -0800
@@ -682,7 +682,6 @@
{
unsigned int condition;
struct task_struct *tsk = current;
- siginfo_t info;
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
@@ -718,23 +717,21 @@
*/
if ((regs->xcs & 3) == 0)
goto clear_TF_reenable;
- if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
- goto clear_TF;
+
+ /*
+ * Was the TF flag set by a debugger? If so, clear it now,
+ * so that register information is correct.
+ */
+ if (tsk->ptrace & PT_DTRACE) {
+ regs->eflags &= ~TF_MASK;
+ tsk->ptrace &= ~PT_DTRACE;
+ if (!tsk->ptrace & PT_DTRACE)
+ goto clear_TF;
+ }
}
/* Ok, finally something we can handle */
- tsk->thread.trap_no = 1;
- tsk->thread.error_code = error_code;
- info.si_signo = SIGTRAP;
- info.si_errno = 0;
- info.si_code = TRAP_BRKPT;
-
- /* If this is a kernel mode trap, save the user PC on entry to
- * the kernel, that's what the debugger can make sense of.
- */
- info.si_addr = ((regs->xcs & 3) == 0) ? (void __user *)tsk->thread.eip
- : (void __user *)regs->eip;
- force_sig_info(SIGTRAP, &info, tsk);
+ send_sigtrap(tsk, regs, error_code);
/* Disable additional traps. They'll be re-enabled when
* the signal is delivered.
On Tue, 14 Feb 2006, Paulo Marques wrote:
>
> Anyway, using the awesome magical power of blind "hand patching", I tried to
> revert this from the 2.6.16-rc3 kernel, but my powers have let me down this
> time :(
>
> Alas, the current kernel is very different from the 2.6.10 version and I don't
> understand this code enough to be able to modify it. (I did try it anyway,
> without success: the debugger still hung).
It does sound like the Kylix debugger depended very tightly on some very
specific old implementation issue. I don't see quite what it could be (gdb
didn't really care, for example), but yes, semantics _did_ change.
With the new semantics, the process doesn't see that it's being debugged
any more because the TF flag change is now hidden from the signal stack.
That indirectly also means that the debugger itself only sees TF change in
the register state if the process itself set it (not if the TF bit was set
implicitly by the debugger asking for a singlestep event).
The new semantics are really bug-fixes, and actually made it possible to
debug things that weren't really possible to debug before. And you had to
do some pretty strange things for them to matter to the debugger, but
apparently Kylix does exactly that ;(
> Before I start moving in that direction is there someone who can give me an
> hint about what might be happening and suggest patches to test, etc.?
Hmm. You could try variations on the appended patch. Try changing the
"#if 0" to "#if 1" in various combinations, to see which one Kylix seems
to care about.
Linus
---
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 963616d..8f403bd 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -384,6 +384,7 @@ static int setup_frame(int sig, struct k
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
+#if 0
/*
* Clear TF when entering the signal handler, but
* notify any tracer that was single-stepping it.
@@ -393,6 +394,7 @@ static int setup_frame(int sig, struct k
regs->eflags &= ~TF_MASK;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);
+#endif
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -478,6 +480,7 @@ static int setup_rt_frame(int sig, struc
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
+#if 0
/*
* Clear TF when entering the signal handler, but
* notify any tracer that was single-stepping it.
@@ -487,6 +490,7 @@ static int setup_rt_frame(int sig, struc
regs->eflags &= ~TF_MASK;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);
+#endif
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -531,6 +535,7 @@ handle_signal(unsigned long sig, siginfo
}
}
+#if 0
/*
* If TF is set due to a debugger (PT_DTRACE), clear the TF flag so
* that register information in the sigcontext is correct.
@@ -540,6 +545,7 @@ handle_signal(unsigned long sig, siginfo
current->ptrace &= ~PT_DTRACE;
regs->eflags &= ~TF_MASK;
}
+#endif
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
In-Reply-To: <[email protected]>
On Tue, 14 Feb 2006 at 20:21:08 +0000, Paulo Marques wrote:
> Going even further, a 2.6.10-bk5 kernel without this single change runs
> the debugger just fine:
>
> > @@ -718,23 +717,21 @@
> > */
> > if ((regs->xcs & 3) == 0)
> > goto clear_TF_reenable;
> > - if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
> > - goto clear_TF;
> > +
> > + /*
> > + * Was the TF flag set by a debugger? If so, clear it now,
> > + * so that register information is correct.
> > + */
> > + if (tsk->ptrace & PT_DTRACE) {
> > + regs->eflags &= ~TF_MASK;
> > + tsk->ptrace &= ~PT_DTRACE;
> > + if (!tsk->ptrace & PT_DTRACE)
^^^^^^^^^^^^^^^^^^^^^^^^
Looks like this is always true because that bit was cleared one line above.
Maybe it should be testing PT_DTRACED instead? And it's missing parens too,
so try:
if (!(tsk->ptrace & PT_DTRACED))
> > + goto clear_TF;
> > + }
> > }
> >
> > /* Ok, finally something we can handle */
--
Chuck
"Equations are the Devil's sentences." --Stephen Colbert
Linus Torvalds wrote:
> [...]
> Hmm. You could try variations on the appended patch. Try changing the
> "#if 0" to "#if 1" in various combinations, to see which one Kylix seems
> to care about.
Sorry about the delay, but being Valentine's day and all changes our
priorities a bit ;)
Anyway, a friend of mine tested the patch and reported that the
combinations 000 (all comented out), 001 (the first 2 commented out, but
the last one not) and 110 (...) still hung the debugger. I suppose these
were all the combinations he tested.
Tonight I'll have more time to test this again and we can probably have
a more interactive debug session.
In the mean time, just a few more data points. The debugger seems to use
LinuxThreads and only works with LD_ASSUME_KERNEL=2.4.1, even on a
2.6.10 kernel.
If we don't set this, the debugger hangs in a different way. Apparently
it is waiting on a signal, it has a signal pending that is one of the
first real-time signals (the ones used by LinuxThreads), but its signal
mask is blocking it.
Anyway, I thought of trying to attach a strace to the debugger tonight
to try to see exactly what the debugger is doing. Is this supposed to
work? Or trying to trace a process that is itself tracing another
process a no-no and can give unreliable results?
--
Paulo Marques - http://www.grupopie.com
Pointy-Haired Boss: I don't see anything that could stand in our way.
Dilbert: Sanity? Reality? The laws of physics?
Chuck Ebbert wrote:
> On Tue, 14 Feb 2006 at 20:21:08 +0000, Paulo Marques wrote:
>
>>>+ regs->eflags &= ~TF_MASK;
>>>+ tsk->ptrace &= ~PT_DTRACE;
>>>+ if (!tsk->ptrace & PT_DTRACE)
>
> ^^^^^^^^^^^^^^^^^^^^^^^^
> Looks like this is always true because that bit was cleared one line above.
> Maybe it should be testing PT_DTRACED instead? And it's missing parens too,
> so try:
> if (!(tsk->ptrace & PT_DTRACED))
Yes, this does look funny :P
However, this is the piece of code that I don't put in in order to make
the debugger work, and it doesn't exist on the vanilla 2.6.16-rc kernel
anymore.
What I did try to do was to add the:
- if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
- goto clear_TF;
condition to the 2.6.16-rc kernel, but that didn't work anyway :(
--
Paulo Marques - http://www.grupopie.com
Pointy-Haired Boss: I don't see anything that could stand in our way.
Dilbert: Sanity? Reality? The laws of physics?
--- ./arch/i386/kernel/ptrace.c.orig 2006-02-16 02:01:15.000000000 +0000
+++ ./arch/i386/kernel/ptrace.c 2006-02-16 01:57:40.000000000 +0000
@@ -362,6 +362,8 @@ long arch_ptrace(struct task_struct *chi
struct user * dummy = NULL;
int i, ret;
unsigned long __user *datap = (unsigned long __user *)data;
+ unsigned long old_flags;
+ struct pt_regs *regs;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
@@ -544,10 +546,20 @@ long arch_ptrace(struct task_struct *chi
ret = -EIO;
break;
}
+
+ regs = get_child_regs(child);
+ old_flags = regs->eflags;
+
+ if (test_tsk_thread_flag(child, TIF_SINGLESTEP))
+ regs->eflags |= TRAP_FLAG;
+
for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
__put_user(getreg(child, i), datap);
datap++;
}
+
+ regs->eflags = old_flags;
+
ret = 0;
break;
}
@@ -558,11 +570,18 @@ long arch_ptrace(struct task_struct *chi
ret = -EIO;
break;
}
+
+ regs = get_child_regs(child);
+ old_flags = regs->eflags;
+
for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
__get_user(tmp, datap);
putreg(child, i, tmp);
datap++;
}
+
+ regs->eflags = (regs->eflags & ~TRAP_FLAG) | (old_flags & TRAP_FLAG);
+
ret = 0;
break;
}
On Thu, 16 Feb 2006, Paulo Marques wrote:
>
> I changed the unconditional set of the flag to:
>
> + if (test_tsk_thread_flag(child, TIF_SINGLESTEP))
> + regs->eflags |= TRAP_FLAG;
>
> and the debugger got a little further, but still had problems. I straced it
> again and saw that it was also using PTRACE_SETREGS, probably sending the same
> flag values it received, and that was causing problems.
>
> We then filtered the trap flag in PTRACE_SETREGS, too. The result is the
> attached patch. The debugger worked fine with this patch applied on top of a
> vanilla 2.6.16-rc3 kernel.
>
> This is an extremelly ugly hack, specially because it basically shows the trap
> flag again, which is exactly what we wanted to avoid when the 2.6.10-bk5
> kernel code was written.
>
> Anyway, since it only affected the ptrace call, I tried to solve this using a
> LD_PRELOAD stub on the ptrace function in user-space. The debugger is actually
> a dynamic executable and indeed had the ptrace undefined symbol, so my chances
> were good.
>
> The result was the attached program that interposes the ptrace call and sets /
> clears the trap flag to fool the kylix debugger.
>
> The problem with this approach is that it is not easy to see from user space
> if the child process is being single stepped or not.
>
> I tried to replace the kernel code:
>
> + if (test_tsk_thread_flag(child, TIF_SINGLESTEP))
>
> with:
>
> + ret = func(PTRACE_PEEKUSER, pid, &(((struct user *) 0)->u_debugreg[6]),
> NULL);
> + if (ret & DR_STEP)
>
> because in arch/i386/kernel/traps.c there is this code:
>
> /* Save debug status register where ptrace can see it */
> tsk->thread.debugreg[6] = condition;
>
> /*
> * Single-stepping through TF: make sure we ignore any events in
> * kernel space (but re-enable TF when returning to user mode).
> */
> if (condition & DR_STEP) {
>
> that made it look like there was some single stepping information stored in
> debugreg[6]. However, the debugger didn't work, so I suppose that debugreg
> isn't updated as often as I wanted to, or something like that.
>
> I did a workaround in the interposer (remembering that a single step was
> requested so that it sets the trap flag on the next call to ptrace) and the
> debugger actually works, but I would prefer to do it better.
Ok. It does seem like the debugger is using the TF bit in the debuggee to
"remember" whether it was single-stepping or not.
Which is pretty insane.
> BTW, is there a good way to do the "test_tsk_thread_flag(child,
> TIF_SINGLESTEP)" from user space?
Not really. Except you should just remember that you asked for
single-stepping. That, together with the status return on the wait (which
tells you why the process stopped - the single-step could have been
aborted because of a real fault), should be plenty good enough, and sounds
like the natural way to do this.
Relying on the TF bit, which is under the control of the debugged
application itself, is kind of hokey.
So your patch isn't too intrusive, which is nice. The thing that _isn't_
nice about it is that it means that the debugger cannot actually set the
TF bit "for real" on the process it is debugging, and it cannot really ask
for what the state of the TF bit is (because it will be overshadowed by
the debugger single-stepping).
So I like your patch because it re-instates old (admittedly broken)
behaviour without breaking the _internal_ kernel logic (just the "external
interface"). And while the old behaviour _was_ broken, being backwards
compatible is damn important.
That said, I'd be a lot happier if we could just fix Kylix instead ;(
Linus
Linus Torvalds wrote:
> On Thu, 16 Feb 2006, Paulo Marques wrote:
> [...]
>>I did a workaround in the interposer (remembering that a single step was
>>requested so that it sets the trap flag on the next call to ptrace) and the
>>debugger actually works, but I would prefer to do it better.
>
> Ok. It does seem like the debugger is using the TF bit in the debuggee to
> "remember" whether it was single-stepping or not.
>
> Which is pretty insane.
It sure is :P
>>BTW, is there a good way to do the "test_tsk_thread_flag(child,
>>TIF_SINGLESTEP)" from user space?
>
> Not really. Except you should just remember that you asked for
> single-stepping. That, together with the status return on the wait (which
> tells you why the process stopped - the single-step could have been
> aborted because of a real fault), should be plenty good enough, and sounds
> like the natural way to do this.
I think I can do a better interposer, then. I can interpose both the
ptrace and the wait functions so that I can keep an internal "is being
single stepped" state for each process being ptrace'd.
> Relying on the TF bit, which is under the control of the debugged
> application itself, is kind of hokey.
If I understand this correctly, if the kernel had some other way of
producing a single step (a new flag on newer processors, a timer
interrupt going on after one cycle, whatever) it might not even set the
trap flag at all, and still execute perfectly well the ptrace syscalls,
with all the expected signals being generated, etc.
So this is very much implementation dependent, and the application
should not rely on internal kernel mechanisms like that...
> So your patch isn't too intrusive, which is nice. The thing that _isn't_
> nice about it is that it means that the debugger cannot actually set the
> TF bit "for real" on the process it is debugging, and it cannot really ask
> for what the state of the TF bit is (because it will be overshadowed by
> the debugger single-stepping).
The patch wasn't meant to be used like that. It was just to show what
was needed to make the debugger happy.
At the very least, the patch needs a lot more comments and a quarantine
on -mm before it can be used on mainline.
> So I like your patch because it re-instates old (admittedly broken)
> behaviour without breaking the _internal_ kernel logic (just the "external
> interface"). And while the old behaviour _was_ broken, being backwards
> compatible is damn important.
>
> That said, I'd be a lot happier if we could just fix Kylix instead ;(
The interposer is the closest thing we have to "fixing kylix". I think
most kylix users will be perfectly happy with the interposer and we
really don't need to change the kernel. They are already used to work
around problems that arise from the total staleness of the project.
I'll try to send a few posts to Kylix forums with the interposer thing
and see how well it is accepted.
From what I've heard, Borland is selling its languages, including
Delphi and Kylix, so maybe the company that buys it will be more willing
to properly maintain kylix in the future :)
--
Paulo Marques - http://www.grupopie.com
Pointy-Haired Boss: I don't see anything that could stand in our way.
Dilbert: Sanity? Reality? The laws of physics?