So I'm trying to fix an issue with this instruction:
ldm (%sp)[40byte] -> %r4 %r5 %r6 %r7 %r8 %r9 %r10 %r11 %sp %pc
Assuming the comment above ASSERT_NOT_IMPLEMENTED
/* FIXME i#1551: NYI on case like "ldm r10, {r10, pc}": if base reg
* is clobbered, "ldr pc [base, disp]" will use wrong base value.
* It seems the only solution is load the target value first and store
* it into some TLS slot for later "ldr pc".
*/
we have to store value from base+pc_reg_offset to TLS and then restore it back to PC at the end of BB.
The problem is that I'm not sure we can restore it using dr_insert_read_tls_field. It doesn't work as excepted, restoring only random trash to pc.
Here is a fragment from log file:
exit_branch_type=0x6 bb->exit_target=0x4ecfc180
bb ilist before mangling:
TAG 0xb6f65438
+0 L3 @0x4ed4538c e51b2034 ldr -0x34(%r11)[4byte] -> %r2
+4 L3 @0x4ed44d24 e3a03000 mov $0x00000000 -> %r3
+8 L3 @0x4ed454c0 e590c000 ldr (%r0)[4byte] -> %r12
+12 L3 @0x4ed451b8 e5802004 str %r2 -> +0x04(%r0)[4byte]
+16 L3 @0x4ed452ec e08c1001 add %r12 %r1 $0x00 -> %r1
+20 L3 @0x4ed43cb8 e5801000 str %r1 -> (%r0)[4byte]
+24 L3 @0x4ed44a48 e1a00003 mov %r3 -> %r0
+28 L3 @0x4ed43b78 e24bd028 sub %r11 $0x00000028 -> %sp
+32 L3 @0x4ed45510 e89daff0 ldm (%sp)[40byte] -> %r4 %r5 %r6 %r7 %r8 %r9 %r10 %r11 %sp %pc
+36 L4 @0x4ed44650 eafeed4a b $0x4ecfc180 <shared_bb_ibl_ret>
END 0xb6f65438
skip restore stolen reg app value for: ldm (%sp) -> %r4 %r5 %r6 %r7 %r8 %r9 %r10 %r11 %sp
bb ilist after mangling:
TAG 0xb6f65438
+0 L3 @0x4ed4538c e51b2034 ldr -0x34(%r11)[4byte] -> %r2
+4 L3 @0x4ed44d24 e3a03000 mov $0x00000000 -> %r3
+8 L3 @0x4ed454c0 e590c000 ldr (%r0)[4byte] -> %r12
+12 L3 @0x4ed451b8 e5802004 str %r2 -> +0x04(%r0)[4byte]
+16 L3 @0x4ed452ec e08c1001 add %r12 %r1 $0x00 -> %r1
+20 L3 @0x4ed43cb8 e5801000 str %r1 -> (%r0)[4byte]
+24 L3 @0x4ed44a48 e1a00003 mov %r3 -> %r0
+28 L3 @0x4ed43b78 e24bd028 sub %r11 $0x00000028 -> %sp
+32 m4 @0x4ed46b64 e58a0000 str %r0 -> (%r10)[4byte]
+36 m4 @0x4ed439bc e1a0000a mov %r10 -> %r0
+40 m4 @0x4ed45644 e58a0008 str %r0 -> +0x08(%r10)[4byte]
+44 L4 @0x4ed46e4c e59d0024 ldr +0x24(%sp)[4byte] -> %r0
+48 m4 @0x4ed44b88 e58a1000 str %r1 -> (%r10)[4byte]
+52 m4 @0x4ed43d08 e59a101c ldr +0x1c(%r10)[4byte] -> %r1
+56 m4 @0x4ed4438c e5911260 ldr +0x0260(%r1)[4byte] -> %r1
+60 m4 @0x4ed44914 e5810000 str %r0 -> (%r1)[4byte]
+64 m4 @0x4ed43da8 e59a1000 ldr (%r10)[4byte] -> %r1
+68 m4 @0x4ed43fc0 e59a0008 ldr +0x08(%r10)[4byte] -> %r0
+72 L4 @0x4ed45510 e89d2ff0 ldm (%sp) -> %r4 %r5 %r6 %r7 %r8 %r9 %r10 %r11 %sp
+76 m4 @0x4ed43e8c e580a018 str %r10 -> +0x18(%r0)[4byte]
+80 m4 @0x4ed44874 e1a0a000 mov %r0 -> %r10
+84 m4 @0x4ed4442c e59a0000 ldr (%r10)[4byte] -> %r0
+88 m4 @0x4ed45118 e59af01c ldr +0x1c(%r10)[4byte] -> %pc
+92 m4 @0x4ed45420 e59ff260 ldr +0x0260(%pc)[4byte] -> %pc
+96 m4 @0x4ed4433c e59ff000 ldr (%pc)[4byte] -> %pc
+100 L4 @0x4ed44650 eafeed4a b $0x4ecfc180 <shared_bb_ibl_ret>
END 0xb6f65438
.........
master_signal_handler: thread=1108, sig=11, xsp=0x4ed5bc88, retaddr=0x0000000b
siginfo: sig = 11, pid = 1322344512, status = 0, errno = 0, si_code = 2
r0 =0x612d0743
r1 =0x612d0743
r2 =0x2a720870
r3 =0x00000000
r4 =0x00000000
r5 =0xb6f64000
r6 =0xbefffa24
r7 =0x00000000
r8 =0x00000000
r9 =0x00000000
r10 =0x4ed2c000
r11 =0xbefffa0c
r12 =0x612d0743
sp =0xbefff9e8
r14 =0x00153904
pc =0x4ed16040
cpsr=0x800a0010
computing memory target for 0x4ed16040 causing SIGSEGV, kernel claims it is 0x4ed16040
fault_address: 0x4ed16040
compute_memory_target: falling back to racy protection checks
It remains impossible to mov from random register to pc: we cannot restore it from spill, since we will already rewrite PC.
code from this PR seems legit to me (maybe it needs some cleanup). Any hints to solve this problem?
P.S. armv7, running app under drrun