Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
# CONTEXT.Rdi 176
# CONTEXT.R8 184
# CONTEXT.R9 192
# CONTEXT.R10 200
# CONTEXT.R11 208
# CONTEXT.R12 216
# CONTEXT.R13 224
# CONTEXT.R14 232
# CONTEXT.R15 240
# CONTEXT.Rip 248
# CONTEXT.Xmm6 512
# sizeof(CONTEXT) 1232
# DISPATCHER_CONTEXT.ControlPc 0
# DISPATCHER_CONTEXT.ImageBase 8
# DISPATCHER_CONTEXT.FunctionEntry 16
# DISPATCHER_CONTEXT.EstablisherFrame 24
# DISPATCHER_CONTEXT.TargetIp 32
# DISPATCHER_CONTEXT.ContextRecord 40
# DISPATCHER_CONTEXT.LanguageHandler 48
# DISPATCHER_CONTEXT.HandlerData 56
# UNW_FLAG_NHANDLER 0
# ExceptionContinueSearch 1
#
# In order to tie the handler to the function one has to compose
# couple of structures: one for .xdata segment and one for .pdata.
#
# UNWIND_INFO structure for .xdata segment would be
#
# function_unwind_info:
# .byte 9,0,0,0
# .rva handler
#
# This structure designates exception handler for a function with
# zero-length prologue, no stack frame or frame register.
#
# To facilitate composing of .pdata structures, auto-generated "gear"
# prologue copies rsp value to rax and denotes next instruction with
# .LSEH_begin_{function_name} label. This essentially defines the SEH
# styling rule mentioned in the beginning. Position of this label is
# chosen in such manner that possible exceptions raised in the "gear"
# prologue would be accounted to caller and unwound from latter's frame.
# End of function is marked with respective .LSEH_end_{function_name}
# label. To summarize, .pdata segment would contain
#
# .rva .LSEH_begin_function
# .rva .LSEH_end_function
# .rva function_unwind_info
#
# Reference to functon_unwind_info from .xdata segment is the anchor.
# In case you wonder why references are 32-bit .rvas and not 64-bit
# .quads. References put into these two segments are required to be
# *relative* to the base address of the current binary module, a.k.a.
# image base. No Win64 module, be it .exe or .dll, can be larger than
# 2GB and thus such relative references can be and are accommodated in
# 32 bits.
#
# Having reviewed the example function code, one can argue that "movq
# %rsp,%rax" above is redundant. It is not! Keep in mind that on Unix
# rax would contain an undefined value. If this "offends" you, use
# another register and refrain from modifying rax till magic_point is
# reached, i.e. as if it was a non-volatile register. If more registers
# are required prior [variable] frame setup is completed, note that
# nobody says that you can have only one "magic point." You can
# "liberate" non-volatile registers by denoting last stack off-load
# instruction and reflecting it in finer grade unwind logic in handler.
# After all, isn't it why it's called *language-specific* handler...
#
# Attentive reader can notice that exceptions would be mishandled in
# auto-generated "gear" epilogue. Well, exception effectively can't
# occur there, because if memory area used by it was subject to
# segmentation violation, then it would be raised upon call to the
# function (and as already mentioned be accounted to caller, which is
# not a problem). If you're still not comfortable, then define tail
# "magic point" just prior ret instruction and have handler treat it...
#
# (*) Note that we're talking about run-time, not debug-time. Lack of
# unwind information makes debugging hard on both Windows and
# Unix. "Unlike" referes to the fact that on Unix signal handler
# will always be invoked, core dumped and appropriate exit code
# returned to parent (for user notification).