Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -55,4 +55,20 @@
 	} :data
 
+    __dso_handle = .;
+
+	.init_array : {
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+		KEEP (*(.init_array .ctors))
+		PROVIDE_HIDDEN (__init_array_end = .);
+	}
+
+	.fini_array : {
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+		KEEP (*(.fini_array .dtors))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+	}
+
 	_end = .;
 
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -112,4 +112,5 @@
 	pcb->dynamic = info->finfo.dynamic;
 	pcb->rtld_runtime = info->env;
+	pcb->cpp_data = info->finfo.cpp_data;
 }
 
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -198,4 +198,9 @@
 	size_t phdr_len = header->e_phnum * header->e_phentsize;
 
+	elf->info->interp = NULL;
+	elf->info->dynamic = NULL;
+	elf->info->cpp_data.ctors_count = 0;
+	elf->info->cpp_data.dtors_count = 0;
+
 	if (phdr_len > sizeof(phdr)) {
 		DPRINTF("more than %d program headers\n", phdr_cap);
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/c/generic/libc.c	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -61,6 +61,16 @@
 #endif
 
+static bool env_setup = false;
 
-static bool env_setup = false;
+/**
+ * Used for C++ constructors/destructors
+ * and the GCC constructor/destructor extension.
+ */
+typedef void (*init_array_entry_t)();
+extern init_array_entry_t __init_array_start[];
+extern init_array_entry_t __init_array_end[];
+typedef void (*fini_array_entry_t)();
+extern fini_array_entry_t __fini_array_start[];
+extern fini_array_entry_t __fini_array_end[];
 
 void __libc_main(void *pcb_ptr)
@@ -115,4 +125,12 @@
 
 	/*
+	 * C++ Static constructor calls.
+	 */
+	ptrdiff_t init_array_entries = (__init_array_end - __init_array_start);
+
+	for (int i = init_array_entries - 1; i > 0; --i)
+		__init_array_start[i]();
+
+	/*
 	 * Run main() and set task return value
 	 * according the result
@@ -124,4 +142,14 @@
 void __libc_exit(int status)
 {
+	/*
+	 * GCC extension __attribute__((destructor)),
+	 * C++ destructors are added to __cxa_finalize call
+	 * when the respective constructor is called.
+	 */
+	ptrdiff_t fini_array_entries = (__fini_array_end - __fini_array_start);
+
+	for (int i = 0; i < fini_array_entries; ++i)
+		__fini_array_start[i]();
+
 	if (env_setup) {
 		__stdio_done();
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/c/include/loader/pcb.h	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -36,5 +36,4 @@
 #ifndef LIBC_PCB_H_
 #define LIBC_PCB_H_
-
 
 typedef void (*entry_point_t)(void);
@@ -76,4 +75,6 @@
 	/** Pointer to dynamic linker state structure (rtld_t). */
 	void *rtld_runtime;
+	/** C++ related data. */
+	cpp_data_t cpp_data;
 } pcb_t;
 
Index: uspace/lib/cpp/include/internal/abi.hpp
===================================================================
--- uspace/lib/cpp/include/internal/abi.hpp	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/cpp/include/internal/abi.hpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -32,4 +32,12 @@
 namespace __cxxabiv1
 {
+    /**
+     * Static constructor/destructor helpers.
+     */
+
+    extern "C" int __cxa_atexit(void (*)(void*), void*, void*);
+
+    extern "C" void __cxa_finalize(void*);
+
     /**
      * Itanium C++ ABI type infos.
Index: uspace/lib/cpp/src/internal/runtime.cpp
===================================================================
--- uspace/lib/cpp/src/internal/runtime.cpp	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/cpp/src/internal/runtime.cpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -27,8 +27,34 @@
  */
 
+#include <cstdlib>
+#include <cstdint>
 #include <internal/abi.hpp>
+#include <exception>
 
 namespace __cxxabiv1
 {
+    namespace aux
+    {
+        struct destructor_t
+        {
+            void (*func)(void*);
+            void* ptr;
+            void* dso;
+        };
+
+        destructor_t* destructors{nullptr};
+        std::size_t destructor_count{0};
+        std::size_t destructor_size{32};
+
+        /**
+         * C atexit does not pass any arguments,
+         * but __cxa_finalize requires one so we
+         * use a wrapper.
+         */
+        void atexit_destructors()
+        {
+            __cxa_finalize(nullptr);
+        }
+    }
 
     /**
@@ -36,7 +62,60 @@
      * call of a pure virtual function cannot be made.
      */
-    // TODO: terminate in this
     extern "C" void __cxa_pure_call()
-    { /* DUMMY BODY */ }
+    {
+        std::terminate();
+    }
+
+    extern "C" int __cxa_atexit(void (*f)(void*), void* p, void* d)
+    {
+        if (!aux::destructors)
+        {
+            aux::destructors = new aux::destructor_t[aux::destructor_size];
+            std::atexit(aux::atexit_destructors);
+        }
+        else if (aux::destructor_count >= aux::destructor_size)
+        {
+            auto tmp = std::realloc(aux::destructors, aux::destructor_size * 2);
+
+            if (!tmp)
+                return -1;
+
+            aux::destructors = static_cast<aux::destructor_t*>(tmp);
+            aux::destructor_size *= 2;
+        }
+
+        auto& destr = aux::destructors[aux::destructor_count++];
+        destr.func = f;
+        destr.ptr = p;
+        destr.dso = d;
+
+        return 0;
+    }
+
+    extern "C" void __cxa_finalize(void *f)
+    {
+        if (!f)
+        {
+            for (std::size_t i = aux::destructor_count; i > 0; --i)
+            {
+                if (aux::destructors[i - 1].func)
+                    (*aux::destructors[i - 1].func)(aux::destructors[i - 1].ptr);
+            }
+        }
+        else
+        {
+            for (std::size_t i = aux::destructor_count; i > 0; --i)
+            {
+                if (aux::destructors[i - 1].func == f)
+                {
+                    (*aux::destructors[i - 1].func)(aux::destructors[i - 1].ptr);
+                    aux::destructors[i - 1].func = nullptr;
+                    aux::destructors[i - 1].ptr = nullptr;
+                    aux::destructors[i - 1].dso = nullptr;
+                    // TODO: shift and decrement count
+                }
+            }
+        }
+    }
 
     __fundamental_type_info::~__fundamental_type_info()
Index: uspace/lib/cpp/src/internal/unwind.cpp
===================================================================
--- uspace/lib/cpp/src/internal/unwind.cpp	(revision 9396c525855832d2f7468890aa9093c4872302a7)
+++ uspace/lib/cpp/src/internal/unwind.cpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
@@ -219,3 +219,8 @@
         // TODO: implement
     }
+
+    extern "C" void __cxa_throw_bad_array_new_length()
+    {
+        // TODO: implement
+    }
 }
