c67c5e657f589ab51c84039bb35f068c278af57d
[iec.git] / src / type3_AndroidCloud / anbox-master / external / cpu_features / src / hwcaps.c
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "cpu_features_macros.h"
19 #include "internal/filesystem.h"
20 #include "internal/hwcaps.h"
21 #include "internal/string_view.h"
22
23 #if defined(NDEBUG)
24 #define D(...)
25 #else
26 #include <stdio.h>
27 #define D(...)           \
28   do {                   \
29     printf(__VA_ARGS__); \
30     fflush(stdout);      \
31   } while (0)
32 #endif
33
34 #if defined(CPU_FEATURES_ARCH_MIPS) || defined(CPU_FEATURES_ARCH_ANY_ARM)
35 #define HWCAPS_ANDROID_MIPS_OR_ARM
36 #endif
37
38 #if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) && \
39     !defined(HWCAPS_ANDROID_MIPS_OR_ARM)
40 #define HWCAPS_REGULAR_LINUX
41 #endif
42
43 #if defined(HWCAPS_ANDROID_MIPS_OR_ARM) || defined(HWCAPS_REGULAR_LINUX)
44 #define HWCAPS_SUPPORTED
45 #endif
46
47 ////////////////////////////////////////////////////////////////////////////////
48 // Implementation of GetElfHwcapFromGetauxval
49 ////////////////////////////////////////////////////////////////////////////////
50
51 // On Linux we simply use getauxval.
52 #if defined(HWCAPS_REGULAR_LINUX)
53 #include <dlfcn.h>
54 #include <sys/auxv.h>
55 static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
56   return getauxval(hwcap_type);
57 }
58 #endif  // defined(HWCAPS_REGULAR_LINUX)
59
60 // On Android we probe the system's C library for a 'getauxval' function and
61 // call it if it exits, or return 0 for failure. This function is available
62 // since API level 20.
63 //
64 // This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge
65 // case where some NDK developers use headers for a platform that is newer than
66 // the one really targetted by their application. This is typically done to use
67 // newer native APIs only when running on more recent Android versions, and
68 // requires careful symbol management.
69 //
70 // Note that getauxval() can't really be re-implemented here, because its
71 // implementation does not parse /proc/self/auxv. Instead it depends on values
72 // that are passed by the kernel at process-init time to the C runtime
73 // initialization layer.
74 #if defined(HWCAPS_ANDROID_MIPS_OR_ARM)
75 #include <dlfcn.h>
76 #define AT_HWCAP 16
77 #define AT_HWCAP2 26
78 #define AT_PLATFORM 15
79 #define AT_BASE_PLATFORM 24
80
81 typedef unsigned long getauxval_func_t(unsigned long);
82
83 static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
84   uint32_t ret = 0;
85   void* libc_handle = NULL;
86   getauxval_func_t* func = NULL;
87
88   dlerror();  // Cleaning error state before calling dlopen.
89   libc_handle = dlopen("libc.so", RTLD_NOW);
90   if (!libc_handle) {
91     D("Could not dlopen() C library: %s\n", dlerror());
92     return 0;
93   }
94   func = (getauxval_func_t*)dlsym(libc_handle, "getauxval");
95   if (!func) {
96     D("Could not find getauxval() in C library\n");
97   } else {
98     // Note: getauxval() returns 0 on failure. Doesn't touch errno.
99     ret = (uint32_t)(*func)(hwcap_type);
100   }
101   dlclose(libc_handle);
102   return ret;
103 }
104 #endif  // defined(HWCAPS_ANDROID_MIPS_OR_ARM)
105
106 #if defined(HWCAPS_SUPPORTED)
107 ////////////////////////////////////////////////////////////////////////////////
108 // Implementation of GetHardwareCapabilities for Android and Linux
109 ////////////////////////////////////////////////////////////////////////////////
110
111 // Fallback when getauxval is not available, retrieves hwcaps from
112 // "/proc/self/auxv".
113 static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
114   struct {
115     uint32_t tag;
116     uint32_t value;
117   } entry;
118   uint32_t result = 0;
119   const char filepath[] = "/proc/self/auxv";
120   const int fd = CpuFeatures_OpenFile(filepath);
121   if (fd < 0) {
122     D("Could not open %s\n", filepath);
123     return 0;
124   }
125   for (;;) {
126     const int ret = CpuFeatures_ReadFile(fd, (char*)&entry, sizeof entry);
127     if (ret < 0) {
128       D("Error while reading %s\n", filepath);
129       break;
130     }
131     // Detect end of list.
132     if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
133       break;
134     }
135     if (entry.tag == hwcap_type) {
136       result = entry.value;
137       break;
138     }
139   }
140   CpuFeatures_CloseFile(fd);
141   return result;
142 }
143
144 // Retrieves hardware capabilities by first trying to call getauxval, if not
145 // available falls back to reading "/proc/self/auxv".
146 static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
147   unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
148   if (!hwcaps) {
149     D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
150     hwcaps = GetElfHwcapFromProcSelfAuxv(type);
151   }
152   return hwcaps;
153 }
154
155 HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
156   HardwareCapabilities capabilities;
157   capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
158   capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
159   return capabilities;
160 }
161
162 PlatformType kEmptyPlatformType;
163
164 PlatformType CpuFeatures_GetPlatformType(void) {
165   PlatformType type = kEmptyPlatformType;
166   char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
167   char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
168
169   if (platform != NULL)
170     CpuFeatures_StringView_CopyString(str(platform), type.platform,
171                                       sizeof(type.platform));
172   if (base_platform != NULL)
173     CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform,
174                                       sizeof(type.base_platform));
175   return type;
176 }
177 #else  // (defined(HWCAPS_SUPPORTED)
178
179 ////////////////////////////////////////////////////////////////////////////////
180 // Implementation of GetHardwareCapabilities for unsupported platforms.
181 ////////////////////////////////////////////////////////////////////////////////
182
183 const HardwareCapabilities kEmptyHardwareCapabilities;
184 HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
185   return kEmptyHardwareCapabilities;
186 }
187 #endif