Open NeedsMoreFlux opened 5 years ago
Debugging the issue it appears that the context register for the re-parse of the instruction in the delayslot is not consistent with the initial parse. One subsequent parses, the context for the pcode of the second instruction is the context of the instruction containing the delay slot.
The correct address is generated by adding the following along with your changes to set the ext_delay on the delay_slot instruction:
:jalx Abs26_m16 is ISA_MODE=1 & RELP=1 & ext_isjal=1 & ext_tgt_x=1 & Abs26_m16
[ext_delay=0b10; ISA_MODE = 0; globalset(Abs26_m16, ISA_MODE); globalset(inst_next, ext_delay); globalset(inst_start,ext_delay);] {
However, this is not the correct fix. We'll take a look at the context parsing for pcode in the delay slot. It is possible this was changed recently.
Bump
Also affects MIPS:LE:32:default Affected instructions: J, JAL
Describe the bug When disassembling/decompiling a PC-relative LW instruction that is preceded by a JAL, JALX, or JR instruction in MIPS16e mode, the address that Ghidra computes for the LW instruction is incorrect. Specifically, Ghidra uses the address of the LW as the value for PC instead of the address of the preceding jump instruction when forming the load address.
To Reproduce
0x0
as MIPS16e instructions by pressing F12. For reference, my listing displays the following:0x4
generates a reference to the data at address0xc
(DAT_0000000c
) instead of address0x8
. The decompiler window also shows the same erroneous reference toDAT_0000000c
.Expected behavior From the operation section of Load Word (PC-Relative) on page 104 of the MIPS16e Application Specific Extension to the MIPS32 Architecture, the
base_pc
value used to compute the load address should be that of the preceding instruction if the LW is in a jump delay slot. For the sample program,base_pc
for the LW instruction should be0x0
, so the operand0x8(pc)
should refer to address0x8
instead.Environment (please complete the following information):
Additional context Part of the problem seems to be in the mips16.sinc SLEIGH file. I found that although the constructor for JAL sets
ext_delay
to0b10
here, the constructors for JALR, JALX, and JR do not (although they still callglobalset(inst_next, ext_delay)
). By adding the appropriate assignments toext_delay
for these constructors (0b10
for JALX and0b01
for JALR and JR), I was able to partially fix this bug, in that the decompilation would sometimes reference the correct address. However, I noticed that when clearing and redefining instructions containing the JALX/LW sequence, the listing display would sometimes update the reference for the LW instruction back to the incorrect address, and this new reference would then propagate to the decompiler somehow. For example, after making theext_delay
additions to mips16.sinc, if I load the test program from above and clear the JALX/LW instructions so that the listing looks likethen the decompilation window shows
with the correct address of
0x8
being passed toFUN_00000010
. But if I then disassemble the JALX/LW bytes again, the listing displayswith the incorrect reference to address
0xc
and the decompilation window showsI haven't figured out why this happens or any way to stop the incorrect reference from being generated other than by clearing the JALX/LW instruction bytes.
Since this bug seems to involve some instructions not setting
ext_delay
correctly, it's plausible that other instructions that rely on the value ofext_delay
might also have buggy behavior when they are preceded by a JALR, JALX, or JR instruction.