CRASH, x86-64 cleancall save_fpstate causes incorrect passing of register operands
Created by: nextsilicon-itay-bookstein
Passing save_fpstate = true
to dr_insert_clean_call
(or, alternatively, DR_CLEANCALL_SAVE_FLOAT
to dr_insert_clean_call_ex
) causes incorrect passing of register operands to the clean-call.
With save_fpstate = false
:
+121 m4 @0x00007fbc087e71b8 48 8d a4 24 f8 f6 ff lea 0xfffff6f8(%rsp) -> %rsp
ff
+129 m4 @0x00007fbc087e3908 e8 5b 14 06 80 call $0x00007fbc8872dd00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+134 m4 @0x00007fbc087e5e18 <label>
+134 m4 @0x00007fbc087e2de0 48 8b 74 24 30 mov 0x30(%rsp)[8byte] -> %rsi
+139 m4 @0x00007fbc087e3c70 48 bf 37 64 68 cc bc mov $0x00007fbccc686437 -> %rdi
7f 00 00
+149 m4 @0x00007fbc087e5a18 e8 bb 62 fb 7f call $0x00007fbc88682b60 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+154 m4 @0x00007fbc086d5aa8 e8 5b 15 06 80 call $0x00007fbc8872de00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
With save_fpstate = true
:
+121 m4 @0x00007fdaeb5571b8 48 8d a4 24 f8 f6 ff lea 0xfffff6f8(%rsp) -> %rsp
ff
+129 m4 @0x00007fdaeb553908 e8 5b 14 06 80 call $0x00007fdb6b49dd00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+134 m4 @0x00007fdaeb555e18 48 8d a4 24 00 fe ff lea 0xfffffe00(%rsp) -> %rsp
ff
+142 m4 @0x00007fdaeb553c70 48 0f ae 04 24 fxsave64 -> (%rsp)[512byte]
+147 m4 @0x00007fdaeb552de0 db e2 fnclex
+149 m4 @0x00007fdaeb555a18 9b fwait
+150 m4 @0x00007fdaeb445aa8 db e3 fninit
+152 m4 @0x00007fdaeb5554d8 <label>
+152 m4 @0x00007fdaeb557308 48 8b 74 24 30 mov 0x30(%rsp)[8byte] -> %rsi
+157 m4 @0x00007fdaeb4408b8 48 bf 37 64 3f af db mov $0x00007fdbaf3f6437 -> %rdi
7f 00 00
+167 m4 @0x00007fdaeb5584c0 e8 bb 62 fb 7f call $0x00007fdb6b3f2b60 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+172 m4 @0x00007fdaeb443b28 48 0f ae 0c 24 fxrstor64 (%rsp)[512byte]
+177 m4 @0x00007fdaeb555b98 48 8d a4 24 00 02 00 lea 0x00000200(%rsp) -> %rsp
00
+185 m4 @0x00007fdaeb556738 e8 5b 15 06 80 call $0x00007fdb6b49de00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
This is a two-parameter clean-call where the first parameter is an immediate and the second parameter is a register operand. You'll see that in both cases the second parameter is loaded from 0x30(%rsp)[8byte]
, but in the save_fpstate = true
case this offset becomes incorrect due to the adjustment of the stack for the fxsave64 spill.
To Reproduce Steps to reproduce the behavior:
- Use
dr_insert_clean_call
withsave_fpstate = true
and anopnd_t
which specifies a register operand.
Please also answer these questions:
- What happens when you run without any client? AFAICT, this is a bug in the implementation of a client API
- What happens when you run with debug build ("-debug" flag to drrun/drconfig/drinject)? Reproduces
Versions
- What version of DynamoRIO are you using? Fairly recent master
- What operating system version are you running on? Ubuntu 20.04.1 LTS
- Is your application 32-bit or 64-bit? 64-bit