diff --git a/src/fn_call.rs b/src/fn_call.rs index d11364ce0d1..ab82223f234 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -513,10 +513,6 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, this.write_null(dest)?; } - "_tlv_atexit" => { - // FIXME: Register the dtor - }, - // Determining stack base address "pthread_attr_init" | "pthread_attr_destroy" | "pthread_attr_get_np" | "pthread_getattr_np" | "pthread_self" | "pthread_get_stacksize_np" => { @@ -554,7 +550,18 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, this.write_null(dest)?; } - // Windows API subs + // macOS API stubs + "_tlv_atexit" => { + // FIXME: Register the dtor + }, + "_NSGetArgc" => { + this.write_scalar(Scalar::Ptr(this.machine.argc.unwrap()), dest)?; + }, + "_NSGetArgv" => { + this.write_scalar(Scalar::Ptr(this.machine.argv.unwrap()), dest)?; + }, + + // Windows API stubs "AddVectoredExceptionHandler" => { // any non zero value works for the stdlib. This is just used for stackoverflows anyway this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?; @@ -576,8 +583,6 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, // this is c::ERROR_CALL_NOT_IMPLEMENTED this.write_scalar(Scalar::from_int(120, dest.layout.size), dest)?; }, - - // Windows TLS "TlsAlloc" => { // This just creates a key; Windows does not natively support TLS dtors. diff --git a/src/lib.rs b/src/lib.rs index 28639976aa0..e6e1a338c9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -121,7 +121,11 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>( // Second argument (argc): 1 let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; - ecx.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?; + let argc = Scalar::from_int(1, dest.layout.size); + ecx.write_scalar(argc, dest)?; + let argc_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?; + ecx.write_scalar(argc, argc_place.into())?; + ecx.machine.argc = Some(argc_place.ptr.to_ptr()?); // FIXME: extract main source file path // Third argument (argv): &[b"foo"] @@ -132,7 +136,11 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>( let foo_place = ecx.allocate(foo_layout, MiriMemoryKind::Env.into())?; ecx.write_scalar(Scalar::Ptr(foo), foo_place.into())?; ecx.memory_mut().mark_immutable(foo_place.to_ptr()?.alloc_id)?; - ecx.write_scalar(foo_place.ptr, dest)?; + let argv = foo_place.ptr; + ecx.write_scalar(argv, dest)?; + let argv_place = ecx.allocate(dest.layout, MiriMemoryKind::Env.into())?; + ecx.write_scalar(argv, argv_place.into())?; + ecx.machine.argc = Some(argv_place.ptr.to_ptr()?); assert!(args.next().is_none(), "start lang item has more arguments than expected"); @@ -253,6 +261,11 @@ pub struct Evaluator<'tcx> { /// Miri does not expose env vars from the host to the emulated program pub(crate) env_vars: HashMap, Pointer>, + /// Program arguments (`Option` because we can only initialize them after creating the ecx). + /// These are *pointers* to argc/argv because macOS. + pub(crate) argc: Option>, + pub(crate) argv: Option>, + /// TLS state pub(crate) tls: TlsData<'tcx>, @@ -267,6 +280,8 @@ impl<'tcx> Evaluator<'tcx> { fn new(validate: bool) -> Self { Evaluator { env_vars: HashMap::default(), + argc: None, + argv: None, tls: TlsData::default(), validate, stacked_borrows: stacked_borrows::State::default(),