0.8.18.14:
[sbcl.git] / src / code / foreign.lisp
1 ;;;; Foreign symbol linkage
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!IMPL")
13
14 ;;; *STATIC-FOREIGN-SYMBOLS* are static as opposed to "dynamic" (not
15 ;;; as opposed to C's "extern"). The table contains symbols known at
16 ;;; the time that the program was built, but not symbols defined in
17 ;;; object files which have been loaded dynamically since then.
18 (declaim (type hash-table *static-foreign-symbols*))
19 (defvar *static-foreign-symbols* (make-hash-table :test 'equal))
20
21 (defun find-foreign-symbol-in-table (name table)
22   (some (lambda (prefix)
23           (gethash (concatenate 'string prefix name) table))
24         #("" "ldso_stub__")))
25
26 (defun foreign-symbol-address-as-integer-or-nil (name &optional datap)
27   (declare (ignorable datap))
28   (or (find-foreign-symbol-in-table name  *static-foreign-symbols*)
29       #!+os-provides-dlopen
30       (progn
31         #-sb-xc-host
32         (values #!-linkage-table
33                 (get-dynamic-foreign-symbol-address name)
34                 #!+linkage-table
35                 (ensure-foreign-symbol-linkage name datap)
36                 t))))
37
38 (defun foreign-symbol-address-as-integer (name &optional datap)
39   (or (foreign-symbol-address-as-integer-or-nil name datap)
40       (error "Unknown foreign symbol: ~S" name)))
41
42 (defun foreign-symbol-address (symbol &optional datap)
43   (declare (ignorable datap))
44   (let ((name (sb!vm:extern-alien-name symbol)))
45     #!-linkage-table
46     (int-sap (foreign-symbol-address-as-integer name))
47     #!+linkage-table
48     (multiple-value-bind (addr sharedp)
49         (foreign-symbol-address-as-integer name datap)
50       #+sb-xc-host
51       (aver (not sharedp))
52       ;; If the address is from linkage-table and refers to data
53       ;; we need to do a bit of juggling.
54       (if (and sharedp datap)
55           (int-sap (sap-ref-word (int-sap addr) 0))
56           (int-sap addr)))))
57
58 #-sb-xc-host
59 (defun foreign-reinit ()
60   #!+os-provides-dlopen
61   (reopen-shared-objects)
62   #!+linkage-table
63   (update-linkage-table))
64
65 ;;; Cleanups before saving a core
66 #-sb-xc-host
67 (defun foreign-deinit ()
68   ;; KLUDGE: Giving this warning only when non-static foreign symbols
69   ;; are used would be much nicer, but actually pretty hard: we can
70   ;; get dynamic symbols thru the runtime as well, so cheking the
71   ;; list of *shared-objects* is not enough. Eugh & blech.
72   #!+(and os-provides-dlopen (not linkage-table))
73   (when (dynamic-foreign-symbols)
74     (warn "~@<Saving cores with alien definitions referring to non-static ~
75            foreign symbols is unsupported on this platform: references to ~
76            such foreign symbols from the restarted core will not work. You ~
77            may be able to work around this limitation by reloading all ~
78            foreign definitions and code using them in the restarted core, ~
79            but no guarantees.~%~%Dynamic foreign symbols in this core: ~
80            ~{~A~^, ~}~:@>" (dynamic-foreign-symbols)))
81   #!+os-provides-dlopen
82   (close-shared-objects))
83
84 (defun foreign-symbol-in-address (sap)
85   (declare (ignorable sap))
86   #-sb-xc-host
87   (let ((addr (sap-int sap)))
88     (declare (ignorable addr))
89     #!+linkage-table
90     (when (<= sb!vm:linkage-table-space-start
91               addr
92               sb!vm:linkage-table-space-end)
93       (maphash (lambda (name info)
94                  (let ((table-addr (linkage-info-address info)))
95                    (when (<= table-addr
96                              addr
97                              (+ table-addr sb!vm:linkage-table-entry-size))
98                      (return-from foreign-symbol-in-address name))))
99                *linkage-info*))
100     #!+os-provides-dladdr
101     (with-alien ((info (struct dl-info
102                                (filename c-string)
103                                (base unsigned)
104                                (symbol c-string)
105                                (symbol-address unsigned)))
106                  (dladdr (function unsigned unsigned (* (struct dl-info)))
107                          :extern "dladdr"))
108       (let ((err (alien-funcall dladdr addr (addr info))))
109         (if (zerop err)
110             nil
111             (slot info 'symbol))))
112     ;; FIXME: Even in the absence of dladdr we could search the
113     ;; static foreign symbols (and *linkage-info*, for that matter).
114     ))
115
116 ;;; How we learn about foreign symbols and dlhandles initially
117 (defvar *!initial-foreign-symbols*)
118
119 #-sb-xc-host
120 (defun !foreign-cold-init ()
121   (dolist (symbol *!initial-foreign-symbols*)
122     (setf (gethash (car symbol) *static-foreign-symbols*) (cdr symbol)))
123   #!+os-provides-dlopen
124   (setf *runtime-dlhandle* (dlopen-or-lose)
125         *shared-objects* nil))
126
127 #!-os-provides-dlopen
128 (define-unsupported-fun load-shared-object)