-
Notifications
You must be signed in to change notification settings - Fork 3
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
Document how shimming works #16
Labels
documentation
Improvements or additions to documentation
non-code
The issue is not related to non-code e.g. infrastructure or documentation
Comments
I've made the following diagram as an overview of the flowchart LR
Start(( ))
IsMethod{{Is method call?}}
IsConstructor{{Is constructor?}}
NotMethodOrConstructor[Emit instruction]
MethodCall[Method call]
EmitMethodStub[Emit method call]
ConstructorCall[Constructor invocation]
EmitConstructorStub[Emit constructor stub]
End(( ))
Start-->IsMethod
IsMethod --> |Yes| MethodCallFlow
IsMethod --> |No| IsConstructor
subgraph MethodCallFlow [Method call]
direction TB
MethodCall-->EmitMethodStub
end
subgraph ConstructorCallFlow [Constructor call]
direction TB
ConstructorCall-->EmitConstructorStub
end
IsConstructor-->|Yes|ConstructorCallFlow
IsConstructor--->|No|NotMethodOrConstructor
NotMethodOrConstructor --> End
ConstructorCallFlow ---> End
MethodCallFlow --> End
I am still missing documentation on:
|
Miista
added
the
non-code
The issue is not related to non-code e.g. infrastructure or documentation
label
Jan 30, 2024
I have the following diagram for an extended view of how ---
title: Rewrite (for each instruction)
---
flowchart TD
subgraph Main
Start
IsLabelAtOffset{"Is there a label at the offset?"}
MarkLabel
IsOpCodeIgnored{"Is opcode ignored?"}
Continue
EmitIL
Start --> EmitILForExceptionHandlers
EmitILForExceptionHandlers --> IsLabelAtOffset
IsLabelAtOffset -->|Yes| MarkLabel
MarkLabel --> IsOpCodeIgnored
IsLabelAtOffset -->|No| IsOpCodeIgnored
IsOpCodeIgnored -->|Yes| Continue
Continue --> Start
IsOpCodeIgnored -->|No| EmitIL
end
subgraph EmitILForExceptionHandlers
%% Try blocks
GetTryBlocks["Get try-blocks (TryStart == instruction.Offset)"]
AnyTryBlocks{"Any try-blocks?"}
BeginExceptionBlock
IncreaseExceptionBlockLevel
GetTryBlocks --> AnyTryBlocks
AnyTryBlocks -->|Yes| BeginExceptionBlock
BeginExceptionBlock --> IncreaseExceptionBlockLevel
IncreaseExceptionBlockLevel --> GetExceptionFilters
AnyTryBlocks -->|No| GetExceptionFilters
%% Exception filters
GetExceptionFilters["Get exception filters"]
ExceptionFilterNull{"Exception filter == null?"}
BeginExceptionFilterBlock
GetExceptionFilters --> ExceptionFilterNull
ExceptionFilterNull -->|Yes| GetHandler
ExceptionFilterNull -->|No| BeginExceptionFilterBlock
BeginExceptionFilterBlock --> GetHandler
%% Handlers
GetHandler["Get handler (HandlerEnd == instruction.Offset)"]
IsHandlerNull{"Handler == null?"}
IsHandlerFinally{"Flags == Finally?"}
EndExceptionBlock
DecreaseExceptionBlockLevel
IsLastCatchBlock{"Is last catch block?"}
GetHandler --> IsHandlerNull
IsHandlerNull -->|Yes| GetCatchOrFinallyBlock
IsHandlerNull -->|No| IsHandlerFinally
IsHandlerFinally -->|Yes| EndExceptionBlock
EndExceptionBlock --> DecreaseExceptionBlockLevel
IsHandlerFinally -->|No| IsLastCatchBlock
IsLastCatchBlock -->|Yes| EndExceptionBlock
DecreaseExceptionBlockLevel --> GetCatchOrFinallyBlock
%% Catch or finally block
GetCatchOrFinallyBlock["Get catch or finally block (HandlerStart == instruction.Offset)"]
IsBlockCatchClause{"Flags == Clause?"}
IsBlockFilter{"Flags == Filter?"}
IsBlockFinally{"Flags == Finally?"}
END
BeginCatchBlock["Begin catch block"]
BeginFilterBlock["Begin filter block"]
BeginFinallyBlock["Begin finally block"]
ThrowFaultBlock["Throw NotSupportedException (fault blocks)"]
GetCatchOrFinallyBlock --> IsBlockCatchClause
IsBlockCatchClause -->|Yes| BeginCatchBlock
IsBlockCatchClause -->|No| IsBlockFilter
IsBlockFilter -->|Yes| BeginFilterBlock
IsBlockFilter -->|No| IsBlockFinally
IsBlockFinally -->|Yes| BeginFinallyBlock
IsBlockFinally -->|No| ThrowFaultBlock
BeginFinallyBlock --> END
end
|
Following is the diagram for how a stub for a direct call (constructor or method) is emitted. ---
title: Stub execution (direct call)
---
flowchart TD
Start
GetMethodFromHandle["Invoke GetMethodFromHandle"]
GetIndexOfMatchingShim["Try to find matching shim"]
FoundMatchingShim{"Found matching shim?\n(Index >= 0)"}
RewriteMethod["Label: RewriteMethod"]
CreateRewriter["Create instance of MethodRewriter"]
CallRewrite["Invoke MethodRewriter::Rewrite"]
GetMethodPointerToRewrittenMethod["Get method pointer to rewritten method"]
InvokeRewrittenMethod["Invoke rewritten method"]
Return["Emit ret"]
GetShimReplacementMethod["Get replacement method specified by shim"]
GetShimMethodPointer["Get method pointer to replacement method"]
GetShimDelegateTarget["Get shim delegate target"]
InvokeShim["Invoke shim"]
ReturnStub["Stub complete"]
Start --> LoadToken
LoadToken --> GetMethodFromHandle
GetMethodFromHandle --> GetIndexOfMatchingShim
GetIndexOfMatchingShim --> FoundMatchingShim
FoundMatchingShim -->|No| RewriteMethod
RewriteMethod --> CreateRewriter
CreateRewriter --> CallRewrite
CallRewrite --> GetMethodPointerToRewrittenMethod
GetMethodPointerToRewrittenMethod --> InvokeRewrittenMethod
InvokeRewrittenMethod --> Return
FoundMatchingShim -->|Yes| GetShimReplacementMethod
GetShimReplacementMethod --> GetShimMethodPointer
GetShimMethodPointer --> GetShimDelegateTarget
GetShimDelegateTarget --> InvokeShim
InvokeShim --> ReturnStub
Return --> ReturnStub
subgraph LoadToken
IsConstructor{"Is constructor?"}
LoadConstructorInfo
LoadMethodInfo
END
IsConstructor -->|Yes| LoadConstructorInfo
IsConstructor -->|No| LoadMethodInfo
LoadConstructorInfo --> END
LoadMethodInfo --> END
end
|
Following is the diagram for how a stub for a virtual call (method only) is emitted. ---
title: Stub execution (virtual call)
---
flowchart TD
Start
GetMethodFromHandle["Invoke GetMethodFromHandle"]
DeVirtualizeMethod["Invoke DeVirtualizeMethod"]
GetIndexOfMatchingShim["Try to find matching shim"]
FoundMatchingShim{"Found matching shim?\n(Index >= 0)"}
RewriteMethod["Label: RewriteMethod"]
CreateRewriter["Create instance of MethodRewriter"]
CallRewrite["Invoke MethodRewriter::Rewrite"]
GetMethodPointerToRewrittenMethod["Get method pointer to rewritten method"]
InvokeRewrittenMethod["Invoke rewritten method"]
Return["Emit ret"]
GetShimReplacementMethod["Get replacement method specified by shim"]
GetShimMethodPointer["Get method pointer to replacement method"]
GetShimDelegateTarget["Get shim delegate target"]
InvokeShim["Invoke shim"]
ReturnStub["Stub complete"]
Start --> LoadMethodInfo
LoadMethodInfo --> GetMethodFromHandle
GetMethodFromHandle --> DeVirtualizeMethod
DeVirtualizeMethod --> GetIndexOfMatchingShim
GetIndexOfMatchingShim --> FoundMatchingShim
FoundMatchingShim -->|No| RewriteMethod
RewriteMethod --> CreateRewriter
CreateRewriter --> CallRewrite
CallRewrite --> GetMethodPointerToRewrittenMethod
GetMethodPointerToRewrittenMethod --> InvokeRewrittenMethod
InvokeRewrittenMethod --> Return
FoundMatchingShim -->|Yes| GetShimReplacementMethod
GetShimReplacementMethod --> GetShimMethodPointer
GetShimMethodPointer --> GetShimDelegateTarget
GetShimDelegateTarget --> InvokeShim
InvokeShim --> ReturnStub
Return --> ReturnStub
|
Missing diagrams:
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
documentation
Improvements or additions to documentation
non-code
The issue is not related to non-code e.g. infrastructure or documentation
Ideally, this should include some descriptive text and a flowchart. For starters, we can document it here in this issue. Ideally, though, it should be in its own page in the wiki of this repository.
The text was updated successfully, but these errors were encountered: