RE: [PATCH v6 9/9] Add documentation for new record Python bindings.

Wiederhake, Tim
2017-03-06T08:56:48Z

Hi Yao,

> I read them again this morning, and have a design question in general, why
> are they specific to btrace?
> (...)
> Can add a base class like RecordInstruction, which have some basic attributes
> for all record methods, and BtraceInstruction extends it to add more btrace
> specific attributes.

Unfortunately, the interfaces to the "full" and "btrace" recording differ quite
much. So even for "common" attributes, the code for the base class instruction
and function segment objects would have to "if (method == ...)" through all
recording methods, cluttering it, making it harder to maintain and potentially
cause trouble if we introduce another recording format in the future when
functions in the base class suddenly are not implemented for all methods
anymore.

My idea was to make use of Python's philosophy of duck-typing. Having specific
(C wrapper) objects for each recording method solves the problem of how to
obtain the requested data from the recording "back end". If we name respective
functions and attributes the same in these classes, we "quack like a duck" and
create the same common interface for the user from Python's perspective.

> Sorry, I don't understand BtraceFunctionCall, can you give an example?
> BtraceFunctionCall.symbol and .level indicates it represents a function call
> rather than a function. In the following example,
>
> f2 () { f1 (); }
> f3 () { f1 (); }
>
> main () { f2 (); f3 (); }
>
> (...)

Your example creates nine function segments as can be seen in
`record function-call-history /lic`:
1 main inst 1,2 at
2 f2 inst 3,6 at
3 f1 inst 7,11 at
4 f2 inst 12,14 at
5 main inst 15,16 at
6 f3 inst 17,20 at
7 f1 inst 21,25 at
8 f3 inst 26,28 at
9 main inst 29,30 at

The objects in (Python) gdb.current_recording().function_call_history represent
one line in that list each. That is, each time execution flow returns to a
function a new segment for this function call is created. The segments that
belong to the same function call (i.e. #1 -> #5 -> #9 or #2 -> #4 or #6 -> #8)
are linked via the prev_sibling and next_sibling attribute of the objects.

"up" is the link to the caller or returned-to function call segment. For #2 and
#4 in the example, this would be "#1".

I hope I was able to clear things up,
Tim

> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Yao Qi
> Sent: Friday, March 3, 2017 12:10 PM
> To: Wiederhake, Tim <tim.wiederhake@intel.com>
> Cc: gdb-patches@sourceware.org; Metzger, Markus T
> <markus.t.metzger@intel.com>; palves@redhat.com; xdje42@gmail.com
> Subject: Re: [PATCH v6 9/9] Add documentation for new record Python
> bindings.
>
> Tim Wiederhake <tim.wiederhake@intel.com> writes:
>
> Hi Tim,
> I read them again this morning, and have a design question in general, why
> are they specific to btrace?
>
> > +The attributes and methods of instruction objects depend on the
> > +current recording method. Currently, only btrace instructions are
> supported.
> > +
> > +A @code{gdb.BtraceInstruction} object has the following attributes:
> > +
> > +@defvar BtraceInstruction.number
> > +An integer identifying this instruction. @var{number} corresponds to
> > +the numbers seen in @code{record instruction-history} (@pxref{Process
> > +Record and Replay}).
> > +@end defvar
> > +
>
> Why is it btrace specific? Instructions in history of any record methods can
> have a number or id, isn't?
>
> > +@defvar BtraceInstruction.error
> > +An integer identifying the error code for gaps in the history.
> > +@code{None} for regular instructions.
> > +@end defvar
>
> > +
> > +@defvar BtraceInstruction.sal
> > +A @code{gdb.Symtab_and_line} object representing the associated
> > +symtab and line of this instruction. May be @code{None} if the
> > +instruction is a gap.
> > +@end defvar
> > +
> > +@defvar BtraceInstruction.pc
> > +An integer representing this instruction's address. May be
> > +@code{None} if the instruction is a gap or the debug symbols could not be
> read.
> > +@end defvar
>
> Again, is it btrace specific? Any instruction will have an address, regardless of
> debug symbol.
>
> Secondly, we have BtraceInstruction.pc, do we still need
> BtraceInstruction.sal? The sal can be got from other python api, although
> these api may not exist.
>
> Can add a base class like RecordInstruction, which have some basic attributes
> for all record methods, and BtraceInstruction extends it to add more btrace
> specific attributes.
>
> > +
> > +@defvar BtraceInstruction.data
> > +A buffer with the raw instruction data. May be @code{None} if the
> > +instruction is a gap.
> > +@end defvar
> > +
> > +@defvar BtraceInstruction.decoded
> > +A human readable string with the disassembled instruction. Contains
> > +the error message for gaps.
> > +@end defvar
> > +
> > +@defvar BtraceInstruction.size
> > +The size of the instruction in bytes. Will be @code{None} if the
> > +instruction is a gap.
> > +@end defvar
> > +
> > +@defvar BtraceInstruction.is_speculative A boolean indicating whether
> > +the instruction was executed speculatively. Will be @code{None} for
> > +gaps.
> > +@end defvar
>
> Why are these four attributes about Btrace or even record? To me, they are
> about instruction decode or disassembly.
>
> > +
> > +The attributes and methods of function call objects depend on the
> > +current recording format. Currently, only btrace function calls are
> > +supported.
> > +
> > +A @code{gdb.BtraceFunctionCall} object has the following attributes:
> > +
> > +@defvar BtraceFunctionCall.number
> > +An integer identifying this function call. @var{number} corresponds
> > +to the numbers seen in @code{record function-call-history}
> > +(@pxref{Process Record and Replay}).
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.symbol
> > +A @code{gdb.Symbol} object representing the associated symbol. May
> > +be @code{None} if the function call is a gap or the debug symbols
> > +could not be read.
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.level
> > +An integer representing the function call's stack level. May be
> > +@code{None} if the function call is a gap.
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.instructions A list of
> > +@code{gdb.BtraceInstruction} objects associated with this function
> > +call.
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.up
> > +A @code{gdb.BtraceFunctionCall} object representing the caller's
> > +function segment. If the call has not been recorded, this will be
> > +the function segment to which control returns. If neither the call
> > +nor the return have been recorded, this will be @code{None}.
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.prev_sibling A
> > +@code{gdb.BtraceFunctionCall} object representing the previous
> > +segment of this function call. May be @code{None}.
> > +@end defvar
> > +
> > +@defvar BtraceFunctionCall.next_sibling A
> > +@code{gdb.BtraceFunctionCall} object representing the next segment of
> > +this function call. May be @code{None}.
> > +@end defvar
> > +
>
> Sorry, I don't understand BtraceFunctionCall, can you give an example?
> BtraceFunctionCall.symbol and .level indicates it represents a function call
> rather than a function. In the following example,
>
> f2 () { f1 (); }
> f3 () { f1 (); }
>
> main () { f2 (); f3 (); }
>
> Here are my understandings,
>
> - There are two BtraceFunctionCall objects bf1 and bf2 for f1, the first
> one, bf1, is about the call in f2 and the second one, bf2, is about the
> call in f3.
> - bf2.up is about the call in f2, and bf3.up is about the call in f3.
> - bf2.next_sibling == bf3 and bf3.prev_sibling == b2
>
> Are they correct?
>
> --
> Yao (齐尧)
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928