mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
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.
This commit is contained in:
125
sim/ppc/psim.c
125
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user