@ -236,6 +236,12 @@ static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete,
gdb_do_syscall ( complete , " system,%s " , cmd , len ) ;
}
static void gdb_gettimeofday ( CPUState * cs , gdb_syscall_complete_cb complete ,
target_ulong tv_addr , target_ulong tz_addr )
{
gdb_do_syscall ( complete , " gettimeofday,%x,%x " , tv_addr , tz_addr ) ;
}
/*
* Host semihosting syscall implementations .
*/
@ -487,6 +493,32 @@ static void host_system(CPUState *cs, gdb_syscall_complete_cb complete,
unlock_user ( p , cmd , 0 ) ;
}
static void host_gettimeofday ( CPUState * cs , gdb_syscall_complete_cb complete ,
target_ulong tv_addr , target_ulong tz_addr )
{
CPUArchState * env G_GNUC_UNUSED = cs - > env_ptr ;
struct gdb_timeval * p ;
int64_t rt ;
/* GDB fails on non-null TZ, so be consistent. */
if ( tz_addr ! = 0 ) {
complete ( cs , - 1 , EINVAL ) ;
return ;
}
p = lock_user ( VERIFY_WRITE , tv_addr , sizeof ( struct gdb_timeval ) , 0 ) ;
if ( ! p ) {
complete ( cs , - 1 , EFAULT ) ;
return ;
}
/* TODO: Like stat, gdb always produces big-endian results; match it. */
rt = g_get_real_time ( ) ;
p - > tv_sec = cpu_to_be32 ( rt / G_USEC_PER_SEC ) ;
p - > tv_usec = cpu_to_be64 ( rt % G_USEC_PER_SEC ) ;
unlock_user ( p , tv_addr , sizeof ( struct gdb_timeval ) ) ;
}
/*
* Static file semihosting syscall implementations .
*/
@ -796,3 +828,13 @@ void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete,
host_system ( cs , complete , cmd , cmd_len ) ;
}
}
void semihost_sys_gettimeofday ( CPUState * cs , gdb_syscall_complete_cb complete ,
target_ulong tv_addr , target_ulong tz_addr )
{
if ( use_gdb_syscalls ( ) ) {
gdb_gettimeofday ( cs , complete , tv_addr , tz_addr ) ;
} else {
host_gettimeofday ( cs , complete , tv_addr , tz_addr ) ;
}
}