[WIP] Support Arm32 and Arm64 in nearDiff - #1098
Conversation
|
We could put some invalid instruction padding in between the end of the actual code and the literal pool, and have the disassembly tools know what that means. |
|
Other ways that change what the JIT does and wastes a small amount of space or time:
Hard to think of something simpler than what you're doing that doesn't add extra meta-data, though. If you can discover all the code entrypoints from the JIT-EE interactions, you could do flow analysis to find live code and treat everything else as data. That seems insane, though, unless we started interleaving data with code, and even then I think you're method would work most of the time. I apologize for my JIT ignorance, but do we generate switch tables as inline data? If so, that data may need to be discovered as well. |
| constexpr unsigned int AArch64_LDRSl = 2407; | ||
|
|
||
| bool HasPCRelLabel = false; | ||
| unsigned int OperandNum = -1; |
| break; | ||
| } | ||
|
|
||
| if (HasPCRelLabel) { |
There was a problem hiding this comment.
Can't it be replaced with Inst.getOpcode() == AArch64_LDRDl || Inst.getOpcode() == AArch64_LDRSl?
| switch (Inst.getOpcode()) { | ||
| case AArch64_LDRDl: | ||
| case AArch64_LDRSl: | ||
| HasPCRelLabel = true; |
| return false; | ||
| } | ||
|
|
||
| const uint8_t* ConsBlockL = nullptr; |
There was a problem hiding this comment.
Could you please add a comment or longer names for these two variables?
|
It seems like this is a bit of a hack to me. On the one hand, if we want to support disassembling blobs of code that might also contain data, we should do something more sophisticated like construct a flow graph, and binary compare any bits between the "found" native code. For this case, it feels like we should extend the "allocMem" JIT-EE interface method to take a "roCloseDataSize" that would be added by the VM to the code size, the way our call to |
|
Closing in favor of dotnet/jitutils#291 |
Right now CorDisTools can not be used to disassemble JIT output during SuperPMI with ARM64 JIT due to the fact that on ARM64 the code block is appended with literal pool (https://github.com/dotnet/coreclr/blob/06f1634c3157dc279779f3dad7d2f327416e3f09/src/jit/emit.cpp#L4629-L4650)
What happens is that the disassembler goes beyond JIT code and tries to decode data in literal pool where it obviously fails.
I couldn't find any information collected during JIT-EE interactions that can help to determine the size of JIT code region. It seems that we are loosing such information during allocMem call by explicitly passing 0 in roDataSize (https://github.com/dotnet/coreclr/blob/06f1634c3157dc279779f3dad7d2f327416e3f09/src/jit/emit.cpp#L4645)
What I am doing here is trying to reconstruct boundary between JIT code and constant pool during instruction decoding by looking at LDR instructions that have PCRel immediate as a second operand and computing the corresponding label addresses using current value of PC. The minimum address is then assumed to be the beginning of a literal pool.
I did experimentation with running SuperPMI with ARM64 JIT with CorDisTools with these changes and it seems that this approach works on the all framework libraries in Core_Root.
@dotnet/jit-contrib
Does anyone think about a better way to figure out the literal pool size?
@briansull @BruceForstall