xref: /aosp_15_r20/bionic/tests/utils.h (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #pragma once
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <dirent.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <dlfcn.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <sys/mman.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <sys/prctl.h>
26*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
27*8d67ca89SAndroid Build Coastguard Worker #include <sys/wait.h>
28*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
29*8d67ca89SAndroid Build Coastguard Worker 
30*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
31*8d67ca89SAndroid Build Coastguard Worker #include <sys/system_properties.h>
32*8d67ca89SAndroid Build Coastguard Worker #endif
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
35*8d67ca89SAndroid Build Coastguard Worker #include <bionic/macros.h>
36*8d67ca89SAndroid Build Coastguard Worker #else
37*8d67ca89SAndroid Build Coastguard Worker #define untag_address(p) p
38*8d67ca89SAndroid Build Coastguard Worker #endif
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker #include <atomic>
41*8d67ca89SAndroid Build Coastguard Worker #include <iomanip>
42*8d67ca89SAndroid Build Coastguard Worker #include <string>
43*8d67ca89SAndroid Build Coastguard Worker #include <regex>
44*8d67ca89SAndroid Build Coastguard Worker 
45*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
46*8d67ca89SAndroid Build Coastguard Worker #include <android-base/macros.h>
47*8d67ca89SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
48*8d67ca89SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
49*8d67ca89SAndroid Build Coastguard Worker 
50*8d67ca89SAndroid Build Coastguard Worker #if defined(__LP64__)
51*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_SYSTEM_LIB "/system/lib64/"
52*8d67ca89SAndroid Build Coastguard Worker #else
53*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_SYSTEM_LIB "/system/lib/"
54*8d67ca89SAndroid Build Coastguard Worker #endif
55*8d67ca89SAndroid Build Coastguard Worker 
56*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
57*8d67ca89SAndroid Build Coastguard Worker #define BIN_DIR "/bin/"
58*8d67ca89SAndroid Build Coastguard Worker #else
59*8d67ca89SAndroid Build Coastguard Worker #define BIN_DIR "/system/bin/"
60*8d67ca89SAndroid Build Coastguard Worker #endif
61*8d67ca89SAndroid Build Coastguard Worker 
62*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
63*8d67ca89SAndroid Build Coastguard Worker #define KNOWN_FAILURE_ON_BIONIC(x) xfail_ ## x
64*8d67ca89SAndroid Build Coastguard Worker #else
65*8d67ca89SAndroid Build Coastguard Worker #define KNOWN_FAILURE_ON_BIONIC(x) x
66*8d67ca89SAndroid Build Coastguard Worker #endif
67*8d67ca89SAndroid Build Coastguard Worker 
68*8d67ca89SAndroid Build Coastguard Worker // bionic's dlsym doesn't work in static binaries, so we can't access icu,
69*8d67ca89SAndroid Build Coastguard Worker // so any unicode test case will fail.
have_dl()70*8d67ca89SAndroid Build Coastguard Worker static inline bool have_dl() {
71*8d67ca89SAndroid Build Coastguard Worker   return (dlopen("libc.so", 0) != nullptr);
72*8d67ca89SAndroid Build Coastguard Worker }
73*8d67ca89SAndroid Build Coastguard Worker 
running_with_native_bridge()74*8d67ca89SAndroid Build Coastguard Worker static inline bool running_with_native_bridge() {
75*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
76*8d67ca89SAndroid Build Coastguard Worker   static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa." ABI_STRING);
77*8d67ca89SAndroid Build Coastguard Worker   return pi != nullptr;
78*8d67ca89SAndroid Build Coastguard Worker #endif
79*8d67ca89SAndroid Build Coastguard Worker   return false;
80*8d67ca89SAndroid Build Coastguard Worker }
81*8d67ca89SAndroid Build Coastguard Worker 
82*8d67ca89SAndroid Build Coastguard Worker #define SKIP_WITH_NATIVE_BRIDGE if (running_with_native_bridge()) GTEST_SKIP()
83*8d67ca89SAndroid Build Coastguard Worker 
84*8d67ca89SAndroid Build Coastguard Worker #if defined(__linux__)
85*8d67ca89SAndroid Build Coastguard Worker 
86*8d67ca89SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
87*8d67ca89SAndroid Build Coastguard Worker 
88*8d67ca89SAndroid Build Coastguard Worker struct map_record {
89*8d67ca89SAndroid Build Coastguard Worker   uintptr_t addr_start;
90*8d67ca89SAndroid Build Coastguard Worker   uintptr_t addr_end;
91*8d67ca89SAndroid Build Coastguard Worker 
92*8d67ca89SAndroid Build Coastguard Worker   int perms;
93*8d67ca89SAndroid Build Coastguard Worker 
94*8d67ca89SAndroid Build Coastguard Worker   size_t offset;
95*8d67ca89SAndroid Build Coastguard Worker 
96*8d67ca89SAndroid Build Coastguard Worker   dev_t device;
97*8d67ca89SAndroid Build Coastguard Worker   ino_t inode;
98*8d67ca89SAndroid Build Coastguard Worker 
99*8d67ca89SAndroid Build Coastguard Worker   std::string pathname;
100*8d67ca89SAndroid Build Coastguard Worker };
101*8d67ca89SAndroid Build Coastguard Worker 
102*8d67ca89SAndroid Build Coastguard Worker class Maps {
103*8d67ca89SAndroid Build Coastguard Worker  public:
parse_maps(std::vector<map_record> * maps)104*8d67ca89SAndroid Build Coastguard Worker   static bool parse_maps(std::vector<map_record>* maps) {
105*8d67ca89SAndroid Build Coastguard Worker     maps->clear();
106*8d67ca89SAndroid Build Coastguard Worker 
107*8d67ca89SAndroid Build Coastguard Worker     std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("/proc/self/maps", "re"), fclose);
108*8d67ca89SAndroid Build Coastguard Worker     if (!fp) return false;
109*8d67ca89SAndroid Build Coastguard Worker 
110*8d67ca89SAndroid Build Coastguard Worker     char line[BUFSIZ];
111*8d67ca89SAndroid Build Coastguard Worker     while (fgets(line, sizeof(line), fp.get()) != nullptr) {
112*8d67ca89SAndroid Build Coastguard Worker       map_record record;
113*8d67ca89SAndroid Build Coastguard Worker       uint32_t dev_major, dev_minor;
114*8d67ca89SAndroid Build Coastguard Worker       int path_offset;
115*8d67ca89SAndroid Build Coastguard Worker       char prot[5]; // sizeof("rwxp")
116*8d67ca89SAndroid Build Coastguard Worker       if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %x:%x %lu %n",
117*8d67ca89SAndroid Build Coastguard Worker             &record.addr_start, &record.addr_end, prot, &record.offset,
118*8d67ca89SAndroid Build Coastguard Worker             &dev_major, &dev_minor, &record.inode, &path_offset) == 7) {
119*8d67ca89SAndroid Build Coastguard Worker         record.perms = 0;
120*8d67ca89SAndroid Build Coastguard Worker         if (prot[0] == 'r') {
121*8d67ca89SAndroid Build Coastguard Worker           record.perms |= PROT_READ;
122*8d67ca89SAndroid Build Coastguard Worker         }
123*8d67ca89SAndroid Build Coastguard Worker         if (prot[1] == 'w') {
124*8d67ca89SAndroid Build Coastguard Worker           record.perms |= PROT_WRITE;
125*8d67ca89SAndroid Build Coastguard Worker         }
126*8d67ca89SAndroid Build Coastguard Worker         if (prot[2] == 'x') {
127*8d67ca89SAndroid Build Coastguard Worker           record.perms |= PROT_EXEC;
128*8d67ca89SAndroid Build Coastguard Worker         }
129*8d67ca89SAndroid Build Coastguard Worker 
130*8d67ca89SAndroid Build Coastguard Worker         // TODO: parse shared/private?
131*8d67ca89SAndroid Build Coastguard Worker 
132*8d67ca89SAndroid Build Coastguard Worker         record.device = makedev(dev_major, dev_minor);
133*8d67ca89SAndroid Build Coastguard Worker         record.pathname = line + path_offset;
134*8d67ca89SAndroid Build Coastguard Worker         if (!record.pathname.empty() && record.pathname.back() == '\n') {
135*8d67ca89SAndroid Build Coastguard Worker           record.pathname.pop_back();
136*8d67ca89SAndroid Build Coastguard Worker         }
137*8d67ca89SAndroid Build Coastguard Worker         maps->push_back(record);
138*8d67ca89SAndroid Build Coastguard Worker       }
139*8d67ca89SAndroid Build Coastguard Worker     }
140*8d67ca89SAndroid Build Coastguard Worker 
141*8d67ca89SAndroid Build Coastguard Worker     return true;
142*8d67ca89SAndroid Build Coastguard Worker   }
143*8d67ca89SAndroid Build Coastguard Worker };
144*8d67ca89SAndroid Build Coastguard Worker 
145*8d67ca89SAndroid Build Coastguard Worker extern "C" pid_t gettid();
146*8d67ca89SAndroid Build Coastguard Worker 
147*8d67ca89SAndroid Build Coastguard Worker #endif
148*8d67ca89SAndroid Build Coastguard Worker 
WaitUntilThreadSleep(std::atomic<pid_t> & tid)149*8d67ca89SAndroid Build Coastguard Worker static inline void WaitUntilThreadSleep(std::atomic<pid_t>& tid) {
150*8d67ca89SAndroid Build Coastguard Worker   while (tid == 0) {
151*8d67ca89SAndroid Build Coastguard Worker     usleep(1000);
152*8d67ca89SAndroid Build Coastguard Worker   }
153*8d67ca89SAndroid Build Coastguard Worker   std::string filename = android::base::StringPrintf("/proc/%d/stat", tid.load());
154*8d67ca89SAndroid Build Coastguard Worker   std::regex regex {R"(\s+S\s+)"};
155*8d67ca89SAndroid Build Coastguard Worker 
156*8d67ca89SAndroid Build Coastguard Worker   while (true) {
157*8d67ca89SAndroid Build Coastguard Worker     std::string content;
158*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(filename, &content));
159*8d67ca89SAndroid Build Coastguard Worker     if (std::regex_search(content, regex)) {
160*8d67ca89SAndroid Build Coastguard Worker       break;
161*8d67ca89SAndroid Build Coastguard Worker     }
162*8d67ca89SAndroid Build Coastguard Worker     usleep(1000);
163*8d67ca89SAndroid Build Coastguard Worker   }
164*8d67ca89SAndroid Build Coastguard Worker }
165*8d67ca89SAndroid Build Coastguard Worker 
166*8d67ca89SAndroid Build Coastguard Worker static inline void AssertChildExited(int pid, int expected_exit_status,
167*8d67ca89SAndroid Build Coastguard Worker                                      const std::string* error_msg = nullptr) {
168*8d67ca89SAndroid Build Coastguard Worker   int status;
169*8d67ca89SAndroid Build Coastguard Worker   std::string error;
170*8d67ca89SAndroid Build Coastguard Worker   if (error_msg == nullptr) {
171*8d67ca89SAndroid Build Coastguard Worker     error_msg = &error;
172*8d67ca89SAndroid Build Coastguard Worker   }
173*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, &status, 0))) << *error_msg;
174*8d67ca89SAndroid Build Coastguard Worker   if (expected_exit_status >= 0) {
175*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(WIFEXITED(status)) << *error_msg;
176*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(expected_exit_status, WEXITSTATUS(status)) << *error_msg;
177*8d67ca89SAndroid Build Coastguard Worker   } else {
178*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(WIFSIGNALED(status)) << *error_msg;
179*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(-expected_exit_status, WTERMSIG(status)) << *error_msg;
180*8d67ca89SAndroid Build Coastguard Worker   }
181*8d67ca89SAndroid Build Coastguard Worker }
182*8d67ca89SAndroid Build Coastguard Worker 
CloseOnExec(int fd)183*8d67ca89SAndroid Build Coastguard Worker static inline bool CloseOnExec(int fd) {
184*8d67ca89SAndroid Build Coastguard Worker   int flags = fcntl(fd, F_GETFD);
185*8d67ca89SAndroid Build Coastguard Worker   // This isn't ideal, but the alternatives are worse:
186*8d67ca89SAndroid Build Coastguard Worker   // * If we return void and use ASSERT_NE here, we get failures at utils.h:191
187*8d67ca89SAndroid Build Coastguard Worker   //   rather than in the relevant test.
188*8d67ca89SAndroid Build Coastguard Worker   // * If we ignore failures of fcntl(), well, that's obviously a bad idea.
189*8d67ca89SAndroid Build Coastguard Worker   if (flags == -1) abort();
190*8d67ca89SAndroid Build Coastguard Worker   return flags & FD_CLOEXEC;
191*8d67ca89SAndroid Build Coastguard Worker }
192*8d67ca89SAndroid Build Coastguard Worker 
193*8d67ca89SAndroid Build Coastguard Worker // The absolute path to the executable
194*8d67ca89SAndroid Build Coastguard Worker const std::string& get_executable_path();
195*8d67ca89SAndroid Build Coastguard Worker 
196*8d67ca89SAndroid Build Coastguard Worker // Access to argc/argv/envp
197*8d67ca89SAndroid Build Coastguard Worker int get_argc();
198*8d67ca89SAndroid Build Coastguard Worker char** get_argv();
199*8d67ca89SAndroid Build Coastguard Worker char** get_envp();
200*8d67ca89SAndroid Build Coastguard Worker 
201*8d67ca89SAndroid Build Coastguard Worker // ExecTestHelper is only used in bionic and glibc tests.
202*8d67ca89SAndroid Build Coastguard Worker #ifndef __APPLE__
203*8d67ca89SAndroid Build Coastguard Worker class ExecTestHelper {
204*8d67ca89SAndroid Build Coastguard Worker  public:
GetArgs()205*8d67ca89SAndroid Build Coastguard Worker   char** GetArgs() {
206*8d67ca89SAndroid Build Coastguard Worker     return const_cast<char**>(args_.data());
207*8d67ca89SAndroid Build Coastguard Worker   }
GetArg0()208*8d67ca89SAndroid Build Coastguard Worker   const char* GetArg0() {
209*8d67ca89SAndroid Build Coastguard Worker     return args_[0];
210*8d67ca89SAndroid Build Coastguard Worker   }
GetEnv()211*8d67ca89SAndroid Build Coastguard Worker   char** GetEnv() {
212*8d67ca89SAndroid Build Coastguard Worker     return const_cast<char**>(env_.data());
213*8d67ca89SAndroid Build Coastguard Worker   }
GetOutput()214*8d67ca89SAndroid Build Coastguard Worker   const std::string& GetOutput() {
215*8d67ca89SAndroid Build Coastguard Worker     return output_;
216*8d67ca89SAndroid Build Coastguard Worker   }
217*8d67ca89SAndroid Build Coastguard Worker 
SetArgs(const std::vector<const char * > & args)218*8d67ca89SAndroid Build Coastguard Worker   void SetArgs(const std::vector<const char*>& args) {
219*8d67ca89SAndroid Build Coastguard Worker     args_ = args;
220*8d67ca89SAndroid Build Coastguard Worker   }
SetEnv(const std::vector<const char * > & env)221*8d67ca89SAndroid Build Coastguard Worker   void SetEnv(const std::vector<const char*>& env) {
222*8d67ca89SAndroid Build Coastguard Worker     env_ = env;
223*8d67ca89SAndroid Build Coastguard Worker   }
224*8d67ca89SAndroid Build Coastguard Worker 
Run(const std::function<void ()> & child_fn,int expected_exit_status,const char * expected_output_regex)225*8d67ca89SAndroid Build Coastguard Worker   void Run(const std::function<void()>& child_fn, int expected_exit_status,
226*8d67ca89SAndroid Build Coastguard Worker            const char* expected_output_regex) {
227*8d67ca89SAndroid Build Coastguard Worker     int fds[2];
228*8d67ca89SAndroid Build Coastguard Worker     ASSERT_NE(pipe(fds), -1);
229*8d67ca89SAndroid Build Coastguard Worker 
230*8d67ca89SAndroid Build Coastguard Worker     pid_t pid = fork();
231*8d67ca89SAndroid Build Coastguard Worker     ASSERT_NE(pid, -1);
232*8d67ca89SAndroid Build Coastguard Worker 
233*8d67ca89SAndroid Build Coastguard Worker     if (pid == 0) {
234*8d67ca89SAndroid Build Coastguard Worker       // Child.
235*8d67ca89SAndroid Build Coastguard Worker       close(fds[0]);
236*8d67ca89SAndroid Build Coastguard Worker       dup2(fds[1], STDOUT_FILENO);
237*8d67ca89SAndroid Build Coastguard Worker       dup2(fds[1], STDERR_FILENO);
238*8d67ca89SAndroid Build Coastguard Worker       if (fds[1] != STDOUT_FILENO && fds[1] != STDERR_FILENO) close(fds[1]);
239*8d67ca89SAndroid Build Coastguard Worker       child_fn();
240*8d67ca89SAndroid Build Coastguard Worker       FAIL();
241*8d67ca89SAndroid Build Coastguard Worker     }
242*8d67ca89SAndroid Build Coastguard Worker 
243*8d67ca89SAndroid Build Coastguard Worker     // Parent.
244*8d67ca89SAndroid Build Coastguard Worker     close(fds[1]);
245*8d67ca89SAndroid Build Coastguard Worker     output_.clear();
246*8d67ca89SAndroid Build Coastguard Worker     char buf[BUFSIZ];
247*8d67ca89SAndroid Build Coastguard Worker     ssize_t bytes_read;
248*8d67ca89SAndroid Build Coastguard Worker     while ((bytes_read = TEMP_FAILURE_RETRY(read(fds[0], buf, sizeof(buf)))) > 0) {
249*8d67ca89SAndroid Build Coastguard Worker       output_.append(buf, bytes_read);
250*8d67ca89SAndroid Build Coastguard Worker     }
251*8d67ca89SAndroid Build Coastguard Worker     close(fds[0]);
252*8d67ca89SAndroid Build Coastguard Worker 
253*8d67ca89SAndroid Build Coastguard Worker     std::string error_msg("Test output:\n" + output_);
254*8d67ca89SAndroid Build Coastguard Worker     AssertChildExited(pid, expected_exit_status, &error_msg);
255*8d67ca89SAndroid Build Coastguard Worker     if (expected_output_regex != nullptr) {
256*8d67ca89SAndroid Build Coastguard Worker       if (!std::regex_search(output_, std::regex(expected_output_regex))) {
257*8d67ca89SAndroid Build Coastguard Worker         FAIL() << "regex " << std::quoted(expected_output_regex) << " didn't match " << std::quoted(output_);
258*8d67ca89SAndroid Build Coastguard Worker       }
259*8d67ca89SAndroid Build Coastguard Worker     }
260*8d67ca89SAndroid Build Coastguard Worker   }
261*8d67ca89SAndroid Build Coastguard Worker 
262*8d67ca89SAndroid Build Coastguard Worker  private:
263*8d67ca89SAndroid Build Coastguard Worker   std::vector<const char*> args_;
264*8d67ca89SAndroid Build Coastguard Worker   std::vector<const char*> env_;
265*8d67ca89SAndroid Build Coastguard Worker   std::string output_;
266*8d67ca89SAndroid Build Coastguard Worker };
267*8d67ca89SAndroid Build Coastguard Worker 
268*8d67ca89SAndroid Build Coastguard Worker void RunGwpAsanTest(const char* test_name);
269*8d67ca89SAndroid Build Coastguard Worker void RunSubtestNoEnv(const char* test_name);
270*8d67ca89SAndroid Build Coastguard Worker #endif
271*8d67ca89SAndroid Build Coastguard Worker 
272*8d67ca89SAndroid Build Coastguard Worker class FdLeakChecker {
273*8d67ca89SAndroid Build Coastguard Worker  public:
FdLeakChecker()274*8d67ca89SAndroid Build Coastguard Worker   FdLeakChecker() {
275*8d67ca89SAndroid Build Coastguard Worker   }
276*8d67ca89SAndroid Build Coastguard Worker 
~FdLeakChecker()277*8d67ca89SAndroid Build Coastguard Worker   ~FdLeakChecker() {
278*8d67ca89SAndroid Build Coastguard Worker     size_t end_count = CountOpenFds();
279*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(start_count_, end_count);
280*8d67ca89SAndroid Build Coastguard Worker   }
281*8d67ca89SAndroid Build Coastguard Worker 
282*8d67ca89SAndroid Build Coastguard Worker  private:
CountOpenFds()283*8d67ca89SAndroid Build Coastguard Worker   static size_t CountOpenFds() {
284*8d67ca89SAndroid Build Coastguard Worker     auto fd_dir = std::unique_ptr<DIR, decltype(&closedir)>{ opendir("/proc/self/fd"), closedir };
285*8d67ca89SAndroid Build Coastguard Worker     size_t count = 0;
286*8d67ca89SAndroid Build Coastguard Worker     dirent* de = nullptr;
287*8d67ca89SAndroid Build Coastguard Worker     while ((de = readdir(fd_dir.get())) != nullptr) {
288*8d67ca89SAndroid Build Coastguard Worker       if (de->d_type == DT_LNK) {
289*8d67ca89SAndroid Build Coastguard Worker         ++count;
290*8d67ca89SAndroid Build Coastguard Worker       }
291*8d67ca89SAndroid Build Coastguard Worker     }
292*8d67ca89SAndroid Build Coastguard Worker     return count;
293*8d67ca89SAndroid Build Coastguard Worker   }
294*8d67ca89SAndroid Build Coastguard Worker 
295*8d67ca89SAndroid Build Coastguard Worker   size_t start_count_ = CountOpenFds();
296*8d67ca89SAndroid Build Coastguard Worker };
297*8d67ca89SAndroid Build Coastguard Worker 
running_with_mte()298*8d67ca89SAndroid Build Coastguard Worker static inline bool running_with_mte() {
299*8d67ca89SAndroid Build Coastguard Worker #ifdef __aarch64__
300*8d67ca89SAndroid Build Coastguard Worker   int level = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
301*8d67ca89SAndroid Build Coastguard Worker   return level >= 0 && (level & PR_TAGGED_ADDR_ENABLE) &&
302*8d67ca89SAndroid Build Coastguard Worker          (level & PR_MTE_TCF_MASK) != PR_MTE_TCF_NONE;
303*8d67ca89SAndroid Build Coastguard Worker #else
304*8d67ca89SAndroid Build Coastguard Worker   return false;
305*8d67ca89SAndroid Build Coastguard Worker #endif
306*8d67ca89SAndroid Build Coastguard Worker }
307*8d67ca89SAndroid Build Coastguard Worker 
308*8d67ca89SAndroid Build Coastguard Worker bool IsLowRamDevice();
309*8d67ca89SAndroid Build Coastguard Worker 
310*8d67ca89SAndroid Build Coastguard Worker int64_t NanoTime();
311*8d67ca89SAndroid Build Coastguard Worker 
312*8d67ca89SAndroid Build Coastguard Worker class Errno {
313*8d67ca89SAndroid Build Coastguard Worker  public:
Errno(int e)314*8d67ca89SAndroid Build Coastguard Worker   Errno(int e) : errno_(e) {}
315*8d67ca89SAndroid Build Coastguard Worker   int errno_;
316*8d67ca89SAndroid Build Coastguard Worker };
317*8d67ca89SAndroid Build Coastguard Worker void PrintTo(const Errno& e, std::ostream* os);
318*8d67ca89SAndroid Build Coastguard Worker bool operator==(const Errno& lhs, const Errno& rhs);
319*8d67ca89SAndroid Build Coastguard Worker #define ASSERT_ERRNO(expected_errno) ASSERT_EQ(Errno(expected_errno), Errno(errno))
320*8d67ca89SAndroid Build Coastguard Worker #define EXPECT_ERRNO(expected_errno) EXPECT_EQ(Errno(expected_errno), Errno(errno))
321