@@ -2397,10 +2397,56 @@ static void _addImageProtocolConformances(const mach_header *mh,
2397
2397
2398
2398
_addImageProtocolConformancesBlock (conformances, conformancesSize);
2399
2399
}
2400
+ #elif defined(__ANDROID__)
2401
+ #include < climits>
2402
+ #include < cstdio>
2403
+ #include < unordered_set>
2404
+
2405
+ static void _addImageProtocolConformances (std::string const & name) {
2406
+ // FIXME: Android: special case the current executable?
2407
+ void *handle = dlopen (name.c_str (), RTLD_LAZY);
2408
+ if (!handle)
2409
+ return ; // not a shared library
2410
+ auto conformances = reinterpret_cast <const uint8_t *>(
2411
+ dlsym (handle, SWIFT_PROTOCOL_CONFORMANCES_SECTION));
2412
+
2413
+ if (!conformances) {
2414
+ // if there are no conformances, don't hold this handle open.
2415
+ dlclose (handle);
2416
+ return ;
2417
+ }
2418
+
2419
+ // Extract the size of the conformances block from the head of the section
2420
+ auto conformancesSize = *reinterpret_cast <const uint64_t *>(conformances);
2421
+ conformances += sizeof (conformancesSize);
2422
+
2423
+ _addImageProtocolConformancesBlock (conformances, conformancesSize);
2424
+
2425
+ dlclose (handle);
2426
+ }
2427
+
2428
+ static void android_iterate_libs (void (*callback)(std::string const &)) {
2429
+ std::unordered_set<std::string> already;
2430
+ FILE* f = fopen (" /proc/self/maps" , " r" );
2431
+ if (!f)
2432
+ return ;
2433
+ char name[PATH_MAX + 1 ];
2434
+ char perms[4 + 1 ];
2435
+ while (fscanf (f, " %*s %4c %*s %*s %*s%*[ ]%[^\n ]" , perms, name) > 0 ) {
2436
+ if (perms[2 ] != ' x' || name[0 ] != ' /' )
2437
+ continue ;
2438
+ if (strncmp (name, " /dev/" , 5 ) == 0 )
2439
+ continue ;
2440
+ std::string name_str = name;
2441
+ if (already.count (name_str) != 0 )
2442
+ continue ;
2443
+ already.insert (name_str);
2444
+ callback (name_str);
2445
+ }
2446
+ fclose (f);
2447
+ }
2448
+
2400
2449
#elif defined(__ELF__)
2401
- #ifdef __ANDROID__
2402
- #define RTLD_NOLOAD 0
2403
- #endif
2404
2450
2405
2451
static int _addImageProtocolConformances (struct dl_phdr_info *info,
2406
2452
size_t size, void * /* data*/ ) {
@@ -2437,15 +2483,15 @@ static void installCallbacksToInspectDylib() {
2437
2483
// Dyld will invoke this on our behalf for all images that have already
2438
2484
// been loaded.
2439
2485
_dyld_register_func_for_add_image (_addImageProtocolConformances);
2486
+ #elif defined(__ANDROID__)
2487
+ // Android only gained dl_iterate_phdr in API 21, so use /proc/self/maps
2488
+ android_iterate_libs (_addImageProtocolConformances);
2440
2489
#elif defined(__ELF__)
2441
2490
// Search the loaded dls. Unlike the above, this only searches the already
2442
2491
// loaded ones.
2443
2492
// FIXME: Find a way to have this continue to happen after.
2444
2493
// rdar://problem/19045112
2445
- #ifndef __ANDROID__
2446
- // FIXME: Android: doesn't have dl_iterate_phdr before API 21
2447
2494
dl_iterate_phdr (_addImageProtocolConformances, nullptr );
2448
- #endif
2449
2495
#else
2450
2496
# error No known mechanism to inspect dynamic libraries on this platform.
2451
2497
#endif
0 commit comments