Skip to content

Commit 65921fc

Browse files
committed
android: load conformance data by reading /proc/self/maps, copy swift.ld for Android target
Hello world works now!
1 parent a1e0e5f commit 65921fc

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

stdlib/public/runtime/CMakeLists.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ add_swift_library(swiftRuntime IS_STDLIB IS_STDLIB_CORE
7272
INSTALL_IN_COMPONENT stdlib)
7373

7474
foreach(sdk ${SWIFT_CONFIGURED_SDKS})
75-
if("${sdk}" STREQUAL "LINUX")
75+
if("${sdk}" STREQUAL "LINUX" OR "${sdk}" STREQUAL "ANDROID")
7676
foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
7777
set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
7878

@@ -86,6 +86,5 @@ foreach(sdk ${SWIFT_CONFIGURED_SDKS})
8686

8787
endforeach()
8888
endif()
89-
# FIXME: Android: make a swift.ld for armv7 android
9089
endforeach()
9190

stdlib/public/runtime/Casting.cpp

+52-6
Original file line numberDiff line numberDiff line change
@@ -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

24052451
static 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

Comments
 (0)