Bug 29869 - sim: align sim register numbers with gdb register numbers
Summary: sim: align sim register numbers with gdb register numbers
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: sim (show other bugs)
Version: unknown
: P2 normal
Target Milestone: ---
Assignee: Mike Frysinger
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-12-10 12:23 UTC by Mike Frysinger
Modified: 2023-12-31 22:44 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Frysinger 2022-12-10 12:23:57 UTC
it would be good if we aligned sim register numbers with gdb's register numbers (as used in the default remote serial protocol).  this has a number of benefits:
* if/when we add RSP support to the sim, gdb/debuggers would "just work" with it
* we can delete the set_gdbarch_register_sim_regno logic from gdb
* we don't need to hand maintain the include/sim/sim-* register lists (as we can generate them from gdb xml files)

some architectures already have aligned their register numbers, so there's no diff to them.  for others, this would represent an ABI break.  sim.h provides sim_fetch_register & sim_store_register APIs, and the sim register numbers are used with those.  changing the enum/constants obviously requires a recompile.  i don't think this is a problem because:
* we already need to do ABI breaks to fix 64-bit address handling (current ABI is limited to 32-bit)
* we'll need to break again to expose multicpu
* libsim is only statically linked into programs (we don't provide a shared lib yet)
* for the gdb<->sim interface, since the GNU sim is bundled+linked in to gdb, we don't have to worry about old/new version skews of gdb/sim
* i'm not aware of anyone using the sim reg numbers outside of the GNU sim, and i don't think gdb even supports that if they tried

while we shouldn't trash the API needlessly, i think atm we have so many shortcomings that we shouldn't bend over backwards to maintain support.

we could support gdb's Target Description Format where the sim would generate an XML document on the fly describing its arches/registers/etc... and thus avoid the register remapping, but i think we should break anyways.  gdb doesn't require XML support be enabled which means it'll still fallback to classic hardcoded register numbers.
https://sourceware.org/gdb/onlinedocs/gdb/Target-Description-Format.html#Target-Description-Format
Comment 1 Tom Tromey 2023-12-23 19:47:21 UTC
I randomly hack on this and while looking at it today I realized
I don't know how to find the number of registers for a particular
sim.  Is this available?

gdbserver wants to iterate over all the registers in its
'fetch_registers' (and also store) callback.
Comment 2 Mike Frysinger 2023-12-24 00:45:04 UTC
include/sim/sim-<arch>.h
Comment 3 Tom Tromey 2023-12-24 20:11:50 UTC
Hmm, that's missing for some arches.
Then I thought about just reusing the xml register descriptions,
but those are also missing in some cases.
Comment 4 Mike Frysinger 2023-12-25 01:52:21 UTC
on the sim side, the key is to start with CPU_REG_FETCH & CPU_REG_STORE.  those set the callbacks for gdb to read/write registers via register number.

ports with sim headers:
aarch64 arm bfin cr16 d10v frv ft32 h8300 lm32 m32c ppc riscv rl78 rx sh

ports w/out gdb support so don't super care:
example-synacor mcore pru

ports that copy & paste register numbers between gdb & sim so they're the same:
avr (AVR_xxx_REGNUM)
bpf (BPF_Rxx)
iq2000 (xxx_REGNUM)
m32r (xxx_REGNUM) -- although it seems they aren't completely in sync
m68hc11 (xxx_REGNUM)
microblaze (NUM_REGS)
mn10300 (struct _state.regs & xxx_REGNUM)
moxie (struct moxie_regset.regs & xxx_REGNUM)
msp430 (struct msp430_cpu_state.regs & MSP430_xxx_REGNUM)
v850 (struct _v850_regs.regs & .sregs & E_xxx_REGNUM)

ports w/gdb port & w/out sim headers that i'm not sure if/how they work:
cris erc32(sparc) mips(many ISAs) or1k ppc
Comment 5 Tom Tromey 2023-12-29 01:35:33 UTC
The issue for gdbserver integration is that a general request
may arrive, which just means "send all the registers".
So, the server has to know how to iterate over them.
Digging a bit I see this info in some ports, but it's not generically
available via the sim public API.  It works in gdb due to the
synchronicity you point out: gdb and the sim generally agree (or
there is a mapping).

I don't really understand why this info isn't in the cgen model
either, but it doesn't seem to be.

Anyway I suspect a new field in _sim_cpu may be the way to go...

Though looking at this, we also don't know the size of registers.
gdb does, but it doesn't inform the remote of this -- the remote
is expected to know.
Comment 6 Mike Frysinger 2023-12-29 04:46:49 UTC
(In reply to Tom Tromey from comment #5)
> I don't really understand why this info isn't in the cgen model
> either, but it doesn't seem to be.

i don't think it makes sense for cgen to know about this.  what we're talking about here is a communication protocol for serializing & deserializing state, and GDB defines that protocol.

> Anyway I suspect a new field in _sim_cpu may be the way to go...

while converting the sim to RSP completely is a pretty heavy lift, i think we have some incremental steps we could consider

* have gdb maintain the lists, and automatically convert/generate/export them to sim in the source tree.  if there are XML files, use those.  if there are enums in header files, use those.  we already do this sort of thing with newlib via sim/common/gennltvals.py, and we commit the result (rather than gen at build time via portable shell/etc...).  i think we have/want to do this regardless.
* add a parallel set of sim_{store,fetch}_register APIs that used the same encoding as RSP.

> Though looking at this, we also don't know the size of registers.
> gdb does, but it doesn't inform the remote of this -- the remote
> is expected to know.

when it comes to the sim APIs, gdb calls the sim with the size.  sim_fetch_register & sim_store_register both have a "length", and the sim basically treats it as "it has to match the register size requested via regno".

sim_fetch_register also is designed such that passing in length=0 will return the size of the requested register without writing to the buffer.  so callers could cheaply probe the size of all registers.
Comment 7 Tom Tromey 2023-12-31 22:44:02 UTC
Ok, I have a proof of concept on my github.
https://github.com/tromey/gdb/tree/t/random-sim-hacking-2

This builds a gdbserver for moxie.
The main content is in sim/common/sim-target.cc
... with various build hacks and whatnot to support this.

I have not tested it at all.