From: Tom Tromey <tom@tromey.com>
To: Simon Farre via Gdb-patches <gdb-patches@sourceware.org>
Cc: Simon Farre <simon.farre.cx@gmail.com>, tom@tromey.com
Subject: Re: [PATCH v4] gdb/dap - dataBreakpointInfo & setDataBreakpoints
Date: Tue, 12 Sep 2023 11:47:02 -0600 [thread overview]
Message-ID: <87wmwvi8rt.fsf@tromey.com> (raw)
In-Reply-To: <20230620093222.210781-1-simon.farre.cx@gmail.com> (Simon Farre via Gdb-patches's message of "Tue, 20 Jun 2023 11:32:22 +0200")
>>>>> "Simon" == Simon Farre via Gdb-patches <gdb-patches@sourceware.org> writes:
Simon> v4.
Simon> Dead imports remained and dead docs on types. Removed
Thank you for the patch.
Simon> Added tests for data breakpoint, both for a simple struct and vars[1]
Simon> which is a std::vector<Var>. To be able to test this, I had to throw in
Simon> the gcc pretty printers file, as I had no other way (it seemed to me) to
Simon> be able to source them from the test.
This is not a good approach because it means the gdb tests are dependent
on the particular implementation of the C++ library.
Instead it's better to write something custom -- like a small C program
that uses a linked list or whatever is convenient, and then also write a
pretty-printer for that data structure.
Simon> I suppose one way to actually make it make
Simon> sense, would be to customize a gdb.Breakpoint (i.e. deriving from it),
Simon> that behaves both as a watchpoint *and* as a finish breakpoint; as soon
Simon> as the finish breakpoint hits, remove the watchpoint.
Non-"location" watchpoints kind of work this way, but TBH they are not
very good. I think they don't really self-disable, which might be
better. And AFAIK they don't really work properly with DWARF location
lists.
Simon> +def _info_not_available(desc):
Simon> + return {"dataId": None, "description": f"{desc}", "accessTypes": None}
This could just be a local function in _databreakpoint_info.
If it is separate it needs some kind of intro comment.
Simon> +
Simon> +@in_gdb_thread
Simon> +def _databreakpoint_info(
Simon> + name: str, variablesReference: Optional[int] = None, frameId: Optional[int] = None
frameId isn't used. I wonder if it should be.
It affects what sorts of expressions can be watched.
Simon> + if variablesReference is not None:
Simon> + variable = None
Simon> + # Resolve variable expression until find_variable throws
Simon> + try:
Simon> + variable = find_variable(variablesReference)
Simon> + except Exception as vr_not_found:
Simon> + return _info_not_available(vr_not_found)
Maybe it'd be better to just wrap the whole body in try/except and
remove some of these smaller ones and extra calls to _info_not_available.
Simon> + elif variablesReference is None:
I think this can just be 'else' because the previous test is for "not None".
Then the final "return" can be removed.
Simon> +def _sanitize_wp_input(breakpoints: Sequence) -> Sequence:
Simon> + """Sanitize input so that it plays well with current design."""
Simon> + res = []
Simon> + for wp in breakpoints:
Simon> + obj = {}
Simon> + obj["condition"] = wp.get("condition")
Simon> + obj["hitCondition"] = wp.get("hitCondition")
Simon> + obj["accessType"] = wp.get("accessType")
Simon> + obj["dataId"] = wp.get("dataId")
Simon> + res.append(obj)
Simon> + return res
I don't understand the need for this. It seems like an identity
function, more or less -- extra fields shouldn't really affect anything.
Simon> +
Simon> +def _wp_type(type: str):
Needs a comment.
Simon> +@in_gdb_thread
Simon> +def _create_watchpoints(dataId, accessType, enabled=True):
This should probably be "_create_watchpoint", since it only makes one.
I don't think 'enabled' is ever used?
Simon> + wp = gdb.Breakpoint(
Simon> + spec=f"*{dataId}", type=gdb.BP_WATCHPOINT, wp_class=_wp_type(accessType)
I don't think this will fully work.
The dataId is computed by:
+ dataId = hex(int(gdb_value.address))
However, "*0xADDR" in gdb really means something like "*(int *)0xADDR".
That is, this watchpoint will only watch a single word.
It's tempting to use something like "*ADDR @ N_BYTES" as the expression.
I wonder if that's supported by all the language parsers, though.
Simon> if isinstance(event, gdb.BreakpointEvent):
Simon> # Ignore the expected stop, we hit a breakpoint instead.
Simon> - _expected_stop = StopKinds.BREAKPOINT
Simon> + if event.breakpoints[0].expression:
Simon> + _expected_stop = StopKinds.DATABREAKPOINT
Simon> + else:
Simon> + _expected_stop = StopKinds.BREAKPOINT
This could also just examine Breakpoint.type which may be more clear.
Simon> + def try_find_member(self, name: str) -> gdb.Value:
Simon> + type = self.value.type
Needs some sort of doc string.
Simon> + # Non-pretty printed values more common. Search type definition first
Simon> + for field in type.fields():
Simon> + if field.name == name:
Simon> + return self.value[field]
I think it's better to just always use the wrapping pretty-printer and
just delete this code.
One way this could matter is if we fix the "multiple variables with the
same name" problem that I think can arise in some C++ inheritance
scenarios -- the printer might rename the fields for presentation
purposes.
Simon> + for (child_name, value) in self.printer.children():
Simon> + if child_name == name:
Simon> + return value
It's possible the children are already cached. I sent some patches to
change this area a little, but I suppose the way it should work is to
examine the cache if it exists.
This is an area where we could add random-access-by-name to the printer
extension methods. Though that would require docs.
Tom
prev parent reply other threads:[~2023-09-12 17:47 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-20 9:32 Simon Farre
2023-09-12 17:47 ` Tom Tromey [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=87wmwvi8rt.fsf@tromey.com \
--to=tom@tromey.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.farre.cx@gmail.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).