blob: 47c8734fab080fdab1b9e4792bee84a8d12c89c9 [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>
John Hughes1d08dcf2001-07-10 13:48:44 +000038#if HAVE_SYS_UIO_H
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +010039# include <sys/uio.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000040#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000041
Denys Vlasenko84703742012-02-25 02:38:52 +010042#if defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000043# include <asm/ptrace_offsets.h>
44# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000045#endif
46
Wichert Akkerman36915a11999-07-13 15:45:02 +000047#ifdef HAVE_SYS_REG_H
Denys Vlasenko84703742012-02-25 02:38:52 +010048# include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko84703742012-02-25 02:38:52 +010051# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Ali Polatel0b4060f2013-09-24 20:04:32 +030058# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
59# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
60# endif
Denys Vlasenko84703742012-02-25 02:38:52 +010061# include <linux/ptrace.h>
Ali Polatel0b4060f2013-09-24 20:04:32 +030062# undef ptrace_peeksiginfo_args
Roland McGrathce9f0742004-03-01 21:29:22 +000063# undef ia64_fpreg
64# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000065#endif
66
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000067int
Dmitry V. Levinccee1692012-03-25 21:49:48 +000068string_to_uint(const char *str)
69{
70 char *error;
71 long value;
72
73 if (!*str)
74 return -1;
75 errno = 0;
76 value = strtol(str, &error, 10);
77 if (errno || *error || value < 0 || (long)(int)value != value)
78 return -1;
79 return (int)value;
80}
81
82int
Denys Vlasenko12014262011-05-30 14:00:14 +020083tv_nz(struct timeval *a)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084{
85 return a->tv_sec || a->tv_usec;
86}
87
88int
Denys Vlasenko12014262011-05-30 14:00:14 +020089tv_cmp(struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090{
91 if (a->tv_sec < b->tv_sec
92 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
93 return -1;
94 if (a->tv_sec > b->tv_sec
95 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
96 return 1;
97 return 0;
98}
99
100double
Denys Vlasenko12014262011-05-30 14:00:14 +0200101tv_float(struct timeval *tv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102{
103 return tv->tv_sec + tv->tv_usec/1000000.0;
104}
105
106void
Denys Vlasenko12014262011-05-30 14:00:14 +0200107tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108{
109 tv->tv_sec = a->tv_sec + b->tv_sec;
110 tv->tv_usec = a->tv_usec + b->tv_usec;
Roland McGrath58372f52007-07-24 01:38:22 +0000111 if (tv->tv_usec >= 1000000) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112 tv->tv_sec++;
113 tv->tv_usec -= 1000000;
114 }
115}
116
117void
Denys Vlasenko12014262011-05-30 14:00:14 +0200118tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119{
120 tv->tv_sec = a->tv_sec - b->tv_sec;
121 tv->tv_usec = a->tv_usec - b->tv_usec;
122 if (((long) tv->tv_usec) < 0) {
123 tv->tv_sec--;
124 tv->tv_usec += 1000000;
125 }
126}
127
128void
Denys Vlasenko12014262011-05-30 14:00:14 +0200129tv_div(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130{
131 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
132 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
133 tv->tv_usec %= 1000000;
134}
135
136void
Denys Vlasenko12014262011-05-30 14:00:14 +0200137tv_mul(struct timeval *tv, struct timeval *a, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138{
139 tv->tv_usec = a->tv_usec * n;
Dmitry V. Levinfefdd972007-06-29 21:25:56 +0000140 tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141 tv->tv_usec %= 1000000;
142}
143
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000144const char *
145xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146{
147 for (; xlat->str != NULL; xlat++)
148 if (xlat->val == val)
149 return xlat->str;
150 return NULL;
151}
152
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200153#if !defined HAVE_STPCPY
Denys Vlasenko52845572011-08-31 12:07:38 +0200154char *
155stpcpy(char *dst, const char *src)
156{
157 while ((*dst = *src++) != '\0')
158 dst++;
159 return dst;
160}
Denys Vlasenko0a295bc2011-09-01 16:31:48 +0200161#endif
Denys Vlasenko52845572011-08-31 12:07:38 +0200162
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100163/* Find a next bit which is set.
164 * Starts testing at cur_bit.
165 * Returns -1 if no more bits are set.
166 *
167 * We never touch bytes we don't need to.
168 * On big-endian, array is assumed to consist of
169 * current_wordsize wide words: for example, is current_wordsize is 4,
170 * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
171 * On little-endian machines, word size is immaterial.
172 */
173int
174next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
175{
176 const unsigned endian = 1;
177 int little_endian = *(char*)&endian;
178
179 const uint8_t *array = bit_array;
180 unsigned pos = cur_bit / 8;
181 unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
182
183 for (;;) {
184 uint8_t bitmask;
185 uint8_t cur_byte;
186
187 if (cur_bit >= size_bits)
188 return -1;
189 cur_byte = array[pos ^ pos_xor_mask];
190 if (cur_byte == 0) {
191 cur_bit = (cur_bit + 8) & (-8);
192 pos++;
193 continue;
194 }
195 bitmask = 1 << (cur_bit & 7);
196 for (;;) {
197 if (cur_byte & bitmask)
198 return cur_bit;
199 cur_bit++;
200 if (cur_bit >= size_bits)
201 return -1;
202 bitmask <<= 1;
203 /* This check *can't be* optimized out: */
204 if (bitmask == 0)
205 break;
206 }
207 pos++;
208 }
209}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210/*
211 * Print entry in struct xlat table, if there.
212 */
213void
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000214printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000216 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217
218 if (str)
Denys Vlasenko5940e652011-09-01 09:55:05 +0200219 tprints(str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000220 else
221 tprintf("%#x /* %s */", val, dflt);
222}
223
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100224/*
Chris Metcalf879dddd2013-03-01 10:41:02 +0100225 * Print 64bit argument at position arg_no and return the index of the next
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100226 * argument.
227 */
228int
Chris Metcalf879dddd2013-03-01 10:41:02 +0100229printllval(struct tcb *tcp, const char *format, int arg_no)
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100230{
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000231#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
232# if SUPPORTED_PERSONALITIES > 1
233 if (current_wordsize > 4) {
234# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100235 tprintf(format, tcp->u_arg[arg_no]);
236 arg_no++;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000237# if SUPPORTED_PERSONALITIES > 1
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100238 } else {
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000239# if defined(AARCH64) || defined(POWERPC64)
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000240 /* Align arg_no to the next even number. */
Chris Metcalf879dddd2013-03-01 10:41:02 +0100241 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000242# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100243 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
244 arg_no += 2;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100245 }
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000246# endif /* SUPPORTED_PERSONALITIES */
247#elif SIZEOF_LONG > 4
248# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
249#elif defined LINUX_MIPSN32
250 tprintf(format, tcp->ext_arg[arg_no]);
Chris Metcalf879dddd2013-03-01 10:41:02 +0100251 arg_no++;
Dmitry V. Levin0b468832013-05-02 08:41:27 +0000252#elif defined X32
253 if (current_personality == 0) {
254 tprintf(format, tcp->ext_arg[arg_no]);
255 arg_no++;
256 } else {
257 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
258 arg_no += 2;
259 }
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100260#else
Dmitry V. Levin8e096c42013-05-06 18:23:01 +0000261# if defined __ARM_EABI__ || \
262 defined LINUX_MIPSO32 || \
263 defined POWERPC || \
264 defined XTENSA
Dmitry V. Levina55b6b12013-05-03 22:27:45 +0000265 /* Align arg_no to the next even number. */
266 arg_no = (arg_no + 1) & 0xe;
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000267# endif
Chris Metcalf879dddd2013-03-01 10:41:02 +0100268 tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
269 arg_no += 2;
Denys Vlasenkoc9d0fc02013-02-17 22:41:33 +0100270#endif
Dmitry V. Levin7a498be2013-05-04 19:51:57 +0000271
Chris Metcalf879dddd2013-03-01 10:41:02 +0100272 return arg_no;
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100273}
Andreas Schwabb5600fc2009-11-04 17:08:34 +0100274
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000275/*
276 * Interpret `xlat' as an array of flags
277 * print the entries whose bits are on in `flags'
278 * return # of flags printed.
279 */
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200280void
Denys Vlasenko12014262011-05-30 14:00:14 +0200281addflags(const struct xlat *xlat, int flags)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282{
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200283 for (; xlat->str; xlat++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284 if (xlat->val && (flags & xlat->val) == xlat->val) {
285 tprintf("|%s", xlat->str);
286 flags &= ~xlat->val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287 }
288 }
289 if (flags) {
290 tprintf("|%#x", flags);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000292}
293
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000294/*
Denys Vlasenko4924dbd2011-08-19 18:06:46 +0200295 * Interpret `xlat' as an array of flags.
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000296 * Print to static string the entries whose bits are on in `flags'
297 * Return static string.
298 */
299const char *
300sprintflags(const char *prefix, const struct xlat *xlat, int flags)
301{
302 static char outstr[1024];
Denys Vlasenko52845572011-08-31 12:07:38 +0200303 char *outptr;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000304 int found = 0;
305
Denys Vlasenko52845572011-08-31 12:07:38 +0200306 outptr = stpcpy(outstr, prefix);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000307
308 for (; xlat->str; xlat++) {
309 if ((flags & xlat->val) == xlat->val) {
310 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200311 *outptr++ = '|';
312 outptr = stpcpy(outptr, xlat->str);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000313 found = 1;
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100314 flags &= ~xlat->val;
315 if (!flags)
316 break;
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000317 }
318 }
319 if (flags) {
320 if (found)
Denys Vlasenko52845572011-08-31 12:07:38 +0200321 *outptr++ = '|';
322 outptr += sprintf(outptr, "%#x", flags);
Roland McGratha6c0d8c2007-11-01 21:46:22 +0000323 }
324
325 return outstr;
326}
327
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000329printflags(const struct xlat *xlat, int flags, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000330{
331 int n;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000332 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333
334 if (flags == 0 && xlat->val == 0) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200335 tprints(xlat->str);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336 return 1;
337 }
338
339 sep = "";
340 for (n = 0; xlat->str; xlat++) {
341 if (xlat->val && (flags & xlat->val) == xlat->val) {
342 tprintf("%s%s", sep, xlat->str);
343 flags &= ~xlat->val;
344 sep = "|";
345 n++;
346 }
347 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000348
349 if (n) {
350 if (flags) {
351 tprintf("%s%#x", sep, flags);
352 n++;
353 }
354 } else {
355 if (flags) {
356 tprintf("%#x", flags);
357 if (dflt)
358 tprintf(" /* %s */", dflt);
359 } else {
360 if (dflt)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200361 tprints("0");
Roland McGrathb2dee132005-06-01 19:02:36 +0000362 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000363 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000364
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000365 return n;
366}
367
368void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000369printnum(struct tcb *tcp, long addr, const char *fmt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370{
Roland McGratheb285352003-01-14 09:59:00 +0000371 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372
373 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200374 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375 return;
376 }
377 if (umove(tcp, addr, &num) < 0) {
378 tprintf("%#lx", addr);
379 return;
380 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200381 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200383 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384}
385
Roland McGrath6bc12202003-11-13 22:32:27 +0000386void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000387printnum_int(struct tcb *tcp, long addr, const char *fmt)
Roland McGrath9814a942005-07-04 23:28:10 +0000388{
389 int num;
390
391 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200392 tprints("NULL");
Roland McGrath9814a942005-07-04 23:28:10 +0000393 return;
394 }
395 if (umove(tcp, addr, &num) < 0) {
396 tprintf("%#lx", addr);
397 return;
398 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200399 tprints("[");
Roland McGrath9814a942005-07-04 23:28:10 +0000400 tprintf(fmt, num);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200401 tprints("]");
Roland McGrath9814a942005-07-04 23:28:10 +0000402}
403
404void
Dmitry V. Levin31382132011-03-04 05:08:02 +0300405printfd(struct tcb *tcp, int fd)
406{
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100407 char path[PATH_MAX + 1];
Grant Edwards8a082772011-04-07 20:25:40 +0000408
Denys Vlasenko61ad0a42013-03-06 18:24:34 +0100409 if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
410 tprintf("%d<%s>", fd, path);
Grant Edwards8a082772011-04-07 20:25:40 +0000411 else
412 tprintf("%d", fd);
Dmitry V. Levin31382132011-03-04 05:08:02 +0300413}
414
415void
Denys Vlasenko12014262011-05-30 14:00:14 +0200416printuid(const char *text, unsigned long uid)
Roland McGrath6bc12202003-11-13 22:32:27 +0000417{
Denys Vlasenko5940e652011-09-01 09:55:05 +0200418 tprintf((uid == -1) ? "%s%ld" : "%s%lu", text, uid);
Roland McGrath6bc12202003-11-13 22:32:27 +0000419}
420
Dmitry V. Levina501f142008-11-10 23:19:13 +0000421/*
422 * Quote string `instr' of length `size'
423 * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200424 * If `len' is -1, treat `instr' as a NUL-terminated string
Dmitry V. Levina501f142008-11-10 23:19:13 +0000425 * and quote at most (`size' - 1) bytes.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100426 *
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200427 * Returns 0 if len == -1 and NUL was seen, 1 otherwise.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100428 * Note that if len >= 0, always returns 1.
Dmitry V. Levina501f142008-11-10 23:19:13 +0000429 */
Mike Frysingerebee04c2012-04-17 22:19:31 -0400430int
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200431string_quote(const char *instr, char *outstr, long len, int size)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000432{
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000433 const unsigned char *ustr = (const unsigned char *) instr;
434 char *s = outstr;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200435 int usehex, c, i, eol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200437 eol = 0x100; /* this can never match a char */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200438 if (len == -1) {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200439 size--;
440 eol = '\0';
441 }
442
443 usehex = 0;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000444 if (xflag > 1)
445 usehex = 1;
446 else if (xflag) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000447 /* Check for presence of symbol which require
448 to hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000449 for (i = 0; i < size; ++i) {
450 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000451 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200452 if (c == eol)
453 break;
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100454
455 /* Force hex unless c is printable or whitespace */
456 if (c > 0x7e) {
457 usehex = 1;
458 break;
459 }
460 /* In ASCII isspace is only these chars: "\t\n\v\f\r".
461 * They happen to have ASCII codes 9,10,11,12,13.
462 */
463 if (c < ' ' && (unsigned)(c - 9) >= 5) {
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000464 usehex = 1;
465 break;
466 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000467 }
468 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000469
470 *s++ = '\"';
471
472 if (usehex) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000473 /* Hex-quote the whole string. */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000474 for (i = 0; i < size; ++i) {
475 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000476 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200477 if (c == eol)
478 goto asciz_ended;
479 *s++ = '\\';
480 *s++ = 'x';
481 *s++ = "0123456789abcdef"[c >> 4];
482 *s++ = "0123456789abcdef"[c & 0xf];
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000483 }
484 } else {
485 for (i = 0; i < size; ++i) {
486 c = ustr[i];
Dmitry V. Levina501f142008-11-10 23:19:13 +0000487 /* Check for NUL-terminated string. */
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200488 if (c == eol)
489 goto asciz_ended;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000490 switch (c) {
491 case '\"': case '\\':
492 *s++ = '\\';
493 *s++ = c;
494 break;
495 case '\f':
496 *s++ = '\\';
497 *s++ = 'f';
498 break;
499 case '\n':
500 *s++ = '\\';
501 *s++ = 'n';
502 break;
503 case '\r':
504 *s++ = '\\';
505 *s++ = 'r';
506 break;
507 case '\t':
508 *s++ = '\\';
509 *s++ = 't';
510 break;
511 case '\v':
512 *s++ = '\\';
513 *s++ = 'v';
514 break;
515 default:
Denys Vlasenko5198ed42013-03-06 23:44:23 +0100516 if (c >= ' ' && c <= 0x7e)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000517 *s++ = c;
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200518 else {
519 /* Print \octal */
520 *s++ = '\\';
521 if (i + 1 < size
522 && ustr[i + 1] >= '0'
523 && ustr[i + 1] <= '9'
524 ) {
525 /* Print \ooo */
526 *s++ = '0' + (c >> 6);
527 *s++ = '0' + ((c >> 3) & 0x7);
528 } else {
529 /* Print \[[o]o]o */
530 if ((c >> 3) != 0) {
531 if ((c >> 6) != 0)
532 *s++ = '0' + (c >> 6);
533 *s++ = '0' + ((c >> 3) & 0x7);
534 }
535 }
536 *s++ = '0' + (c & 0x7);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000537 }
538 break;
539 }
540 }
541 }
542
543 *s++ = '\"';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000544 *s = '\0';
Roland McGrath6d970322007-11-01 23:53:59 +0000545
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200546 /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200547 if (len == -1 && ustr[i] == '\0') {
Denys Vlasenko8778bff2011-08-31 12:22:56 +0200548 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
549 * but next char is NUL.
550 */
551 return 0;
552 }
553
554 return 1;
555
556 asciz_ended:
557 *s++ = '\"';
558 *s = '\0';
559 /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
560 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561}
562
Dmitry V. Levina501f142008-11-10 23:19:13 +0000563/*
564 * Print path string specified by address `addr' and length `n'.
565 * If path length exceeds `n', append `...' to the output.
566 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000568printpathn(struct tcb *tcp, long addr, int n)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100570 char path[MAXPATHLEN + 1];
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100571 int nul_seen;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100572
Dmitry V. Levina501f142008-11-10 23:19:13 +0000573 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200574 tprints("NULL");
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000575 return;
576 }
577
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100578 /* Cap path length to the path buffer size */
Dmitry V. Levina501f142008-11-10 23:19:13 +0000579 if (n > sizeof path - 1)
580 n = sizeof path - 1;
Dmitry V. Levina501f142008-11-10 23:19:13 +0000581
582 /* Fetch one byte more to find out whether path length > n. */
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100583 nul_seen = umovestr(tcp, addr, n + 1, path);
584 if (nul_seen < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 tprintf("%#lx", addr);
586 else {
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100587 char *outstr;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000588
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100589 path[n] = '\0';
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100590 n++;
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100591 outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100592 string_quote(path, outstr, -1, n);
593 tprints(outstr);
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100594 if (!nul_seen)
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100595 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 }
597}
598
599void
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000600printpath(struct tcb *tcp, long addr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601{
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100602 /* Size must correspond to char path[] size in printpathn */
603 printpathn(tcp, addr, MAXPATHLEN);
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000604}
605
Dmitry V. Levina501f142008-11-10 23:19:13 +0000606/*
607 * Print string specified by address `addr' and length `len'.
608 * If `len' < 0, treat the string as a NUL-terminated string.
609 * If string length exceeds `max_strlen', append `...' to the output.
610 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000611void
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200612printstr(struct tcb *tcp, long addr, long len)
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000613{
614 static char *str = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000615 static char *outstr;
Roland McGrath6d970322007-11-01 23:53:59 +0000616 int size;
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100617 int ellipsis;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618
619 if (!addr) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200620 tprints("NULL");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000621 return;
622 }
Dmitry V. Levina501f142008-11-10 23:19:13 +0000623 /* Allocate static buffers if they are not allocated yet. */
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200624 if (!str) {
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000625 unsigned int outstr_size = 4 * max_strlen + /*for quotes and NUL:*/ 3;
626
627 if (outstr_size / 4 != max_strlen)
628 die_out_of_memory();
Dmitry V. Levina501f142008-11-10 23:19:13 +0000629 str = malloc(max_strlen + 1);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200630 if (!str)
631 die_out_of_memory();
Dmitry V. Levin378f9c52012-03-25 22:56:53 +0000632 outstr = malloc(outstr_size);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200633 if (!outstr)
634 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000635 }
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000636
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200637 if (len == -1) {
Dmitry V. Levina501f142008-11-10 23:19:13 +0000638 /*
639 * Treat as a NUL-terminated string: fetch one byte more
640 * because string_quote() quotes one byte less.
641 */
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000642 size = max_strlen + 1;
643 if (umovestr(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000644 tprintf("%#lx", addr);
645 return;
646 }
647 }
648 else {
Denys Vlasenkob5d43b82012-04-28 14:58:35 +0200649 size = max_strlen;
650 if (size > (unsigned long)len)
651 size = (unsigned long)len;
Dmitry V. Levinbea02032007-10-08 21:48:01 +0000652 if (umoven(tcp, addr, size, str) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653 tprintf("%#lx", addr);
654 return;
655 }
656 }
657
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100658 /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
659 * or we were requested to print more than -s NUM chars)...
660 */
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100661 ellipsis = (string_quote(str, outstr, len, size) &&
662 (len < 0 || len > max_strlen));
Roland McGratha503dcf2007-08-02 02:06:26 +0000663
Denys Vlasenkob3c52cf2012-01-19 17:20:23 +0100664 tprints(outstr);
665 if (ellipsis)
666 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667}
668
John Hughes1d08dcf2001-07-10 13:48:44 +0000669#if HAVE_SYS_UIO_H
670void
Denys Vlasenko12014262011-05-30 14:00:14 +0200671dumpiov(struct tcb *tcp, int len, long addr)
John Hughes1d08dcf2001-07-10 13:48:44 +0000672{
Denys Vlasenko84703742012-02-25 02:38:52 +0100673#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000674 union {
675 struct { u_int32_t base; u_int32_t len; } *iov32;
676 struct { u_int64_t base; u_int64_t len; } *iov64;
677 } iovu;
678#define iov iovu.iov64
679#define sizeof_iov \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100680 (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000681#define iov_iov_base(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100682 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000683#define iov_iov_len(i) \
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100684 (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000685#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000686 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000687#define sizeof_iov sizeof(*iov)
688#define iov_iov_base(i) iov[i].iov_base
689#define iov_iov_len(i) iov[i].iov_len
690#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000691 int i;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200692 unsigned size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000693
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200694 size = sizeof_iov * len;
695 /* Assuming no sane program has millions of iovs */
696 if ((unsigned)len > 1024*1024 /* insane or negative size? */
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000697 || (iov = malloc(size)) == NULL) {
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200698 fprintf(stderr, "Out of memory\n");
699 return;
John Hughes1d08dcf2001-07-10 13:48:44 +0000700 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000701 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000702 for (i = 0; i < len; i++) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000703 /* include the buffer number to make it easy to
704 * match up the trace with the source */
705 tprintf(" * %lu bytes in buffer %d\n",
706 (unsigned long)iov_iov_len(i), i);
707 dumpstr(tcp, (long) iov_iov_base(i),
708 iov_iov_len(i));
709 }
John Hughes1d08dcf2001-07-10 13:48:44 +0000710 }
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200711 free(iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000712#undef sizeof_iov
713#undef iov_iov_base
714#undef iov_iov_len
715#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000716}
717#endif
718
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719void
Denys Vlasenko12014262011-05-30 14:00:14 +0200720dumpstr(struct tcb *tcp, long addr, int len)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721{
722 static int strsize = -1;
723 static unsigned char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724
Denys Vlasenko76325802013-02-22 14:47:39 +0100725 char outbuf[
726 (
727 (sizeof(
728 "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
729 "1234567890123456") + /*in case I'm off by few:*/ 4)
730 /*align to 8 to make memset easier:*/ + 7) & -8
731 ];
732 const unsigned char *src;
733 int i;
734
735 memset(outbuf, ' ', sizeof(outbuf));
736
737 if (strsize < len + 16) {
Denys Vlasenko5d645812011-08-20 12:48:18 +0200738 free(str);
Denys Vlasenko76325802013-02-22 14:47:39 +0100739 str = malloc(len + 16);
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200740 if (!str) {
741 strsize = -1;
742 fprintf(stderr, "Out of memory\n");
743 return;
744 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100745 strsize = len + 16;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000746 }
747
748 if (umoven(tcp, addr, len, (char *) str) < 0)
749 return;
750
Denys Vlasenko76325802013-02-22 14:47:39 +0100751 /* Space-pad to 16 bytes */
752 i = len;
753 while (i & 0xf)
754 str[i++] = ' ';
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200755
Denys Vlasenko76325802013-02-22 14:47:39 +0100756 i = 0;
757 src = str;
758 while (i < len) {
759 char *dst = outbuf;
760 /* Hex dump */
761 do {
762 if (i < len) {
763 *dst++ = "0123456789abcdef"[*src >> 4];
764 *dst++ = "0123456789abcdef"[*src & 0xf];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765 }
766 else {
Denys Vlasenko76325802013-02-22 14:47:39 +0100767 *dst++ = ' ';
768 *dst++ = ' ';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000769 }
Denys Vlasenko76325802013-02-22 14:47:39 +0100770 dst++; /* space is there by memset */
771 i++;
772 if ((i & 7) == 0)
773 dst++; /* space is there by memset */
774 src++;
775 } while (i & 0xf);
776 /* ASCII dump */
777 i -= 16;
778 src -= 16;
779 do {
780 if (*src >= ' ' && *src < 0x7f)
781 *dst++ = *src;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 else
Denys Vlasenko76325802013-02-22 14:47:39 +0100783 *dst++ = '.';
784 src++;
785 } while (++i & 0xf);
786 *dst = '\0';
Denys Vlasenkof90979b2013-02-22 15:00:11 +0100787 tprintf(" | %05x %s |\n", i - 16, outbuf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000788 }
789}
790
Mike Frysinger612659e2012-02-14 14:38:28 +0100791#ifdef HAVE_PROCESS_VM_READV
792/* C library supports this, but the kernel might not. */
793static bool process_vm_readv_not_supported = 0;
794#else
795
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100796/* Need to do this since process_vm_readv() is not yet available in libc.
797 * When libc is be updated, only "static bool process_vm_readv_not_supported"
798 * line should remain.
799 */
800#if !defined(__NR_process_vm_readv)
801# if defined(I386)
802# define __NR_process_vm_readv 347
803# elif defined(X86_64)
804# define __NR_process_vm_readv 310
805# elif defined(POWERPC)
806# define __NR_process_vm_readv 351
807# endif
808#endif
809
810#if defined(__NR_process_vm_readv)
811static bool process_vm_readv_not_supported = 0;
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400812/* Have to avoid duplicating with the C library headers. */
813static ssize_t strace_process_vm_readv(pid_t pid,
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100814 const struct iovec *lvec,
815 unsigned long liovcnt,
816 const struct iovec *rvec,
817 unsigned long riovcnt,
818 unsigned long flags)
819{
820 return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
821}
Mike Frysinger24ee60b2012-05-04 19:37:29 -0400822#define process_vm_readv strace_process_vm_readv
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100823#else
824static bool process_vm_readv_not_supported = 1;
825# define process_vm_readv(...) (errno = ENOSYS, -1)
826#endif
Mike Frysinger612659e2012-02-14 14:38:28 +0100827
828#endif /* end of hack */
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100829
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830#define PAGMASK (~(PAGSIZ - 1))
831/*
832 * move `len' bytes of data from process `pid'
833 * at address `addr' to our space at `laddr'
834 */
835int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000836umoven(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837{
Roland McGratheb9e2e82009-06-02 16:49:22 -0700838 int pid = tcp->pid;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000839 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 union {
841 long val;
842 char x[sizeof(long)];
843 } u;
844
Denys Vlasenko2544f982013-02-19 17:39:56 +0100845#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100846 if (current_wordsize < sizeof(addr))
847 addr &= (1ul << 8 * current_wordsize) - 1;
Denys Vlasenkod2a660f2012-02-25 00:43:22 +0100848#endif
849
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100850 if (!process_vm_readv_not_supported) {
851 struct iovec local[1], remote[1];
852 int r;
853
854 local[0].iov_base = laddr;
855 remote[0].iov_base = (void*)addr;
856 local[0].iov_len = remote[0].iov_len = len;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000857 r = process_vm_readv(pid, local, 1, remote, 1, 0);
Ben Noordhuis1d58fe92013-02-26 12:24:25 +0100858 if (r == len)
859 return 0;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000860 if (r >= 0) {
861 error_msg("umoven: short read (%d < %d) @0x%lx",
862 r, len, addr);
863 return -1;
864 }
865 switch (errno) {
866 case ENOSYS:
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100867 process_vm_readv_not_supported = 1;
Dmitry V. Levin97005922013-02-26 21:16:22 +0000868 break;
869 case ESRCH:
870 /* the process is gone */
871 return -1;
872 case EFAULT: case EIO: case EPERM:
873 /* address space is inaccessible */
874 return -1;
875 default:
876 /* all the rest is strange and should be reported */
Denys Vlasenko905e8e02013-02-26 12:30:09 +0100877 perror_msg("process_vm_readv");
Dmitry V. Levin97005922013-02-26 21:16:22 +0000878 return -1;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100879 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100880 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100881
Dmitry V. Levin97005922013-02-26 21:16:22 +0000882 nread = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883 if (addr & (sizeof(long) - 1)) {
884 /* addr not a multiple of sizeof(long) */
885 n = addr - (addr & -sizeof(long)); /* residue */
886 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700887 errno = 0;
888 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000889 switch (errno) {
890 case 0:
891 break;
892 case ESRCH: case EINVAL:
893 /* these could be seen if the process is gone */
894 return -1;
895 case EFAULT: case EIO: case EPERM:
896 /* address space is inaccessible */
897 return -1;
898 default:
899 /* all the rest is strange and should be reported */
900 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
901 pid, addr);
902 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700903 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100904 m = MIN(sizeof(long) - n, len);
905 memcpy(laddr, &u.x[n], m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100906 addr += sizeof(long);
907 laddr += m;
908 nread += m;
909 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910 }
911 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700912 errno = 0;
913 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +0000914 switch (errno) {
915 case 0:
916 break;
917 case ESRCH: case EINVAL:
918 /* these could be seen if the process is gone */
919 return -1;
920 case EFAULT: case EIO: case EPERM:
921 /* address space is inaccessible */
922 if (nread) {
923 perror_msg("umoven: short read (%d < %d) @0x%lx",
924 nread, nread + len, addr - nread);
925 }
926 return -1;
927 default:
928 /* all the rest is strange and should be reported */
929 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%lx",
930 pid, addr);
931 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700932 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +0100933 m = MIN(sizeof(long), len);
934 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +0100935 addr += sizeof(long);
936 laddr += m;
937 nread += m;
938 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 return 0;
942}
943
944/*
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100945 * Like `umove' but make the additional effort of looking
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946 * for a terminating zero byte.
Denys Vlasenko6cecba52012-01-20 11:56:00 +0100947 *
948 * Returns < 0 on error, > 0 if NUL was seen,
949 * (TODO if useful: return count of bytes including NUL),
950 * else 0 if len bytes were read but no NUL byte seen.
951 *
952 * Note: there is no guarantee we won't overwrite some bytes
953 * in laddr[] _after_ terminating NUL (but, of course,
954 * we never write past laddr[len-1]).
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 */
956int
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +0000957umovestr(struct tcb *tcp, long addr, int len, char *laddr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958{
Denys Vlasenko16940922013-03-01 18:52:59 +0100959#if SIZEOF_LONG == 4
960 const unsigned long x01010101 = 0x01010101ul;
961 const unsigned long x80808080 = 0x80808080ul;
962#elif SIZEOF_LONG == 8
963 const unsigned long x01010101 = 0x0101010101010101ul;
964 const unsigned long x80808080 = 0x8080808080808080ul;
965#else
966# error SIZEOF_LONG > 8
967#endif
968
Roland McGratheb9e2e82009-06-02 16:49:22 -0700969 int pid = tcp->pid;
Denys Vlasenko16940922013-03-01 18:52:59 +0100970 int n, m, nread;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 union {
Denys Vlasenko16940922013-03-01 18:52:59 +0100972 unsigned long val;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 char x[sizeof(long)];
974 } u;
975
Denys Vlasenko2544f982013-02-19 17:39:56 +0100976#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100977 if (current_wordsize < sizeof(addr))
978 addr &= (1ul << 8 * current_wordsize) - 1;
Dmitry V. Levin856c7ed2011-12-26 20:12:02 +0000979#endif
980
Dmitry V. Levin97005922013-02-26 21:16:22 +0000981 nread = 0;
Denys Vlasenko3af224c2012-01-28 01:46:33 +0100982 if (!process_vm_readv_not_supported) {
983 struct iovec local[1], remote[1];
984
985 local[0].iov_base = laddr;
986 remote[0].iov_base = (void*)addr;
987
988 while (len > 0) {
989 int end_in_page;
990 int r;
991 int chunk_len;
992
993 /* Don't read kilobytes: most strings are short */
994 chunk_len = len;
995 if (chunk_len > 256)
996 chunk_len = 256;
997 /* Don't cross pages. I guess otherwise we can get EFAULT
998 * and fail to notice that terminating NUL lies
999 * in the existing (first) page.
1000 * (I hope there aren't arches with pages < 4K)
1001 */
1002 end_in_page = ((addr + chunk_len) & 4095);
1003 r = chunk_len - end_in_page;
1004 if (r > 0) /* if chunk_len > end_in_page */
1005 chunk_len = r; /* chunk_len -= end_in_page */
1006
1007 local[0].iov_len = remote[0].iov_len = chunk_len;
Dmitry V. Levin97005922013-02-26 21:16:22 +00001008 r = process_vm_readv(pid, local, 1, remote, 1, 0);
1009 if (r > 0) {
1010 if (memchr(local[0].iov_base, '\0', r))
1011 return 1;
1012 local[0].iov_base += r;
1013 remote[0].iov_base += r;
1014 len -= r;
1015 nread += r;
1016 continue;
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001017 }
Dmitry V. Levin97005922013-02-26 21:16:22 +00001018 switch (errno) {
1019 case ENOSYS:
1020 process_vm_readv_not_supported = 1;
1021 goto vm_readv_didnt_work;
1022 case ESRCH:
1023 /* the process is gone */
1024 return -1;
1025 case EFAULT: case EIO: case EPERM:
1026 /* address space is inaccessible */
1027 if (nread) {
1028 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1029 nread, nread + len, addr);
1030 }
1031 return -1;
1032 default:
1033 /* all the rest is strange and should be reported */
1034 perror_msg("process_vm_readv");
1035 return -1;
1036 }
Denys Vlasenko3af224c2012-01-28 01:46:33 +01001037 }
1038 return 0;
1039 }
1040 vm_readv_didnt_work:
1041
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 if (addr & (sizeof(long) - 1)) {
1043 /* addr not a multiple of sizeof(long) */
1044 n = addr - (addr & -sizeof(long)); /* residue */
1045 addr &= -sizeof(long); /* residue */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001046 errno = 0;
1047 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001048 switch (errno) {
1049 case 0:
1050 break;
1051 case ESRCH: case EINVAL:
1052 /* these could be seen if the process is gone */
1053 return -1;
1054 case EFAULT: case EIO: case EPERM:
1055 /* address space is inaccessible */
1056 return -1;
1057 default:
1058 /* all the rest is strange and should be reported */
1059 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1060 pid, addr);
1061 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001062 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001063 m = MIN(sizeof(long) - n, len);
1064 memcpy(laddr, &u.x[n], m);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001065 while (n & (sizeof(long) - 1))
1066 if (u.x[n++] == '\0')
Denys Vlasenko6cecba52012-01-20 11:56:00 +01001067 return 1;
Denys Vlasenko16940922013-03-01 18:52:59 +01001068 addr += sizeof(long);
1069 laddr += m;
1070 nread += m;
1071 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001072 }
Denys Vlasenko16940922013-03-01 18:52:59 +01001073
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 while (len) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001075 errno = 0;
1076 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
Dmitry V. Levin97005922013-02-26 21:16:22 +00001077 switch (errno) {
1078 case 0:
1079 break;
1080 case ESRCH: case EINVAL:
1081 /* these could be seen if the process is gone */
1082 return -1;
1083 case EFAULT: case EIO: case EPERM:
1084 /* address space is inaccessible */
1085 if (nread) {
1086 perror_msg("umovestr: short read (%d < %d) @0x%lx",
1087 nread, nread + len, addr - nread);
1088 }
1089 return -1;
1090 default:
1091 /* all the rest is strange and should be reported */
1092 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%lx",
1093 pid, addr);
1094 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001095 }
Denys Vlasenkoa47e6b92012-01-21 04:01:56 +01001096 m = MIN(sizeof(long), len);
1097 memcpy(laddr, u.x, m);
Denys Vlasenko16940922013-03-01 18:52:59 +01001098 /* "If a NUL char exists in this word" */
1099 if ((u.val - x01010101) & ~u.val & x80808080)
1100 return 1;
1101 addr += sizeof(long);
1102 laddr += m;
1103 nread += m;
1104 len -= m;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 }
John Hughesaa09c6b2001-05-15 14:53:43 +00001106 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107}
1108
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109int
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001110upeek(int pid, long off, long *res)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111{
1112 long val;
1113
Roland McGratheb9e2e82009-06-02 16:49:22 -07001114 errno = 0;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001115 val = ptrace(PTRACE_PEEKUSER, (pid_t)pid, (char *) off, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001116 if (val == -1 && errno) {
1117 if (errno != ESRCH) {
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001118 perror_msg("upeek: PTRACE_PEEKUSER pid:%d @0x%lx)", pid, off);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001119 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001121 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 *res = val;
1123 return 0;
1124}
1125
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001126/* Note! On new kernels (about 2.5.46+), we use PTRACE_O_TRACECLONE
1127 * and PTRACE_O_TRACE[V]FORK for tracing children.
1128 * If you are adding a new arch which is only supported by newer kernels,
1129 * you most likely don't need to add any code below
1130 * beside a dummy "return 0" block in change_syscall().
1131 */
1132
Denys Vlasenko3bb7cd62009-02-09 18:55:59 +00001133/*
1134 * These #if's are huge, please indent them correctly.
1135 * It's easy to get confused otherwise.
1136 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001138#include "syscall.h"
Roland McGrath3291ef22008-05-20 00:34:34 +00001139
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001140#ifndef CLONE_PTRACE
1141# define CLONE_PTRACE 0x00002000
1142#endif
1143#ifndef CLONE_VFORK
1144# define CLONE_VFORK 0x00004000
1145#endif
1146#ifndef CLONE_VM
1147# define CLONE_VM 0x00000100
1148#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001149
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001150#ifdef IA64
Roland McGrathd81f1d92003-01-09 06:53:34 +00001151
1152typedef unsigned long *arg_setup_state;
1153
1154static int
1155arg_setup(struct tcb *tcp, arg_setup_state *state)
1156{
Jan Kratochvil1f942712008-08-06 21:38:52 +00001157 unsigned long cfm, sof, sol;
1158 long bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001159
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001160 if (ia64_ia32mode) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001161 /* Satisfy a false GCC warning. */
1162 *state = NULL;
Roland McGrath08267b82004-02-20 22:56:43 +00001163 return 0;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001164 }
Roland McGrath08267b82004-02-20 22:56:43 +00001165
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001166 if (upeek(tcp->pid, PT_AR_BSP, &bsp) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001167 return -1;
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001168 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001169 return -1;
1170
1171 sof = (cfm >> 0) & 0x7f;
1172 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00001173 bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001174
Jan Kratochvil1f942712008-08-06 21:38:52 +00001175 *state = (unsigned long *) bsp;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001176 return 0;
1177}
1178
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001179# define arg_finish_change(tcp, state) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180
Roland McGrathd81f1d92003-01-09 06:53:34 +00001181static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001182get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001183{
Roland McGrath08267b82004-02-20 22:56:43 +00001184 int ret;
1185
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001186 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001187 ret = upeek(tcp->pid, PT_R11, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001188 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001189 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001190 (unsigned long) ia64_rse_skip_regs(*state, 0),
1191 sizeof(long), (void *) valp);
1192 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001193}
1194
1195static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001196get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001197{
Roland McGrath08267b82004-02-20 22:56:43 +00001198 int ret;
1199
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001200 if (ia64_ia32mode)
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001201 ret = upeek(tcp->pid, PT_R9, valp);
Roland McGrath08267b82004-02-20 22:56:43 +00001202 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001203 ret = umoven(tcp,
Roland McGrath08267b82004-02-20 22:56:43 +00001204 (unsigned long) ia64_rse_skip_regs(*state, 1),
1205 sizeof(long), (void *) valp);
1206 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001207}
Roland McGrathd81f1d92003-01-09 06:53:34 +00001208
1209static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001210set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211{
Roland McGrath08267b82004-02-20 22:56:43 +00001212 int req = PTRACE_POKEDATA;
1213 void *ap;
1214
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001215 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001216 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1217 req = PTRACE_POKEUSER;
1218 } else
1219 ap = ia64_rse_skip_regs(*state, 0);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001220 errno = 0;
1221 ptrace(req, tcp->pid, ap, val);
1222 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001223}
1224
1225static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001226set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001227{
Roland McGrath08267b82004-02-20 22:56:43 +00001228 int req = PTRACE_POKEDATA;
1229 void *ap;
1230
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001231 if (ia64_ia32mode) {
Roland McGrath08267b82004-02-20 22:56:43 +00001232 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1233 req = PTRACE_POKEUSER;
1234 } else
1235 ap = ia64_rse_skip_regs(*state, 1);
Roland McGratheb9e2e82009-06-02 16:49:22 -07001236 errno = 0;
1237 ptrace(req, tcp->pid, ap, val);
1238 return errno ? -1 : 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001239}
1240
Roland McGrathb659f872008-07-18 01:19:36 +00001241/* ia64 does not return the input arguments from functions (and syscalls)
1242 according to ia64 RSE (Register Stack Engine) behavior. */
1243
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001244# define restore_arg0(tcp, state, val) ((void) (state), 0)
1245# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathb659f872008-07-18 01:19:36 +00001246
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001247#elif defined(SPARC) || defined(SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001249# if defined(SPARC64)
1250# undef PTRACE_GETREGS
1251# define PTRACE_GETREGS PTRACE_GETREGS64
1252# undef PTRACE_SETREGS
1253# define PTRACE_SETREGS PTRACE_SETREGS64
1254# endif
1255
Mike Frysinger8566c502009-10-12 11:05:14 -04001256typedef struct pt_regs arg_setup_state;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001258# define arg_setup(tcp, state) \
1259 (ptrace(PTRACE_GETREGS, (tcp)->pid, (char *) (state), 0))
1260# define arg_finish_change(tcp, state) \
1261 (ptrace(PTRACE_SETREGS, (tcp)->pid, (char *) (state), 0))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001263# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1264# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1265# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1266# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1267# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001269#else /* other architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001271# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001272/* Note: this is only true for the `clone' system call, which handles
1273 arguments specially. We could as well say that its first two arguments
1274 are swapped relative to other architectures, but that would just be
1275 another #ifdef in the calls. */
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001276# define arg0_offset PT_GPR3
1277# define arg1_offset PT_ORIGGPR2
1278# define restore_arg0(tcp, state, val) ((void) (state), 0)
1279# define restore_arg1(tcp, state, val) ((void) (state), 0)
1280# define arg0_index 1
1281# define arg1_index 0
1282# elif defined(ALPHA) || defined(MIPS)
1283# define arg0_offset REG_A0
1284# define arg1_offset (REG_A0+1)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001285# elif defined(POWERPC)
1286# define arg0_offset (sizeof(unsigned long)*PT_R3)
1287# define arg1_offset (sizeof(unsigned long)*PT_R4)
1288# define restore_arg0(tcp, state, val) ((void) (state), 0)
1289# elif defined(HPPA)
1290# define arg0_offset PT_GR26
1291# define arg1_offset (PT_GR26-4)
H.J. Lu35be5812012-04-16 13:00:01 +02001292# elif defined(X86_64) || defined(X32)
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001293# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1294# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1295# elif defined(SH)
1296# define arg0_offset (4*(REG_REG0+4))
1297# define arg1_offset (4*(REG_REG0+5))
1298# elif defined(SH64)
1299 /* ABI defines arg0 & 1 in r2 & r3 */
1300# define arg0_offset (REG_OFFSET+16)
1301# define arg1_offset (REG_OFFSET+24)
1302# define restore_arg0(tcp, state, val) 0
1303# elif defined CRISV10 || defined CRISV32
1304# define arg0_offset (4*PT_R11)
1305# define arg1_offset (4*PT_ORIG_R10)
1306# define restore_arg0(tcp, state, val) 0
1307# define restore_arg1(tcp, state, val) 0
1308# define arg0_index 1
1309# define arg1_index 0
1310# else
1311# define arg0_offset 0
1312# define arg1_offset 4
1313# if defined ARM
1314# define restore_arg0(tcp, state, val) 0
1315# endif
1316# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317
1318typedef int arg_setup_state;
1319
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001320# define arg_setup(tcp, state) (0)
1321# define arg_finish_change(tcp, state) 0
Denys Vlasenko752e5a02013-06-28 14:35:47 +02001322# define get_arg0(tcp, cookie, valp) (upeek((tcp)->pid, arg0_offset, (valp)))
1323# define get_arg1(tcp, cookie, valp) (upeek((tcp)->pid, arg1_offset, (valp)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324
1325static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001326set_arg0(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001327{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001328 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001329}
1330
1331static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001332set_arg1(struct tcb *tcp, void *cookie, long val)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001333{
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001334 return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001335}
1336
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001337#endif /* architectures */
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001339#ifndef restore_arg0
1340# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1341#endif
1342#ifndef restore_arg1
1343# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1344#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001345
Denys Vlasenko2d1e90f2012-02-25 02:46:14 +01001346#ifndef arg0_index
1347# define arg0_index 0
1348# define arg1_index 1
1349#endif
Roland McGrath90d0afd2004-03-01 21:05:16 +00001350
James Hogan05eb9052012-11-29 17:37:37 +00001351static int
1352change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
1353{
1354#if defined(I386)
1355 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
1356 return -1;
1357 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001358#elif defined(X86_64)
James Hogan05eb9052012-11-29 17:37:37 +00001359 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
1360 return -1;
1361 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001362#elif defined(X32)
1363 /* setbpt/clearbpt never used: */
1364 /* X32 is only supported since about linux-3.0.30 */
James Hogan05eb9052012-11-29 17:37:37 +00001365#elif defined(POWERPC)
1366 if (ptrace(PTRACE_POKEUSER, tcp->pid,
1367 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
1368 return -1;
1369 return 0;
1370#elif defined(S390) || defined(S390X)
1371 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
1372 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new) < 0)
1373 return -1;
1374 return 0;
1375#elif defined(M68K)
1376 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new) < 0)
1377 return -1;
1378 return 0;
1379#elif defined(SPARC) || defined(SPARC64)
1380 state->u_regs[U_REG_G1] = new;
1381 return 0;
1382#elif defined(MIPS)
1383 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new) < 0)
1384 return -1;
1385 return 0;
1386#elif defined(ALPHA)
1387 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new) < 0)
1388 return -1;
1389 return 0;
1390#elif defined(AVR32)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001391 /* setbpt/clearbpt never used: */
1392 /* AVR32 is only supported since about linux-2.6.19 */
James Hogan05eb9052012-11-29 17:37:37 +00001393#elif defined(BFIN)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001394 /* setbpt/clearbpt never used: */
1395 /* Blackfin is only supported since about linux-2.6.23 */
James Hogan05eb9052012-11-29 17:37:37 +00001396#elif defined(IA64)
Denys Vlasenkoc09646a2013-07-01 12:28:17 +02001397 if (ia64_ia32mode) {
James Hogan05eb9052012-11-29 17:37:37 +00001398 switch (new) {
1399 case 2:
1400 break; /* x86 SYS_fork */
1401 case SYS_clone:
1402 new = 120;
1403 break;
1404 default:
1405 fprintf(stderr, "%s: unexpected syscall %d\n",
1406 __FUNCTION__, new);
1407 return -1;
1408 }
1409 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new) < 0)
1410 return -1;
1411 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new) < 0)
1412 return -1;
1413 return 0;
1414#elif defined(HPPA)
1415 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new) < 0)
1416 return -1;
1417 return 0;
1418#elif defined(SH)
1419 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new) < 0)
1420 return -1;
1421 return 0;
1422#elif defined(SH64)
1423 /* Top half of reg encodes the no. of args n as 0x1n.
1424 Assume 0 args as kernel never actually checks... */
1425 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
1426 0x100000 | new) < 0)
1427 return -1;
1428 return 0;
1429#elif defined(CRISV10) || defined(CRISV32)
1430 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R9), new) < 0)
1431 return -1;
1432 return 0;
1433#elif defined(ARM)
1434 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
1435# ifndef PTRACE_SET_SYSCALL
1436# define PTRACE_SET_SYSCALL 23
1437# endif
1438 if (ptrace(PTRACE_SET_SYSCALL, tcp->pid, 0, new & 0xffff) != 0)
1439 return -1;
1440 return 0;
Denys Vlasenkobf357fc2013-02-12 13:06:51 +01001441#elif defined(AARCH64)
1442 /* setbpt/clearbpt never used: */
1443 /* AARCH64 is only supported since about linux-3.0.31 */
James Hogan05eb9052012-11-29 17:37:37 +00001444#elif defined(TILE)
Denys Vlasenkod27809c2013-02-12 12:50:10 +01001445 /* setbpt/clearbpt never used: */
1446 /* Tilera CPUs are only supported since about linux-2.6.34 */
James Hogan05eb9052012-11-29 17:37:37 +00001447#elif defined(MICROBLAZE)
Denys Vlasenkoa86696b2013-02-12 16:07:54 +01001448 /* setbpt/clearbpt never used: */
1449 /* microblaze is only supported since about linux-2.6.30 */
Christian Svensson492f81f2013-02-14 13:26:27 +01001450#elif defined(OR1K)
1451 /* never reached; OR1K is only supported by kernels since 3.1.0. */
James Hogan5f999a82013-02-22 14:44:10 +00001452#elif defined(METAG)
1453 /* setbpt/clearbpt never used: */
1454 /* Meta is only supported since linux-3.7 */
Chris Zankel8f636ed2013-03-25 10:22:07 -07001455#elif defined(XTENSA)
1456 /* setbpt/clearbpt never used: */
1457 /* Xtensa is only supported since linux 2.6.13 */
Vineet Gupta7daacbb2013-08-16 12:47:06 +05301458#elif defined(ARC)
1459 /* setbpt/clearbpt never used: */
1460 /* ARC only supported since 3.9 */
James Hogan05eb9052012-11-29 17:37:37 +00001461#else
1462#warning Do not know how to handle change_syscall for this architecture
1463#endif /* architecture */
1464 return -1;
1465}
1466
Roland McGrathd81f1d92003-01-09 06:53:34 +00001467int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001468setbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001469{
Roland McGrath3291ef22008-05-20 00:34:34 +00001470 static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
Roland McGrathd81f1d92003-01-09 06:53:34 +00001471 arg_setup_state state;
1472
1473 if (tcp->flags & TCB_BPTSET) {
1474 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1475 return -1;
1476 }
1477
Roland McGrath3291ef22008-05-20 00:34:34 +00001478 /*
1479 * It's a silly kludge to initialize this with a search at runtime.
1480 * But it's better than maintaining another magic thing in the
1481 * godforsaken tables.
1482 */
1483 if (clone_scno[current_personality] == 0) {
1484 int i;
1485 for (i = 0; i < nsyscalls; ++i)
1486 if (sysent[i].sys_func == sys_clone) {
1487 clone_scno[current_personality] = i;
1488 break;
1489 }
1490 }
1491
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001492 if (tcp->s_ent->sys_func == sys_fork ||
1493 tcp->s_ent->sys_func == sys_vfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001494 if (arg_setup(tcp, &state) < 0
1495 || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1496 || get_arg1(tcp, &state, &tcp->inst[1]) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001497 || change_syscall(tcp, &state,
1498 clone_scno[current_personality]) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001499 || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1500 || set_arg1(tcp, &state, 0) < 0
1501 || arg_finish_change(tcp, &state) < 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001502 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001503 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1504 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001505 tcp->flags |= TCB_BPTSET;
1506 return 0;
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001507 }
Roland McGrathd81f1d92003-01-09 06:53:34 +00001508
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001509 if (tcp->s_ent->sys_func == sys_clone) {
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001510 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001511 contrary to x86 vfork above. Even on x86 we turn the
Jan Kratochvil8fc95752008-08-06 21:43:35 +00001512 vfork semantics into plain fork - each application must not
1513 depend on the vfork specifics according to POSIX. We would
1514 hang waiting for the parent resume otherwise. We need to
1515 clear also CLONE_VM but only in the CLONE_VFORK case as
1516 otherwise we would break pthread_create. */
1517
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001518 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1519 if (new_arg0 & CLONE_VFORK)
1520 new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1521 if (arg_setup(tcp, &state) < 0
1522 || set_arg0(tcp, &state, new_arg0) < 0
1523 || arg_finish_change(tcp, &state) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001524 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001525 tcp->inst[0] = tcp->u_arg[arg0_index];
1526 tcp->inst[1] = tcp->u_arg[arg1_index];
Denys Vlasenko55980f52012-05-14 16:40:28 +02001527 tcp->flags |= TCB_BPTSET;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001528 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001529 }
1530
Dmitry V. Levin0c661512012-02-20 21:17:58 +00001531 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1532 tcp->scno, tcp->pid);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001533 return -1;
1534}
1535
1536int
Denys Vlasenko12014262011-05-30 14:00:14 +02001537clearbpt(struct tcb *tcp)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001538{
1539 arg_setup_state state;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001540 if (arg_setup(tcp, &state) < 0
James Hogan05eb9052012-11-29 17:37:37 +00001541 || change_syscall(tcp, &state, tcp->scno) < 0
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001542 || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1543 || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1544 || arg_finish_change(tcp, &state))
Denys Vlasenkoc133bf02011-06-23 21:57:54 +02001545 if (errno != ESRCH)
1546 return -1;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001547 tcp->flags &= ~TCB_BPTSET;
1548 return 0;
1549}