This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

supporting all kinds of partially-<unavailable> enum target_object types (was: Re: [PATCH] Send qXfer:traceframe-info:read when traceframe is selected.)


(Sending this as separate email, as I'm not objecting to the patch.)

Compared to when the tfile target itself handled reading from
the file's RO sections itself, IMO, the end result is more confusing,
with strange interfaces -- "why is traceframe_info being called if
there's no traceframe selected in the first place" immediately comes
to mind.  It seems to me we traded one little wrinkle for a
larger one.  :-)

I sent this to Sergio offlist in the context of supporting
partially <unavailable> $_siginfo, but I think it's appropriate
here too.  So this was about supporting <unavailable> target
objects other than memory (in that case, TARGET_OBJECT_SIGNAL_INFO),
but it'd apply to memory just as well.

I think a clean solution would entail extending the
target_xfer interface.  Consider an object/value like this:

  0          100      150        200           512
  DDDDDDDDDDDxxxxxxxxxDDDDDD...DDIIIIIIIIIIII..III

where D is valid data, and xxx is unavailable data, and I is beyond
the end of the object (Invalid).  Currently, if we start the
xfer at 0, requesting, say 512 bytes, we'll first get back 100 bytes.
The xfer machinery then retries fetching [100,512), and gets back
TARGET_XFER_E_UNAVAILABLE.  That's sufficient when you're either
interested in either having the whole of the 512 bytes available,
or erroring out.  But, in this scenario, we're interested in
the data at [150,512).  The problem is that the last
TARGET_XFER_E_UNAVAILABLE gives us no indication where to
start the read next.  We'd need something like:

get me [0,512) >>>
           <<< here's [0,100)

get me [100,512)  >>>
           <<< [100,150) is unavailable    (**1)

get me [150,512) >>>
           <<< here's [150,200)

get me [200,512) >>>
           <<< no more data

We could do that by changing target_xfer_partial's
interface from:

    LONGEST (*to_xfer_partial) (struct target_ops *ops,
				enum target_object object, const char *annex,
				gdb_byte *readbuf, const gdb_byte *writebuf,
				ULONGEST offset, LONGEST len);

to:

    int (*to_xfer_partial) (struct target_ops *ops,
				enum target_object object, const char *annex,
				gdb_byte *readbuf, const gdb_byte *writebuf,
				ULONGEST offset, ULONGEST len, ULONGEST *read_count);

Where the target implementation would write how many bytes were read
to *READ_COUNT, instead of returning it. (The int return would then be just
be success/error, instead of the read length.)

When returning TARGET_XFER_E_UNAVAILABLE, we'd return in
*READ_COUNT the number of unavailable bytes "read", or IOW, where
the next non-<unavailable> byte is, or LEN, if that comes before.

So the (**1) case above would return TARGET_XFER_E_UNAVAILABLE
with *READ_COUNT set to 50.

target_read_memory would be likewise adjusted, or a variant added.
And then, in specific case of values, read_value_memory would not have that
available_memory vector or any traceframe_number check, but instead
would call target_read_memory in a loop, and if TARGET_XFER_E_UNAVAILABLE
comes out, it'd mark READ_COUNT value bytes unavailable starting at
the requested address, and then continue reading from the previous
addr + READ_COUNT, rinse repeat, until the whole value was read in.

This naturally implies pushing down the decision of whether
to return TARGET_XFER_E_UNAVAILABLE or something else
down to the target.  (Which kinds of leads back to tfile
itself reading from RO memory from file (though we could
export a function in exec.c for that that tfile delegates to,
instead of re-adding the old code).

-- 
Pedro Alves


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]