From 946b114876474f325fac8e47dc7462611390aed6 Mon Sep 17 00:00:00 2001 From: Gregory Pakosz Date: Fri, 6 Nov 2015 15:44:18 +0100 Subject: [PATCH] added support for Android M loading libraries straight from APK/ZIP files Until https://code.google.com/p/android/issues/detail?id=193009 is fixed, the only way to know the path of the library inside the APK/ZIP file is to explore the ZIP content. However, there is no need to read the ZIP central directory. We can scan backwards from the mapped offset until we find the local file header. --- src/whereami.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/whereami.c b/src/whereami.c index 3433d28..e969270 100644 --- a/src/whereami.c +++ b/src/whereami.c @@ -202,6 +202,11 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) #define WAI_PROC_SELF_MAPS "/proc/self/maps" #endif +#if defined(__ANDROID__) || defined(ANDROID) +#include +#include +#endif + WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) @@ -242,6 +247,43 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) break; length = (int)strlen(resolved); +#if defined(__ANDROID__) || defined(ANDROID) + if (length > 4 + &&buffer[length - 1] == 'k' + &&buffer[length - 2] == 'p' + &&buffer[length - 3] == 'a' + &&buffer[length - 4] == '.') + { + int fd = open(path, O_RDONLY); + char* begin; + char* p; + + begin = mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + p = begin + offset; + + while (p >= begin) // scan backwards + { + if (*((uint32_t*)p) == 0x04034b50UL) // local file header found + { + uint16_t length_ = *((uint16_t*)(p + 26)); + + if (length + 2 + length_ < sizeof(buffer)) + { + memcpy(&buffer[length], "!/", 2); + memcpy(&buffer[length + 2], p + 30, length_); + length += 2 + length_; + } + + break; + } + + p -= 4; + } + + munmap(begin, offset); + close(fd); + } +#endif if (length <= capacity) { memcpy(out, resolved, length);