A better register interface

Andrew Cagney
2001-02-14T20:39:00Z

Hello,

As many people will tell you GDB's current register interface/model is
so large you can comfortably drive a road train through it.

Right now there are roughly the following interfaces:

On the target side:

o supply_register()

o register_buffer()
(nee register_buffer[])

While on the GDB side, there are a number of ways of getting at the
cache and all are used randomly.

o read_register()

o write_register()

o get_saved_register()

o find_saved_register()

but quickly decays into:

o {read,write}_register_pid()

o read_register_bytes()

o register_buffer()

o {read,write}_register_gen()

Accompanying this there is the split of GDB's registers into virtual,
raw, normal? and pseudo. Pseudo registers are significant as, in theory
at least, they are not backed by real bytes but instead constructed on
the fly using bits and bytes from other registers. Well nice theory :-/

Associated with this are a number of bugs. The most common are:

o you can't get a complex pseudo
register from a saved frame

o you can't modify a complex pseudo

o you can only print complex psuedos
by a hack - have it backed by a
read only buffer.

o the RAW_REGISTER_BYTE() macro determines
everything including the format of the
remote G packet.

(a complex pseudo is one that is constructed from random bits from the
register cache or stack).

I'd like to bite the bullet and see GDB rid of this mess. As a starting
point, I'd like to propose the following as the minimal interface and
try to cut things down so that there is only a minimal number of calls
into the register cache. Hopefully this proposal would also help better
clarify the register interfaces. In this I've borrowed from several
recent postings (Steven Johnson and Nick Duffek) along with too many bad
experiences with the existing model.

--

While eventually, I'd like to see a clear separation between the two
sides of the register cache - the target side which supplies raw bytes
and the gdb/core side which uses values and register names, it won't be
possible for some time. Instead, I'd like to see the existing REGNUM
space structured as:

core gdb | target side

0
.
. raw register space
.
NUM_RAW_REGISTERS
.
. any additional non raw registers
.
NUM_COOKED_REGISTERS

There are 0..NUM_RAW_REGISTERS raw registers that contain raw register
bytes supplied by the target.

The target side is only allowed to access 0..NUM_RAW_REGISTERS using
functions like:

supply_raw_register(RAWNUM, buf, sizeof buf)
set_raw_register_state (RAWNUM, that register valid stuff);
fetch_raw_register(RAWNUM, buf, sizeof buf)
something for value changed?
raw_register_size(RAWNUM)
raw_register_name(RAWNUM)

raw_register_name() is significant as it is new. It is there for two
reasons:

o it allows the implementation
of a simple but meanginful
``info raw-registers''
command that would just dump
the raw buffer

o it provides abstract names to
each target side register.

remote.c would then be able to
describe its G packet in terms
of ``target names'' rather than
magic numbers and mysterious offsets.
(eg set G-packet-format r0:4,4;r1:12,8;...)

There are 0..NUM_COOKED_REGISTERS cooked/pseudo registers that supply
register values to core-gdb.

gdb-core would be allowd to access cooked registers. Cooked register
methods would have frame associated with them (NULL implies no frame but
must be handled).

cooked_register_name(frame, REGNUM)
cooked_register_type(frame, REGNUM)
provides the size implicitly
read_cooked_register(frame, REGNUM, buf, sizeof buf)
write_cooked_register(frame, REGNUM, buf, sizeof buf)
along with a few others such as:
cooked_register_attrib_p (frame, REGNUM, some attribute - is FP?)

thoughts. The key thing is that, the interface is minimized. This
would mean that chunks of GDB would need re-implemented. But as they
say, no pain, no gain.

Andrew