blob: c96ccdacbf81c58e6ca62575692043e68284260c [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
Dmitry V. Levinfadf3792015-02-13 00:26:38 +000052#include "ptrace.h"
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000053
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000054int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000055string_to_uint(const char *str)
56{
57 char *error;
58 long value;
59
60 if (!*str)
61 return -1;
62 errno = 0;
63 value = strtol(str, &error, 10);
64 if (errno || *error || value < 0 || (long)(int)value != value)
65 return -1;
66 return (int)value;
67}
68
69int
Dmitry V. Levin447db452014-05-29 17:59:01 +000070tv_nz(const struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071{
72 return a->tv_sec || a->tv_usec;
73}
74
75int
Dmitry V. Levin447db452014-05-29 17:59:01 +000076tv_cmp(const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077{
78 if (a->tv_sec < b->tv_sec
79 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
80 return -1;
81 if (a->tv_sec > b->tv_sec
82 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
83 return 1;
84 return 0;
85}
86
87double
Dmitry V. Levin447db452014-05-29 17:59:01 +000088tv_float(const struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089{
90 return tv->tv_sec + tv->tv_usec/1000000.0;
91}
92
93void
Dmitry V. Levin447db452014-05-29 17:59:01 +000094tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095{
96 tv->tv_sec = a->tv_sec + b->tv_sec;
97 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +000098 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099 tv->tv_sec++;
100 tv->tv_usec -= 1000000;
101 }
102}
103
104void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000105tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106{
107 tv->tv_sec = a->tv_sec - b->tv_sec;
108 tv->tv_usec = a->tv_usec - b->tv_usec;
109 if (((long) tv->tv_usec) < 0) {
110 tv->tv_sec--;
111 tv->tv_usec += 1000000;
112 }
113}
114
115void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000116tv_div(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117{
118 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
119 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
120 tv->tv_usec %= 1000000;
121}
122
123void
Dmitry V. Levin447db452014-05-29 17:59:01 +0000124tv_mul(struct timeval *tv, const struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125{
126 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000127 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128 tv->tv_usec %= 1000000;
129}
130
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000131const char *
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000132xlookup(const struct xlat *xlat, const unsigned int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133{
134 for (; xlat->str != NULL; xlat++)
135 if (xlat->val == val)
136 return xlat->str;
137 return NULL;
138}
139
Dmitry V. Levin4176d532014-09-21 22:42:45 +0000140static int
141xlat_bsearch_compare(const void *a, const void *b)
142{
143 const unsigned int val1 = (const unsigned long) a;
144 const unsigned int val2 = ((const struct xlat *) b)->val;
145 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
146}
147
148const char *
149xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned int val)
150{
151 const struct xlat *e =
152 bsearch((const void*) (const unsigned long) val,
153 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
154
155 return e ? e->str : NULL;
156}
157
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200158#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200159char *
160stpcpy(char *dst, const char *src)
161{
162 while ((*dst = *src++) != '\0')
163 dst++;
164 return dst;
165}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200166#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200167
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100168/* Find a next bit which is set.
169 * Starts testing at cur_bit.
170 * Returns -1 if no more bits are set.
171 *
172 * We never touch bytes we don't need to.
173 * On big-endian, array is assumed to consist of
174 * current_wordsize wide words: for example, is current_wordsize is 4,
175 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
176 * On little-endian machines, word size is immaterial.
177 */
178int
179next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
180{
181 const unsigned endian = 1;
182 int little_endian = *(char*)&endian;
183
184 const uint8_t *array = bit_array;
185 unsigned pos = cur_bit / 8;
186 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
187
188 for (;;) {
189 uint8_t bitmask;
190 uint8_t cur_byte;
191
192 if (cur_bit >= size_bits)
193 return -1;
194 cur_byte = array[pos ^ pos_xor_mask];
195 if (cur_byte == 0) {
196 cur_bit = (cur_bit + 8) & (-8);
197 pos++;
198 continue;
199 }
200 bitmask = 1 << (cur_bit & 7);
201 for (;;) {
202 if (cur_byte & bitmask)
203 return cur_bit;
204 cur_bit++;
205 if (cur_bit >= size_bits)
206 return -1;
207 bitmask <<= 1;
208 /* This check *can't be* optimized out: */
209 if (bitmask == 0)
210 break;
211 }
212 pos++;
213 }
214}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215/*
216 * Print entry in struct xlat table, if there.
217 */
218void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000219printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000220{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000221 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000222
223 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200224 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000225 else
226 tprintf("%#x /* %s */", val, dflt);
227}
228
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100229/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000230 * Fetch 64bit argument at position arg_no and
231 * return the index of the next argument.
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100232 */
233int
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000234getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100235{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000236#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
237# if SUPPORTED_PERSONALITIES > 1
238 if (current_wordsize > 4) {
239# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000240 *val = tcp->u_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100241 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000242# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100243 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000244# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000245 /* Align arg_no to the next even number. */
246 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000247# endif /* AARCH64 || POWERPC64 */
248 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100249 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100250 }
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000251# endif /* SUPPORTED_PERSONALITIES > 1 */
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000252#elif SIZEOF_LONG > 4
253# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
254#elif defined LINUX_MIPSN32
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000255 *val = tcp->ext_arg[arg_no];
Chris Metcalf879dddd2013-03-01 10:41:02 +0100256 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000257#elif defined X32
258 if (current_personality == 0) {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000259 *val = tcp->ext_arg[arg_no];
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000260 arg_no++;
261 } else {
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000262 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000263 arg_no += 2;
264 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100265#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000266# if defined __ARM_EABI__ || \
267 defined LINUX_MIPSO32 || \
268 defined POWERPC || \
269 defined XTENSA
Dmitry V. Levin3c49b022014-08-07 00:07:28 +0000270 /* Align arg_no to the next even number. */
271 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000272# endif
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000273 *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100274 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100275#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000276
Chris Metcalf879dddd2013-03-01 10:41:02 +0100277 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100278}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100279
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000280/*
Dmitry V. Levin1ea64732015-01-10 00:08:58 +0000281 * Print 64bit argument at position arg_no and
282 * return the index of the next argument.
283 */
284int
285printllval(struct tcb *tcp, const char *format, int arg_no)
286{
287 unsigned long long val = 0;
288
289 arg_no = getllval(tcp, &val, arg_no);
290 tprintf(format, val);
291 return arg_no;
292}
293
294/*
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295 * Interpret `xlat' as an array of flags
296 * print the entries whose bits are on in `flags'
297 * return # of flags printed.
298 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200299void
Denys Vlasenko12014262011-05-30 14:00:14 +0200300addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200302 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000303 if (xlat->val && (flags & xlat->val) == xlat->val) {
304 tprintf("|%s", xlat->str);
305 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000306 }
307 }
308 if (flags) {
309 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311}
312
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000313/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200314 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000315 * Print to static string the entries whose bits are on in `flags'
316 * Return static string.
317 */
318const char *
319sprintflags(const char *prefix, const struct xlat *xlat, int flags)
320{
321 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200322 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000323 int found = 0;
324
Denys Vlasenko52845572011-08-31 12:07:38 +0200325 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000326
327 for (; xlat->str; xlat++) {
328 if ((flags & xlat->val) == xlat->val) {
329 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200330 *outptr++ = '|';
331 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000332 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100333 flags &= ~xlat->val;
334 if (!flags)
335 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000336 }
337 }
338 if (flags) {
339 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200340 *outptr++ = '|';
341 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000342 }
343
344 return outstr;
345}
346
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000347int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000348printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000349{
350 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000351 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352
353 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200354 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000355 return 1;
356 }
357
358 sep = "";
359 for (n = 0; xlat->str; xlat++) {
360 if (xlat->val && (flags & xlat->val) == xlat->val) {
361 tprintf("%s%s", sep, xlat->str);
362 flags &= ~xlat->val;
363 sep = "|";
364 n++;
365 }
366 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000367
368 if (n) {
369 if (flags) {
370 tprintf("%s%#x", sep, flags);
371 n++;
372 }
373 } else {
374 if (flags) {
375 tprintf("%#x", flags);
376 if (dflt)
377 tprintf(" /* %s */", dflt);
378 } else {
379 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200380 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000381 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000383
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384 return n;
385}
386
387void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000388printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389{
Roland McGratheb285352003-01-14 09:59:00 +0000390 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391
392 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200393 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 return;
395 }
396 if (umove(tcp, addr, &num) < 0) {
397 tprintf("%#lx", addr);
398 return;
399 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200400 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000401 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200402 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403}
404
Roland McGrath6bc12202003-11-13 22:32:27 +0000405void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000406printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000407{
408 int num;
409
410 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200411 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000412 return;
413 }
414 if (umove(tcp, addr, &num) < 0) {
415 tprintf("%#lx", addr);
416 return;
417 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200418 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000419 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200420 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000421}
422
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000423const char *
424sprinttime(time_t t)
425{
426 struct tm *tmp;
Dmitry V. Levind4a9d832015-01-08 15:08:16 +0000427 static char buf[sizeof(int) * 3 * 6];
Dmitry V. Levinb1a01b82014-12-06 03:53:16 +0000428
429 if (t == 0) {
430 strcpy(buf, "0");
431 return buf;
432 }
433 tmp = localtime(&t);
434 if (tmp)
435 snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
436 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
437 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
438 else
439 snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
440
441 return buf;
442}
443
Masatake YAMATOf5480672014-11-22 19:03:33 +0900444static char *
445getfdproto(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
446{
447#if HAVE_SYS_XATTR_H
448 ssize_t r;
449 char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
450
451 if (fd < 0)
452 return NULL;
453
454 sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
455 r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
456 if (r <= 0)
457 return NULL;
458 else {
459 /*
460 * This is a protection for the case when the kernel
461 * side does not append a null byte to the buffer.
462 */
463 buf[r] = '\0';
464 return buf;
465 }
466#else
467 return NULL;
468#endif
469}
470
Roland McGrath9814a942005-07-04 23:28:10 +0000471void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300472printfd(struct tcb *tcp, int fd)
473{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100474 char path[PATH_MAX + 1];
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000475 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
476 static const char socket_prefix[] = "socket:[";
477 const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000478 const size_t path_len = strlen(path);
Grant Edwards8a082772011-04-07 20:25:40 +0000479
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000480 tprintf("%d<", fd);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000481 if (show_fd_path > 1 &&
482 strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000483 path[path_len - 1] == ']') {
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000484 unsigned long inodenr;
Masatake YAMATOf605e922014-12-10 12:55:06 +0900485#define PROTO_NAME_LEN 32
486 char proto_buf[PROTO_NAME_LEN];
487 const char *proto =
488 getfdproto(tcp, fd, proto_buf, PROTO_NAME_LEN);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000489 inodenr = strtoul(path + socket_prefix_len, NULL, 10);
Masatake YAMATOf605e922014-12-10 12:55:06 +0900490 if (!print_sockaddr_by_inode(inodenr, proto)) {
Masatake YAMATOf5480672014-11-22 19:03:33 +0900491 if (proto)
492 tprintf("%s:[%lu]", proto, inodenr);
493 else
494 tprints(path);
495 }
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000496 } else {
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000497 print_quoted_string(path, path_len,
498 QUOTE_OMIT_LEADING_TRAILING_QUOTES);
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000499 }
Dmitry V. Levinc7235992015-01-24 19:51:39 +0000500 tprints(">");
Dmitry V. Levin2f6510c2014-08-21 03:17:48 +0000501 } else
Grant Edwards8a082772011-04-07 20:25:40 +0000502 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300503}
504
Dmitry V. Levina501f142008-11-10 23:19:13 +0000505/*
506 * Quote string `instr' of length `size'
507 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100508 *
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000509 * If QUOTE_0_TERMINATED `style' flag is set,
510 * treat `instr' as a NUL-terminated string,
511 * checking up to (`size' + 1) bytes of `instr'.
512 *
513 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
514 * do not add leading and trailing quoting symbols.
515 *
516 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
517 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000518 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000519static int
520string_quote(const char *instr, char *outstr, const unsigned int size,
521 const unsigned int style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000523 const unsigned char *ustr = (const unsigned char *) instr;
524 char *s = outstr;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000525 unsigned int i;
526 int usehex, c, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000528 if (style & QUOTE_0_TERMINATED)
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200529 eol = '\0';
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000530 else
531 eol = 0x100; /* this can never match a char */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200532
533 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000534 if (xflag > 1)
535 usehex = 1;
536 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000537 /* Check for presence of symbol which require
538 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000539 for (i = 0; i < size; ++i) {
540 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000541 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200542 if (c == eol)
543 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100544
545 /* Force hex unless c is printable or whitespace */
546 if (c > 0x7e) {
547 usehex = 1;
548 break;
549 }
550 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
551 * They happen to have ASCII codes 9,10,11,12,13.
552 */
553 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000554 usehex = 1;
555 break;
556 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557 }
558 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000559
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000560 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
561 *s++ = '\"';
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000562
563 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000564 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000565 for (i = 0; i < size; ++i) {
566 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000567 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200568 if (c == eol)
569 goto asciz_ended;
570 *s++ = '\\';
571 *s++ = 'x';
572 *s++ = "0123456789abcdef"[c >> 4];
573 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000574 }
575 } else {
576 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;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000581 switch (c) {
582 case '\"': case '\\':
583 *s++ = '\\';
584 *s++ = c;
585 break;
586 case '\f':
587 *s++ = '\\';
588 *s++ = 'f';
589 break;
590 case '\n':
591 *s++ = '\\';
592 *s++ = 'n';
593 break;
594 case '\r':
595 *s++ = '\\';
596 *s++ = 'r';
597 break;
598 case '\t':
599 *s++ = '\\';
600 *s++ = 't';
601 break;
602 case '\v':
603 *s++ = '\\';
604 *s++ = 'v';
605 break;
606 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100607 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000608 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200609 else {
610 /* Print \octal */
611 *s++ = '\\';
612 if (i + 1 < size
613 && ustr[i + 1] >= '0'
614 && ustr[i + 1] <= '9'
615 ) {
616 /* Print \ooo */
617 *s++ = '0' + (c >> 6);
618 *s++ = '0' + ((c >> 3) & 0x7);
619 } else {
620 /* Print \[[o]o]o */
621 if ((c >> 3) != 0) {
622 if ((c >> 6) != 0)
623 *s++ = '0' + (c >> 6);
624 *s++ = '0' + ((c >> 3) & 0x7);
625 }
626 }
627 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000628 }
629 break;
630 }
631 }
632 }
633
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000634 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
635 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000636 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000637
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200638 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000639 if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200640 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
641 * but next char is NUL.
642 */
643 return 0;
644 }
645
646 return 1;
647
648 asciz_ended:
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000649 if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
650 *s++ = '\"';
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200651 *s = '\0';
652 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
653 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000654}
655
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000656#ifndef ALLOCA_CUTOFF
657# define ALLOCA_CUTOFF 4032
658#endif
659#define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
660
661/*
662 * Quote string `str' of length `size' and print the result.
663 *
664 * If QUOTE_0_TERMINATED `style' flag is set,
665 * treat `str' as a NUL-terminated string and
666 * quote at most (`size' - 1) bytes.
667 *
668 * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
669 * do not add leading and trailing quoting symbols.
670 *
671 * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
672 * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
673 */
674int
675print_quoted_string(const char *str, unsigned int size,
676 const unsigned int style)
677{
678 char *buf;
679 char *outstr;
680 unsigned int alloc_size;
681 int rc;
682
683 if (size && style & QUOTE_0_TERMINATED)
684 --size;
685
686 alloc_size = 4 * size;
687 if (alloc_size / 4 != size) {
688 error_msg("Out of memory");
689 tprints("???");
690 return -1;
691 }
692 alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
693
694 if (use_alloca(alloc_size)) {
695 outstr = alloca(alloc_size);
696 buf = NULL;
697 } else {
698 outstr = buf = malloc(alloc_size);
699 if (!buf) {
700 error_msg("Out of memory");
701 tprints("???");
702 return -1;
703 }
704 }
705
706 rc = string_quote(str, outstr, size, style);
707 tprints(outstr);
708
709 free(buf);
710 return rc;
711}
712
Dmitry V. Levina501f142008-11-10 23:19:13 +0000713/*
714 * Print path string specified by address `addr' and length `n'.
715 * If path length exceeds `n', append `...' to the output.
716 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717void
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000718printpathn(struct tcb *tcp, long addr, unsigned int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719{
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000720 char path[PATH_MAX + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100721 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100722
Dmitry V. Levina501f142008-11-10 23:19:13 +0000723 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200724 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000725 return;
726 }
727
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100728 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000729 if (n > sizeof path - 1)
730 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000731
732 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100733 nul_seen = umovestr(tcp, addr, n + 1, path);
734 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 tprintf("%#lx", addr);
736 else {
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000737 path[n++] = '\0';
738 print_quoted_string(path, n, QUOTE_0_TERMINATED);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100739 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100740 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000741 }
742}
743
744void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000745printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100747 /* Size must correspond to char path[] size in printpathn */
Dmitry V. Levin025b3582014-11-21 22:28:34 +0000748 printpathn(tcp, addr, PATH_MAX);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000749}
750
Dmitry V. Levina501f142008-11-10 23:19:13 +0000751/*
752 * Print string specified by address `addr' and length `len'.
753 * If `len' < 0, treat the string as a NUL-terminated string.
754 * If string length exceeds `max_strlen', append `...' to the output.
755 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000756void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200757printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000758{
759 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 static char *outstr;
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000761 unsigned int size;
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000762 unsigned int style;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100763 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000764
765 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200766 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 return;
768 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000769 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200770 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000771 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
772
773 if (outstr_size / 4 != max_strlen)
774 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000775 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200776 if (!str)
777 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000778 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200779 if (!outstr)
780 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000782
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000783 size = max_strlen;
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200784 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000785 /*
786 * Treat as a NUL-terminated string: fetch one byte more
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000787 * because string_quote may look one byte ahead.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000788 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000789 if (umovestr(tcp, addr, size + 1, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000790 tprintf("%#lx", addr);
791 return;
792 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000793 style = QUOTE_0_TERMINATED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000794 }
795 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200796 if (size > (unsigned long)len)
797 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000798 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 tprintf("%#lx", addr);
800 return;
801 }
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000802 style = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 }
804
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100805 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
806 * or we were requested to print more than -s NUM chars)...
807 */
Dmitry V. Levin513e96e2015-01-26 01:17:08 +0000808 ellipsis = (string_quote(str, outstr, size, style) &&
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +0000809 (len < 0 || (unsigned long) len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000810
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100811 tprints(outstr);
812 if (ellipsis)
813 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814}
815
John Hughes1d08dcf2001-07-10 13:48:44 +0000816void
Denys Vlasenko12014262011-05-30 14:00:14 +0200817dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000818{
Denys Vlasenko84703742012-02-25 02:38:52 +0100819#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000820 union {
821 struct { u_int32_t base; u_int32_t len; } *iov32;
822 struct { u_int64_t base; u_int64_t len; } *iov64;
823 } iovu;
824#define iov iovu.iov64
825#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100826 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000827#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100828 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000829#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100830 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000831#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000832 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000833#define sizeof_iov sizeof(*iov)
834#define iov_iov_base(i) iov[i].iov_base
835#define iov_iov_len(i) iov[i].iov_len
836#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000837 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200838 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000839
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200840 size = sizeof_iov * len;
841 /* Assuming no sane program has millions of iovs */
842 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000843 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200844 fprintf(stderr, "Out of memory\n");
845 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000846 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000847 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000848 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000849 /* include the buffer number to make it easy to
850 * match up the trace with the source */
851 tprintf(" * %lu bytes in buffer %d\n",
852 (unsigned long)iov_iov_len(i), i);
853 dumpstr(tcp, (long) iov_iov_base(i),
854 iov_iov_len(i));
855 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000856 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200857 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000858#undef sizeof_iov
859#undef iov_iov_base
860#undef iov_iov_len
861#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000862}
John Hughes1d08dcf2001-07-10 13:48:44 +0000863
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000864void
Denys Vlasenko12014262011-05-30 14:00:14 +0200865dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000866{
867 static int strsize = -1;
868 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000869
Denys Vlasenko76325802013-02-22 14:47:39 +0100870 char outbuf[
871 (
872 (sizeof(
873 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
874 "1234567890123456") + /*in case I'm off by few:*/ 4)
875 /*align to 8 to make memset easier:*/ + 7) & -8
876 ];
877 const unsigned char *src;
878 int i;
879
880 memset(outbuf, ' ', sizeof(outbuf));
881
882 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200883 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100884 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200885 if (!str) {
886 strsize = -1;
887 fprintf(stderr, "Out of memory\n");
888 return;
889 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100890 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000891 }
892
893 if (umoven(tcp, addr, len, (char *) str) < 0)
894 return;
895
Denys Vlasenko76325802013-02-22 14:47:39 +0100896 /* Space-pad to 16 bytes */
897 i = len;
898 while (i & 0xf)
899 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200900
Denys Vlasenko76325802013-02-22 14:47:39 +0100901 i = 0;
902 src = str;
903 while (i < len) {
904 char *dst = outbuf;
905 /* Hex dump */
906 do {
907 if (i < len) {
908 *dst++ = "0123456789abcdef"[*src >> 4];
909 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 }
911 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100912 *dst++ = ' ';
913 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000914 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100915 dst++; /* space is there by memset */
916 i++;
917 if ((i & 7) == 0)
918 dst++; /* space is there by memset */
919 src++;
920 } while (i & 0xf);
921 /* ASCII dump */
922 i -= 16;
923 src -= 16;
924 do {
925 if (*src >= ' ' && *src < 0x7f)
926 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000927 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100928 *dst++ = '.';
929 src++;
930 } while (++i & 0xf);
931 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100932 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 }
934}
935
Mike Frysinger612659e2012-02-14 14:38:28 +0100936#ifdef HAVE_PROCESS_VM_READV
937/* C library supports this, but the kernel might not. */
938static bool process_vm_readv_not_supported = 0;
939#else
940
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100941/* Need to do this since process_vm_readv() is not yet available in libc.
942 * When libc is be updated, only "static bool process_vm_readv_not_supported"
943 * line should remain.
944 */
945#if !defined(__NR_process_vm_readv)
946# if defined(I386)
947# define __NR_process_vm_readv 347
948# elif defined(X86_64)
949# define __NR_process_vm_readv 310
950# elif defined(POWERPC)
951# define __NR_process_vm_readv 351
952# endif
953#endif
954
955#if defined(__NR_process_vm_readv)
956static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400957/* Have to avoid duplicating with the C library headers. */
958static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100959 const struct iovec *lvec,
960 unsigned long liovcnt,
961 const struct iovec *rvec,
962 unsigned long riovcnt,
963 unsigned long flags)
964{
965 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
966}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400967#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100968#else
969static bool process_vm_readv_not_supported = 1;
970# define process_vm_readv(...) (errno = ENOSYS, -1)
971#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100972
973#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100974
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975#define PAGMASK (~(PAGSIZ - 1))
976/*
977 * move `len' bytes of data from process `pid'
978 * at address `addr' to our space at `laddr'
979 */
980int
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000981umoven(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700983 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +0000984 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 union {
986 long val;
987 char x[sizeof(long)];
988 } u;
989
Denys Vlasenko2544f982013-02-19 17:39:56 +0100990#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100991 if (current_wordsize < sizeof(addr))
992 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100993#endif
994
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100995 if (!process_vm_readv_not_supported) {
996 struct iovec local[1], remote[1];
997 int r;
998
999 local[0].iov_base = laddr;
1000 remote[0].iov_base = (void*)addr;
1001 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001002 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001003 if ((unsigned int) r == len)
Ben Noordhuis1d58fe92013-02-26 12:24:25 +01001004 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001005 if (r >= 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001006 error_msg("umoven: short read (%u < %u) @0x%lx",
1007 (unsigned int) r, len, addr);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001008 return -1;
1009 }
1010 switch (errno) {
1011 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001012 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001013 break;
1014 case ESRCH:
1015 /* the process is gone */
1016 return -1;
1017 case EFAULT: case EIO: case EPERM:
1018 /* address space is inaccessible */
1019 return -1;
1020 default:
1021 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001022 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +00001023 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001024 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001025 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001026
Dmitry V. Levin97005922013-02-26 21:16:22 +00001027 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 if (addr & (sizeof(long) - 1)) {
1029 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001030 n = addr & (sizeof(long) - 1); /* residue */
1031 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001032 errno = 0;
1033 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001034 switch (errno) {
1035 case 0:
1036 break;
1037 case ESRCH: case EINVAL:
1038 /* these could be seen if the process is gone */
1039 return -1;
1040 case EFAULT: case EIO: case EPERM:
1041 /* address space is inaccessible */
1042 return -1;
1043 default:
1044 /* all the rest is strange and should be reported */
1045 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1046 pid, addr);
1047 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001048 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001049 m = MIN(sizeof(long) - n, len);
1050 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001051 addr += sizeof(long);
1052 laddr += m;
1053 nread += m;
1054 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 }
1056 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001057 errno = 0;
1058 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001059 switch (errno) {
1060 case 0:
1061 break;
1062 case ESRCH: case EINVAL:
1063 /* these could be seen if the process is gone */
1064 return -1;
1065 case EFAULT: case EIO: case EPERM:
1066 /* address space is inaccessible */
1067 if (nread) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001068 perror_msg("umoven: short read (%u < %u) @0x%lx",
Dmitry V. Levin97005922013-02-26 21:16:22 +00001069 nread, nread + len, addr - nread);
1070 }
1071 return -1;
1072 default:
1073 /* all the rest is strange and should be reported */
1074 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
1075 pid, addr);
1076 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001077 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001078 m = MIN(sizeof(long), len);
1079 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001080 addr += sizeof(long);
1081 laddr += m;
1082 nread += m;
1083 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086 return 0;
1087}
1088
1089/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001090 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001092 *
1093 * Returns < 0 on error, > 0 if NUL was seen,
1094 * (TODO if useful: return count of bytes including NUL),
1095 * else 0 if len bytes were read but no NUL byte seen.
1096 *
1097 * Note: there is no guarantee we won't overwrite some bytes
1098 * in laddr[] _after_ terminating NUL (but, of course,
1099 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100 */
1101int
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001102umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103{
Denys Vlasenko16940922013-03-01 18:52:59 +01001104#if SIZEOF_LONG == 4
1105 const unsigned long x01010101 = 0x01010101ul;
1106 const unsigned long x80808080 = 0x80808080ul;
1107#elif SIZEOF_LONG == 8
1108 const unsigned long x01010101 = 0x0101010101010101ul;
1109 const unsigned long x80808080 = 0x8080808080808080ul;
1110#else
1111# error SIZEOF_LONG > 8
1112#endif
1113
Roland McGratheb9e2e82009-06-02 16:49:22 -07001114 int pid = tcp->pid;
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001115 unsigned int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116 union {
Denys Vlasenko16940922013-03-01 18:52:59 +01001117 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 char x[sizeof(long)];
1119 } u;
1120
Denys Vlasenko2544f982013-02-19 17:39:56 +01001121#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001122 if (current_wordsize < sizeof(addr))
1123 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +00001124#endif
1125
Dmitry V. Levin97005922013-02-26 21:16:22 +00001126 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001127 if (!process_vm_readv_not_supported) {
1128 struct iovec local[1], remote[1];
1129
1130 local[0].iov_base = laddr;
1131 remote[0].iov_base = (void*)addr;
1132
1133 while (len > 0) {
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001134 unsigned int chunk_len;
1135 unsigned int end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001136 int r;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001137
1138 /* Don't read kilobytes: most strings are short */
1139 chunk_len = len;
1140 if (chunk_len > 256)
1141 chunk_len = 256;
1142 /* Don't cross pages. I guess otherwise we can get EFAULT
1143 * and fail to notice that terminating NUL lies
1144 * in the existing (first) page.
1145 * (I hope there aren't arches with pages < 4K)
1146 */
1147 end_in_page = ((addr + chunk_len) & 4095);
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001148 if (chunk_len > end_in_page) /* crosses to the next page */
1149 chunk_len -= end_in_page;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001150
1151 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001152 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1153 if (r > 0) {
1154 if (memchr(local[0].iov_base, '\0', r))
1155 return 1;
1156 local[0].iov_base += r;
1157 remote[0].iov_base += r;
1158 len -= r;
1159 nread += r;
1160 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001161 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001162 switch (errno) {
1163 case ENOSYS:
1164 process_vm_readv_not_supported = 1;
1165 goto vm_readv_didnt_work;
1166 case ESRCH:
1167 /* the process is gone */
1168 return -1;
1169 case EFAULT: case EIO: case EPERM:
1170 /* address space is inaccessible */
1171 if (nread) {
1172 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1173 nread, nread + len, addr);
1174 }
1175 return -1;
1176 default:
1177 /* all the rest is strange and should be reported */
1178 perror_msg("process_vm_readv");
1179 return -1;
1180 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001181 }
1182 return 0;
1183 }
1184 vm_readv_didnt_work:
1185
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 if (addr & (sizeof(long) - 1)) {
1187 /* addr not a multiple of sizeof(long) */
Dmitry V. Levin97e59962015-01-14 08:05:45 +00001188 n = addr & (sizeof(long) - 1); /* residue */
1189 addr &= -sizeof(long); /* aligned address */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001190 errno = 0;
1191 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001192 switch (errno) {
1193 case 0:
1194 break;
1195 case ESRCH: case EINVAL:
1196 /* these could be seen if the process is gone */
1197 return -1;
1198 case EFAULT: case EIO: case EPERM:
1199 /* address space is inaccessible */
1200 return -1;
1201 default:
1202 /* all the rest is strange and should be reported */
1203 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1204 pid, addr);
1205 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001206 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001207 m = MIN(sizeof(long) - n, len);
1208 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 while (n & (sizeof(long) - 1))
1210 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001211 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001212 addr += sizeof(long);
1213 laddr += m;
1214 nread += m;
1215 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001217
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001219 errno = 0;
1220 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001221 switch (errno) {
1222 case 0:
1223 break;
1224 case ESRCH: case EINVAL:
1225 /* these could be seen if the process is gone */
1226 return -1;
1227 case EFAULT: case EIO: case EPERM:
1228 /* address space is inaccessible */
1229 if (nread) {
1230 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1231 nread, nread + len, addr - nread);
1232 }
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), len);
1241 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001242 /* "If a NUL char exists in this word" */
1243 if ((u.val - x01010101) & ~u.val & x80808080)
1244 return 1;
1245 addr += sizeof(long);
1246 laddr += m;
1247 nread += m;
1248 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001250 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251}
1252
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001254upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255{
1256 long val;
1257
Roland McGratheb9e2e82009-06-02 16:49:22 -07001258 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001259 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001260 if (val == -1 && errno) {
1261 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001262 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001263 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001265 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 *res = val;
1267 return 0;
1268}
1269
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001270/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1271 * and PTRACE_O_TRACE[V]FORK for tracing children.
1272 * If you are adding a new arch which is only supported by newer kernels,
1273 * you most likely don't need to add any code below
1274 * beside a dummy "return 0" block in change_syscall().
1275 */
1276
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001277/*
1278 * These #if's are huge, please indent them correctly.
1279 * It's easy to get confused otherwise.
1280 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001282#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001283
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001284#ifndef CLONE_PTRACE
1285# define CLONE_PTRACE 0x00002000
1286#endif
1287#ifndef CLONE_VFORK
1288# define CLONE_VFORK 0x00004000
1289#endif
1290#ifndef CLONE_VM
1291# define CLONE_VM 0x00000100
1292#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001293
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001294#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001295
1296typedef unsigned long *arg_setup_state;
1297
1298static int
1299arg_setup(struct tcb *tcp, arg_setup_state *state)
1300{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001301 unsigned long cfm, sof, sol;
1302 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001304 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001305 /* Satisfy a false GCC warning. */
1306 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001307 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001308 }
Roland McGrath08267b82004-02-20 22:56:43 +00001309
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001310 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001312 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001313 return -1;
1314
1315 sof = (cfm >> 0) & 0x7f;
1316 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001317 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318
Jan Kratochvil1f942712008-08-06 21:38:52 +00001319 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001320 return 0;
1321}
1322
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001323# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324
Roland McGrathd81f1d92003-01-09 06:53:34 +00001325static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001326get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327{
Roland McGrath08267b82004-02-20 22:56:43 +00001328 int ret;
1329
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001330 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001331 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001332 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001333 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001334 (unsigned long) ia64_rse_skip_regs(*state, 0),
1335 sizeof(long), (void *) valp);
1336 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001337}
1338
1339static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001340get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001341{
Roland McGrath08267b82004-02-20 22:56:43 +00001342 int ret;
1343
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001344 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001345 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001346 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001347 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001348 (unsigned long) ia64_rse_skip_regs(*state, 1),
1349 sizeof(long), (void *) valp);
1350 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001351}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352
1353static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001354set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355{
Roland McGrath08267b82004-02-20 22:56:43 +00001356 int req = PTRACE_POKEDATA;
1357 void *ap;
1358
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001359 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001360 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1361 req = PTRACE_POKEUSER;
1362 } else
1363 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001364 errno = 0;
1365 ptrace(req, tcp->pid, ap, val);
1366 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001367}
1368
1369static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001370set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371{
Roland McGrath08267b82004-02-20 22:56:43 +00001372 int req = PTRACE_POKEDATA;
1373 void *ap;
1374
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001375 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001376 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1377 req = PTRACE_POKEUSER;
1378 } else
1379 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001380 errno = 0;
1381 ptrace(req, tcp->pid, ap, val);
1382 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001383}
1384
Roland McGrathb659f872008-07-18 01:19:36 +00001385/* ia64 does not return the input arguments from functions (and syscalls)
1386 according to ia64 RSE (Register Stack Engine) behavior. */
1387
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001388# define restore_arg0(tcp, state, val) ((void) (state), 0)
1389# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001390
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001391#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001392
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001393# if defined(SPARC64)
1394# undef PTRACE_GETREGS
1395# define PTRACE_GETREGS PTRACE_GETREGS64
1396# undef PTRACE_SETREGS
1397# define PTRACE_SETREGS PTRACE_SETREGS64
1398# endif
1399
Mike Frysinger8566c502009-10-12 11:05:14 -04001400typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001402# define arg_setup(tcp, state) \
1403 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1404# define arg_finish_change(tcp, state) \
1405 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001407# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1408# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1409# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1410# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1411# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001413#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001414
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001415# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001416/* Note: this is only true for the `clone' system call, which handles
1417 arguments specially. We could as well say that its first two arguments
1418 are swapped relative to other architectures, but that would just be
1419 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001420# define arg0_offset PT_GPR3
1421# define arg1_offset PT_ORIGGPR2
1422# define restore_arg0(tcp, state, val) ((void) (state), 0)
1423# define restore_arg1(tcp, state, val) ((void) (state), 0)
1424# define arg0_index 1
1425# define arg1_index 0
1426# elif defined(ALPHA) || defined(MIPS)
1427# define arg0_offset REG_A0
1428# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001429# elif defined(POWERPC)
1430# define arg0_offset (sizeof(unsigned long)*PT_R3)
1431# define arg1_offset (sizeof(unsigned long)*PT_R4)
1432# define restore_arg0(tcp, state, val) ((void) (state), 0)
1433# elif defined(HPPA)
1434# define arg0_offset PT_GR26
1435# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001436# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001437# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1438# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1439# elif defined(SH)
1440# define arg0_offset (4*(REG_REG0+4))
1441# define arg1_offset (4*(REG_REG0+5))
1442# elif defined(SH64)
1443 /* ABI defines arg0 & 1 in r2 & r3 */
1444# define arg0_offset (REG_OFFSET+16)
1445# define arg1_offset (REG_OFFSET+24)
1446# define restore_arg0(tcp, state, val) 0
1447# elif defined CRISV10 || defined CRISV32
1448# define arg0_offset (4*PT_R11)
1449# define arg1_offset (4*PT_ORIG_R10)
1450# define restore_arg0(tcp, state, val) 0
1451# define restore_arg1(tcp, state, val) 0
1452# define arg0_index 1
1453# define arg1_index 0
1454# else
1455# define arg0_offset 0
1456# define arg1_offset 4
1457# if defined ARM
1458# define restore_arg0(tcp, state, val) 0
1459# endif
1460# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001461
1462typedef int arg_setup_state;
1463
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001464# define arg_setup(tcp, state) (0)
1465# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001466# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1467# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468
1469static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001470set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001471{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001472 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001473}
1474
1475static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001476set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001477{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001478 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479}
1480
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001481#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001482
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001483#ifndef restore_arg0
1484# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1485#endif
1486#ifndef restore_arg1
1487# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1488#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001489
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001490#ifndef arg0_index
1491# define arg0_index 0
1492# define arg1_index 1
1493#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001494
James Hogan05eb9052012-11-29 17:37:37 +00001495static int
1496change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1497{
1498#if defined(I386)
1499 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1500 return -1;
1501 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001502#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001503 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1504 return -1;
1505 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001506#elif defined(X32)
1507 /* setbpt/clearbpt never used: */
1508 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001509#elif defined(POWERPC)
1510 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1511 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1512 return -1;
1513 return 0;
1514#elif defined(S390) || defined(S390X)
1515 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1516 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1517 return -1;
1518 return 0;
1519#elif defined(M68K)
1520 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1521 return -1;
1522 return 0;
1523#elif defined(SPARC) || defined(SPARC64)
1524 state->u_regs[U_REG_G1] = new;
1525 return 0;
1526#elif defined(MIPS)
1527 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1528 return -1;
1529 return 0;
1530#elif defined(ALPHA)
1531 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1532 return -1;
1533 return 0;
1534#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001535 /* setbpt/clearbpt never used: */
1536 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001537#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001538 /* setbpt/clearbpt never used: */
1539 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001540#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001541 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001542 switch (new) {
1543 case 2:
1544 break; /* x86 SYS_fork */
1545 case SYS_clone:
1546 new = 120;
1547 break;
1548 default:
1549 fprintf(stderr, "%s: unexpected syscall %d\n",
1550 __FUNCTION__, new);
1551 return -1;
1552 }
1553 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1554 return -1;
1555 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1556 return -1;
1557 return 0;
1558#elif defined(HPPA)
1559 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1560 return -1;
1561 return 0;
1562#elif defined(SH)
1563 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1564 return -1;
1565 return 0;
1566#elif defined(SH64)
1567 /* Top half of reg encodes the no. of args n as 0x1n.
1568 Assume 0 args as kernel never actually checks... */
1569 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1570 0x100000 | new) < 0)
1571 return -1;
1572 return 0;
1573#elif defined(CRISV10) || defined(CRISV32)
1574 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1575 return -1;
1576 return 0;
1577#elif defined(ARM)
1578 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1579# ifndef PTRACE_SET_SYSCALL
1580# define PTRACE_SET_SYSCALL 23
1581# endif
1582 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1583 return -1;
1584 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001585#elif defined(AARCH64)
1586 /* setbpt/clearbpt never used: */
1587 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001588#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001589 /* setbpt/clearbpt never used: */
1590 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001591#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001592 /* setbpt/clearbpt never used: */
1593 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001594#elif defined(OR1K)
1595 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001596#elif defined(METAG)
1597 /* setbpt/clearbpt never used: */
1598 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001599#elif defined(XTENSA)
1600 /* setbpt/clearbpt never used: */
1601 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301602#elif defined(ARC)
1603 /* setbpt/clearbpt never used: */
1604 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001605#else
1606#warning Do not know how to handle change_syscall for this architecture
1607#endif /* architecture */
1608 return -1;
1609}
1610
Roland McGrathd81f1d92003-01-09 06:53:34 +00001611int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001612setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001613{
Roland McGrath3291ef22008-05-20 00:34:34 +00001614 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001615 arg_setup_state state;
1616
1617 if (tcp->flags & TCB_BPTSET) {
1618 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1619 return -1;
1620 }
1621
Roland McGrath3291ef22008-05-20 00:34:34 +00001622 /*
1623 * It's a silly kludge to initialize this with a search at runtime.
1624 * But it's better than maintaining another magic thing in the
1625 * godforsaken tables.
1626 */
1627 if (clone_scno[current_personality] == 0) {
Dmitry V. Levin3ed5d022014-09-10 13:46:04 +00001628 unsigned int i;
Roland McGrath3291ef22008-05-20 00:34:34 +00001629 for (i = 0; i < nsyscalls; ++i)
1630 if (sysent[i].sys_func == sys_clone) {
1631 clone_scno[current_personality] = i;
1632 break;
1633 }
1634 }
1635
Dmitry V. Levin65563152014-05-12 13:43:10 +00001636 if (tcp->s_ent->sys_func == sys_fork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001637 if (arg_setup(tcp, &state) < 0
1638 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1639 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001640 || change_syscall(tcp, &state,
1641 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001642 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1643 || set_arg1(tcp, &state, 0) < 0
1644 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001645 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001646 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1647 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001648 tcp->flags |= TCB_BPTSET;
1649 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001650 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001651
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001652 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001653 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001654 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001655 vfork semantics into plain fork - each application must not
1656 depend on the vfork specifics according to POSIX. We would
1657 hang waiting for the parent resume otherwise. We need to
1658 clear also CLONE_VM but only in the CLONE_VFORK case as
1659 otherwise we would break pthread_create. */
1660
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001661 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1662 if (new_arg0 & CLONE_VFORK)
1663 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1664 if (arg_setup(tcp, &state) < 0
1665 || set_arg0(tcp, &state, new_arg0) < 0
1666 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001667 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001668 tcp->inst[0] = tcp->u_arg[arg0_index];
1669 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001670 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001671 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001672 }
1673
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001674 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1675 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001676 return -1;
1677}
1678
1679int
Denys Vlasenko12014262011-05-30 14:00:14 +02001680clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001681{
1682 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001683 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001684 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001685 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1686 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1687 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001688 if (errno != ESRCH)
1689 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001690 tcp->flags &= ~TCB_BPTSET;
1691 return 0;
1692}