Reimplement addbuilddir() in C inside getpath.c, so as to execute it
at interpreter startup before importing any non-builtin modules.
Should fix #9589.
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 4164a12..fff502e 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -394,12 +394,35 @@
         return 1;
     }
 
-    /* Check to see if argv[0] is in the build directory */
+    /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
+       is written by setup.py and contains the relative path to the location
+       of shared library modules. */
     wcscpy(exec_prefix, argv0_path);
-    joinpath(exec_prefix, L"Modules/Setup");
+    joinpath(exec_prefix, L"pybuilddir.txt");
     if (isfile(exec_prefix)) {
-        reduce(exec_prefix);
-        return -1;
+        FILE *f = _Py_wfopen(exec_prefix, L"rb");
+        if (f == NULL)
+            errno = 0;
+        else {
+            char buf[MAXPATHLEN+1];
+            PyObject *decoded;
+            wchar_t rel_builddir_path[MAXPATHLEN+1];
+            size_t n;
+            n = fread(buf, 1, MAXPATHLEN, f);
+            buf[n] = '\0';
+            fclose(f);
+            decoded = PyUnicode_DecodeUTF8(buf, n, "surrogateescape");
+            if (decoded != NULL) {
+                n = PyUnicode_AsWideChar(decoded, rel_builddir_path, MAXPATHLEN);
+                Py_DECREF(decoded);
+                if (n >= 0) {
+                    rel_builddir_path[n] = L'\0';
+                    wcscpy(exec_prefix, argv0_path);
+                    joinpath(exec_prefix, rel_builddir_path);
+                    return -1;
+                }
+            }
+        }
     }
 
     /* Search from argv0_path, until root is found */
diff --git a/Modules/main.c b/Modules/main.c
index 7929b05..d605bab 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -101,10 +101,10 @@
 PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\
 ";
 
-#ifndef MS_WINDOWS
-static FILE*
-_wfopen(const wchar_t *path, const wchar_t *mode)
+FILE *
+_Py_wfopen(const wchar_t *path, const wchar_t *mode)
 {
+#ifndef MS_WINDOWS
     char cpath[PATH_MAX];
     char cmode[10];
     size_t r;
@@ -119,8 +119,10 @@
         return NULL;
     }
     return fopen(cpath, cmode);
-}
+#else
+    return _wfopen(path, mode);
 #endif
+}
 
 
 static int
@@ -640,7 +642,7 @@
         }
 
         if (sts==-1 && filename!=NULL) {
-            if ((fp = _wfopen(filename, L"r")) == NULL) {
+            if ((fp = _Py_wfopen(filename, L"r")) == NULL) {
                 char cfilename[PATH_MAX];
                 size_t r = wcstombs(cfilename, filename, PATH_MAX);
                 if (r == PATH_MAX)