Skip to content

Commit 311f8c3

Browse files
ctypes: check _dyld_shared_cache_contains_path in find_library
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.
1 parent 1648c99 commit 311f8c3

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

Lib/ctypes/macholib/dyld.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
from ctypes.macholib.dylib import dylib_info
88
from itertools import *
99

10+
try:
11+
from _ctypes import _dyld_shared_cache_contains_path
12+
except ImportError:
13+
def _dyld_shared_cache_contains_path(*args):
14+
raise NotImplementedError
15+
1016
__all__ = [
1117
'dyld_find', 'framework_find',
1218
'framework_info', 'dylib_info',
@@ -124,6 +130,12 @@ def dyld_find(name, executable_path=None, env=None):
124130
), env):
125131
if os.path.isfile(path):
126132
return path
133+
try:
134+
if _dyld_shared_cache_contains_path(path):
135+
return path
136+
except NotImplementedError:
137+
pass
138+
127139
raise ValueError("dylib %s could not be found" % (name,))
128140

129141
def framework_find(fn, executable_path=None, env=None):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ctypes: Mac OS 11: check for system libraries in the shared cache

Modules/_ctypes/callproc.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
#include "ctypes_dlfcn.h"
6565
#endif
6666

67+
#ifdef __APPLE__
68+
extern bool _dyld_shared_cache_contains_path(const char* path) __attribute__((weak_import));
69+
#endif
70+
6771
#ifdef MS_WIN32
6872
#include <malloc.h>
6973
#endif
@@ -1398,6 +1402,37 @@ copy_com_pointer(PyObject *self, PyObject *args)
13981402
}
13991403
#else
14001404

1405+
#ifdef __APPLE__
1406+
static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
1407+
{
1408+
PyObject *name, *name2;
1409+
char *name_str;
1410+
1411+
if (_dyld_shared_cache_contains_path == NULL) {
1412+
PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
1413+
return NULL;
1414+
}
1415+
1416+
if (!PyArg_ParseTuple(args, "O", &name))
1417+
return NULL;
1418+
1419+
if (name == Py_None)
1420+
Py_RETURN_FALSE;
1421+
1422+
if (PyUnicode_FSConverter(name, &name2) == 0)
1423+
return NULL;
1424+
if (PyBytes_Check(name2))
1425+
name_str = PyBytes_AS_STRING(name2);
1426+
else
1427+
name_str = PyByteArray_AS_STRING(name2);
1428+
1429+
if(_dyld_shared_cache_contains_path(name_str))
1430+
Py_RETURN_TRUE;
1431+
else
1432+
Py_RETURN_FALSE;
1433+
}
1434+
#endif
1435+
14011436
static PyObject *py_dl_open(PyObject *self, PyObject *args)
14021437
{
14031438
PyObject *name, *name2;
@@ -1908,6 +1943,9 @@ PyMethodDef _ctypes_module_methods[] = {
19081943
"dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
19091944
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
19101945
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
1946+
#endif
1947+
#ifdef __APPLE__
1948+
{"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
19111949
#endif
19121950
{"alignment", align_func, METH_O, alignment_doc},
19131951
{"sizeof", sizeof_func, METH_O, sizeof_doc},

0 commit comments

Comments
 (0)