OpenSolaris

You are not signed in. Sign in or register.

The System Object Filesystem

The system object filesystem (objfs), is mounted at /system/object on every Solaris system. Its purpose is to expose the symbol table and CTF data for all objects currently loaded in the kernel, with the primary consumer being libdtrace. Why is this so important for DTrace? to quote from the original ARC case:

The dtracekernel privilege was created to allow uprivileged users to trace kernel activity with DTrace. Unfortunately, DTrace still has to use /dev/kmem to get type and symbol information. This has the side effect of requiring all privileges, so a user with the dtracekernel privilege cannot use D scripts that rely on CTF data or kernel symbols. This also prevents a 32-bit DTrace consumer from running on a 64-bit system, and is one of the barriers to DTrace in a local zone (since we can't include /dev/kmem in a local zone for obvious reasons).

Now that DTrace uses /system/object, the dtrace_kernel privilege actually behaves like it's supposed to, and you have the added benefit of being able to run your favorite ELF tools (nm(1), elfdump(1), etc) on the resulting files.

Finding the source

The source is located at usr/src/uts/common/fs/objfs. The following table provides a brief description of each file:

FileDescription
usr/src/uts/common/fs/objfs/objfs_vfs.cVFS and kernel module interfaces
usr/src/uts/common/fs/objfs/objfs_root.cThe root directory
usr/src/uts/common/fs/objfs/objfs_odir.cPer-object directory
usr/src/uts/common/fs/objfs/objfs_data.cThe 'object' data file
usr/src/uts/common/fs/objfs/objfs_common.cMiscellaneous shared routines

Understanding the source

The object filesystem is built on top of gfs, a framework for constructing pseudo filesystems. See David Powell's blog post for a description of GFS, why it was developed, and how it's used.

At the heart of objfs is the 'object' data file. The rest of the source code exists solely to present this data in the appropriate manner. The first question you might ask is: why have '/system/object/module/object', with nothing else in the directory? Isn't that redundant? The reason is simple extensibility. When /proc was first developed, there was a single file for each process, which quickly wore out its welcome. We think there may be other uses for this filesystem out there, and we don't want to rule any future enhancements.

The choice of ELF files follows a similar trend. The primary reason is that the existing tools (most notably libctf) already have existing interfaces to interact with ELF files. On top of that, the ELF format is by nature extensible, so we can add information within the ELF object file, in addition to creating new entries in the per-object directory. You might notice there is no text or data associated with the object file. The data is self explanatory: exposing it is a clear security risk. The choice to export text is more subtle. But module text is modified after being loaded, so if we chose to export it would be revealing privileged information (such as which DTrace probes were enabled).

The source code is laid out around the data_sections table, which describes how to construct each section. The seemingly endless set of macros expand into a structure that the sect_*() family of functions can then access. The bulk processing is done in objfsdataread(). We check the following in order: the ELF header, the section headers, and finally the section data itself.

Using the filesystem

The /system/object interface is not public, nor is it a stable interface. If you find yourself needing to use the filesystem, let us know so that we can determine whether it makes sense to stabilize the interface. The best ways to examine the data is through standard libraries, such as libelf(3LIB) or libctf.