C++ Exception Support: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(10 intermediate revisions by 7 users not shown)
Line 1:
If the g++ that targets your operating system follows the [httphttps://wwwitanium-cxx-abi.codesourcerygithub.com/publicio/cxx-abi/abi-eh.html Itanium C++ ABI] (GCC does so for almost all architectures), you can follow this article and add C++ exception support to your kernel.
 
==Introduction==
In the ABI, C++ exception is supported by the cooperation of three layers. The first layer is the compiler. The compiler translates the "try" "catch" "throw" statements into calls to specific functions in C++ runtime. The second layer is the C++ runtime. For exception support this layer is more or less a wrapper around the third layer. All the dirty work are done by the third layer: the unwind library. BTW, the second layer also adds support for RTTI & dynamic_cast
 
Line 8:
If you don't have any of the unix header files when compiling libcxxrt or libgcc_eh, e.g. <unistd.h>, create an empty one and try again. If you still can't compile libcxxrt or libgcc_eh, find a copy of the corresponding header file from a unix system and find out exactly what you are missing.
 
==Port libcxxrt==
libcxxrt can be downloaded [httphttps://github.com/pathscalelibcxxrt/libcxxrt here]. libcxxrt is very easy to port, only 1 .c file and 8 .cc files. It depends on a few simple libc functions and a few pthread functions. If you don't need multi-thread support in your kernel (no smp, kernel code isn't preemptive), create some pthread stubs. Then copy all the source files and header files into your own kernel source tree and compile them with your existing build system, no special compiler flags are needed.
 
==Port libgcc_eh==
libgcc_eh is more difficult.
# First thing is to try to cross compile GCC (you will fail, don't worry).
Line 26:
Some of the compiler flags that affect code generation may cause stack unwinding to fail. In particular, flags like "-fomit-stack-pointer" and "-mregparms={n}" could break things. When debugging the ported code, try compiling without these flags first.
 
==Rolling your own==
(NOTE: This is not yet complete, and hasn't been independently tested)
If you're adverse to including external code in your OS (or just want the challenge), you should be able to write your own C++ library, which handles the dispatching and allocation of exceptions (stack backtracing is handed by libgcc, which you should already be including with your build). If you choose this route, make sure to run _init upon loading each module (library or executable) to properly register the exception handling frames with the unwind code.
 
The functions you'll need to implement all start with `__cxa_` and are documented in the Itanium C++ ABI (which is also used for x86 by GCC)
You will also need to implement `__gxx_personality_v0` (which according to the clang docs, is the de-facto standard for C++), the structures used by this function to know what to do are documented in [httphttps://mentorembedded.github.iocom/itanium-cxx-abi/cxx-abi/raw/master/exceptions.pdf this] PDF.
 
It is also possible to create macros that implement exception-like control structures (especially useful if you use visual C++). You can implement exceptions with nothing more than setjmp and a linked list. However, you will need to create an exception class that all exceptions derive from, which implements some form of basic RTTI.
 
You can also implement the entire unwind library that matches the IA64 C++ Spec. Libc++ and Libc++abi provide great starting points for Layers 1 and 2. All thats needed is Layer 3 which provides the __Unwind_RaiseException logic which uses the "eh_frame" specs from LSB, DWARF4 spec, IA64 C++ spec and the System V spec. To see an example of how to do this, see [https://github.com/Bareflank/hypervisor/tree/master/bfunwind here]
 
==Function stubs==
If you don't have some of the needed funtions, try some of these stubs
 
===malloc===
<sourcesyntaxhighlight lang="cpp">
void* malloc(size_t size) {
static char* freeMemoryBase = SOME_BASE_ADDRESS;
Line 48:
return freeMemoryBase - size;
}
</syntaxhighlight>
</source>
 
===pthread===
You may use the following stub for pthread, or you can just define LIBCXXRT_WEAK_LOCKS for libcxxrt, which will make libcxxrt treat all pthread functions as weak symbol, so you do not actually need to provide these functions, but only a single pthread.h with only declarations.
<sourcesyntaxhighlight lang="cpp">
namespace { void* threadDataTable[64]; int freeEntry = 0;}
int pthread_key_create(pthread_key_t* key, void (*)(void*)) {
Line 103:
return 0;
}
</syntaxhighlight>
</source>
 
===dladdr===
This function is used for debugging by libcxxrt, not a big problem to simply return an error.
<sourcesyntaxhighlight lang="c">
int dladdr(void*, Dl_info*) {
return 0;
}
</syntaxhighlight>
</source>
 
==Link Script==
If you use a custom link script, make sure to place .eh_frame_hdr, .eh_frame and .gcc_except_table in the exact order in your final output. Otherwise sometimes you are not able to catch any exceptionexceptions.
 
== See Also ==
 
* httphttps://wwwitanium-cxx-abi.codesourcerygithub.comio/cxx-abi/abi-eh.html (While sounding like being specific to the Itanium, this is the base for the common C++ ABI)
 
* http://www.codeproject.com/cpp/exceptionhandler.asp (Specific to VC++.)
Line 124:
* http://www.microsoft.com/msj/0197/Exception/Exception.aspx (Article on SEH, the [[Stack#Unwinding the stack|stack-based unwinding]] used by VC++ and most other Windows compilers. Any use of stack-based SEH may or may not be covered by USPTO patent #5,628,016, held by Borland International, Inc.; GCC and most other UNIX compilers use the same table-based mechanism on the x86 that is the rule on RISC architectures, thus being unaffected by the patent.)
 
* https://web.archive.org/web/20120620090841/http://www.kuzbass.ru:8086/docs/isocpp/except.html
 
* The standard header '''<exception>''', declaring several support functions.
 
* http://llvm.org/docs/ExceptionHandling.html (How LLVM/Clang handles C++ exceptions, references the C++ABI and the following document)
* httphttps://mentorembedded.github.iocom/itanium-cxx-abi/cxx-abi/raw/master/exceptions.pdf (A document by HP on C++ exception handling)
 
[[Category:C++]]