@@ -142,7 +142,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
142142
143143 // create empty functions with similar signature
144144 ModuleUtils::iterImportedFunctions (wasm, [&](Function* func) {
145- if (func->module == " env" ) {
145+ if (func->module == env-> name ) {
146146 Builder builder (*env);
147147 auto * copied = ModuleUtils::copyFunction (func, *env);
148148 copied->module = Name ();
@@ -155,7 +155,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
155155
156156 // create tables with similar initial and max values
157157 ModuleUtils::iterImportedTables (wasm, [&](Table* table) {
158- if (table->module == " env" ) {
158+ if (table->module == env-> name ) {
159159 auto * copied = ModuleUtils::copyTable (table, *env);
160160 copied->module = Name ();
161161 copied->base = Name ();
@@ -165,7 +165,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
165165 });
166166
167167 ModuleUtils::iterImportedGlobals (wasm, [&](Global* global) {
168- if (global->module == " env" ) {
168+ if (global->module == env-> name ) {
169169 auto * copied = ModuleUtils::copyGlobal (global, *env);
170170 copied->module = Name ();
171171 copied->base = Name ();
@@ -179,7 +179,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
179179
180180 // create an exported memory with the same initial and max size
181181 ModuleUtils::iterImportedMemories (wasm, [&](Memory* memory) {
182- if (memory->module == " env" ) {
182+ if (memory->module == env-> name ) {
183183 env->memory .name = wasm.memory .name ;
184184 env->memory .exists = true ;
185185 env->memory .initial = memory->initial ;
@@ -194,6 +194,11 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
194194 return env;
195195}
196196
197+ // Whether to ignore external input to the program as it runs. If set, we will
198+ // assume that stdin is empty, that any env vars we try to read are not set,
199+ // that there are not arguments passed to main, etc.
200+ static bool ignoreExternalInput = false ;
201+
197202struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
198203 Module* wasm;
199204 EvallingModuleInstance* instance;
@@ -242,10 +247,63 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
242247 }
243248
244249 Literals callImport (Function* import , LiteralList& arguments) override {
250+ Name WASI (" wasi_snapshot_preview1" );
251+
252+ if (ignoreExternalInput) {
253+ if (import ->module == WASI) {
254+ if (import ->base == " environ_sizes_get" ) {
255+ if (arguments.size () != 2 || arguments[0 ].type != Type::i32 ||
256+ import ->getResults () != Type::i32 ) {
257+ throw FailToEvalException (" wasi environ_sizes_get has wrong sig" );
258+ }
259+
260+ // Write out a count of i32(0) and return __WASI_ERRNO_SUCCESS (0).
261+ store32 (arguments[0 ].geti32 (), 0 );
262+ return {Literal (int32_t (0 ))};
263+ }
264+
265+ if (import ->base == " environ_get" ) {
266+ if (arguments.size () != 2 || arguments[0 ].type != Type::i32 ||
267+ import ->getResults () != Type::i32 ) {
268+ throw FailToEvalException (" wasi environ_get has wrong sig" );
269+ }
270+
271+ // Just return __WASI_ERRNO_SUCCESS (0).
272+ return {Literal (int32_t (0 ))};
273+ }
274+
275+ if (import ->base == " args_sizes_get" ) {
276+ if (arguments.size () != 2 || arguments[0 ].type != Type::i32 ||
277+ import ->getResults () != Type::i32 ) {
278+ throw FailToEvalException (" wasi args_sizes_get has wrong sig" );
279+ }
280+
281+ // Write out an argc of i32(0) and return a __WASI_ERRNO_SUCCESS (0).
282+ store32 (arguments[0 ].geti32 (), 0 );
283+ return {Literal (int32_t (0 ))};
284+ }
285+
286+ if (import ->base == " args_get" ) {
287+ if (arguments.size () != 2 || arguments[0 ].type != Type::i32 ||
288+ import ->getResults () != Type::i32 ) {
289+ throw FailToEvalException (" wasi args_get has wrong sig" );
290+ }
291+
292+ // Just return __WASI_ERRNO_SUCCESS (0).
293+ return {Literal (int32_t (0 ))};
294+ }
295+
296+ // Otherwise, we don't recognize this import; continue normally to
297+ // error.
298+ }
299+ }
300+
245301 std::string extra;
246302 if (import ->module == ENV && import ->base == " ___cxa_atexit" ) {
247303 extra = " \n recommendation: build with -s NO_EXIT_RUNTIME=1 so that calls "
248304 " to atexit are not emitted" ;
305+ } else if (import ->module == WASI && !ignoreExternalInput) {
306+ extra = " \n recommendation: consider --ignore-external-input" ;
249307 }
250308 throw FailToEvalException (std::string (" call import: " ) +
251309 import ->module .str + " ." + import ->base .str +
@@ -416,14 +474,14 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
416474};
417475
418476void evalCtors (Module& wasm, std::vector<std::string> ctors) {
477+ std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
478+
419479 // build and link the env module
420480 auto envModule = buildEnvModule (wasm);
421481 CtorEvalExternalInterface envInterface;
422482 auto envInstance =
423483 std::make_shared<EvallingModuleInstance>(*envModule, &envInterface);
424-
425- std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
426- linkedInstances[" env" ] = envInstance;
484+ linkedInstances[envModule->name ] = envInstance;
427485
428486 CtorEvalExternalInterface interface (linkedInstances);
429487 try {
@@ -525,6 +583,14 @@ int main(int argc, const char* argv[]) {
525583 WasmCtorEvalOption,
526584 Options::Arguments::One,
527585 [&](Options* o, const std::string& argument) { ctorsString = argument; })
586+ .add (" --ignore-external-input" ,
587+ " -ipi" ,
588+ " Assumes no env vars are to be read, stdin is empty, etc." ,
589+ WasmCtorEvalOption,
590+ Options::Arguments::Zero,
591+ [&](Options* o, const std::string& argument) {
592+ ignoreExternalInput = true ;
593+ })
528594 .add_positional (" INFILE" ,
529595 Options::Arguments::One,
530596 [](Options* o, const std::string& argument) {
0 commit comments