Skip to content
Permalink
Browse files

[android][runtime] Load metadata using /proc/self/maps

As in 62cdab7,
use `/proc/self/maps`, instead of `dl_iterate_phdr`.
  • Loading branch information...
modocache committed Jan 20, 2016
1 parent 9b3db6e commit 32391abf733831131939c82d1d5d7eefd8d3743d
Showing with 64 additions and 0 deletions.
  1. +64 −0 stdlib/public/runtime/MetadataLookup.cpp
@@ -150,6 +150,67 @@ static void _addImageTypeMetadataRecords(const mach_header *mh,

_addImageTypeMetadataRecordsBlock(records, recordsSize);
}

#elif defined(__ANDROID__)
#include <climits>
#include <cstdio>
#include <unordered_set>
#include <unistd.h>

static void _addImageTypeMetadataRecords(const char *name) {
void *handle = dlopen(name, RTLD_LAZY);
if (!handle)
return; // not a shared library
auto records = reinterpret_cast<const uint8_t*>(
dlsym(handle, SWIFT_TYPE_METADATA_SECTION));

if (!records) {
// if there are no records, don't hold this handle open.
dlclose(handle);
return;
}

// Extract the size of the conformances block from the head of the section
auto recordsSize = *reinterpret_cast<const uint64_t*>(records);
records += sizeof(recordsSize);

_addImageTypeMetadataRecordsBlock(records, recordsSize);

dlclose(handle);
}

static void android_iterate_libs(void (*callback)(const char*)) {
std::unordered_set<std::string> already;
FILE* f = fopen("/proc/self/maps", "r");
if (!f)
return;
char ownname[PATH_MAX + 1];
if (readlink("/proc/self/exe", ownname, sizeof(ownname)) == -1) {
fprintf(stderr, "swift: can't find path of executable\n");
ownname[0] = '\0';
}

char name[PATH_MAX + 1];
char perms[4 + 1];
while (fscanf(f, " %*s %4c %*s %*s %*s%*[ ]%[^\n]", perms, name) > 0) {
if (perms[2] != 'x' || name[0] != '/')
continue;
if (strncmp(name, "/dev/", 5) == 0)
continue;
std::string name_str = name;
if (already.count(name_str) != 0)
continue;
already.insert(name_str);
const char* libname = name_str.c_str();
if (strcmp(libname, ownname) == 0) {
// need to pass null if opening main executable
libname = nullptr;
}
callback(libname);
}
fclose(f);
}

#elif defined(__ELF__)
static int _addImageTypeMetadataRecords(struct dl_phdr_info *info,
size_t size, void * /*data*/) {
@@ -184,6 +245,9 @@ static void _initializeCallbacksToInspectDylib() {
// Dyld will invoke this on our behalf for all images that have already
// been loaded.
_dyld_register_func_for_add_image(_addImageTypeMetadataRecords);
#elif defined(__ANDROID__)
// Android only gained dl_iterate_phdr in API 21, so use /proc/self/maps
android_iterate_libs(_addImageTypeMetadataRecords);
#elif defined(__ELF__)
// Search the loaded dls. Unlike the above, this only searches the already
// loaded ones.

2 comments on commit 32391ab

@ephemer

This comment has been minimized.

Copy link
Member

replied Jan 20, 2016

What does this change mean practically for code usability / stability? PS. Great to have you on board @modocache!

@modocache

This comment has been minimized.

Copy link
Member Author

replied Jan 20, 2016

This became necessary after rebasing onto apple/swift master. It mirrors 62cdab7 and is required to build the project; see: https://github.com/SwiftAndroid/swift/wiki/Getting-started#building-from-source 👍

Please sign in to comment.
You can’t perform that action at this time.