2 @comment node-name, next, previous, up
3 @chapter Foreign Linkage
7 * Lazy Alien Resolution::
12 @comment node-name, next, previous, up
13 @section Linkage-table
15 Linkage-table allows saving cores with foreign code loaded, and is
16 also utilized to allow references to as-of-yet unknown aliens.
17 @xref{Lazy Alien Resolution}.
19 The SBCL implementation is somewhat simplified from the CMUCL one by
20 Timothy Moore, but the basic idea and mechanism remain identical:
21 instead of having addresses from @code{dlsym(3)} in the core, we have
22 addresses to an mmapped memory area (@code{LINKAGE_TABLE_SPACE}) that
23 is initialized at startup to contain jumps & references to the correct
24 addresses, based on information stored on the lisp side in
25 @code{*LINKAGE-INFO*}.
27 @subsection Differences to CMUCL
29 CMUCL does lazy linkage for code, keeps all foreign addresses in the
30 linkage-table, and handles the initialization from C. We do eager
31 linkage for everything, maintain a separate
32 @code{*STATIC-FOREIGN-SYMBOLS*} just like on non-linkage-table ports
33 (this allows more code sharing between ports, makes thread-safety
34 easier to achieve, and cuts one jump's worth of overhead from stuff
35 like closure_tramp), and do the initialization from lisp.
37 @subsection Nitty Gritty Details
39 Symbols in @code{*STATIC-FOREIGN-SYMBOLS*} are handled the old
40 fashioned way: linkage-table is only used for symbols resolved with
43 On system startup @code{FOREIGN-REINIT} iterates through the
44 @code{*LINKAGE-INFO*}, which is a hash-table mapping dynamic foreign
45 names to @code{LINKAGE-INFO} structures, and calls
46 @code{arch_write_linkage_table_jmp}@code{/ref} to write the
47 appropriate entries to the linkage-table.
49 When a foreign symbol is referred to, it is first looked for in the
50 @code{*STATIC-FOREIGN-SYMBOLS*}. If not found,
51 @code{ENSURE-FOREIGN-LINKAGE} is called, which looks for the
52 corresponding entry in @code{*LINKAGE-INFO*}, creating one and writing
53 the appropriate entry in the linkage table if necessary.
55 @code{FOREIGN-SYMBOL-ADDRESS} and @code{FOREIGN-SYMBOL-SAP} take an
56 optional datap argument, used to indicate that the symbol refers to a
57 variable. In similar fashion there is a new kind of fixup and a new
58 VOP: @code{:FOREIGN-DATAREF} and @code{FOREIGN-SYMBOL-DATAREF-SAP}.
60 The @code{DATAP} argument is automagically provided by the alien
61 interface for normal definitions, but is really needed only for
62 dynamic foreign variables. For those it indicates the need for the
63 indirection either within a conditional branch in
64 @code{FOREIGN-SYMBOL-SAP}, or via @code{:FOREIGN-DATAREF} fixup and
65 @code{FOREIGN-SYMBOL-DATAREF-SAP} VOP: "this address holds the
66 address of the foreign variable, not the variable itself". Within SBCL
67 itself (in the fixups manifest in various VOPs) this fixup type is
68 never used, as all foreign symbols used internally are static.
70 One thing worth noting is that @code{FOREIGN-SYMBOL-SAP} and friends
71 now have the potential side-effect of entering information in
72 @code{*LINKAGE-INFO*} and the linkage-table proper. If the usage case
73 is about checking if the symbol is available use
74 @code{FIND-FOREIGN-SYMBOL-ADDRESS}, which is side-effect free. (This
79 @subsubsection Porting to new operating systems
81 Find a memory area for the linkage-table, and add it for the OS in
82 @file{src/compiler/target/parms.lisp} by defining
83 @code{SB!VM:LINKAGE-TABLE-SPACE-START} and
84 @code{SB!VM:LINKAGE-TABLE-SPACE-END}. See existing ports and CMUCL for
87 @subsubsection Porting to new architectures
89 Write @code{arch_write_linkage_table_jmp} and @code{arch_write_linkage_table_ref}.
91 Write @code{FOREIGN-SYMBOL-DATAREF} VOP.
93 Define correct @code{SB!VM:LINKAGE-TABLE-ENTRY-SIZE} in
94 @file{src/compiler/target/parms.lisp}.
97 @node Lazy Alien Resolution
98 @comment node-name, next, previous, up
99 @section Lazy Alien Resolution
101 On linkage-table ports SBCL is able to deal with forward-references to
102 aliens -- which is to say, compile and load code referring to aliens
103 before the shared object containing the alien in question has been
106 This is handled by @code{ENSURE-DYNAMIC-FOREIGN-SYMBOL-ADDRESS}, which
107 first tries to resolve the address in the loaded shared objects, but
108 failing that records the alien as undefined and returns the address of
109 a read/write/execute protected guard page for variables, and address
110 of @code{undefined_alien_function} for routines. These are in turn
111 responsible for catching attempts to access the undefined alien, and
112 signalling the appropriate error.
114 These placeholder addresses get recorded in the linkage-table.
116 When new shared objects are loaded @code{UPDATE-LINKAGE-TABLE} is
117 called, which in turn attempts to resolve all currently undefined
118 aliens, and registers the correct addresses for them in the
123 @comment node-name, next, previous, up
126 SBCL is capable of providing C with linkage to Lisp -- the upshot of which is that
127 C-functions can call Lisp functions thru what look like function pointers to C.
129 These ``function pointers'' are called Alien Callbacks. An alien
130 callback sequence has 4 parts / stages / bounces:
133 @item Assembler Wrapper
135 saves the arguments from the C-call according to the alien-fun-type of
136 the callback, and calls #'ENTER-ALIEN-CALLBACK with the index
137 indentifying the callback, a pointer to the arguments copied on the
138 stack and a pointer to return value storage. When control returns to
139 the wrapper it returns the value to C. There is one assembler wrapper
140 per callback.[1] The SAP to the wrapper code vector is what is passed
141 to foreign code as a callback.
143 The Assembler Wrapper is generated by
144 @code{ALIEN-CALLBACK-ASSEMBLER-WRAPPER}.
146 @item #'ENTER-ALIEN-CALLBACK
148 pulls the Lisp Trampoline for the given index, and calls it with the
149 argument and result pointers.
151 @item Lisp Trampoline
153 calls the Lisp Wrapper with the argument and result pointers, and the
154 function designator for the callback. There is one lisp trampoline per
159 parses the arguments from stack, calls the actual callback with the
160 arguments, and saves the return value at the result pointer. The lisp
161 wrapper is shared between all the callbacks having the same same
166 [1] As assembler wrappers need to be allocated in static addresses and
167 are (in the current scheme of things) never released it might be worth
168 it to split it into two parts: per-callback trampoline that pushes the
169 index of the lisp trampoline on the stack, and jumps to the
170 appropriate assembler wrapper. The assembler wrapper could then be
171 shared between all the callbacks with the same alien-fun-type. This
172 would amortize most of the static allocation costs between multiple