From 9efeca7b5d26e4267ed9eebb87193e0df4dbe468 Mon Sep 17 00:00:00 2001 From: Ellis Nielsen Date: Sun, 22 Oct 2023 13:53:23 -0500 Subject: [PATCH] Implement an alternative way to pass parameters (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * init commit * review changes * remove unused extern var * Apply suggestions from code review Co-authored-by: Björn Dahlgren * removed json header, from scriptProfiler.hpp. changed to pass file path out through data pointer for linux * Dedmen's genius idea * submodule update * Update src/scriptProfiler.cpp --------- Co-authored-by: Dedmen Miller Co-authored-by: Björn Dahlgren --- .gitignore | 3 +- .gitmodules | 3 ++ lib/json | 1 + parameters.json | 13 ++++++ src/CMakeLists.txt | 4 +- src/scriptProfiler.cpp | 91 +++++++++++++++++++++++++++++++++++++++++- tracy | 2 +- 7 files changed, 112 insertions(+), 5 deletions(-) create mode 160000 lib/json create mode 100644 parameters.json diff --git a/.gitignore b/.gitignore index 3c1c88f..188e20a 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ /src/Debug /src/ArmaScriptProfiler.vcxproj.user /src/Release +/out *.biprivatekey # CLion @@ -50,4 +51,4 @@ cmake-build-*/ .hemtt/local addons/*.pbo keys/* -releases/* +releases/* \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index b4d7987..a61071a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "tracy"] path = tracy url = https://github.com/dedmen/tracy.git +[submodule "lib/json"] + path = lib/json + url = https://github.com/nlohmann/json.git diff --git a/lib/json b/lib/json new file mode 160000 index 0000000..5d27543 --- /dev/null +++ b/lib/json @@ -0,0 +1 @@ +Subproject commit 5d2754306d67d1e654a1a34e1d2e74439a9d53b3 diff --git a/parameters.json b/parameters.json new file mode 100644 index 0000000..d06ce4d --- /dev/null +++ b/parameters.json @@ -0,0 +1,13 @@ +{ + "profilerAdapter": "Tracy", + "profilerOutput": "", + "profilerEnableInstruction": true, + "profilerEnableEngine": false, + "profilerEngineThreads": false, + "profilerEngineDoFile": false, + "profilerEngineDoMem": false, + "profilerNoPaths": false, + "profilerNoInstrumentation": false, + "profilerEnableFAlloc": false, + "profilerEnableNetwork": true +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 366b684..4ce1e25 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required (VERSION 3.13) set(INTERCEPT_CLIENT_PATH "${CMAKE_SOURCE_DIR}/intercept/src/client") set(BROFILER_BASE_PATH "${CMAKE_SOURCE_DIR}/brofiler") +set(LIB_BASE_PATH "${CMAKE_SOURCE_DIR}/lib") set(INTERCEPT_INCLUDE_PATH "${INTERCEPT_CLIENT_PATH}/headers" "${INTERCEPT_CLIENT_PATH}/headers/shared" "${INTERCEPT_CLIENT_PATH}/headers/client/" "${INTERCEPT_CLIENT_PATH}/headers/client/sqf") set(BROFILER_INCLUDE_PATH "${BROFILER_BASE_PATH}/BrofilerCore" "${BROFILER_BASE_PATH}/ThirdParty/TaskScheduler/Scheduler/Include") set(TRACY_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/tracy") - +set(JSON_INCLUDE_PATH "${LIB_BASE_PATH}/json/single_include") if(USE_64BIT_BUILD) set(INTERCEPT_PLUGIN_NAME "ArmaScriptProfiler_x64") @@ -70,6 +71,7 @@ add_library( ${INTERCEPT_PLUGIN_NAME} SHARED ${library_sources} ${INTERCEPT_SOUR include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${INTERCEPT_INCLUDE_PATH} ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${BROFILER_INCLUDE_PATH} ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${TRACY_INCLUDE_PATH} ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${JSON_INCLUDE_PATH} ) target_link_libraries (${INTERCEPT_PLUGIN_NAME} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/src/scriptProfiler.cpp b/src/scriptProfiler.cpp index 631c74f..ebc12da 100644 --- a/src/scriptProfiler.cpp +++ b/src/scriptProfiler.cpp @@ -2,11 +2,16 @@ #include #include #include +#include +#include +#include #ifndef __linux__ #include #else #include -#include +#include +#include +#include #endif #include "ProfilerAdapter.hpp" #include "AdapterArmaDiag.hpp" @@ -26,6 +31,7 @@ using namespace intercept; using namespace std::chrono_literals; std::chrono::high_resolution_clock::time_point startTime; static sqf_script_type* GameDataProfileScope_type; +static nlohmann::json json; scriptProfiler profiler{}; bool instructionLevelProfiling = false; @@ -987,6 +993,25 @@ std::optional getCommandLineParam(std::string_view needle) { adapterStr = adapterStr.substr(0, adapterStr.length() - 1); return adapterStr; } + + if (!json.empty() && json.contains(needle.substr(1))) { + switch (json[needle.substr(1)].type()) { + case nlohmann::json::value_t::boolean: + { + if (json[needle.substr(1)].get()) { + return "true"; + } else { + return {}; + } + } + case nlohmann::json::value_t::string: + { + return json[needle.substr(1)].get(); + } + default: + return {}; + } + } return {}; } @@ -1306,9 +1331,72 @@ class GameInstructionNewExpression : public game_instruction { #pragma endregion Instructions #endif + + +#if __linux__ +extern "C" int iterateCallback(struct dl_phdr_info* info, size_t size, void* data) { + std::filesystem::path sharedPath = info->dlpi_name; + if (sharedPath.filename() == "ArmaScriptProfiler_x64.so") { + *static_cast(data) = info->dlpi_name; + return 0; + } + return 0; +} +#endif + +std::filesystem::path getSharedObjectPath() { +#if __linux__ + std::filesystem::path path; + dl_iterate_phdr(iterateCallback, &path); + return path; + +#else + wchar_t buffer[MAX_PATH] = { 0 }; + HMODULE handle = nullptr; + if(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(&getSharedObjectPath), &handle) == 0) { + sqf::diag_log("getSharedObjectPath: GetModuleHandle failed"); + return std::filesystem::path{}; + } + + DWORD len = GetModuleFileNameW(handle, buffer, MAX_PATH); + if (len == 0) { + return std::filesystem::path{}; + } + return std::filesystem::path{buffer}; +#endif +} + +std::filesystem::path findConfigFilePath() { + + std::filesystem::path path = getSharedObjectPath(); + path = path.parent_path().parent_path(); + + std::filesystem::path dirName{ "config"sv }; + std::filesystem::path fileName{ "parameters.json"sv }; + path = path / dirName / fileName; + + return path; +} + void scriptProfiler::preStart() { sqf::diag_log("Arma Script Profiler preStart"); + std::filesystem::path filePath = findConfigFilePath(); + + if (!filePath.empty() && std::filesystem::exists(filePath)) { + sqf::diag_log("ASP: Found a Configuration File"sv); + std::ifstream file(filePath); + try { + json = nlohmann::json::parse(file); + } + catch (nlohmann::json::exception& error) { + // log error, set parameterFile false, and continue by using getCommandLineParam + sqf::diag_log(error.what()); + + } + } + auto startAdapter = getCommandLineParam("-profilerAdapter"sv); if (startAdapter) { @@ -1319,7 +1407,6 @@ void scriptProfiler::preStart() { auto chromeAdapter = std::make_shared(); GProfilerAdapter = chromeAdapter; sqf::diag_log("ASP: Selected Chrome Adapter"sv); - auto chromeOutput = getCommandLineParam("-profilerOutput"sv); if (chromeOutput) chromeAdapter->setTargetFile(*chromeOutput); diff --git a/tracy b/tracy index 725d705..72ae4d2 160000 --- a/tracy +++ b/tracy @@ -1 +1 @@ -Subproject commit 725d705d593f73f6afa1fe1e372f233d30e45eb8 +Subproject commit 72ae4d2ee41165de61f73d404f78db984f2414e6