@@ -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