NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
49.09k stars 5.65k forks source link

Poor VFP11 (ARMneon?) support for 32bit arm (thumb2) #6573

Open tihmstar opened 1 month ago

tihmstar commented 1 month ago

Describe the bug In the following file https://github.com/NationalSecurityAgency/ghidra/blob/7381dd3bd0ffb5949f1fbc685b527b5c0965ce10/Ghidra/Processors/ARM/data/languages/ARMneon.sinc Only FPSCR seems to be handled, but not the other floating point registers. Looking at https://developer.arm.com/documentation/ddi0274/h (DDI0274H_vfp11_r1p5_trm.pdf) For example at 2.4 Loading operands from ARM1136JF-S registers i can see mentioning of several other registers which are not mentioned anywhere in ARMneon.sinc likeFPSID, (FPSCR), FPEXC, FPINST, or FPINST2. Ghidra only seems to care about FPSCR but ignore everything else.

This causes the following (incorrect) disassembly:

4f f0 80 40     mov.w      r0,#0x40000000
e8 ee 10 0a     mcr        p10,0x7,r0,cr8,cr0,0x0
4f f0 00 00     mov.w      r0,#0x0
e1 ee 10 0a     vmsr       fpscr,r0

Hopper disassembles this to

mov.w      r0, #0x40000000
vmsr       fpexc, r0
mov.w      r0, #0x0
vmsr       fpscr, r0

You can see that fpexc isn't handled correctly in ghidra (nor are any other registers except for fpscr).

Furthermore, when decompiling the following segment:

bf f3 6f 8f     isb        #0xf
4f f0 80 40     mov.w      r0,#0x40000000
e8 ee 10 0a     mcr        p10,0x7,r0,cr8,cr0,0x0
4f f0 00 00     mov.w      r0,#0x0
e1 ee 10 0a     vmsr       fpscr,r0
40 f6 00 22     movw       r2,#0xa00
c3 f6 60 52     movt       r2,#0x3d60
42 f8 04 8b     str.w      r8,[r2],#0x4=>DAT_3d600a00
c2 f8 00 90     str.w      r9,[r2,#0x0]=>DAT_3d600a04
00 f0 19 f8     bl         set_registers_to_0xdeadbeef                      void set_registers_to_0xdeadbeef

we get

  InstructionSynchronizationBarrier(0xf);
  coprocessor_moveto(10,7,0,0x40000000,in_cr8,in_cr0);
  set_registers_to_0xdeadbeef();

In the disassembly mov.w r0,#0x40000000; vmsr fpexc, r0 is displayed as coprocessor_moveto(10,7,0,0x40000000,in_cr8,in_cr0); which is because the instruction doesn't seem to be implemented. But mov.w r0,#0x0;vmsr fpscr,r0; is skipped entirely in the disassembly view!

To Reproduce Disassemble and decompile the bytes:

bf f3 6f 8f 
4f f0 80 40 
e8 ee 10 0a  
4f f0 00 00  
e1 ee 10 0a 

Expected behavior In the disassembly view the floating point instructions should be displayed correctly (like in hopper disassembler).

mov.w      r0, #0x40000000
vmsr       fpexc, r0
mov.w      r0, #0x0
vmsr       fpscr, r0

In the decompilation view the moves to the registers should be visible somehow. For example something like:

coproc_moveto_FPEXC(0x40000000);
coproc_moveto_FPSCR(0);

Environment (please complete the following information):