xref: /aosp_15_r20/bionic/tests/malloc_iterate_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2018 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 #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
20*8d67ca89SAndroid Build Coastguard Worker 
21*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <time.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
26*8d67ca89SAndroid Build Coastguard Worker 
27*8d67ca89SAndroid Build Coastguard Worker #include <vector>
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include <android-base/test_utils.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <async_safe/log.h>
31*8d67ca89SAndroid Build Coastguard Worker #include <procinfo/process_map.h>
32*8d67ca89SAndroid Build Coastguard Worker 
33*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
34*8d67ca89SAndroid Build Coastguard Worker 
35*8d67ca89SAndroid Build Coastguard Worker extern "C" void malloc_disable();
36*8d67ca89SAndroid Build Coastguard Worker extern "C" void malloc_enable();
37*8d67ca89SAndroid Build Coastguard Worker extern "C" int malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t base,
38*8d67ca89SAndroid Build Coastguard Worker                               size_t size, void* arg), void* arg);
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker struct AllocDataType {
41*8d67ca89SAndroid Build Coastguard Worker   void* ptr;
42*8d67ca89SAndroid Build Coastguard Worker   size_t size;
43*8d67ca89SAndroid Build Coastguard Worker   size_t size_reported;
44*8d67ca89SAndroid Build Coastguard Worker   size_t count;
45*8d67ca89SAndroid Build Coastguard Worker };
46*8d67ca89SAndroid Build Coastguard Worker 
47*8d67ca89SAndroid Build Coastguard Worker struct TestDataType {
48*8d67ca89SAndroid Build Coastguard Worker   size_t total_allocated_bytes;
49*8d67ca89SAndroid Build Coastguard Worker   std::vector<AllocDataType> allocs;
50*8d67ca89SAndroid Build Coastguard Worker };
51*8d67ca89SAndroid Build Coastguard Worker 
AllocPtr(TestDataType * test_data,size_t size)52*8d67ca89SAndroid Build Coastguard Worker static void AllocPtr(TestDataType* test_data, size_t size) {
53*8d67ca89SAndroid Build Coastguard Worker   test_data->allocs.resize(test_data->allocs.size() + 1);
54*8d67ca89SAndroid Build Coastguard Worker   AllocDataType* alloc = &test_data->allocs.back();
55*8d67ca89SAndroid Build Coastguard Worker   void* ptr = malloc(size);
56*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(ptr != nullptr);
57*8d67ca89SAndroid Build Coastguard Worker   alloc->ptr = ptr;
58*8d67ca89SAndroid Build Coastguard Worker   alloc->size = malloc_usable_size(ptr);
59*8d67ca89SAndroid Build Coastguard Worker   alloc->size_reported = 0;
60*8d67ca89SAndroid Build Coastguard Worker   alloc->count = 0;
61*8d67ca89SAndroid Build Coastguard Worker }
62*8d67ca89SAndroid Build Coastguard Worker 
FreePtrs(TestDataType * test_data)63*8d67ca89SAndroid Build Coastguard Worker static void FreePtrs(TestDataType* test_data) {
64*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < test_data->allocs.size(); i++) {
65*8d67ca89SAndroid Build Coastguard Worker     free(test_data->allocs[i].ptr);
66*8d67ca89SAndroid Build Coastguard Worker   }
67*8d67ca89SAndroid Build Coastguard Worker }
68*8d67ca89SAndroid Build Coastguard Worker 
SavePointers(uintptr_t base,size_t size,void * data)69*8d67ca89SAndroid Build Coastguard Worker static void SavePointers(uintptr_t base, size_t size, void* data) {
70*8d67ca89SAndroid Build Coastguard Worker   TestDataType* test_data = reinterpret_cast<TestDataType*>(data);
71*8d67ca89SAndroid Build Coastguard Worker 
72*8d67ca89SAndroid Build Coastguard Worker   test_data->total_allocated_bytes += size;
73*8d67ca89SAndroid Build Coastguard Worker 
74*8d67ca89SAndroid Build Coastguard Worker   uintptr_t end;
75*8d67ca89SAndroid Build Coastguard Worker   if (__builtin_add_overflow(base, size, &end)) {
76*8d67ca89SAndroid Build Coastguard Worker     // Skip this entry.
77*8d67ca89SAndroid Build Coastguard Worker     return;
78*8d67ca89SAndroid Build Coastguard Worker   }
79*8d67ca89SAndroid Build Coastguard Worker 
80*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < test_data->allocs.size(); i++) {
81*8d67ca89SAndroid Build Coastguard Worker     uintptr_t ptr = reinterpret_cast<uintptr_t>(test_data->allocs[i].ptr);
82*8d67ca89SAndroid Build Coastguard Worker     if (ptr >= base && ptr < end) {
83*8d67ca89SAndroid Build Coastguard Worker       test_data->allocs[i].count++;
84*8d67ca89SAndroid Build Coastguard Worker 
85*8d67ca89SAndroid Build Coastguard Worker       uintptr_t max_size = end - ptr;
86*8d67ca89SAndroid Build Coastguard Worker       if (max_size > test_data->allocs[i].size) {
87*8d67ca89SAndroid Build Coastguard Worker         test_data->allocs[i].size_reported = test_data->allocs[i].size;
88*8d67ca89SAndroid Build Coastguard Worker       } else {
89*8d67ca89SAndroid Build Coastguard Worker         test_data->allocs[i].size_reported = max_size;
90*8d67ca89SAndroid Build Coastguard Worker       }
91*8d67ca89SAndroid Build Coastguard Worker     }
92*8d67ca89SAndroid Build Coastguard Worker   }
93*8d67ca89SAndroid Build Coastguard Worker }
94*8d67ca89SAndroid Build Coastguard Worker 
VerifyPtrs(TestDataType * test_data)95*8d67ca89SAndroid Build Coastguard Worker static void VerifyPtrs(TestDataType* test_data) {
96*8d67ca89SAndroid Build Coastguard Worker   test_data->total_allocated_bytes = 0;
97*8d67ca89SAndroid Build Coastguard Worker 
98*8d67ca89SAndroid Build Coastguard Worker   // Find all of the maps that are from the native allocator.
99*8d67ca89SAndroid Build Coastguard Worker   auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name,
100*8d67ca89SAndroid Build Coastguard Worker                       bool) {
101*8d67ca89SAndroid Build Coastguard Worker     if (strcmp(name, "[anon:libc_malloc]") == 0 || strncmp(name, "[anon:scudo:", 12) == 0 ||
102*8d67ca89SAndroid Build Coastguard Worker         strncmp(name, "[anon:GWP-ASan", 14) == 0) {
103*8d67ca89SAndroid Build Coastguard Worker       malloc_iterate(start, end - start, SavePointers, test_data);
104*8d67ca89SAndroid Build Coastguard Worker     }
105*8d67ca89SAndroid Build Coastguard Worker   };
106*8d67ca89SAndroid Build Coastguard Worker 
107*8d67ca89SAndroid Build Coastguard Worker   std::vector<char> buffer(64 * 1024);
108*8d67ca89SAndroid Build Coastguard Worker 
109*8d67ca89SAndroid Build Coastguard Worker   // Avoid doing allocations so that the maps don't change while looking
110*8d67ca89SAndroid Build Coastguard Worker   // for the pointers.
111*8d67ca89SAndroid Build Coastguard Worker   malloc_disable();
112*8d67ca89SAndroid Build Coastguard Worker   bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer.data(),
113*8d67ca89SAndroid Build Coastguard Worker                                                         buffer.size(), callback);
114*8d67ca89SAndroid Build Coastguard Worker   malloc_enable();
115*8d67ca89SAndroid Build Coastguard Worker 
116*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(parsed) << "Failed to parse /proc/self/maps";
117*8d67ca89SAndroid Build Coastguard Worker 
118*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < test_data->allocs.size(); i++) {
119*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(1UL, test_data->allocs[i].count) << "Failed on size " << test_data->allocs[i].size;
120*8d67ca89SAndroid Build Coastguard Worker     if (test_data->allocs[i].count == 1) {
121*8d67ca89SAndroid Build Coastguard Worker       EXPECT_EQ(test_data->allocs[i].size, test_data->allocs[i].size_reported);
122*8d67ca89SAndroid Build Coastguard Worker     }
123*8d67ca89SAndroid Build Coastguard Worker   }
124*8d67ca89SAndroid Build Coastguard Worker }
125*8d67ca89SAndroid Build Coastguard Worker 
AllocateSizes(TestDataType * test_data,const std::vector<size_t> & sizes)126*8d67ca89SAndroid Build Coastguard Worker static void AllocateSizes(TestDataType* test_data, const std::vector<size_t>& sizes) {
127*8d67ca89SAndroid Build Coastguard Worker   static constexpr size_t kInitialAllocations = 40;
128*8d67ca89SAndroid Build Coastguard Worker   static constexpr size_t kNumAllocs = 50;
129*8d67ca89SAndroid Build Coastguard Worker   for (size_t size : sizes) {
130*8d67ca89SAndroid Build Coastguard Worker     // Verify that if the tcache is enabled, that tcache pointers
131*8d67ca89SAndroid Build Coastguard Worker     // are found by allocating and freeing 20 pointers (should be larger
132*8d67ca89SAndroid Build Coastguard Worker     // than the total number of cache entries).
133*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < kInitialAllocations; i++) {
134*8d67ca89SAndroid Build Coastguard Worker       void* ptr = malloc(size);
135*8d67ca89SAndroid Build Coastguard Worker       ASSERT_TRUE(ptr != nullptr);
136*8d67ca89SAndroid Build Coastguard Worker       memset(ptr, 0, size);
137*8d67ca89SAndroid Build Coastguard Worker       free(ptr);
138*8d67ca89SAndroid Build Coastguard Worker     }
139*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < kNumAllocs; i++) {
140*8d67ca89SAndroid Build Coastguard Worker       AllocPtr(test_data, size);
141*8d67ca89SAndroid Build Coastguard Worker     }
142*8d67ca89SAndroid Build Coastguard Worker   }
143*8d67ca89SAndroid Build Coastguard Worker }
144*8d67ca89SAndroid Build Coastguard Worker #endif
145*8d67ca89SAndroid Build Coastguard Worker 
146*8d67ca89SAndroid Build Coastguard Worker // Verify that small allocs can be found properly.
TEST(malloc_iterate,small_allocs)147*8d67ca89SAndroid Build Coastguard Worker TEST(malloc_iterate, small_allocs) {
148*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
149*8d67ca89SAndroid Build Coastguard Worker   SKIP_WITH_HWASAN;
150*8d67ca89SAndroid Build Coastguard Worker   TestDataType test_data;
151*8d67ca89SAndroid Build Coastguard Worker 
152*8d67ca89SAndroid Build Coastguard Worker   // Try to cycle through all of the different small bins.
153*8d67ca89SAndroid Build Coastguard Worker   // This is specific to the implementation of jemalloc and should be
154*8d67ca89SAndroid Build Coastguard Worker   // adjusted if a different native memory allocator is used.
155*8d67ca89SAndroid Build Coastguard Worker   std::vector<size_t> sizes{8,    16,   32,   48,    64,    80,    96,    112,   128,  160,
156*8d67ca89SAndroid Build Coastguard Worker                             192,  224,  256,  320,   384,   448,   512,   640,   768,  896,
157*8d67ca89SAndroid Build Coastguard Worker                             1024, 1280, 1536, 1792,  2048,  2560,  3072,  3584,  4096, 5120,
158*8d67ca89SAndroid Build Coastguard Worker                             6144, 7168, 8192, 10240, 12288, 14336, 16384, 32768, 65536};
159*8d67ca89SAndroid Build Coastguard Worker   AllocateSizes(&test_data, sizes);
160*8d67ca89SAndroid Build Coastguard Worker 
161*8d67ca89SAndroid Build Coastguard Worker   SCOPED_TRACE("");
162*8d67ca89SAndroid Build Coastguard Worker   VerifyPtrs(&test_data);
163*8d67ca89SAndroid Build Coastguard Worker 
164*8d67ca89SAndroid Build Coastguard Worker   FreePtrs(&test_data);
165*8d67ca89SAndroid Build Coastguard Worker #else
166*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "bionic-only test";
167*8d67ca89SAndroid Build Coastguard Worker #endif
168*8d67ca89SAndroid Build Coastguard Worker }
169*8d67ca89SAndroid Build Coastguard Worker 
170*8d67ca89SAndroid Build Coastguard Worker // Verify that large allocs can be found properly.
TEST(malloc_iterate,large_allocs)171*8d67ca89SAndroid Build Coastguard Worker TEST(malloc_iterate, large_allocs) {
172*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
173*8d67ca89SAndroid Build Coastguard Worker   SKIP_WITH_HWASAN;
174*8d67ca89SAndroid Build Coastguard Worker   TestDataType test_data;
175*8d67ca89SAndroid Build Coastguard Worker 
176*8d67ca89SAndroid Build Coastguard Worker   // Try some larger sizes.
177*8d67ca89SAndroid Build Coastguard Worker   std::vector<size_t> sizes{131072, 262144, 524288, 1048576, 2097152};
178*8d67ca89SAndroid Build Coastguard Worker   AllocateSizes(&test_data, sizes);
179*8d67ca89SAndroid Build Coastguard Worker 
180*8d67ca89SAndroid Build Coastguard Worker   SCOPED_TRACE("");
181*8d67ca89SAndroid Build Coastguard Worker   VerifyPtrs(&test_data);
182*8d67ca89SAndroid Build Coastguard Worker 
183*8d67ca89SAndroid Build Coastguard Worker   FreePtrs(&test_data);
184*8d67ca89SAndroid Build Coastguard Worker #else
185*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "bionic-only test";
186*8d67ca89SAndroid Build Coastguard Worker #endif
187*8d67ca89SAndroid Build Coastguard Worker }
188*8d67ca89SAndroid Build Coastguard Worker 
189*8d67ca89SAndroid Build Coastguard Worker // Verify that there are no crashes attempting to get pointers from
190*8d67ca89SAndroid Build Coastguard Worker // non-allocated pointers.
TEST(malloc_iterate,invalid_pointers)191*8d67ca89SAndroid Build Coastguard Worker TEST(malloc_iterate, invalid_pointers) {
192*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
193*8d67ca89SAndroid Build Coastguard Worker   SKIP_WITH_HWASAN;
194*8d67ca89SAndroid Build Coastguard Worker   TestDataType test_data = {};
195*8d67ca89SAndroid Build Coastguard Worker 
196*8d67ca89SAndroid Build Coastguard Worker   // Only attempt to get memory data for maps that are not from the native allocator.
197*8d67ca89SAndroid Build Coastguard Worker   auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name,
198*8d67ca89SAndroid Build Coastguard Worker                       bool) {
199*8d67ca89SAndroid Build Coastguard Worker     if (strcmp(name, "[anon:libc_malloc]") != 0 && strncmp(name, "[anon:scudo:", 12) != 0 &&
200*8d67ca89SAndroid Build Coastguard Worker         strncmp(name, "[anon:GWP-ASan", 14) != 0) {
201*8d67ca89SAndroid Build Coastguard Worker       size_t total = test_data.total_allocated_bytes;
202*8d67ca89SAndroid Build Coastguard Worker       malloc_iterate(start, end - start, SavePointers, &test_data);
203*8d67ca89SAndroid Build Coastguard Worker       total = test_data.total_allocated_bytes - total;
204*8d67ca89SAndroid Build Coastguard Worker       if (total > 0) {
205*8d67ca89SAndroid Build Coastguard Worker         char buffer[256];
206*8d67ca89SAndroid Build Coastguard Worker         int len = 0;
207*8d67ca89SAndroid Build Coastguard Worker         if (name[0] != '\0') {
208*8d67ca89SAndroid Build Coastguard Worker           len = async_safe_format_buffer(buffer, sizeof(buffer), "Failed on map %s: %zu\n", name,
209*8d67ca89SAndroid Build Coastguard Worker                                          total);
210*8d67ca89SAndroid Build Coastguard Worker         } else {
211*8d67ca89SAndroid Build Coastguard Worker           len = async_safe_format_buffer(buffer, sizeof(buffer),
212*8d67ca89SAndroid Build Coastguard Worker                                          "Failed on map anon:<%" PRIx64 "-%" PRIx64 ">: %zu\n",
213*8d67ca89SAndroid Build Coastguard Worker                                          start, end, total);
214*8d67ca89SAndroid Build Coastguard Worker         }
215*8d67ca89SAndroid Build Coastguard Worker         if (len > 0) {
216*8d67ca89SAndroid Build Coastguard Worker           write(STDOUT_FILENO, buffer, len);
217*8d67ca89SAndroid Build Coastguard Worker         }
218*8d67ca89SAndroid Build Coastguard Worker       }
219*8d67ca89SAndroid Build Coastguard Worker     }
220*8d67ca89SAndroid Build Coastguard Worker   };
221*8d67ca89SAndroid Build Coastguard Worker 
222*8d67ca89SAndroid Build Coastguard Worker   std::vector<char> buffer(64 * 1024);
223*8d67ca89SAndroid Build Coastguard Worker 
224*8d67ca89SAndroid Build Coastguard Worker   // Need to make sure that there are no allocations while reading the
225*8d67ca89SAndroid Build Coastguard Worker   // maps. Otherwise, it might create a new map during this check and
226*8d67ca89SAndroid Build Coastguard Worker   // incorrectly think a map is empty while it actually includes real
227*8d67ca89SAndroid Build Coastguard Worker   // allocations.
228*8d67ca89SAndroid Build Coastguard Worker   malloc_disable();
229*8d67ca89SAndroid Build Coastguard Worker   bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer.data(),
230*8d67ca89SAndroid Build Coastguard Worker                                                         buffer.size(), callback);
231*8d67ca89SAndroid Build Coastguard Worker   malloc_enable();
232*8d67ca89SAndroid Build Coastguard Worker 
233*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(parsed) << "Failed to parse /proc/self/maps";
234*8d67ca89SAndroid Build Coastguard Worker 
235*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0UL, test_data.total_allocated_bytes);
236*8d67ca89SAndroid Build Coastguard Worker #else
237*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "bionic-only test";
238*8d67ca89SAndroid Build Coastguard Worker #endif
239*8d67ca89SAndroid Build Coastguard Worker }
240*8d67ca89SAndroid Build Coastguard Worker 
TEST(malloc_iterate,malloc_disable_prevents_allocs)241*8d67ca89SAndroid Build Coastguard Worker TEST(malloc_iterate, malloc_disable_prevents_allocs) {
242*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
243*8d67ca89SAndroid Build Coastguard Worker   SKIP_WITH_HWASAN;
244*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
245*8d67ca89SAndroid Build Coastguard Worker   if ((pid = fork()) == 0) {
246*8d67ca89SAndroid Build Coastguard Worker     malloc_disable();
247*8d67ca89SAndroid Build Coastguard Worker     void* ptr = malloc(1024);
248*8d67ca89SAndroid Build Coastguard Worker     if (ptr == nullptr) {
249*8d67ca89SAndroid Build Coastguard Worker       exit(1);
250*8d67ca89SAndroid Build Coastguard Worker     }
251*8d67ca89SAndroid Build Coastguard Worker     memset(ptr, 0, 1024);
252*8d67ca89SAndroid Build Coastguard Worker     exit(0);
253*8d67ca89SAndroid Build Coastguard Worker   }
254*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, pid);
255*8d67ca89SAndroid Build Coastguard Worker 
256*8d67ca89SAndroid Build Coastguard Worker   // Expect that the malloc will hang forever, and that if the process
257*8d67ca89SAndroid Build Coastguard Worker   // does not return for two seconds, it is hung.
258*8d67ca89SAndroid Build Coastguard Worker   sleep(2);
259*8d67ca89SAndroid Build Coastguard Worker   pid_t wait_pid = TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG));
260*8d67ca89SAndroid Build Coastguard Worker   if (wait_pid <= 0) {
261*8d67ca89SAndroid Build Coastguard Worker     kill(pid, SIGKILL);
262*8d67ca89SAndroid Build Coastguard Worker   }
263*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, wait_pid) << "Unknown failure in waitpid.";
264*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, wait_pid) << "malloc_disable did not prevent allocation calls.";
265*8d67ca89SAndroid Build Coastguard Worker #else
266*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "bionic-only test";
267*8d67ca89SAndroid Build Coastguard Worker #endif
268*8d67ca89SAndroid Build Coastguard Worker }
269