blob: 813878913ef7bd074521e90c4941af231bb49516 [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>
Dmitry V. Levind93c4e82015-06-17 20:09:13 +000037#ifdef HAVE_SYS_XATTR_H
Masatake YAMATOf5480672014-11-22 19:03:33 +090038# 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. Levin332a3262015-07-05 22:09:29 +0000379printaddr(const long addr)
380{
381 if (!addr)
382 tprints("NULL");
383 else
384 tprintf("%#lx", addr);
385}
386
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000387#define DEF_PRINTNUM(name, type) \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000388bool \
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000389printnum_ ## name(struct tcb *tcp, const long addr, const char *fmt) \
390{ \
391 type num; \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000392 if (umove_or_printaddr(tcp, addr, &num)) \
393 return false; \
394 tprints("["); \
395 tprintf(fmt, num); \
396 tprints("]"); \
397 return true; \
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000398}
399
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000400#define DEF_PRINTPAIR(name, type) \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000401bool \
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000402printpair_ ## name(struct tcb *tcp, const long addr, const char *fmt) \
403{ \
404 type pair[2]; \
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000405 if (umove_or_printaddr(tcp, addr, &pair)) \
406 return false; \
407 tprints("["); \
408 tprintf(fmt, pair[0]); \
409 tprints(", "); \
410 tprintf(fmt, pair[1]); \
411 tprints("]"); \
412 return true; \
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000413}
414
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000415DEF_PRINTNUM(int, int)
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000416DEF_PRINTPAIR(int, int)
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000417DEF_PRINTNUM(short, short)
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000418DEF_PRINTNUM(int64, uint64_t)
Dmitry V. Levin69127a32015-07-05 22:09:29 +0000419DEF_PRINTPAIR(int64, uint64_t)
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000420
421#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000422bool
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000423printnum_long_int(struct tcb *tcp, const long addr,
424 const char *fmt_long, const char *fmt_int)
425{
426 if (current_wordsize > sizeof(int)) {
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000427 return printnum_int64(tcp, addr, fmt_long);
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000428 } else {
Dmitry V. Levind77f6692015-08-18 21:57:27 +0000429 return printnum_int(tcp, addr, fmt_int);
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000430 }
431}
Dmitry V. Levinc88163e2015-07-05 22:09:29 +0000432#endif
Roland McGrath9814a942005-07-04 23:28:10 +0000433
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000434const char *
435sprinttime(time_t t)
436{
437 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000438 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000439
440 if (t == 0) {
441 strcpy(buf, "0");
442 return buf;
443 }
444 tmp = localtime(&t);
445 if (tmp)
446 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
447 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
448 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
449 else
450 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
451
452 return buf;
453}
454
Masatake YAMATOf5480672014-11-22 19:03:33 +0900455static char *
456getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
457{
Dmitry V. Levind93c4e82015-06-17 20:09:13 +0000458#ifdef HAVE_SYS_XATTR_H
Masatake YAMATOf5480672014-11-22 19:03:33 +0900459 ssize_t r;
460 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
461
462 if (fd < 0)
463 return NULL;
464
465 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
466 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
467 if (r <= 0)
468 return NULL;
469 else {
470 /*
471 * This is a protection for the case when the kernel
472 * side does not append a null byte to the buffer.
473 */
474 buf[r] = '\0';
475 return buf;
476 }
477#else
478 return NULL;
479#endif
480}
481
Roland McGrath9814a942005-07-04 23:28:10 +0000482void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300483printfd(struct tcb *tcp, int fd)
484{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100485 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000486 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
487 static const char socket_prefix[] = "socket:[";
488 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000489 const size_t path_len = strlen(path);
Grant Edwards8a082772011-04-07 20:25:40 +0000490
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000491 tprintf("%d<", fd);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000492 if (show_fd_path > 1 &&
493 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000494 path[path_len - 1] == ']') {
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000495 unsigned long inodenr;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900496#define PROTO_NAME_LEN 32
497 char proto_buf[PROTO_NAME_LEN];
498 const char *proto =
499 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000500 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900501 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900502 if (proto)
503 tprintf("%s:[%lu]", proto, inodenr);
504 else
505 tprints(path);
506 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000507 } else {
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000508 print_quoted_string(path, path_len,
509 QUOTE_OMIT_LEADING_TRAILING_QUOTES);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000510 }
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000511 tprints(">");
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000512 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000513 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300514}
515
Dmitry V. Levina501f142008-11-10 23:19:13 +0000516/*
517 * Quote string `instr' of length `size'
518 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100519 *
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000520 * If QUOTE_0_TERMINATED `style' flag is set,
521 * treat `instr' as a NUL-terminated string,
522 * checking up to (`size' + 1) bytes of `instr'.
523 *
524 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
525 * do not add leading and trailing quoting symbols.
526 *
527 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
528 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000529 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000530static int
531string_quote(const char *instr, char *outstr, const unsigned int size,
532 const unsigned int style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000533{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000534 const unsigned char *ustr = (const unsigned char *) instr;
535 char *s = outstr;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000536 unsigned int i;
537 int usehex, c, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000539 if (style & QUOTE_0_TERMINATED)
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200540 eol = '\0';
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000541 else
542 eol = 0x100; /* this can never match a char */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200543
544 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000545 if (xflag > 1)
546 usehex = 1;
547 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000548 /* Check for presence of symbol which require
549 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000550 for (i = 0; i < size; ++i) {
551 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000552 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200553 if (c == eol)
554 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100555
556 /* Force hex unless c is printable or whitespace */
557 if (c > 0x7e) {
558 usehex = 1;
559 break;
560 }
561 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
562 * They happen to have ASCII codes 9,10,11,12,13.
563 */
564 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 usehex = 1;
566 break;
567 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 }
569 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000570
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000571 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
572 *s++ = '\"';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000573
574 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000575 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000576 for (i = 0; i < size; ++i) {
577 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000578 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200579 if (c == eol)
580 goto asciz_ended;
581 *s++ = '\\';
582 *s++ = 'x';
583 *s++ = "0123456789abcdef"[c >> 4];
584 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000585 }
586 } else {
587 for (i = 0; i < size; ++i) {
588 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000589 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200590 if (c == eol)
591 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000592 switch (c) {
593 case '\"': case '\\':
594 *s++ = '\\';
595 *s++ = c;
596 break;
597 case '\f':
598 *s++ = '\\';
599 *s++ = 'f';
600 break;
601 case '\n':
602 *s++ = '\\';
603 *s++ = 'n';
604 break;
605 case '\r':
606 *s++ = '\\';
607 *s++ = 'r';
608 break;
609 case '\t':
610 *s++ = '\\';
611 *s++ = 't';
612 break;
613 case '\v':
614 *s++ = '\\';
615 *s++ = 'v';
616 break;
617 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100618 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000619 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200620 else {
621 /* Print \octal */
622 *s++ = '\\';
623 if (i + 1 < size
624 && ustr[i + 1] >= '0'
625 && ustr[i + 1] <= '9'
626 ) {
627 /* Print \ooo */
628 *s++ = '0' + (c >> 6);
629 *s++ = '0' + ((c >> 3) & 0x7);
630 } else {
631 /* Print \[[o]o]o */
632 if ((c >> 3) != 0) {
633 if ((c >> 6) != 0)
634 *s++ = '0' + (c >> 6);
635 *s++ = '0' + ((c >> 3) & 0x7);
636 }
637 }
638 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000639 }
640 break;
641 }
642 }
643 }
644
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000645 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
646 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000648
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200649 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000650 if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200651 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
652 * but next char is NUL.
653 */
654 return 0;
655 }
656
657 return 1;
658
659 asciz_ended:
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000660 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
661 *s++ = '\"';
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200662 *s = '\0';
663 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
664 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665}
666
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000667#ifndef ALLOCA_CUTOFF
668# define ALLOCA_CUTOFF 4032
669#endif
670#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
671
672/*
673 * Quote string `str' of length `size' and print the result.
674 *
675 * If QUOTE_0_TERMINATED `style' flag is set,
676 * treat `str' as a NUL-terminated string and
677 * quote at most (`size' - 1) bytes.
678 *
679 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
680 * do not add leading and trailing quoting symbols.
681 *
682 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
683 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
684 */
685int
686print_quoted_string(const char *str, unsigned int size,
687 const unsigned int style)
688{
689 char *buf;
690 char *outstr;
691 unsigned int alloc_size;
692 int rc;
693
694 if (size && style & QUOTE_0_TERMINATED)
695 --size;
696
697 alloc_size = 4 * size;
698 if (alloc_size / 4 != size) {
699 error_msg("Out of memory");
700 tprints("???");
701 return -1;
702 }
703 alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
704
705 if (use_alloca(alloc_size)) {
706 outstr = alloca(alloc_size);
707 buf = NULL;
708 } else {
709 outstr = buf = malloc(alloc_size);
710 if (!buf) {
711 error_msg("Out of memory");
712 tprints("???");
713 return -1;
714 }
715 }
716
717 rc = string_quote(str, outstr, size, style);
718 tprints(outstr);
719
720 free(buf);
721 return rc;
722}
723
Dmitry V. Levina501f142008-11-10 23:19:13 +0000724/*
725 * Print path string specified by address `addr' and length `n'.
726 * If path length exceeds `n', append `...' to the output.
727 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000728void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000729printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000731 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100732 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100733
Dmitry V. Levina501f142008-11-10 23:19:13 +0000734 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200735 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000736 return;
737 }
738
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100739 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000740 if (n > sizeof path - 1)
741 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000742
743 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100744 nul_seen = umovestr(tcp, addr, n + 1, path);
745 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746 tprintf("%#lx", addr);
747 else {
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000748 path[n++] = '\0';
749 print_quoted_string(path, n, QUOTE_0_TERMINATED);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100750 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100751 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752 }
753}
754
755void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000756printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100758 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000759 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000760}
761
Dmitry V. Levina501f142008-11-10 23:19:13 +0000762/*
763 * Print string specified by address `addr' and length `len'.
764 * If `len' < 0, treat the string as a NUL-terminated string.
765 * If string length exceeds `max_strlen', append `...' to the output.
766 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000767void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200768printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000769{
770 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000771 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000772 unsigned int size;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000773 unsigned int style;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100774 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000775
776 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200777 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000778 return;
779 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000780 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200781 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000782 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
783
784 if (outstr_size / 4 != max_strlen)
785 die_out_of_memory();
Dmitry V. Levin3e9d71f2015-05-25 20:41:02 +0000786 str = xmalloc(max_strlen + 1);
787 outstr = xmalloc(outstr_size);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000788 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000789
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000790 size = max_strlen;
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200791 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000792 /*
793 * Treat as a NUL-terminated string: fetch one byte more
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000794 * because string_quote may look one byte ahead.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000795 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000796 if (umovestr(tcp, addr, size + 1, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 tprintf("%#lx", addr);
798 return;
799 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000800 style = QUOTE_0_TERMINATED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000801 }
802 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200803 if (size > (unsigned long)len)
804 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000805 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000806 tprintf("%#lx", addr);
807 return;
808 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000809 style = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000810 }
811
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100812 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
813 * or we were requested to print more than -s NUM chars)...
814 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000815 ellipsis = (string_quote(str, outstr, size, style) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000816 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000817
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100818 tprints(outstr);
819 if (ellipsis)
820 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821}
822
John Hughes1d08dcf2001-07-10 13:48:44 +0000823void
Denys Vlasenko12014262011-05-30 14:00:14 +0200824dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000825{
Denys Vlasenko84703742012-02-25 02:38:52 +0100826#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000827 union {
828 struct { u_int32_t base; u_int32_t len; } *iov32;
829 struct { u_int64_t base; u_int64_t len; } *iov64;
830 } iovu;
831#define iov iovu.iov64
832#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100833 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000834#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100835 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000836#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100837 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000838#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000839 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000840#define sizeof_iov sizeof(*iov)
841#define iov_iov_base(i) iov[i].iov_base
842#define iov_iov_len(i) iov[i].iov_len
843#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000844 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200845 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000846
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200847 size = sizeof_iov * len;
848 /* Assuming no sane program has millions of iovs */
849 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000850 || (iov = malloc(size)) == NULL) {
Dmitry V. Levindf389912015-05-25 23:33:31 +0300851 error_msg("Out of memory");
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200852 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000853 }
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100854 if (umoven(tcp, addr, size, iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000855 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000856 /* include the buffer number to make it easy to
857 * match up the trace with the source */
858 tprintf(" * %lu bytes in buffer %d\n",
859 (unsigned long)iov_iov_len(i), i);
860 dumpstr(tcp, (long) iov_iov_base(i),
861 iov_iov_len(i));
862 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000863 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200864 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000865#undef sizeof_iov
866#undef iov_iov_base
867#undef iov_iov_len
868#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000869}
John Hughes1d08dcf2001-07-10 13:48:44 +0000870
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000871void
Denys Vlasenko12014262011-05-30 14:00:14 +0200872dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000873{
874 static int strsize = -1;
875 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000876
Denys Vlasenko76325802013-02-22 14:47:39 +0100877 char outbuf[
878 (
879 (sizeof(
880 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
881 "1234567890123456") + /*in case I'm off by few:*/ 4)
882 /*align to 8 to make memset easier:*/ + 7) & -8
883 ];
884 const unsigned char *src;
885 int i;
886
887 memset(outbuf, ' ', sizeof(outbuf));
888
889 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200890 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100891 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200892 if (!str) {
893 strsize = -1;
Dmitry V. Levindf389912015-05-25 23:33:31 +0300894 error_msg("Out of memory");
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200895 return;
896 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100897 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000898 }
899
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100900 if (umoven(tcp, addr, len, str) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 return;
902
Denys Vlasenko76325802013-02-22 14:47:39 +0100903 /* Space-pad to 16 bytes */
904 i = len;
905 while (i & 0xf)
906 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200907
Denys Vlasenko76325802013-02-22 14:47:39 +0100908 i = 0;
909 src = str;
910 while (i < len) {
911 char *dst = outbuf;
912 /* Hex dump */
913 do {
914 if (i < len) {
915 *dst++ = "0123456789abcdef"[*src >> 4];
916 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 }
918 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100919 *dst++ = ' ';
920 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100922 dst++; /* space is there by memset */
923 i++;
924 if ((i & 7) == 0)
925 dst++; /* space is there by memset */
926 src++;
927 } while (i & 0xf);
928 /* ASCII dump */
929 i -= 16;
930 src -= 16;
931 do {
932 if (*src >= ' ' && *src < 0x7f)
933 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100935 *dst++ = '.';
936 src++;
937 } while (++i & 0xf);
938 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100939 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 }
941}
942
Mike Frysinger612659e2012-02-14 14:38:28 +0100943#ifdef HAVE_PROCESS_VM_READV
944/* C library supports this, but the kernel might not. */
945static bool process_vm_readv_not_supported = 0;
946#else
947
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100948/* Need to do this since process_vm_readv() is not yet available in libc.
949 * When libc is be updated, only "static bool process_vm_readv_not_supported"
950 * line should remain.
951 */
952#if !defined(__NR_process_vm_readv)
953# if defined(I386)
954# define __NR_process_vm_readv 347
955# elif defined(X86_64)
956# define __NR_process_vm_readv 310
957# elif defined(POWERPC)
958# define __NR_process_vm_readv 351
959# endif
960#endif
961
962#if defined(__NR_process_vm_readv)
963static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400964/* Have to avoid duplicating with the C library headers. */
965static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100966 const struct iovec *lvec,
967 unsigned long liovcnt,
968 const struct iovec *rvec,
969 unsigned long riovcnt,
970 unsigned long flags)
971{
972 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
973}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400974#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100975#else
976static bool process_vm_readv_not_supported = 1;
977# define process_vm_readv(...) (errno = ENOSYS, -1)
978#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100979
980#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100981
Dmitry V. Levinea1fea62015-03-31 19:45:08 +0000982static ssize_t
983vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
984{
985 const struct iovec local = {
986 .iov_base = laddr,
987 .iov_len = len
988 };
989 const struct iovec remote = {
990 .iov_base = (void *) raddr,
991 .iov_len = len
992 };
993
994 return process_vm_readv(pid, &local, 1, &remote, 1, 0);
995}
996
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997/*
998 * move `len' bytes of data from process `pid'
Denys Vlasenko7e69ed92015-03-21 19:50:53 +0100999 * at address `addr' to our space at `our_addr'
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 */
1001int
Denys Vlasenko7e69ed92015-03-21 19:50:53 +01001002umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003{
Denys Vlasenko7e69ed92015-03-21 19:50:53 +01001004 char *laddr = our_addr;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001005 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001006 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 union {
1008 long val;
1009 char x[sizeof(long)];
1010 } u;
1011
Denys Vlasenko2544f982013-02-19 17:39:56 +01001012#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001013 if (current_wordsize < sizeof(addr))
1014 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +01001015#endif
1016
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001017 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001018 int r = vm_read_mem(pid, laddr, addr, len);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001019 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +01001020 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001021 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001022 error_msg("umoven: short read (%u < %u) @0x%lx",
1023 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001024 return -1;
1025 }
1026 switch (errno) {
1027 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001028 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001029 break;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001030 case EPERM:
1031 /* operation not permitted, try PTRACE_PEEKDATA */
1032 break;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001033 case ESRCH:
1034 /* the process is gone */
1035 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001036 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001037 /* address space is inaccessible */
1038 return -1;
1039 default:
1040 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001041 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +00001042 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001043 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001044 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001045
Dmitry V. Levin97005922013-02-26 21:16:22 +00001046 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 if (addr & (sizeof(long) - 1)) {
1048 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001049 n = addr & (sizeof(long) - 1); /* residue */
1050 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001051 errno = 0;
1052 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001053 switch (errno) {
1054 case 0:
1055 break;
1056 case ESRCH: case EINVAL:
1057 /* these could be seen if the process is gone */
1058 return -1;
1059 case EFAULT: case EIO: case EPERM:
1060 /* address space is inaccessible */
1061 return -1;
1062 default:
1063 /* all the rest is strange and should be reported */
1064 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1065 pid, addr);
1066 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001067 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001068 m = MIN(sizeof(long) - n, len);
1069 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001070 addr += sizeof(long);
1071 laddr += m;
1072 nread += m;
1073 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 }
1075 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001076 errno = 0;
1077 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001078 switch (errno) {
1079 case 0:
1080 break;
1081 case ESRCH: case EINVAL:
1082 /* these could be seen if the process is gone */
1083 return -1;
1084 case EFAULT: case EIO: case EPERM:
1085 /* address space is inaccessible */
1086 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001087 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001088 nread, nread + len, addr - nread);
1089 }
1090 return -1;
1091 default:
1092 /* all the rest is strange and should be reported */
1093 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1094 pid, addr);
1095 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001096 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001097 m = MIN(sizeof(long), len);
1098 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001099 addr += sizeof(long);
1100 laddr += m;
1101 nread += m;
1102 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 return 0;
1106}
1107
Dmitry V. Levin332a3262015-07-05 22:09:29 +00001108int
1109umoven_or_printaddr(struct tcb *tcp, const long addr, const unsigned int len,
1110 void *our_addr)
1111{
1112 if (!addr) {
1113 tprints("NULL");
1114 return -1;
1115 }
Dmitry V. Levin61b79892015-07-14 22:03:55 +00001116 if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
Dmitry V. Levin332a3262015-07-05 22:09:29 +00001117 umoven(tcp, addr, len, our_addr) < 0) {
1118 tprintf("%#lx", addr);
1119 return -1;
1120 }
1121 return 0;
1122}
1123
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001125 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001127 *
1128 * Returns < 0 on error, > 0 if NUL was seen,
1129 * (TODO if useful: return count of bytes including NUL),
1130 * else 0 if len bytes were read but no NUL byte seen.
1131 *
1132 * Note: there is no guarantee we won't overwrite some bytes
1133 * in laddr[] _after_ terminating NUL (but, of course,
1134 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 */
1136int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001137umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138{
Denys Vlasenko16940922013-03-01 18:52:59 +01001139#if SIZEOF_LONG == 4
1140 const unsigned long x01010101 = 0x01010101ul;
1141 const unsigned long x80808080 = 0x80808080ul;
1142#elif SIZEOF_LONG == 8
1143 const unsigned long x01010101 = 0x0101010101010101ul;
1144 const unsigned long x80808080 = 0x8080808080808080ul;
1145#else
1146# error SIZEOF_LONG > 8
1147#endif
1148
Roland McGratheb9e2e82009-06-02 16:49:22 -07001149 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001150 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001152 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 char x[sizeof(long)];
1154 } u;
1155
Denys Vlasenko2544f982013-02-19 17:39:56 +01001156#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001157 if (current_wordsize < sizeof(addr))
1158 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001159#endif
1160
Dmitry V. Levin97005922013-02-26 21:16:22 +00001161 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001162 if (!process_vm_readv_not_supported) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001163 const size_t page_size = get_pagesize();
1164 const size_t page_mask = page_size - 1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001165
1166 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001167 unsigned int chunk_len;
1168 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001169
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001170 /*
1171 * Don't cross pages, otherwise we can get EFAULT
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001172 * and fail to notice that terminating NUL lies
1173 * in the existing (first) page.
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001174 */
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001175 chunk_len = len > page_size ? page_size : len;
1176 end_in_page = (addr + chunk_len) & page_mask;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001177 if (chunk_len > end_in_page) /* crosses to the next page */
1178 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001179
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001180 int r = vm_read_mem(pid, laddr, addr, chunk_len);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001181 if (r > 0) {
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001182 if (memchr(laddr, '\0', r))
Dmitry V. Levin97005922013-02-26 21:16:22 +00001183 return 1;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001184 addr += r;
1185 laddr += r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001186 nread += r;
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001187 len -= r;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001188 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001189 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001190 switch (errno) {
1191 case ENOSYS:
1192 process_vm_readv_not_supported = 1;
1193 goto vm_readv_didnt_work;
1194 case ESRCH:
1195 /* the process is gone */
1196 return -1;
Dmitry V. Levinb2893c92015-03-30 15:21:55 +00001197 case EPERM:
1198 /* operation not permitted, try PTRACE_PEEKDATA */
1199 if (!nread)
1200 goto vm_readv_didnt_work;
1201 /* fall through */
1202 case EFAULT: case EIO:
Dmitry V. Levin97005922013-02-26 21:16:22 +00001203 /* address space is inaccessible */
1204 if (nread) {
1205 perror_msg("umovestr: short read (%d < %d) @0x%lx",
Dmitry V. Levinea1fea62015-03-31 19:45:08 +00001206 nread, nread + len, addr - nread);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001207 }
1208 return -1;
1209 default:
1210 /* all the rest is strange and should be reported */
1211 perror_msg("process_vm_readv");
1212 return -1;
1213 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001214 }
1215 return 0;
1216 }
1217 vm_readv_didnt_work:
1218
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219 if (addr & (sizeof(long) - 1)) {
1220 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001221 n = addr & (sizeof(long) - 1); /* residue */
1222 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001223 errno = 0;
1224 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001225 switch (errno) {
1226 case 0:
1227 break;
1228 case ESRCH: case EINVAL:
1229 /* these could be seen if the process is gone */
1230 return -1;
1231 case EFAULT: case EIO: case EPERM:
1232 /* address space is inaccessible */
1233 return -1;
1234 default:
1235 /* all the rest is strange and should be reported */
1236 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1237 pid, addr);
1238 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001239 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001240 m = MIN(sizeof(long) - n, len);
1241 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 while (n & (sizeof(long) - 1))
1243 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001244 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001245 addr += sizeof(long);
1246 laddr += m;
1247 nread += m;
1248 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001250
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001252 errno = 0;
1253 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001254 switch (errno) {
1255 case 0:
1256 break;
1257 case ESRCH: case EINVAL:
1258 /* these could be seen if the process is gone */
1259 return -1;
1260 case EFAULT: case EIO: case EPERM:
1261 /* address space is inaccessible */
1262 if (nread) {
1263 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1264 nread, nread + len, addr - nread);
1265 }
1266 return -1;
1267 default:
1268 /* all the rest is strange and should be reported */
1269 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1270 pid, addr);
1271 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001272 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001273 m = MIN(sizeof(long), len);
1274 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001275 /* "If a NUL char exists in this word" */
1276 if ((u.val - x01010101) & ~u.val & x80808080)
1277 return 1;
1278 addr += sizeof(long);
1279 laddr += m;
1280 nread += m;
1281 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001283 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284}
1285
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001286int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001287upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288{
1289 long val;
1290
Roland McGratheb9e2e82009-06-02 16:49:22 -07001291 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001292 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001293 if (val == -1 && errno) {
1294 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001295 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001296 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001298 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299 *res = val;
1300 return 0;
1301}