2

I'm writing a native mode application (think: link /subsystem:native). This means I can't use anything from kernel32.dll, which (apparently) means nothing from the C runtime libraries. Mostly that's not a problem for me as everything I need is in ntdll.dll. The code is written and working.

However, I'm writing the code in c++, and there's the question of what to do with exception handling. I believe the intent for native mode applications is to use SEH, which is what I've done. But that's not quite working.

If I compile without /EHa, my destructors don't get called when I RtlRaiseException. But if I do compile with /EHa, I'm getting an undefined symbol (unresolved external symbol __CxxFrameHandler4), which apparently only exists in the C runtime.

(How) can I compile my c++ code to support unwinding while still building a native mode application?


Edit: VC has 4 possible settings for exception handling, all of which have problems in this context:

  • Yes with SEH Exceptions (/EHa) - As mentioned above, this results in unresolved external symbol __CxxFrameHandler4.
  • Yes (/EHsc) - 2 unresolved symbols: __CxxFrameHandler4 & __std_terminate
  • Yes with Extern C functions (/EHs) - Same 2 unresolveds as /EHsc
  • No - No unresolved symbols, but destructors don't get called when exceptions get raised.

I wondered if I could link to the non-dll version of the C runtime. After all, if everything's embedded in my executable, it won't need to load any dlls when running at boot time, right?

So, I tried linking in libvcruntime.lib (the apparent home of __CxxFrameHandler4). The good news is that __CxxFrameHandler4 is no longer unresolved. The bad news is that gave me an additional 55 unresolved symbols. This list includes items like __imp_TlsAlloc and __imp_TlsGetValue which are clearly from kernel32.dll (and thus unavailable to me).

I'm prepared to use either C++ exceptions or SEH, but I can't get either to work in this context.

I see a number of exception-related functions exported in ntdll. Maybe there's some other exception handling mechanism I'm supposed to be hooking into?


Edit2: Since __CxxFrameHandler4 isn't working for me, I tried disabling the new exception handling (/d2FH4-). The only effect this had was to change the unresolved symbol to __CxxFrameHandler3. Not the result I was hoping for.

I'm out of ideas here. If there's some way to unwind the stack without using kernel32, I'm not finding it. The fact that there are exported functions in ntdll with "Exception" in their name suggests there might be, but perhaps not. Perhaps the intent there was always "C" code where destructors aren't a thing.

If anyone has any new things to try or a new place to look, I'd appreciate it. Or even an authoritative source that says it can't be done. At least then I'd know.

David Wohlferd
  • 7,110
  • 2
  • 29
  • 56

1 Answers1

2

There is this (peculiar) cl.exe /kernel switch. Basically that means:

No exceptions, no RTTI and no default new() / delete()

I might think you have already found this switch and are happy using it?

EDIT:

Probably the key question is: "Why this switch exists?". My guess is it is a "message from above" that says: do not even try C++ exceptions, RTTI and dflt new()/delete() when developing low level "things" using C++ on WIN.

In any case, I would not recommend C++ stack unwinding in C++ low level aka "native" WIN builds. I assume you do know about SEH? In case you do, then you know well those dark woods. While in there one can use ASAN. Survivors tales do exist.

Chef Gladiator
  • 902
  • 11
  • 23
  • I had not found this switch (have an upvote). Mostly this seems to be about adding warnings for things you shouldn't do in kernel mode. I tried adding it, but it doesn't seem to have changed anything. – David Wohlferd Sep 18 '20 at 20:28
  • @DavidWohlferd -- "Mostly this seems to be about adding warnings" --- Hmm, your project should not compile if you use the /kernel switch **and** you use try/throw/catch or RTTI or include anything from MS STL, methinks. -- https://godbolt.org/z/ea5MfM – Chef Gladiator Sep 19 '20 at 05:45
  • Correction ... you can do whatever you want from MS STL + do a /kernel build. It is only that will generate SEH exceptions. – Chef Gladiator Sep 21 '20 at 20:07