This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH 1/2] This patch fixes GDBServer's run control for single stepping
- From: Antoine Tremblay <antoine dot tremblay at ericsson dot com>
- To: Yao Qi <qiyaoltc at gmail dot com>
- Cc: Antoine Tremblay <antoine dot tremblay at ericsson dot com>, Pedro Alves <palves at redhat dot com>, "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Date: Wed, 29 Mar 2017 10:11:17 -0400
- Subject: Re: [PATCH 1/2] This patch fixes GDBServer's run control for single stepping
- Authentication-results: sourceware.org; auth=none
- Authentication-results: sourceware.org; dkim=none (message not signed) header.d=none;sourceware.org; dmarc=none action=none header.from=ericsson.com;
- References: <20161129120702.9490-1-antoine.tremblay@ericsson.com> <20170127150139.GB24676@E107787-LIN> <wwokwpdg5vxa.fsf@ericsson.com> <CAH=s-PP-i3v_Fr=QeWt9BQeJzjCHtW79nGYpJ9hF-Bb=OBo89Q@mail.gmail.com> <wwokr33o5pkb.fsf@ericsson.com> <CAH=s-PO98nCE4UB9ag+V=M2mBnZT0FOeHV3d7mFMLYe1+v=mFg@mail.gmail.com> <wwok8tps8yo2.fsf@ericsson.com> <2255ed6f-a146-026c-f871-00e9a33dfcf0@redhat.com> <wwokwpcp7fvn.fsf@ericsson.com> <b5fb81d1-66fc-68c2-9785-ffa487de59e0@redhat.com> <wwoktw7t7bzy.fsf@ericsson.com> <CAH=s-PPx+SjoE0DkTKKNqg4Dr4zHFNt6QeC-XXT_LoXVh004iw@mail.gmail.com> <wwokh93s1he3.fsf@ericsson.com> <CAH=s-PPrB=s6d9Q07W=-b8Sz9umh6_Lj24PyO4x99Z3QrtfmzQ@mail.gmail.com> <wwokzig4l0i1.fsf@ericsson.com>
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
Antoine Tremblay writes:
> Yao Qi writes:
>
>> On 17-02-17 19:17:56, Antoine Tremblay wrote:
>>> > In ARM ARM, we have the pseudo code,
>>> >
>>> > boolean InITBlock()
>>> > return (ITSTATE.IT<3:0> != ‘0000’);
>>> >
>>> > ITSTATE can be got from CPSR.
>>>
>>> Yes that's good if you're inserting a breakpoint at current PC but
>>> otherwise you will need something else...
>>
>> In software single step, we calculate the next pcs, and select
>> breakpoint kinds of them, according to current pc. If current
>> pc is not within IT block (!InITBlock ()) or the last instruction
>> in IT block (LastInITBlock ()), we can safely use 16-bit thumb
>> breakpoint for any thumb instruction. That is, in
>> gdbserver/linux-aarch32-low.c:arm_breakpoint_kind_from_current_state,
>> we can return ARM_BP_KIND_THUMB if (!InITBlock () || LastInITBlock ()).
>
> This is not entirely true since we have to check if the next pcs are in
> an IT block rather then only the current one, so there's multiple
> scenarios.
>
> Consider if current PC is the IT instruction for example, then there's
> at least 2 next pcs inside the IT block where we will need to install an THUMB2
> breakpoint and get_next_pcs will return that.
>
> Now I find myself trying to replicate the logic in thumb_get_next_pcs_raw
> for IT blocks in arm_breakpoint_kind_from_current_state and it doesn't
> feel right.
>
> It gives something like:
>
> void
> set_single_step_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
> {
> struct single_step_breakpoint *bp;
>
> gdb_assert (ptid_get_pid (current_ptid) == ptid_get_pid (ptid));
>
> CORE_ADDR placed_address = stop_at;
> int breakpoint_kind
> = target_breakpoint_kind_from_current_state (&placed_address);
>
> bp = (struct single_step_breakpoint *) set_breakpoint_type_at_with_kind
> (single_step_breakpoint, placed_address, NULL, breakpoint_kind);
> bp->ptid = ptid;
> }
>
> int
> arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr)
> {
> if (arm_is_thumb_mode ())
> {
>
> if ( current_pcs_or_expected_next_pcs_are_in_it_block ??? /* That's
> not right... */
>
> {
> *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
> return ARM_BP_KIND_THUMB;
> }
> else
> {
> *pcptr = MAKE_THUMB_ADDR (*pcptr);
> return arm_breakpoint_kind_from_pc (pcptr);
> }
> }
> else
> {
> return arm_breakpoint_kind_from_pc (pcptr);
> }
> }
>
> It would be much better if get_next_pcs could select the breakpoint kind
> itself and hint that to set_single_step_breakpoint like :
>
> VEC (struct { next_pc, breakpoint_kind }) = (*the_low_target.get_next_pcs) (regcache);
>
> for (i = 0; VEC_iterate (struct { CORE_ADDR, kind }, next_pcs, i, pc); ++i)
> set_single_step_breakpoint (pc, kind, current_ptid);
>
> But of course that means changing that virtual function for all archs
> etc... :(
>
> I'm thinking of going with that approch but I would like to know if you
> have any other solutions to propose or if that sounds OK before writing
> all that code ?
>
> Thanks,
> Antoine
Just a small follow-up on this idea, I think it would simplify GDB's
implementation too, it would have to change anyway since the interface
is shared.
See commit 833b7ab5008b769dca6db6d5ee1d21d33e730132
introduces a special case in arm_breakpoint_kind_from_current_state
where it's checked if GDB is single stepping and if so redoes the
arm_get_next_pc to get the execution mode of the next instruction.
I could do the same kind of thing in GDBServer recall get_next_pcs and
if I get > 1 PC in the vect it would mean I have an IT block, but it
sounds like a hack.
I also find that confusing given that the documentation for
breakpoint_kind_from_current_state is:
# Return the breakpoint kind for this target based on the current
# processor state (e.g. the current instruction mode on ARM) and the
# *PCPTR. In default, it is gdbarch->breakpoint_kind_from_pc.
Finding the next PCs kind with this function seems like adding another
meaning to it...