• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // shader_cache_file_hooking:
7 //    Hooks file API functions to intercept Metal shader cache access and return as if the file
8 //    doesn't exist. This is to avoid slow cache access happened after the cache becomes huge over
9 //    time.
10 //
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <iostream>
18 #include <regex>
19 
20 namespace
21 {
22 constexpr char kMetalCacheExpr[] = R"(.*com\.apple\.metal.*(libraries|functions).*\.(maps|data))";
23 }
24 
HookedOpen(const char * path,int flags,mode_t mode)25 int HookedOpen(const char *path, int flags, mode_t mode)
26 {
27     std::regex expr(kMetalCacheExpr);
28 
29     if (!std::regex_match(path, expr))
30     {
31         return open(path, flags, mode);
32     }
33 
34 #if !defined(NDEBUG)
35     std::cerr << "open(\"" << path << "\", \"" << flags << "\") is skipped" << std::endl;
36 #endif
37     if (flags & O_CREAT)
38     {
39         errno = EACCES;
40         return -1;
41     }
42 
43     // Treat as if the cache doesn't exist
44     errno = ENOENT;
45     return -1;
46 }
47 
HookedFopen(const char * filename,const char * mode)48 FILE *HookedFopen(const char *filename, const char *mode)
49 {
50     std::regex expr(kMetalCacheExpr);
51     if (!std::regex_match(filename, expr))
52     {
53         return fopen(filename, mode);
54     }
55 
56 #if !defined(NDEBUG)
57     std::cerr << "fopen(\"" << filename << "\", \"" << mode << "\") is skipped" << std::endl;
58 #endif
59     if (strstr(mode, "r"))
60     {
61         // Treat as if the cache doesn't exist
62         errno = ENOENT;
63         return nullptr;
64     }
65 
66     errno = EACCES;
67     return nullptr;
68 }
69 
70 // See https://opensource.apple.com/source/dyld/dyld-210.2.3/include/mach-o/dyld-interposing.h
71 #define DYLD_INTERPOSE(_replacment, _replacee)                                  \
72     __attribute__((used)) static struct                                         \
73     {                                                                           \
74         const void *replacment;                                                 \
75         const void *replacee;                                                   \
76     } _interpose_##_replacee __attribute__((section("__DATA,__interpose"))) = { \
77         (const void *)(unsigned long)&_replacment, (const void *)(unsigned long)&_replacee};
78 
79 DYLD_INTERPOSE(HookedOpen, open)
80 DYLD_INTERPOSE(HookedFopen, fopen)
81