GDBServer handles register reads/writes a bit differently compared to GDB.
Since C register writes are only allowed with cheri.ptrace_forge_cap=1,
GDBServer will keep issuing warnings if such setting is 0.
This patch improves it by issuing a single more helpful warning to the
user. If cheri.ptrace_forge_cap is flipped, the warning will be issued
again appropriately to remind the user about it.
Bug-ID: https://git.morello-project.org/morello/binutils-gdb/-/issues/5
/* FIXME-Morello: Fixup the register set size. */
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_MORELLO,
0, OPTIONAL_REGS,
- aarch64_fill_cregset, aarch64_store_cregset },
+ aarch64_fill_cregset, aarch64_store_cregset, nullptr,
+ "cheri.ptrace_forge_cap"
+ },
NULL_REGSET
};
break;
case NT_ARM_MORELLO:
if (features.capability)
- regset->size = AARCH64_LINUX_CREGS_SIZE;
+ {
+ regset->size = AARCH64_LINUX_CREGS_SIZE;
+ regset->sysctl_write_should_warn = true;
+ }
break;
default:
gdb_assert_not_reached ("Unknown register set found.");
free (buf);
return 0;
}
+ else if (errno == EPERM && regset->sysctl_write_permission != nullptr)
+ {
+ if (regset->sysctl_write_should_warn)
+ {
+ warning ("Unable to store registers.\n"
+ "Please run \"sysctl %s=1\".",
+ regset->sysctl_write_permission);
+ regset->sysctl_write_should_warn = false;
+ }
+ }
else
{
perror ("Warning: ptrace(regsets_store_inferior_registers)");
}
else if (regset->type == GENERAL_REGS)
saw_general_regs = 1;
+ else
+ {
+ /* We've succeeded in writing the registers. If this register set
+ has a sysctl permission flag and the warnings are disabled,
+ re-enable it so we can issue a warning next time the write
+ attempt fails. */
+ if (regset->sysctl_write_permission != nullptr
+ && !regset->sysctl_write_should_warn)
+ regset->sysctl_write_should_warn = true;
+ }
+
free (buf);
}
if (saw_general_regs)
/* The arch's regsets array initializer must be terminated with a NULL
regset. */
#define NULL_REGSET \
- { 0, 0, 0, -1, (enum regset_type) -1, NULL, NULL }
+ { 0, 0, 0, -1, (enum regset_type) -1, nullptr, nullptr, nullptr, nullptr }
struct regset_info
{
enum regset_type type;
regset_fill_func fill_function;
regset_store_func store_function;
+ /* The name of the sysctl flag that controls read/write permission for this
+ particular register set. If it is nullptr, it means there is no such
+ switch. */
+ const char *sysctl_read_permission = nullptr;
+ const char *sysctl_write_permission = nullptr;
+ bool sysctl_read_should_warn = true;
+ bool sysctl_write_should_warn = true;
};
/* Aggregation of all the supported regsets of a given