1 /* 2 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) altlinux.org> 3 * Copyright (c) 2016-2018 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "defs.h" 30 31 #include DEF_MPERS_TYPE(timeval_t) 32 33 typedef struct timeval timeval_t; 34 35 #include MPERS_DEFS 36 37 #include "xstring.h" 38 39 static const char timeval_fmt[] = "{tv_sec=%lld, tv_usec=%llu}"; 40 41 static void 42 print_timeval_t(const timeval_t *t) 43 { 44 tprintf(timeval_fmt, (long long) t->tv_sec, 45 zero_extend_signed_to_ull(t->tv_usec)); 46 } 47 48 static void 49 print_timeval_t_utime(const timeval_t *t) 50 { 51 print_timeval_t(t); 52 tprints_comment(sprinttime_usec(t->tv_sec, 53 zero_extend_signed_to_ull(t->tv_usec))); 54 } 55 56 MPERS_PRINTER_DECL(void, print_struct_timeval, const void *arg) 57 { 58 print_timeval_t(arg); 59 } 60 61 MPERS_PRINTER_DECL(bool, print_struct_timeval_data_size, 62 const void *arg, const size_t size) 63 { 64 if (size < sizeof(timeval_t)) { 65 tprints("?"); 66 return false; 67 } 68 69 print_timeval_t(arg); 70 return true; 71 } 72 73 MPERS_PRINTER_DECL(void, print_timeval, 74 struct tcb *const tcp, const kernel_ulong_t addr) 75 { 76 timeval_t t; 77 78 if (umove_or_printaddr(tcp, addr, &t)) 79 return; 80 81 print_timeval_t(&t); 82 } 83 84 MPERS_PRINTER_DECL(void, print_timeval_utimes, 85 struct tcb *const tcp, const kernel_ulong_t addr) 86 { 87 timeval_t t[2]; 88 89 if (umove_or_printaddr(tcp, addr, &t)) 90 return; 91 92 tprints("["); 93 print_timeval_t_utime(&t[0]); 94 tprints(", "); 95 print_timeval_t_utime(&t[1]); 96 tprints("]"); 97 } 98 99 MPERS_PRINTER_DECL(const char *, sprint_timeval, 100 struct tcb *const tcp, const kernel_ulong_t addr) 101 { 102 timeval_t t; 103 static char buf[sizeof(timeval_fmt) + 3 * sizeof(t)]; 104 105 if (!addr) { 106 strcpy(buf, "NULL"); 107 } else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || 108 umove(tcp, addr, &t)) { 109 xsprintf(buf, "%#" PRI_klx, addr); 110 } else { 111 xsprintf(buf, timeval_fmt, 112 (long long) t.tv_sec, 113 zero_extend_signed_to_ull(t.tv_usec)); 114 } 115 116 return buf; 117 } 118 119 MPERS_PRINTER_DECL(void, print_itimerval, 120 struct tcb *const tcp, const kernel_ulong_t addr) 121 { 122 timeval_t t[2]; 123 124 if (umove_or_printaddr(tcp, addr, &t)) 125 return; 126 127 tprints("{it_interval="); 128 print_timeval_t(&t[0]); 129 tprints(", it_value="); 130 print_timeval_t(&t[1]); 131 tprints("}"); 132 } 133 134 #ifdef ALPHA 135 136 void 137 print_timeval32_t(const timeval32_t *t) 138 { 139 tprintf(timeval_fmt, (long long) t->tv_sec, 140 zero_extend_signed_to_ull(t->tv_usec)); 141 } 142 143 static void 144 print_timeval32_t_utime(const timeval32_t *t) 145 { 146 print_timeval32_t(t); 147 tprints_comment(sprinttime_usec(t->tv_sec, 148 zero_extend_signed_to_ull(t->tv_usec))); 149 } 150 151 void 152 print_timeval32(struct tcb *const tcp, const kernel_ulong_t addr) 153 { 154 timeval32_t t; 155 156 if (umove_or_printaddr(tcp, addr, &t)) 157 return; 158 159 print_timeval32_t(&t); 160 } 161 162 void 163 print_timeval32_utimes(struct tcb *const tcp, const kernel_ulong_t addr) 164 { 165 timeval32_t t[2]; 166 167 if (umove_or_printaddr(tcp, addr, &t)) 168 return; 169 170 tprints("["); 171 print_timeval32_t_utime(&t[0]); 172 tprints(", "); 173 print_timeval32_t_utime(&t[1]); 174 tprints("]"); 175 } 176 177 void 178 print_itimerval32(struct tcb *const tcp, const kernel_ulong_t addr) 179 { 180 timeval32_t t[2]; 181 182 if (umove_or_printaddr(tcp, addr, &t)) 183 return; 184 185 tprints("{it_interval="); 186 print_timeval32_t(&t[0]); 187 tprints(", it_value="); 188 print_timeval32_t(&t[1]); 189 tprints("}"); 190 } 191 192 const char * 193 sprint_timeval32(struct tcb *const tcp, const kernel_ulong_t addr) 194 { 195 timeval32_t t; 196 static char buf[sizeof(timeval_fmt) + 3 * sizeof(t)]; 197 198 if (!addr) { 199 strcpy(buf, "NULL"); 200 } else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || 201 umove(tcp, addr, &t)) { 202 xsprintf(buf, "%#" PRI_klx, addr); 203 } else { 204 xsprintf(buf, timeval_fmt, 205 (long long) t.tv_sec, 206 zero_extend_signed_to_ull(t.tv_usec)); 207 } 208 209 return buf; 210 } 211 212 #endif /* ALPHA */ 213