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 remains 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
56 @code{FOREIGN-SYMBOL-ADDRESS-AS-INTEGER} take an optional datap
57 argument, used to indicate that the symbol refers to a variable. In
58 similar fashion there is a new kind of fixup and a new VOP:
59 @code{:FOREIGN-DATAREF} and @code{FOREIGN-SYMBOL-DATAREF-ADDRESS}. The
60 @code{DATAP} argument is automagically provided by the alien interface
61 for normal definitions, but is really needed only for dynamic foreign
62 variables. For those it indicates the need for the indirection either
63 within a conditional branch in @code{FOREIGN-SYMBOL-ADDRESS}, or via
64 @code{:FOREIGN-DATAREF} fixup and
65 @code{FOREIGN-SYMBOL-DATAREF-ADDRESS} 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-ADDRESS} and
71 friends now have the potential side-effect of entering information in
72 @code{*LINKAGE-INFO*} and the linkage-table proper: hence it's important to
73 use the correct datap argument even if calling these just to "check if
74 it's there" (like SB-POSIX does).
78 @subsubsection Porting to new operating systems
80 Find a memory area for the linkage-table, and add it for the OS in
81 @file{src/compiler/target/parms.lisp} by defining
82 @code{SB!VM:LINKAGE-TABLE-SPACE-START} and
83 @code{SB!VM:LINKAGE-TABLE-SPACE-END}. See existing ports and CMUCL for
86 @subsubsection Porting to new architextures
88 Write @code{arch_write_linkage_table_jmp} and @code{arch_write_linkage_table_ref}.
90 Write @code{FOREIGN-SYMBOL-DATAREF} VOP.
92 Define correct @code{SB!VM:LINKAGE-TABLE-ENTRY-SIZE} in
93 @file{src/compiler/target/parms.lisp}.
96 @node Lazy Alien Resolution
97 @comment node-name, next, previous, up
98 @section Lazy Alien Resolution
100 On linkage-table ports SBCL is able to deal with forward-references to
101 aliens -- which is to say, compile and load code referring to aliens
102 before the shared object containing the alien in question has been
105 This is handled by @code{GET-DYNAMIC-FOREIGN-SYMBOL-ADDRESS}, which
106 first tries to resolve the address in the loaded shared objects, but
107 failing that records the alien as undefined and returns the address of
108 a read/write/execute protected guard page for variables, and address
109 of @code{undefined_alien_function} for routines. These are in turn
110 responsible for catching attempts to access the undefined alien, and
111 signalling the appropriate error.
113 These placeholder addresses get recorded in the linkage-table.
115 When new shared objects are loaded @code{UPDATE-LINKAGE-TABLE} is
116 called, which in turn attempts to resolve all currently undefined
117 aliens, and registers the correct addresses for them in the
122 @comment node-name, next, previous, up
125 SBCL is capable of providing C with linkage to Lisp -- the upshot of which is that
126 C-functions can call Lisp functions thru what look like function pointers to C.
128 These ``function pointers'' are called Alien Callbacks. An alien
129 callback sequence has 4 parts / stages / bounces:
132 @item Assembler Wrapper
134 saves the arguments from the C-call according to the alien-fun-type of
135 the callback, and calls #'ENTER-ALIEN-CALLBACK with the index
136 indentifying the callback, a pointer to the arguments copied on the
137 stack and a pointer to return value storage. When control returns to
138 the wrapper it returns the value to C. There is one assembler wrapper
139 per callback.[1] The SAP to the wrapper code vector is what is passed
140 to foreign code as a callback.
142 The Assembler Wrapper is generated by
143 @code{ALIEN-CALLBACK-ASSEMBLER-WRAPPER}.
145 @item #'ENTER-ALIEN-CALLBACK
147 pulls the Lisp Trampoline for the given index, and calls it with the
148 argument and result pointers.
150 @item Lisp Trampoline
152 calls the Lisp Wrapper with the argument and result pointers, and the
153 function designator for the callback. There is one lisp trampoline per
158 parses the arguments from stack, calls the actual callback with the
159 arguments, and saves the return value at the result pointer. The lisp
160 wrapper is shared between all the callbacks having the same same
165 [1] As assembler wrappers need to be allocated in static addresses and
166 are (in the current scheme of things) never released it might be worth
167 it to split it into two parts: per-callback trampoline that pushes the
168 index of the lisp trampoline on the stack, and jumps to the
169 appropriate assembler wrapper. The assembler wrapper could then be
170 shared between all the callbacks with the same alien-fun-type. This
171 would amortize most of the static allocation costs between multiple