public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
* Breakpoint stepping
@ 2007-07-04 18:20 Mark Wielaard
  2007-07-05  4:45 ` Phil Muldoon
                   ` (4 more replies)
  0 siblings, 5 replies; 22+ messages in thread
From: Mark Wielaard @ 2007-07-04 18:20 UTC (permalink / raw)
  To: frysk

[-- Attachment #1: Type: text/plain, Size: 9510 bytes --]

As you might have noticed over the last week I have dropped in the new
breakpoint stepping framework (or hopefully you didn't notice since I
did try to do it in chunks that all had no detectable functional
behavior changes). This is an update to my previous general stepping
overview http://sourceware.org/ml/frysk/2007-q2/msg00283.html
and a request for review of the next steps with regard to the
instruction parsers, testframework and what to use as ssol area.

The main difference with the previous stepping overview regarding the
ptrace state machine is that there is now an explicit Stepping state,
which is a sub-state of Running and that Running.sendContinue() now not
only determines how to instruct ptrace to continue the task, but also
returns a different Running state based on whether or not we asked for a
continue or step-continue. This makes interpreting the cause of the trap
event we subsequently expect to get easier. This was previously recorded
as a field in the Task itself.

With respect to breakpoints the ptrace task states have been adapted to
all call setupSteppingBreakpoint() after a breakpoint hit has been
detected, which makes sure the PC is setup correctly (which previously
could be off by one on some architectures) and to mark the Task as being
at that particular breakpoint (this is still kept as Task field for now)
and to not actually call Breakpoint.prepareStep(), which is now handled
in Running.sendContinue(). In the previous version when reset-breakpoint
stepping was used another task could miss the breakpoint if the Task
moved into a Blocked state before continuing.

All the logic of how to breakpoint step has been moved into the
Breakpoint class that checks the properties of a new Instruction class
object which is created by the Isa through an instruction parser before
the breakpoint is inserted at a given location (previously we
represented instructions just as a byte[]). An Instruction knows how
long the instruction is, which bytes it represents, whether it can be
single stepped out of line and how to set that up given the original pc
location and an alternative address, plus any fixups that are needed to
the Task afterwards (and it has a notion of whether or not the
Instruction can be simulated, but that isn't currently used, see below).
A Breakpoint ties an Instruction to a particular address and Proc (and
Tasks can have zero or more Breakpoints, they share the same Breakpoint
on the same address with other Tasks of a Proc and when no Tasks of a
Proc has an Breakpoint at a particular address anymore the Breakpoint is
removed).

For stepping the Breakpoint the Running.sendContinue() method first
calls Breakpoint.prepareStep(), then signals ptrace to do a single step
of the Task, putting the Task in Stepping state and then in
handleTrapEvent() calls Breakpoint.stepDone(). prepareStep() queries the
capabilities of the Instruction at the pc address and depending on that
either sets things up for doing a step out of line, simulate the
instruction (but none of the current Instructions have been setup to do
simulation yes, and look at the comment in prepareStep() to see what is
needed to fully enable this option) or reset the current Instruction
(removing the breakpoint instruction temporarily). Accordingly a
Breakpoint can be in the state NOT_STEPPING, OUT_OF_LINE_STEPPING,
SIMULATE_STEPPING or RESET_STEPPING.

In the case of RESET_STEPPING (which was the only option we supported
before) other Tasks might miss and just past the Breakpoint during the
brief period between the reset, step and reinstall. Breakpoint
prepareStep() just takes the Instruction bytes and puts them at the
current pc address, and doneStep() reinstates the breakpoint
instruction.

When the Instruction supports single step out of line then the
Breakpoint requests an address in the single step out of line area of
the Proc, instructs the Instruction to install itself there for the
current Task calling Instruction.setupExecuteOutOfLine(). The default
action of setupExecuteOutOfLine() is to set the pc to the given address
and place a copy the instruction bytes there (although this can be
overridden if an Instruction wants to do something more fancy). When the
task signals the Breakpoint that a step was taken by calling stepDone(),
the Breakpoint calls Instruction fixupExecuteOutOfLine() with the
original pc and replacement address so any adjustments can be done to
the Task registers. The default action is to just set the pc to the
original pc plus the length of the Instruction just stepped. But
Instructions can override that if more is needed. As an example the RET
instruction doesn't do any fixup (since the only action is setting the
pc to the right location in the first place) and the JMP instruction
sets the pc to original pc plus/minus the difference of the alternate
address and the pc after the single step. Afterward the Breakpoint
returns the used address to the Proc so it can be used by other Tasks
needing to do a single step out of line.

The Proc maintains a single step out of line area pool of addresses that
point to locations that are at least as big is the largest instruction
of the instruction set. The Proc gets this list from the Isa the first
time an address is requested through getOutOfLineAddress(). Currently
this is (for x86 and x86_64) just the address of the main function entry
point(see below). The address is taken out of the pool and the
Breakpoint is responsible for putting it back through doneOutOfLine (see
above). If no address is currently available the call blocks till one is
available (this was way easier than inventing yet another TaskState and
getting the communication between Proc and Task about this right, and
contention is very low and at the longest it takes for an address to
become available is one instruction single step).

All the above seems to work nicely for x86 and x86_64 (powerpc hasn't
been updated, but as long as an Isa doesn't return Instructions through
an instruction parser that returns single stepping out of line capable
Instructions the old reset-breakpoint stepping is used) with all the old
testcases and a couple of new ones but there are 3 areas of improvement
needed:

- Instruction Parser.  The framework is in place and works for the few
Instructions that are known to the instruction parse, but there are all
hand coded (see IA32InstructionParser which just handles NOP, INT3, RETQ
and one JMP variant, the X8664Instruction just delegates to the IA32 for
now). There don't seem to be libraries available to easily plugin that
would give us the fixup instructions needed. The best available is the
kprobes examples from the linux kernel which have as drawback that they
are coded to be intimately tied to the kernel/C way of doing things and
only handles instructions found in kernel space. For uprobes this should
have been extended to handle every instruction that can occur in user
space, but I haven't seen that work yet (and apparently is only
available for x86 and no other architecture at this time). Any
alternatives to look at would be appreciated. Otherwise I need to sit
down with the various instruction manuals and just code it up by hand.
(Bonus points for finding something that would not just give us ssol
fixups but also simulation of instructions when hooked to the registers
and memory of a Task).

- Testsuite.  The best I could come up with for now is TestInstructions
and funit-instructions.c which is a nice little framework for having a
simple assembly instructions labeled in such a way that a 'instruction
address path' can be communicated to the java side so it can do either a
full step through the program or install breakpoints on every
instruction and make sure that every step and/or breakpoint hit takes it
to the right next address. But the assembly part has to be written
completely by hand (and unsurprisingly the simple assembly program
currently used works identically on x86 and x86_64). Trying to reuse the
funit-asm.h generic assembly instructions to make it platform neutral
was really hard especially since the labels used on the C and inline
assembly side have to kept in sync and mixing C defines and asm
statements don't seem to mix very well. Also at the moment it is just
using nops and jmps to keep things simple. I guess that in the end, if
we have real instruction parsers we could try to generate them using
that. Ideas or experiences with setting something up to track individual
instructions and getting the right addresses listed appreciated.

- Single Step Out Of Line Address Area.  Currently the Isa (for x86 and
x86_64 at least) just provide one address. The address of the main()
function entry point taken by just doing:

        Elf elf = new Elf(proc.getExe(), ElfCommand.ELF_C_READ);
        Dwarf dwarf = new Dwarf(elf, DwarfCommand.READ, null);
        DwarfDie die = DwarfDie.getDecl(dwarf, "main");
        return die.getEntryBreakpoints();

This works surprisingly well for a simple first approach, and programs
generally don't reenter their own main() function. But it would be nice
to either find an area that is guaranteed to never be used (again) by
the process, or to map in an executable area in the inferior that is
just used by us (maybe just making the inferior load a dummy shared
library). Again any suggestions welcome.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2007-07-23 12:19 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-04 18:20 Breakpoint stepping Mark Wielaard
2007-07-05  4:45 ` Phil Muldoon
2007-07-05 12:39   ` Mark Wielaard
2007-07-10  9:59     ` Leaving visible breakpoints in memory/core (Was: Breakpoint stepping) Mark Wielaard
2007-07-10 13:52       ` Andrew Cagney
2007-07-10 18:06       ` Phil Muldoon
2007-07-11  9:47         ` Mark Wielaard
2007-07-12  2:49           ` Roland McGrath
2007-07-12 14:24             ` Phil Muldoon
2007-07-12 20:24               ` Roland McGrath
2007-07-16 15:57                 ` Mark Wielaard
2007-07-17 15:43                   ` Phil Muldoon
2007-07-17 17:06                     ` Mark Wielaard
2007-07-16 15:53               ` Mark Wielaard
2007-07-17 15:47                 ` Phil Muldoon
2007-07-17 17:08                   ` Mark Wielaard
2007-07-05 18:37 ` Breakpoint stepping Andrew Cagney
2007-07-23 12:19   ` Mark Wielaard
2007-07-10 10:39 ` Instruction parser (Was: Breakpoint stepping) Mark Wielaard
2007-07-10 10:50 ` Instruction breakpoint-stepping testsuite " Mark Wielaard
2007-07-16  9:19   ` [patch] " Mark Wielaard
2007-07-10 10:57 ` SSOL Area " Mark Wielaard

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 read-only IMAP folder(s) and NNTP newsgroup(s).