michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "shared-libraries.h" michael@0: michael@0: #define PATH_MAX_TOSTRING(x) #x michael@0: #define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x) michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include "platform.h" michael@0: #include "shared-libraries.h" michael@0: michael@0: #if !defined(MOZ_WIDGET_GONK) michael@0: // TODO fix me with proper include michael@0: #include "nsDebug.h" michael@0: #ifdef ANDROID michael@0: #include "ElfLoader.h" // dl_phdr_info michael@0: #else michael@0: #include // dl_phdr_info michael@0: #endif michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #ifdef ANDROID michael@0: extern "C" __attribute__((weak)) michael@0: int dl_iterate_phdr( michael@0: int (*callback) (struct dl_phdr_info *info, michael@0: size_t size, void *data), michael@0: void *data); michael@0: #endif michael@0: michael@0: int dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data) michael@0: { michael@0: SharedLibraryInfo& info = *reinterpret_cast(data); michael@0: michael@0: if (dl_info->dlpi_phnum <= 0) michael@0: return 0; michael@0: michael@0: unsigned long libStart = -1; michael@0: unsigned long libEnd = 0; michael@0: michael@0: for (size_t i = 0; i < dl_info->dlpi_phnum; i++) { michael@0: if (dl_info->dlpi_phdr[i].p_type != PT_LOAD) { michael@0: continue; michael@0: } michael@0: unsigned long start = dl_info->dlpi_addr + dl_info->dlpi_phdr[i].p_vaddr; michael@0: unsigned long end = start + dl_info->dlpi_phdr[i].p_memsz; michael@0: if (start < libStart) michael@0: libStart = start; michael@0: if (end > libEnd) michael@0: libEnd = end; michael@0: } michael@0: SharedLibrary shlib(libStart, libEnd, 0, "", dl_info->dlpi_name); michael@0: info.AddSharedLibrary(shlib); michael@0: michael@0: return 0; michael@0: } michael@0: #endif michael@0: michael@0: SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() michael@0: { michael@0: SharedLibraryInfo info; michael@0: michael@0: #if !defined(MOZ_WIDGET_GONK) michael@0: dl_iterate_phdr(dl_iterate_callback, &info); michael@0: #ifndef ANDROID michael@0: return info; michael@0: #endif michael@0: #endif michael@0: michael@0: pid_t pid = getpid(); michael@0: char path[PATH_MAX]; michael@0: snprintf(path, PATH_MAX, "/proc/%d/maps", pid); michael@0: std::ifstream maps(path); michael@0: std::string line; michael@0: int count = 0; michael@0: while (std::getline(maps, line)) { michael@0: int ret; michael@0: //XXX: needs input sanitizing michael@0: unsigned long start; michael@0: unsigned long end; michael@0: char perm[6] = ""; michael@0: unsigned long offset; michael@0: char name[PATH_MAX] = ""; michael@0: ret = sscanf(line.c_str(), michael@0: "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n", michael@0: &start, &end, perm, &offset, name); michael@0: if (!strchr(perm, 'x')) { michael@0: // Ignore non executable entries michael@0: continue; michael@0: } michael@0: if (ret != 5 && ret != 4) { michael@0: LOG("Get maps line failed"); michael@0: continue; michael@0: } michael@0: #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) michael@0: // Use proc/pid/maps to get the dalvik-jit section since it has michael@0: // no associated phdrs michael@0: if (strcmp(name, "/dev/ashmem/dalvik-jit-code-cache") != 0) michael@0: continue; michael@0: #else michael@0: if (strcmp(perm, "r-xp") != 0) { michael@0: // Ignore entries that are writable and/or shared. michael@0: // At least one graphics driver uses short-lived "rwxs" mappings michael@0: // (see bug 926734 comment 5), so just checking for 'x' isn't enough. michael@0: continue; michael@0: } michael@0: #endif michael@0: SharedLibrary shlib(start, end, offset, "", name); michael@0: info.AddSharedLibrary(shlib); michael@0: if (count > 10000) { michael@0: LOG("Get maps failed"); michael@0: break; michael@0: } michael@0: count++; michael@0: } michael@0: return info; michael@0: }