-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVX-512 debugger support: breakpoints #87843
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsAs part of implementing AVX-512 support (link), we should support breakpoints on AVX-512 instructions, especially newly supported EVEX encoded instructions. Currently, consider the following test case:
If you build it (either Debug or Release in Visual Studio) and run it, it prints Setting the breakpoint that location actually sets it on this instruction:
This is a RIP-relative When the debugger sets a breakpoint, it copies the instruction to a "patch" location. After the breakpoint, it executes the instruction from the patch location. Thus, it needs special handling for RIP-relative addressing, as the executed code RIP will be different from when the code was generated. The debugger disassembles the instruction to determine if it uses RIP-relative addressing. If so, it updates the RIP-relative address in the patch to point to the patch buffer with additional space for data, which is copied from the original location. For The debugger figures out characteristics of the instruction, such as whether it contains RIP-relative addressing, using These tables understand up to VEX encodings, but do not understand EVEX encodings. Either they need to be updated, or some other mechanism needs to be introduced in Note that the JIT currently generates RIP-relative reads for 512-bit vector constants in the data section. It generally does not generate RIP-relative reads or writes to class static variables (where it is expected it would generate RIP-relative addressing) because 512-bit vector statics get placed in the Frozen (non GC) heap (so they don't move). Currently, that heap is normally too far away from the generated code heap to allow for RIP-relative addressing. However, that could change (and it is a goal to change it, as with #78292, which was reverted). And if they are placed closer to the JIT, RIP-relative addressing will automatically be enabled.
|
fyi @hoyosjs |
cc @dotnet/avx512-contrib |
Some places that need to change: runtime/src/coreclr/debug/ee/controller.h Lines 304 to 308 in 5fd32d9
runtime/src/coreclr/debug/ee/controller.cpp Lines 4896 to 4899 in 5fd32d9
(needs "64" case) |
Do the instruction tables need the update too? |
It needs to learn about EVEX encodings. Whether that is by replacing the instruction tables, creating a new set of EVEX-specific tables, or writing manual EVEX parsing code (and not using the table code path) is up for design discussion. |
As part of implementing AVX-512 support (link), we should support breakpoints on AVX-512 instructions, especially newly supported EVEX encoded instructions.
Currently, consider the following test case:
If you build it (either Debug or Release in Visual Studio) and run it, it prints
16
. If you set a breakpoint on the indicated line, then run it in VS, hit the breakpoint, then continue, it prints0
. The act of setting, hitting, and running after a breakpoint in the debugger causes program behavior to differ.Setting the breakpoint that location actually sets it on this instruction:
This is a RIP-relative
read
instruction.When the debugger sets a breakpoint, it copies the instruction to a "patch" location. After the breakpoint, it executes the instruction from the patch location. Thus, it needs special handling for RIP-relative addressing, as the executed code RIP will be different from when the code was generated. The debugger disassembles the instruction to determine if it uses RIP-relative addressing. If so, it updates the RIP-relative address in the patch to point to the patch buffer with additional space for data, which is copied from the original location. For
write
operations, the data is copied back to the original location after the instruction is executed.The debugger figures out characteristics of the instruction, such as whether it contains RIP-relative addressing, using
NativeWalker::DecodeInstructionForPatchSkip
and the tables that were introduced with dotnet/coreclr#25958: see https://github.com/dotnet/runtime/tree/main/src/coreclr/debug/ee/amd64/gen_amd64InstrDecode.These tables understand up to VEX encodings, but do not understand EVEX encodings. Either they need to be updated, or some other mechanism needs to be introduced in
NativeWalker::DecodeInstructionForPatchSkip
for EVEX instructions.Note that the JIT currently generates RIP-relative reads for 512-bit vector constants in the data section. It generally does not generate RIP-relative reads or writes to class static variables (where it is expected it would generate RIP-relative addressing) because 512-bit vector statics get placed in the Frozen (non GC) heap (so they don't move). Currently, that heap is normally too far away from the generated code heap to allow for RIP-relative addressing. However, that could change (and it is a goal to change it, as with #78292, which was reverted). And if they are placed closer to the JIT, RIP-relative addressing will automatically be enabled.
Thus, for RIP-relative reads on which breakpoints are set, executing in the debugger will currently load random data, leading to incorrect program behavior. For RIP-relative writes (which probably don't currently occur), arbitrary data corruption could occur.
The text was updated successfully, but these errors were encountered: