diff --git a/.gitmodules b/.gitmodules index 3f804f6b7..7c87d52db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,4 +10,6 @@ [submodule "3rd/frida_gum/gumpp"] path = 3rd/frida_gum/gumpp url = https://github.com/fesily/gumpp - +[submodule "3rd/json"] + path = 3rd/json + url = https://github.com/nlohmann/json diff --git a/3rd/json b/3rd/json new file mode 160000 index 000000000..546370c9e --- /dev/null +++ b/3rd/json @@ -0,0 +1 @@ +Subproject commit 546370c9e778d99e7176641123e5cc1d0b62acab diff --git a/compile/common/launcher.lua b/compile/common/launcher.lua index d8348beb7..d07451822 100644 --- a/compile/common/launcher.lua +++ b/compile/common/launcher.lua @@ -20,6 +20,7 @@ lm:lua_source 'launcher_source' { "3rd/bee.lua", "3rd/frida_gum/gumpp", "3rd/lua/lua54", + "3rd/json/single_include", "src/launcher", }, sources = { diff --git a/compile/common/package_json.lua b/compile/common/package_json.lua index 4a47a1af4..ff10bf517 100644 --- a/compile/common/package_json.lua +++ b/compile/common/package_json.lua @@ -252,6 +252,11 @@ Debugger address. }, type = "string", }, + module = { + default = "null", + markdownDescription = "specify lua module path/name", + type = "string", + } } if OS == "win32" then @@ -471,6 +476,10 @@ for k, v in pairs(attributes.common) do attributes.attach[k] = v attributes.launch[k] = v end + +table.insert(attributes.attach.luaVersion.enum, "unknown") +attributes.attach.luaVersion.default = "unknown" + json.contributes.debuggers[1].configurationAttributes = { launch = { properties = attributes.launch }, attach = { properties = attributes.attach }, diff --git a/extension/script/attach.lua b/extension/script/attach.lua index 1559b20f1..a94759f8a 100644 --- a/extension/script/attach.lua +++ b/extension/script/attach.lua @@ -1,4 +1,4 @@ -local path, pid = ... +local path, pid, debugger_path = ... if _VERSION == nil or type == nil or assert == nil @@ -19,6 +19,10 @@ if is_luajit and jit == nil then return "wait initialized" end +if debugger_path == "" then + debugger_path = nil +end + local function dofile(filename, ...) local load = _VERSION == "Lua 5.1" and loadstring or load local f = assert(io.open(filename)) @@ -26,20 +30,11 @@ local function dofile(filename, ...) f:close() return assert(load(str, "=(debugger.lua)"))(...) end -local function isLatest() - local ipc = dofile(path.."/script/common/ipc.lua") - local fd = ipc(path, pid, "luaVersion") - local result = false - if fd then - result = "lua-latest" == fd:read "a" - fd:close() - end - return result -end + local dbg = dofile(path.."/script/debugger.lua", path) dbg:start { address = ("@%s/tmp/pid_%s"):format(path, pid), - latest = isLatest(), + debugger_path = debugger_path, } dbg:event "wait" -return "ok" \ No newline at end of file +return "ok" diff --git a/extension/script/debugger.lua b/extension/script/debugger.lua index b3b495ee2..381d902c0 100644 --- a/extension/script/debugger.lua +++ b/extension/script/debugger.lua @@ -133,7 +133,7 @@ local function initDebugger(dbg, cfg) local luadebug = os.getenv "LUA_DEBUG_CORE" local updateenv = false if not luadebug then - luadebug = detectLuaDebugPath(cfg) + luadebug = cfg.debugger_path or detectLuaDebugPath(cfg) updateenv = true end local isWindows = package.config:sub(1, 1) == "\\" @@ -212,7 +212,7 @@ function dbg:event(...) end function dbg:set_wait(name, f) - _G[name] = function(...) + _G[name] = function (...) _G[name] = nil f(...) self:event 'wait' @@ -224,7 +224,7 @@ function dbg:setup_patch() local rawxpcall = xpcall function pcall(f, ...) return rawxpcall(f, - function(msg) + function (msg) self:event("exception", msg) return msg end, @@ -233,7 +233,7 @@ function dbg:setup_patch() function xpcall(f, msgh, ...) return rawxpcall(f, - function(msg) + function (msg) self:event("exception", msg) return msgh and msgh(msg) or msg end @@ -254,7 +254,7 @@ function dbg:setup_patch() function coroutine.wrap(f) local wf = rawcoroutinewrap(f) local _, co = debug.getupvalue(wf, 1) - return function(...) + return function (...) self:event("thread", co, 0) return coreturn(co, wf(...)) end diff --git a/extension/script/frontend/debuger_factory.lua b/extension/script/frontend/debuger_factory.lua index 88703895d..d9eed5412 100644 --- a/extension/script/frontend/debuger_factory.lua +++ b/extension/script/frontend/debuger_factory.lua @@ -221,6 +221,9 @@ local function create_process_in_console(args, callback) if not process then return nil, err end + if callback then + callback(process) + end if args.inject ~= "none" then local ok, errmsg = process_inject.inject(process, "launch", args) if not ok then @@ -231,9 +234,6 @@ local function create_process_in_console(args, callback) end end end - if callback then - callback(process) - end if need_resume then process:resume() end diff --git a/extension/script/frontend/proxy.lua b/extension/script/frontend/proxy.lua index e8cee4277..b0d9d7ec6 100644 --- a/extension/script/frontend/proxy.lua +++ b/extension/script/frontend/proxy.lua @@ -4,6 +4,7 @@ local fs = require 'bee.filesystem' local sp = require 'bee.subprocess' local platform_os = require 'frontend.platform_os' local process_inject = require 'frontend.process_inject' +local json = require 'common.json' local server local client local initReq @@ -15,11 +16,16 @@ local function getUnixAddress(pid) return "@"..(path / ("pid_%d"):format(pid)):string() end -local function ipc_send_latest(pid) +local function ipc_send_config(pid, args) + --TODO: clear config file fs.create_directories(WORKDIR / "tmp") local ipc = require "common.ipc" - local fd = assert(ipc(WORKDIR, pid, "luaVersion", "w")) - fd:write("latest") + local fd = assert(ipc(WORKDIR, pid, "config", "w")) + local config = { + version = args.luaVersion, + module = args.module + } + fd:write(json.encode(config)) fd:close() end @@ -56,13 +62,11 @@ end local function attach_process(pkg, pid) local args = pkg.arguments - if args.luaVersion == "lua-latest" then - ipc_send_latest(pid) - end + ipc_send_config(pid, args) local ok, errmsg = process_inject.inject(pid, "attach", args) if not ok then - return false, errmsg - end + return false, errmsg + end server = network(getUnixAddress(pid), true) server.sendmsg(initReq) @@ -80,8 +84,8 @@ local function proxy_attach(pkg) local args = pkg.arguments platform_os.init(args) if platform_os() ~= "Windows" and platform_os() ~= "macOS" then - attach_tcp(pkg, args) - return + attach_tcp(pkg, args) + return end if args.processId then local processId = tonumber(args.processId) @@ -92,7 +96,7 @@ local function proxy_attach(pkg) return end if args.processName then - local pids = require "frontend.query_process"(args.processName) + local pids = require "frontend.query_process" (args.processName) if #pids == 0 then response_error(pkg, ('Cannot found process `%s`.'):format(args.processName)) return @@ -113,7 +117,7 @@ local function create_server(args, pid) local s, address if args.address ~= nil then s = network(args.address, args.client) - address = (args.client and "s:" or "c:") .. args.address + address = (args.client and "s:" or "c:")..args.address else pid = pid or sp.get_id() s = network(getUnixAddress(pid), true) @@ -158,11 +162,12 @@ local function proxy_launch_console(pkg) response_error(pkg, "`runtimeExecutable` need specify `inject` or `address`.") return end - local process, err = debuger_factory.create_process_in_console(args, function (process) + local process, err = debuger_factory.create_process_in_console(args, function(process) local address server, address = create_server(args, process:get_id()) - if args.luaVersion == "lua-latest" and type(address) == "number" then - ipc_send_latest(address) + + if type(address) == "number" then + ipc_send_config(address, args) end end) if not process then diff --git a/src/launcher/autoattach/autoattach.cpp b/src/launcher/autoattach/autoattach.cpp index bb8ec5049..0c88ab1cf 100644 --- a/src/launcher/autoattach/autoattach.cpp +++ b/src/launcher/autoattach/autoattach.cpp @@ -1,19 +1,27 @@ #include #include -#include +#include #include -#include -#include #include +#include #include #include #include -#include #include #include namespace luadebug::autoattach { +#ifdef _WIN32 +# define EXT ".dll" +#else +# define EXT ".so" +#endif + constexpr auto lua_module_backlist = { + "launcher" EXT, + "luadebug" EXT, + }; + constexpr auto find_lua_module_key = "lua_newstate"; constexpr auto lua_module_strings = std::array { "luaJIT_BC_%s", // luajit @@ -26,7 +34,22 @@ namespace luadebug::autoattach { "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" " $", // others }; - static bool is_lua_module(const char* module_path, bool check_export = true, bool check_strings = false) { + + static bool is_lua_module(session& session, const char* module_path, bool check_export, bool check_strings) { + auto str = std::string_view(module_path); + // blacklist module + auto root = get_plugin_root(); + if (root) { + if (str.find((*root).string()) != std::string_view::npos) { + // in luadebug root dir + for (auto& s : lua_module_backlist) { + if (str.find(s) != std::string_view::npos) + return false; + } + } + } + const auto& target_lua_module = session.lua_module; + if (!target_lua_module.empty() && str.find(target_lua_module) != std::string_view::npos) return true; if (check_export && Gum::Process::module_find_export_by_name(module_path, find_lua_module_key)) return true; if (Gum::Process::module_find_symbol_by_name(module_path, find_lua_module_key)) return true; // TODO: when signature mode, check strings @@ -49,7 +72,7 @@ namespace luadebug::autoattach { false #endif ; - if (!is_lua_module(path.c_str(), check_export, true)) { + if (!is_lua_module(*ctx::get()->session, path.c_str(), check_export, true)) { return false; } // find lua module lazy @@ -61,22 +84,22 @@ namespace luadebug::autoattach { if (ctx->lua_module) { return; } - - bool found = false; - lua_module rm(ctx->mode); - Gum::Process::enumerate_modules([&rm, &found](const Gum::ModuleDetails& details) -> bool { - if (is_lua_module(details.path())) { - auto range = details.range(); - rm.memory_address = range.base_address; - rm.memory_size = range.size; - rm.path = details.path(); - rm.name = details.name(); - found = true; + Gum::Process::enumerate_modules([&ctx](const Gum::ModuleDetails& details) -> bool { + auto& session = *ctx->session; + if (is_lua_module(session, details.path(), true, false)) { + ctx->lua_module = lua_module { session.mode }; + auto range = details.range(); + ctx->lua_module->memory_address = range.base_address; + ctx->lua_module->memory_size = range.size; + ctx->lua_module->path = details.path(); + ctx->lua_module->name = details.name(); + ctx->lua_module->version = session.version; + ctx->session.reset(); return false; } return true; }); - if (!found) { + if (!ctx->lua_module) { if (ctx->wait_dll) return; if (!wait_dll(load_lua_module)) { @@ -88,23 +111,27 @@ namespace luadebug::autoattach { return; } - log::info("find lua module path:{}", rm.path); - if (!rm.initialize()) { + log::info("find lua module path:{}", ctx->lua_module->path); + if (!ctx->lua_module->initialize()) { + ctx->lua_module.reset(); return; } - ctx->lua_module = std::move(rm); } - void start(work_mode mode) { + void start() { auto ctx = ctx::get(); std::lock_guard guard(ctx->mtx); - ctx->mode = mode; start_impl(ctx); } - void start() { + void start(work_mode mode) { auto ctx = ctx::get(); std::lock_guard guard(ctx->mtx); + ctx->session = init_session(mode); + if (!ctx->session) { + log::fatal("can't load config"); + return; + } start_impl(ctx); } diff --git a/src/launcher/autoattach/autoattach.h b/src/launcher/autoattach/autoattach.h index e68f3185a..b74490107 100644 --- a/src/launcher/autoattach/autoattach.h +++ b/src/launcher/autoattach/autoattach.h @@ -12,6 +12,7 @@ namespace luadebug::autoattach { launch, attach, }; - attach_status attach_lua(lua::state L); + struct lua_module; + attach_status attach_lua(lua::state L, lua_module &module); void initialize(work_mode mode); } diff --git a/src/launcher/autoattach/ctx.h b/src/launcher/autoattach/ctx.h index 1d2a18dee..cb711d14c 100644 --- a/src/launcher/autoattach/ctx.h +++ b/src/launcher/autoattach/ctx.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include @@ -12,9 +13,9 @@ namespace luadebug::autoattach { struct ctx { std::mutex mtx; - work_mode mode; - std::optional lua_module; bool wait_dll = false; + std::optional lua_module; + std::optional session; static ctx* get() { static ctx obj; diff --git a/src/launcher/autoattach/lua_module.cpp b/src/launcher/autoattach/lua_module.cpp index 8ee7b0225..a2ad8b77e 100644 --- a/src/launcher/autoattach/lua_module.cpp +++ b/src/launcher/autoattach/lua_module.cpp @@ -1,46 +1,18 @@ +#include #include #include +#include #include #include #include +#include #include #include namespace luadebug::autoattach { - static lua_version lua_version_from_string [[maybe_unused]] (const std::string_view& v) { - if (v == "luajit") - return lua_version::luajit; - if (v == "lua51") - return lua_version::lua51; - if (v == "lua52") - return lua_version::lua52; - if (v == "lua53") - return lua_version::lua53; - if (v == "lua54") - return lua_version::lua54; - return lua_version::unknown; - } - - static const char* lua_version_to_string(lua_version v) { - switch (v) { - case lua_version::lua51: - return "lua51"; - case lua_version::lua52: - return "lua52"; - case lua_version::lua53: - return "lua53"; - case lua_version::lua54: - return "lua54"; - case lua_version::luajit: - return "luajit"; - default: - return "unknown"; - } - } - static bool in_module(const lua_module& m, void* addr) { - return addr > m.memory_address && addr <= (void*)((intptr_t)m.memory_address + m.memory_size); + return addr >= m.memory_address && addr <= (void*)((intptr_t)m.memory_address + m.memory_size); } static lua_version get_lua_version(const lua_module& m) { @@ -89,6 +61,19 @@ namespace luadebug::autoattach { } } + bool load_luadebug_dll(lua_module* lm, lua_version version) { + auto luadebug_path = get_luadebug_path(version); + if (!luadebug_path) + return false; + auto path = (*luadebug_path).string(); + std::string error; + if (!Gum::Process::module_load(path.c_str(), &error)) { + log::fatal("load debugger [{}] failed: {}", path, error); + } + lm->debugger_path = path; + return true; + } + bool lua_module::initialize() { resolver.module_name = path; auto error_msg = lua::initialize(resolver); @@ -96,10 +81,16 @@ namespace luadebug::autoattach { log::fatal("lua initialize failed, can't find {}", error_msg); return false; } - version = get_lua_version(*this); + if (version == lua_version::unknown) { + version = get_lua_version(*this); + } log::info("current lua version: {}", lua_version_to_string(version)); - watchdog = create_watchdog(mode, version, resolver); + watchdog = create_watchdog(*this); + if (version != lua_version::unknown) { + if (!load_luadebug_dll(this, version)) + return false; + } if (!watchdog) { return false; } diff --git a/src/launcher/autoattach/lua_module.h b/src/launcher/autoattach/lua_module.h index 6d909f8bd..eab90a882 100644 --- a/src/launcher/autoattach/lua_module.h +++ b/src/launcher/autoattach/lua_module.h @@ -1,20 +1,13 @@ #pragma once #include +#include #include #include namespace luadebug::autoattach { struct watchdog; - enum class lua_version { - unknown, - luajit, - lua51, - lua52, - lua53, - lua54, - }; struct lua_module { std::string path; std::string name; @@ -24,6 +17,7 @@ namespace luadebug::autoattach { lua_resolver resolver; work_mode mode; struct watchdog* watchdog = nullptr; + std::string debugger_path; lua_module(work_mode mode) : mode(mode) {} diff --git a/src/launcher/autoattach/lua_version.cpp b/src/launcher/autoattach/lua_version.cpp new file mode 100644 index 000000000..554f9364b --- /dev/null +++ b/src/launcher/autoattach/lua_version.cpp @@ -0,0 +1,37 @@ +#include + +namespace luadebug::autoattach { + const char* lua_version_to_string(lua_version v) { + switch (v) { + case lua_version::lua51: + return "lua51"; + case lua_version::lua52: + return "lua52"; + case lua_version::lua53: + return "lua53"; + case lua_version::lua54: + return "lua54"; + case lua_version::luajit: + return "luajit"; + case lua_version::latest: + return "lua-latest"; + default: + return "unknown"; + } + } + lua_version lua_version_from_string(const std::string_view& v) { + if (v == "luajit") + return lua_version::luajit; + else if (v == "lua51") + return lua_version::lua51; + else if (v == "lua52") + return lua_version::lua52; + else if (v == "lua53") + return lua_version::lua53; + else if (v == "lua54") + return lua_version::lua54; + else if (v == "lua-latest") + return lua_version::latest; + return lua_version::unknown; + } +} diff --git a/src/launcher/autoattach/lua_version.h b/src/launcher/autoattach/lua_version.h new file mode 100644 index 000000000..76d92e8a6 --- /dev/null +++ b/src/launcher/autoattach/lua_version.h @@ -0,0 +1,15 @@ +#pragma once +#include +namespace luadebug::autoattach { + enum class lua_version { + unknown, + luajit, + lua51, + lua52, + lua53, + lua54, + latest, + }; + const char* lua_version_to_string(lua_version v); + lua_version lua_version_from_string(const std::string_view& v); +} diff --git a/src/launcher/autoattach/session.cpp b/src/launcher/autoattach/session.cpp new file mode 100644 index 000000000..db354f429 --- /dev/null +++ b/src/launcher/autoattach/session.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace std::string_view_literals; + +namespace luadebug::autoattach { + static lua_version get_lua_version(nlohmann::json& values) { + const auto key = "version"sv; + auto it = values.find(key); + if (it == values.end()) { + return lua_version::unknown; + } + return lua_version_from_string(it->get()); + } + + static std::string get_lua_module(nlohmann::json& values) { + const auto key = "module"sv; + + auto it = values.find(key); + if (it == values.end()) { + return {}; + } + auto value = it->get(); + if (!fs::exists(value)) + return value; + + do { + if (!fs::is_symlink(value)) + return value; + auto link = fs::read_symlink(value); + if (link.is_absolute()) + value = link.string(); + else + value = (fs::path(value).parent_path() / link).lexically_normal().string(); + } while (true); + } + + std::optional init_session(work_mode mode) { + session session; + nlohmann::json values; + + auto tmp = get_tmp_dir(); + if (!tmp) + return std::nullopt; + auto filename = ((*tmp) / std::format("ipc_{}_config", Gum::Process::get_id())).string(); + + std::ifstream s(filename, s.binary); + if (!s.is_open()) + return std::nullopt; + try { + s >> values; + } catch (const nlohmann::json::exception& e) { + log::info("init_from_file error: {}", e.what()); + } + + session.mode = mode; + session.version = get_lua_version(values); + session.lua_module = get_lua_module(values); + + return session; + } +} // namespace luadebug::autoattach diff --git a/src/launcher/autoattach/session.h b/src/launcher/autoattach/session.h new file mode 100644 index 000000000..9c382ce4e --- /dev/null +++ b/src/launcher/autoattach/session.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace luadebug::autoattach { + struct session { + work_mode mode; + lua_version version = lua_version::unknown; + std::string lua_module; + }; + std::optional init_session(work_mode mode); +} diff --git a/src/launcher/hook/create_watchdog.cpp b/src/launcher/hook/create_watchdog.cpp index e93c5fa62..d2f183a8f 100644 --- a/src/launcher/hook/create_watchdog.cpp +++ b/src/launcher/hook/create_watchdog.cpp @@ -34,6 +34,7 @@ namespace luadebug::autoattach { { watch_point::type::common, "luaV_gettable" }, { watch_point::type::common, "luaV_settable" }, }; + case lua_version::latest: case lua_version::lua54: return { { watch_point::type::common, "luaD_poscall" }, @@ -55,22 +56,22 @@ namespace luadebug::autoattach { } } - watchdog* create_watchdog(work_mode mode, lua_version version, const lua::resolver& resolver) { - auto context = std::make_unique(); + watchdog* create_watchdog(lua_module& module) { + auto context = std::make_unique(module); if (!context->init()) { return nullptr; } - if (context->init_watch(resolver, get_watch_points(mode, version))) { + if (context->init_watch(module.resolver, get_watch_points(module.mode, module.version))) { // TODO: fix other thread pc context->hook(); return context.release(); } - if (version == lua_version::unknown) { + if (module.version == lua_version::unknown) { // TODO: more errmsg log::fatal("watchdog initialize failed"); return nullptr; } - if (context->init_watch(resolver, get_watch_points(mode, lua_version::unknown))) { + if (context->init_watch(module.resolver, get_watch_points(module.mode, lua_version::unknown))) { // TODO: fix other thread pc context->hook(); return context.release(); diff --git a/src/launcher/hook/create_watchdog.h b/src/launcher/hook/create_watchdog.h index 0b493546b..de1a50cee 100644 --- a/src/launcher/hook/create_watchdog.h +++ b/src/launcher/hook/create_watchdog.h @@ -11,5 +11,5 @@ namespace luadebug::lua { namespace luadebug::autoattach { struct watchdog; - watchdog* create_watchdog(work_mode mode, lua_version v, const lua::resolver& resolver); + watchdog* create_watchdog(lua_module& module); } diff --git a/src/launcher/hook/watchdog.cpp b/src/launcher/hook/watchdog.cpp index 7004a1c34..6afb5487a 100644 --- a/src/launcher/hook/watchdog.cpp +++ b/src/launcher/hook/watchdog.cpp @@ -132,8 +132,9 @@ namespace luadebug::autoattach { } }; - watchdog::watchdog() - : interceptor { Gum::Interceptor_obtain() } {} + watchdog::watchdog(struct lua_module& lua_module) + : lua_module(lua_module) + , interceptor { Gum::Interceptor_obtain() } {} watchdog::~watchdog() { if (luahook_set) { trampoline::destroy(this, luahook_index); @@ -203,7 +204,7 @@ namespace luadebug::autoattach { } void watchdog::attach_lua(lua::state L, lua::debug ar) { - switch (autoattach::attach_lua(L)) { + switch (autoattach::attach_lua(L, lua_module)) { case attach_status::fatal: case attach_status::success: // TODO: how to free so diff --git a/src/launcher/hook/watchdog.h b/src/launcher/hook/watchdog.h index 9e360edc8..fd209ad4c 100644 --- a/src/launcher/hook/watchdog.h +++ b/src/launcher/hook/watchdog.h @@ -12,11 +12,13 @@ #include namespace luadebug::autoattach { + struct lua_module; + struct watchdog { static_assert(std::is_same_v); public: - watchdog(); + watchdog(struct lua_module& lua_module); ~watchdog(); watchdog(const watchdog&) = delete; bool init(); @@ -27,6 +29,7 @@ namespace luadebug::autoattach { void attach_lua(lua::state L, lua::debug ar); private: + struct lua_module& lua_module; std::mutex mtx; std::vector watch_points; Gum::RefPtr interceptor; diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index da618c8b9..4487bada9 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -1,25 +1,27 @@ #include +#include #include #include #include + #ifndef _WIN32 -# include # define DLLEXPORT __attribute__((visibility("default"))) # define DLLEXPORT_DECLARATION #else -# include # define DLLEXPORT __declspec(dllexport) # define DLLEXPORT_DECLARATION __cdecl #endif + +#include #include #include namespace luadebug::autoattach { - static std::string readfile(const fs::path& filename) { + static std::string readfile(const fs::path &filename) { #ifdef _WIN32 - FILE* f = _wfopen(filename.c_str(), L"rb"); + FILE *f = _wfopen(filename.c_str(), L"rb"); #else - FILE* f = fopen(filename.c_str(), "rb"); + FILE *f = fopen(filename.c_str(), "rb"); #endif if (!f) { return std::string(); @@ -34,7 +36,7 @@ namespace luadebug::autoattach { return tmp; } - attach_status attach_lua(lua::state L) { + attach_status attach_lua(lua::state L, lua_module &module) { log::info("attach lua vm entry"); auto r = bee::path_helper::dll_path(); if (!r) { @@ -49,12 +51,10 @@ namespace luadebug::autoattach { return attach_status::fatal; } lua::call(L, root.generic_u8string().c_str()); -#ifdef _WIN32 - lua::call(L, std::to_string(GetCurrentProcessId()).c_str()); -#else - lua::call(L, std::to_string(getpid()).c_str()); -#endif - if (lua::pcall(L, 2, 1, 0)) { + lua::call(L, std::to_string(Gum::Process::get_id()).c_str()); + lua::call(L, module.debugger_path.c_str()); + + if (lua::pcall(L, 3, 1, 0)) { /* 这里失败无法调用log::fatal,因为无法知道调试器已经加载到哪一步才失败的。 所以调试器不应该把错误抛到这里。 diff --git a/src/launcher/util/log.cpp b/src/launcher/util/log.cpp index 5b9e2cfc5..9eacfa34e 100644 --- a/src/launcher/util/log.cpp +++ b/src/launcher/util/log.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -16,6 +17,8 @@ # include #endif +#include + namespace luadebug::log { using namespace bee::net; @@ -51,18 +54,11 @@ namespace luadebug::log { } void notify_frontend(const std::string& msg) { - auto dllpath = bee::path_helper::dll_path(); - if (!dllpath) { + auto tmp = get_tmp_dir(); + if (!tmp) return; - } - auto rootpath = dllpath.value().parent_path().parent_path(); - auto path = std::format("{}/tmp/pid_{}", rootpath.generic_u8string(), -#if defined(_WIN32) - GetCurrentProcessId() -#else - getpid() -#endif - ); + auto path = ((*tmp) / std::format("pid_{}", Gum::Process::get_id())).string(); + if (!socket::initialize()) { return; } diff --git a/src/launcher/util/path.cpp b/src/launcher/util/path.cpp new file mode 100644 index 000000000..e4031c283 --- /dev/null +++ b/src/launcher/util/path.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +namespace luadebug { + std::optional get_plugin_root() { + auto dllpath = bee::path_helper::dll_path(); + if (!dllpath) { + return std::nullopt; + } + return dllpath.value().parent_path().parent_path(); + } + + std::optional get_tmp_dir() { + auto root = get_plugin_root(); + if (!root) + return std::nullopt; + return (*root) / "tmp"; + } + + std::optional get_runtime_dir() { + auto root = get_plugin_root(); + if (!root) + return std::nullopt; + auto os = +#if defined(_WIN32) + "windows"; +#elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) + "darwin"; +#else + "linux"; +#endif + auto arch = +#if defined(_M_ARM64) || defined(__aarch64__) + "arm64"; +#elif defined(_M_IX86) || defined(__i386__) + "ia32"; +#elif defined(_M_X64) || defined(__x86_64__) + "x64"; +#else +# error "Unknown architecture" +#endif + auto platform = std::format("{}-{}", os, arch); + return (*root) / "runtime" / platform; + } + + std::optional get_lua_runtime_dir(autoattach::lua_version version) { + auto runtime = get_runtime_dir(); + if (!runtime) + return std::nullopt; + return (*runtime) / autoattach::lua_version_to_string(version); + } + + std::optional get_luadebug_path(autoattach::lua_version version) { + auto runtime = get_lua_runtime_dir(version); + if (!runtime) + return std::nullopt; +#define LUADEBUG_FILE "luadebug" + +#if defined(_WIN32) +# define EXT ".dll" +#else +# define EXT ".so" +#endif + return (*runtime) / (LUADEBUG_FILE EXT); + } + +} diff --git a/src/launcher/util/path.h b/src/launcher/util/path.h new file mode 100644 index 000000000..49c17fae7 --- /dev/null +++ b/src/launcher/util/path.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include + +namespace luadebug { + std::optional get_plugin_root(); + std::optional get_tmp_dir(); + std::optional get_runtime_dir(); + std::optional get_lua_runtime_dir(autoattach::lua_version version); + std::optional get_luadebug_path(autoattach::lua_version version); +}