Re: gdb for Riscv, single stepping issue

Pedro Alves <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
On 2022-06-28 16:52, John Baldwin wrote:
> On 6/27/22 1:40 PM, James Becker wrote:
>> Hello,
>>
>> I have a RISCV-EL2 core running in a Nexys A7 FPGA board.
>>
>> I have openocd for riscv running over jtag with a connection by
>> riscv-gdb to the openocd instance at port 3333.
>>
>> Everything works fine, stepping, break points, load, view memory.
>>
>> But I have one issue: Some of the memory in my design is 4 byte
>> aligned.  Its designed for fast instruction fetch, its known as ICCM.
>>
>> When I have code running in that memory, gdb still works fine for
>> breakpoints, but it will not single step.
>>
>> Looking at the openocd debug files, it appears that gdb is attempting to
>> do a 2 byte read as a part of the single stepping procedure.
>>
>> Since my memory does not support 2 byte reads or writes, this fails.
>>
>> Is there some way that gdb can be configured to not do any 2-byte word
>> reads or writes during single stepping?  I can't seem to find any.
> 
> Hmm, setting breakpoints tries to read 1 byte at a time unless you have
> disabled compressed breakpoints.  It looks like as a local hack you could
> change use-compressed-breakpoints to just read 4 bytes rather than 2
> initially?  Perhaps this is upstreamable if you make it read 4 bytes if
> the target address is 4 byte aligned and only fall back to reading 2 bytes
> if it isn't?
> 

Is that from riscv_breakpoint_kind_from_pc?  That uses target_read_code,
so I'd think that since it goes via the code cache, it would read a whole
cache line at once, meaning 64 bytes (show code-cache, show dcache line-size).

OTOH, riscv_insn::fetch_instruction uses target_read_memory to read 2 bytes,
so I wonder whether this is the access in question:

  /* All insns are at least 16 bits.  */
  status = target_read_memory (addr, buf, 2);
  if (status)
    memory_error (TARGET_XFER_E_IO, addr);

Why is this using target_read_memory instead of target_read_code, though?
If it did that, then the code cache would be involved here too, papering over
the issue, presumably.

Curious that the Riscv stub behaves this way, though.  I mean, failing the
access instead of reading in aligned 4 bytes chunks, and doing read-modify-write,
if necessary, hiding the issue from GDB.  Even inf-ptrace.c handles unaligned
reads/writes and shorter-than-word-sized reads/writes itself, like:

static ULONGEST
inf_ptrace_peek_poke (ptid_t ptid, gdb_byte *readbuf,
		      const gdb_byte *writebuf,
		      ULONGEST addr, ULONGEST len)
{
...
  /* We transfer aligned words.  Thus align ADDR down to a word
     boundary and determine how many bytes to skip at the
     beginning.  */
...
      /* Read the word, also when doing a partial word write.  */
      if (readbuf != NULL || chunk < sizeof (PTRACE_TYPE_RET))
	{


I guess this also affects the "x" command at least (e.g., "x/2b $pc"), since that
doesn't use the code cache either.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.