@@ -2397,10 +2397,56 @@ static void _addImageProtocolConformances(const mach_header *mh,
23972397
23982398 _addImageProtocolConformancesBlock (conformances, conformancesSize);
23992399}
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+
24002449#elif defined(__ELF__)
2401- #ifdef __ANDROID__
2402- #define RTLD_NOLOAD 0
2403- #endif
24042450
24052451static int _addImageProtocolConformances (struct dl_phdr_info *info,
24062452 size_t size, void * /* data*/ ) {
@@ -2437,15 +2483,15 @@ static void installCallbacksToInspectDylib() {
24372483 // Dyld will invoke this on our behalf for all images that have already
24382484 // been loaded.
24392485 _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);
24402489 #elif defined(__ELF__)
24412490 // Search the loaded dls. Unlike the above, this only searches the already
24422491 // loaded ones.
24432492 // FIXME: Find a way to have this continue to happen after.
24442493 // rdar://problem/19045112
2445- #ifndef __ANDROID__
2446- // FIXME: Android: doesn't have dl_iterate_phdr before API 21
24472494 dl_iterate_phdr (_addImageProtocolConformances, nullptr );
2448- #endif
24492495 #else
24502496 # error No known mechanism to inspect dynamic libraries on this platform.
24512497 #endif
0 commit comments