blob: 6afafbbf6d74aac60c713e5f910db0797a2c81a8 [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>
Masatake YAMATOf5480672014-11-22 19:03:33 +090037#if HAVE_SYS_XATTR_H
38# include <sys/xattr.h>
39#endif
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000040#include <sys/uio.h>
Wichert Akkerman36915a11999-07-13 15:45:02 +000041
Dmitry V. Levin5503dd22015-02-13 02:12:14 +000042#include "regs.h"
Dmitry V. Levin7211dbc2015-02-28 12:20:21 +000043#include "ptrace.h"
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000044
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000045int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000046string_to_uint(const char *str)
47{
48 char *error;
49 long value;
50
51 if (!*str)
52 return -1;
53 errno = 0;
54 value = strtol(str, &error, 10);
55 if (errno || *error || value < 0 || (long)(int)value != value)
56 return -1;
57 return (int)value;
58}
59
60int
Dmitry V. Levin447db452014-05-29 17:59:01 +000061tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000062{
63 return a->tv_sec || a->tv_usec;
64}
65
66int
Dmitry V. Levin447db452014-05-29 17:59:01 +000067tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000068{
69 if (a->tv_sec < b->tv_sec
70 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
71 return -1;
72 if (a->tv_sec > b->tv_sec
73 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
74 return 1;
75 return 0;
76}
77
78double
Dmitry V. Levin447db452014-05-29 17:59:01 +000079tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080{
81 return tv->tv_sec + tv->tv_usec/1000000.0;
82}
83
84void
Dmitry V. Levin447db452014-05-29 17:59:01 +000085tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086{
87 tv->tv_sec = a->tv_sec + b->tv_sec;
88 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +000089 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090 tv->tv_sec++;
91 tv->tv_usec -= 1000000;
92 }
93}
94
95void
Dmitry V. Levin447db452014-05-29 17:59:01 +000096tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000097{
98 tv->tv_sec = a->tv_sec - b->tv_sec;
99 tv->tv_usec = a->tv_usec - b->tv_usec;
100 if (((long) tv->tv_usec) < 0) {
101 tv->tv_sec--;
102 tv->tv_usec += 1000000;
103 }
104}
105
106void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000107tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
110 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
111 tv->tv_usec %= 1000000;
112}
113
114void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000115tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116{
117 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000118 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119 tv->tv_usec %= 1000000;
120}
121
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000122const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000123xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124{
125 for (; xlat->str != NULL; xlat++)
126 if (xlat->val == val)
127 return xlat->str;
128 return NULL;
129}
130
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000131static int
132xlat_bsearch_compare(const void *a, const void *b)
133{
134 const unsigned int val1 = (const unsigned long) a;
135 const unsigned int val2 = ((const struct xlat *) b)->val;
136 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
137}
138
139const char *
140xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
141{
142 const struct xlat *e =
143 bsearch((const void*) (const unsigned long) val,
144 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
145
146 return e ? e->str : NULL;
147}
148
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200149#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200150char *
151stpcpy(char *dst, const char *src)
152{
153 while ((*dst = *src++) != '\0')
154 dst++;
155 return dst;
156}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200157#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200158
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100159/* Find a next bit which is set.
160 * Starts testing at cur_bit.
161 * Returns -1 if no more bits are set.
162 *
163 * We never touch bytes we don't need to.
164 * On big-endian, array is assumed to consist of
165 * current_wordsize wide words: for example, is current_wordsize is 4,
166 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
167 * On little-endian machines, word size is immaterial.
168 */
169int
170next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
171{
172 const unsigned endian = 1;
173 int little_endian = *(char*)&endian;
174
175 const uint8_t *array = bit_array;
176 unsigned pos = cur_bit / 8;
177 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
178
179 for (;;) {
180 uint8_t bitmask;
181 uint8_t cur_byte;
182
183 if (cur_bit >= size_bits)
184 return -1;
185 cur_byte = array[pos ^ pos_xor_mask];
186 if (cur_byte == 0) {
187 cur_bit = (cur_bit + 8) & (-8);
188 pos++;
189 continue;
190 }
191 bitmask = 1 << (cur_bit & 7);
192 for (;;) {
193 if (cur_byte & bitmask)
194 return cur_bit;
195 cur_bit++;
196 if (cur_bit >= size_bits)
197 return -1;
198 bitmask <<= 1;
199 /* This check *can't be* optimized out: */
200 if (bitmask == 0)
201 break;
202 }
203 pos++;
204 }
205}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206/*
207 * Print entry in struct xlat table, if there.
208 */
209void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000210printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000212 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213
214 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200215 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000216 else
217 tprintf("%#x /* %s */", val, dflt);
218}
219
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100220/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000221 * Fetch 64bit argument at position arg_no and
222 * return the index of the next argument.
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100223 */
224int
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000225getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100226{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000227#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
228# if SUPPORTED_PERSONALITIES > 1
229 if (current_wordsize > 4) {
230# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000231 *val = tcp->u_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100232 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000233# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100234 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000235# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000236 /* Align arg_no to the next even number. */
237 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000238# endif /* AARCH64 || POWERPC64 */
239 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100240 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100241 }
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000242# endif /* SUPPORTED_PERSONALITIES > 1 */
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000243#elif SIZEOF_LONG > 4
244# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
245#elif defined LINUX_MIPSN32
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000246 *val = tcp->ext_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100247 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000248#elif defined X32
249 if (current_personality == 0) {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000250 *val = tcp->ext_arg[arg_no];
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000251 arg_no++;
252 } else {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000253 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000254 arg_no += 2;
255 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100256#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000257# if defined __ARM_EABI__ || \
258 defined LINUX_MIPSO32 || \
259 defined POWERPC || \
260 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000261 /* Align arg_no to the next even number. */
262 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000263# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000264 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100265 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100266#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000267
Chris Metcalf879dddd2013-03-01 10:41:02 +0100268 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100269}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100270
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000272 * Print 64bit argument at position arg_no and
273 * return the index of the next argument.
274 */
275int
276printllval(struct tcb *tcp, const char *format, int arg_no)
277{
278 unsigned long long val = 0;
279
280 arg_no = getllval(tcp, &val, arg_no);
281 tprintf(format, val);
282 return arg_no;
283}
284
285/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286 * Interpret `xlat' as an array of flags
287 * print the entries whose bits are on in `flags'
288 * return # of flags printed.
289 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200290void
Denys Vlasenko12014262011-05-30 14:00:14 +0200291addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000292{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200293 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294 if (xlat->val && (flags & xlat->val) == xlat->val) {
295 tprintf("|%s", xlat->str);
296 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297 }
298 }
299 if (flags) {
300 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302}
303
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000304/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200305 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000306 * Print to static string the entries whose bits are on in `flags'
307 * Return static string.
308 */
309const char *
310sprintflags(const char *prefix, const struct xlat *xlat, int flags)
311{
312 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200313 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000314 int found = 0;
315
Denys Vlasenko52845572011-08-31 12:07:38 +0200316 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000317
318 for (; xlat->str; xlat++) {
319 if ((flags & xlat->val) == xlat->val) {
320 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200321 *outptr++ = '|';
322 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000323 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100324 flags &= ~xlat->val;
325 if (!flags)
326 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000327 }
328 }
329 if (flags) {
330 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200331 *outptr++ = '|';
332 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000333 }
334
335 return outstr;
336}
337
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000339printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000340{
341 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000342 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000343
344 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200345 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346 return 1;
347 }
348
349 sep = "";
350 for (n = 0; xlat->str; xlat++) {
351 if (xlat->val && (flags & xlat->val) == xlat->val) {
352 tprintf("%s%s", sep, xlat->str);
353 flags &= ~xlat->val;
354 sep = "|";
355 n++;
356 }
357 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000358
359 if (n) {
360 if (flags) {
361 tprintf("%s%#x", sep, flags);
362 n++;
363 }
364 } else {
365 if (flags) {
366 tprintf("%#x", flags);
367 if (dflt)
368 tprintf(" /* %s */", dflt);
369 } else {
370 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200371 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000372 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000373 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000374
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375 return n;
376}
377
378void
Dmitry V. Levin1c603a92015-02-17 22:03:17 +0000379printnum_long(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380{
Roland McGratheb285352003-01-14 09:59:00 +0000381 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382
383 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200384 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 return;
386 }
387 if (umove(tcp, addr, &num) < 0) {
388 tprintf("%#lx", addr);
389 return;
390 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200391 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200393 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394}
395
Roland McGrath6bc12202003-11-13 22:32:27 +0000396void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000397printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000398{
399 int num;
400
401 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200402 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000403 return;
404 }
405 if (umove(tcp, addr, &num) < 0) {
406 tprintf("%#lx", addr);
407 return;
408 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200409 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000410 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200411 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000412}
413
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000414const char *
415sprinttime(time_t t)
416{
417 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000418 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000419
420 if (t == 0) {
421 strcpy(buf, "0");
422 return buf;
423 }
424 tmp = localtime(&t);
425 if (tmp)
426 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
427 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
428 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
429 else
430 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
431
432 return buf;
433}
434
Masatake YAMATOf5480672014-11-22 19:03:33 +0900435static char *
436getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
437{
438#if HAVE_SYS_XATTR_H
439 ssize_t r;
440 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
441
442 if (fd < 0)
443 return NULL;
444
445 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
446 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
447 if (r <= 0)
448 return NULL;
449 else {
450 /*
451 * This is a protection for the case when the kernel
452 * side does not append a null byte to the buffer.
453 */
454 buf[r] = '\0';
455 return buf;
456 }
457#else
458 return NULL;
459#endif
460}
461
Roland McGrath9814a942005-07-04 23:28:10 +0000462void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300463printfd(struct tcb *tcp, int fd)
464{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100465 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000466 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
467 static const char socket_prefix[] = "socket:[";
468 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000469 const size_t path_len = strlen(path);
Grant Edwards8a082772011-04-07 20:25:40 +0000470
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000471 tprintf("%d<", fd);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000472 if (show_fd_path > 1 &&
473 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000474 path[path_len - 1] == ']') {
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000475 unsigned long inodenr;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900476#define PROTO_NAME_LEN 32
477 char proto_buf[PROTO_NAME_LEN];
478 const char *proto =
479 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000480 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900481 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900482 if (proto)
483 tprintf("%s:[%lu]", proto, inodenr);
484 else
485 tprints(path);
486 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000487 } else {
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000488 print_quoted_string(path, path_len,
489 QUOTE_OMIT_LEADING_TRAILING_QUOTES);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000490 }
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000491 tprints(">");
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000492 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000493 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300494}
495
Dmitry V. Levina501f142008-11-10 23:19:13 +0000496/*
497 * Quote string `instr' of length `size'
498 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100499 *
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000500 * If QUOTE_0_TERMINATED `style' flag is set,
501 * treat `instr' as a NUL-terminated string,
502 * checking up to (`size' + 1) bytes of `instr'.
503 *
504 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
505 * do not add leading and trailing quoting symbols.
506 *
507 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
508 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000509 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000510static int
511string_quote(const char *instr, char *outstr, const unsigned int size,
512 const unsigned int style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000513{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000514 const unsigned char *ustr = (const unsigned char *) instr;
515 char *s = outstr;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000516 unsigned int i;
517 int usehex, c, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000519 if (style & QUOTE_0_TERMINATED)
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200520 eol = '\0';
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000521 else
522 eol = 0x100; /* this can never match a char */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200523
524 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000525 if (xflag > 1)
526 usehex = 1;
527 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000528 /* Check for presence of symbol which require
529 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000530 for (i = 0; i < size; ++i) {
531 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000532 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200533 if (c == eol)
534 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100535
536 /* Force hex unless c is printable or whitespace */
537 if (c > 0x7e) {
538 usehex = 1;
539 break;
540 }
541 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
542 * They happen to have ASCII codes 9,10,11,12,13.
543 */
544 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000545 usehex = 1;
546 break;
547 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 }
549 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000551 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
552 *s++ = '\"';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000553
554 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000555 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000556 for (i = 0; i < size; ++i) {
557 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000558 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200559 if (c == eol)
560 goto asciz_ended;
561 *s++ = '\\';
562 *s++ = 'x';
563 *s++ = "0123456789abcdef"[c >> 4];
564 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 }
566 } else {
567 for (i = 0; i < size; ++i) {
568 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000569 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200570 if (c == eol)
571 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000572 switch (c) {
573 case '\"': case '\\':
574 *s++ = '\\';
575 *s++ = c;
576 break;
577 case '\f':
578 *s++ = '\\';
579 *s++ = 'f';
580 break;
581 case '\n':
582 *s++ = '\\';
583 *s++ = 'n';
584 break;
585 case '\r':
586 *s++ = '\\';
587 *s++ = 'r';
588 break;
589 case '\t':
590 *s++ = '\\';
591 *s++ = 't';
592 break;
593 case '\v':
594 *s++ = '\\';
595 *s++ = 'v';
596 break;
597 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100598 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000599 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200600 else {
601 /* Print \octal */
602 *s++ = '\\';
603 if (i + 1 < size
604 && ustr[i + 1] >= '0'
605 && ustr[i + 1] <= '9'
606 ) {
607 /* Print \ooo */
608 *s++ = '0' + (c >> 6);
609 *s++ = '0' + ((c >> 3) & 0x7);
610 } else {
611 /* Print \[[o]o]o */
612 if ((c >> 3) != 0) {
613 if ((c >> 6) != 0)
614 *s++ = '0' + (c >> 6);
615 *s++ = '0' + ((c >> 3) & 0x7);
616 }
617 }
618 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000619 }
620 break;
621 }
622 }
623 }
624
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000625 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
626 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000627 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000628
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200629 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000630 if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200631 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
632 * but next char is NUL.
633 */
634 return 0;
635 }
636
637 return 1;
638
639 asciz_ended:
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000640 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
641 *s++ = '\"';
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200642 *s = '\0';
643 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
644 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645}
646
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000647#ifndef ALLOCA_CUTOFF
648# define ALLOCA_CUTOFF 4032
649#endif
650#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
651
652/*
653 * Quote string `str' of length `size' and print the result.
654 *
655 * If QUOTE_0_TERMINATED `style' flag is set,
656 * treat `str' as a NUL-terminated string and
657 * quote at most (`size' - 1) bytes.
658 *
659 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
660 * do not add leading and trailing quoting symbols.
661 *
662 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
663 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
664 */
665int
666print_quoted_string(const char *str, unsigned int size,
667 const unsigned int style)
668{
669 char *buf;
670 char *outstr;
671 unsigned int alloc_size;
672 int rc;
673
674 if (size && style & QUOTE_0_TERMINATED)
675 --size;
676
677 alloc_size = 4 * size;
678 if (alloc_size / 4 != size) {
679 error_msg("Out of memory");
680 tprints("???");
681 return -1;
682 }
683 alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
684
685 if (use_alloca(alloc_size)) {
686 outstr = alloca(alloc_size);
687 buf = NULL;
688 } else {
689 outstr = buf = malloc(alloc_size);
690 if (!buf) {
691 error_msg("Out of memory");
692 tprints("???");
693 return -1;
694 }
695 }
696
697 rc = string_quote(str, outstr, size, style);
698 tprints(outstr);
699
700 free(buf);
701 return rc;
702}
703
Dmitry V. Levina501f142008-11-10 23:19:13 +0000704/*
705 * Print path string specified by address `addr' and length `n'.
706 * If path length exceeds `n', append `...' to the output.
707 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000709printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000710{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000711 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100712 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100713
Dmitry V. Levina501f142008-11-10 23:19:13 +0000714 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200715 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000716 return;
717 }
718
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100719 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000720 if (n > sizeof path - 1)
721 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000722
723 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100724 nul_seen = umovestr(tcp, addr, n + 1, path);
725 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000726 tprintf("%#lx", addr);
727 else {
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000728 path[n++] = '\0';
729 print_quoted_string(path, n, QUOTE_0_TERMINATED);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100730 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100731 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732 }
733}
734
735void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000736printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100738 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000739 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000740}
741
Dmitry V. Levina501f142008-11-10 23:19:13 +0000742/*
743 * Print string specified by address `addr' and length `len'.
744 * If `len' < 0, treat the string as a NUL-terminated string.
745 * If string length exceeds `max_strlen', append `...' to the output.
746 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000747void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200748printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000749{
750 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000752 unsigned int size;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000753 unsigned int style;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100754 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000755
756 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200757 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758 return;
759 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000760 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200761 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000762 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
763
764 if (outstr_size / 4 != max_strlen)
765 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000766 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200767 if (!str)
768 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000769 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200770 if (!outstr)
771 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000772 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000773
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000774 size = max_strlen;
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200775 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000776 /*
777 * Treat as a NUL-terminated string: fetch one byte more
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000778 * because string_quote may look one byte ahead.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000779 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000780 if (umovestr(tcp, addr, size + 1, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 tprintf("%#lx", addr);
782 return;
783 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000784 style = QUOTE_0_TERMINATED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785 }
786 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200787 if (size > (unsigned long)len)
788 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000789 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000790 tprintf("%#lx", addr);
791 return;
792 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000793 style = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 }
795
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100796 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
797 * or we were requested to print more than -s NUM chars)...
798 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000799 ellipsis = (string_quote(str, outstr, size, style) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000800 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000801
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100802 tprints(outstr);
803 if (ellipsis)
804 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805}
806
John Hughes1d08dcf2001-07-10 13:48:44 +0000807void
Denys Vlasenko12014262011-05-30 14:00:14 +0200808dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000809{
Denys Vlasenko84703742012-02-25 02:38:52 +0100810#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000811 union {
812 struct { u_int32_t base; u_int32_t len; } *iov32;
813 struct { u_int64_t base; u_int64_t len; } *iov64;
814 } iovu;
815#define iov iovu.iov64
816#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100817 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000818#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100819 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000820#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100821 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000822#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000823 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000824#define sizeof_iov sizeof(*iov)
825#define iov_iov_base(i) iov[i].iov_base
826#define iov_iov_len(i) iov[i].iov_len
827#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000828 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200829 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000830
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200831 size = sizeof_iov * len;
832 /* Assuming no sane program has millions of iovs */
833 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000834 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200835 fprintf(stderr, "Out of memory\n");
836 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000837 }
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100838 if (umoven(tcp, addr, size, iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000839 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000840 /* include the buffer number to make it easy to
841 * match up the trace with the source */
842 tprintf(" * %lu bytes in buffer %d\n",
843 (unsigned long)iov_iov_len(i), i);
844 dumpstr(tcp, (long) iov_iov_base(i),
845 iov_iov_len(i));
846 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000847 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200848 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000849#undef sizeof_iov
850#undef iov_iov_base
851#undef iov_iov_len
852#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000853}
John Hughes1d08dcf2001-07-10 13:48:44 +0000854
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000855void
Denys Vlasenko12014262011-05-30 14:00:14 +0200856dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000857{
858 static int strsize = -1;
859 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000860
Denys Vlasenko76325802013-02-22 14:47:39 +0100861 char outbuf[
862 (
863 (sizeof(
864 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
865 "1234567890123456") + /*in case I'm off by few:*/ 4)
866 /*align to 8 to make memset easier:*/ + 7) & -8
867 ];
868 const unsigned char *src;
869 int i;
870
871 memset(outbuf, ' ', sizeof(outbuf));
872
873 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200874 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100875 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200876 if (!str) {
877 strsize = -1;
878 fprintf(stderr, "Out of memory\n");
879 return;
880 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100881 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 }
883
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100884 if (umoven(tcp, addr, len, str) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 return;
886
Denys Vlasenko76325802013-02-22 14:47:39 +0100887 /* Space-pad to 16 bytes */
888 i = len;
889 while (i & 0xf)
890 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200891
Denys Vlasenko76325802013-02-22 14:47:39 +0100892 i = 0;
893 src = str;
894 while (i < len) {
895 char *dst = outbuf;
896 /* Hex dump */
897 do {
898 if (i < len) {
899 *dst++ = "0123456789abcdef"[*src >> 4];
900 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 }
902 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100903 *dst++ = ' ';
904 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000905 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100906 dst++; /* space is there by memset */
907 i++;
908 if ((i & 7) == 0)
909 dst++; /* space is there by memset */
910 src++;
911 } while (i & 0xf);
912 /* ASCII dump */
913 i -= 16;
914 src -= 16;
915 do {
916 if (*src >= ' ' && *src < 0x7f)
917 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000918 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100919 *dst++ = '.';
920 src++;
921 } while (++i & 0xf);
922 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100923 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924 }
925}
926
Mike Frysinger612659e2012-02-14 14:38:28 +0100927#ifdef HAVE_PROCESS_VM_READV
928/* C library supports this, but the kernel might not. */
929static bool process_vm_readv_not_supported = 0;
930#else
931
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100932/* Need to do this since process_vm_readv() is not yet available in libc.
933 * When libc is be updated, only "static bool process_vm_readv_not_supported"
934 * line should remain.
935 */
936#if !defined(__NR_process_vm_readv)
937# if defined(I386)
938# define __NR_process_vm_readv 347
939# elif defined(X86_64)
940# define __NR_process_vm_readv 310
941# elif defined(POWERPC)
942# define __NR_process_vm_readv 351
943# endif
944#endif
945
946#if defined(__NR_process_vm_readv)
947static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400948/* Have to avoid duplicating with the C library headers. */
949static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100950 const struct iovec *lvec,
951 unsigned long liovcnt,
952 const struct iovec *rvec,
953 unsigned long riovcnt,
954 unsigned long flags)
955{
956 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
957}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400958#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100959#else
960static bool process_vm_readv_not_supported = 1;
961# define process_vm_readv(...) (errno = ENOSYS, -1)
962#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100963
964#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100965
Dmitry V. Levinea1fea62015-03-31 19:45:08 +0000966static ssize_t
967vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
968{
969 const struct iovec local = {
970 .iov_base = laddr,
971 .iov_len = len
972 };
973 const struct iovec remote = {
974 .iov_base = (void *) raddr,
975 .iov_len = len
976 };
977
978 return process_vm_readv(pid, &local, 1, &remote, 1, 0);
979}
980
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981/*
982 * move `len' bytes of data from process `pid'
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100983 * at address `addr' to our space at `our_addr'
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 */
985int
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100986umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987{
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100988 char *laddr = our_addr;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700989 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000990 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 union {
992 long val;
993 char x[sizeof(long)];
994 } u;
995
Denys Vlasenko2544f982013-02-19 17:39:56 +0100996#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100997 if (current_wordsize < sizeof(addr))
998 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100999#endif
1000
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001001 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001002 int r = vm_read_mem(pid, laddr, addr, len);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001003 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +01001004 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001005 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001006 error_msg("umoven: short read (%u < %u) @0x%lx",
1007 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001008 return -1;
1009 }
1010 switch (errno) {
1011 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001012 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001013 break;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001014 case EPERM:
1015 /* operation not permitted, try PTRACE_PEEKDATA */
1016 break;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001017 case ESRCH:
1018 /* the process is gone */
1019 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001020 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001021 /* address space is inaccessible */
1022 return -1;
1023 default:
1024 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001025 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +00001026 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001027 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001028 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001029
Dmitry V. Levin97005922013-02-26 21:16:22 +00001030 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 if (addr & (sizeof(long) - 1)) {
1032 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001033 n = addr & (sizeof(long) - 1); /* residue */
1034 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001035 errno = 0;
1036 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001037 switch (errno) {
1038 case 0:
1039 break;
1040 case ESRCH: case EINVAL:
1041 /* these could be seen if the process is gone */
1042 return -1;
1043 case EFAULT: case EIO: case EPERM:
1044 /* address space is inaccessible */
1045 return -1;
1046 default:
1047 /* all the rest is strange and should be reported */
1048 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1049 pid, addr);
1050 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001051 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001052 m = MIN(sizeof(long) - n, len);
1053 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001054 addr += sizeof(long);
1055 laddr += m;
1056 nread += m;
1057 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 }
1059 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001060 errno = 0;
1061 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001062 switch (errno) {
1063 case 0:
1064 break;
1065 case ESRCH: case EINVAL:
1066 /* these could be seen if the process is gone */
1067 return -1;
1068 case EFAULT: case EIO: case EPERM:
1069 /* address space is inaccessible */
1070 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001071 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001072 nread, nread + len, addr - nread);
1073 }
1074 return -1;
1075 default:
1076 /* all the rest is strange and should be reported */
1077 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1078 pid, addr);
1079 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001080 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001081 m = MIN(sizeof(long), len);
1082 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001083 addr += sizeof(long);
1084 laddr += m;
1085 nread += m;
1086 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089 return 0;
1090}
1091
1092/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001093 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001094 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001095 *
1096 * Returns < 0 on error, > 0 if NUL was seen,
1097 * (TODO if useful: return count of bytes including NUL),
1098 * else 0 if len bytes were read but no NUL byte seen.
1099 *
1100 * Note: there is no guarantee we won't overwrite some bytes
1101 * in laddr[] _after_ terminating NUL (but, of course,
1102 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103 */
1104int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001105umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106{
Denys Vlasenko16940922013-03-01 18:52:59 +01001107#if SIZEOF_LONG == 4
1108 const unsigned long x01010101 = 0x01010101ul;
1109 const unsigned long x80808080 = 0x80808080ul;
1110#elif SIZEOF_LONG == 8
1111 const unsigned long x01010101 = 0x0101010101010101ul;
1112 const unsigned long x80808080 = 0x8080808080808080ul;
1113#else
1114# error SIZEOF_LONG > 8
1115#endif
1116
Roland McGratheb9e2e82009-06-02 16:49:22 -07001117 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001118 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001120 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 char x[sizeof(long)];
1122 } u;
1123
Denys Vlasenko2544f982013-02-19 17:39:56 +01001124#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001125 if (current_wordsize < sizeof(addr))
1126 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001127#endif
1128
Dmitry V. Levin97005922013-02-26 21:16:22 +00001129 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001130 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001131 const size_t page_size = get_pagesize();
1132 const size_t page_mask = page_size - 1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001133
1134 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001135 unsigned int chunk_len;
1136 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001137
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001138 /*
1139 * Don't cross pages, otherwise we can get EFAULT
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001140 * and fail to notice that terminating NUL lies
1141 * in the existing (first) page.
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001142 */
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001143 chunk_len = len > page_size ? page_size : len;
1144 end_in_page = (addr + chunk_len) & page_mask;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001145 if (chunk_len > end_in_page) /* crosses to the next page */
1146 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001147
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001148 int r = vm_read_mem(pid, laddr, addr, chunk_len);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001149 if (r > 0) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001150 if (memchr(laddr, '\0', r))
Dmitry V. Levin97005922013-02-26 21:16:22 +00001151 return 1;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001152 addr += r;
1153 laddr += r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001154 nread += r;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001155 len -= r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001156 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001157 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001158 switch (errno) {
1159 case ENOSYS:
1160 process_vm_readv_not_supported = 1;
1161 goto vm_readv_didnt_work;
1162 case ESRCH:
1163 /* the process is gone */
1164 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001165 case EPERM:
1166 /* operation not permitted, try PTRACE_PEEKDATA */
1167 if (!nread)
1168 goto vm_readv_didnt_work;
1169 /* fall through */
1170 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001171 /* address space is inaccessible */
1172 if (nread) {
1173 perror_msg("umovestr: short read (%d < %d) @0x%lx",
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001174 nread, nread + len, addr - nread);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001175 }
1176 return -1;
1177 default:
1178 /* all the rest is strange and should be reported */
1179 perror_msg("process_vm_readv");
1180 return -1;
1181 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001182 }
1183 return 0;
1184 }
1185 vm_readv_didnt_work:
1186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 if (addr & (sizeof(long) - 1)) {
1188 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001189 n = addr & (sizeof(long) - 1); /* residue */
1190 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001191 errno = 0;
1192 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001193 switch (errno) {
1194 case 0:
1195 break;
1196 case ESRCH: case EINVAL:
1197 /* these could be seen if the process is gone */
1198 return -1;
1199 case EFAULT: case EIO: case EPERM:
1200 /* address space is inaccessible */
1201 return -1;
1202 default:
1203 /* all the rest is strange and should be reported */
1204 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1205 pid, addr);
1206 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001207 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001208 m = MIN(sizeof(long) - n, len);
1209 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 while (n & (sizeof(long) - 1))
1211 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001212 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001213 addr += sizeof(long);
1214 laddr += m;
1215 nread += m;
1216 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001218
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001220 errno = 0;
1221 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001222 switch (errno) {
1223 case 0:
1224 break;
1225 case ESRCH: case EINVAL:
1226 /* these could be seen if the process is gone */
1227 return -1;
1228 case EFAULT: case EIO: case EPERM:
1229 /* address space is inaccessible */
1230 if (nread) {
1231 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1232 nread, nread + len, addr - nread);
1233 }
1234 return -1;
1235 default:
1236 /* all the rest is strange and should be reported */
1237 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1238 pid, addr);
1239 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001240 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001241 m = MIN(sizeof(long), len);
1242 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001243 /* "If a NUL char exists in this word" */
1244 if ((u.val - x01010101) & ~u.val & x80808080)
1245 return 1;
1246 addr += sizeof(long);
1247 laddr += m;
1248 nread += m;
1249 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001251 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252}
1253
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001255upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001256{
1257 long val;
1258
Roland McGratheb9e2e82009-06-02 16:49:22 -07001259 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001260 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001261 if (val == -1 && errno) {
1262 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001263 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001264 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001266 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 *res = val;
1268 return 0;
1269}