Debugging a Native Node Addon on Windows

David Velho
4 min readAug 16, 2023

--

While working on building a project that includes a NodeJs addon using N-API for Windows(and *nix), I found that binaries built on my machine work but the same binaries do not work on another machine.

loading libtorrent on my machine where the dev environment is setup
loading libtorrent on another machine without a dev environment

But the file(s) are all present. What is happening? The same behaviour was observed on Linux and MacOS machines other than mine.

I would have switched to Linux and used strace to see what was happening, but I wanted to see if Windows has any good alternatives. After some quick Google searching, I realized that I could use the built-in Visual Studio debugger.

Note: I assume that you have the Visual Studio environment setup for C++ development on windows, along with the required SDKs installed

The commands I used to load and test the libtorrent build are (in a NodeJs shell) -

const lib = require(‘./libtorrent.node’);

So I tried to find a Debug target (using the CMake extension that populates Visual Studio with stuff)

Debug targets populated by the Visual Studio CMake addon

No luck. Next, I opened Visual Studio and tried to start a NodeJs process using the debugger -

Visual Studio debug menu

But the “Start Debugging” option was greyed out. However, the “Attach to Process” option is available. Choosing that option opens the following menu -

Attach to process menu

The Module window will be of interest to us

Visual Studio Module window from the Debug view

Notice the timestamp column. Lets sort the list by timestamp and focus on the rows with a timestamp -

Close-up of module window last few rows

This makes sense as we haven’t loaded the addon yet. Let’s load the addon through Node and check the window again

loading libtorrent

We see a few more entries. On observing them, we see the following:

  • libcrypto-3-x64.dll
  • libssl-3-x64.dll

Going through the dependencies, we see that our project’s main dependency libtorrent depends on OpenSSL. Finally it clicked that I installed OpenSSL through choco

Solution 1: Bundle and distribute required DLLs

Let’s try to bundle the required DLLs with the project

libtorrent with additional DLLs

And we see that libtorrent is successfully loaded

successfully loading libtorrent

But that’s not a feasible solution. There might be scenarios where one cannot bundle multiple DLLs due to some restriction. How do we proceed?

Solution 2: If it works, it ain’t stupid

We know that the project depends on libcrypto and libssl, but probably uses a few functions or items from them. To test this theory out, I modified my project's CMakeLists.txt file to fetch openssl from Github using CMake's built in (version 3.11 and later) FetchContent

The following is an extract of the CMakeLists.txt file:

include(FetchContent)
FetchContent_Declare(
openssl
GIT_REPOSITORY https://github.com/janbar/openssl-cmake.git
SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib/openssl
GIT_TAG 392d455cd0b0fe992b312c9648eb5ea87e3afcea
)

FetchContent_MakeAvailable(openssl)
set(OPENSSL_ROOT_DIR ${CMAKE_SOURCE_DIR}/lib/openssl/*)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPENSSL_CRYPTO_LIBRARY ${CMAKE_SOURCE_DIR}/build/_deps/openssl-build/crypto/Debug)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(OPENSSL_CRYPTO_LIBRARY ${CMAKE_SOURCE_DIR}/build/_deps/openssl-build/crypto/Release)
endif()

The statement to set OPENSSL_CRYPTO_LIBRARY can be optimised further

This resulted in the following files being generated -

List of files generated after statically linking openssl
libtorrent successfully loading

--

--

No responses yet