450 lines
16 KiB
Diff
450 lines
16 KiB
Diff
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
|
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
Date: Thu, 9 Aug 2018 17:17:16 +0200
|
|
Subject: gdb-rhbz1187581-power8-regs-4of7.patch
|
|
|
|
;; Add GDB support to access/display POWER8 registers (IBM, RH BZ 1187581).
|
|
|
|
commit 4277c4b87addb5354cc47b98d7a73e44cfaf22c2
|
|
Author: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
|
|
Date: Mon Aug 6 16:24:55 2018 -0300
|
|
|
|
Use remote register numbers in tracepoint mask
|
|
|
|
Currently, tracepoint register masks in the QTDP packets include both
|
|
internal and remote register numbers, as well as pseudo-register
|
|
numbers.
|
|
|
|
This patch changes this so that the mask only includes remote register
|
|
numbers.
|
|
|
|
Register numbers from agent expressions are already set in the mask
|
|
using remote numbers. Other tracepoint actions used internal numbers,
|
|
e.g. "collect $regs" or "collect $<pseudoreg>". To handle pseudoreg
|
|
numbers, an empty agent expression is created and ax_reg_mask is
|
|
called for this expression and the pseudoreg. This will cause the ax
|
|
to set its mask with the corresponding remote raw register
|
|
numbers (using ax_regs_mask, which calls
|
|
gdbarch_ax_pseudo_register_collect).
|
|
|
|
If ax_regs_mask and gdbarch_ax_pseudo_register_collect also generate
|
|
more ax bytecode, the ax is also appended to the collection list. It
|
|
isn't clear that this was the original intent for
|
|
gdbarch_ax_pseudo_register_collect, and none of the arches seem to do
|
|
this, but if this changes in the future, it should work.
|
|
|
|
The patch also refactors the code used by validate_action line to
|
|
validate axs into a function that is now called from every place that
|
|
generates axs. Previously, some parts of tracepoint.c that generated
|
|
axs didn't check if the ax length was greater than MAX_AGENT_EXPR_LEN.
|
|
|
|
gdb/ChangeLog:
|
|
2018-08-06 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
|
|
|
|
* tracepoint.h (class collection_list) <add_register>: Remove.
|
|
<add_remote_register, add_ax_registers, add_local_register>:
|
|
Declare.
|
|
<add_memrange>: Add scope parameter.
|
|
* tracepoint.c (encode_actions_1): Likewise.
|
|
(collection_list::add_register): Rename to ...
|
|
(collection_list::add_remote_register): ... this. Update
|
|
comment.
|
|
(collection_list::add_ax_registers, add_local_register): New
|
|
methods.
|
|
(collection_list::add_memrange): Add scope parameter. Call
|
|
add_local_register instead of add_register.
|
|
(finalize_tracepoint_aexpr): New function.
|
|
(collection_list::collect_symbol): Update calls to add_memrange.
|
|
Call add_local_register instead of add_register. Call
|
|
add_ax_registers. Call finalize_tracepoint_aexpr.
|
|
(encode_actions_1): Get remote regnos for $reg action. Call
|
|
add_remote_register, add_ax_registers, and add_local_register.
|
|
Update call to add_memrange. Call finalize_tracepoint_aexpr.
|
|
(validate_actionline): Call finalize_tracepoint_aexpr.
|
|
|
|
+2018-08-06 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
|
|
+
|
|
+ * tracepoint.h (class collection_list) <add_register>: Remove.
|
|
+ <add_remote_register, add_ax_registers, add_local_register>:
|
|
+ Declare.
|
|
+ <add_memrange>: Add scope parameter.
|
|
+ * tracepoint.c (encode_actions_1): Likewise.
|
|
+ (collection_list::add_register): Rename to ...
|
|
+ (collection_list::add_remote_register): ... this. Update
|
|
+ comment.
|
|
+ (collection_list::add_ax_registers, add_local_register): New
|
|
+ methods.
|
|
+ (collection_list::add_memrange): Add scope parameter. Call
|
|
+ add_local_register instead of add_register.
|
|
+ (finalize_tracepoint_aexpr): New function.
|
|
+ (collection_list::collect_symbol): Update calls to add_memrange.
|
|
+ Call add_local_register instead of add_register. Call
|
|
+ add_ax_registers. Call finalize_tracepoint_aexpr.
|
|
+ (encode_actions_1): Get remote regnos for $reg action. Call
|
|
+ add_remote_register, add_ax_registers, and add_local_register.
|
|
+ Update call to add_memrange. Call finalize_tracepoint_aexpr.
|
|
+ (validate_actionline): Call finalize_tracepoint_aexpr.
|
|
+
|
|
2018-08-06 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
|
|
|
|
* remote.c (remote_target::download_tracepoint): Remove BUF_SIZE.
|
|
|
|
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
|
|
--- a/gdb/tracepoint.c
|
|
+++ b/gdb/tracepoint.c
|
|
@@ -615,6 +615,19 @@ report_agent_reqs_errors (struct agent_expr *aexpr)
|
|
error (_("Expression is too complicated."));
|
|
}
|
|
|
|
+/* Call ax_reqs on AEXPR and raise an error if something is wrong. */
|
|
+
|
|
+static void
|
|
+finalize_tracepoint_aexpr (struct agent_expr *aexpr)
|
|
+{
|
|
+ ax_reqs (aexpr);
|
|
+
|
|
+ if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
|
+ error (_("Expression is too complicated."));
|
|
+
|
|
+ report_agent_reqs_errors (aexpr);
|
|
+}
|
|
+
|
|
/* worker function */
|
|
void
|
|
validate_actionline (const char *line, struct breakpoint *b)
|
|
@@ -699,12 +712,7 @@ validate_actionline (const char *line, struct breakpoint *b)
|
|
exp.get (),
|
|
trace_string);
|
|
|
|
- if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
|
- error (_("Expression is too complicated."));
|
|
-
|
|
- ax_reqs (aexpr.get ());
|
|
-
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
}
|
|
}
|
|
while (p && *p++ == ',');
|
|
@@ -731,11 +739,7 @@ validate_actionline (const char *line, struct breakpoint *b)
|
|
long. */
|
|
agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ());
|
|
|
|
- if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
|
- error (_("Expression is too complicated."));
|
|
-
|
|
- ax_reqs (aexpr.get ());
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
}
|
|
}
|
|
while (p && *p++ == ',');
|
|
@@ -811,10 +815,10 @@ memrange_sortmerge (std::vector<memrange> &memranges)
|
|
}
|
|
}
|
|
|
|
-/* Add a register to a collection list. */
|
|
+/* Add remote register number REGNO to the collection list mask. */
|
|
|
|
void
|
|
-collection_list::add_register (unsigned int regno)
|
|
+collection_list::add_remote_register (unsigned int regno)
|
|
{
|
|
if (info_verbose)
|
|
printf_filtered ("collect register %d\n", regno);
|
|
@@ -824,12 +828,74 @@ collection_list::add_register (unsigned int regno)
|
|
m_regs_mask[regno / 8] |= 1 << (regno % 8);
|
|
}
|
|
|
|
+/* Add all the registers from the mask in AEXPR to the mask in the
|
|
+ collection list. Registers in the AEXPR mask are already remote
|
|
+ register numbers. */
|
|
+
|
|
+void
|
|
+collection_list::add_ax_registers (struct agent_expr *aexpr)
|
|
+{
|
|
+ if (aexpr->reg_mask_len > 0)
|
|
+ {
|
|
+ for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
|
+ {
|
|
+ QUIT; /* Allow user to bail out with ^C. */
|
|
+ if (aexpr->reg_mask[ndx1] != 0)
|
|
+ {
|
|
+ /* Assume chars have 8 bits. */
|
|
+ for (int ndx2 = 0; ndx2 < 8; ndx2++)
|
|
+ if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
|
+ /* It's used -- record it. */
|
|
+ add_remote_register (ndx1 * 8 + ndx2);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* If REGNO is raw, add its corresponding remote register number to
|
|
+ the mask. If REGNO is a pseudo-register, figure out the necessary
|
|
+ registers using a temporary agent expression, and add it to the
|
|
+ list if it needs more than just a mask. */
|
|
+
|
|
+void
|
|
+collection_list::add_local_register (struct gdbarch *gdbarch,
|
|
+ unsigned int regno,
|
|
+ CORE_ADDR scope)
|
|
+{
|
|
+ if (regno < gdbarch_num_regs (gdbarch))
|
|
+ {
|
|
+ int remote_regno = gdbarch_remote_register_number (gdbarch, regno);
|
|
+
|
|
+ if (remote_regno < 0)
|
|
+ error (_("Can't collect register %d"), regno);
|
|
+
|
|
+ add_remote_register (remote_regno);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ agent_expr_up aexpr (new agent_expr (gdbarch, scope));
|
|
+
|
|
+ ax_reg_mask (aexpr.get (), regno);
|
|
+
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
+
|
|
+ add_ax_registers (aexpr.get ());
|
|
+
|
|
+ /* Usually ax_reg_mask for a pseudo-regiser only sets the
|
|
+ corresponding raw registers in the ax mask, but if this isn't
|
|
+ the case add the expression that is generated to the
|
|
+ collection list. */
|
|
+ if (aexpr->len > 0)
|
|
+ add_aexpr (std::move (aexpr));
|
|
+ }
|
|
+}
|
|
+
|
|
/* Add a memrange to a collection list. */
|
|
|
|
void
|
|
collection_list::add_memrange (struct gdbarch *gdbarch,
|
|
int type, bfd_signed_vma base,
|
|
- ULONGEST len)
|
|
+ ULONGEST len, CORE_ADDR scope)
|
|
{
|
|
if (info_verbose)
|
|
printf_filtered ("(%d,%s,%s)\n", type, paddress (gdbarch, base), pulongest (len));
|
|
@@ -840,7 +906,7 @@ collection_list::add_memrange (struct gdbarch *gdbarch,
|
|
m_memranges.emplace_back (type, base, base + len);
|
|
|
|
if (type != memrange_absolute) /* Better collect the base register! */
|
|
- add_register (type);
|
|
+ add_local_register (gdbarch, type, scope);
|
|
}
|
|
|
|
/* Add a symbol to a collection list. */
|
|
@@ -882,19 +948,19 @@ collection_list::collect_symbol (struct symbol *sym,
|
|
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
|
|
treat_as_expr = 1;
|
|
else
|
|
- add_memrange (gdbarch, memrange_absolute, offset, len);
|
|
+ add_memrange (gdbarch, memrange_absolute, offset, len, scope);
|
|
break;
|
|
case LOC_REGISTER:
|
|
reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
|
|
if (info_verbose)
|
|
printf_filtered ("LOC_REG[parm] %s: ",
|
|
SYMBOL_PRINT_NAME (sym));
|
|
- add_register (reg);
|
|
+ add_local_register (gdbarch, reg, scope);
|
|
/* Check for doubles stored in two registers. */
|
|
/* FIXME: how about larger types stored in 3 or more regs? */
|
|
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
|
|
len > register_size (gdbarch, reg))
|
|
- add_register (reg + 1);
|
|
+ add_local_register (gdbarch, reg + 1, scope);
|
|
break;
|
|
case LOC_REF_ARG:
|
|
printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
|
|
@@ -911,7 +977,7 @@ collection_list::collect_symbol (struct symbol *sym,
|
|
SYMBOL_PRINT_NAME (sym), pulongest (len),
|
|
paddress (gdbarch, offset), reg);
|
|
}
|
|
- add_memrange (gdbarch, reg, offset, len);
|
|
+ add_memrange (gdbarch, reg, offset, len, scope);
|
|
break;
|
|
case LOC_REGPARM_ADDR:
|
|
reg = SYMBOL_VALUE (sym);
|
|
@@ -923,7 +989,7 @@ collection_list::collect_symbol (struct symbol *sym,
|
|
SYMBOL_PRINT_NAME (sym), pulongest (len),
|
|
paddress (gdbarch, offset), reg);
|
|
}
|
|
- add_memrange (gdbarch, reg, offset, len);
|
|
+ add_memrange (gdbarch, reg, offset, len, scope);
|
|
break;
|
|
case LOC_LOCAL:
|
|
reg = frame_regno;
|
|
@@ -935,7 +1001,7 @@ collection_list::collect_symbol (struct symbol *sym,
|
|
SYMBOL_PRINT_NAME (sym), pulongest (len),
|
|
paddress (gdbarch, offset), reg);
|
|
}
|
|
- add_memrange (gdbarch, reg, offset, len);
|
|
+ add_memrange (gdbarch, reg, offset, len, scope);
|
|
break;
|
|
|
|
case LOC_UNRESOLVED:
|
|
@@ -968,26 +1034,10 @@ collection_list::collect_symbol (struct symbol *sym,
|
|
return;
|
|
}
|
|
|
|
- ax_reqs (aexpr.get ());
|
|
-
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
|
|
/* Take care of the registers. */
|
|
- if (aexpr->reg_mask_len > 0)
|
|
- {
|
|
- for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
|
- {
|
|
- QUIT; /* Allow user to bail out with ^C. */
|
|
- if (aexpr->reg_mask[ndx1] != 0)
|
|
- {
|
|
- /* Assume chars have 8 bits. */
|
|
- for (int ndx2 = 0; ndx2 < 8; ndx2++)
|
|
- if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
|
- /* It's used -- record it. */
|
|
- add_register (ndx1 * 8 + ndx2);
|
|
- }
|
|
- }
|
|
- }
|
|
+ add_ax_registers (aexpr.get ());
|
|
|
|
add_aexpr (std::move (aexpr));
|
|
}
|
|
@@ -1257,8 +1307,18 @@ encode_actions_1 (struct command_line *action,
|
|
|
|
if (0 == strncasecmp ("$reg", action_exp, 4))
|
|
{
|
|
- for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
|
|
- collect->add_register (i);
|
|
+ for (i = 0; i < gdbarch_num_regs (target_gdbarch ());
|
|
+ i++)
|
|
+ {
|
|
+ int remote_regno = (gdbarch_remote_register_number
|
|
+ (target_gdbarch (), i));
|
|
+
|
|
+ /* Ignore arch regnos without a corresponding
|
|
+ remote regno. This can happen for regnos not
|
|
+ in the tdesc. */
|
|
+ if (remote_regno >= 0)
|
|
+ collect->add_remote_register (remote_regno);
|
|
+ }
|
|
action_exp = strchr (action_exp, ','); /* more? */
|
|
}
|
|
else if (0 == strncasecmp ("$arg", action_exp, 4))
|
|
@@ -1288,27 +1348,10 @@ encode_actions_1 (struct command_line *action,
|
|
target_gdbarch (),
|
|
trace_string);
|
|
|
|
- ax_reqs (aexpr.get ());
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
|
|
/* take care of the registers */
|
|
- if (aexpr->reg_mask_len > 0)
|
|
- {
|
|
- for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
|
- {
|
|
- QUIT; /* allow user to bail out with ^C */
|
|
- if (aexpr->reg_mask[ndx1] != 0)
|
|
- {
|
|
- /* assume chars have 8 bits */
|
|
- for (int ndx2 = 0; ndx2 < 8; ndx2++)
|
|
- if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
|
- {
|
|
- /* It's used -- record it. */
|
|
- collect->add_register (ndx1 * 8 + ndx2);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
+ collect->add_ax_registers (aexpr.get ());
|
|
|
|
collect->add_aexpr (std::move (aexpr));
|
|
action_exp = strchr (action_exp, ','); /* more? */
|
|
@@ -1340,7 +1383,8 @@ encode_actions_1 (struct command_line *action,
|
|
name);
|
|
if (info_verbose)
|
|
printf_filtered ("OP_REGISTER: ");
|
|
- collect->add_register (i);
|
|
+ collect->add_local_register (target_gdbarch (),
|
|
+ i, tloc->address);
|
|
break;
|
|
}
|
|
|
|
@@ -1352,7 +1396,8 @@ encode_actions_1 (struct command_line *action,
|
|
check_typedef (exp->elts[1].type);
|
|
collect->add_memrange (target_gdbarch (),
|
|
memrange_absolute, addr,
|
|
- TYPE_LENGTH (exp->elts[1].type));
|
|
+ TYPE_LENGTH (exp->elts[1].type),
|
|
+ tloc->address);
|
|
collect->append_exp (exp.get ());
|
|
break;
|
|
|
|
@@ -1376,28 +1421,10 @@ encode_actions_1 (struct command_line *action,
|
|
exp.get (),
|
|
trace_string);
|
|
|
|
- ax_reqs (aexpr.get ());
|
|
-
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
|
|
/* Take care of the registers. */
|
|
- if (aexpr->reg_mask_len > 0)
|
|
- {
|
|
- for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
|
- {
|
|
- QUIT; /* Allow user to bail out with ^C. */
|
|
- if (aexpr->reg_mask[ndx1] != 0)
|
|
- {
|
|
- /* Assume chars have 8 bits. */
|
|
- for (int ndx2 = 0; ndx2 < 8; ndx2++)
|
|
- if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
|
- {
|
|
- /* It's used -- record it. */
|
|
- collect->add_register (ndx1 * 8 + ndx2);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
+ collect->add_ax_registers (aexpr.get ());
|
|
|
|
collect->add_aexpr (std::move (aexpr));
|
|
collect->append_exp (exp.get ());
|
|
@@ -1422,8 +1449,7 @@ encode_actions_1 (struct command_line *action,
|
|
agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
|
|
exp.get ());
|
|
|
|
- ax_reqs (aexpr.get ());
|
|
- report_agent_reqs_errors (aexpr.get ());
|
|
+ finalize_tracepoint_aexpr (aexpr.get ());
|
|
|
|
/* Even though we're not officially collecting, add
|
|
to the collect list anyway. */
|
|
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
|
|
--- a/gdb/tracepoint.h
|
|
+++ b/gdb/tracepoint.h
|
|
@@ -263,9 +263,14 @@ public:
|
|
void add_aexpr (agent_expr_up aexpr);
|
|
|
|
void add_register (unsigned int regno);
|
|
+ void add_remote_register (unsigned int regno);
|
|
+ void add_ax_registers (struct agent_expr *aexpr);
|
|
+ void add_local_register (struct gdbarch *gdbarch,
|
|
+ unsigned int regno,
|
|
+ CORE_ADDR scope);
|
|
void add_memrange (struct gdbarch *gdbarch,
|
|
int type, bfd_signed_vma base,
|
|
- ULONGEST len);
|
|
+ ULONGEST len, CORE_ADDR scope);
|
|
void collect_symbol (struct symbol *sym,
|
|
struct gdbarch *gdbarch,
|
|
long frame_regno, long frame_offset,
|