dicej / component-linking-demo

Demo of shared-everything linking using the WebAssembly Component Model
5 stars 1 forks source link

unexpected imports in libc.so's import section #5

Closed lxyhit closed 1 year ago

lxyhit commented 1 year ago

When reproducing “component-linking-demo“ project under a virtual machine running Ubuntu 20.04 on x86 architecture, I noticed that the resulting libc.so seems to import some functions and globals that i did't expected to see. I used WABT to translate libc.so and observed the following partial output in import section:

(import "env" "getentropy" (func $getentropy (type 4)))
(import "env" "isatty" (func $isatty (type 0)))
(import "env" "reallocarray" (func $reallocarray (type 6)))
(import "env" "crypt_r" (func $crypt_r (type 6)))
(import "GOT.mem" "errno" (global $errno (mut i32)))
(import "GOT.mem" "_CLOCK_REALTIME" (global $_CLOCK_REALTIME (mut i32)))
(import "GOT.mem" "__wasilibc_environ" (global $__wasilibc_environ (mut i32)))

In addition to these imports, there are numerous similar imports. In my understanding, it seems that libc.so should implement and export these functions rather than importing them. Is this because there is a problem with my reproduction of the project or these imports in libc.so are normal?At last,English is not my native language; please excuse typing errors.

dicej commented 1 year ago

Yes, that confused me also when I first enabled building wasi-libc as a shared library. The reason all those imports exist is that wasm-ld converts weak, externally-visible symbols into pairs of imports and exports. For example, getentropy is declared as a weak symbol in wasi-libc, so wasm-ld generates an import and and an export for it. The dynamic linker (or wit-component in this example) is responsible for matching imports to exports, and will allow a module to import its own export if no other library provides one. That means that normally libc.so will import its own getentropy export (i.e. it doesn't need another library to provide it).

To summarize: libc.so can import from itself, so almost none of those imports require an external implementation. It's the dynamic linker's responsibility to link the imports to the exports and provide the remaining imports itself (e.g. via a synthetic module that contains the linear memory and function table).

lxyhit commented 1 year ago

Yes, that confused me also when I first enabled building wasi-libc as a shared library. The reason all those imports exist is that wasm-ld converts weak, externally-visible symbols into pairs of imports and exports. For example, getentropy is declared as a weak symbol in wasi-libc, so wasm-ld generates an import and and an export for it. The dynamic linker (or wit-component in this example) is responsible for matching imports to exports, and will allow a module to import its own export if no other library provides one. That means that normally libc.so will import its own getentropy export (i.e. it doesn't need another library to provide it).

To summarize: libc.so can import from itself, so almost none of those imports require an external implementation. It's the dynamic linker's responsibility to link the imports to the exports and provide the remaining imports itself (e.g. via a synthetic module that contains the linear memory and function table).

That is very clear to me. Appreciate you taking the time to explain😀.