#include "gdbcmd.h" /* For maintenanceprintlist. */
#include "observer.h"
#include "exceptions.h"
+#include "remote.h"
/*
* DATA STRUCTURE
long sizeof_cooked_registers;
long sizeof_cooked_register_status;
- /* Offset and size (in 8 bit bytes), of reach register in the
+ /* Offset and size (in 8 bit bytes), of each register in the
register cache. All registers (including those in the range
[NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an
offset. */
static struct regcache_list *current_regcache;
struct regcache *
-get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
+ struct address_space *aspace)
{
struct regcache_list *list;
struct regcache *new_regcache;
&& get_regcache_arch (list->regcache) == gdbarch)
return list->regcache;
- new_regcache = regcache_xmalloc_1 (gdbarch,
- target_thread_address_space (ptid), 0);
+ new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
new_regcache->ptid = ptid;
- gdb_assert (new_regcache->aspace != NULL);
list = xmalloc (sizeof (struct regcache_list));
list->regcache = new_regcache;
return new_regcache;
}
+struct regcache *
+get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+{
+ struct address_space *aspace;
+
+ /* For the benefit of "maint print registers" & co when debugging an
+ executable, allow dumping the regcache even when there is no
+ thread selected (target_thread_address_space internal-errors if
+ no address space is found). Note that normal user commands will
+ fail higher up on the call stack due to no
+ target_has_registers. */
+ aspace = (ptid_equal (null_ptid, ptid)
+ ? NULL
+ : target_thread_address_space (ptid));
+
+ return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace);
+}
+
static ptid_t current_thread_ptid;
static struct gdbarch *current_thread_arch;
to the current thread. This switching shouldn't be necessary
only there is still only one target side register cache. Sigh!
On the bright side, at least there is a regcache object. */
- if (!regcache->readonly_p)
+ if (!regcache->readonly_p
+ && regcache_register_status (regcache, regnum) == REG_UNKNOWN)
{
- if (regcache_register_status (regcache, regnum) == REG_UNKNOWN)
- {
- struct cleanup *old_chain = save_inferior_ptid ();
+ struct cleanup *old_chain = save_inferior_ptid ();
- inferior_ptid = regcache->ptid;
- target_fetch_registers (regcache, regnum);
- do_cleanups (old_chain);
- }
-#if 0
- /* FIXME: cagney/2004-08-07: At present a number of targets
- forget (or didn't know that they needed) to set this leading to
- panics. Also is the problem that targets need to indicate
- that a register is in one of the possible states: valid,
- undefined, unknown. The last of which isn't yet
- possible. */
- gdb_assert (regcache_register_status (regcache, regnum) == REG_VALID);
-#endif
+ inferior_ptid = regcache->ptid;
+ target_fetch_registers (regcache, regnum);
+ do_cleanups (old_chain);
+
+ /* A number of targets can't access the whole set of raw
+ registers (because the debug API provides no means to get at
+ them). */
+ if (regcache->register_status[regnum] == REG_UNKNOWN)
+ regcache->register_status[regnum] = REG_UNAVAILABLE;
}
if (regcache->register_status[regnum] != REG_VALID)
return regcache->register_status[regnum];
}
+ else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+ {
+ struct value *mark, *computed;
+ enum register_status result = REG_VALID;
+
+ mark = value_mark ();
+
+ computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+ regcache, regnum);
+ if (value_entirely_available (computed))
+ memcpy (buf, value_contents_raw (computed),
+ regcache->descr->sizeof_register[regnum]);
+ else
+ {
+ memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+ result = REG_UNAVAILABLE;
+ }
+
+ value_free_to_mark (mark);
+
+ return result;
+ }
else
return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
regnum, buf);
}
+struct value *
+regcache_cooked_read_value (struct regcache *regcache, int regnum)
+{
+ gdb_assert (regnum >= 0);
+ gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+ if (regnum < regcache->descr->nr_raw_registers
+ || (regcache->readonly_p
+ && regcache->register_status[regnum] != REG_UNKNOWN)
+ || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+ {
+ struct value *result;
+
+ result = allocate_value (register_type (regcache->descr->gdbarch,
+ regnum));
+ VALUE_LVAL (result) = lval_register;
+ VALUE_REGNUM (result) = regnum;
+
+ /* It is more efficient in general to do this delegation in this
+ direction than in the other one, even though the value-based
+ API is preferred. */
+ if (regcache_cooked_read (regcache, regnum,
+ value_contents_raw (result)) == REG_UNAVAILABLE)
+ mark_value_bytes_unavailable (result, 0,
+ TYPE_LENGTH (value_type (result)));
+
+ return result;
+ }
+ else
+ return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+ regcache, regnum);
+}
+
enum register_status
regcache_cooked_read_signed (struct regcache *regcache, int regnum,
LONGEST *val)
enum regcache_dump_what
{
regcache_dump_none, regcache_dump_raw,
- regcache_dump_cooked, regcache_dump_groups
+ regcache_dump_cooked, regcache_dump_groups,
+ regcache_dump_remote
};
static void
}
}
+ /* Remote packet configuration. */
+ if (what_to_dump == regcache_dump_remote)
+ {
+ if (regnum < 0)
+ {
+ fprintf_unfiltered (file, "Rmt Nr g/G Offset");
+ }
+ else if (regnum < regcache->descr->nr_raw_registers)
+ {
+ int pnum, poffset;
+
+ if (remote_register_number_and_offset (get_regcache_arch (regcache), regnum,
+ &pnum, &poffset))
+ fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+ }
+ }
+
fprintf_unfiltered (file, "\n");
}
regcache_print (args, regcache_dump_groups);
}
+static void
+maintenance_print_remote_registers (char *args, int from_tty)
+{
+ regcache_print (args, regcache_dump_remote);
+}
+
extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */
void
"including each register's group.\n"
"Takes an optional file parameter."),
&maintenanceprintlist);
+ add_cmd ("remote-registers", class_maintenance,
+ maintenance_print_remote_registers, _("\
+Print the internal register configuration including each register's\n\
+remote register number and buffer offset in the g/G packets.\n\
+Takes an optional file parameter."),
+ &maintenanceprintlist);
}