linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [RFC] kprobes with thumb2 conditional code
@ 2011-03-11 17:01 Tixy
  2011-03-17 13:48 ` Dave Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Tixy @ 2011-03-11 17:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hello All

I'm about to start work on getting kprobes working with thumb2.

One of the issues I have is that when probes are placed onto
conditionally executed instructions in a IT block, they may not fire if
the condition is not met. This is because on ARM we use invalid
instructions for breakpoints, and the ARM ARM says:

  "it is IMPLEMENTATION DEFINED whether the instruction executes as a
   NOP or causes an Undefined Instruction exception"

This is a similar issue to that already encountered by GDB [1][2]

If we take this code as an example...

probe1:
if(condition) {
probe2:
    some_code;
}

It seams reasonable at first sight that probe2 would only fire if the
condition is true. This will always be the case if the compiler
generates test-and-branch code, but if it generates conditionally
executed instructions for 'some_code' then it gets complicated...

The current arm kprobes implementation will always fire probe2 because
it uses unconditional instructions for its breakpoints. With thumb
instructions we can't force unconditional execution, so we would have an
'implementation defined' situation whether it would fire or not when the
condition is false. (Thought you would hope it would be consistent on a
particular device.)

Some options for dealing with this, in increasing order of
complexity... 

1. Accept the situation as described.

2. Change arm probes to use conditional instructions so we would
(hopefully) have consistent undefined behaviour in both arm and thumb
code. (If that isn't an oxymoron :-)

3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
when condition false) and not execute the probe's callback functions in
these cases. E.g. consistently make probe2 appear to not fire when
condition is false.

4. Make thumb probes fire unconditionally like current arm
implementation...

4a. Use breakpoint instructions rather than undefined instructions for
kprobes. Apparently this doesn't play nicely with hardware debuggers [2]
though I don't have enough experience in this area to otherwise comment.

4b. Rewrite IT blocks when probes are inserted into them to make the
breakpoint unconditional. This would require parsing backwards through
the instruction stream to find the IT instruction, which I don't believe
is possible with variable length thumb instructions. Or, another
possibility which was suggested to me, use the unwind table to find the
start of the containing function and parse forwards to find the IT
instruction. Though the kernel doesn't currently have enough information
to skip things like inline data that may be the function.

The effort, complexity and bloat involved in 4b seems to be rather
excessive to me, even before getting into the book-keeping required to
handle multiple probes in the same IT block. So 4b is a bit of a straw
man.

BTW, does anyone know of any test code for kprobes, particularly with
regard to checking emulation/single-stepping of the different CPU
instructions?

Thanks for any feedback

-- 
Tixy


[1] http://permalink.gmane.org/gmane.comp.gdb.patches/54862  
[2]
http://thread.gmane.org/gmane.linux.ports.arm.kernel/72199/focus=73489

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-03-11 17:01 [RFC] kprobes with thumb2 conditional code Tixy
@ 2011-03-17 13:48 ` Dave Martin
  2011-03-17 22:46   ` Nicolas Pitre
  0 siblings, 1 reply; 8+ messages in thread
From: Dave Martin @ 2011-03-17 13:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
> Hello All
>
> I'm about to start work on getting kprobes working with thumb2.
>
> One of the issues I have is that when probes are placed onto
> conditionally executed instructions in a IT block, they may not fire if
> the condition is not met. This is because on ARM we use invalid
> instructions for breakpoints, and the ARM ARM says:
>
> ?"it is IMPLEMENTATION DEFINED whether the instruction executes as a
> ? NOP or causes an Undefined Instruction exception"
>
> This is a similar issue to that already encountered by GDB [1][2]
>
> If we take this code as an example...
>
> probe1:
> if(condition) {
> probe2:
> ? ?some_code;
> }
>
> It seams reasonable at first sight that probe2 would only fire if the
> condition is true. This will always be the case if the compiler
> generates test-and-branch code, but if it generates conditionally
> executed instructions for 'some_code' then it gets complicated...
>
> The current arm kprobes implementation will always fire probe2 because

Well, actually it's somewhat unpredictable whether/when a probe on
probe2 will fire, because it depends on the code generated by the
compiler.  The compiler could choose to use a conditional instruction
at probe2, or it could conditionally branch round it, even in ARM.
Or, the whole conditional might disappear to be replaced with an
unconditional instruction sequence that has the same overall effect.

> it uses unconditional instructions for its breakpoints. With thumb
> instructions we can't force unconditional execution, so we would have an
> 'implementation defined' situation whether it would fire or not when the
> condition is false. (Thought you would hope it would be consistent on a
> particular device.)
>
> Some options for dealing with this, in increasing order of
> complexity...
>
> 1. Accept the situation as described.
>
> 2. Change arm probes to use conditional instructions so we would
> (hopefully) have consistent undefined behaviour in both arm and thumb
> code. (If that isn't an oxymoron :-)
>
> 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
> when condition false) and not execute the probe's callback functions in
> these cases. E.g. consistently make probe2 appear to not fire when
> condition is false.

My preference would be for option (1) or (3).  For (3), we could
choose to extend this behaviour to cover the existing ARM
implementation as well as Thumb, which could be a tidier and more
consistent approach.  This seems to be the "right" thing, since it
means kprobes never fire for real on instructions which are logically
not executed, no matter how the compiler (or human) implemented the
conditionality.  Currently, ARM kprobes can fire on instructions which
would fail their condition check, which might be considered wrong.

Alternatively, we could avoid fixing what isn't broken and leave the
ARM implementation unchanged.  Since the compiler will implement some
different instruction-level optimisations in Thumb compared with ARM,
it may not make sense to try to make the kprobe firing behaviour
behave exactly the same around conditional code in both instruction
sets -- because the code generation differences may always cause the
observed behaviour to be different anyway, just as might happen if you
switch to a newer compiler or use a different -march/-mtune
combination.

For the same reasons described above, I'd advise against the more
complex routes in (4).  The extra complexity probably doesn't bring
any useful consistency.


Has anyone made use of kprobes in a way where the precise firing
behaviour for conditional code would be important?

Cheers
---Dave

>
> 4. Make thumb probes fire unconditionally like current arm
> implementation...
>
> 4a. Use breakpoint instructions rather than undefined instructions for
> kprobes. Apparently this doesn't play nicely with hardware debuggers [2]
> though I don't have enough experience in this area to otherwise comment.
>
> 4b. Rewrite IT blocks when probes are inserted into them to make the
> breakpoint unconditional. This would require parsing backwards through
> the instruction stream to find the IT instruction, which I don't believe
> is possible with variable length thumb instructions. Or, another
> possibility which was suggested to me, use the unwind table to find the
> start of the containing function and parse forwards to find the IT
> instruction. Though the kernel doesn't currently have enough information
> to skip things like inline data that may be the function.
>
> The effort, complexity and bloat involved in 4b seems to be rather
> excessive to me, even before getting into the book-keeping required to
> handle multiple probes in the same IT block. So 4b is a bit of a straw
> man.
>
> BTW, does anyone know of any test code for kprobes, particularly with
> regard to checking emulation/single-stepping of the different CPU
> instructions?
>
> Thanks for any feedback
>
> --
> Tixy
>
>
> [1] http://permalink.gmane.org/gmane.comp.gdb.patches/54862
> [2]
> http://thread.gmane.org/gmane.linux.ports.arm.kernel/72199/focus=73489
>
>
>
> _______________________________________________
> linaro-dev mailing list
> linaro-dev at lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-dev
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-03-17 13:48 ` Dave Martin
@ 2011-03-17 22:46   ` Nicolas Pitre
  2011-03-18 16:43     ` Dave Martin
  2011-06-15  9:45     ` Tixy
  0 siblings, 2 replies; 8+ messages in thread
From: Nicolas Pitre @ 2011-03-17 22:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 17 Mar 2011, Dave Martin wrote:

> On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
> > Hello All
> >
> > I'm about to start work on getting kprobes working with thumb2.
> >
> > One of the issues I have is that when probes are placed onto
> > conditionally executed instructions in a IT block, they may not fire if
> > the condition is not met. This is because on ARM we use invalid
> > instructions for breakpoints, and the ARM ARM says:
> >
> > ?"it is IMPLEMENTATION DEFINED whether the instruction executes as a
> > ? NOP or causes an Undefined Instruction exception"
> >
> > This is a similar issue to that already encountered by GDB [1][2]
> >
> > If we take this code as an example...
> >
> > probe1:
> > if(condition) {
> > probe2:
> > ? ?some_code;
> > }
> >
> > It seams reasonable at first sight that probe2 would only fire if the
> > condition is true. This will always be the case if the compiler
> > generates test-and-branch code, but if it generates conditionally
> > executed instructions for 'some_code' then it gets complicated...
> >
> > The current arm kprobes implementation will always fire probe2 because
> 
> Well, actually it's somewhat unpredictable whether/when a probe on
> probe2 will fire, because it depends on the code generated by the
> compiler.  The compiler could choose to use a conditional instruction
> at probe2, or it could conditionally branch round it, even in ARM.

And we definitely don't want that.

> Or, the whole conditional might disappear to be replaced with an
> unconditional instruction sequence that has the same overall effect.

Sure, but this is an extreme case which is not specific to ARM or 
Thumb2.  Such a situation could happen on x86 as well.  Let's not worry 
about that and keep ourselves to those cases we have control over.

> > it uses unconditional instructions for its breakpoints. With thumb
> > instructions we can't force unconditional execution, so we would have an
> > 'implementation defined' situation whether it would fire or not when the
> > condition is false. (Thought you would hope it would be consistent on a
> > particular device.)
> >
> > Some options for dealing with this, in increasing order of
> > complexity...
> >
> > 1. Accept the situation as described.
> >
> > 2. Change arm probes to use conditional instructions so we would
> > (hopefully) have consistent undefined behaviour in both arm and thumb
> > code. (If that isn't an oxymoron :-)
> >
> > 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
> > when condition false) and not execute the probe's callback functions in
> > these cases. E.g. consistently make probe2 appear to not fire when
> > condition is false.
> 
> My preference would be for option (1) or (3).  For (3), we could
> choose to extend this behaviour to cover the existing ARM
> implementation as well as Thumb, which could be a tidier and more
> consistent approach.  This seems to be the "right" thing, since it
> means kprobes never fire for real on instructions which are logically
> not executed, no matter how the compiler (or human) implemented the
> conditionality.  Currently, ARM kprobes can fire on instructions which
> would fail their condition check, which might be considered wrong.

Definitely #3.

In the ARM case, this can be achieved by saving the condition code 
of the replaced instruction when installing a probe, and test it 
against the CPSR value from the interrupted state.  If the condition is 
false then just skip the native emulation of the resulting NOP and 
ignore the probe callback.  In the Thumb2 case the IT state in the CPSR 
would indicate right away if the probe should be ignored.

> Alternatively, we could avoid fixing what isn't broken and leave the
> ARM implementation unchanged.

I wouldn't call the ARM implementation not broken.  It just happens that 
probes are typically installed at the beginning of functions and no 
conditional instructions are normally placed there.  This would explain 
why no one reported this issue so far.

> Since the compiler will implement some
> different instruction-level optimisations in Thumb compared with ARM,
> it may not make sense to try to make the kprobe firing behaviour
> behave exactly the same around conditional code in both instruction
> sets -- because the code generation differences may always cause the
> observed behaviour to be different anyway, just as might happen if you
> switch to a newer compiler or use a different -march/-mtune
> combination.

That doesn't matter.  We should respect the expected execution flow at 
the probe location irrespective of any compiler optimization.  It is 
true that code generation might be different between different compilers 
and options, but that's not our problem as long as we don't introduce 
more randomness.  And it happens that making this work properly is 
trivial with Thumb2.  And in ARM mode, the most complex task is to 
determine if a given instruction is conditionally executable or not.


Nicolas

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-03-17 22:46   ` Nicolas Pitre
@ 2011-03-18 16:43     ` Dave Martin
  2011-06-15  9:45     ` Tixy
  1 sibling, 0 replies; 8+ messages in thread
From: Dave Martin @ 2011-03-18 16:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 17, 2011 at 10:46 PM, Nicolas Pitre
<nicolas.pitre@linaro.org> wrote:
> On Thu, 17 Mar 2011, Dave Martin wrote:
>
>> On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
>> > Hello All
>> >
>> > I'm about to start work on getting kprobes working with thumb2.
>> >
>> > One of the issues I have is that when probes are placed onto
>> > conditionally executed instructions in a IT block, they may not fire if
>> > the condition is not met. This is because on ARM we use invalid
>> > instructions for breakpoints, and the ARM ARM says:
>> >
>> > ?"it is IMPLEMENTATION DEFINED whether the instruction executes as a
>> > ? NOP or causes an Undefined Instruction exception"
>> >
>> > This is a similar issue to that already encountered by GDB [1][2]
>> >
>> > If we take this code as an example...
>> >
>> > probe1:
>> > if(condition) {
>> > probe2:
>> > ? ?some_code;
>> > }
>> >
>> > It seams reasonable at first sight that probe2 would only fire if the
>> > condition is true. This will always be the case if the compiler
>> > generates test-and-branch code, but if it generates conditionally
>> > executed instructions for 'some_code' then it gets complicated...
>> >
>> > The current arm kprobes implementation will always fire probe2 because
>>
>> Well, actually it's somewhat unpredictable whether/when a probe on
>> probe2 will fire, because it depends on the code generated by the
>> compiler. ?The compiler could choose to use a conditional instruction
>> at probe2, or it could conditionally branch round it, even in ARM.
>
> And we definitely don't want that.
>
>> Or, the whole conditional might disappear to be replaced with an
>> unconditional instruction sequence that has the same overall effect.
>
> Sure, but this is an extreme case which is not specific to ARM or
> Thumb2. ?Such a situation could happen on x86 as well. ?Let's not worry
> about that and keep ourselves to those cases we have control over.
>
>> > it uses unconditional instructions for its breakpoints. With thumb
>> > instructions we can't force unconditional execution, so we would have an
>> > 'implementation defined' situation whether it would fire or not when the
>> > condition is false. (Thought you would hope it would be consistent on a
>> > particular device.)
>> >
>> > Some options for dealing with this, in increasing order of
>> > complexity...
>> >
>> > 1. Accept the situation as described.
>> >
>> > 2. Change arm probes to use conditional instructions so we would
>> > (hopefully) have consistent undefined behaviour in both arm and thumb
>> > code. (If that isn't an oxymoron :-)
>> >
>> > 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
>> > when condition false) and not execute the probe's callback functions in
>> > these cases. E.g. consistently make probe2 appear to not fire when
>> > condition is false.
>>
>> My preference would be for option (1) or (3). ?For (3), we could
>> choose to extend this behaviour to cover the existing ARM
>> implementation as well as Thumb, which could be a tidier and more
>> consistent approach. ?This seems to be the "right" thing, since it
>> means kprobes never fire for real on instructions which are logically
>> not executed, no matter how the compiler (or human) implemented the
>> conditionality. ?Currently, ARM kprobes can fire on instructions which
>> would fail their condition check, which might be considered wrong.
>
> Definitely #3.
>
> In the ARM case, this can be achieved by saving the condition code
> of the replaced instruction when installing a probe, and test it
> against the CPSR value from the interrupted state. ?If the condition is
> false then just skip the native emulation of the resulting NOP and
> ignore the probe callback. ?In the Thumb2 case the IT state in the CPSR
> would indicate right away if the probe should be ignored.

We could also insert a conditional undefined instruction for the probe
-- this may reduce the number of false positives, but it depends on
the hardware implementation.
Since kprobes needs to do explicit condition code checks anyway, use
of conditional undefs doesn't add any functionality, however.

>
>> Alternatively, we could avoid fixing what isn't broken and leave the
>> ARM implementation unchanged.
>
> I wouldn't call the ARM implementation not broken. ?It just happens that
> probes are typically installed at the beginning of functions and no
> conditional instructions are normally placed there. ?This would explain
> why no one reported this issue so far.

Well, fair enough -- if there's appetite for tidying this up, and we
don't think it will break anything anyone else is doing, then I'd say
fixing it is a good idea.

>
>> Since the compiler will implement some
>> different instruction-level optimisations in Thumb compared with ARM,
>> it may not make sense to try to make the kprobe firing behaviour
>> behave exactly the same around conditional code in both instruction
>> sets -- because the code generation differences may always cause the
>> observed behaviour to be different anyway, just as might happen if you
>> switch to a newer compiler or use a different -march/-mtune
>> combination.
>
> That doesn't matter. ?We should respect the expected execution flow at
> the probe location irrespective of any compiler optimization. ?It is
> true that code generation might be different between different compilers
> and options, but that's not our problem as long as we don't introduce
> more randomness. ?And it happens that making this work properly is
> trivial with Thumb2. ?And in ARM mode, the most complex task is to
> determine if a given instruction is conditionally executable or not.

Note that in Thumb, not everything that's conditional is inside an IT
block: there are a couple of conditional branch encodings which have
an explicit condition code.

It's still a pretty simple decoding task, but not quite as simple as
the ARM case.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-03-17 22:46   ` Nicolas Pitre
  2011-03-18 16:43     ` Dave Martin
@ 2011-06-15  9:45     ` Tixy
  2011-06-15 11:16       ` Dave Martin
  1 sibling, 1 reply; 8+ messages in thread
From: Tixy @ 2011-06-15  9:45 UTC (permalink / raw)
  To: linux-arm-kernel

I would like to revisit the discussion about how to handle kprobes
placed on conditionally executed instructions...

On Thu, 2011-03-17 at 18:46 -0400, Nicolas Pitre wrote: 
> On Thu, 17 Mar 2011, Dave Martin wrote:
> > On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
> > > it uses unconditional instructions for its breakpoints. With thumb
> > > instructions we can't force unconditional execution, so we would have an
> > > 'implementation defined' situation whether it would fire or not when the
> > > condition is false. (Thought you would hope it would be consistent on a
> > > particular device.)
> > >
> > > Some options for dealing with this, in increasing order of
> > > complexity...
> > >
> > > 1. Accept the situation as described.
> > >
> > > 2. Change arm probes to use conditional instructions so we would
> > > (hopefully) have consistent undefined behaviour in both arm and thumb
> > > code. (If that isn't an oxymoron :-)
> > >
> > > 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
> > > when condition false) and not execute the probe's callback functions in
> > > these cases. E.g. consistently make probe2 appear to not fire when
> > > condition is false.
> > 
> > My preference would be for option (1) or (3).  For (3), we could
> > choose to extend this behaviour to cover the existing ARM
> > implementation as well as Thumb, which could be a tidier and more
> > consistent approach.  This seems to be the "right" thing, since it
> > means kprobes never fire for real on instructions which are logically
> > not executed, no matter how the compiler (or human) implemented the
> > conditionality.  Currently, ARM kprobes can fire on instructions which
> > would fail their condition check, which might be considered wrong.
> 
> Definitely #3.
> 
> In the ARM case, this can be achieved by saving the condition code 
> of the replaced instruction when installing a probe, and test it 
> against the CPSR value from the interrupted state.  If the condition is 
> false then just skip the native emulation of the resulting NOP and 
> ignore the probe callback.  In the Thumb2 case the IT state in the CPSR 
> would indicate right away if the probe should be ignored.

If we don't fire a probe because a conditional instruction wouldn't be
executed then for branch instructions we only fire when branches are
taken. So, with things like loops...

1:  movs r0, r0, asl #1
    bpl 1b

the probe would fire on every iteration of the loop except the last.
This inconsistency seems bad to me.

We could make exceptions for branches, and every other instruction which
can changes PC, but we would still have the issue that we can't force
unconditional firing of Thumb branches in an IT block.

There doesn't appear to be a single satisfactory solution. 

Perhaps we should do option #1, i.e. don't change anything and have
probes always firing except when breakpoints are missed in IT blocks due
to the condition being false.

Or looking at it another way, leave things as the are until someone
comes up with a real-life use-case which indicates that a change is
needed.

-- 
Tixy 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-06-15  9:45     ` Tixy
@ 2011-06-15 11:16       ` Dave Martin
  2011-06-15 12:24         ` Tixy
  0 siblings, 1 reply; 8+ messages in thread
From: Dave Martin @ 2011-06-15 11:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 15, 2011 at 10:45:38AM +0100, Tixy wrote:
> I would like to revisit the discussion about how to handle kprobes
> placed on conditionally executed instructions...
> 
> On Thu, 2011-03-17 at 18:46 -0400, Nicolas Pitre wrote: 
> > On Thu, 17 Mar 2011, Dave Martin wrote:
> > > On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
> > > > it uses unconditional instructions for its breakpoints. With thumb
> > > > instructions we can't force unconditional execution, so we would have an
> > > > 'implementation defined' situation whether it would fire or not when the
> > > > condition is false. (Thought you would hope it would be consistent on a
> > > > particular device.)
> > > >
> > > > Some options for dealing with this, in increasing order of
> > > > complexity...
> > > >
> > > > 1. Accept the situation as described.
> > > >
> > > > 2. Change arm probes to use conditional instructions so we would
> > > > (hopefully) have consistent undefined behaviour in both arm and thumb
> > > > code. (If that isn't an oxymoron :-)
> > > >
> > > > 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
> > > > when condition false) and not execute the probe's callback functions in
> > > > these cases. E.g. consistently make probe2 appear to not fire when
> > > > condition is false.
> > > 
> > > My preference would be for option (1) or (3).  For (3), we could
> > > choose to extend this behaviour to cover the existing ARM
> > > implementation as well as Thumb, which could be a tidier and more
> > > consistent approach.  This seems to be the "right" thing, since it
> > > means kprobes never fire for real on instructions which are logically
> > > not executed, no matter how the compiler (or human) implemented the
> > > conditionality.  Currently, ARM kprobes can fire on instructions which
> > > would fail their condition check, which might be considered wrong.
> > 
> > Definitely #3.
> > 
> > In the ARM case, this can be achieved by saving the condition code 
> > of the replaced instruction when installing a probe, and test it 
> > against the CPSR value from the interrupted state.  If the condition is 
> > false then just skip the native emulation of the resulting NOP and 
> > ignore the probe callback.  In the Thumb2 case the IT state in the CPSR 
> > would indicate right away if the probe should be ignored.
> 
> If we don't fire a probe because a conditional instruction wouldn't be
> executed then for branch instructions we only fire when branches are
> taken. So, with things like loops...
> 
> 1:  movs r0, r0, asl #1
>     bpl 1b
> 
> the probe would fire on every iteration of the loop except the last.
> This inconsistency seems bad to me.
> 
> We could make exceptions for branches, and every other instruction which
> can changes PC, but we would still have the issue that we can't force
> unconditional firing of Thumb branches in an IT block.

I suspect that it's more common to see conditional branches outside IT
blocks than inside, due to the different encodings available and the
fact that it's most common for a conditional branch to follow some
unconditional instruction to set up the condition.

According to my hacky measurements, only about 2% of the conditional
branches in a typical vmlinux image are inside IT blocks.  So if we
don't solve this case it may not be catastrophic.

> There doesn't appear to be a single satisfactory solution. 

Since the instruction stream can be reliably decoded _forwards_, we
could trap on the branch-not-taken case by setting an additional probe
after the affected branch.

Where branches appear in IT blocks, they're not allowed to be anywhere
except at the end of the block, so the next instruction is either outside
the block, or is an IT instruction itself (in which case we can still
set a probe on it).  In valid code there will always be a next instruction,
since the CPU will fall through the branch if the condition is false.

That would deal with almost all cases, but it adds a bit of complexity
so I'm not convinced it's worth it.

> 
> Perhaps we should do option #1, i.e. don't change anything and have
> probes always firing except when breakpoints are missed in IT blocks due
> to the condition being false.
> 
> Or looking at it another way, leave things as the are until someone
> comes up with a real-life use-case which indicates that a change is
> needed.

We could ask the question of what a developer is trying to detect when
a kprobe is set.

It would either be:

	a) does the PC logically reach this address?
	b) is this instruction logically executed?

Currently, the proposed implementation (#3) follows interpretation (b).

We cannot reliably implement (a) because the CPU may effectively skip
over IT blocks rather than considering each instruction in turn for
potential faulting; i.e., the CPU does not reliably answer question (a)
for us.  Notions like where the PC is at a particular time and the 
exact locations it visits usually can have pretty fuzzy meaning once
you get into actual CPU implementation; so the ARM architecture doesn't
commit CPU implementors to meaningfully answering question (a) in all
situations -- which is the fundamental difficulty here, since this is
the question people usually expect to be answered when they set a
breakpoint.

So, we have a choice between a consistent but sometimes counterintuitive
approach (b), or an inconsistent (and hence sometimes counterintuitive)
approach approximating (a).  The latter case will be more complex to
implement, and I'm not sure of the benefits.

We could make a special exception to the false-firing rule for branches,
but that raises the question of which other instructions should be
excepted.  Efectively, this means that we "guess" based on the actual
instruction whether the developer meant (a) or (b) when setting their
kprobe.  Unfortunately I don't think there's a correct answer to
that question magically, unless the API has a way for the developer
to actually state this.  It doesn't, AFAICT.

Apart from simple things like breaking on entry to a function,
I think we can (and should) expect developers using kprobes in an arch-
specific manner to understand what they're doing.  For example,
set your probe on the start of a loop, and the first unconditional
instruction following the looping branch, not on the looping branch
itself.

Either way, we should of course document clearly the implemented
kprobe firing behaviour so that people understand how to work with it.

Those are just my thoughts ... I don't think there's any single
correct answer to how to implement this.  Going for the simplest
reasonable-looking approach and changing it later if and only if
this causes problems for people seems the best approach in such cases.

If you think that that #3 is not the simplest reasonable-looking
approach after all, then I guess we can think about alternatives.

---Cheers

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-06-15 11:16       ` Dave Martin
@ 2011-06-15 12:24         ` Tixy
  2011-06-15 12:41           ` Dave Martin
  0 siblings, 1 reply; 8+ messages in thread
From: Tixy @ 2011-06-15 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2011-06-15 at 12:16 +0100, Dave Martin wrote:
> On Wed, Jun 15, 2011 at 10:45:38AM +0100, Tixy wrote:
> > I would like to revisit the discussion about how to handle kprobes
> > placed on conditionally executed instructions...
> > 
> > On Thu, 2011-03-17 at 18:46 -0400, Nicolas Pitre wrote: 
> > > On Thu, 17 Mar 2011, Dave Martin wrote:
> > > > On Fri, Mar 11, 2011 at 5:01 PM, Tixy <tixy@yxit.co.uk> wrote:
> > > > > it uses unconditional instructions for its breakpoints. With thumb
> > > > > instructions we can't force unconditional execution, so we would have an
> > > > > 'implementation defined' situation whether it would fire or not when the
> > > > > condition is false. (Thought you would hope it would be consistent on a
> > > > > particular device.)
> > > > >
> > > > > Some options for dealing with this, in increasing order of
> > > > > complexity...
> > > > >
> > > > > 1. Accept the situation as described.
> > > > >
> > > > > 2. Change arm probes to use conditional instructions so we would
> > > > > (hopefully) have consistent undefined behaviour in both arm and thumb
> > > > > code. (If that isn't an oxymoron :-)
> > > > >
> > > > > 3. Do 2, and modify kprobe_handler to test for false firings (breakpoint
> > > > > when condition false) and not execute the probe's callback functions in
> > > > > these cases. E.g. consistently make probe2 appear to not fire when
> > > > > condition is false.
> > > > 
> > > > My preference would be for option (1) or (3).  For (3), we could
> > > > choose to extend this behaviour to cover the existing ARM
> > > > implementation as well as Thumb, which could be a tidier and more
> > > > consistent approach.  This seems to be the "right" thing, since it
> > > > means kprobes never fire for real on instructions which are logically
> > > > not executed, no matter how the compiler (or human) implemented the
> > > > conditionality.  Currently, ARM kprobes can fire on instructions which
> > > > would fail their condition check, which might be considered wrong.
> > > 
> > > Definitely #3.
> > > 
> > > In the ARM case, this can be achieved by saving the condition code 
> > > of the replaced instruction when installing a probe, and test it 
> > > against the CPSR value from the interrupted state.  If the condition is 
> > > false then just skip the native emulation of the resulting NOP and 
> > > ignore the probe callback.  In the Thumb2 case the IT state in the CPSR 
> > > would indicate right away if the probe should be ignored.
> > 
> > If we don't fire a probe because a conditional instruction wouldn't be
> > executed then for branch instructions we only fire when branches are
> > taken. So, with things like loops...
> > 
> > 1:  movs r0, r0, asl #1
> >     bpl 1b
> > 
> > the probe would fire on every iteration of the loop except the last.
> > This inconsistency seems bad to me.
> > 
> > We could make exceptions for branches, and every other instruction which
> > can changes PC, but we would still have the issue that we can't force
> > unconditional firing of Thumb branches in an IT block.
> 
> I suspect that it's more common to see conditional branches outside IT
> blocks than inside, due to the different encodings available and the
> fact that it's most common for a conditional branch to follow some
> unconditional instruction to set up the condition.
> 
> According to my hacky measurements, only about 2% of the conditional
> branches in a typical vmlinux image are inside IT blocks.  So if we
> don't solve this case it may not be catastrophic.
> 
> > There doesn't appear to be a single satisfactory solution. 
> 
> Since the instruction stream can be reliably decoded _forwards_, we
> could trap on the branch-not-taken case by setting an additional probe
> after the affected branch.
> 
> Where branches appear in IT blocks, they're not allowed to be anywhere
> except at the end of the block, so the next instruction is either outside
> the block, or is an IT instruction itself (in which case we can still
> set a probe on it).  In valid code there will always be a next instruction,
> since the CPU will fall through the branch if the condition is false.

But, if we are asked to probe a normal unconditional branch, we don't
know if its in an IT block or not. E.g. the branch instruction in this:

	cmp	r1, #0
	itt	eq
	moveq	r0, #1
	beq	somewhere
	ldr	r0, [r1]

and in this:

	mov	r0, #1
	b	somewhere
	.word	some_literal_pool_value

are the same instruction, the 'beq' syntax is just for readability.

The real Thumb conditional branch instructions aren't allowed in IT
blocks. It was when I implemented emulation of these that I began to
have second thoughts about the approach to conditional instructions.

> That would deal with almost all cases, but it adds a bit of complexity
> so I'm not convinced it's worth it.

Too complex to go there ;-)

<big snip>
> Either way, we should of course document clearly the implemented
> kprobe firing behaviour so that people understand how to work with it.
> 
> Those are just my thoughts ... I don't think there's any single
> correct answer to how to implement this.  Going for the simplest
> reasonable-looking approach and changing it later if and only if
> this causes problems for people seems the best approach in such cases.
> 
> If you think that that #3 is not the simplest reasonable-looking
> approach after all, then I guess we can think about alternatives.

I'm now convinced that #3 is best after all. It is the only thing we can
get simple, consistent rules for. I.e.

        "Kprobes on conditional instructions don't trigger when the
        condition is false. For conditional branches, this means that
        they don't trigger in the branch not taken case."

-- 
Tixy

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC] kprobes with thumb2 conditional code
  2011-06-15 12:24         ` Tixy
@ 2011-06-15 12:41           ` Dave Martin
  0 siblings, 0 replies; 8+ messages in thread
From: Dave Martin @ 2011-06-15 12:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 15, 2011 at 01:24:35PM +0100, Tixy wrote:
> On Wed, 2011-06-15 at 12:16 +0100, Dave Martin wrote:

[...]

> > Where branches appear in IT blocks, they're not allowed to be anywhere
> > except at the end of the block, so the next instruction is either outside
> > the block, or is an IT instruction itself (in which case we can still
> > set a probe on it).  In valid code there will always be a next instruction,
> > since the CPU will fall through the branch if the condition is false.
> 
> But, if we are asked to probe a normal unconditional branch, we don't
> know if its in an IT block or not. E.g. the branch instruction in this:
> 
> 	cmp	r1, #0
> 	itt	eq
> 	moveq	r0, #1
> 	beq	somewhere
> 	ldr	r0, [r1]
> 
> and in this:
> 
> 	mov	r0, #1
> 	b	somewhere
> 	.word	some_literal_pool_value
> 
> are the same instruction, the 'beq' syntax is just for readability.

Good point, I understand that those instructions are encoded the same, but
I hadn't considered the possibility that the following bytes will contain data
instead of instructions... though actually that will be common-ish after
unconditional branches.

Attempting to set a probe in data will of course be bad, since it may
lead to undetectable corruption.  Ugh.

(Hard to work around, unless you really want to implement full
instruction tracing or watchpoints.  OK, let's not do that! ;) 

> The real Thumb conditional branch instructions aren't allowed in IT
> blocks. It was when I implemented emulation of these that I began to
> have second thoughts about the approach to conditional instructions.
> 
> > That would deal with almost all cases, but it adds a bit of complexity
> > so I'm not convinced it's worth it.
> 
> Too complex to go there ;-)

Yup, I agree.

[...]

> > If you think that that #3 is not the simplest reasonable-looking
> > approach after all, then I guess we can think about alternatives.
> 
> I'm now convinced that #3 is best after all. It is the only thing we can
> get simple, consistent rules for. I.e.
> 
>         "Kprobes on conditional instructions don't trigger when the
>         condition is false. For conditional branches, this means that
>         they don't trigger in the branch not taken case."

Plus it's fairly striaghtforward to implement, so shouldn't waste effort.

As long as people don't get unpleasant surprises from setting a probe
on a function entry point, I think that's OK as an approach.

I think a real function generated by the compiler will never have a
conditional instruction at its entry point, since the ABI permits the
condition flags to be clobbered across procedure calls and returns
anyway... so the result of such an instruction would be indeterminate.
So a probe set on an external function label should always fire even
with the proposed implementation.

So #3 sounds good for me.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-06-15 12:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-11 17:01 [RFC] kprobes with thumb2 conditional code Tixy
2011-03-17 13:48 ` Dave Martin
2011-03-17 22:46   ` Nicolas Pitre
2011-03-18 16:43     ` Dave Martin
2011-06-15  9:45     ` Tixy
2011-06-15 11:16       ` Dave Martin
2011-06-15 12:24         ` Tixy
2011-06-15 12:41           ` Dave Martin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).