Clang-Cl assembly output - .seh_ pseudo code

Hello Clang-Developers,

I have a question about the assembly output Clang-Cl generated for me, when passing /Fa. The code was using a __try and __except statement and I wanted to see how the __try statement is represented in the target assembly. To my surprise there was no “.cv_loc” for that specific line - so I scrolled up a bit.

There I found:

push rbp

.seh_pushreg 5

sub rsp, 48

.seh_stackalloc 48

lea rbp, [rsp + 48]

.seh_setframe 5, 48

.seh_endprologue

I looked up those words and only could find out that those are pseudo code. I wonder, why am I not allowed to see the content behind those pseudo code? Is there a way to find out what will be written there later?

I also found the following lines in a different code which really confused me:

push rax

.seh_stackalloc 8

.seh_endprologue

Even though there is written “stackalloc” the rsp is not changed, but in the code I posted above it was changed.

Kind greetings

Björn

I can say a bit about them. We inherited these directives from the gnu assembler, and a similar question was asked about GCC here:
https://stackoverflow.com/questions/20819927/what-are-seh-assembly-commands-that-gcc-outputs/38181874

Basically, these directives do not emit instructions, they record metadata about the prologue. Later, the .seh_handlerdata directive emits that metadata into an .xdata section, encoded according to these rules:
https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019

So, truly, these directives describe how to unwind the stack. They do not describe how __try / __except work. That is controlled by the data after .seh_handlerdata. Those bytes are typically known as the LSDA, “language-specific data area”. The personality function __C_specific_handler interprets the LSDA to handle exceptions.

Hope that helps.

Hey Reid,

Thank you for your tips! This really helped me understanding the situation better. Because of what you said I found the following code in the assembly:

.Lfunc_end9:

.seh_handlerdata

.set “.L??$universalCall@X$$V@@YAXPEAX@Z$parent_frame_offset”, 32

.long (.Llsda_end4-.Llsda_begin4)/16 # Number of call sites

.Llsda_begin4:

.long .Ltmp55@IMGREL+1 # LabelStart

.long .Ltmp56@IMGREL+1 # LabelEnd

.long “?filt$0@0@?$universalCall@X$$V@@”@IMGREL # FilterFunction

.long .LBB9_1@IMGREL # ExceptionHandler

.Llsda_end4:

.section .text,“xr”,discard,"??$universalCall@X$$V@@YAXPEAX@Z"

.seh_endproc

That was really cool! Our code crashes soon after the function declaring(?) that stuff, so I tried finding the stuff on the stack – however I’m not sure if the values there are correct and if I found the right location. I basically dumped the entire stack between RSP and RBP – I found 2 sometime 3 addresses there that seems to be in my range.

However… Is it possible to some how directly read the values that are written there to ensure the ones on stack are the right ones? That sounds difficult to me…