1
1
use super :: unsupported;
2
+ use crate :: collections:: HashMap ;
2
3
use crate :: error:: Error as StdError ;
3
4
use crate :: ffi:: { OsStr , OsString } ;
4
5
use crate :: marker:: PhantomData ;
5
6
use crate :: os:: xous:: ffi:: Error as XousError ;
6
7
use crate :: path:: { self , PathBuf } ;
7
- use crate :: { fmt, io} ;
8
+ use crate :: sync:: {
9
+ atomic:: { AtomicPtr , AtomicUsize , Ordering } ,
10
+ Mutex , Once ,
11
+ } ;
12
+ use crate :: { fmt, io, vec} ;
13
+
14
+ pub ( crate ) mod params;
15
+
16
+ static PARAMS_ADDRESS : AtomicPtr < u8 > = AtomicPtr :: new ( core:: ptr:: null_mut ( ) ) ;
8
17
9
18
#[ cfg( not( test) ) ]
10
19
#[ cfg( feature = "panic_unwind" ) ]
11
20
mod eh_unwinding {
12
- pub ( crate ) struct EhFrameFinder ( usize /* eh_frame */ ) ;
13
- pub ( crate ) static mut EH_FRAME_SETTINGS : EhFrameFinder = EhFrameFinder ( 0 ) ;
14
- impl EhFrameFinder {
15
- pub ( crate ) unsafe fn init ( & mut self , eh_frame : usize ) {
16
- unsafe {
17
- EH_FRAME_SETTINGS . 0 = eh_frame;
18
- }
19
- }
20
- }
21
+ pub ( crate ) struct EhFrameFinder ;
22
+ pub ( crate ) static mut EH_FRAME_ADDRESS : usize = 0 ;
23
+ pub ( crate ) static EH_FRAME_SETTINGS : EhFrameFinder = EhFrameFinder ;
24
+
21
25
unsafe impl unwind:: EhFrameFinder for EhFrameFinder {
22
26
fn find ( & self , _pc : usize ) -> Option < unwind:: FrameInfo > {
23
- Some ( unwind:: FrameInfo {
24
- text_base : None ,
25
- kind : unwind:: FrameInfoKind :: EhFrame ( self . 0 ) ,
26
- } )
27
+ if unsafe { EH_FRAME_ADDRESS == 0 } {
28
+ None
29
+ } else {
30
+ Some ( unwind:: FrameInfo {
31
+ text_base : None ,
32
+ kind : unwind:: FrameInfoKind :: EhFrame ( unsafe { EH_FRAME_ADDRESS } ) ,
33
+ } )
34
+ }
27
35
}
28
36
}
29
37
}
@@ -41,12 +49,21 @@ mod c_compat {
41
49
}
42
50
43
51
#[ no_mangle]
44
- pub extern "C" fn _start ( eh_frame : usize ) {
52
+ pub extern "C" fn _start ( eh_frame : usize , params_address : usize ) {
45
53
#[ cfg( feature = "panic_unwind" ) ]
46
- unsafe {
47
- super :: eh_unwinding:: EH_FRAME_SETTINGS . init ( eh_frame) ;
54
+ {
55
+ unsafe { super :: eh_unwinding:: EH_FRAME_ADDRESS = eh_frame } ;
48
56
unwind:: set_custom_eh_frame_finder ( & super :: eh_unwinding:: EH_FRAME_SETTINGS ) . ok ( ) ;
49
57
}
58
+
59
+ if params_address != 0 {
60
+ let params_address = crate :: ptr:: with_exposed_provenance_mut :: < u8 > ( params_address) ;
61
+ if unsafe {
62
+ super :: params:: ApplicationParameters :: new_from_ptr ( params_address) . is_some ( )
63
+ } {
64
+ super :: PARAMS_ADDRESS . store ( params_address, core:: sync:: atomic:: Ordering :: Relaxed ) ;
65
+ }
66
+ }
50
67
exit ( unsafe { main ( ) } ) ;
51
68
}
52
69
@@ -116,44 +133,103 @@ pub fn current_exe() -> io::Result<PathBuf> {
116
133
unsupported ( )
117
134
}
118
135
119
- pub struct Env ( !) ;
136
+ pub ( crate ) fn get_application_parameters ( ) -> Option < params:: ApplicationParameters > {
137
+ let params_address = PARAMS_ADDRESS . load ( Ordering :: Relaxed ) ;
138
+ unsafe { params:: ApplicationParameters :: new_from_ptr ( params_address) }
139
+ }
140
+
141
+ // ---------- Environment handling ---------- //
142
+ static ENV : AtomicUsize = AtomicUsize :: new ( 0 ) ;
143
+ static ENV_INIT : Once = Once :: new ( ) ;
144
+ type EnvStore = Mutex < HashMap < OsString , OsString > > ;
145
+
146
+ fn get_env_store ( ) -> & ' static EnvStore {
147
+ ENV_INIT . call_once ( || {
148
+ let env_store = EnvStore :: default ( ) ;
149
+ if let Some ( params) = get_application_parameters ( ) {
150
+ for param in params {
151
+ if let Ok ( envs) = params:: EnvironmentBlock :: try_from ( & param) {
152
+ let mut env_store = env_store. lock ( ) . unwrap ( ) ;
153
+ for env in envs {
154
+ env_store. insert ( env. key . into ( ) , env. value . into ( ) ) ;
155
+ }
156
+ break ;
157
+ }
158
+ }
159
+ }
160
+ ENV . store ( Box :: into_raw ( Box :: new ( env_store) ) as _ , Ordering :: Relaxed )
161
+ } ) ;
162
+ unsafe { & * core:: ptr:: with_exposed_provenance :: < EnvStore > ( ENV . load ( Ordering :: Relaxed ) ) }
163
+ }
164
+
165
+ pub struct Env {
166
+ iter : vec:: IntoIter < ( OsString , OsString ) > ,
167
+ }
168
+
169
+ // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
170
+ pub struct EnvStrDebug < ' a > {
171
+ slice : & ' a [ ( OsString , OsString ) ] ,
172
+ }
173
+
174
+ impl fmt:: Debug for EnvStrDebug < ' _ > {
175
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
176
+ let Self { slice } = self ;
177
+ f. debug_list ( )
178
+ . entries ( slice. iter ( ) . map ( |( a, b) | ( a. to_str ( ) . unwrap ( ) , b. to_str ( ) . unwrap ( ) ) ) )
179
+ . finish ( )
180
+ }
181
+ }
120
182
121
183
impl Env {
122
184
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
123
185
pub fn str_debug ( & self ) -> impl fmt:: Debug + ' _ {
124
- let Self ( inner ) = self ;
125
- match * inner { }
186
+ let Self { iter } = self ;
187
+ EnvStrDebug { slice : iter . as_slice ( ) }
126
188
}
127
189
}
128
190
129
191
impl fmt:: Debug for Env {
130
- fn fmt ( & self , _ : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
131
- let Self ( inner ) = self ;
132
- match * inner { }
192
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
193
+ let Self { iter } = self ;
194
+ f . debug_list ( ) . entries ( iter . as_slice ( ) ) . finish ( )
133
195
}
134
196
}
135
197
198
+ impl !Send for Env { }
199
+ impl !Sync for Env { }
200
+
136
201
impl Iterator for Env {
137
202
type Item = ( OsString , OsString ) ;
138
203
fn next ( & mut self ) -> Option < ( OsString , OsString ) > {
139
- self . 0
204
+ self . iter . next ( )
205
+ }
206
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
207
+ self . iter . size_hint ( )
140
208
}
141
209
}
142
210
143
211
pub fn env ( ) -> Env {
144
- panic ! ( "not supported on this platform" )
212
+ let clone_to_vec = |map : & HashMap < OsString , OsString > | -> Vec < _ > {
213
+ map. iter ( ) . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) ) . collect ( )
214
+ } ;
215
+
216
+ let iter = clone_to_vec ( & * get_env_store ( ) . lock ( ) . unwrap ( ) ) . into_iter ( ) ;
217
+ Env { iter }
145
218
}
146
219
147
- pub fn getenv ( _ : & OsStr ) -> Option < OsString > {
148
- None
220
+ pub fn getenv ( k : & OsStr ) -> Option < OsString > {
221
+ get_env_store ( ) . lock ( ) . unwrap ( ) . get ( k ) . cloned ( )
149
222
}
150
223
151
- pub unsafe fn setenv ( _: & OsStr , _: & OsStr ) -> io:: Result < ( ) > {
152
- Err ( io:: const_io_error!( io:: ErrorKind :: Unsupported , "cannot set env vars on this platform" ) )
224
+ pub unsafe fn setenv ( k : & OsStr , v : & OsStr ) -> io:: Result < ( ) > {
225
+ let ( k, v) = ( k. to_owned ( ) , v. to_owned ( ) ) ;
226
+ get_env_store ( ) . lock ( ) . unwrap ( ) . insert ( k, v) ;
227
+ Ok ( ( ) )
153
228
}
154
229
155
- pub unsafe fn unsetenv ( _: & OsStr ) -> io:: Result < ( ) > {
156
- Err ( io:: const_io_error!( io:: ErrorKind :: Unsupported , "cannot unset env vars on this platform" ) )
230
+ pub unsafe fn unsetenv ( k : & OsStr ) -> io:: Result < ( ) > {
231
+ get_env_store ( ) . lock ( ) . unwrap ( ) . remove ( k) ;
232
+ Ok ( ( ) )
157
233
}
158
234
159
235
pub fn temp_dir ( ) -> PathBuf {
0 commit comments