[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sbcl-devel
Subject:    [Sbcl-devel] [PATCH 3/4] Support #+(and linkage-table (not os-provides-dlopen))
From:       Eric Timmons <etimmons () mit ! edu>
Date:       2020-07-13 20:02:35
Message-ID: 20200713200236.22507-4-etimmons () mit ! edu
[Download RAW message or body]

Add a new C function - arch_read_linkage_entry - that backs out the true
foreign address of the corresponding symbol from the data in the linkage table.

Add a Lisp function - FIND-FOREIGN-SYMBOL-ADDRESS-FROM-LINKAGE-TABLE - that
uses this new C function to return the address, while accounting for undefined
symbols (so as to not accidentally return a reference to a guard page).

Teach FIND-FOREIGN-SYMBOL-ADDRESS to use
FIND-FOREIGN-SYMBOL-ADDRESS-FROM-LINKAGE-TABLE when libdl is not
available. Replace all calls to FIND-DYNAMIC-FOREIGN-SYMBOL-ADDRESS with
FIND-FOREIGN-SYMBOL-ADDRESS as the former is not available on
-os-provides-dlopen and the latter correctly falls back the the best option
based on *FEATURES*.
---
 contrib/sb-bsd-sockets/sb-bsd-sockets.asd |  2 +-
 package-data-list.lisp-expr               |  1 +
 src/code/debug-int.lisp                   |  2 +-
 src/code/foreign.lisp                     |  5 ++-
 src/code/linkage-table.lisp               | 22 +++++++++++--
 src/compiler/target-main.lisp             |  2 +-
 src/runtime/Config.alpha-linux            |  6 +++-
 src/runtime/Config.arm-android            |  6 +++-
 src/runtime/Config.arm-linux              |  6 +++-
 src/runtime/Config.arm64-linux            |  6 +++-
 src/runtime/Config.hppa-linux             |  7 +++-
 src/runtime/Config.mips-linux             |  6 +++-
 src/runtime/Config.ppc-linux              |  6 +++-
 src/runtime/Config.ppc64-linux            |  6 +++-
 src/runtime/Config.riscv-linux            |  7 +++-
 src/runtime/Config.sparc-linux            |  7 +++-
 src/runtime/Config.sparc-sunos            | 10 ++++--
 src/runtime/Config.x86-64-darwin          |  8 ++++-
 src/runtime/Config.x86-64-gnu-kfreebsd    |  7 +++-
 src/runtime/Config.x86-64-linux           |  6 +++-
 src/runtime/Config.x86-64-sunos           |  8 ++++-
 src/runtime/Config.x86-darwin             |  8 ++++-
 src/runtime/Config.x86-gnu-kfreebsd       |  7 +++-
 src/runtime/Config.x86-linux              |  7 +++-
 src/runtime/Config.x86-sunos              |  8 ++++-
 src/runtime/arch.h                        |  1 +
 src/runtime/arm-arch.c                    | 12 +++++++
 src/runtime/arm64-arch.c                  | 11 +++++++
 src/runtime/mips-arch.c                   |  8 +++++
 src/runtime/ppc-arch.c                    | 40 +++++++++++++++++++++++
 src/runtime/riscv-arch.c                  |  8 +++++
 src/runtime/sparc-arch.c                  | 19 +++++++++++
 src/runtime/x86-64-arch.c                 | 11 +++++++
 src/runtime/x86-arch.c                    | 14 ++++++++
 tests/foreign.test.sh                     | 22 +++++++++++++
 tools-for-build/Makefile                  |  4 ++-
 36 files changed, 289 insertions(+), 27 deletions(-)

diff --git a/contrib/sb-bsd-sockets/sb-bsd-sockets.asd b/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
index 2bdaf22d5..847e0be3a 100644
--- a/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
+++ b/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
@@ -6,7 +6,7 @@
 ;;; 1003.1-2003 defines an alternative API, which is specified in the
 ;;; RFC to be thread-safe. If it seems to be available, use it.
 
-(when (sb-alien::find-dynamic-foreign-symbol-address "getaddrinfo")
+(when (sb-alien::find-foreign-symbol-address "getaddrinfo")
   (pushnew :sb-bsd-sockets-addrinfo *features*))
 
 (defsystem "sb-bsd-sockets"
diff --git a/package-data-list.lisp-expr b/package-data-list.lisp-expr
index 852fdb6bc..8cd6eb63f 100644
--- a/package-data-list.lisp-expr
+++ b/package-data-list.lisp-expr
@@ -2800,6 +2800,7 @@ SB-KERNEL) have been undone, but probably more remain."
                "FD-STREAM" "FD-STREAM-FD" "FD-STREAM-P"
                "FIND-DYNAMIC-FOREIGN-SYMBOL-ADDRESS"
                "FIND-FOREIGN-SYMBOL-ADDRESS"
+               "FIND-FOREIGN-SYMBOL-ADDRESS-FROM-LINKAGE-TABLE"
                "FIND-FOREIGN-SYMBOL-IN-TABLE"
                "FOREIGN-SYMBOL-SAP"
                "FOREIGN-SYMBOL-ADDRESS"
diff --git a/src/code/debug-int.lisp b/src/code/debug-int.lisp
index 6bff6d1d7..54949fa5a 100644
--- a/src/code/debug-int.lisp
+++ b/src/code/debug-int.lisp
@@ -970,7 +970,7 @@ (defun nth-interrupt-context (n)
 ;;; address.
 (defun static-foreign-symbol-address (name)
   #+linkage-table
-  (find-dynamic-foreign-symbol-address name)
+  (find-foreign-symbol-address name)
   #-linkage-table
   (foreign-symbol-address name))
 
diff --git a/src/code/foreign.lisp b/src/code/foreign.lisp
index 6a30c9cb5..81b89d4b7 100644
--- a/src/code/foreign.lisp
+++ b/src/code/foreign.lisp
@@ -16,7 +16,10 @@ (defun find-foreign-symbol-address (name)
 symbol in the linkage table, and never returns an address in the linkage-table."
   (or #-linkage-table
       (find-foreign-symbol-in-table name *static-foreign-symbols*)
-      (find-dynamic-foreign-symbol-address name)))
+      #+os-provides-dlopen
+      (find-dynamic-foreign-symbol-address name)
+      #+(and linkage-table (not os-provides-dlopen))
+      (find-foreign-symbol-address-from-linkage-table name)))
 
 ;;; Note that much conditionalization is for nothing at this point, because all
 ;;; platforms that we care about implement dlopen(). But if one did not, only
diff --git a/src/code/linkage-table.lisp b/src/code/linkage-table.lisp
index 6ae3f2326..5b18039a6 100644
--- a/src/code/linkage-table.lisp
+++ b/src/code/linkage-table.lisp
@@ -22,6 +22,9 @@
 (define-alien-routine arch-write-linkage-table-entry void
   (index int) (real-address unsigned) (datap int))
 
+(define-alien-routine arch-read-linkage-table-entry (* t)
+  (index int) (datap int))
+
 (define-load-time-global *linkage-info*
     ;; CDR of the cons is the list of undefineds
     (list (make-hash-table :test 'equal :synchronized t)))
@@ -33,7 +36,8 @@ (define-alien-variable undefined-alien-address unsigned)
              ;; Produce two values: an indicator of whether the foreign symbol was
              ;; found; and the address as an integer if found, or a guard address
              ;; which when accessed will result in an UNDEFINED-ALIEN-ERROR.
-             `(let ((addr (find-dynamic-foreign-symbol-address name)))
+             `(let ((addr (or #+os-provides-dlopen
+                              (find-dynamic-foreign-symbol-address name))))
                 (cond (addr
                        (values t addr))
                       (t
@@ -71,7 +75,7 @@ (defun ensure-foreign-symbol-linkage (name datap)
                                                            (if datap 1 0))
                            (logically-readonlyize name)
                            (setf (gethash key ht) index))))))
-               (sb-vm::linkage-table-entry-address it))
+          (sb-vm::linkage-table-entry-address it))
         (error "Linkage-table full (~D entries): cannot link ~S."
                (hash-table-count ht) name))))
 
@@ -96,6 +100,7 @@ (defun update-linkage-table (full-scan)
     (flet ((recheck (key index)
              (let* ((datap (listp key))
                     (name (if datap (car key) key)))
+               (declare (ignorable name))
                ;; Symbols required for Lisp startup
                ;; will not be re-pointed to a different address ever.
                ;; Nor will those referenced by ELF core.
@@ -114,3 +119,16 @@ (defun update-linkage-table (full-scan)
             (recheck key (the (not null) (gethash key ht)))))
       (setf (cdr info) notdef)))))
 )
+
+(defun find-foreign-symbol-address-from-linkage-table (name)
+  "Returns the address of the foreign symbol NAME, or NIL. Consults only the
+linkage table to find the address."
+  (let* ((info *linkage-info*)
+         (ht (car info)))
+    (multiple-value-bind (index datap)
+        (with-system-mutex ((hash-table-lock ht))
+          (or (gethash name ht)
+              (values (gethash (list name) ht) t)))
+      (when (and index
+                 (not (member (if datap (list name) name) (cdr info) :test #'equal)))
+        (sap-int (alien-sap (arch-read-linkage-table-entry index (if datap 1 0))))))))
diff --git a/src/compiler/target-main.lisp b/src/compiler/target-main.lisp
index 5c14b15ba..d26734bf6 100644
--- a/src/compiler/target-main.lisp
+++ b/src/compiler/target-main.lisp
@@ -47,7 +47,7 @@ (defun compile-in-lexenv (form *lexenv* name source-info tlf ephemeral errorp)
                    (make-compilation
                     :msan-unpoison
                     (and (member :msan *features*)
-                         (find-dynamic-foreign-symbol-address "__msan_unpoison"))
+                         (find-foreign-symbol-address "__msan_unpoison"))
                     :block-compile nil))
                   (*current-path* nil)
                   (*last-message-count* (list* 0 nil nil))
diff --git a/src/runtime/Config.alpha-linux b/src/runtime/Config.alpha-linux
index ba1e2900d..d6312f46b 100644
--- a/src/runtime/Config.alpha-linux
+++ b/src/runtime/Config.alpha-linux
@@ -17,7 +17,11 @@ ASSEM_SRC = alpha-assem.S ldso-stubs.S
 ARCH_SRC = alpha-arch.c
 
 OS_SRC = linux-os.c linux-mman.c alpha-linux-os.c
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
 
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
diff --git a/src/runtime/Config.arm-android b/src/runtime/Config.arm-android
index 2854b65f4..d9f285738 100644
--- a/src/runtime/Config.arm-android
+++ b/src/runtime/Config.arm-android
@@ -18,7 +18,11 @@ ASSEM_SRC = arm-assem.S
 ARCH_SRC = arm-arch.c
 
 OS_SRC = linux-os.c linux-mman.c arm-linux-os.c android-os.c arm-android-os.c
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
 
 ifdef LISP_FEATURE_GENCGC
   GC_SRC = fullcgc.c gencgc.c traceroot.c
diff --git a/src/runtime/Config.arm-linux b/src/runtime/Config.arm-linux
index 2f72b244e..cbfb50bea 100644
--- a/src/runtime/Config.arm-linux
+++ b/src/runtime/Config.arm-linux
@@ -16,7 +16,11 @@ ASSEM_SRC = arm-assem.S
 ARCH_SRC = arm-arch.c
 
 OS_SRC = linux-os.c linux-mman.c arm-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 ifdef LISP_FEATURE_GENCGC
   GC_SRC = fullcgc.c gencgc.c traceroot.c
diff --git a/src/runtime/Config.arm64-linux b/src/runtime/Config.arm64-linux
index 467245941..644c6ecb7 100644
--- a/src/runtime/Config.arm64-linux
+++ b/src/runtime/Config.arm64-linux
@@ -15,7 +15,11 @@ ASSEM_SRC = arm64-assem.S
 ARCH_SRC = arm64-arch.c
 
 OS_SRC = linux-os.c linux-mman.c arm64-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 ifdef LISP_FEATURE_GENCGC
   GC_SRC = fullcgc.c gencgc.c traceroot.c
diff --git a/src/runtime/Config.hppa-linux b/src/runtime/Config.hppa-linux
index 75cc31c8c..53fa0c44d 100644
--- a/src/runtime/Config.hppa-linux
+++ b/src/runtime/Config.hppa-linux
@@ -16,7 +16,12 @@ ASSEM_SRC = hppa-assem.S ldso-stubs.S
 ARCH_SRC = hppa-arch.c
 
 OS_SRC = linux-os.c linux-mman.c hppa-linux-os.c
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
 endif
diff --git a/src/runtime/Config.mips-linux b/src/runtime/Config.mips-linux
index 7ec674f4b..ef2a47788 100644
--- a/src/runtime/Config.mips-linux
+++ b/src/runtime/Config.mips-linux
@@ -16,7 +16,11 @@ ASSEM_SRC = mips-assem.S
 ARCH_SRC = mips-arch.c
 
 OS_SRC = linux-os.c linux-mman.c mips-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 ifdef LISP_FEATURE_LARGEFILE
   CFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
diff --git a/src/runtime/Config.ppc-linux b/src/runtime/Config.ppc-linux
index 2f3ce9f63..b84581c75 100644
--- a/src/runtime/Config.ppc-linux
+++ b/src/runtime/Config.ppc-linux
@@ -17,7 +17,11 @@ ASSEM_SRC = ppc-assem.S
 ARCH_SRC = ppc-arch.c
 
 OS_SRC = linux-os.c linux-mman.c ppc-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 ifdef LISP_FEATURE_GENCGC
   GC_SRC = fullcgc.c gencgc.c traceroot.c
diff --git a/src/runtime/Config.ppc64-linux b/src/runtime/Config.ppc64-linux
index e58cb5d5c..5c7b48fa4 100644
--- a/src/runtime/Config.ppc64-linux
+++ b/src/runtime/Config.ppc64-linux
@@ -17,7 +17,11 @@ ASSEM_SRC = ppc64-assem.S
 ARCH_SRC = ppc-arch.c
 
 OS_SRC = linux-os.c linux-mman.c ppc-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 ifdef LISP_FEATURE_GENCGC
   GC_SRC = fullcgc.c gencgc.c traceroot.c
diff --git a/src/runtime/Config.riscv-linux b/src/runtime/Config.riscv-linux
index 5d585934e..eac70062a 100644
--- a/src/runtime/Config.riscv-linux
+++ b/src/runtime/Config.riscv-linux
@@ -14,7 +14,12 @@ NM = ./linux-nm
 ARCH_SRC = riscv-arch.c
 
 OS_SRC = linux-os.c linux-mman.c riscv-linux-os.c
-OS_LIBS = -ldl -Wl,-no-as-needed
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL) -Wl,-no-as-needed
+endif
+
 ifdef LISP_FEATURE_SB_THREAD
   OS_LIBS += -lpthread
 endif
diff --git a/src/runtime/Config.sparc-linux b/src/runtime/Config.sparc-linux
index 8b7ab0d44..e52db9374 100644
--- a/src/runtime/Config.sparc-linux
+++ b/src/runtime/Config.sparc-linux
@@ -18,7 +18,12 @@ ASSEM_SRC = sparc-assem.S
 ARCH_SRC = sparc-arch.c
 
 OS_SRC = linux-os.c linux-mman.c sparc-linux-os.c
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
 endif
diff --git a/src/runtime/Config.sparc-sunos b/src/runtime/Config.sparc-sunos
index 911b088cd..44c3b938b 100644
--- a/src/runtime/Config.sparc-sunos
+++ b/src/runtime/Config.sparc-sunos
@@ -13,7 +13,7 @@ CC = gcc
 CFLAGS += -DSVR4 -D_REENTRANT
 ASFLAGS = -g -DSVR4 -Wa,-xarch=v8plus
 #LINKFLAGS += -v
-NM = nm -t x -p 
+NM = nm -t x -p
 # This next line has nothing to do with disabling PIE. It has only to
 # do with the problem that "grep" on the build machine I'm using can't
 # parse "-e '[^f]nopie" and so gets an error in GNUmakefile.
@@ -23,7 +23,13 @@ ASSEM_SRC = sparc-assem.S
 ARCH_SRC = sparc-arch.c
 
 OS_SRC = sunos-os.c sparc-sunos-os.c
-OS_LIBS = -ldl -lsocket -lnsl -lrt
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
+OS_LIBS += -lsocket -lnsl -lrt
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
 endif
diff --git a/src/runtime/Config.x86-64-darwin b/src/runtime/Config.x86-64-darwin
index 027d0dfb8..cc7eda92e 100644
--- a/src/runtime/Config.x86-64-darwin
+++ b/src/runtime/Config.x86-64-darwin
@@ -24,7 +24,13 @@ endif
 
 OS_SRC = bsd-os.c x86-64-bsd-os.c darwin-os.c x86-64-darwin-os.c
 
-OS_LIBS = -lSystem -lc -ldl
+OS_LIBS = -lSystem -lc
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS += $(OS_LIBDL)
+endif
+
 ifdef LISP_FEATURE_SB_THREAD
   OS_LIBS += -lpthread
 endif
diff --git a/src/runtime/Config.x86-64-gnu-kfreebsd b/src/runtime/Config.x86-64-gnu-kfreebsd
index 6fd4cdd05..492207b34 100644
--- a/src/runtime/Config.x86-64-gnu-kfreebsd
+++ b/src/runtime/Config.x86-64-gnu-kfreebsd
@@ -15,7 +15,12 @@ include Config.x86-64-bsd
 # worked fine for most things, but LOAD-FOREIGN & friends require
 # dlopen() etc., which in turn depend on dynamic linking of the
 # runtime.
-OS_LIBS += -lutil -ldl -Wl,-no-as-needed
+OS_LIBS += -lutil
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS += $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 # use libthr (1:1 threading).  libpthread (m:n threading) does not work.
 ifdef LISP_FEATURE_SB_THREAD
diff --git a/src/runtime/Config.x86-64-linux b/src/runtime/Config.x86-64-linux
index 904631c68..f8632449e 100644
--- a/src/runtime/Config.x86-64-linux
+++ b/src/runtime/Config.x86-64-linux
@@ -28,7 +28,11 @@ OS_SRC = linux-os.c linux-mman.c x86-64-linux-os.c
 # interface, though.:-| As far as I (WHN 2002-05-19) know, no one is
 # working on one and it would be a nice thing to have.)
 LINKFLAGS += -Wl,--export-dynamic
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
 
 ifdef LISP_FEATURE_LARGEFILE
   CFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
diff --git a/src/runtime/Config.x86-64-sunos b/src/runtime/Config.x86-64-sunos
index 17eef040f..efefbe038 100644
--- a/src/runtime/Config.x86-64-sunos
+++ b/src/runtime/Config.x86-64-sunos
@@ -13,7 +13,13 @@ ASSEM_SRC = x86-64-assem.S
 ARCH_SRC = x86-64-arch.c
 
 OS_SRC = sunos-os.c x86-64-sunos-os.c
-OS_LIBS= -ldl -lsocket -lnsl -lrt
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
+OS_LIBS += -lsocket -lnsl -lrt
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
 endif
diff --git a/src/runtime/Config.x86-darwin b/src/runtime/Config.x86-darwin
index 1fb6c53c4..4b4f18c0a 100644
--- a/src/runtime/Config.x86-darwin
+++ b/src/runtime/Config.x86-darwin
@@ -27,7 +27,13 @@ endif
 
 OS_SRC = bsd-os.c x86-bsd-os.c darwin-os.c x86-darwin-os.c
 
-OS_LIBS = -lSystem -lc -ldl
+OS_LIBS = -lSystem -lc
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS += $(OS_LIBDL)
+endif
+
 ifdef LISP_FEATURE_SB_THREAD
   OS_LIBS += -lpthread
 endif
diff --git a/src/runtime/Config.x86-gnu-kfreebsd b/src/runtime/Config.x86-gnu-kfreebsd
index e49dde4a6..e7fcc5f8f 100644
--- a/src/runtime/Config.x86-gnu-kfreebsd
+++ b/src/runtime/Config.x86-gnu-kfreebsd
@@ -17,7 +17,12 @@ include Config.x86-bsd
 # runtime.
 LINKFLAGS += -dynamic -Wl,--export-dynamic -m32
 
-OS_LIBS += -lutil -ldl -Wl,-no-as-needed
+OS_LIBS += -lutil
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS += $(OS_LIBDL) -Wl,-no-as-needed
+endif
 
 # use libthr (1:1 threading).  libpthread (m:n threading) does not work.
 ifdef LISP_FEATURE_SB_THREAD
diff --git a/src/runtime/Config.x86-linux b/src/runtime/Config.x86-linux
index 67a758eb6..acdb32f88 100644
--- a/src/runtime/Config.x86-linux
+++ b/src/runtime/Config.x86-linux
@@ -28,7 +28,12 @@ OS_SRC = linux-os.c linux-mman.c x86-linux-os.c
 # interface, though.:-| As far as I (WHN 2002-05-19) know, no one is
 # working on one and it would be a nice thing to have.)
 LINKFLAGS += -Wl,--export-dynamic -m32
-OS_LIBS = -ldl
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
 __LDFLAGS__ = -m elf_i386
 
 
diff --git a/src/runtime/Config.x86-sunos b/src/runtime/Config.x86-sunos
index c63fa6676..aa100d042 100644
--- a/src/runtime/Config.x86-sunos
+++ b/src/runtime/Config.x86-sunos
@@ -18,7 +18,13 @@ ASSEM_SRC = x86-assem.S
 ARCH_SRC = x86-arch.c
 
 OS_SRC = sunos-os.c x86-sunos-os.c
-OS_LIBS= -ldl -lsocket -lnsl -lrt
+
+OS_LIBDL = -ldl
+ifeq ($(or $(LISP_FEATURE_OS_PROVIDES_DLOPEN),$(LISP_FEATURE_OS_PROVIDES_DLADDR)),1)
+OS_LIBS = $(OS_LIBDL)
+endif
+
+OS_LIBS += -lsocket -lnsl -lrt
 
 ifdef LISP_FEATURE_SB_CORE_COMPRESSION
   OS_LIBS += -lz
diff --git a/src/runtime/arch.h b/src/runtime/arch.h
index 26f7f2269..0616bd60b 100644
--- a/src/runtime/arch.h
+++ b/src/runtime/arch.h
@@ -65,5 +65,6 @@ extern void arch_handle_single_step_trap(os_context_t *context, int trap);
 #endif
 
 extern void arch_write_linkage_table_entry(int index, void *target_addr, int datap);
+extern void *arch_read_linkage_table_entry(int index, int datap);
 
 #endif /* __ARCH_H__ */
diff --git a/src/runtime/arm-arch.c b/src/runtime/arm-arch.c
index 9984bf5c9..676afaa88 100644
--- a/src/runtime/arm-arch.c
+++ b/src/runtime/arm-arch.c
@@ -169,3 +169,15 @@ void arch_write_linkage_table_entry(int index, void *target_addr, int datap)
 
   os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr =
+      (char *)LINKAGE_TABLE_SPACE_END - (index + 1) * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return (unsigned long*) *(unsigned long *)reloc_addr;
+  }
+
+  return *(void**)((int*)reloc_addr+3);
+}
diff --git a/src/runtime/arm64-arch.c b/src/runtime/arm64-arch.c
index c68b98ff0..9c4f2f292 100644
--- a/src/runtime/arm64-arch.c
+++ b/src/runtime/arm64-arch.c
@@ -178,3 +178,14 @@ void arch_write_linkage_table_entry(int index, void *target_addr, int datap)
 
   os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr = (char*)LINKAGE_TABLE_SPACE_START + index * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return (unsigned long*) *(unsigned long *)reloc_addr;
+  }
+
+  return *(void**)((int*)reloc_addr+2);
+}
diff --git a/src/runtime/mips-arch.c b/src/runtime/mips-arch.c
index 200f7632a..7e183c4a8 100644
--- a/src/runtime/mips-arch.c
+++ b/src/runtime/mips-arch.c
@@ -440,3 +440,11 @@ arch_write_linkage_table_entry(int index, void *target_addr, int datap)
         (char*)LINKAGE_TABLE_SPACE_END - (index + 1) * LINKAGE_TABLE_ENTRY_SIZE;
     *(unsigned int *)reloc_addr = (unsigned int)target_addr;
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+    char *reloc_addr =
+        (char*)LINKAGE_TABLE_SPACE_END - (index + 1) * LINKAGE_TABLE_ENTRY_SIZE;
+    return *(unsigned int *)reloc_addr;
+}
diff --git a/src/runtime/ppc-arch.c b/src/runtime/ppc-arch.c
index 92e151207..f8b1cf3fd 100644
--- a/src/runtime/ppc-arch.c
+++ b/src/runtime/ppc-arch.c
@@ -834,3 +834,43 @@ arch_write_linkage_table_entry(int index, void *target_addr, int datap)
 
   os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr = (char*)LINKAGE_TABLE_SPACE_START + index * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return *(unsigned long *)reloc_addr;
+  }
+
+#if defined LISP_FEATURE_64_BIT
+#ifdef LISP_FEATURE_LITTLE_ENDIAN
+  int* inst_ptr;
+  unsigned long a0, a16, a32, a48;
+
+  inst_ptr = (int*) reloc_addr;
+
+  a48 = *inst_ptr++ & 0xffff;
+  a32 = *inst_ptr++ & 0xffff;
+  inst_ptr++;
+  a16 = *inst_ptr++ & 0xffff;
+  a0 = *inst_ptr++ & 0xffff;
+
+  return (void*) (a0 + (a16 << 16) + (a32 << 32) + (a48 << 48));
+#else
+  void *target_addr;
+  memcpy(target_addr, reloc_addr, 24);
+  return target_addr;
+#endif
+#endif
+  int* inst_ptr;
+  unsigned long hi;
+  unsigned long lo;
+
+  inst_ptr = (int*) reloc_addr;
+
+  hi = *inst_ptr++ & 0xffff;
+  lo = *inst_ptr++ & 0xffff;
+
+  return (void*) (lo + (hi << 16));
+}
diff --git a/src/runtime/riscv-arch.c b/src/runtime/riscv-arch.c
index f7bd5755f..4fcb5d4af 100644
--- a/src/runtime/riscv-arch.c
+++ b/src/runtime/riscv-arch.c
@@ -152,6 +152,14 @@ void arch_write_linkage_table_entry(int index, void *target_addr, int datap)
     *(uword_t*)reloc_addr = (uword_t)target_addr;
 }
 
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+    char *reloc_addr =
+        (char*)LINKAGE_TABLE_SPACE_END - (index + 1) * LINKAGE_TABLE_ENTRY_SIZE;
+    return *(uword_t *)reloc_addr;
+}
+
 lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs) {
     return ((lispobj(*)(lispobj, lispobj *, int, struct thread*))SYMBOL(CALL_INTO_LISP)->value)
       (fun, args, nargs, arch_os_get_current_thread());
diff --git a/src/runtime/sparc-arch.c b/src/runtime/sparc-arch.c
index 417c6285b..2ad0095f3 100644
--- a/src/runtime/sparc-arch.c
+++ b/src/runtime/sparc-arch.c
@@ -429,3 +429,22 @@ arch_write_linkage_table_entry(int index, void *target_addr, int datap)
 
   os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr = (char*)LINKAGE_TABLE_SPACE_START + index * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return (unsigned long*) *(unsigned long *)reloc_addr;
+  }
+
+  int* inst_ptr;
+  unsigned long hi;
+  unsigned long lo;
+
+  inst_ptr = (int*) reloc_addr;
+  hi = *inst_ptr++ & 0x3fffff;
+  lo = *inst_ptr & 0x3ff;
+
+  return (void*)(lo + (hi << 10));
+}
diff --git a/src/runtime/x86-64-arch.c b/src/runtime/x86-64-arch.c
index 139273cc5..a10d5781a 100644
--- a/src/runtime/x86-64-arch.c
+++ b/src/runtime/x86-64-arch.c
@@ -504,6 +504,17 @@ arch_write_linkage_table_entry(int index, void *target_addr, int datap)
     *(void**)(reloc_addr+8) = target_addr;
 }
 
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr = (char*)LINKAGE_TABLE_SPACE_START + index * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return (void*) *(uword_t *)reloc_addr;
+  }
+
+  return *(void**)(reloc_addr+8);
+}
+
 /* These setup and check *both* the sse2 and x87 FPUs. While lisp code
    only uses the sse2 FPU, other code (such as libc) may use the x87 FPU.
  */
diff --git a/src/runtime/x86-arch.c b/src/runtime/x86-arch.c
index fc2674be9..4d347ae61 100644
--- a/src/runtime/x86-arch.c
+++ b/src/runtime/x86-arch.c
@@ -405,3 +405,17 @@ arch_write_linkage_table_entry(int index, void *target_addr, int datap)
     /* write a nop for good measure. */
     *reloc_addr = 0x90;
 }
+
+void
+*arch_read_linkage_table_entry(int index, int datap)
+{
+  char *reloc_addr = (char*)LINKAGE_TABLE_SPACE_START + index * LINKAGE_TABLE_ENTRY_SIZE;
+  if (datap) {
+    return (unsigned long*) *(unsigned long *)reloc_addr;
+  }
+
+  long offset = 0;
+
+  offset = reloc_addr[1] + (reloc_addr[2] << 8) + (reloc_addr[3] << 16) + (reloc_addr[4] << 24);
+  return (void*) (offset + reloc_addr + 5);
+}
diff --git a/tests/foreign.test.sh b/tests/foreign.test.sh
index 1139d91b5..a54a9cc0f 100755
--- a/tests/foreign.test.sh
+++ b/tests/foreign.test.sh
@@ -485,5 +485,27 @@ cat > $TEST_FILESTEM.alien.enum.lisp <<EOF
 EOF
 expect_clean_compile $TEST_FILESTEM.alien.enum.lisp
 
+# If dlopen is available, check that the address we get for a symbol
+# from dlsym and from backing it out of the linkage table match.
+run_sbcl <<EOF
+  (eval-when (:compile-toplevel :load-toplevel :execute)
+    (setq *features* (union *features* sb-impl:+internal-features+)))
+  #+(and linkage-table os-provides-dlopen)
+  (progn
+    (extern-alien "posix_argv" (* (* char)))
+    (extern-alien "sin" (function double double))
+
+    ;; Test that data pointers are the same.
+    (assert (= (sb-sys:find-dynamic-foreign-symbol-address "posix_argv")
+               (sb-sys:find-foreign-symbol-address-from-linkage-table "posix_argv")))
+
+    ;; Test that function pointers are the same.
+    (assert (= (sb-sys:find-dynamic-foreign-symbol-address "sin")
+               (sb-sys:find-foreign-symbol-address-from-linkage-table "sin"))))
+
+  (exit :code $EXIT_LISP_WIN)
+EOF
+check_status_maybe_lose "arch-read-linkage-table-entry" $?
+
 # success convention for script
 exit $EXIT_TEST_WIN
diff --git a/tools-for-build/Makefile b/tools-for-build/Makefile
index 1be91e9df..a9e2cf98d 100644
--- a/tools-for-build/Makefile
+++ b/tools-for-build/Makefile
@@ -12,7 +12,9 @@
 
 CPPFLAGS+=-I../src/runtime
 LDFLAGS:=$(LDFLAGS)
-LDLIBS:=$(OS_LIBS)
+# Unconditionally include libdl to make sure we can robustly detect the libdl
+# related features.
+LDLIBS:= $(OS_LIBDL) $(OS_LIBS)
 
 all: grovel-headers determine-endianness where-is-mcontext mmap-rwx
 
-- 
2.27.0



_______________________________________________
Sbcl-devel mailing list
Sbcl-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-devel
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic