Skip to content

Commit

Permalink
ctypes: check _dyld_shared_cache_contains_path in find_library
Browse files Browse the repository at this point in the history
System libraries in Mac OS 11 may be present only in the shared cache,
with the actual mach-o file not present in the corresponding location
on the filesystem.   ctypes.util.find_library should check the
shared cache in order to behave consistently across Mac OS 10.15
and earlier and Mac OS 11.0 and later.
  • Loading branch information
lawrence-danna-apple committed Jun 30, 2020
1 parent 1648c99 commit 311f8c3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Lib/ctypes/macholib/dyld.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
from ctypes.macholib.dylib import dylib_info
from itertools import *

try:
from _ctypes import _dyld_shared_cache_contains_path
except ImportError:
def _dyld_shared_cache_contains_path(*args):
raise NotImplementedError

__all__ = [
'dyld_find', 'framework_find',
'framework_info', 'dylib_info',
Expand Down Expand Up @@ -124,6 +130,12 @@ def dyld_find(name, executable_path=None, env=None):
), env):
if os.path.isfile(path):
return path
try:
if _dyld_shared_cache_contains_path(path):
return path
except NotImplementedError:
pass

raise ValueError("dylib %s could not be found" % (name,))

def framework_find(fn, executable_path=None, env=None):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ctypes: Mac OS 11: check for system libraries in the shared cache
38 changes: 38 additions & 0 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
#include "ctypes_dlfcn.h"
#endif

#ifdef __APPLE__
extern bool _dyld_shared_cache_contains_path(const char* path) __attribute__((weak_import));
#endif

#ifdef MS_WIN32
#include <malloc.h>
#endif
Expand Down Expand Up @@ -1398,6 +1402,37 @@ copy_com_pointer(PyObject *self, PyObject *args)
}
#else

#ifdef __APPLE__
static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
char *name_str;

if (_dyld_shared_cache_contains_path == NULL) {
PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
return NULL;
}

if (!PyArg_ParseTuple(args, "O", &name))
return NULL;

if (name == Py_None)
Py_RETURN_FALSE;

if (PyUnicode_FSConverter(name, &name2) == 0)
return NULL;
if (PyBytes_Check(name2))
name_str = PyBytes_AS_STRING(name2);
else
name_str = PyByteArray_AS_STRING(name2);

if(_dyld_shared_cache_contains_path(name_str))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
#endif

static PyObject *py_dl_open(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
Expand Down Expand Up @@ -1908,6 +1943,9 @@ PyMethodDef _ctypes_module_methods[] = {
"dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
#endif
#ifdef __APPLE__
{"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
#endif
{"alignment", align_func, METH_O, alignment_doc},
{"sizeof", sizeof_func, METH_O, sizeof_doc},
Expand Down

0 comments on commit 311f8c3

Please sign in to comment.