emscripten-core / emscripten-core/emscripten

POSIXism leaks to compiled MINIMAL_RUNTIME code: environ_get in code but unused

Open
#10,345 5 comments 0 reactions 0 assignees View on GitHub
wontfix
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

After updating our builds to latest LLVM backend, I am seeing a callstack
```
_environ_get
__emscripten_environ_constructor
initRuntime
```
even when the program does not use POSIX environment functionality. This looks like creeped in from #9525.

More specifically, builds now contain
```js
var ENV={};

function __get_executable_name() {
return "./this.program";
}function _emscripten_get_environ() {
if (!_emscripten_get_environ.strings) {
// Default values.
var env = {
'USER': 'web_user',
'LOGNAME': 'web_user',
'PATH': '/',
'PWD': '/',
'HOME': '/home/web_user',
// Browser language detection #8751
'LANG': ((typeof navigator === 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8',
'_': __get_executable_name()
};
// Apply the user-provided values, if any.
for (var x in ENV) {
env[x] = ENV[x];
}
var strings = [];
for (var x in env) {
strings.push(x + '=' + env[x]);
}
_emscripten_get_environ.strings = strings;
}
return _emscripten_get_environ.strings;
}
function writeAsciiToMemory(str, buffer, dontAddNull) {
for (var i = 0; i < str.length; ++i) {
HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
}
function _environ_get(__environ, environ_buf) {
console.error('_environ_get');
var strings = _emscripten_get_environ();
var bufSize = 0;
strings.forEach(function(string, i) {
var ptr = environ_buf + bufSize;
HEAP32[(((__environ)+(i * 4))>>2)]=ptr;
writeAsciiToMemory(string, ptr);
bufSize += string.length + 1;
});
return 0;
}

function _environ_sizes_get(penviron_count, penviron_buf_size) {
var strings = _emscripten_get_environ();
HEAP32[((penviron_count)>>2)]=strings.length;
var bufSize = 0;
strings.forEach(function(string) {
bufSize += string.length + 1;
});
HEAP32[((penviron_buf_size)>>2)]=bufSize;
return 0;
}
function _exit(status) {
throw 'exit(' + status + ')';
}
```

and Wasm code has
```wasm
(import "wasi_snapshot_preview1" "environ_sizes_get" (func $__wasi_environ_sizes_get (param i32 i32) (result i32)))
(import "wasi_snapshot_preview1" "environ_get" (func $__wasi_environ_get (param i32 i32) (result i32)))

(func $__wasm_call_ctors (; 405 ;)
(local $0 i32)
(call $__emscripten_environ_constructor)
...

(func $__emscripten_environ_constructor (; 3510 ;)
(local $0 i32)
(local $1 i32)
(local $2 i32)
(global.set $global$0
(local.tee $0
(i32.sub
(global.get $global$0)
(i32.const 16)
)
)
)
(block $label$1
(br_if $label$1
(call $__wasi_environ_sizes_get
(i32.add
(local.get $0)
(i32.const 12)
)
(i32.add
(local.get $0)
(i32.const 8)
)
)
)
(i32.store
(i32.const 738840)
(local.tee $1
(call $dlmalloc
(i32.add
(i32.shl
(i32.load offset=12
(local.get $0)
)
(i32.const 2)
)
(i32.const 4)
)
)
)
)
(br_if $label$1
(i32.eqz
(local.get $1)
)
)
(block $label$2
(if
(local.tee $1
(call $dlmalloc
(i32.load offset=8
(local.get $0)
)
)
)
(br_if $label$2
(local.tee $2
(i32.load
(i32.const 738840)
)
)
)
)
(i32.store
(i32.const 738840)
(i32.const 0)
)
(br $label$1)
)
(i32.store
(i32.add
(local.get $2)
(i32.shl
(i32.load offset=12
(local.get $0)
)
(i32.const 2)
)
)
(i32.const 0)
)
(br_if $label$1
(i32.eqz
(call $__wasi_environ_get
(i32.load
(i32.const 738840)
)
(local.get $1)
)
)
)
(i32.store
(i32.const 738840)
(i32.const 0)
)
)
(global.set $global$0
(i32.add
(local.get $0)
(i32.const 16)
)
)
)
```
that are unused by the build.

How should these be best removed? Should we introduce a -s WASI=0/1 parameter, or can the constructor be dropped by some other way?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.