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