Target/Process (and data access) change proposal for non-8-bit byte architectures

Hi people,

As some of you may already be aware I'm trying to modify lldb in order
to debug CSR's kalimba architectures, which for certain variants have
non-8-bit byte sizes. This is proving to be quite tough, and clearly
(I'm not being critical here - I'm just stating a fact) lldb is not
currently architectured to support this feature.

The issue I'd like to discuss now is the signatures of the ReadMemory
functions of the Target and Process.

(From Target)
size_t
ReadMemory (const Address& addr,
  bool prefer_file_cache,
  void *dst,
  size_t dst_len,
  Error &error,
  lldb::addr_t *load_addr_ptr = NULL);

size_t
ReadMemoryFromFileCache (const Address& addr,
  void *dst,
  size_t dst_len,
  Error &error);

(From Process)
virtual size_t
ReadMemory (lldb::addr_t vm_addr,
void *buf,
size_t size,
Error &error);

(and so on)

The problem, IMO, is the way in which the caller must allocate and size
a buffer (void* dst/buff) and pass this, and it's size to the
invocation. This means that all clients of these functions must enquire
as to their targets byte-size, multiple this number by the requested
number of "units", and then upon return sub-divide the read data into
target-sized units. This is messy and also means that all callers
require this level of awareness; and it's further complicated by the
fact that the kalimba 24 bit variants, have 24-bit bytes from their data
bus, but 8-bit bytes (kalvariant-5) or 32-bit bytes (kalvariant-3) on
their code bus.

I'd like to solve this in the following way, I would swap the

void* dst parameter
for
DataBufferSP&

(and rename size/dst_len to target_bytes_requested).
Then it would the callee's (i.e. Target/Process) responsibility to
allocate the buffer. This makes it easier to encapsulate details
required for handling the Target's byte size, since it is then hidden
within the Target class. Memory release semantics, I think, will be
unchanged, since where the caller was previously as follows:

DataBufferSP data_sp;
data_sp.reset(new Data... (size));
target->ReadMemory(
address,
false,
data_sp->GetBytes (),
data_sp->GetByteSize(),
error);

With my proposal we'd have:

DataBufferSP data_sp;
target->ReadMemory(
address,
false,
data_sp,
target_bytes_requested,
error);

(The return value also being in terms of number of target bytes.)

So memory release would (still) be simple.

For further support of my quest I'd also like to enhance the DataBuffer
class. Currently it offers:

virtual const uint8_t *
GetBytes () const = 0;

virtual lldb::offset_t
GetByteSize() const = 0;

These routines are fine. (To me they are referring to host bytes). I'd
like to add:

virtual const TargetByte *
GetTargetBytes () const = 0;

virtual lldb::offset_t
GetTargetByteSize() const = 0;

I'm not quite sure how to implement these DataBuffer (and maybe
DataExtractor) changes quite yet. But clearly I require a way for memory
accessing client code to deal with target bytes, without polluting that
code by attempting to subdivide buffers of host bytes.

your comments and feedback appreciated

thanks
Matt

Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Keep up to date with CSR on our technical blog, www.csr.com/blog, CSR people blog, www.csr.com/people, YouTube, www.youtube.com/user/CSRplc, Facebook, www.facebook.com/pages/CSR/191038434253534, or follow us on Twitter at www.twitter.com/CSR_plc.
New for 2014, you can now access the wide range of products powered by aptX at www.aptx.com.