Unify ctf_fetch_registers and tfile_fetch_registers

Functions ctf_fetch_registers and tfile_fetch_registers have some
duplicated code about guessing the PC in regcache.  Sometimes, we
may change one function and forget to update the other one, like this
https://www.sourceware.org/ml/gdb-patches/2014-01/msg00292.html

This patch is to move the duplicated code into a new function
tracefile_fetch_registers, and let both ctf_fetch_registers and
tfile_fetch_registers call it.

gdb:

2014-04-22  Yao Qi  <yao@codesourcery.com>

	* tracefile-tfile.c (tfile_fetch_registers): Move the bottom to ...
	* tracefile.c (tracefile_fetch_registers): ... it.  New function.
	* tracefile.h (tracefile_fetch_registers): Declare.
	* ctf.c (ctf_fetch_registers): Remove the bottom.  Call
	tracefile_fetch_registers.
This commit is contained in:
Yao Qi 2014-04-18 19:32:01 +08:00
parent f159927f4d
commit 48b6e87ef2
5 changed files with 82 additions and 97 deletions

View File

@ -1,3 +1,13 @@
2014-04-22 Yao Qi <yao@codesourcery.com>
* tracefile-tfile.c (tfile_fetch_registers): Move the bottom
to ...
* tracefile.c (tracefile_fetch_registers): ... it. New
function.
* tracefile.h (tracefile_fetch_registers): Declare.
* ctf.c (ctf_fetch_registers): Remove the bottom. Call
tracefile_fetch_registers.
2014-04-19 Eli Zaretskii <eliz@gnu.org>
PR gdb/14018

View File

@ -1229,8 +1229,6 @@ ctf_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
int offset, regn, regsize, pc_regno;
gdb_byte *regs = NULL;
struct bt_ctf_event *event = NULL;
struct bt_iter_pos *pos;
@ -1270,13 +1268,14 @@ ctf_fetch_registers (struct target_ops *ops,
if (event != NULL)
{
int offset, regsize, regn;
const struct bt_definition *scope
= bt_ctf_get_top_level_scope (event,
BT_EVENT_FIELDS);
const struct bt_definition *array
= bt_ctf_get_field (event, scope, "contents");
gdb_byte *regs = (gdb_byte *) bt_ctf_get_char_array (array);
regs = (gdb_byte *) bt_ctf_get_char_array (array);
/* Assume the block is laid out in GDB register number order,
each register with the size that it has in GDB. */
offset = 0;
@ -1300,48 +1299,9 @@ ctf_fetch_registers (struct target_ops *ops,
}
offset += regsize;
}
return;
}
regs = alloca (trace_regblock_size);
/* We get here if no register data has been found. Mark registers
as unavailable. */
for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
regcache_raw_supply (regcache, regn, NULL);
/* We can often usefully guess that the PC is going to be the same
as the address of the tracepoint. */
pc_regno = gdbarch_pc_regnum (gdbarch);
if (pc_regno >= 0 && (regno == -1 || regno == pc_regno))
{
struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
if (tp != NULL && tp->base.loc)
{
/* But don't try to guess if tracepoint is multi-location... */
if (tp->base.loc->next != NULL)
{
warning (_("Tracepoint %d has multiple "
"locations, cannot infer $pc"),
tp->base.number);
return;
}
/* ... or does while-stepping. */
if (tp->step_count > 0)
{
warning (_("Tracepoint %d does while-stepping, "
"cannot infer $pc"),
tp->base.number);
return;
}
store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
gdbarch_byte_order (gdbarch),
tp->base.loc->address);
regcache_raw_supply (regcache, pc_regno, regs);
}
}
else
tracefile_fetch_registers (regcache, regno);
}
/* This is the implementation of target_ops method to_xfer_partial.

View File

@ -795,18 +795,17 @@ tfile_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
int offset, regn, regsize, pc_regno;
gdb_byte *regs;
int offset, regn, regsize;
/* An uninitialized reg size says we're not going to be
successful at getting register blocks. */
if (!trace_regblock_size)
return;
regs = alloca (trace_regblock_size);
if (traceframe_find_block_type ('R', 0) >= 0)
{
gdb_byte *regs = alloca (trace_regblock_size);
tfile_read (regs, trace_regblock_size);
/* Assume the block is laid out in GDB register number order,
@ -832,56 +831,9 @@ tfile_fetch_registers (struct target_ops *ops,
}
offset += regsize;
}
return;
}
/* We get here if no register data has been found. Mark registers
as unavailable. */
for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
regcache_raw_supply (regcache, regn, NULL);
/* We can often usefully guess that the PC is going to be the same
as the address of the tracepoint. */
pc_regno = gdbarch_pc_regnum (gdbarch);
/* XXX This guessing code below only works if the PC register isn't
a pseudo-register. The value of a pseudo-register isn't stored
in the (non-readonly) regcache -- instead it's recomputed
(probably from some other cached raw register) whenever the
register is read. This guesswork should probably move to some
higher layer. */
if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
return;
if (regno == -1 || regno == pc_regno)
{
struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
if (tp && tp->base.loc)
{
/* But don't try to guess if tracepoint is multi-location... */
if (tp->base.loc->next)
{
warning (_("Tracepoint %d has multiple "
"locations, cannot infer $pc"),
tp->base.number);
return;
}
/* ... or does while-stepping. */
if (tp->step_count > 0)
{
warning (_("Tracepoint %d does while-stepping, "
"cannot infer $pc"),
tp->base.number);
return;
}
store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
gdbarch_byte_order (gdbarch),
tp->base.loc->address);
regcache_raw_supply (regcache, pc_regno, regs);
}
}
else
tracefile_fetch_registers (regcache, regno);
}
static enum target_xfer_status

View File

@ -21,6 +21,7 @@
#include "tracefile.h"
#include "ctf.h"
#include "exec.h"
#include "regcache.h"
/* Helper macros. */
@ -377,6 +378,66 @@ trace_save_ctf (const char *dirname, int target_does_save)
do_cleanups (back_to);
}
/* Fetch register data from tracefile, shared for both tfile and
ctf. */
void
tracefile_fetch_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
int regn, pc_regno;
/* We get here if no register data has been found. Mark registers
as unavailable. */
for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
regcache_raw_supply (regcache, regn, NULL);
/* We can often usefully guess that the PC is going to be the same
as the address of the tracepoint. */
pc_regno = gdbarch_pc_regnum (gdbarch);
/* XXX This guessing code below only works if the PC register isn't
a pseudo-register. The value of a pseudo-register isn't stored
in the (non-readonly) regcache -- instead it's recomputed
(probably from some other cached raw register) whenever the
register is read. This guesswork should probably move to some
higher layer. */
if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
return;
if (regno == -1 || regno == pc_regno)
{
struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
gdb_byte *regs;
if (tp && tp->base.loc)
{
/* But don't try to guess if tracepoint is multi-location... */
if (tp->base.loc->next)
{
warning (_("Tracepoint %d has multiple "
"locations, cannot infer $pc"),
tp->base.number);
return;
}
/* ... or does while-stepping. */
if (tp->step_count > 0)
{
warning (_("Tracepoint %d does while-stepping, "
"cannot infer $pc"),
tp->base.number);
return;
}
regs = alloca (register_size (gdbarch, pc_regno));
store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
gdbarch_byte_order (gdbarch),
tp->base.loc->address);
regcache_raw_supply (regcache, pc_regno, regs);
}
}
}
/* This is the implementation of target_ops method to_has_all_memory. */
static int

View File

@ -113,4 +113,6 @@ extern struct trace_file_writer *tfile_trace_file_writer_new (void);
extern void init_tracefile_ops (struct target_ops *ops);
extern void tracefile_fetch_registers (struct regcache *regcache, int regno);
#endif /* TRACEFILE_H */