Writing drivers in C++

Runtime support routines

Device drivers are linked within the kernel environment and do not have access to C++ runtime support routines from libC. Some of these routines are, however, necessary to support the code generated for drivers. ``Language feature selection'' describes some of these circumstances.

If the driver code has unresolved references to standard C++ runtime support routines:

  1. Use the ar -x command to extract the object code for these routines from /usr/ccs/lib/libC.a.

  2. Include these routines when the driver is linked into a single object file with the ld -r command.

  3. Use the ld -r -Bexport option to hide the names of the runtime support routines in each driver. These routines can only be included once in a kernel or multiple name definition errors will occur.

    This step is not necessary if you are absolutely certain that no other C++ drivers will be installed on a system with your driver, but it is not generally possible to know this for drivers that are being released to customers. You could also build a separate utility module that supplies these routines and have the drivers depend on it, but this does not prevent the problems that can arise if a customer has other C++ drivers installed on the system.

The runtime support routines that may be required in drivers are:

Runtime support routine Needed to resolve
dtor_list.o __process_needed_destructions
pure_virt.o __pure_virtual_called
vec_cctor.o __vec_cctor
vec_newdel.o __array_delete

Some of these support routines call std::abort( ) (mangled name: abort__3stdFv) when certain internal error conditions occur. The normal implementation of this library routine is not appropriate within the kernel, so the driver code must include a replacement error mechanism that makes sense for the driver. One possibility is an error mechanism that calls the ASSERT(D3) kernel function, although this will only be called for the -DDEBUG kernel.

Note also that vec_newdel.o will contain unresolved references to a variety of exception-handling related entry points, such as __rethrow( ) and __free_thrown_object( ). These entry points will not be called because drivers are not allowed to throw exceptions, but the entry points must be resolved or the driver will not be linkable or loadable.

Compiling a C module such as this solves these problems:

   /* dummy.c: */

/* implement this as appropriate */

void abort__3stdFv() { /* indicate internal error */ }

/* leave these as empty */

void __free_thrown_object() {}

void __exception_caught() {}

void __rethrow() {}

The end result is that the typical link command for a C++ device driver might look something like this:
   ld -r -o Driver.o mydriver.o vec_newdel.o dummy.o
A subsequent release of the HDK may provide a more elegant solution to these issues by including a specially-built version of libC.a or providing a dynamically loadable kernel module that supports the C++ runtime support routines.

The C++ runtime support routine issues discussed above are also applicable for SCO SVR5 2.X and SCO OpenServer 5, although there are fewer entry points to resolve and abort is not in namespace std, so the replacement routine does not need to use a mangled name.

© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005