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.
NOTE: Now that ISO-C allows pointers to functions and pointers to data to have different internal representations, some of the following interfaces will need to be revisited.
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 pathpath
must 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 namemodule
is 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:
path
An optional comma-separated list of module search paths. When
NULL
, the default search path is used.
subdirlist
An optional
NULL
terminated list of subdirectories to search. WhenNULL
, the default built-in list is used (refer tostdSubdirs
inloadmod.c
). The default list is also substituted for entries insubdirlist
with 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.
patternlist
An optional
NULL
terminated 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 tostdPatterns
inloadmod.c
). The default list is also substituted for entries inpatternlist
with the valueDEFAULT_LIST
. This makes it possible to augment the default list instead of replacing it.
options
An optional parameter that is passed to the newly loaded module's
SetupProc
function (if it has one). This argument is normally aNULL
terminated 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 standard entry point, for example a special shared library) the options parameter can be set to
EXTERN_MODULE
to tell the loader not to reject the module when it doesn't find the standard entry point.
modreq
An 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 itsSetupProc
function.The
XF86ModReqInfo
struct 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
XF86ModuleVersionInfo
record (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:
majorversion
Must match the module's majorversion exactly.
minorversion
The module's minor version must be no less than this value. This comparison is only made if
majorversion
is specified and matches.patchlevel
The module's patchlevel must be no less than this value. This comparison is only made if
minorversion
is specified and matches.abiclass
String must match the module's abiclass string.
abiversion
Must be consistent with the module's abiversion (major equal, minor no older).
moduleclass
String must match the module's moduleclass string.
errmaj
An optional pointer to a variable holding the major part or the error code. When provided,
*errmaj
is filled in whenLoadModule()
fails.
errmin
Like
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 the
LoadSubModule()
described below).
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:
modname
The 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.
vendor
The 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
.
xf86version
The 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
.
majorversion
The 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.
minorversion
The 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.
patchlevel
The 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.
abiclass
The 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_NONE
no classABI_CLASS_ANSIC
only requires the ANSI C interfacesABI_CLASS_VIDEODRV
requires the video driver ABIABI_CLASS_XINPUT
requires the XInput driver ABIABI_CLASS_EXTENSION
requires the extension module ABIABI_CLASS_FONT
requires the font module ABI
abiversion
The 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
moduleclass
This 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
checksum
Not 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
SetupProc
if 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 theSetupProc
is successful it must return a non-NULL
value. The loader checks this, and if it isNULL
it unloads the module and reports the failure to the caller ofLoadModule()
. If theSetupProc
does things that need to be undone when the module is unloaded, it should define aTearDownProc
, and return a pointer that theTearDownProc
can use to undo what has been done.When a module is loaded multiple times, the
SetupProc
is 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
tearDownData
parameter 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. Theparent
parameter 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 likeUnloadModule()
, 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
NULL
terminated list of canonical modules names for modules found in the default module search path. Thesubdirlist
andpatternlist
parameters 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 moreNULL
terminated lists of symbols. The end of the argument list is indicated by aNULL
argument.
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 aNULL
argument.
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. The function takes one or moreNULL
terminated lists of symbols. The end of the argument list is indicated by aNULL
argument.
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 aNULL
argument.
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
delayflag
parameter 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 theerrmaj
value, and the value iferrmin
. Ifname
is 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
. TheExtensionModule
struct 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
. TheFontModule
struct is defined as:
typedef struct { InitFont initFunc; char * name; pointer module; } FontModule;