diff options
author | Mike Frysinger <vapier@gentoo.org> | 2024-01-10 23:35:49 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2024-01-18 01:46:27 -0500 |
commit | dcc6c863ed4e0198f9df590ea86554f550c42237 (patch) | |
tree | 12b08000dc208274976adcb0188b9ef110d70e4d /sim | |
parent | 9be58d07909ea72b3351e71121b00b63e3e0d7e7 (diff) | |
download | fsf-binutils-gdb-dcc6c863ed4e0198f9df590ea86554f550c42237.zip fsf-binutils-gdb-dcc6c863ed4e0198f9df590ea86554f550c42237.tar.gz fsf-binutils-gdb-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.
Diffstat (limited to 'sim')
-rw-r--r-- | sim/ppc/psim.c | 125 |
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; } |