drreg_reserve_reg across BBs

28 views
Skip to first unread message

Mohammad Ewais

unread,
Nov 23, 2021, 4:50:44 AM11/23/21
to DynamoRIO Users
Hi,

I need to insert clean calls before and after each memory access, these clean calls also require me to reserve a register before the first call and unreserve it after. 
The case in question is the following jmp qword ptr [0xADDRESS]. This means I CANNOT insert clean call or unreserve the register AFTER the instruction.

I thought of moving the second clean call and the unreservation to the beginning of the next BB (the jmp target), this would work well with the clean call insertion, but unreserving the register (or rather, not unreserving it in time) would give me this error:
ASSERT FAILURE: /home/travis/build/DynamoRIO/dynamorio/ext/drreg/drreg.c:649: !pt->reg[((reg)-DR_REG_RAX)].in_use (user failed to unreserve a register)

I had a similar situation with CALL instructions, but for calls I get to use R11 without reserving it because it is caller saved and is guaranteed to be "empty" by the time I instrument the call instruction. 

How do I go about this? Is there a way to achieve what I am trying to do?

sharma...@google.com

unread,
Nov 23, 2021, 11:24:10 AM11/23/21
to DynamoRIO Users
Hi,

> I thought of moving the second clean call and the unreservation to the beginning of the next BB (the jmp target), this would work well with the clean call insertion, but unreserving the register (or rather, not unreserving it in time) would give me this error:

drreg works at the fragment level, so all regs need to be unreserved by the end of the fragment. It is currently not possible to have cross-fragment reservations.

> The case in question is the following jmp qword ptr [0xADDRESS]. This means I CANNOT insert clean call or unreserve the register AFTER the instruction.

Usually, we add all instrumentation _before_ the instruction (e.g. drreg reservation, clean call, drreg un-reservation, app instr; in that order). I assume that's not possible in this case? Is it because you are modifying the original app instruction? Or does the second clean call (the one after the mem access) cannot be moved to before for some reason?

If refactoring the instrumentation to be all before the instr doesn't work, another option could be to split the jmp from address in memory into a load from memory and jmp from reg.

Abhinav

Mohammad Ewais

unread,
Nov 23, 2021, 1:37:14 PM11/23/21
to DynamoRIO Users
Hi Abhinav,

Unfortunately, I cannot move the entire instrumentation before the instruction. My project requires virtualizing an application's memory across multiple machines (yikes!) which involves locking and unlocking before and after each memory access.

I did try breaking the jmp down to a mov to reg followed by jump from the reg, but that register has to be reserved before I do so, which means I also have to unreserve it after is used by the jump. Back to the issue of unreserving after jump breaking the BB requirement.

sharma...@google.com

unread,
Nov 23, 2021, 6:20:55 PM11/23/21
to DynamoRIO Users
After all clients add their instrumentation, DR would mangle that jmp into a load+jmp internally. But unfortunately, there's no interface for post-mangling instrumentation for clients that would allow you to use the loaded value before the jmp.

An alternative approach is replacing the app's `jmp [mem]` to the following sequence:

<reserve scratch reg using drreg> mov [mem], <scratch-reg> // add your instrumentation around this read, and ignore all other memory accesses in this snippet <store scratch-reg contents to some location L>
<unreserve scratch reg> jmp [L]

L must be a location that's directly addressable without using any reg. You can get L using dr_raw_tls_calloc in your client init. This returns a slot that's addressable using just a segment reg on x86, or the stolen reg on ARM (which doesn't need reservation/unreservation).

I'm assuming here that you need to instrument around only the memory accesses originally present in the app (that is, the mov in the above sequence), and that you're okay with ignoring the reads/writes of L, or any other memory access made by DR (by drreg or other internal accesses).

Does this help?

Abhinav

Mohammad Ewais

unread,
Nov 24, 2021, 5:17:43 AM11/24/21
to DynamoRIO Users
jmp can have a full 64 bit address as an operand anyway, so I can just use a location in my TLS as an absolute address.

Anyway, sounds like a good possible solution, will give it a try. Thanks a lot.

Reply all
Reply to author
Forward
0 new messages