AArch64 fails to encode OP_ldr with pc-relative operand
For porting drbbdup to AArchXX for #4134 (closed) I changed the drbbdup tests to use rel-addr operands instead of abs-addr operands (via OPND_CREATE_ABSMEM
) (xref #5295) and it all worked on AArch64: the tests pass. But they fail on ARM trying to encode the load of the rel-addr since it does not reach:
ERROR: Could not find encoding for: ldr <rel> 0xb6fb2008[4byte] -> %r0
When I went to see how a64 worked: when logging is enabled it hits an assert:
SYSLOG_ERROR: Application /home/derek/dr/build/suite/tests/bin/simple_app (3952044). Internal Error: DynamoRIO debug check failure: /home/derek/dr/
src/core/ir/disassemble_shared.c:1520 nxt_pc != NULL
Yet without logging it works!
In the debugger we have:
(gdb) x/90i targetf->start_pc
0xffffb3fb0008: ldp x0, x1, [x28]
0xffffb3fb000c: str x1, [x28, #360]
0xffffb3fb0010: mrs x0, nzcv
0xffffb3fb0014: str x0, [x28, #344]
0xffffb3fb0018: mov x0, #0xe080 // #57472
0xffffb3fb001c: movk x0, #0xb3f9, lsl #16
0xffffb3fb0020: movk x0, #0xffff, lsl #32
0xffffb3fb0024: ldr x0, [x0]
0xffffb3fb0028: cmp x0, #0x1
0xffffb3fb002c: b.ne 0xffffb3fb0048 // b.any
The instrumentation had just a ldr
with a rel-addr opnd: so who inserted the mov;movk;movk
?
Disabling the disassembly assert (looks like it only really needs it for the length: so maybe we should remove the encode there for a64) logging now works
after instrumentation:
TAG 0x0000ffffb38840c0
+0 m4 @0x0000fffd6f8e50e8 6d6d7564 str %x1 -> +0x0168(%x28)[8byte]
+4 m4 @0x0000fffd6f8e4da0 6d6d7564 mrs %nzcv -> %x0
+8 m4 @0x0000fffd6f8e4cd8 6d6d7564 str %x0 -> +0x0158(%x28)[8byte]
+12 m4 @0x0000fffd6f8e4c58 6d6d7564 ldr <rel> 0x0000ffff6f856080[8byte] -> %x0
+16 m4 @0x0000fffd6f8e4e20 6d6d7564 <label>
+20 m4 @0x0000fffd6f8e4bd8 6d6d7564 subs %x0 $0x0000000000000001 lsl $0x0000000000000000 -> %xzr
+24 m4 @0x0000fffd6f8e4b10 6d6d7564 b.ne @0x0000fffd6f8e4fa0[8byte]
...
bb ilist after mangling:
TAG 0x0000ffffb38840c0
+0 m4 @0x0000fffd6f8e50e8 6d6d7564 str %x1 -> +0x0168(%x28)[8byte]
+4 m4 @0x0000fffd6f8e4da0 6d6d7564 mrs %nzcv -> %x0
+8 m4 @0x0000fffd6f8e4cd8 6d6d7564 str %x0 -> +0x0158(%x28)[8byte]
+12 m4 @0x0000fffd6f8e4418 6d6d7564 movz $0x6080 lsl $0x00 -> %x0
+16 m4 @0x0000fffd6f8e4350 6d6d7564 movk %x0 $0x6f85 lsl $0x10 -> %x0
+20 m4 @0x0000fffd6f8e42d0 6d6d7564 movk %x0 $0xffff lsl $0x20 -> %x0
+24 m4 @0x0000fffd6f8e4208 6d6d7564 ldr (%x0)[8byte] -> %x0
+28 m4 @0x0000fffd6f8e4e20 6d6d7564 <label>
+32 m4 @0x0000fffd6f8e4bd8 6d6d7564 subs %x0 $0x0000000000000001 lsl $0x0000000000000000 -> %xzr
+36 m4 @0x0000fffd6f8e4b10 6d6d7564 b.ne @0x0000fffd6f8e4fa0[8byte]
...
It looks like the a64 mangling does the immediate-into-reg expansion. But this is tool code: why is it being mangled? Here we go:
if (instr_has_rel_addr_reference(instr)
/* XXX i#1834: it should be up to the app to re-relativize, yet on amd64
* our own samples are relying on DR re-relativizing (and we just haven't
* run big enough apps to hit reachability problems) so for now we continue
* mangling meta instrs for x86 builds.
*/
IF_ARM(&&instr_is_app(instr))) {
instr_t *res = mangle_rel_addr(dcontext, ilist, instr, next_instr);
So the IF_ARM
doesn't apply to a64.
#1834 is confusingly closed: I re-opened it since it does not seem completely resolved.
This issue covers the disas assert and specific aarchxx issues. The rest overlaps with #1834.