blob: 782b414649e9652edb04c4c823725fd75ef85f30 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/param.h>
36#include <fcntl.h>
Mike Frysinger54646b82015-08-19 13:29:27 -040037#include <stdarg.h>
Dmitry V. Levind93c4e82015-06-17 20:09:13 +000038#ifdef HAVE_SYS_XATTR_H
Masatake YAMATOf5480672014-11-22 19:03:33 +090039# include <sys/xattr.h>
40#endif
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000041#include <sys/uio.h>
Wichert Akkerman36915a11999-07-13 15:45:02 +000042
Dmitry V. Levin5503dd22015-02-13 02:12:14 +000043#include "regs.h"
Dmitry V. Levin7211dbc2015-02-28 12:20:21 +000044#include "ptrace.h"
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000045
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000047string_to_uint(const char *str)
48{
49 char *error;
50 long value;
51
52 if (!*str)
53 return -1;
54 errno = 0;
55 value = strtol(str, &error, 10);
56 if (errno || *error || value < 0 || (long)(int)value != value)
57 return -1;
58 return (int)value;
59}
60
61int
Dmitry V. Levin447db452014-05-29 17:59:01 +000062tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063{
64 return a->tv_sec || a->tv_usec;
65}
66
67int
Dmitry V. Levin447db452014-05-29 17:59:01 +000068tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069{
70 if (a->tv_sec < b->tv_sec
71 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
72 return -1;
73 if (a->tv_sec > b->tv_sec
74 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
75 return 1;
76 return 0;
77}
78
79double
Dmitry V. Levin447db452014-05-29 17:59:01 +000080tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000081{
82 return tv->tv_sec + tv->tv_usec/1000000.0;
83}
84
85void
Dmitry V. Levin447db452014-05-29 17:59:01 +000086tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087{
88 tv->tv_sec = a->tv_sec + b->tv_sec;
89 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +000090 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000091 tv->tv_sec++;
92 tv->tv_usec -= 1000000;
93 }
94}
95
96void
Dmitry V. Levin447db452014-05-29 17:59:01 +000097tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098{
99 tv->tv_sec = a->tv_sec - b->tv_sec;
100 tv->tv_usec = a->tv_usec - b->tv_usec;
101 if (((long) tv->tv_usec) < 0) {
102 tv->tv_sec--;
103 tv->tv_usec += 1000000;
104 }
105}
106
107void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000108tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109{
110 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
111 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
112 tv->tv_usec %= 1000000;
113}
114
115void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000116tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117{
118 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000119 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 tv->tv_usec %= 1000000;
121}
122
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000123const char *
Dmitry V. Levinc0db59b2016-05-14 21:55:35 +0000124xlookup(const struct xlat *xlat, const uint64_t val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125{
126 for (; xlat->str != NULL; xlat++)
127 if (xlat->val == val)
128 return xlat->str;
129 return NULL;
130}
131
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000132static int
133xlat_bsearch_compare(const void *a, const void *b)
134{
Dmitry V. Levin43242e62016-04-28 18:37:54 +0000135 const uint64_t val1 = *(const uint64_t *) a;
136 const uint64_t val2 = ((const struct xlat *) b)->val;
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000137 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
138}
139
140const char *
Dmitry V. Levin43242e62016-04-28 18:37:54 +0000141xlat_search(const struct xlat *xlat, const size_t nmemb, const uint64_t val)
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000142{
143 const struct xlat *e =
Dmitry V. Levin43242e62016-04-28 18:37:54 +0000144 bsearch((const void*) &val,
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000145 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
146
147 return e ? e->str : NULL;
148}
149
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200150#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200151char *
152stpcpy(char *dst, const char *src)
153{
154 while ((*dst = *src++) != '\0')
155 dst++;
156 return dst;
157}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200158#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200159
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100160/* Find a next bit which is set.
161 * Starts testing at cur_bit.
162 * Returns -1 if no more bits are set.
163 *
164 * We never touch bytes we don't need to.
165 * On big-endian, array is assumed to consist of
166 * current_wordsize wide words: for example, is current_wordsize is 4,
167 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
168 * On little-endian machines, word size is immaterial.
169 */
170int
171next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
172{
173 const unsigned endian = 1;
174 int little_endian = *(char*)&endian;
175
176 const uint8_t *array = bit_array;
177 unsigned pos = cur_bit / 8;
178 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
179
180 for (;;) {
181 uint8_t bitmask;
182 uint8_t cur_byte;
183
184 if (cur_bit >= size_bits)
185 return -1;
186 cur_byte = array[pos ^ pos_xor_mask];
187 if (cur_byte == 0) {
188 cur_bit = (cur_bit + 8) & (-8);
189 pos++;
190 continue;
191 }
192 bitmask = 1 << (cur_bit & 7);
193 for (;;) {
194 if (cur_byte & bitmask)
195 return cur_bit;
196 cur_bit++;
197 if (cur_bit >= size_bits)
198 return -1;
199 bitmask <<= 1;
200 /* This check *can't be* optimized out: */
201 if (bitmask == 0)
202 break;
203 }
204 pos++;
205 }
206}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000207/*
208 * Print entry in struct xlat table, if there.
209 */
210void
Dmitry V. Levinc1328102016-04-28 18:42:10 +0000211printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212{
Mike Frysinger54646b82015-08-19 13:29:27 -0400213 va_list args;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214
Mike Frysinger54646b82015-08-19 13:29:27 -0400215 va_start(args, xlat);
216 for (; xlat; xlat = va_arg(args, const struct xlat *)) {
217 const char *str = xlookup(xlat, val);
218
219 if (str) {
220 tprints(str);
221 va_end(args);
222 return;
223 }
224 }
225 /* No hits -- print raw # instead. */
Dmitry V. Levinc1328102016-04-28 18:42:10 +0000226 tprintf("%#" PRIx64 " /* %s */", val, dflt);
Mike Frysinger54646b82015-08-19 13:29:27 -0400227
228 va_end(args);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229}
230
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100231/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000232 * Fetch 64bit argument at position arg_no and
233 * return the index of the next argument.
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100234 */
235int
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000236getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100237{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000238#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
239# if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin6974c912015-11-26 18:25:34 +0000240# ifdef X86_64
241 if (current_personality != 1) {
242# else
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000243 if (current_wordsize > 4) {
Dmitry V. Levin6974c912015-11-26 18:25:34 +0000244# endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000245# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000246 *val = tcp->u_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100247 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000248# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100249 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000250# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000251 /* Align arg_no to the next even number. */
252 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000253# endif /* AARCH64 || POWERPC64 */
254 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100255 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100256 }
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000257# endif /* SUPPORTED_PERSONALITIES > 1 */
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000258#elif SIZEOF_LONG > 4
259# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
Dmitry V. Levinb0c51132016-06-17 16:12:13 +0000260#elif HAVE_STRUCT_TCB_EXT_ARG
261# if SUPPORTED_PERSONALITIES > 1
262 if (current_personality == 1) {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000263 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000264 arg_no += 2;
Dmitry V. Levinb0c51132016-06-17 16:12:13 +0000265 } else
266# endif
267 {
268 *val = tcp->ext_arg[arg_no];
269 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000270 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100271#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000272# if defined __ARM_EABI__ || \
273 defined LINUX_MIPSO32 || \
274 defined POWERPC || \
275 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000276 /* Align arg_no to the next even number. */
277 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000278# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000279 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100280 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100281#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000282
Chris Metcalf879dddd2013-03-01 10:41:02 +0100283 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100284}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100285
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000287 * Print 64bit argument at position arg_no and
288 * return the index of the next argument.
289 */
290int
291printllval(struct tcb *tcp, const char *format, int arg_no)
292{
293 unsigned long long val = 0;
294
295 arg_no = getllval(tcp, &val, arg_no);
296 tprintf(format, val);
297 return arg_no;
298}
299
300/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301 * Interpret `xlat' as an array of flags
302 * print the entries whose bits are on in `flags'
303 * return # of flags printed.
304 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200305void
Dmitry V. Levinc9146eb2016-04-28 18:19:27 +0000306addflags(const struct xlat *xlat, uint64_t flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200308 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 if (xlat->val && (flags & xlat->val) == xlat->val) {
310 tprintf("|%s", xlat->str);
311 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312 }
313 }
314 if (flags) {
Dmitry V. Levinc9146eb2016-04-28 18:19:27 +0000315 tprintf("|%#" PRIx64, flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317}
318
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000319/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200320 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000321 * Print to static string the entries whose bits are on in `flags'
322 * Return static string.
323 */
324const char *
Dmitry V. Levin48110232016-05-15 14:26:03 +0000325sprintflags(const char *prefix, const struct xlat *xlat, uint64_t flags)
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000326{
327 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200328 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000329 int found = 0;
330
Denys Vlasenko52845572011-08-31 12:07:38 +0200331 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000332
Dmitry V. Levin71af1152015-11-15 20:44:13 +0000333 if (flags == 0 && xlat->val == 0 && xlat->str) {
334 strcpy(outptr, xlat->str);
335 return outstr;
336 }
337
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000338 for (; xlat->str; xlat++) {
Dmitry V. Levin71af1152015-11-15 20:44:13 +0000339 if (xlat->val && (flags & xlat->val) == xlat->val) {
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000340 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200341 *outptr++ = '|';
342 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000343 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100344 flags &= ~xlat->val;
345 if (!flags)
346 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000347 }
348 }
349 if (flags) {
350 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200351 *outptr++ = '|';
Dmitry V. Levin01c910c2016-04-28 18:49:36 +0000352 outptr += sprintf(outptr, "%#" PRIx64, flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000353 }
354
355 return outstr;
356}
357
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000358int
Dmitry V. Levin00beed62016-04-28 18:55:18 +0000359printflags64(const struct xlat *xlat, uint64_t flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000360{
361 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000362 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000363
Mike Frysinger79bddff2015-10-31 00:47:59 -0400364 if (flags == 0 && xlat->val == 0 && xlat->str) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200365 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000366 return 1;
367 }
368
369 sep = "";
370 for (n = 0; xlat->str; xlat++) {
371 if (xlat->val && (flags & xlat->val) == xlat->val) {
372 tprintf("%s%s", sep, xlat->str);
373 flags &= ~xlat->val;
374 sep = "|";
375 n++;
376 }
377 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000378
379 if (n) {
380 if (flags) {
Dmitry V. Levin00beed62016-04-28 18:55:18 +0000381 tprintf("%s%#" PRIx64, sep, flags);
Roland McGrathb2dee132005-06-01 19:02:36 +0000382 n++;
383 }
384 } else {
385 if (flags) {
Dmitry V. Levin00beed62016-04-28 18:55:18 +0000386 tprintf("%#" PRIx64, flags);
Roland McGrathb2dee132005-06-01 19:02:36 +0000387 if (dflt)
388 tprintf(" /* %s */", dflt);
389 } else {
390 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200391 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000392 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000394
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000395 return n;
396}
397
398void
Dmitry V. Levin332a3262015-07-05 22:09:29 +0000399printaddr(const long addr)
400{
401 if (!addr)
402 tprints("NULL");
403 else
404 tprintf("%#lx", addr);
405}
406
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000407#define DEF_PRINTNUM(name, type) \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000408bool \
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000409printnum_ ## name(struct tcb *tcp, const long addr, const char *fmt) \
410{ \
411 type num; \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000412 if (umove_or_printaddr(tcp, addr, &num)) \
413 return false; \
414 tprints("["); \
415 tprintf(fmt, num); \
416 tprints("]"); \
417 return true; \
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000418}
419
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000420#define DEF_PRINTPAIR(name, type) \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000421bool \
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000422printpair_ ## name(struct tcb *tcp, const long addr, const char *fmt) \
423{ \
424 type pair[2]; \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000425 if (umove_or_printaddr(tcp, addr, &pair)) \
426 return false; \
427 tprints("["); \
428 tprintf(fmt, pair[0]); \
429 tprints(", "); \
430 tprintf(fmt, pair[1]); \
431 tprints("]"); \
432 return true; \
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000433}
434
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000435DEF_PRINTNUM(int, int)
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000436DEF_PRINTPAIR(int, int)
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000437DEF_PRINTNUM(short, short)
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000438DEF_PRINTNUM(int64, uint64_t)
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000439DEF_PRINTPAIR(int64, uint64_t)
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000440
441#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000442bool
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000443printnum_long_int(struct tcb *tcp, const long addr,
444 const char *fmt_long, const char *fmt_int)
445{
446 if (current_wordsize > sizeof(int)) {
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000447 return printnum_int64(tcp, addr, fmt_long);
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000448 } else {
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000449 return printnum_int(tcp, addr, fmt_int);
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000450 }
451}
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000452#endif
Roland McGrath9814a942005-07-04 23:28:10 +0000453
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000454const char *
455sprinttime(time_t t)
456{
457 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000458 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000459
460 if (t == 0) {
461 strcpy(buf, "0");
462 return buf;
463 }
464 tmp = localtime(&t);
465 if (tmp)
466 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
467 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
468 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
469 else
470 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
471
472 return buf;
473}
474
Fabien Siron2850f742016-07-06 15:49:22 +0000475enum sock_proto
Fabien Siron802cc282016-06-17 16:29:53 +0000476getfdproto(struct tcb *tcp, int fd)
Masatake YAMATOf5480672014-11-22 19:03:33 +0900477{
Dmitry V. Levind93c4e82015-06-17 20:09:13 +0000478#ifdef HAVE_SYS_XATTR_H
Fabien Siron802cc282016-06-17 16:29:53 +0000479 size_t bufsize = 256;
480 char buf[bufsize];
Masatake YAMATOf5480672014-11-22 19:03:33 +0900481 ssize_t r;
482 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
483
484 if (fd < 0)
Fabien Siron802cc282016-06-17 16:29:53 +0000485 return SOCK_PROTO_UNKNOWN;
Masatake YAMATOf5480672014-11-22 19:03:33 +0900486
487 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
488 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
489 if (r <= 0)
Fabien Siron802cc282016-06-17 16:29:53 +0000490 return SOCK_PROTO_UNKNOWN;
Masatake YAMATOf5480672014-11-22 19:03:33 +0900491 else {
492 /*
493 * This is a protection for the case when the kernel
494 * side does not append a null byte to the buffer.
495 */
496 buf[r] = '\0';
Fabien Siron802cc282016-06-17 16:29:53 +0000497
498 return get_proto_by_name(buf);
Masatake YAMATOf5480672014-11-22 19:03:33 +0900499 }
500#else
Fabien Siron802cc282016-06-17 16:29:53 +0000501 return SOCK_PROTO_UNKNOWN;
Masatake YAMATOf5480672014-11-22 19:03:33 +0900502#endif
503}
504
Roland McGrath9814a942005-07-04 23:28:10 +0000505void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300506printfd(struct tcb *tcp, int fd)
507{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100508 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000509 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
510 static const char socket_prefix[] = "socket:[";
511 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000512 const size_t path_len = strlen(path);
Grant Edwards8a082772011-04-07 20:25:40 +0000513
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000514 tprintf("%d<", fd);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000515 if (show_fd_path > 1 &&
516 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000517 path[path_len - 1] == ']') {
Dmitry V. Levin3c17d1b2016-02-01 23:14:59 +0000518 unsigned long inode =
Dmitry V. Levinea8b8e32016-01-23 16:35:02 +0000519 strtoul(path + socket_prefix_len, NULL, 10);
Dmitry V. Levin3c17d1b2016-02-01 23:14:59 +0000520
521 if (!print_sockaddr_by_inode_cached(inode)) {
Fabien Siron802cc282016-06-17 16:29:53 +0000522 const enum sock_proto proto =
523 getfdproto(tcp, fd);
Dmitry V. Levin3c17d1b2016-02-01 23:14:59 +0000524 if (!print_sockaddr_by_inode(inode, proto))
525 tprints(path);
526 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000527 } else {
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000528 print_quoted_string(path, path_len,
529 QUOTE_OMIT_LEADING_TRAILING_QUOTES);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000530 }
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000531 tprints(">");
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000532 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000533 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300534}
535
Dmitry V. Levina501f142008-11-10 23:19:13 +0000536/*
537 * Quote string `instr' of length `size'
538 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100539 *
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000540 * If QUOTE_0_TERMINATED `style' flag is set,
541 * treat `instr' as a NUL-terminated string,
542 * checking up to (`size' + 1) bytes of `instr'.
543 *
544 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
545 * do not add leading and trailing quoting symbols.
546 *
547 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
548 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000549 */
Dmitry V. Levin3c17d1b2016-02-01 23:14:59 +0000550int
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000551string_quote(const char *instr, char *outstr, const unsigned int size,
552 const unsigned int style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000554 const unsigned char *ustr = (const unsigned char *) instr;
555 char *s = outstr;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000556 unsigned int i;
557 int usehex, c, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000559 if (style & QUOTE_0_TERMINATED)
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200560 eol = '\0';
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000561 else
562 eol = 0x100; /* this can never match a char */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200563
564 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 if (xflag > 1)
566 usehex = 1;
567 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000568 /* Check for presence of symbol which require
569 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000570 for (i = 0; i < size; ++i) {
571 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000572 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200573 if (c == eol)
574 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100575
576 /* Force hex unless c is printable or whitespace */
577 if (c > 0x7e) {
578 usehex = 1;
579 break;
580 }
581 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
582 * They happen to have ASCII codes 9,10,11,12,13.
583 */
584 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000585 usehex = 1;
586 break;
587 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 }
589 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000590
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000591 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
592 *s++ = '\"';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000593
594 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000595 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000596 for (i = 0; i < size; ++i) {
597 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000598 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200599 if (c == eol)
600 goto asciz_ended;
601 *s++ = '\\';
602 *s++ = 'x';
603 *s++ = "0123456789abcdef"[c >> 4];
604 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000605 }
606 } else {
607 for (i = 0; i < size; ++i) {
608 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000609 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200610 if (c == eol)
611 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000612 switch (c) {
613 case '\"': case '\\':
614 *s++ = '\\';
615 *s++ = c;
616 break;
617 case '\f':
618 *s++ = '\\';
619 *s++ = 'f';
620 break;
621 case '\n':
622 *s++ = '\\';
623 *s++ = 'n';
624 break;
625 case '\r':
626 *s++ = '\\';
627 *s++ = 'r';
628 break;
629 case '\t':
630 *s++ = '\\';
631 *s++ = 't';
632 break;
633 case '\v':
634 *s++ = '\\';
635 *s++ = 'v';
636 break;
637 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100638 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000639 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200640 else {
641 /* Print \octal */
642 *s++ = '\\';
643 if (i + 1 < size
644 && ustr[i + 1] >= '0'
645 && ustr[i + 1] <= '9'
646 ) {
647 /* Print \ooo */
648 *s++ = '0' + (c >> 6);
649 *s++ = '0' + ((c >> 3) & 0x7);
650 } else {
651 /* Print \[[o]o]o */
652 if ((c >> 3) != 0) {
653 if ((c >> 6) != 0)
654 *s++ = '0' + (c >> 6);
655 *s++ = '0' + ((c >> 3) & 0x7);
656 }
657 }
658 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000659 }
660 break;
661 }
662 }
663 }
664
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000665 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
666 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000668
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200669 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000670 if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200671 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
672 * but next char is NUL.
673 */
674 return 0;
675 }
676
677 return 1;
678
679 asciz_ended:
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000680 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
681 *s++ = '\"';
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200682 *s = '\0';
683 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
684 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685}
686
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000687#ifndef ALLOCA_CUTOFF
688# define ALLOCA_CUTOFF 4032
689#endif
690#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
691
692/*
693 * Quote string `str' of length `size' and print the result.
694 *
695 * If QUOTE_0_TERMINATED `style' flag is set,
696 * treat `str' as a NUL-terminated string and
697 * quote at most (`size' - 1) bytes.
698 *
699 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
700 * do not add leading and trailing quoting symbols.
701 *
702 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
703 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
704 */
705int
706print_quoted_string(const char *str, unsigned int size,
707 const unsigned int style)
708{
709 char *buf;
710 char *outstr;
711 unsigned int alloc_size;
712 int rc;
713
714 if (size && style & QUOTE_0_TERMINATED)
715 --size;
716
717 alloc_size = 4 * size;
718 if (alloc_size / 4 != size) {
719 error_msg("Out of memory");
720 tprints("???");
721 return -1;
722 }
723 alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
724
725 if (use_alloca(alloc_size)) {
726 outstr = alloca(alloc_size);
727 buf = NULL;
728 } else {
729 outstr = buf = malloc(alloc_size);
730 if (!buf) {
731 error_msg("Out of memory");
732 tprints("???");
733 return -1;
734 }
735 }
736
737 rc = string_quote(str, outstr, size, style);
738 tprints(outstr);
739
740 free(buf);
741 return rc;
742}
743
Dmitry V. Levina501f142008-11-10 23:19:13 +0000744/*
745 * Print path string specified by address `addr' and length `n'.
746 * If path length exceeds `n', append `...' to the output.
747 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000748void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000749printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000751 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100752 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100753
Dmitry V. Levina501f142008-11-10 23:19:13 +0000754 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200755 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000756 return;
757 }
758
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100759 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000760 if (n > sizeof path - 1)
761 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000762
763 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100764 nul_seen = umovestr(tcp, addr, n + 1, path);
765 if (nul_seen < 0)
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000766 printaddr(addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 else {
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000768 path[n++] = '\0';
769 print_quoted_string(path, n, QUOTE_0_TERMINATED);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100770 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100771 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772 }
773}
774
775void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000776printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100778 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000779 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000780}
781
Dmitry V. Levina501f142008-11-10 23:19:13 +0000782/*
783 * Print string specified by address `addr' and length `len'.
784 * If `len' < 0, treat the string as a NUL-terminated string.
785 * If string length exceeds `max_strlen', append `...' to the output.
786 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000787void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200788printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000789{
790 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000792 unsigned int size;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000793 unsigned int style;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100794 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000795
796 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200797 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000798 return;
799 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000800 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200801 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000802 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
803
804 if (outstr_size / 4 != max_strlen)
805 die_out_of_memory();
Dmitry V. Levin3e9d71f2015-05-25 20:41:02 +0000806 str = xmalloc(max_strlen + 1);
807 outstr = xmalloc(outstr_size);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000809
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000810 size = max_strlen;
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200811 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000812 /*
813 * Treat as a NUL-terminated string: fetch one byte more
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000814 * because string_quote may look one byte ahead.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000815 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000816 if (umovestr(tcp, addr, size + 1, str) < 0) {
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000817 printaddr(addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000818 return;
819 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000820 style = QUOTE_0_TERMINATED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 }
822 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200823 if (size > (unsigned long)len)
824 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000825 if (umoven(tcp, addr, size, str) < 0) {
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000826 printaddr(addr);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000827 return;
828 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000829 style = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830 }
831
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100832 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
833 * or we were requested to print more than -s NUM chars)...
834 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000835 ellipsis = (string_quote(str, outstr, size, style) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000836 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000837
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100838 tprints(outstr);
839 if (ellipsis)
840 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000841}
842
John Hughes1d08dcf2001-07-10 13:48:44 +0000843void
Dmitry V. Levin05a0af62016-01-20 00:17:02 +0000844dumpiov_upto(struct tcb *tcp, int len, long addr, unsigned long data_size)
John Hughes1d08dcf2001-07-10 13:48:44 +0000845{
Denys Vlasenko84703742012-02-25 02:38:52 +0100846#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000847 union {
Dmitry V. Levin08941942016-01-16 22:50:09 +0000848 struct { uint32_t base; uint32_t len; } *iov32;
849 struct { uint64_t base; uint64_t len; } *iov64;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000850 } iovu;
851#define iov iovu.iov64
852#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100853 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000854#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100855 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000856#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100857 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000858#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000859 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000860#define sizeof_iov sizeof(*iov)
861#define iov_iov_base(i) iov[i].iov_base
862#define iov_iov_len(i) iov[i].iov_len
863#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000864 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200865 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000866
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200867 size = sizeof_iov * len;
868 /* Assuming no sane program has millions of iovs */
869 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000870 || (iov = malloc(size)) == NULL) {
Dmitry V. Levindf389912015-05-25 23:33:31 +0300871 error_msg("Out of memory");
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200872 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000873 }
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100874 if (umoven(tcp, addr, size, iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000875 for (i = 0; i < len; i++) {
Dmitry V. Levin05a0af62016-01-20 00:17:02 +0000876 unsigned long iov_len = iov_iov_len(i);
877 if (iov_len > data_size)
878 iov_len = data_size;
879 if (!iov_len)
880 break;
881 data_size -= iov_len;
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000882 /* include the buffer number to make it easy to
883 * match up the trace with the source */
Dmitry V. Levin05a0af62016-01-20 00:17:02 +0000884 tprintf(" * %lu bytes in buffer %d\n", iov_len, i);
885 dumpstr(tcp, (long) iov_iov_base(i), iov_len);
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000886 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000887 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200888 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000889#undef sizeof_iov
890#undef iov_iov_base
891#undef iov_iov_len
892#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000893}
John Hughes1d08dcf2001-07-10 13:48:44 +0000894
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000895void
Denys Vlasenko12014262011-05-30 14:00:14 +0200896dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000897{
898 static int strsize = -1;
899 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000900
Denys Vlasenko76325802013-02-22 14:47:39 +0100901 char outbuf[
902 (
903 (sizeof(
904 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
905 "1234567890123456") + /*in case I'm off by few:*/ 4)
906 /*align to 8 to make memset easier:*/ + 7) & -8
907 ];
908 const unsigned char *src;
909 int i;
910
911 memset(outbuf, ' ', sizeof(outbuf));
912
913 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200914 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100915 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200916 if (!str) {
917 strsize = -1;
Dmitry V. Levindf389912015-05-25 23:33:31 +0300918 error_msg("Out of memory");
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200919 return;
920 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100921 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 }
923
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100924 if (umoven(tcp, addr, len, str) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925 return;
926
Denys Vlasenko76325802013-02-22 14:47:39 +0100927 /* Space-pad to 16 bytes */
928 i = len;
929 while (i & 0xf)
930 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200931
Denys Vlasenko76325802013-02-22 14:47:39 +0100932 i = 0;
933 src = str;
934 while (i < len) {
935 char *dst = outbuf;
936 /* Hex dump */
937 do {
938 if (i < len) {
939 *dst++ = "0123456789abcdef"[*src >> 4];
940 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 }
942 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100943 *dst++ = ' ';
944 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000945 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100946 dst++; /* space is there by memset */
947 i++;
948 if ((i & 7) == 0)
949 dst++; /* space is there by memset */
950 src++;
951 } while (i & 0xf);
952 /* ASCII dump */
953 i -= 16;
954 src -= 16;
955 do {
956 if (*src >= ' ' && *src < 0x7f)
957 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100959 *dst++ = '.';
960 src++;
961 } while (++i & 0xf);
962 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100963 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964 }
965}
966
Mike Frysinger612659e2012-02-14 14:38:28 +0100967#ifdef HAVE_PROCESS_VM_READV
968/* C library supports this, but the kernel might not. */
969static bool process_vm_readv_not_supported = 0;
970#else
971
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100972/* Need to do this since process_vm_readv() is not yet available in libc.
973 * When libc is be updated, only "static bool process_vm_readv_not_supported"
974 * line should remain.
975 */
976#if !defined(__NR_process_vm_readv)
977# if defined(I386)
978# define __NR_process_vm_readv 347
979# elif defined(X86_64)
980# define __NR_process_vm_readv 310
981# elif defined(POWERPC)
982# define __NR_process_vm_readv 351
983# endif
984#endif
985
986#if defined(__NR_process_vm_readv)
987static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400988/* Have to avoid duplicating with the C library headers. */
989static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100990 const struct iovec *lvec,
991 unsigned long liovcnt,
992 const struct iovec *rvec,
993 unsigned long riovcnt,
994 unsigned long flags)
995{
996 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
997}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400998#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100999#else
1000static bool process_vm_readv_not_supported = 1;
1001# define process_vm_readv(...) (errno = ENOSYS, -1)
1002#endif
Mike Frysinger612659e2012-02-14 14:38:28 +01001003
1004#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001005
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001006static ssize_t
1007vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
1008{
1009 const struct iovec local = {
1010 .iov_base = laddr,
1011 .iov_len = len
1012 };
1013 const struct iovec remote = {
1014 .iov_base = (void *) raddr,
1015 .iov_len = len
1016 };
1017
1018 return process_vm_readv(pid, &local, 1, &remote, 1, 0);
1019}
1020
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021/*
1022 * move `len' bytes of data from process `pid'
Denys Vlasenko7e69ed92015-03-21 19:50:53 +01001023 * at address `addr' to our space at `our_addr'
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 */
1025int
Denys Vlasenko7e69ed92015-03-21 19:50:53 +01001026umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027{
Denys Vlasenko7e69ed92015-03-21 19:50:53 +01001028 char *laddr = our_addr;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001029 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001030 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 union {
1032 long val;
1033 char x[sizeof(long)];
1034 } u;
1035
Denys Vlasenko2544f982013-02-19 17:39:56 +01001036#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001037 if (current_wordsize < sizeof(addr))
1038 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +01001039#endif
1040
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001041 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001042 int r = vm_read_mem(pid, laddr, addr, len);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001043 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +01001044 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001045 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001046 error_msg("umoven: short read (%u < %u) @0x%lx",
1047 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001048 return -1;
1049 }
1050 switch (errno) {
1051 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001052 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001053 break;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001054 case EPERM:
1055 /* operation not permitted, try PTRACE_PEEKDATA */
1056 break;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001057 case ESRCH:
1058 /* the process is gone */
1059 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001060 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001061 /* address space is inaccessible */
1062 return -1;
1063 default:
1064 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001065 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +00001066 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001067 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001068 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001069
Dmitry V. Levin97005922013-02-26 21:16:22 +00001070 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 if (addr & (sizeof(long) - 1)) {
1072 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001073 n = addr & (sizeof(long) - 1); /* residue */
1074 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001075 errno = 0;
1076 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001077 switch (errno) {
1078 case 0:
1079 break;
1080 case ESRCH: case EINVAL:
1081 /* these could be seen if the process is gone */
1082 return -1;
1083 case EFAULT: case EIO: case EPERM:
1084 /* address space is inaccessible */
1085 return -1;
1086 default:
1087 /* all the rest is strange and should be reported */
1088 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1089 pid, addr);
1090 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001091 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001092 m = MIN(sizeof(long) - n, len);
1093 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001094 addr += sizeof(long);
1095 laddr += m;
1096 nread += m;
1097 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 }
1099 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001100 errno = 0;
1101 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001102 switch (errno) {
1103 case 0:
1104 break;
1105 case ESRCH: case EINVAL:
1106 /* these could be seen if the process is gone */
1107 return -1;
1108 case EFAULT: case EIO: case EPERM:
1109 /* address space is inaccessible */
1110 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001111 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001112 nread, nread + len, addr - nread);
1113 }
1114 return -1;
1115 default:
1116 /* all the rest is strange and should be reported */
1117 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1118 pid, addr);
1119 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001120 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001121 m = MIN(sizeof(long), len);
1122 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001123 addr += sizeof(long);
1124 laddr += m;
1125 nread += m;
1126 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 return 0;
1130}
1131
Dmitry V. Levin332a3262015-07-05 22:09:29 +00001132int
1133umoven_or_printaddr(struct tcb *tcp, const long addr, const unsigned int len,
1134 void *our_addr)
1135{
Dmitry V. Levin484326d2016-06-11 01:28:21 +00001136 if (!addr || !verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
Dmitry V. Levin332a3262015-07-05 22:09:29 +00001137 umoven(tcp, addr, len, our_addr) < 0) {
Dmitry V. Levin484326d2016-06-11 01:28:21 +00001138 printaddr(addr);
Dmitry V. Levin332a3262015-07-05 22:09:29 +00001139 return -1;
1140 }
1141 return 0;
1142}
1143
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001145 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001147 *
1148 * Returns < 0 on error, > 0 if NUL was seen,
1149 * (TODO if useful: return count of bytes including NUL),
1150 * else 0 if len bytes were read but no NUL byte seen.
1151 *
1152 * Note: there is no guarantee we won't overwrite some bytes
1153 * in laddr[] _after_ terminating NUL (but, of course,
1154 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 */
1156int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001157umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158{
Denys Vlasenko16940922013-03-01 18:52:59 +01001159#if SIZEOF_LONG == 4
1160 const unsigned long x01010101 = 0x01010101ul;
1161 const unsigned long x80808080 = 0x80808080ul;
1162#elif SIZEOF_LONG == 8
1163 const unsigned long x01010101 = 0x0101010101010101ul;
1164 const unsigned long x80808080 = 0x8080808080808080ul;
1165#else
1166# error SIZEOF_LONG > 8
1167#endif
1168
Roland McGratheb9e2e82009-06-02 16:49:22 -07001169 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001170 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001172 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 char x[sizeof(long)];
1174 } u;
1175
Denys Vlasenko2544f982013-02-19 17:39:56 +01001176#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001177 if (current_wordsize < sizeof(addr))
1178 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001179#endif
1180
Dmitry V. Levin97005922013-02-26 21:16:22 +00001181 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001182 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001183 const size_t page_size = get_pagesize();
1184 const size_t page_mask = page_size - 1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001185
1186 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001187 unsigned int chunk_len;
1188 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001189
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001190 /*
1191 * Don't cross pages, otherwise we can get EFAULT
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001192 * and fail to notice that terminating NUL lies
1193 * in the existing (first) page.
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001194 */
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001195 chunk_len = len > page_size ? page_size : len;
1196 end_in_page = (addr + chunk_len) & page_mask;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001197 if (chunk_len > end_in_page) /* crosses to the next page */
1198 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001199
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001200 int r = vm_read_mem(pid, laddr, addr, chunk_len);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001201 if (r > 0) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001202 if (memchr(laddr, '\0', r))
Dmitry V. Levin97005922013-02-26 21:16:22 +00001203 return 1;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001204 addr += r;
1205 laddr += r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001206 nread += r;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001207 len -= r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001208 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001209 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001210 switch (errno) {
1211 case ENOSYS:
1212 process_vm_readv_not_supported = 1;
1213 goto vm_readv_didnt_work;
1214 case ESRCH:
1215 /* the process is gone */
1216 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001217 case EPERM:
1218 /* operation not permitted, try PTRACE_PEEKDATA */
1219 if (!nread)
1220 goto vm_readv_didnt_work;
1221 /* fall through */
1222 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001223 /* address space is inaccessible */
1224 if (nread) {
1225 perror_msg("umovestr: short read (%d < %d) @0x%lx",
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001226 nread, nread + len, addr - nread);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001227 }
1228 return -1;
1229 default:
1230 /* all the rest is strange and should be reported */
1231 perror_msg("process_vm_readv");
1232 return -1;
1233 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001234 }
1235 return 0;
1236 }
1237 vm_readv_didnt_work:
1238
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 if (addr & (sizeof(long) - 1)) {
1240 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001241 n = addr & (sizeof(long) - 1); /* residue */
1242 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001243 errno = 0;
1244 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001245 switch (errno) {
1246 case 0:
1247 break;
1248 case ESRCH: case EINVAL:
1249 /* these could be seen if the process is gone */
1250 return -1;
1251 case EFAULT: case EIO: case EPERM:
1252 /* address space is inaccessible */
1253 return -1;
1254 default:
1255 /* all the rest is strange and should be reported */
1256 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1257 pid, addr);
1258 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001259 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001260 m = MIN(sizeof(long) - n, len);
1261 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 while (n & (sizeof(long) - 1))
1263 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001264 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001265 addr += sizeof(long);
1266 laddr += m;
1267 nread += m;
1268 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001270
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001272 errno = 0;
1273 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001274 switch (errno) {
1275 case 0:
1276 break;
1277 case ESRCH: case EINVAL:
1278 /* these could be seen if the process is gone */
1279 return -1;
1280 case EFAULT: case EIO: case EPERM:
1281 /* address space is inaccessible */
1282 if (nread) {
1283 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1284 nread, nread + len, addr - nread);
1285 }
1286 return -1;
1287 default:
1288 /* all the rest is strange and should be reported */
1289 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1290 pid, addr);
1291 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001292 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001293 m = MIN(sizeof(long), len);
1294 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001295 /* "If a NUL char exists in this word" */
1296 if ((u.val - x01010101) & ~u.val & x80808080)
1297 return 1;
1298 addr += sizeof(long);
1299 laddr += m;
1300 nread += m;
1301 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001303 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304}
Dmitry V. Levin72e4f7a2016-05-06 23:26:43 +00001305
1306/*
1307 * Iteratively fetch and print up to nmemb elements of elem_size size
1308 * from the array that starts at tracee's address start_addr.
1309 *
1310 * Array elements are being fetched to the address specified by elem_buf.
1311 *
1312 * The fetcher callback function specified by umoven_func should follow
1313 * the same semantics as umoven_or_printaddr function.
1314 *
1315 * The printer callback function specified by print_func is expected
1316 * to print something; if it returns false, no more iterations will be made.
1317 *
1318 * The pointer specified by opaque_data is passed to each invocation
1319 * of print_func callback function.
1320 *
1321 * This function prints:
1322 * - "NULL", if start_addr is NULL;
1323 * - "[]", if nmemb is 0;
1324 * - start_addr, if nmemb * elem_size overflows or wraps around;
1325 * - nothing, if the first element cannot be fetched
1326 * (if umoven_func returns non-zero), but it is assumed that
1327 * umoven_func has printed the address it failed to fetch data from;
1328 * - elements of the array, delimited by ", ", with the array itself
1329 * enclosed with [] brackets.
1330 *
1331 * If abbrev(tcp) is true, then
1332 * - the maximum number of elements printed equals to max_strlen;
1333 * - "..." is printed instead of max_strlen+1 element
1334 * and no more iterations will be made.
1335 *
1336 * This function returns true only if
1337 * - umoven_func has been called at least once AND
1338 * - umoven_func has not returned false.
1339 */
1340bool
1341print_array(struct tcb *tcp,
1342 const unsigned long start_addr,
1343 const size_t nmemb,
1344 void *const elem_buf,
1345 const size_t elem_size,
1346 int (*const umoven_func)(struct tcb *,
1347 long,
1348 unsigned int,
1349 void *),
1350 bool (*const print_func)(struct tcb *,
1351 void *elem_buf,
1352 size_t elem_size,
1353 void *opaque_data),
1354 void *const opaque_data)
1355{
1356 if (!start_addr) {
1357 tprints("NULL");
1358 return false;
1359 }
1360
1361 if (!nmemb) {
1362 tprints("[]");
1363 return false;
1364 }
1365
1366 const size_t size = nmemb * elem_size;
1367 const unsigned long end_addr = start_addr + size;
1368
1369 if (end_addr <= start_addr || size / elem_size != nmemb) {
1370 printaddr(start_addr);
1371 return false;
1372 }
1373
1374 const unsigned long abbrev_end =
1375 (abbrev(tcp) && max_strlen < nmemb) ?
1376 start_addr + elem_size * max_strlen : end_addr;
1377 unsigned long cur;
1378
1379 for (cur = start_addr; cur < end_addr; cur += elem_size) {
1380 if (cur != start_addr)
1381 tprints(", ");
1382
1383 if (umoven_func(tcp, cur, elem_size, elem_buf))
1384 break;
1385
1386 if (cur == start_addr)
1387 tprints("[");
1388
1389 if (cur >= abbrev_end) {
1390 tprints("...");
1391 cur = end_addr;
1392 break;
1393 }
1394
1395 if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
1396 cur = end_addr;
1397 break;
1398 }
1399 }
1400 if (cur != start_addr)
1401 tprints("]");
1402
1403 return cur >= end_addr;
1404}
Elvira Khabirova3c1105d2016-06-12 16:39:02 +03001405
1406int
1407printargs(struct tcb *tcp)
1408{
1409 if (entering(tcp)) {
1410 int i;
1411 int n = tcp->s_ent->nargs;
1412 for (i = 0; i < n; i++)
1413 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
1414 }
1415 return 0;
1416}
1417
1418int
1419printargs_u(struct tcb *tcp)
1420{
1421 const int n = tcp->s_ent->nargs;
1422 int i;
1423 for (i = 0; i < n; ++i)
1424 tprintf("%s%u", i ? ", " : "",
1425 (unsigned int) tcp->u_arg[i]);
1426 return RVAL_DECODED;
1427}
1428
1429int
1430printargs_d(struct tcb *tcp)
1431{
1432 const int n = tcp->s_ent->nargs;
1433 int i;
1434 for (i = 0; i < n; ++i)
1435 tprintf("%s%d", i ? ", " : "",
1436 (int) tcp->u_arg[i]);
1437 return RVAL_DECODED;
1438}
Dmitry V. Levinbf2698a2016-07-03 22:15:45 +00001439
1440#if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
1441# define open_file open64
1442#else
1443# define open_file open
1444#endif
1445
1446int
1447read_int_from_file(const char *const fname, int *const pvalue)
1448{
1449 const int fd = open_file(fname, O_RDONLY);
1450 if (fd < 0)
1451 return -1;
1452
1453 long lval;
1454 char buf[sizeof(lval) * 3];
1455 int n = read(fd, buf, sizeof(buf) - 1);
1456 int saved_errno = errno;
1457 close(fd);
1458
1459 if (n < 0) {
1460 errno = saved_errno;
1461 return -1;
1462 }
1463
1464 buf[n] = '\0';
1465 char *endptr = 0;
1466 errno = 0;
1467 lval = strtol(buf, &endptr, 10);
1468 if (!endptr || (*endptr && '\n' != *endptr)
1469#if INT_MAX < LONG_MAX
1470 || lval > INT_MAX || lval < INT_MIN
1471#endif
1472 || ERANGE == errno) {
1473 if (!errno)
1474 errno = EINVAL;
1475 return -1;
1476 }
1477
1478 *pvalue = (int) lval;
1479 return 0;
1480}