How do SJLJ-Exceptions works?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

How do SJLJ-Exceptions works?

Hans Wennborg via cfe-dev

Hello Clang- and LLVM-Experts,

 

I was not sure which list is the right one, so I tried both – sorry for any inconvenient >o<

Lately I was working a lot with exceptions under Windows and especially with the Clang compiler. Out of curiosity I came along "Exception Handling in LLVM" and tried to understand the SJLJ exception handling. At first glance this made total sense to me! Store important registers and when the exception occurs - restore the saved registers. Kinda like setjump and longjump but with less registers.

 

However, there are two things I really don't understand (about exception handling in general). I guess it works something like that:

When I execute a function with a try-catch segment, as soon as I hit the try statement (Pretending I'm a Debugger or so), I would save the registerts (RSP, RIP of the catch block) on the stack I guess and keep doing what I do. However, when I encounter an exception now - how do I know where to find my stored registers on the stack? In the mean time I could had millions of push instructions so it can't be an offset. Also I can't imagine that the stack is marked somehow - like with a special bit pattern, risk would be to high that someone else uses that pattern. So I wonder... what is the secret behind it? Also is that the mysterious 'stack unwinding' I often heard about?

 

Thank you for any tip and help in advance!

Kind greetings

Björn

 

 

Als GmbH eingetragen im Handelsregister Bad Homburg v.d.H. HRB 9816, USt.ID-Nr. DE 114 165 789 Geschäftsführer: Dr. Hiroshi Nakamura, Dr. Robert Plank, Markus Bode, Heiko Lampert, Takashi Nagano, Takeshi Fukushima. Junichi Tajika
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: How do SJLJ-Exceptions works?

Hans Wennborg via cfe-dev
Hi Bjoern,

On Mon, 10 Feb 2020 at 07:30, Gaier, Bjoern via cfe-dev
<[hidden email]> wrote:
> When I execute a function with a try-catch segment, as soon as I hit the try statement (Pretending I'm a Debugger or so), I would save the registerts (RSP, RIP of the catch block) on the stack I guess and keep doing what I do. However, when I encounter an exception now - how do I know where to find my stored registers on the stack?

It's a bit more dependent on the runtime than that. You can use
-fsjlj-exceptions with Clang to see what it would actually do to code
even on platforms that normally use DWARF based exceptions (obviously
just a tool to inspect assembly, you shouldn't try to run the result).

Roughly speaking, try blocks result in a call to some function like
_Unwind_SjLj_Register that stashes the information needed to find the
right catch block and/or call needed destructors in a reasonably
generic fashion. It looks like libunwind's implementation makes those
frame-contexts into a linked-list accessed (essentially) via a global
variable.

The key files are lib/CodeGen/SjLjEHPrepare.cpp in LLVM and
src/Unwind-sjlj.c in libunwind.

> Also is that the mysterious 'stack unwinding' I often heard about?

More or less. The process libunwind goes through to look through all
these registered frames and restore needed state is called unwinding.

Cheers.

Tim.
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: How do SJLJ-Exceptions works?

Hans Wennborg via cfe-dev
Hello Tim,

Thank you! Both source files gave me a good idea about what is happening! That is really interesting!

Kind greetings
Björn

-----Original Message-----
From: Tim Northover <[hidden email]>
Sent: 10 February 2020 19:27
To: Gaier, Bjoern <[hidden email]>
Cc: Clang Dev <[hidden email]>; [hidden email]
Subject: Re: [cfe-dev] How do SJLJ-Exceptions works?

Hi Bjoern,

On Mon, 10 Feb 2020 at 07:30, Gaier, Bjoern via cfe-dev <[hidden email]> wrote:
> When I execute a function with a try-catch segment, as soon as I hit the try statement (Pretending I'm a Debugger or so), I would save the registerts (RSP, RIP of the catch block) on the stack I guess and keep doing what I do. However, when I encounter an exception now - how do I know where to find my stored registers on the stack?

It's a bit more dependent on the runtime than that. You can use -fsjlj-exceptions with Clang to see what it would actually do to code even on platforms that normally use DWARF based exceptions (obviously just a tool to inspect assembly, you shouldn't try to run the result).

Roughly speaking, try blocks result in a call to some function like _Unwind_SjLj_Register that stashes the information needed to find the right catch block and/or call needed destructors in a reasonably generic fashion. It looks like libunwind's implementation makes those frame-contexts into a linked-list accessed (essentially) via a global variable.

The key files are lib/CodeGen/SjLjEHPrepare.cpp in LLVM and src/Unwind-sjlj.c in libunwind.

> Also is that the mysterious 'stack unwinding' I often heard about?

More or less. The process libunwind goes through to look through all these registered frames and restore needed state is called unwinding.

Cheers.

Tim.
Als GmbH eingetragen im Handelsregister Bad Homburg v.d.H. HRB 9816, USt.ID-Nr. DE 114 165 789 Geschäftsführer: Dr. Hiroshi Nakamura, Dr. Robert Plank, Markus Bode, Heiko Lampert, Takashi Nagano, Takeshi Fukushima. Junichi Tajika
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev