From 6bfc90dfaf5a3f36926b0c4d139691216fd843cf Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Mon, 1 Jan 2024 22:53:46 +0800 Subject: [PATCH] Support absolute paths in `CRYSTAL_INTERPRETER_LOADER_INFO` (#14147) --- src/compiler/crystal/interpreter/context.cr | 12 ++++-------- src/compiler/crystal/loader/msvc.cr | 16 +++++++++++++++- src/compiler/crystal/loader/unix.cr | 1 + 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/compiler/crystal/interpreter/context.cr b/src/compiler/crystal/interpreter/context.cr index 94456b4cec0e..d597810b36de 100644 --- a/src/compiler/crystal/interpreter/context.cr +++ b/src/compiler/crystal/interpreter/context.cr @@ -410,13 +410,6 @@ class Crystal::Repl::Context args.delete("-lgc") Crystal::Loader.parse(args).tap do |loader| - if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts "Crystal::Loader loaded libraries:" - loader.loaded_libraries.each do |path| - STDERR.puts " #{path}" - end - end - # FIXME: Part 2: This is a workaround for initial integration of the interpreter: # We append a handle to the current executable (i.e. the compiler program) # to the loader's handle list. This gives the loader access to all the symbols in the compiler program, @@ -426,7 +419,10 @@ class Crystal::Repl::Context loader.load_current_program_handle if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts " current program handle" + STDERR.puts "Crystal::Loader loaded libraries:" + loader.loaded_libraries.each do |path| + STDERR.puts " #{path}" + end end end } diff --git a/src/compiler/crystal/loader/msvc.cr b/src/compiler/crystal/loader/msvc.cr index d4b899db0e87..e9fdc9af5bbd 100644 --- a/src/compiler/crystal/loader/msvc.cr +++ b/src/compiler/crystal/loader/msvc.cr @@ -139,7 +139,7 @@ class Crystal::Loader return false unless handle @handles << handle - @loaded_libraries << dll + @loaded_libraries << (module_filename(handle) || dll) end true @@ -162,6 +162,7 @@ class Crystal::Loader def load_current_program_handle if LibC.GetModuleHandleExW(0, nil, out hmodule) != 0 @handles << hmodule + @loaded_libraries << (Process.executable_path || "current program handle") end end @@ -172,6 +173,19 @@ class Crystal::Loader @handles.clear end + private def module_filename(handle) + Crystal::System.retry_wstr_buffer do |buffer, small_buf| + len = LibC.GetModuleFileNameW(handle, buffer, buffer.size) + if 0 < len < buffer.size + break String.from_utf16(buffer[0, len]) + elsif small_buf && len == buffer.size + next 32767 # big enough. 32767 is the maximum total path length of UNC path. + else + break nil + end + end + end + # Returns a list of directories used as the default search paths. # # For MSVC this is simply the contents of the `LIB` environment variable, diff --git a/src/compiler/crystal/loader/unix.cr b/src/compiler/crystal/loader/unix.cr index 4c202231d7e6..39fef6e0c318 100644 --- a/src/compiler/crystal/loader/unix.cr +++ b/src/compiler/crystal/loader/unix.cr @@ -120,6 +120,7 @@ class Crystal::Loader def load_current_program_handle if program_handle = LibC.dlopen(nil, LibC::RTLD_LAZY | LibC::RTLD_GLOBAL) @handles << program_handle + @loaded_libraries << (Process.executable_path || "current program handle") end end