This section describes the interfaces to the module loader. The loader interfaces can be divided into two groups: those that are only available to the XFree86 common layer, and those that are also available to modules.
The loader is capable of loading modules in a range of object formats,
and knowledge of these formats is built in to the loader. Knowledge of
new object formats can be added to the loader in a straightforward
manner. This makes it possible to provide OS-independent modules (for
a given CPU architecture type). In addition to this, the loader can
load modules via the OS-provided dlopen(3) service where
available. Such modules are not platform independent, and the semantics
of dlopen() on most systems results in significant
limitations in the use of modules of this type. Support for
dlopen() modules in the loader is primarily for
experimental and development purposes.
Symbols exported by the loader (on behalf of the core X server) to modules are determined at compile time. Only those symbols explicitly exported are available to modules. All external symbols of loaded modules are exported to other modules, and to the core X server. The loader can be requested to check for unresolved symbols at any time, and the action to be taken for unresolved symbols can be controlled by the caller of the loader. Typically the caller identifies which symbols can safely remain unresolved and which cannot.
The following is the semi-private loader interface that is available to the XFree86 common layer.
void LoaderInit(void)The
LoaderInit()function initialises the loader, and it must be called once before calling any other loader functions. This function initialises the tables of exported symbols, and anything else that might need to be initialised.
void LoaderSetPath(const char *path)The
LoaderSetPath()function initialises a default module search path. This must be called if calls to other functions are to be made without explicitly specifying a module search path. The search pathpathmust be a string of one or more comma separated absolute paths. Modules are expected to be located below these paths, possibly in subdirectories of these paths.
pointer LoadModule(const char *module, const char *path,
const char **subdirlist, const char **patternlist,
pointer options, const XF86ModReqInfo * modreq,
int *errmaj, int *errmin)The
LoadModule()function loads the module calledmodule. The return value is a module handle, and may be used in future calls to the loader that require a reference to a loaded module. The module namemoduleis normally the module's canonical name, which doesn't contain any directory path information, or any object/library file prefixes of suffixes. Currently a full pathname and/or filename is also accepted. This might change. The other parameters are:
pathAn optional comma-separated list of module search paths. When
NULL, the default search path is used.
subdirlistAn optional
NULLterminated list of subdirectories to search. WhenNULL, the default built-in list is used (refer tostdSubdirsinloadmod.c). The default list is also substituted for entries insubdirlistwith the valueDEFAULT_LIST. This makes is possible to augment the default list instead of replacing it. Subdir elements must be relative, and must not contain"..". If any violate this requirement, the load fails.
patternlistAn optional
NULLterminated list of POSIX regular expressions used to connect module filenames with canonical module names. Each regex should contain exactly one subexpression that corresponds to the canonical module name. WhenNULL, the default built-in list is used (refer tostdPatternsinloadmod.c). The default list is also substituted for entries inpatternlistwith the valueDEFAULT_LIST. This makes it possible to augment the default list instead of replacing it.
optionsAn optional parameter that is passed to the newly loaded module's
SetupProcfunction (if it has one). This argument is normally aNULLterminated list ofOptions, and must be interpreted that way by modules loaded directly by the XFree86 common layer. However, it may be used for application-specific parameter passing in other situations.When loading ``external'' modules (modules that don't have the the standard entry point, for example a special shared library) the options parameter can be set to
EXTERN_MODULEto tell the loader not to reject the module when it doesn't find the standard entry point.
modreqAn optional
XF86ModReqInfo*containing version/ABI/vendor information to requirements to check the newly loaded module against. The main purpose of this is to allow the loader to verify that a module of the correct type/version before running itsSetupProcfunction.The
XF86ModReqInfostruct is defined as follows:typedef struct { CARD8 majorversion; /* MAJOR_UNSPEC */ CARD8 minorversion; /* MINOR_UNSPEC */ CARD16 patchlevel; /* PATCH_UNSPEC */ const char * abiclass; /* ABI_CLASS_NONE */ CARD32 abiversion; /* ABI_VERS_UNSPEC */ const char * moduleclass; /* MOD_CLASS_NONE */ } XF86ModReqInfo;The information here is compared against the equivalent information in the module's
XF86ModuleVersionInforecord (which is described below). The values in comments above indicate ``don't care'' settings for each of the fields. The comparisons made are as follows:
majorversionMust match the module's majorversion exactly.
minorversionThe module's minor version must be no less than this value. This comparison is only made if
majorversionis specified and matches.patchlevelThe module's patchlevel must be no less than this value. This comparison is only made if
minorversionis specified and matches.abiclassString must match the module's abiclass string.
abiversionMust be consistent with the module's abiversion (major equal, minor no older).
moduleclassString must match the module's moduleclass string.
errmajAn optional pointer to a variable holding the major part or the error code. When provided, it
*errmajis filled in whenLoadModule()fails.
errminLike
errmaj, but for the minor part of the error code.
void UnloadModule(pointer mod)This function unloads the module referred to by the handle mod. All child modules are also unloaded recursively. This function must not be used to directly unload modules that are child modules (i.e., those that have been loaded with
LoadSubModule()).
Modules must provide information about themselves to the loader, and
may optionally provide entry points for "setup" and "teardown" functions
(those two functions are referred to here as SetupProc
and TearDownProc).
The module information is contained in the
XF86ModuleVersionInfo struct, which is defined as follows:
typedef struct { const char * modname; /* name of module, e.g. "foo" */ const char * vendor; /* vendor specific string */ CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ CARD32 _modinfo2_; /* infoarea with a binary editor/sign tool */ CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ CARD8 majorversion; /* module-specific major version */ CARD8 minorversion; /* module-specific minor version */ CARD16 patchlevel; /* module-specific patch level */ const char * abiclass; /* ABI class that the module uses */ CARD32 abiversion; /* ABI version */ const char * moduleclass; /* module class */ CARD32 checksum[4]; /* contains a digital signature of the */ /* version info structure */ } XF86ModuleVersionInfo;The fields are used as follows:
modnameThe module's name. This field is currently only for informational purposes, but the loader may be modified in future to require it to match the module's canonical name.
vendorThe module vendor. This field is for informational purposes only.
_modinfo1_This field holds the first part of a signature that can be used to locate this structure in the binary. It should always be initialised to
MODINFOSTRING1.
_modinfo2_This field holds the second part of a signature that can be used to locate this structure in the binary. It should always be initialised to
MODINFOSTRING2.
xf86versionThe XFree86 version against which the module was compiled. This is mostly for informational/diagnostic purposes. It should be initialised to
XF86_VERSION_CURRENT, which is defined inxf86Version.h.
majorversionThe module-specific major version. For modules where this version is used for more than simply informational purposes, the major version should only change (be incremented) when ABI incompatibilities are introduced, or ABI components are removed.
minorversionThe module-specific minor version. For modules where this version is used for more than simply informational purposes, the minor version should only change (be incremented) when ABI additions are made in a backward compatible way. It should be reset to zero when the major version is increased.
patchlevelThe module-specific patch level. The patch level should increase with new revisions of the module where there are no ABI changes, and it should be reset to zero when the minor version is increased.
abiclassThe ABI class that the module requires. The class is specified as a string for easy extensibility. It should indicate which (if any) of the X server's built-in ABI classes that the module relies on, or a third-party ABI if appropriate. Built-in ABI classes currently defined are:
ABI_CLASS_NONEno classABI_CLASS_ANSIConly requires the ANSI C interfacesABI_CLASS_VIDEODRVrequires the video driver ABIABI_CLASS_XINPUTrequires the XInput driver ABIABI_CLASS_EXTENSIONrequires the extension module ABIABI_CLASS_FONTrequires the font module ABI
abiversionThe version of abiclass that the module requires. The version consists of major and minor components. The major version must match and the minor version must be no newer than that provided by the server or parent module. Version identifiers for the built-in classes currently defined are:
ABI_ANSIC_VERSION
ABI_VIDEODRV_VERSION
ABI_XINPUT_VERSION
ABI_EXTENSION_VERSION
ABI_FONT_VERSION
moduleclassThis is similar to the abiclass field, except that it defines the type of module rather than the ABI it requires. For example, although all video drivers require the video driver ABI, not all modules that require the video driver ABI are video drivers. This distinction can be made with the moduleclass. Currently pre-defined module classes are:
MOD_CLASS_NONE
MOD_CLASS_VIDEODRV
MOD_CLASS_XINPUT
MOD_CLASS_FONT
MOD_CLASS_EXTENSION
checksumNot currently used.
The module version information, and the optional SetupProc
and TearDownProc entry points are found by the loader
by locating a data object in the module called "modnameModuleData",
where "modname" is the canonical name of the module. Modules must
contain such a data object, and it must be declared with global scope,
be compile-time initialised, and is of the following type:
typedef struct {
XF86ModuleVersionInfo * vers;
ModuleSetupProc setup;
ModuleTearDownProc teardown;
} XF86ModuleData;
The vers parameter must be initialised to a pointer to a correctly
initialised XF86ModuleVersionInfo struct. The other
two parameter are optional, and should be initialised to
NULL when not required. The other parameters are defined
as
typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *)
typedef void (*ModuleTearDownProc)(pointer)
pointer SetupProc(pointer module, pointer options,
int *errmaj, int *errmin)When defined, this function is called by the loader after successfully loading a module. module is a handle for the newly loaded module, and maybe used by the
SetupProcif it calls other loader functions that require a reference to it. The remaining arguments are those that were passed to theLoadModule()(orLoadSubModule()), and are described above. When theSetupProcis successful it must return a non-NULLvalue. The loader checks this, and if it isNULLit unloads the module and reports the failure to the caller ofLoadModule(). If theSetupProcdoes things that need to be undone when the module is unloaded, it should define aTearDownProc, and return a pointer that theTearDownProccan use to undo what has been done.When a module is loaded multiple times, the
SetupProcis called once for each time it is loaded.
void TearDownProc(pointer tearDownData)When defined, this function is called when the loader unloads a module. The
tearDownDataparameter is the return value of theSetupProc()that was called when the module was loaded. The purpose of this function is to clean up before the module is unloaded (for example, by freeing allocated resources).
The following is the Loader interface that is available to any part of the server, and may also be used from within modules.
pointer LoadSubModule(pointer parent, const char *module,
const char **subdirlist, const char **patternlist,
pointer options, const XF86ModReqInfo * modreq,
int *errmaj, int *errmin)This function is like the
LoadModule()function described above, except that the module loaded is registered as a child of the calling module. Theparentparameter is the calling module's handle. Modules loaded with this function are automatically unloaded when the parent module is unloaded. The other difference is that the path parameter may not be specified. The module search path used for modules loaded with this function is the default search path as initialised withLoaderSetPath().
void UnloadSubModule(pointer module)This function unloads the module with handle
module. If that module itself has children, they are also unloaded. It is likeLoadModule(), except that it is safe to use for unloading child modules.
pointer LoaderSymbol(const char *symbol)This function returns the address of the symbol with name
symbol. This may be used to locate a module entry point with a known name.
char **LoaderlistDirs(const char **subdirlist,
const char **patternlist)This function returns a
NULLterminated list of canonical modules names for modules found in the default module search path. Thesubdirlistandpatternlistparameters are as described above, and can be used to control the locations and names that are searched. If no modules are found, the return value isNULL. The returned list should be freed by callingLoaderFreeDirList()when it is no longer needed.
void LoaderFreeDirList(char **list)This function frees a module list created by
LoaderlistDirs().
void LoaderReqSymLists(const char **list0, ...)This function allows the registration of required symbols with the loader. It is normally used by a caller of
LoadSubModule(). If any symbols registered in this way are found to be unresolved whenLoaderCheckUnresolved()is called thenLoaderCheckUnresolved()will report a failure. The function takes one or moreNULLterminated lists of symbols. The end of the argument list is indicated by aNULLargument.
void LoaderReqSymbols(const char *sym0, ...)This function is like
LoaderReqSymLists()except that its arguments are symbols rather than lists of symbols. This function is more convenient when single functions are to be registered, especially when the single function might depend on runtime factors. The end of the argument list is indicated by aNULLargument.
void LoaderRefSymLists(const char **list0, ...)This function allows the registration of possibly unresolved symbols with the loader. When
LoaderCheckUnresolved()is run it won't generate warnings for symbols registered in this way unless they were also registered as required symbols.
void LoaderRefSymbols(const char *sym0, ...)This function is like
LoaderRefSymLists()except that its arguments are symbols rather than lists of symbols. This function is more convenient when single functions are to be registered, especially when the single function might depend on runtime factors. The end of the argument list is indicated by aNULLargument.
int LoaderCheckUnresolved(int delayflag)This function checks for unresolved symbols. It generates warnings for unresolved symbols that have not been registered with
LoaderRefSymLists(), and maps them to a dummy function. This behaviour may change in future. If unresolved symbols are found that have been registered withLoaderReqSymLists()orLoaderReqSymbols()then this function returns a non-zero value. If none of these symbols are unresolved the return value is zero, indicating success.The
delayflagparameter should normally be set toLD_RESOLV_IFDONE.
LoaderErrorMsg(const char *name, const char *modname,
int errmaj, int errmin)This function prints an error message that includes the text ``Failed to load module'', the module name
modname, a message specific to theerrmajvalue, and the value iferrmin. Ifnameis non-NULL, it is printed as an identifying prefix to the message (followed by a `:').
The loader contains some functions for registering some classes of modules. These may be moved out of the loader at some point.
void LoadExtension(ExtensionModule *ext)This registers the entry points for the extension identified by
ext. TheExtensionModulestruct is defined as:
typedef struct { InitExtension initFunc; char * name; Bool *disablePtr; InitExtension setupFunc; } ExtensionModule;
void LoadFont(FontModule *font)This registers the entry points for the font rasteriser module identified by
font. TheFontModulestruct is defined as:
typedef struct { InitFont initFunc; char * name; pointer module; } FontModule;