Skip to content

Commit 39ca828

Browse files
authored
[wasm coreclr] enable corerun on nodeJS (#119250)
1 parent d217ccf commit 39ca828

File tree

7 files changed

+89
-25
lines changed

7 files changed

+89
-25
lines changed

docs/workflow/building/coreclr/wasm.md

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ This will start a local HTTP server and you can open the provided URL in your br
6363
You can also run the runtime directly in Node.js:
6464

6565
```bash
66-
cd artifacts/bin/coreclr/browser.wasm.Debug/corewasmrun/
67-
node corewasmrun.js
66+
cd artifacts/bin/coreclr/browser.wasm.Debug/
67+
node ./corerun.js -c /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/helloworld.dll
6868
```
6969

70+
Note that path in the `args` need to be absolute path on your host file system in unix format (even on Windows).
71+
7072
## Debugging
7173

7274
### Chrome DevTools with DWARF Support
@@ -94,25 +96,38 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC
9496

9597
2. **Create a launch.json configuration:**
9698
```json
97-
{
98-
"version": "0.2.0",
99-
"configurations": [
100-
{
101-
"type": "node",
102-
"request": "launch",
103-
"name": "corewasmrun",
104-
"skipFiles": [
105-
"<node_internals>/**"
106-
],
107-
"program": "corewasmrun.js",
108-
"cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/corewasmrun/"
109-
}
110-
]
111-
}
99+
{
100+
"version": "0.2.0",
101+
"configurations": [
102+
{
103+
"type": "node",
104+
"request": "launch",
105+
"name": "corerun",
106+
"skipFiles": [
107+
"<node_internals>/**"
108+
],
109+
"outputCapture": "std",
110+
"program": "corerun.js",
111+
"env": {
112+
"PAL_DBG_CHANNELS": "+all.all"
113+
},
114+
"args": [
115+
"-c",
116+
"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/",
117+
"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll"
118+
],
119+
"cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/"
120+
}
121+
]
122+
}
112123
```
113124

125+
Note that path in the `args` need to be absolute path on your host file system in unix format (even on Windows).
126+
114127
3. **Set breakpoints** in `corewasmrun.js` in one of the `put_char` functions (the `stdout`/`stderr` implementation)
115128

116129
4. **Start debugging** and step through the WebAssembly code using the call stack
117130

118131
This approach allows you to debug the JavaScript host and step into WebAssembly code or into the C/C++ code if the Dwarf Debugging extension was installed.
132+
133+
5. to display `WCHAR *` strings in debugger watch window, cast it to `char16_t*` like `(char16_t*)pLoaderModule->m_fileName`

src/coreclr/hosts/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
include_directories(inc)
22

3+
if(CLR_CMAKE_HOST_WIN32)
4+
add_subdirectory(coreshim)
5+
endif(CLR_CMAKE_HOST_WIN32)
6+
37
if (CLR_CMAKE_TARGET_ARCH_WASM)
48
add_subdirectory(corewasmrun)
5-
else()
6-
if(CLR_CMAKE_HOST_WIN32)
7-
add_subdirectory(coreshim)
8-
endif(CLR_CMAKE_HOST_WIN32)
9-
10-
add_subdirectory(corerun)
119
endif()
10+
11+
add_subdirectory(corerun)

src/coreclr/hosts/corerun/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ endif(CLR_CMAKE_HOST_WIN32)
1111
#Required to expose symbols for global symbol discovery.
1212
set(CLR_CMAKE_KEEP_NATIVE_SYMBOLS TRUE)
1313

14+
if (DEFINED CLR_CMAKE_ICU_DIR)
15+
link_directories(${CLR_CMAKE_ICU_DIR}/lib)
16+
endif(DEFINED CLR_CMAKE_ICU_DIR)
17+
1418
add_executable_clr(corerun
1519
corerun.cpp
1620
dotenv.cpp
@@ -42,6 +46,20 @@ else(CLR_CMAKE_HOST_WIN32)
4246
if(NOT CLR_CMAKE_TARGET_ANDROID)
4347
target_link_libraries(corerun PRIVATE pthread)
4448
endif()
49+
# Static linking
50+
if (CLR_CMAKE_TARGET_ARCH_WASM)
51+
target_link_libraries(corerun PRIVATE
52+
coreclr_static
53+
clrinterpreter
54+
icuuc
55+
icui18n
56+
icudata)
57+
# linker options for NodeJs, link in JavaScript helper, access to local filesystem
58+
if (CLR_CMAKE_TARGET_BROWSER)
59+
target_compile_options(corerun PRIVATE -fwasm-exceptions)
60+
target_link_options(corerun PRIVATE -fwasm-exceptions -sEXPORTED_RUNTIME_METHODS=FS -sEXIT_RUNTIME=1 -sINITIAL_MEMORY=134217728 -sSTACK_SIZE=5MB -lnoderawfs.js -lnodefs.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/corerun.js -Wl,-error-limit=0)
61+
endif()
62+
endif()
4563
endif(CLR_CMAKE_HOST_WIN32)
4664

4765
if (CLR_CMAKE_HOST_APPLE)

src/coreclr/hosts/corerun/corerun.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,26 @@ static string_t build_tpa(const string_t& core_root, const string_t& core_librar
158158

159159
static bool try_get_export(pal::mod_t mod, const char* symbol, void** fptr)
160160
{
161+
#ifndef TARGET_WASM
161162
assert(mod != nullptr && symbol != nullptr && fptr != nullptr);
162163
*fptr = pal::get_module_symbol(mod, symbol);
163164
if (*fptr != nullptr)
164165
return true;
166+
#else // !TARGET_WASM
167+
if (!strcmp(symbol, "coreclr_initialize")){
168+
*fptr = (void*)coreclr_initialize;
169+
return true;
170+
} else if (!strcmp(symbol, "coreclr_execute_assembly")){
171+
*fptr = (void*)coreclr_execute_assembly;
172+
return true;
173+
} else if (!strcmp(symbol, "coreclr_shutdown_2")){
174+
*fptr = (void*)coreclr_shutdown_2;
175+
return true;
176+
} else if (!strcmp(symbol, "coreclr_set_error_writer")){
177+
*fptr = (void*)coreclr_set_error_writer;
178+
return true;
179+
}
180+
#endif // !TARGET_WASM
165181

166182
pal::fprintf(stderr, W("Export '%s' not found.\n"), symbol);
167183
return false;

src/coreclr/hosts/corerun/corerun.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,14 @@ namespace pal
375375
const char_t dir_delim = W('/');
376376
const char_t env_path_delim = W(':');
377377

378+
#ifndef TARGET_WASM
378379
#if defined(__APPLE__)
379380
const char_t nativelib_ext[] = W(".dylib");
380381
#else // Various Linux-related OS-es
381382
const char_t nativelib_ext[] = W(".so");
382383
#endif
383384
const char_t coreclr_lib[] = W("libcoreclr");
385+
#endif // !TARGET_WASM
384386

385387
inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); }
386388
inline size_t strlen(const char_t* str) { return ::strlen(str); }
@@ -568,6 +570,7 @@ namespace pal
568570

569571
inline bool try_load_hostpolicy(pal::string_t mock_hostpolicy_value)
570572
{
573+
#ifndef TARGET_WASM
571574
if (!string_ends_with(mock_hostpolicy_value, pal::nativelib_ext))
572575
mock_hostpolicy_value.append(pal::nativelib_ext);
573576

@@ -576,6 +579,9 @@ namespace pal
576579
pal::fprintf(stderr, W("Failed to load mock hostpolicy at path '%s'. Error: %s\n"), mock_hostpolicy_value.c_str(), dlerror());
577580

578581
return hMod != nullptr;
582+
#else // !TARGET_WASM
583+
return false;
584+
#endif // !TARGET_WASM
579585
}
580586

581587
inline bool try_load_library(const pal::string_t& path, pal::mod_t& hMod)
@@ -592,6 +598,7 @@ namespace pal
592598

593599
inline bool try_load_coreclr(const pal::string_t& core_root, pal::mod_t& hMod)
594600
{
601+
#ifndef TARGET_WASM
595602
pal::string_t coreclr_path = core_root;
596603
pal::ensure_trailing_delimiter(coreclr_path);
597604
coreclr_path.append(pal::coreclr_lib);
@@ -603,7 +610,7 @@ namespace pal
603610
pal::fprintf(stderr, W("Failed to load: '%s'. Error: %s\n"), coreclr_path.c_str(), dlerror());
604611
return false;
605612
}
606-
613+
#endif // !TARGET_WASM
607614
return true;
608615
}
609616
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Module.preRun = () => {
2+
// copy all node/shell env variables to emscripten env
3+
for (const [key, value] of Object.entries(process.env)) {
4+
ENV[key] = value;
5+
}
6+
console.log("corerun.js preRun: " + Module.FS.cwd());
7+
};

src/coreclr/pal/src/arch/wasm/stubs.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "pal/dbgmsg.h"
55
#include "pal/signal.hpp"
6+
#include <emscripten/emscripten.h>
67

78
SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first
89

@@ -18,7 +19,7 @@ DBG_DebugBreak()
1819
#ifdef _DEBUG
1920
DBG_PrintInterpreterStack();
2021
#endif // _DEBUG
21-
asm volatile ("unreachable");
22+
emscripten_debugger();
2223
}
2324

2425
/* context */

0 commit comments

Comments
 (0)