blob: ccf687ff1e2a751f39b2af96ab50d429cd45d7f3 [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/user.h>
36#include <sys/param.h>
37#include <fcntl.h>
Masatake YAMATOf5480672014-11-22 19:03:33 +090038#if HAVE_SYS_XATTR_H
39# include <sys/xattr.h>
40#endif
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000041#include <sys/uio.h>
Wichert Akkerman36915a11999-07-13 15:45:02 +000042
Denys Vlasenko84703742012-02-25 02:38:52 +010043#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000044# include <asm/ptrace_offsets.h>
45# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000046#endif
47
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010049# include <sys/reg.h>
Maarten ter Huurne40c174b2014-10-20 01:02:48 +020050#endif
51
52#ifdef HAVE_LINUX_PTRACE_H
Denys Vlasenko84703742012-02-25 02:38:52 +010053# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000054# ifdef HAVE_STRUCT_IA64_FPREG
55# define ia64_fpreg XXX_ia64_fpreg
56# endif
57# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
58# define pt_all_user_regs XXX_pt_all_user_regs
59# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030060# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
61# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
62# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010063# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030064# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000065# undef ia64_fpreg
66# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000070string_to_uint(const char *str)
71{
72 char *error;
73 long value;
74
75 if (!*str)
76 return -1;
77 errno = 0;
78 value = strtol(str, &error, 10);
79 if (errno || *error || value < 0 || (long)(int)value != value)
80 return -1;
81 return (int)value;
82}
83
84int
Dmitry V. Levin447db452014-05-29 17:59:01 +000085tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086{
87 return a->tv_sec || a->tv_usec;
88}
89
90int
Dmitry V. Levin447db452014-05-29 17:59:01 +000091tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092{
93 if (a->tv_sec < b->tv_sec
94 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
95 return -1;
96 if (a->tv_sec > b->tv_sec
97 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
98 return 1;
99 return 0;
100}
101
102double
Dmitry V. Levin447db452014-05-29 17:59:01 +0000103tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104{
105 return tv->tv_sec + tv->tv_usec/1000000.0;
106}
107
108void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000109tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110{
111 tv->tv_sec = a->tv_sec + b->tv_sec;
112 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000113 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114 tv->tv_sec++;
115 tv->tv_usec -= 1000000;
116 }
117}
118
119void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000120tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121{
122 tv->tv_sec = a->tv_sec - b->tv_sec;
123 tv->tv_usec = a->tv_usec - b->tv_usec;
124 if (((long) tv->tv_usec) < 0) {
125 tv->tv_sec--;
126 tv->tv_usec += 1000000;
127 }
128}
129
130void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000131tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132{
133 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
134 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
135 tv->tv_usec %= 1000000;
136}
137
138void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000139tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140{
141 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000142 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143 tv->tv_usec %= 1000000;
144}
145
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000146const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000147xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148{
149 for (; xlat->str != NULL; xlat++)
150 if (xlat->val == val)
151 return xlat->str;
152 return NULL;
153}
154
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000155static int
156xlat_bsearch_compare(const void *a, const void *b)
157{
158 const unsigned int val1 = (const unsigned long) a;
159 const unsigned int val2 = ((const struct xlat *) b)->val;
160 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
161}
162
163const char *
164xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
165{
166 const struct xlat *e =
167 bsearch((const void*) (const unsigned long) val,
168 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
169
170 return e ? e->str : NULL;
171}
172
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200173#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200174char *
175stpcpy(char *dst, const char *src)
176{
177 while ((*dst = *src++) != '\0')
178 dst++;
179 return dst;
180}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200181#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200182
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100183/* Find a next bit which is set.
184 * Starts testing at cur_bit.
185 * Returns -1 if no more bits are set.
186 *
187 * We never touch bytes we don't need to.
188 * On big-endian, array is assumed to consist of
189 * current_wordsize wide words: for example, is current_wordsize is 4,
190 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
191 * On little-endian machines, word size is immaterial.
192 */
193int
194next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
195{
196 const unsigned endian = 1;
197 int little_endian = *(char*)&endian;
198
199 const uint8_t *array = bit_array;
200 unsigned pos = cur_bit / 8;
201 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
202
203 for (;;) {
204 uint8_t bitmask;
205 uint8_t cur_byte;
206
207 if (cur_bit >= size_bits)
208 return -1;
209 cur_byte = array[pos ^ pos_xor_mask];
210 if (cur_byte == 0) {
211 cur_bit = (cur_bit + 8) & (-8);
212 pos++;
213 continue;
214 }
215 bitmask = 1 << (cur_bit & 7);
216 for (;;) {
217 if (cur_byte & bitmask)
218 return cur_bit;
219 cur_bit++;
220 if (cur_bit >= size_bits)
221 return -1;
222 bitmask <<= 1;
223 /* This check *can't be* optimized out: */
224 if (bitmask == 0)
225 break;
226 }
227 pos++;
228 }
229}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230/*
231 * Print entry in struct xlat table, if there.
232 */
233void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000234printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000236 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237
238 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200239 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 else
241 tprintf("%#x /* %s */", val, dflt);
242}
243
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100244/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000245 * Fetch 64bit argument at position arg_no and
246 * return the index of the next argument.
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100247 */
248int
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000249getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100250{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000251#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
252# if SUPPORTED_PERSONALITIES > 1
253 if (current_wordsize > 4) {
254# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000255 *val = tcp->u_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100256 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000257# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100258 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000259# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000260 /* Align arg_no to the next even number. */
261 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000262# endif /* AARCH64 || POWERPC64 */
263 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100264 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100265 }
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000266# endif /* SUPPORTED_PERSONALITIES > 1 */
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000267#elif SIZEOF_LONG > 4
268# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
269#elif defined LINUX_MIPSN32
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000270 *val = tcp->ext_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100271 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000272#elif defined X32
273 if (current_personality == 0) {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000274 *val = tcp->ext_arg[arg_no];
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000275 arg_no++;
276 } else {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000277 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000278 arg_no += 2;
279 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100280#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000281# if defined __ARM_EABI__ || \
282 defined LINUX_MIPSO32 || \
283 defined POWERPC || \
284 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000285 /* Align arg_no to the next even number. */
286 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000287# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000288 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100289 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100290#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000291
Chris Metcalf879dddd2013-03-01 10:41:02 +0100292 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100293}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100294
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000296 * Print 64bit argument at position arg_no and
297 * return the index of the next argument.
298 */
299int
300printllval(struct tcb *tcp, const char *format, int arg_no)
301{
302 unsigned long long val = 0;
303
304 arg_no = getllval(tcp, &val, arg_no);
305 tprintf(format, val);
306 return arg_no;
307}
308
309/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310 * Interpret `xlat' as an array of flags
311 * print the entries whose bits are on in `flags'
312 * return # of flags printed.
313 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200314void
Denys Vlasenko12014262011-05-30 14:00:14 +0200315addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200317 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318 if (xlat->val && (flags & xlat->val) == xlat->val) {
319 tprintf("|%s", xlat->str);
320 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 }
322 }
323 if (flags) {
324 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326}
327
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000328/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200329 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000330 * Print to static string the entries whose bits are on in `flags'
331 * Return static string.
332 */
333const char *
334sprintflags(const char *prefix, const struct xlat *xlat, int flags)
335{
336 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200337 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000338 int found = 0;
339
Denys Vlasenko52845572011-08-31 12:07:38 +0200340 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000341
342 for (; xlat->str; xlat++) {
343 if ((flags & xlat->val) == xlat->val) {
344 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200345 *outptr++ = '|';
346 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000347 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100348 flags &= ~xlat->val;
349 if (!flags)
350 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000351 }
352 }
353 if (flags) {
354 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200355 *outptr++ = '|';
356 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000357 }
358
359 return outstr;
360}
361
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000362int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000363printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364{
365 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000366 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000367
368 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200369 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370 return 1;
371 }
372
373 sep = "";
374 for (n = 0; xlat->str; xlat++) {
375 if (xlat->val && (flags & xlat->val) == xlat->val) {
376 tprintf("%s%s", sep, xlat->str);
377 flags &= ~xlat->val;
378 sep = "|";
379 n++;
380 }
381 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000382
383 if (n) {
384 if (flags) {
385 tprintf("%s%#x", sep, flags);
386 n++;
387 }
388 } else {
389 if (flags) {
390 tprintf("%#x", flags);
391 if (dflt)
392 tprintf(" /* %s */", dflt);
393 } else {
394 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200395 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000396 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000398
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000399 return n;
400}
401
402void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000403printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404{
Roland McGratheb285352003-01-14 09:59:00 +0000405 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000406
407 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200408 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 return;
410 }
411 if (umove(tcp, addr, &num) < 0) {
412 tprintf("%#lx", addr);
413 return;
414 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200415 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200417 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000418}
419
Roland McGrath6bc12202003-11-13 22:32:27 +0000420void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000421printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000422{
423 int num;
424
425 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200426 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000427 return;
428 }
429 if (umove(tcp, addr, &num) < 0) {
430 tprintf("%#lx", addr);
431 return;
432 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200433 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000434 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200435 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000436}
437
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000438const char *
439sprinttime(time_t t)
440{
441 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000442 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000443
444 if (t == 0) {
445 strcpy(buf, "0");
446 return buf;
447 }
448 tmp = localtime(&t);
449 if (tmp)
450 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
451 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
452 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
453 else
454 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
455
456 return buf;
457}
458
Masatake YAMATOf5480672014-11-22 19:03:33 +0900459static char *
460getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
461{
462#if HAVE_SYS_XATTR_H
463 ssize_t r;
464 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
465
466 if (fd < 0)
467 return NULL;
468
469 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
470 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
471 if (r <= 0)
472 return NULL;
473 else {
474 /*
475 * This is a protection for the case when the kernel
476 * side does not append a null byte to the buffer.
477 */
478 buf[r] = '\0';
479 return buf;
480 }
481#else
482 return NULL;
483#endif
484}
485
Roland McGrath9814a942005-07-04 23:28:10 +0000486void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300487printfd(struct tcb *tcp, int fd)
488{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100489 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000490 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
491 static const char socket_prefix[] = "socket:[";
492 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000493 const size_t path_len = strlen(path);
Grant Edwards8a082772011-04-07 20:25:40 +0000494
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000495 tprintf("%d<", fd);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000496 if (show_fd_path > 1 &&
497 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000498 path[path_len - 1] == ']') {
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000499 unsigned long inodenr;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900500#define PROTO_NAME_LEN 32
501 char proto_buf[PROTO_NAME_LEN];
502 const char *proto =
503 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000504 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900505 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900506 if (proto)
507 tprintf("%s:[%lu]", proto, inodenr);
508 else
509 tprints(path);
510 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000511 } else {
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000512 print_quoted_string(path, path_len,
513 QUOTE_OMIT_LEADING_TRAILING_QUOTES);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000514 }
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000515 tprints(">");
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000516 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000517 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300518}
519
Dmitry V. Levina501f142008-11-10 23:19:13 +0000520/*
521 * Quote string `instr' of length `size'
522 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100523 *
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000524 * If QUOTE_0_TERMINATED `style' flag is set,
525 * treat `instr' as a NUL-terminated string,
526 * checking up to (`size' + 1) bytes of `instr'.
527 *
528 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
529 * do not add leading and trailing quoting symbols.
530 *
531 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
532 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000533 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000534static int
535string_quote(const char *instr, char *outstr, const unsigned int size,
536 const unsigned int style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000538 const unsigned char *ustr = (const unsigned char *) instr;
539 char *s = outstr;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000540 unsigned int i;
541 int usehex, c, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000543 if (style & QUOTE_0_TERMINATED)
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200544 eol = '\0';
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000545 else
546 eol = 0x100; /* this can never match a char */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200547
548 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000549 if (xflag > 1)
550 usehex = 1;
551 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000552 /* Check for presence of symbol which require
553 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000554 for (i = 0; i < size; ++i) {
555 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000556 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200557 if (c == eol)
558 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100559
560 /* Force hex unless c is printable or whitespace */
561 if (c > 0x7e) {
562 usehex = 1;
563 break;
564 }
565 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
566 * They happen to have ASCII codes 9,10,11,12,13.
567 */
568 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000569 usehex = 1;
570 break;
571 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 }
573 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000575 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
576 *s++ = '\"';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000577
578 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000579 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000580 for (i = 0; i < size; ++i) {
581 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000582 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200583 if (c == eol)
584 goto asciz_ended;
585 *s++ = '\\';
586 *s++ = 'x';
587 *s++ = "0123456789abcdef"[c >> 4];
588 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000589 }
590 } else {
591 for (i = 0; i < size; ++i) {
592 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000593 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200594 if (c == eol)
595 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000596 switch (c) {
597 case '\"': case '\\':
598 *s++ = '\\';
599 *s++ = c;
600 break;
601 case '\f':
602 *s++ = '\\';
603 *s++ = 'f';
604 break;
605 case '\n':
606 *s++ = '\\';
607 *s++ = 'n';
608 break;
609 case '\r':
610 *s++ = '\\';
611 *s++ = 'r';
612 break;
613 case '\t':
614 *s++ = '\\';
615 *s++ = 't';
616 break;
617 case '\v':
618 *s++ = '\\';
619 *s++ = 'v';
620 break;
621 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100622 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000623 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200624 else {
625 /* Print \octal */
626 *s++ = '\\';
627 if (i + 1 < size
628 && ustr[i + 1] >= '0'
629 && ustr[i + 1] <= '9'
630 ) {
631 /* Print \ooo */
632 *s++ = '0' + (c >> 6);
633 *s++ = '0' + ((c >> 3) & 0x7);
634 } else {
635 /* Print \[[o]o]o */
636 if ((c >> 3) != 0) {
637 if ((c >> 6) != 0)
638 *s++ = '0' + (c >> 6);
639 *s++ = '0' + ((c >> 3) & 0x7);
640 }
641 }
642 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000643 }
644 break;
645 }
646 }
647 }
648
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000649 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
650 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000652
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200653 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000654 if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200655 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
656 * but next char is NUL.
657 */
658 return 0;
659 }
660
661 return 1;
662
663 asciz_ended:
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000664 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
665 *s++ = '\"';
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200666 *s = '\0';
667 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
668 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669}
670
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000671#ifndef ALLOCA_CUTOFF
672# define ALLOCA_CUTOFF 4032
673#endif
674#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
675
676/*
677 * Quote string `str' of length `size' and print the result.
678 *
679 * If QUOTE_0_TERMINATED `style' flag is set,
680 * treat `str' as a NUL-terminated string and
681 * quote at most (`size' - 1) bytes.
682 *
683 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
684 * do not add leading and trailing quoting symbols.
685 *
686 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
687 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
688 */
689int
690print_quoted_string(const char *str, unsigned int size,
691 const unsigned int style)
692{
693 char *buf;
694 char *outstr;
695 unsigned int alloc_size;
696 int rc;
697
698 if (size && style & QUOTE_0_TERMINATED)
699 --size;
700
701 alloc_size = 4 * size;
702 if (alloc_size / 4 != size) {
703 error_msg("Out of memory");
704 tprints("???");
705 return -1;
706 }
707 alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
708
709 if (use_alloca(alloc_size)) {
710 outstr = alloca(alloc_size);
711 buf = NULL;
712 } else {
713 outstr = buf = malloc(alloc_size);
714 if (!buf) {
715 error_msg("Out of memory");
716 tprints("???");
717 return -1;
718 }
719 }
720
721 rc = string_quote(str, outstr, size, style);
722 tprints(outstr);
723
724 free(buf);
725 return rc;
726}
727
Dmitry V. Levina501f142008-11-10 23:19:13 +0000728/*
729 * Print path string specified by address `addr' and length `n'.
730 * If path length exceeds `n', append `...' to the output.
731 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000733printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000735 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100736 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100737
Dmitry V. Levina501f142008-11-10 23:19:13 +0000738 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200739 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000740 return;
741 }
742
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100743 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000744 if (n > sizeof path - 1)
745 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000746
747 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100748 nul_seen = umovestr(tcp, addr, n + 1, path);
749 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750 tprintf("%#lx", addr);
751 else {
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000752 path[n++] = '\0';
753 print_quoted_string(path, n, QUOTE_0_TERMINATED);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100754 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100755 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 }
757}
758
759void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000760printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100762 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000763 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000764}
765
Dmitry V. Levina501f142008-11-10 23:19:13 +0000766/*
767 * Print string specified by address `addr' and length `len'.
768 * If `len' < 0, treat the string as a NUL-terminated string.
769 * If string length exceeds `max_strlen', append `...' to the output.
770 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000771void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200772printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000773{
774 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000775 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000776 unsigned int size;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000777 unsigned int style;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100778 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779
780 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200781 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 return;
783 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000784 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200785 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000786 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
787
788 if (outstr_size / 4 != max_strlen)
789 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000790 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200791 if (!str)
792 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000793 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200794 if (!outstr)
795 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000797
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000798 size = max_strlen;
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200799 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000800 /*
801 * Treat as a NUL-terminated string: fetch one byte more
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000802 * because string_quote may look one byte ahead.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000803 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000804 if (umovestr(tcp, addr, size + 1, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 tprintf("%#lx", addr);
806 return;
807 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000808 style = QUOTE_0_TERMINATED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000809 }
810 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200811 if (size > (unsigned long)len)
812 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000813 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 tprintf("%#lx", addr);
815 return;
816 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000817 style = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000818 }
819
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100820 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
821 * or we were requested to print more than -s NUM chars)...
822 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000823 ellipsis = (string_quote(str, outstr, size, style) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000824 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000825
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100826 tprints(outstr);
827 if (ellipsis)
828 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829}
830
John Hughes1d08dcf2001-07-10 13:48:44 +0000831void
Denys Vlasenko12014262011-05-30 14:00:14 +0200832dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000833{
Denys Vlasenko84703742012-02-25 02:38:52 +0100834#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000835 union {
836 struct { u_int32_t base; u_int32_t len; } *iov32;
837 struct { u_int64_t base; u_int64_t len; } *iov64;
838 } iovu;
839#define iov iovu.iov64
840#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100841 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000842#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100843 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000844#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100845 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000846#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000847 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000848#define sizeof_iov sizeof(*iov)
849#define iov_iov_base(i) iov[i].iov_base
850#define iov_iov_len(i) iov[i].iov_len
851#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000852 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200853 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000854
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200855 size = sizeof_iov * len;
856 /* Assuming no sane program has millions of iovs */
857 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000858 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200859 fprintf(stderr, "Out of memory\n");
860 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000861 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000862 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000863 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000864 /* include the buffer number to make it easy to
865 * match up the trace with the source */
866 tprintf(" * %lu bytes in buffer %d\n",
867 (unsigned long)iov_iov_len(i), i);
868 dumpstr(tcp, (long) iov_iov_base(i),
869 iov_iov_len(i));
870 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000871 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200872 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000873#undef sizeof_iov
874#undef iov_iov_base
875#undef iov_iov_len
876#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000877}
John Hughes1d08dcf2001-07-10 13:48:44 +0000878
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879void
Denys Vlasenko12014262011-05-30 14:00:14 +0200880dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881{
882 static int strsize = -1;
883 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000884
Denys Vlasenko76325802013-02-22 14:47:39 +0100885 char outbuf[
886 (
887 (sizeof(
888 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
889 "1234567890123456") + /*in case I'm off by few:*/ 4)
890 /*align to 8 to make memset easier:*/ + 7) & -8
891 ];
892 const unsigned char *src;
893 int i;
894
895 memset(outbuf, ' ', sizeof(outbuf));
896
897 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200898 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100899 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200900 if (!str) {
901 strsize = -1;
902 fprintf(stderr, "Out of memory\n");
903 return;
904 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100905 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000906 }
907
908 if (umoven(tcp, addr, len, (char *) str) < 0)
909 return;
910
Denys Vlasenko76325802013-02-22 14:47:39 +0100911 /* Space-pad to 16 bytes */
912 i = len;
913 while (i & 0xf)
914 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200915
Denys Vlasenko76325802013-02-22 14:47:39 +0100916 i = 0;
917 src = str;
918 while (i < len) {
919 char *dst = outbuf;
920 /* Hex dump */
921 do {
922 if (i < len) {
923 *dst++ = "0123456789abcdef"[*src >> 4];
924 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000925 }
926 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100927 *dst++ = ' ';
928 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000929 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100930 dst++; /* space is there by memset */
931 i++;
932 if ((i & 7) == 0)
933 dst++; /* space is there by memset */
934 src++;
935 } while (i & 0xf);
936 /* ASCII dump */
937 i -= 16;
938 src -= 16;
939 do {
940 if (*src >= ' ' && *src < 0x7f)
941 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100943 *dst++ = '.';
944 src++;
945 } while (++i & 0xf);
946 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100947 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 }
949}
950
Mike Frysinger612659e2012-02-14 14:38:28 +0100951#ifdef HAVE_PROCESS_VM_READV
952/* C library supports this, but the kernel might not. */
953static bool process_vm_readv_not_supported = 0;
954#else
955
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100956/* Need to do this since process_vm_readv() is not yet available in libc.
957 * When libc is be updated, only "static bool process_vm_readv_not_supported"
958 * line should remain.
959 */
960#if !defined(__NR_process_vm_readv)
961# if defined(I386)
962# define __NR_process_vm_readv 347
963# elif defined(X86_64)
964# define __NR_process_vm_readv 310
965# elif defined(POWERPC)
966# define __NR_process_vm_readv 351
967# endif
968#endif
969
970#if defined(__NR_process_vm_readv)
971static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400972/* Have to avoid duplicating with the C library headers. */
973static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100974 const struct iovec *lvec,
975 unsigned long liovcnt,
976 const struct iovec *rvec,
977 unsigned long riovcnt,
978 unsigned long flags)
979{
980 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
981}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400982#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100983#else
984static bool process_vm_readv_not_supported = 1;
985# define process_vm_readv(...) (errno = ENOSYS, -1)
986#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100987
988#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100989
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990#define PAGMASK (~(PAGSIZ - 1))
991/*
992 * move `len' bytes of data from process `pid'
993 * at address `addr' to our space at `laddr'
994 */
995int
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000996umoven(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700998 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000999 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 union {
1001 long val;
1002 char x[sizeof(long)];
1003 } u;
1004
Denys Vlasenko2544f982013-02-19 17:39:56 +01001005#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001006 if (current_wordsize < sizeof(addr))
1007 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +01001008#endif
1009
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001010 if (!process_vm_readv_not_supported) {
1011 struct iovec local[1], remote[1];
1012 int r;
1013
1014 local[0].iov_base = laddr;
1015 remote[0].iov_base = (void*)addr;
1016 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001017 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001018 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +01001019 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001020 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001021 error_msg("umoven: short read (%u < %u) @0x%lx",
1022 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001023 return -1;
1024 }
1025 switch (errno) {
1026 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001027 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001028 break;
1029 case ESRCH:
1030 /* the process is gone */
1031 return -1;
1032 case EFAULT: case EIO: case EPERM:
1033 /* address space is inaccessible */
1034 return -1;
1035 default:
1036 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001037 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +00001038 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001039 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001040 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001041
Dmitry V. Levin97005922013-02-26 21:16:22 +00001042 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001043 if (addr & (sizeof(long) - 1)) {
1044 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001045 n = addr & (sizeof(long) - 1); /* residue */
1046 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001047 errno = 0;
1048 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001049 switch (errno) {
1050 case 0:
1051 break;
1052 case ESRCH: case EINVAL:
1053 /* these could be seen if the process is gone */
1054 return -1;
1055 case EFAULT: case EIO: case EPERM:
1056 /* address space is inaccessible */
1057 return -1;
1058 default:
1059 /* all the rest is strange and should be reported */
1060 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1061 pid, addr);
1062 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001063 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001064 m = MIN(sizeof(long) - n, len);
1065 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001066 addr += sizeof(long);
1067 laddr += m;
1068 nread += m;
1069 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001070 }
1071 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001072 errno = 0;
1073 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001074 switch (errno) {
1075 case 0:
1076 break;
1077 case ESRCH: case EINVAL:
1078 /* these could be seen if the process is gone */
1079 return -1;
1080 case EFAULT: case EIO: case EPERM:
1081 /* address space is inaccessible */
1082 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001083 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001084 nread, nread + len, addr - nread);
1085 }
1086 return -1;
1087 default:
1088 /* all the rest is strange and should be reported */
1089 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1090 pid, addr);
1091 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001092 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001093 m = MIN(sizeof(long), len);
1094 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001095 addr += sizeof(long);
1096 laddr += m;
1097 nread += m;
1098 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 return 0;
1102}
1103
1104/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001105 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001107 *
1108 * Returns < 0 on error, > 0 if NUL was seen,
1109 * (TODO if useful: return count of bytes including NUL),
1110 * else 0 if len bytes were read but no NUL byte seen.
1111 *
1112 * Note: there is no guarantee we won't overwrite some bytes
1113 * in laddr[] _after_ terminating NUL (but, of course,
1114 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115 */
1116int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001117umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118{
Denys Vlasenko16940922013-03-01 18:52:59 +01001119#if SIZEOF_LONG == 4
1120 const unsigned long x01010101 = 0x01010101ul;
1121 const unsigned long x80808080 = 0x80808080ul;
1122#elif SIZEOF_LONG == 8
1123 const unsigned long x01010101 = 0x0101010101010101ul;
1124 const unsigned long x80808080 = 0x8080808080808080ul;
1125#else
1126# error SIZEOF_LONG > 8
1127#endif
1128
Roland McGratheb9e2e82009-06-02 16:49:22 -07001129 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001130 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001132 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 char x[sizeof(long)];
1134 } u;
1135
Denys Vlasenko2544f982013-02-19 17:39:56 +01001136#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001137 if (current_wordsize < sizeof(addr))
1138 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001139#endif
1140
Dmitry V. Levin97005922013-02-26 21:16:22 +00001141 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001142 if (!process_vm_readv_not_supported) {
1143 struct iovec local[1], remote[1];
1144
1145 local[0].iov_base = laddr;
1146 remote[0].iov_base = (void*)addr;
1147
1148 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001149 unsigned int chunk_len;
1150 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001151 int r;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001152
1153 /* Don't read kilobytes: most strings are short */
1154 chunk_len = len;
1155 if (chunk_len > 256)
1156 chunk_len = 256;
1157 /* Don't cross pages. I guess otherwise we can get EFAULT
1158 * and fail to notice that terminating NUL lies
1159 * in the existing (first) page.
1160 * (I hope there aren't arches with pages < 4K)
1161 */
1162 end_in_page = ((addr + chunk_len) & 4095);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001163 if (chunk_len > end_in_page) /* crosses to the next page */
1164 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001165
1166 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001167 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1168 if (r > 0) {
1169 if (memchr(local[0].iov_base, '\0', r))
1170 return 1;
1171 local[0].iov_base += r;
1172 remote[0].iov_base += r;
1173 len -= r;
1174 nread += r;
1175 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001176 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001177 switch (errno) {
1178 case ENOSYS:
1179 process_vm_readv_not_supported = 1;
1180 goto vm_readv_didnt_work;
1181 case ESRCH:
1182 /* the process is gone */
1183 return -1;
1184 case EFAULT: case EIO: case EPERM:
1185 /* address space is inaccessible */
1186 if (nread) {
1187 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1188 nread, nread + len, addr);
1189 }
1190 return -1;
1191 default:
1192 /* all the rest is strange and should be reported */
1193 perror_msg("process_vm_readv");
1194 return -1;
1195 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001196 }
1197 return 0;
1198 }
1199 vm_readv_didnt_work:
1200
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 if (addr & (sizeof(long) - 1)) {
1202 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001203 n = addr & (sizeof(long) - 1); /* residue */
1204 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001205 errno = 0;
1206 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001207 switch (errno) {
1208 case 0:
1209 break;
1210 case ESRCH: case EINVAL:
1211 /* these could be seen if the process is gone */
1212 return -1;
1213 case EFAULT: case EIO: case EPERM:
1214 /* address space is inaccessible */
1215 return -1;
1216 default:
1217 /* all the rest is strange and should be reported */
1218 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1219 pid, addr);
1220 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001221 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001222 m = MIN(sizeof(long) - n, len);
1223 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 while (n & (sizeof(long) - 1))
1225 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001226 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001227 addr += sizeof(long);
1228 laddr += m;
1229 nread += m;
1230 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001232
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001233 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001234 errno = 0;
1235 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001236 switch (errno) {
1237 case 0:
1238 break;
1239 case ESRCH: case EINVAL:
1240 /* these could be seen if the process is gone */
1241 return -1;
1242 case EFAULT: case EIO: case EPERM:
1243 /* address space is inaccessible */
1244 if (nread) {
1245 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1246 nread, nread + len, addr - nread);
1247 }
1248 return -1;
1249 default:
1250 /* all the rest is strange and should be reported */
1251 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1252 pid, addr);
1253 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001254 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001255 m = MIN(sizeof(long), len);
1256 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001257 /* "If a NUL char exists in this word" */
1258 if ((u.val - x01010101) & ~u.val & x80808080)
1259 return 1;
1260 addr += sizeof(long);
1261 laddr += m;
1262 nread += m;
1263 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001265 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266}
1267
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001269upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270{
1271 long val;
1272
Roland McGratheb9e2e82009-06-02 16:49:22 -07001273 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001274 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001275 if (val == -1 && errno) {
1276 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001277 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001278 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001280 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281 *res = val;
1282 return 0;
1283}
1284
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001285/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1286 * and PTRACE_O_TRACE[V]FORK for tracing children.
1287 * If you are adding a new arch which is only supported by newer kernels,
1288 * you most likely don't need to add any code below
1289 * beside a dummy "return 0" block in change_syscall().
1290 */
1291
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001292/*
1293 * These #if's are huge, please indent them correctly.
1294 * It's easy to get confused otherwise.
1295 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001297#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001298
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001299#ifndef CLONE_PTRACE
1300# define CLONE_PTRACE 0x00002000
1301#endif
1302#ifndef CLONE_VFORK
1303# define CLONE_VFORK 0x00004000
1304#endif
1305#ifndef CLONE_VM
1306# define CLONE_VM 0x00000100
1307#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001308
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001309#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310
1311typedef unsigned long *arg_setup_state;
1312
1313static int
1314arg_setup(struct tcb *tcp, arg_setup_state *state)
1315{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001316 unsigned long cfm, sof, sol;
1317 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001319 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001320 /* Satisfy a false GCC warning. */
1321 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001322 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001323 }
Roland McGrath08267b82004-02-20 22:56:43 +00001324
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001325 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001326 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001327 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001328 return -1;
1329
1330 sof = (cfm >> 0) & 0x7f;
1331 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001332 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001333
Jan Kratochvil1f942712008-08-06 21:38:52 +00001334 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001335 return 0;
1336}
1337
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001338# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001339
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001341get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001342{
Roland McGrath08267b82004-02-20 22:56:43 +00001343 int ret;
1344
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001345 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001346 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001347 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001348 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001349 (unsigned long) ia64_rse_skip_regs(*state, 0),
1350 sizeof(long), (void *) valp);
1351 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352}
1353
1354static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001355get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001356{
Roland McGrath08267b82004-02-20 22:56:43 +00001357 int ret;
1358
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001359 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001360 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001361 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001362 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001363 (unsigned long) ia64_rse_skip_regs(*state, 1),
1364 sizeof(long), (void *) valp);
1365 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001367
1368static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001369set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001370{
Roland McGrath08267b82004-02-20 22:56:43 +00001371 int req = PTRACE_POKEDATA;
1372 void *ap;
1373
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001374 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001375 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1376 req = PTRACE_POKEUSER;
1377 } else
1378 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001379 errno = 0;
1380 ptrace(req, tcp->pid, ap, val);
1381 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001382}
1383
1384static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001385set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001386{
Roland McGrath08267b82004-02-20 22:56:43 +00001387 int req = PTRACE_POKEDATA;
1388 void *ap;
1389
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001390 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001391 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1392 req = PTRACE_POKEUSER;
1393 } else
1394 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001395 errno = 0;
1396 ptrace(req, tcp->pid, ap, val);
1397 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001398}
1399
Roland McGrathb659f872008-07-18 01:19:36 +00001400/* ia64 does not return the input arguments from functions (and syscalls)
1401 according to ia64 RSE (Register Stack Engine) behavior. */
1402
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001403# define restore_arg0(tcp, state, val) ((void) (state), 0)
1404# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001405
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001406#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001408# if defined(SPARC64)
1409# undef PTRACE_GETREGS
1410# define PTRACE_GETREGS PTRACE_GETREGS64
1411# undef PTRACE_SETREGS
1412# define PTRACE_SETREGS PTRACE_SETREGS64
1413# endif
1414
Mike Frysinger8566c502009-10-12 11:05:14 -04001415typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001416
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001417# define arg_setup(tcp, state) \
1418 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1419# define arg_finish_change(tcp, state) \
1420 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001421
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001422# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1423# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1424# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1425# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1426# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001428#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001429
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001430# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001431/* Note: this is only true for the `clone' system call, which handles
1432 arguments specially. We could as well say that its first two arguments
1433 are swapped relative to other architectures, but that would just be
1434 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001435# define arg0_offset PT_GPR3
1436# define arg1_offset PT_ORIGGPR2
1437# define restore_arg0(tcp, state, val) ((void) (state), 0)
1438# define restore_arg1(tcp, state, val) ((void) (state), 0)
1439# define arg0_index 1
1440# define arg1_index 0
1441# elif defined(ALPHA) || defined(MIPS)
1442# define arg0_offset REG_A0
1443# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001444# elif defined(POWERPC)
1445# define arg0_offset (sizeof(unsigned long)*PT_R3)
1446# define arg1_offset (sizeof(unsigned long)*PT_R4)
1447# define restore_arg0(tcp, state, val) ((void) (state), 0)
1448# elif defined(HPPA)
1449# define arg0_offset PT_GR26
1450# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001451# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001452# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1453# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1454# elif defined(SH)
1455# define arg0_offset (4*(REG_REG0+4))
1456# define arg1_offset (4*(REG_REG0+5))
1457# elif defined(SH64)
1458 /* ABI defines arg0 & 1 in r2 & r3 */
1459# define arg0_offset (REG_OFFSET+16)
1460# define arg1_offset (REG_OFFSET+24)
1461# define restore_arg0(tcp, state, val) 0
1462# elif defined CRISV10 || defined CRISV32
1463# define arg0_offset (4*PT_R11)
1464# define arg1_offset (4*PT_ORIG_R10)
1465# define restore_arg0(tcp, state, val) 0
1466# define restore_arg1(tcp, state, val) 0
1467# define arg0_index 1
1468# define arg1_index 0
1469# else
1470# define arg0_offset 0
1471# define arg1_offset 4
1472# if defined ARM
1473# define restore_arg0(tcp, state, val) 0
1474# endif
1475# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001476
1477typedef int arg_setup_state;
1478
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001479# define arg_setup(tcp, state) (0)
1480# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001481# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1482# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483
1484static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001485set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001486{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001487 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001488}
1489
1490static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001491set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001492{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001494}
1495
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001496#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001497
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001498#ifndef restore_arg0
1499# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1500#endif
1501#ifndef restore_arg1
1502# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1503#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001504
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001505#ifndef arg0_index
1506# define arg0_index 0
1507# define arg1_index 1
1508#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001509
James Hogan05eb9052012-11-29 17:37:37 +00001510static int
1511change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1512{
1513#if defined(I386)
1514 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1515 return -1;
1516 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001517#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001518 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1519 return -1;
1520 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001521#elif defined(X32)
1522 /* setbpt/clearbpt never used: */
1523 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001524#elif defined(POWERPC)
1525 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1526 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1527 return -1;
1528 return 0;
1529#elif defined(S390) || defined(S390X)
1530 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1531 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1532 return -1;
1533 return 0;
1534#elif defined(M68K)
1535 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1536 return -1;
1537 return 0;
1538#elif defined(SPARC) || defined(SPARC64)
1539 state->u_regs[U_REG_G1] = new;
1540 return 0;
1541#elif defined(MIPS)
1542 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1543 return -1;
1544 return 0;
1545#elif defined(ALPHA)
1546 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1547 return -1;
1548 return 0;
1549#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001550 /* setbpt/clearbpt never used: */
1551 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001552#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001553 /* setbpt/clearbpt never used: */
1554 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001555#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001556 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001557 switch (new) {
1558 case 2:
1559 break; /* x86 SYS_fork */
1560 case SYS_clone:
1561 new = 120;
1562 break;
1563 default:
1564 fprintf(stderr, "%s: unexpected syscall %d\n",
1565 __FUNCTION__, new);
1566 return -1;
1567 }
1568 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1569 return -1;
1570 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1571 return -1;
1572 return 0;
1573#elif defined(HPPA)
1574 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1575 return -1;
1576 return 0;
1577#elif defined(SH)
1578 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1579 return -1;
1580 return 0;
1581#elif defined(SH64)
1582 /* Top half of reg encodes the no. of args n as 0x1n.
1583 Assume 0 args as kernel never actually checks... */
1584 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1585 0x100000 | new) < 0)
1586 return -1;
1587 return 0;
1588#elif defined(CRISV10) || defined(CRISV32)
1589 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1590 return -1;
1591 return 0;
1592#elif defined(ARM)
1593 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1594# ifndef PTRACE_SET_SYSCALL
1595# define PTRACE_SET_SYSCALL 23
1596# endif
1597 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1598 return -1;
1599 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001600#elif defined(AARCH64)
1601 /* setbpt/clearbpt never used: */
1602 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001603#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001604 /* setbpt/clearbpt never used: */
1605 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001606#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001607 /* setbpt/clearbpt never used: */
1608 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001609#elif defined(OR1K)
1610 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001611#elif defined(METAG)
1612 /* setbpt/clearbpt never used: */
1613 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001614#elif defined(XTENSA)
1615 /* setbpt/clearbpt never used: */
1616 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301617#elif defined(ARC)
1618 /* setbpt/clearbpt never used: */
1619 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001620#else
1621#warning Do not know how to handle change_syscall for this architecture
1622#endif /* architecture */
1623 return -1;
1624}
1625
Roland McGrathd81f1d92003-01-09 06:53:34 +00001626int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001627setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001628{
Roland McGrath3291ef22008-05-20 00:34:34 +00001629 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001630 arg_setup_state state;
1631
1632 if (tcp->flags & TCB_BPTSET) {
1633 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1634 return -1;
1635 }
1636
Roland McGrath3291ef22008-05-20 00:34:34 +00001637 /*
1638 * It's a silly kludge to initialize this with a search at runtime.
1639 * But it's better than maintaining another magic thing in the
1640 * godforsaken tables.
1641 */
1642 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001643 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001644 for (i = 0; i < nsyscalls; ++i)
1645 if (sysent[i].sys_func == sys_clone) {
1646 clone_scno[current_personality] = i;
1647 break;
1648 }
1649 }
1650
Dmitry V. Levin65563152014-05-12 13:43:10 +00001651 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001652 if (arg_setup(tcp, &state) < 0
1653 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1654 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001655 || change_syscall(tcp, &state,
1656 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001657 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1658 || set_arg1(tcp, &state, 0) < 0
1659 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001660 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001661 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1662 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001663 tcp->flags |= TCB_BPTSET;
1664 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001665 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001666
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001667 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001668 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001669 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001670 vfork semantics into plain fork - each application must not
1671 depend on the vfork specifics according to POSIX. We would
1672 hang waiting for the parent resume otherwise. We need to
1673 clear also CLONE_VM but only in the CLONE_VFORK case as
1674 otherwise we would break pthread_create. */
1675
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001676 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1677 if (new_arg0 & CLONE_VFORK)
1678 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1679 if (arg_setup(tcp, &state) < 0
1680 || set_arg0(tcp, &state, new_arg0) < 0
1681 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001682 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001683 tcp->inst[0] = tcp->u_arg[arg0_index];
1684 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001685 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001686 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001687 }
1688
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001689 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1690 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001691 return -1;
1692}
1693
1694int
Denys Vlasenko12014262011-05-30 14:00:14 +02001695clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001696{
1697 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001698 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001699 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001700 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1701 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1702 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001703 if (errno != ESRCH)
1704 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001705 tcp->flags &= ~TCB_BPTSET;
1706 return 0;
1707}