Artifact ID: | dc06d68d3f64b11a7ab063125b940b779185b0a8919cd6c9cbfe5ed8b16bdd4c |
---|---|
Page Name: | XVFS Build Walkthrough |
Date: | 2019-09-17 19:53:08 |
Original User: | rkeene |
Mimetype: | text/x-markdown |
Parent: | ad09df452f38181cd402a33b90b86a073a58a06512117f6a394e1ec9a074488d (diff) |
Next | 66e72f878f3bd9873f3032d4caf2c2443b818664dfa9f26eca239fc93cd110eb |
XVFS Build Walkthrough
xvfs-create
The script "xvfs-create
" which is referenced below creates a C source file containing
a local static structure and an Xvfs_<name>_Init()
symbol. The C source file contains
all the data from the specified directory, file names, contents, sizes, directory
children. This C file can be compiled in a few different ways ("Client", "Standalone",
and "Flexible") covered below.
"Server"
Description
The "Server" mode is a single in-process handler for "//xvfs:/
" and additional clients
can call Xvfs_Register()
to register their filesystem with that handler. This has the
advantage of being more efficient since there are not one Tcl_Filesystem
per extension
which have to all be searched through but instead a single handler which uses a
Tcl_HashTable
to map the namespace to things which have called Xvfs_Register()
.
The "Server" mode thus has 2 symbols:
Xvfs_Init()
which initializes theTcl_Filesystem
for all of "//xvfs:/
" as well as setup the emptyTcl_HashTable
Xvfs_Register()
which is for other extensions to call to register their name under "//xvfs:/
"
Build Output
$ make xvfs.so
cc -I. -DUSE_TCL_STUBS=1 -DXVFS_DEBUG -I/usr/include -DXVFS_MODE_SERVER -fPIC -g3 -ggdb3 -Wall -o xvfs.o -c xvfs-core.c
cc -fPIC -g3 -ggdb3 -Wall -shared -o xvfs.so xvfs.o -L/usr/lib64 -ltclstub8.6
$ nm -D xvfs.so | grep ' [TU] '
0000000000004a07 T Xvfs_Init
0000000000004c6a T Xvfs_Register
U fprintf
U memcmp
U memcpy
U stderr
U strchr
Here we can see that indeed the only defined symbols for relocation are
Xvfs_Init()
and Xvfs_Register()
, as well as some undefined symbols which we
rely on. The symbols fprintf()
and stderr
are only used for debugging and
would not be required in a production build.
"Client"
Description
The "Client" mode is very simple. It converts the specified directory ("example")
into a C source file where all of the files contents and all directories children
are structures of a local static structure. Then a Xvfs_example_Init()
function
is created which call Xvfs_Register()
pointing to this structure (actually it
points to some handlers so that the structure can change over time without relying
on the core to be adaptable).
The "Client" mode thus exports a single symbol, Xvfs_<name>_Init()
, and relies
on a single symbol from the "Server" mode, Xvfs_Register()
.
Once you [load]
this extension the Xvfs_example_Init()
function is called and
the VFS is registered under //xvfs:/example
for all interpreters in this
process.
Build Output
$ make example-client.so
./xvfs-create --directory example --name example > example.c.new
mv example.c.new example.c
cc -I. -DUSE_TCL_STUBS=1 -DXVFS_DEBUG -I/usr/include -DXVFS_MODE_CLIENT -fPIC -g3 -ggdb3 -Wall -o example-client.o -c example.c
cc -fPIC -g3 -ggdb3 -Wall -shared -o example-client.so example-client.o -L/usr/lib64 -ltclstub8.6
$ nm -D example-client.so | grep ' [TU] '
U Xvfs_Register
0000000000000ed5 T Xvfs_example_Init
U memcmp
U strlen
"Standalone"
Description
The "Standalone" mode is a logically combined "Client" and "Server" mode. However, it does not check
for anything already handling "//xvfs:/
" and always registers its own Tcl_Filesystem
handling only //xvfs:/<name>
. It does not export an Xvfs_Register()
function and is
completely standalone (hence the name).
It will work and can be [load]d
on any version of Tcl, the same as "Client" mode but with no external
dependencies on the "Server" mode.
The "Standalone" mode thus exports a single symbol, Xvfs_<name>_Init()
.
Build Output
$ make example-standalone.so
./xvfs-create --directory example --name example > example.c.new
mv example.c.new example.c
cc -I. -DUSE_TCL_STUBS=1 -DXVFS_DEBUG -I/usr/include -DXVFS_MODE_STANDALONE -fPIC -g3 -ggdb3 -Wall -o example-standalone.o -c example.c
cc -fPIC -g3 -ggdb3 -Wall -shared -o example-standalone.so example-standalone.o -L/usr/lib64 -ltclstub8.6
$ nm -D example-standalone.so | grep ' [TU] '
0000000000004d26 T Xvfs_example_Init
U fprintf
U memcmp
U memcpy
U stderr
U strlen
"Flexible"
Description
The "Flexible" mode is a combination of "Standalone" and "Client modes. It will search for an existing
handler of "//xvfs:/
" and if so call that handler's Xvfs_Register()
function. If no such handler exists
it will invoke the same handler as "Standalone" mode and register its own Tcl_Filesystem
.
Because we cannot be linked with an undefined symbol to Xvfs_Register()
the "Flexible" mode does not
use the run-time linker to find the symbol for Xvfs_Register()
but rather works with the Tcl VFS
layer to locate that symbol dynamically.
The "Flexible" mode thus exports a single symbol, Xvfs_<name>_Init()
and has no hard requirements
on dependent symbols, however the "Server" mode's Xvfs_Register()
will be called if its
Xvfs_Init()
function has been called previously to register a handler for //xvfs:/
.
Build Output
$ make example-flexible.so
./xvfs-create --directory example --name example > example.c.new
mv example.c.new example.c
cc -I. -DUSE_TCL_STUBS=1 -DXVFS_DEBUG -I/usr/include -DXVFS_MODE_FLEXIBLE -fPIC -g3 -ggdb3 -Wall -o example-flexible.o -c example.c
cc -fPIC -g3 -ggdb3 -Wall -shared -o example-flexible.so example-flexible.o -L/usr/lib64 -ltclstub8.6
$ nm -D example-flexible.so | grep ' [TU] '
00000000000050c8 T Xvfs_example_Init
U fprintf
U memcmp
U memcpy
U stderr
U strlen