diff options
author | 오창석/Advanced DX Lab(SR)/Staff Engineer/삼성전자 <seok.oh@samsung.com> | 2018-09-28 19:15:23 +0900 |
---|---|---|
committer | GitHub Enterprise <noreply-CODE@samsung.com> | 2018-09-28 19:15:23 +0900 |
commit | 9d70792c9b997452e71798568e08f74601e86378 (patch) | |
tree | 1331a7ee5062d90f18e3f5f2aeafef55d29b426c | |
parent | c393da4b3cea0915376d84da032c2d3c13af221b (diff) | |
parent | fc142e79e4746cd68d7430199f85aa8a51f9bf7f (diff) | |
download | heaptrack-tizen_5.0.tar.gz heaptrack-tizen_5.0.tar.bz2 heaptrack-tizen_5.0.zip |
Merge pull request #41 from dotnet/memory_profiler_fixsubmit/tizen_5.0/20181106.000001submit/tizen_5.0/20181101.000009submit/tizen/20181001.124515accepted/tizen/unified/20181001.150959accepted/tizen/5.0/unified/20181106.201556accepted/tizen/5.0/unified/20181102.031859tizen_5.0accepted/tizen_5.0_unified
Memory profiler fix for security capabilities
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | packaging/0001-Target-build | 43 | ||||
-rw-r--r-- | packaging/heaptrack.spec | 6 | ||||
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/track/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/track/heaptrack_inject.cpp | 221 |
6 files changed, 241 insertions, 58 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d02e780..cb73977 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,13 @@ option( On ) +option( + TIZEN + "Tizen platform" + Off +) +add_definitions(-DTIZEN=$<BOOL:${TIZEN}>) + if(HEAPTRACK_BUILD_GUI) find_package(Qt5 5.2.0 NO_MODULE OPTIONAL_COMPONENTS Widgets) find_package(ECM 1.0.0 NO_MODULE) diff --git a/packaging/0001-Target-build b/packaging/0001-Target-build deleted file mode 100644 index ea68e5f..0000000 --- a/packaging/0001-Target-build +++ /dev/null @@ -1,43 +0,0 @@ - heaptrack/src/CMakeLists.txt | 4 ++-- - heaptrack/src/track/CMakeLists.txt | 12 ++++++------ - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/heaptrack/src/CMakeLists.txt b/heaptrack/src/CMakeLists.txt -index f29097a..afa1a09 100644 ---- a/heaptrack/src/CMakeLists.txt -+++ b/heaptrack/src/CMakeLists.txt -@@ -5,5 +5,5 @@ include_directories( - - add_subdirectory(util) - add_subdirectory(track) --add_subdirectory(interpret) --add_subdirectory(analyze) -+add_subdirectory(interpret) -+#add_subdirectory(analyze) -diff --git a/heaptrack/src/track/CMakeLists.txt b/heaptrack/src/track/CMakeLists.txt -index 06f59b7..ef005e7 100644 ---- a/heaptrack/src/track/CMakeLists.txt -+++ b/heaptrack/src/track/CMakeLists.txt -@@ -8,9 +8,9 @@ configure_file(heaptrack.sh.cmake - ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack @ONLY - ) - --install(PROGRAMS ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack -- DESTINATION ${BIN_INSTALL_DIR} --) -+#install(PROGRAMS ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack -+# DESTINATION ${BIN_INSTALL_DIR} -+#) - - # heaptrack_preload: track a newly started process - add_library(heaptrack_preload MODULE -@@ -62,6 +62,6 @@ install(TARGETS heaptrack_inject - ) - - # public API for custom pool allocators or static binaries --install(FILES heaptrack_api.h -- DESTINATION ${CMAKE_INSTALL_PREFIX}/include --) -+#install(FILES heaptrack_api.h -+# DESTINATION ${CMAKE_INSTALL_PREFIX}/include -+#) diff --git a/packaging/heaptrack.spec b/packaging/heaptrack.spec index 704ad9d..a34c3e3 100644 --- a/packaging/heaptrack.spec +++ b/packaging/heaptrack.spec @@ -7,7 +7,6 @@ Group: Application Framework/Application State Management License: GPL Source0: %{name}-%{version}.tar.gz Source1001: heaptrack.manifest -Source1002: 0001-Target-build %define heaptrack_src heaptrack-%{version} %define heaptrack_build build-%{_target_platform} AutoReqProv: no @@ -37,11 +36,7 @@ Heaptrack for Tizen applications %prep %setup -q -# 0001-Target-build.patch cp %{SOURCE1001} . -cp %{SOURCE1002} . -# Gbp-Patch-Macros -patch -p2 < 0001-Target-build %build @@ -64,6 +59,7 @@ cmake \ -DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_BUILD_TYPE=%{_heaptrack_build_conf} \ -DHEAPTRACK_BUILD_GUI=OFF \ + -DTIZEN=ON \ .. make %{?jobs:-j%jobs} VERBOSE=1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f29097a..db4d61d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,4 +6,6 @@ include_directories( add_subdirectory(util) add_subdirectory(track) add_subdirectory(interpret) -add_subdirectory(analyze) +if (NOT TIZEN) + add_subdirectory(analyze) +endif() diff --git a/src/track/CMakeLists.txt b/src/track/CMakeLists.txt index 06f59b7..162cacd 100644 --- a/src/track/CMakeLists.txt +++ b/src/track/CMakeLists.txt @@ -8,9 +8,11 @@ configure_file(heaptrack.sh.cmake ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack @ONLY ) -install(PROGRAMS ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack - DESTINATION ${BIN_INSTALL_DIR} -) +if (NOT TIZEN) + install(PROGRAMS ${PROJECT_BINARY_DIR}/${BIN_INSTALL_DIR}/heaptrack + DESTINATION ${BIN_INSTALL_DIR} + ) +endif() # heaptrack_preload: track a newly started process add_library(heaptrack_preload MODULE @@ -61,7 +63,9 @@ install(TARGETS heaptrack_inject LIBRARY DESTINATION ${LIB_INSTALL_DIR}/heaptrack/ ) -# public API for custom pool allocators or static binaries -install(FILES heaptrack_api.h - DESTINATION ${CMAKE_INSTALL_PREFIX}/include -) +if (NOT TIZEN) + # public API for custom pool allocators or static binaries + install(FILES heaptrack_api.h + DESTINATION ${CMAKE_INSTALL_PREFIX}/include + ) +endif() diff --git a/src/track/heaptrack_inject.cpp b/src/track/heaptrack_inject.cpp index 84cc671..5684649 100644 --- a/src/track/heaptrack_inject.cpp +++ b/src/track/heaptrack_inject.cpp @@ -27,7 +27,11 @@ #include <sys/mman.h> +#include <map> +#include <tuple> #include <type_traits> +#include <utility> +#include <vector> /** * @file heaptrack_inject.cpp @@ -43,6 +47,93 @@ #error unsupported word size #endif +static int isCoreCLR(const char *filename) +{ + const char *localFilename = strrchr(filename,'/'); + if (!localFilename) + { + localFilename = filename; + } + else + { + ++localFilename; + } + + if (strcmp(localFilename, "libclrjit.so") == 0 + || strcmp(localFilename, "libcoreclr.so") == 0 + || strcmp(localFilename, "libcoreclrtraceptprovider.so") == 0 + || strcmp(localFilename, "libdbgshim.so") == 0 + || strcmp(localFilename, "libmscordaccore.so") == 0 + || strcmp(localFilename, "libmscordbi.so") == 0 + || strcmp(localFilename, "libprotojit.so") == 0 + || strcmp(localFilename, "libsosplugin.so") == 0 + || strcmp(localFilename, "libsos.so") == 0 + || strcmp(localFilename, "libsuperpmi-shim-collector.so") == 0 + || strcmp(localFilename, "libsuperpmi-shim-counter.so") == 0 + || strcmp(localFilename, "libsuperpmi-shim-simple.so") == 0 + || strcmp(localFilename, "System.Globalization.Native.so") == 0 + || strcmp(localFilename, "System.IO.Compression.Native.so") == 0 + || strcmp(localFilename, "System.Native.so") == 0 + || strcmp(localFilename, "System.Net.Http.Native.so") == 0 + || strcmp(localFilename, "System.Net.Security.Native.so") == 0 + || strcmp(localFilename, "System.Security.Cryptography.Native.OpenSsl.so") == 0 + || strcmp(localFilename, "System.Security.Cryptography.Native.so") == 0) + { + return 1; + } + else + { + return 0; + } +} + +static bool isExiting = false; + +static int dl_iterate_phdr_get_maps(struct dl_phdr_info* info, size_t /*size*/, void* data) +{ + auto maps = (std::map<void *, std::tuple<size_t, int, int>> *) data; + + const char* fileName = info->dlpi_name; + if (!fileName || !fileName[0]) { + fileName = "x"; + } + + int isCoreclr = isCoreCLR(fileName); + + debugLog<VerboseOutput>("dl_iterate_phdr_get_maps: %s %zx", fileName, info->dlpi_addr); + + for (int i = 0; i < info->dlpi_phnum; i++) { + const auto& phdr = info->dlpi_phdr[i]; + + if (phdr.p_type == PT_LOAD) { + constexpr uintptr_t pageMask = (uintptr_t) 0xfff; + + uintptr_t start = (info->dlpi_addr + phdr.p_vaddr) & ~pageMask; + uintptr_t end = (info->dlpi_addr + phdr.p_vaddr + phdr.p_memsz + pageMask) & ~pageMask; + + void *addr = (void *) start; + size_t size = (size_t) (end - start); + + int prot = 0; + + if (phdr.p_flags & PF_R) + prot |= PROT_READ; + if (phdr.p_flags & PF_W) + prot |= PROT_WRITE; + if (phdr.p_flags & PF_X) + prot |= PROT_EXEC; + + if (maps->find(addr) == maps->end()) { + maps->insert(std::make_pair(addr, std::make_tuple(size, prot, isCoreclr))); + } else { + debugLog<VerboseOutput>("dl_iterate_phdr_get_maps: repeated section address %s %zx", fileName, info->dlpi_addr); + } + } + } + + return 0; +} + namespace { namespace Elf { @@ -137,10 +228,47 @@ struct dlopen static void* hook(const char* filename, int flag) noexcept { + std::map<void *, std::tuple<size_t, int, int>> map_before, map_after; + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map_before); + } + auto ret = original(filename, flag); + if (ret) { heaptrack_invalidate_module_cache(); overwrite_symbols(); + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map_after); + } + + if(map_after.size() < map_before.size()) { + debugLog<VerboseOutput>("dlopen: count of sections after dlopen is less than before: %p %s %x", ret, filename, flag); + } else if (map_after.size() != map_before.size()) { + std::vector<std::pair<void *, std::tuple<size_t, int, int>>> newMmaps; + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + + for (const auto & section_after : map_after) { + if (map_before.find(section_after.first) == map_before.end()) { + newMmaps.push_back(section_after); + } + } + } + + heaptrack_dlopen(newMmaps, false, reinterpret_cast<void *>(hooks::dlopen::original)); + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + + newMmaps.clear(); + } + } } return ret; } @@ -153,9 +281,49 @@ struct dlclose static int hook(void* handle) noexcept { + std::map<void *, std::tuple<size_t, int, int>> map_before, map_after; + + if (!isExiting) { + if (!RecursionGuard::isActive) { + RecursionGuard guard; + dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map_before); + } + } + auto ret = original(handle); if (!ret) { heaptrack_invalidate_module_cache(); + + if (!isExiting) { + if (!RecursionGuard::isActive) { + RecursionGuard guard; + dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map_after); + } + + if(map_after.size() > map_before.size()) { + debugLog<VerboseOutput>("dlopen: count of sections after dlclose is greater than before: %p", handle); + } else if (map_after.size() != map_before.size()) { + std::vector<std::pair<void *, size_t>> munmaps; + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + + for (const auto & section_before : map_before) { + if (map_after.find(section_before.first) == map_after.end()) { + munmaps.push_back(std::make_pair(section_before.first, std::get<0>(section_before.second))); + } + } + } + + heaptrack_dlclose(munmaps); + + if (!RecursionGuard::isActive) { + RecursionGuard guard; + + munmaps.clear(); + } + } + } } return ret; } @@ -188,7 +356,7 @@ struct mmap int prot, int flags, int fd, - off_t offset) + off_t offset) noexcept { void *ret = original(addr, length, prot, flags, fd, offset); @@ -210,7 +378,7 @@ struct mmap64 int prot, int flags, int fd, - off64_t offset) + off64_t offset) noexcept { void *ret = original(addr, length, prot, flags, fd, offset); @@ -375,12 +543,61 @@ void overwrite_symbols() noexcept } extern "C" { + void heaptrack_inject(const char* outputFileName) noexcept { + atexit([]() { + isExiting = true; + }); + heaptrack_init(outputFileName, []() { overwrite_symbols(); }, [](FILE* out) { fprintf(out, "A\n"); }, []() { bool do_shutdown = true; dl_iterate_phdr(&iterate_phdrs, &do_shutdown); }); + + { + std::map<void *, std::tuple<size_t, int, int>> map; + + dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map); + + std::vector<std::pair<void *, std::tuple<size_t, int, int>>> newMmaps; + + for (const auto & section : map) { + newMmaps.push_back(section); + } + + heaptrack_dlopen(newMmaps, true, reinterpret_cast<void *>(hooks::dlopen::original)); + } +} + +#if TIZEN +int dotnet_launcher_inject() noexcept +{ + int res = -1; + char *env = nullptr; + char* output = nullptr; + + env = getenv("DUMP_HEAPTRACK_OUTPUT"); + if (env == nullptr) { + goto ret; + } + + output = strdup(env); + if (output == nullptr) { + goto ret; + } + + heaptrack_inject(output); + res = 0; + +ret: + unsetenv("DUMP_HEAPTRACK_OUTPUT"); + + free(output); + + return res; } +#endif + } |