@@ -62,6 +62,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
6262 // We need to support it because std uses it.
6363 relative_clocks. push ( this. eval_libc_i32 ( "CLOCK_UPTIME_RAW" ) ) ;
6464 }
65+ "solaris" | "illumos" => {
66+ // The REALTIME clock returns the actual time since the Unix epoch.
67+ absolute_clocks = vec ! [ this. eval_libc_i32( "CLOCK_REALTIME" ) ] ;
68+ // MONOTONIC, in the other hand, is the high resolution, non-adjustable
69+ // clock from an arbitrary time in the past.
70+ // Note that the man page mentions HIGHRES but it is just
71+ // an alias of MONOTONIC and the libc crate does not expose it anyway.
72+ // https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html
73+ relative_clocks = vec ! [ this. eval_libc_i32( "CLOCK_MONOTONIC" ) ] ;
74+ }
6575 target => throw_unsup_format ! ( "`clock_gettime` is not supported on target OS {target}" ) ,
6676 }
6777
@@ -153,30 +163,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
153163 // chrono crate yet.
154164 // This may not be consistent with libc::localtime_r's result.
155165 let tm_isdst = -1 ;
156-
157- // tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
158- // This may not be consistent with libc::localtime_r's result.
159- let offset_in_seconds = dt. offset ( ) . fix ( ) . local_minus_utc ( ) ;
160- let tm_gmtoff = offset_in_seconds;
161- let mut tm_zone = String :: new ( ) ;
162- if offset_in_seconds < 0 {
163- tm_zone. push ( '-' ) ;
164- } else {
165- tm_zone. push ( '+' ) ;
166- }
167- let offset_hour = offset_in_seconds. abs ( ) / 3600 ;
168- write ! ( tm_zone, "{:02}" , offset_hour) . unwrap ( ) ;
169- let offset_min = ( offset_in_seconds. abs ( ) % 3600 ) / 60 ;
170- if offset_min != 0 {
171- write ! ( tm_zone, "{:02}" , offset_min) . unwrap ( ) ;
172- }
173-
174- // FIXME: String de-duplication is needed so that we only allocate this string only once
175- // even when there are multiple calls to this function.
176- let tm_zone_ptr =
177- this. alloc_os_str_as_c_str ( & OsString :: from ( tm_zone) , MiriMemoryKind :: Machine . into ( ) ) ?;
178-
179- this. write_pointer ( tm_zone_ptr, & this. project_field_named ( & result, "tm_zone" ) ?) ?;
180166 this. write_int_fields_named (
181167 & [
182168 ( "tm_sec" , dt. second ( ) . into ( ) ) ,
@@ -188,11 +174,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
188174 ( "tm_wday" , dt. weekday ( ) . num_days_from_sunday ( ) . into ( ) ) ,
189175 ( "tm_yday" , dt. ordinal0 ( ) . into ( ) ) ,
190176 ( "tm_isdst" , tm_isdst) ,
191- ( "tm_gmtoff" , tm_gmtoff. into ( ) ) ,
192177 ] ,
193178 & result,
194179 ) ?;
195180
181+ // solaris/illumos system tm struct does not have
182+ // the additional tm_zone/tm_gmtoff fields.
183+ // https://docs.oracle.com/cd/E36784_01/html/E36874/localtime-r-3c.html
184+ if !matches ! ( & * this. tcx. sess. target. os, "solaris" | "illumos" ) {
185+ // tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
186+ // This may not be consistent with libc::localtime_r's result.
187+ let offset_in_seconds = dt. offset ( ) . fix ( ) . local_minus_utc ( ) ;
188+ let tm_gmtoff = offset_in_seconds;
189+ let mut tm_zone = String :: new ( ) ;
190+ if offset_in_seconds < 0 {
191+ tm_zone. push ( '-' ) ;
192+ } else {
193+ tm_zone. push ( '+' ) ;
194+ }
195+ let offset_hour = offset_in_seconds. abs ( ) / 3600 ;
196+ write ! ( tm_zone, "{:02}" , offset_hour) . unwrap ( ) ;
197+ let offset_min = ( offset_in_seconds. abs ( ) % 3600 ) / 60 ;
198+ if offset_min != 0 {
199+ write ! ( tm_zone, "{:02}" , offset_min) . unwrap ( ) ;
200+ }
201+
202+ // FIXME: String de-duplication is needed so that we only allocate this string only once
203+ // even when there are multiple calls to this function.
204+ let tm_zone_ptr = this
205+ . alloc_os_str_as_c_str ( & OsString :: from ( tm_zone) , MiriMemoryKind :: Machine . into ( ) ) ?;
206+
207+ this. write_pointer ( tm_zone_ptr, & this. project_field_named ( & result, "tm_zone" ) ?) ?;
208+ this. write_int_fields_named ( & [ ( "tm_gmtoff" , tm_gmtoff. into ( ) ) ] , & result) ?;
209+ }
196210 Ok ( result. ptr ( ) )
197211 }
198212 #[ allow( non_snake_case, clippy:: arithmetic_side_effects) ]
0 commit comments