public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Farre <simon.farre.cx@gmail.com>
To: Tom Tromey <tom@tromey.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH v3] gdb/DAP Fix disassemble bug
Date: Wed, 12 Jul 2023 11:17:30 +0200	[thread overview]
Message-ID: <4719ab45-639a-d40b-4385-7f1117e00da8@gmail.com> (raw)
In-Reply-To: <871qheqkkl.fsf@tromey.com>

> A few nits here:
>
> * Should use @in_gdb_thread
>
> * I can tell from the line spacing that you didn't run "black".
>
> * The DAP code has a convention of prefixing internal functions with "_"
I'll be sure to fix the nits!
> Simon> +    while len(instructions) < (offset + 1):
> Simon> +        block = gdb.current_progspace().block_for_pc(start)
> Simon> +        # Fail fast; if we can't find a block backwards
> Simon> +        # fill all with "invalid values"
> Simon> +        if block is None:
> Simon> +            tmp = []
> Simon> +            for i in range(0, offset - len(instructions)):
> Simon> +                tmp.append({"addr": 0, "asm": "unknown"})
> Simon> +            instructions = tmp + instructions
>
> I wonder if this block should end with a 'break'.  I guess I don't
> really follow the logic here.
That's probably true, as that would break the while loop's condition, so 
we might as well
break out early.
> Simon> +    if skip_insns < 0:
> Simon> +        ins = disasm_backwards(arch, pc, skip_insns, count)
> Simon> +        skip_insns = 0
> Simon> +        count = count - len(ins)
> Simon> +        result = [
> Simon> +            {"address": hex(elt["addr"]), "instruction": elt["asm"]} for elt in ins
> Simon> +        ]
> Simon> +
> Simon> +    for elt in arch.disassemble(pc, count=count + skip_insns)[skip_insns:]:
>
> Likewise it seems weird to fall through here.
>
> I think a test case with a negative skip would be good.
>
> Tom

So, this block explicitly is what solves the problem with the prior 
patch (where skip_insns could be negative, but wasn't accounted for - 
particularly if total count was more than that negative offset)
Let's take a simple example, where offset is -50 and total count is 100, 
that means we want instructions in the range [-50 .. 50);
If skip_insns is less than 0 (i.e., the instructionOffset is negative), 
we deal with those first - set skip_insns to 0 and decrement total count 
of requested instructions
Then we proceed and disassemble the remainder in the "postive offset 
direction". If there is no remainder after the first branch, no more 
instructions are going to be dissassembled.

The reason why I'm setting skip_insns = 0 here, is to not have strange 
and long if-then-else branches. Because then we must account for a 
multiplication of things (instead of the simple fall-through approach);
The different scenarios would be:
Is offset negative? * (is total count less than that offset? || is total 
count more than that offset?) = 1 + (2)
Is offset positive? (total count doesn't matter, we just start at offset 
.. offset+total count) = 1
Where each branch also will have copy pasted logic to account for these 
different scenarios.

Here we instead just say "process before, then process what remains" - 
if skip_insns (instructionOffset) isn't negative, that branch is never 
taken.
I think perhaps the current checked in work, confuses things with how 
it's named in the helper function;
skip_insns is actually not skipped instructions it's instructionOffset 
as you can see in the actual handler function.

I would like some pointers though, on how we would test this? Decide on 
a platform?
Because it's not just a matter of testing the instruction count being 
returned, that's trivial, we must also make sure that the *actual 
disassembly* is correct.
If the test suite was written in a "good" (don't let my frustration at 
Tcl shine through:P) language, I could write something that calls 
objdump/readelf, reads the actual instructions
and compares it with the output of the request. In Python or Javascript 
this would be trivial and could be whipped up in 10 minutes, I am not as 
confident it's that easy in Tcl unfortunately.
Perhaps call into Python from tcl? What do you think?

Either way, next patch will have tests on the instruction count being 
correct at least.


      reply	other threads:[~2023-07-12  9:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-27 16:38 Simon Farre
2023-07-11 20:06 ` Tom Tromey
2023-07-12  9:17   ` Simon Farre [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4719ab45-639a-d40b-4385-7f1117e00da8@gmail.com \
    --to=simon.farre.cx@gmail.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).