aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2024-01-10 23:35:49 -0500
committerMike Frysinger <vapier@gentoo.org>2024-01-18 01:46:27 -0500
commitdcc6c863ed4e0198f9df590ea86554f550c42237 (patch)
tree12b08000dc208274976adcb0188b9ef110d70e4d
parent9be58d07909ea72b3351e71121b00b63e3e0d7e7 (diff)
downloadbinutils-dcc6c863ed4e0198f9df590ea86554f550c42237.zip
binutils-dcc6c863ed4e0198f9df590ea86554f550c42237.tar.gz
binutils-dcc6c863ed4e0198f9df590ea86554f550c42237.tar.bz2
sim: ppc: switch register read/writes to union to avoid aliasing issues
This code creates a small buffer on the stack w/alloca, then proceeds to write to it with a cast to a pointer type based on the register type, then reads from it with a cast to a pointer type based on the register size. gcc will flags only one of these lines as "maybe used uninitialized", but it seems to track back to this memory abuse. Create a large union with all the possible types that this code will read or write as, and then use those. It's a bit ugly, but is probably better than using raw memcpy's everywhere.
-rw-r--r--sim/ppc/psim.c125
1 files changed, 75 insertions, 50 deletions
diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c
index 8c1c5a0..88047af 100644
--- a/sim/ppc/psim.c
+++ b/sim/ppc/psim.c
@@ -789,7 +789,21 @@ psim_read_register(psim *system,
transfer_mode mode)
{
register_descriptions description;
- char *cooked_buf;
+ union {
+ uint8_t bytes[16];
+ unsigned_word unsigned_word;
+ unsigned_1 unsigned_1;
+ unsigned_2 unsigned_2;
+ unsigned_4 unsigned_4;
+ unsigned_8 unsigned_8;
+ creg creg;
+ fpreg fpreg;
+ fpscreg fpscreg;
+ gpreg gpreg;
+ msreg msreg;
+ spreg spreg;
+ sreg sreg;
+ } cooked_buf;
cpu *processor;
/* find our processor */
@@ -808,81 +822,80 @@ psim_read_register(psim *system,
description = register_description(reg);
if (description.type == reg_invalid)
return 0;
- cooked_buf = alloca (description.size);
/* get the cooked value */
switch (description.type) {
case reg_gpr:
- *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
+ cooked_buf.gpreg = cpu_registers(processor)->gpr[description.index];
break;
case reg_spr:
- *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
+ cooked_buf.spreg = cpu_registers(processor)->spr[description.index];
break;
case reg_sr:
- *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
+ cooked_buf.sreg = cpu_registers(processor)->sr[description.index];
break;
case reg_fpr:
- *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
+ cooked_buf.fpreg = cpu_registers(processor)->fpr[description.index];
break;
case reg_pc:
- *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
+ cooked_buf.unsigned_word = cpu_get_program_counter(processor);
break;
case reg_cr:
- *(creg*)cooked_buf = cpu_registers(processor)->cr;
+ cooked_buf.creg = cpu_registers(processor)->cr;
break;
case reg_msr:
- *(msreg*)cooked_buf = cpu_registers(processor)->msr;
+ cooked_buf.msreg = cpu_registers(processor)->msr;
break;
case reg_fpscr:
- *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
+ cooked_buf.fpscreg = cpu_registers(processor)->fpscr;
break;
case reg_insns:
- *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
+ cooked_buf.unsigned_word = mon_get_number_of_insns(system->monitor,
which_cpu);
break;
case reg_stalls:
if (cpu_model(processor) == NULL)
error("$stalls only valid if processor unit model enabled (-I)\n");
- *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
+ cooked_buf.unsigned_word = model_get_number_of_stalls(cpu_model(processor));
break;
case reg_cycles:
if (cpu_model(processor) == NULL)
error("$cycles only valid if processor unit model enabled (-I)\n");
- *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
+ cooked_buf.unsigned_word = model_get_number_of_cycles(cpu_model(processor));
break;
#ifdef WITH_ALTIVEC
case reg_vr:
- *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
+ cooked_buf.vreg = cpu_registers(processor)->altivec.vr[description.index];
break;
case reg_vscr:
- *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
+ cooked_buf.vscreg = cpu_registers(processor)->altivec.vscr;
break;
#endif
#ifdef WITH_E500
case reg_gprh:
- *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
+ cooked_buf.gpreg = cpu_registers(processor)->e500.gprh[description.index];
break;
case reg_evr:
- *(uint64_t*)cooked_buf = EVR(description.index);
+ cooked_buf.uint64_t = EVR(description.index);
break;
case reg_acc:
- *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
+ cooked_buf.accreg = cpu_registers(processor)->e500.acc;
break;
#endif
@@ -898,36 +911,36 @@ psim_read_register(psim *system,
/* FIXME - assumes that all registers are simple integers */
switch (description.size) {
case 1:
- *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
+ *(unsigned_1*)buf = H2T_1(cooked_buf.unsigned_1);
break;
case 2:
- *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
+ *(unsigned_2*)buf = H2T_2(cooked_buf.unsigned_2);
break;
case 4:
- *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
+ *(unsigned_4*)buf = H2T_4(cooked_buf.unsigned_4);
break;
case 8:
- *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
+ *(unsigned_8*)buf = H2T_8(cooked_buf.unsigned_8);
break;
#ifdef WITH_ALTIVEC
case 16:
if (HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
{
union { vreg v; unsigned_8 d[2]; } h, t;
- memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
+ memcpy(&h.v/*dest*/, cooked_buf.bytes/*src*/, description.size);
{ _SWAP_8(t.d[0] =, h.d[1]); }
{ _SWAP_8(t.d[1] =, h.d[0]); }
memcpy(buf/*dest*/, &t/*src*/, description.size);
break;
}
else
- memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
+ memcpy(buf/*dest*/, cooked_buf.bytes/*src*/, description.size);
break;
#endif
}
}
else {
- memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
+ memcpy(buf/*dest*/, cooked_buf.bytes/*src*/, description.size);
}
return description.size;
@@ -945,7 +958,21 @@ psim_write_register(psim *system,
{
cpu *processor;
register_descriptions description;
- char *cooked_buf;
+ union {
+ uint8_t bytes[16];
+ unsigned_word unsigned_word;
+ unsigned_1 unsigned_1;
+ unsigned_2 unsigned_2;
+ unsigned_4 unsigned_4;
+ unsigned_8 unsigned_8;
+ creg creg;
+ fpreg fpreg;
+ fpscreg fpscreg;
+ gpreg gpreg;
+ msreg msreg;
+ spreg spreg;
+ sreg sreg;
+ } cooked_buf;
/* find our processor */
if (which_cpu == MAX_NR_PROCESSORS) {
@@ -960,7 +987,6 @@ psim_write_register(psim *system,
description = register_description(reg);
if (description.type == reg_invalid)
return 0;
- cooked_buf = alloca (description.size);
if (which_cpu == -1) {
int i;
@@ -977,16 +1003,16 @@ psim_write_register(psim *system,
if (mode == raw_transfer) {
switch (description.size) {
case 1:
- *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
+ cooked_buf.unsigned_1 = T2H_1(*(unsigned_1*)buf);
break;
case 2:
- *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
+ cooked_buf.unsigned_2 = T2H_2(*(unsigned_2*)buf);
break;
case 4:
- *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
+ cooked_buf.unsigned_4 = T2H_4(*(unsigned_4*)buf);
break;
case 8:
- *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
+ cooked_buf.unsigned_8 = T2H_8(*(unsigned_8*)buf);
break;
#ifdef WITH_ALTIVEC
case 16:
@@ -996,86 +1022,85 @@ psim_write_register(psim *system,
memcpy(&t.v/*dest*/, buf/*src*/, description.size);
{ _SWAP_8(h.d[0] =, t.d[1]); }
{ _SWAP_8(h.d[1] =, t.d[0]); }
- memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
+ memcpy(cooked_buf.bytes/*dest*/, &h/*src*/, description.size);
break;
}
else
- memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
+ memcpy(cooked_buf.bytes/*dest*/, buf/*src*/, description.size);
#endif
}
}
else {
- memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
+ memcpy(cooked_buf.bytes/*dest*/, buf/*src*/, description.size);
}
/* put the cooked value into the register */
switch (description.type) {
case reg_gpr:
- cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
+ cpu_registers(processor)->gpr[description.index] = cooked_buf.gpreg;
break;
case reg_fpr:
- cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
+ cpu_registers(processor)->fpr[description.index] = cooked_buf.fpreg;
break;
case reg_pc:
- cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
+ cpu_set_program_counter(processor, cooked_buf.unsigned_word);
break;
case reg_spr:
- cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
+ cpu_registers(processor)->spr[description.index] = cooked_buf.spreg;
break;
case reg_sr:
- cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
+ cpu_registers(processor)->sr[description.index] = cooked_buf.sreg;
break;
case reg_cr:
- cpu_registers(processor)->cr = *(creg*)cooked_buf;
+ cpu_registers(processor)->cr = cooked_buf.creg;
break;
case reg_msr:
- cpu_registers(processor)->msr = *(msreg*)cooked_buf;
+ cpu_registers(processor)->msr = cooked_buf.msreg;
break;
case reg_fpscr:
- cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
+ cpu_registers(processor)->fpscr = cooked_buf.fpscreg;
break;
#ifdef WITH_E500
case reg_gprh:
- cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
+ cpu_registers(processor)->e500.gprh[description.index] = cooked_buf.gpreg;
break;
case reg_evr:
{
uint64_t v;
- v = *(uint64_t*)cooked_buf;
+ v = cooked_buf.uint64_t;
cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
cpu_registers(processor)->gpr[description.index] = v;
break;
}
case reg_acc:
- cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
+ cpu_registers(processor)->e500.acc = cooked_buf.accreg;
break;
#endif
#ifdef WITH_ALTIVEC
case reg_vr:
- cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
+ cpu_registers(processor)->altivec.vr[description.index] = cooked_buf.vreg;
break;
case reg_vscr:
- cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
+ cpu_registers(processor)->altivec.vscr = cooked_buf.vscreg;
break;
#endif
default:
- printf_filtered("psim_write_register(processor=%p,cooked_buf=%p,reg=%s) %s\n",
- processor, cooked_buf, reg,
- "read of this register unimplemented");
+ printf_filtered("psim_write_register(processor=%p,buf=%p,reg=%s) %s\n",
+ processor, buf, reg, "read of this register unimplemented");
return 0;
}