Branch data Line data Source code
1 : : /*
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>
5 : : * 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>
9 : : * Copyright (c) 1999-2017 The strace developers.
10 : : * All rights reserved.
11 : : *
12 : : * Redistribution and use in source and binary forms, with or without
13 : : * modification, are permitted provided that the following conditions
14 : : * are met:
15 : : * 1. Redistributions of source code must retain the above copyright
16 : : * notice, this list of conditions and the following disclaimer.
17 : : * 2. Redistributions in binary form must reproduce the above copyright
18 : : * notice, this list of conditions and the following disclaimer in the
19 : : * documentation and/or other materials provided with the distribution.
20 : : * 3. The name of the author may not be used to endorse or promote products
21 : : * derived from this software without specific prior written permission.
22 : : *
23 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 : : */
34 : :
35 : : #include "defs.h"
36 : : #include <sys/param.h>
37 : : #include <fcntl.h>
38 : : #include <stdarg.h>
39 : : #ifdef HAVE_SYS_XATTR_H
40 : : # include <sys/xattr.h>
41 : : #endif
42 : : #include <sys/uio.h>
43 : : #include <asm/unistd.h>
44 : :
45 : : #include "scno.h"
46 : : #include "regs.h"
47 : : #include "ptrace.h"
48 : :
49 : : int
50 : 10987 : string_to_uint_ex(const char *const str, char **const endptr,
51 : : const unsigned int max_val, const char *const accepted_ending)
52 : : {
53 : : char *end;
54 : : long val;
55 : :
56 [ + + ]: 10987 : if (!*str)
57 : : return -1;
58 : :
59 : 10971 : errno = 0;
60 : 10971 : val = strtol(str, &end, 10);
61 : :
62 [ + + ][ + + ]: 10971 : if (str == end || val < 0 || (unsigned long) val > max_val
[ + + ]
63 [ - + ][ # # ]: 10129 : || (val == LONG_MAX && errno == ERANGE))
64 : : return -1;
65 : :
66 [ + + ][ + + ]: 10129 : if (*end && (!accepted_ending || !strchr(accepted_ending, *end)))
[ - + ][ # # ]
[ # # ][ + + ]
67 : : return -1;
68 : :
69 [ + + ]: 10101 : if (endptr)
70 : 1422 : *endptr = end;
71 : :
72 : 10101 : return (int) val;
73 : : }
74 : :
75 : : int
76 : 7035 : string_to_uint(const char *const str)
77 : : {
78 : 7035 : return string_to_uint_upto(str, INT_MAX);
79 : : }
80 : :
81 : : int
82 : 5172 : tv_nz(const struct timeval *a)
83 : : {
84 [ + - ][ + - ]: 5172 : return a->tv_sec || a->tv_usec;
85 : : }
86 : :
87 : : int
88 : 44138 : tv_cmp(const struct timeval *a, const struct timeval *b)
89 : : {
90 [ + + ]: 44138 : if (a->tv_sec < b->tv_sec
91 [ + + ][ + + ]: 44104 : || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
92 : : return -1;
93 [ + + ]: 44045 : if (a->tv_sec > b->tv_sec
94 [ + - ][ + + ]: 43993 : || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
95 : : return 1;
96 : 33549 : return 0;
97 : : }
98 : :
99 : : double
100 : 188 : tv_float(const struct timeval *tv)
101 : : {
102 : 188 : return tv->tv_sec + tv->tv_usec/1000000.0;
103 : : }
104 : :
105 : : void
106 : 5339 : tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
107 : : {
108 : 5339 : tv->tv_sec = a->tv_sec + b->tv_sec;
109 : 5339 : tv->tv_usec = a->tv_usec + b->tv_usec;
110 [ - + ]: 5339 : if (tv->tv_usec >= 1000000) {
111 : 0 : tv->tv_sec++;
112 : 0 : tv->tv_usec -= 1000000;
113 : : }
114 : 5339 : }
115 : :
116 : : void
117 : 130041 : tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
118 : : {
119 : 130041 : tv->tv_sec = a->tv_sec - b->tv_sec;
120 : 130041 : tv->tv_usec = a->tv_usec - b->tv_usec;
121 [ - + ]: 130041 : if (((long) tv->tv_usec) < 0) {
122 : 0 : tv->tv_sec--;
123 : 0 : tv->tv_usec += 1000000;
124 : : }
125 : 130041 : }
126 : :
127 : : void
128 : 183 : tv_div(struct timeval *tv, const struct timeval *a, int n)
129 : : {
130 : 183 : tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
131 : 183 : tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
132 : 183 : tv->tv_usec %= 1000000;
133 : 183 : }
134 : :
135 : : void
136 : 183 : tv_mul(struct timeval *tv, const struct timeval *a, int n)
137 : : {
138 : 183 : tv->tv_usec = a->tv_usec * n;
139 : 183 : tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
140 : 183 : tv->tv_usec %= 1000000;
141 : 183 : }
142 : :
143 : : #if !defined HAVE_STPCPY
144 : : char *
145 : : stpcpy(char *dst, const char *src)
146 : : {
147 : : while ((*dst = *src++) != '\0')
148 : : dst++;
149 : : return dst;
150 : : }
151 : : #endif
152 : :
153 : : /* Find a next bit which is set.
154 : : * Starts testing at cur_bit.
155 : : * Returns -1 if no more bits are set.
156 : : *
157 : : * We never touch bytes we don't need to.
158 : : * On big-endian, array is assumed to consist of
159 : : * current_wordsize wide words: for example, is current_wordsize is 4,
160 : : * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
161 : : * On little-endian machines, word size is immaterial.
162 : : */
163 : : int
164 : 578 : next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
165 : : {
166 : 578 : const unsigned endian = 1;
167 : 578 : int little_endian = *(char *) (void *) &endian;
168 : :
169 : 578 : const uint8_t *array = bit_array;
170 : 578 : unsigned pos = cur_bit / 8;
171 : 2912 : unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
172 : :
173 : : for (;;) {
174 : : uint8_t bitmask;
175 : : uint8_t cur_byte;
176 : :
177 [ + + ]: 2912 : if (cur_bit >= size_bits)
178 : : return -1;
179 : 2707 : cur_byte = array[pos ^ pos_xor_mask];
180 [ + + ]: 2707 : if (cur_byte == 0) {
181 : 2167 : cur_bit = (cur_bit + 8) & (-8);
182 : 2167 : pos++;
183 : 2167 : continue;
184 : : }
185 : 540 : bitmask = 1 << (cur_bit & 7);
186 : : for (;;) {
187 [ + + ]: 1646 : if (cur_byte & bitmask)
188 : 367 : return cur_bit;
189 : 1279 : cur_bit++;
190 [ + + ]: 1279 : if (cur_bit >= size_bits)
191 : : return -1;
192 : 1273 : bitmask <<= 1;
193 : : /* This check *can't be* optimized out: */
194 [ + + ]: 1273 : if (bitmask == 0)
195 : : break;
196 : : }
197 : 167 : pos++;
198 : : }
199 : : }
200 : :
201 : : /*
202 : : * Fetch 64bit argument at position arg_no and
203 : : * return the index of the next argument.
204 : : */
205 : : int
206 : 1154 : getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
207 : : {
208 : : #if SIZEOF_KERNEL_LONG_T > 4
209 : : # ifndef current_klongsize
210 [ + + ][ + + ]: 1720 : if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
211 : : # if defined(AARCH64) || defined(POWERPC64)
212 : : /* Align arg_no to the next even number. */
213 : : arg_no = (arg_no + 1) & 0xe;
214 : : # endif /* AARCH64 || POWERPC64 */
215 : 862 : *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
216 : 862 : arg_no += 2;
217 : : } else
218 : : # endif /* !current_klongsize */
219 : : {
220 : 858 : *val = tcp->u_arg[arg_no];
221 : 858 : arg_no++;
222 : : }
223 : : #else /* SIZEOF_KERNEL_LONG_T == 4 */
224 : : # if defined __ARM_EABI__ \
225 : : || defined LINUX_MIPSO32 \
226 : : || defined POWERPC \
227 : : || defined XTENSA
228 : : /* Align arg_no to the next even number. */
229 : : arg_no = (arg_no + 1) & 0xe;
230 : : # elif defined SH
231 : : /*
232 : : * The SH4 ABI does allow long longs in odd-numbered registers, but
233 : : * does not allow them to be split between registers and memory - and
234 : : * there are only four argument registers for normal functions. As a
235 : : * result, pread, for example, takes an extra padding argument before
236 : : * the offset. This was changed late in the 2.4 series (around 2.4.20).
237 : : */
238 : : if (arg_no == 3)
239 : : arg_no++;
240 : : # endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
241 : : *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
242 : : arg_no += 2;
243 : : #endif
244 : :
245 : 1154 : return arg_no;
246 : : }
247 : :
248 : : /*
249 : : * Print 64bit argument at position arg_no and
250 : : * return the index of the next argument.
251 : : */
252 : : int
253 : 566 : printllval(struct tcb *tcp, const char *format, int arg_no)
254 : : {
255 : 566 : unsigned long long val = 0;
256 : :
257 : 566 : arg_no = getllval(tcp, &val, arg_no);
258 : 566 : tprintf(format, val);
259 : 566 : return arg_no;
260 : : }
261 : :
262 : : void
263 : 118608 : printaddr(const kernel_ulong_t addr)
264 : : {
265 [ + + ]: 118608 : if (!addr)
266 : 69909 : tprints("NULL");
267 : : else
268 : 48699 : tprintf("%#" PRI_klx, addr);
269 : 118608 : }
270 : :
271 : : #define DEF_PRINTNUM(name, type) \
272 : : bool \
273 : : printnum_ ## name(struct tcb *const tcp, const kernel_ulong_t addr, \
274 : : const char *const fmt) \
275 : : { \
276 : : type num; \
277 : : if (umove_or_printaddr(tcp, addr, &num)) \
278 : : return false; \
279 : : tprints("["); \
280 : : tprintf(fmt, num); \
281 : : tprints("]"); \
282 : : return true; \
283 : : }
284 : :
285 : : #define DEF_PRINTNUM_ADDR(name, type) \
286 : : bool \
287 : : printnum_addr_ ## name(struct tcb *tcp, const kernel_ulong_t addr) \
288 : : { \
289 : : type num; \
290 : : if (umove_or_printaddr(tcp, addr, &num)) \
291 : : return false; \
292 : : tprints("["); \
293 : : printaddr(num); \
294 : : tprints("]"); \
295 : : return true; \
296 : : }
297 : :
298 : : #define DEF_PRINTPAIR(name, type) \
299 : : bool \
300 : : printpair_ ## name(struct tcb *const tcp, const kernel_ulong_t addr, \
301 : : const char *const fmt) \
302 : : { \
303 : : type pair[2]; \
304 : : if (umove_or_printaddr(tcp, addr, &pair)) \
305 : : return false; \
306 : : tprints("["); \
307 : : tprintf(fmt, pair[0]); \
308 : : tprints(", "); \
309 : : tprintf(fmt, pair[1]); \
310 : : tprints("]"); \
311 : : return true; \
312 : : }
313 : :
314 [ + + ]: 2142 : DEF_PRINTNUM(int, int)
315 [ + + ]: 38 : DEF_PRINTNUM_ADDR(int, unsigned int)
316 [ - + ]: 16 : DEF_PRINTPAIR(int, int)
317 [ - + ]: 12 : DEF_PRINTNUM(short, short)
318 [ + + ]: 162 : DEF_PRINTNUM(int64, uint64_t)
319 [ + + ]: 24 : DEF_PRINTNUM_ADDR(int64, uint64_t)
320 [ + + ]: 24 : DEF_PRINTPAIR(int64, uint64_t)
321 : :
322 : : #ifndef current_wordsize
323 : : bool
324 : 37 : printnum_long_int(struct tcb *const tcp, const kernel_ulong_t addr,
325 : : const char *const fmt_long, const char *const fmt_int)
326 : : {
327 [ + + ]: 37 : if (current_wordsize > sizeof(int)) {
328 : 14 : return printnum_int64(tcp, addr, fmt_long);
329 : : } else {
330 : 23 : return printnum_int(tcp, addr, fmt_int);
331 : : }
332 : : }
333 : :
334 : : bool
335 : 23 : printnum_addr_long_int(struct tcb *tcp, const kernel_ulong_t addr)
336 : : {
337 [ + + ]: 23 : if (current_wordsize > sizeof(int)) {
338 : 8 : return printnum_addr_int64(tcp, addr);
339 : : } else {
340 : 15 : return printnum_addr_int(tcp, addr);
341 : : }
342 : : }
343 : : #endif /* !current_wordsize */
344 : :
345 : : #ifndef current_klongsize
346 : : bool
347 : 8 : printnum_addr_klong_int(struct tcb *tcp, const kernel_ulong_t addr)
348 : : {
349 [ + + ]: 8 : if (current_klongsize > sizeof(int)) {
350 : 4 : return printnum_addr_int64(tcp, addr);
351 : : } else {
352 : 4 : return printnum_addr_int(tcp, addr);
353 : : }
354 : : }
355 : : #endif /* !current_klongsize */
356 : :
357 : : /**
358 : : * Prints time to a (static internal) buffer and returns pointer to it.
359 : : *
360 : : * @param sec Seconds since epoch.
361 : : * @param part_sec Amount of second parts since the start of a second.
362 : : * @param max_part_sec Maximum value of a valid part_sec.
363 : : * @param width 1 + floor(log10(max_part_sec)).
364 : : */
365 : : static const char *
366 : 242 : sprinttime_ex(const long long sec, const unsigned long long part_sec,
367 : : const unsigned int max_part_sec, const int width)
368 : : {
369 : : static char buf[sizeof(int) * 3 * 6 + sizeof(part_sec) * 3
370 : : + sizeof("+0000")];
371 : :
372 [ + + ][ + + ]: 242 : if ((sec == 0 && part_sec == 0) || part_sec > max_part_sec)
373 : : return NULL;
374 : :
375 : 216 : time_t t = (time_t) sec;
376 : 216 : struct tm *tmp = (sec == t) ? localtime(&t) : NULL;
377 [ + + ]: 216 : if (!tmp)
378 : : return NULL;
379 : :
380 : 215 : size_t pos = strftime(buf, sizeof(buf), "%FT%T", tmp);
381 [ + - ]: 215 : if (!pos)
382 : : return NULL;
383 : :
384 [ + + ]: 215 : if (part_sec > 0) {
385 : 191 : int ret = snprintf(buf + pos, sizeof(buf) - pos, ".%0*llu",
386 : : width, part_sec);
387 : :
388 [ + - ][ + - ]: 191 : if (ret < 0 || (size_t) ret >= sizeof(buf) - pos)
389 : : return NULL;
390 : :
391 : 191 : pos += ret;
392 : : }
393 : :
394 [ - + ]: 215 : return strftime(buf + pos, sizeof(buf) - pos, "%z", tmp) ? buf : NULL;
395 : : }
396 : :
397 : : const char *
398 : 10 : sprinttime(long long sec)
399 : : {
400 : 10 : return sprinttime_ex(sec, 0, 0, 0);
401 : : }
402 : :
403 : : const char *
404 : 24 : sprinttime_usec(long long sec, unsigned long long usec)
405 : : {
406 : 24 : return sprinttime_ex(sec, usec, 999999, 6);
407 : : }
408 : :
409 : : const char *
410 : 208 : sprinttime_nsec(long long sec, unsigned long long nsec)
411 : : {
412 : 208 : return sprinttime_ex(sec, nsec, 999999999, 9);
413 : : }
414 : :
415 : : enum sock_proto
416 : 508 : getfdproto(struct tcb *tcp, int fd)
417 : : {
418 : : #ifdef HAVE_SYS_XATTR_H
419 : 508 : size_t bufsize = 256;
420 : 508 : char buf[bufsize];
421 : : ssize_t r;
422 : : char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
423 : :
424 [ + - ]: 508 : if (fd < 0)
425 : : return SOCK_PROTO_UNKNOWN;
426 : :
427 : 508 : sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
428 : 508 : r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
429 [ + - ]: 508 : if (r <= 0)
430 : : return SOCK_PROTO_UNKNOWN;
431 : : else {
432 : : /*
433 : : * This is a protection for the case when the kernel
434 : : * side does not append a null byte to the buffer.
435 : : */
436 : 508 : buf[r] = '\0';
437 : :
438 : 508 : return get_proto_by_name(buf);
439 : : }
440 : : #else
441 : : return SOCK_PROTO_UNKNOWN;
442 : : #endif
443 : : }
444 : :
445 : : unsigned long
446 : 346 : getfdinode(struct tcb *tcp, int fd)
447 : : {
448 : : char path[PATH_MAX + 1];
449 : :
450 [ + - ]: 346 : if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
451 : 346 : const char *str = STR_STRIP_PREFIX(path, "socket:[");
452 : :
453 [ + - ]: 346 : if (str != path) {
454 : 346 : const size_t str_len = strlen(str);
455 [ + - ][ + - ]: 346 : if (str_len && str[str_len - 1] == ']')
456 : 346 : return strtoul(str, NULL, 10);
457 : : }
458 : : }
459 : :
460 : : return 0;
461 : : }
462 : :
463 : : void
464 : 511210 : printfd(struct tcb *tcp, int fd)
465 : : {
466 : : char path[PATH_MAX + 1];
467 [ + + ][ + - ]: 511396 : if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
468 : : const char *str;
469 : : size_t len;
470 : : unsigned long inode;
471 : :
472 : 186 : tprintf("%d<", fd);
473 [ + + ]: 186 : if (show_fd_path <= 1
474 [ + + ]: 106 : || (str = STR_STRIP_PREFIX(path, "socket:[")) == path
475 [ + - ]: 94 : || !(len = strlen(str))
476 [ + - ]: 94 : || str[len - 1] != ']'
477 [ + - ]: 94 : || !(inode = strtoul(str, NULL, 10))
478 [ - + ]: 94 : || !print_sockaddr_by_inode(tcp, fd, inode)) {
479 : 92 : print_quoted_string(path, strlen(path),
480 : : QUOTE_OMIT_LEADING_TRAILING_QUOTES);
481 : : }
482 : 186 : tprints(">");
483 : : } else
484 : 511024 : tprintf("%d", fd);
485 : 511210 : }
486 : :
487 : : /*
488 : : * Quote string `instr' of length `size'
489 : : * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
490 : : *
491 : : * If QUOTE_0_TERMINATED `style' flag is set,
492 : : * treat `instr' as a NUL-terminated string,
493 : : * checking up to (`size' + 1) bytes of `instr'.
494 : : *
495 : : * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
496 : : * do not add leading and trailing quoting symbols.
497 : : *
498 : : * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
499 : : * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
500 : : */
501 : : int
502 : 251731 : string_quote(const char *instr, char *outstr, const unsigned int size,
503 : : const unsigned int style)
504 : : {
505 : 251731 : const unsigned char *ustr = (const unsigned char *) instr;
506 : 251731 : char *s = outstr;
507 : : unsigned int i;
508 : : int usehex, c, eol;
509 : :
510 [ + + ]: 251731 : if (style & QUOTE_0_TERMINATED)
511 : : eol = '\0';
512 : : else
513 : 241040 : eol = 0x100; /* this can never match a char */
514 : :
515 : 251731 : usehex = 0;
516 [ + + ][ + + ]: 251731 : if ((xflag > 1) || (style & QUOTE_FORCE_HEX)) {
517 : : usehex = 1;
518 [ + + ]: 251595 : } else if (xflag) {
519 : : /* Check for presence of symbol which require
520 : : to hex-quote the whole string. */
521 [ + + ]: 1486 : for (i = 0; i < size; ++i) {
522 : 1464 : c = ustr[i];
523 : : /* Check for NUL-terminated string. */
524 [ + - ]: 1464 : if (c == eol)
525 : : break;
526 : :
527 : : /* Force hex unless c is printable or whitespace */
528 [ + + ]: 1464 : if (c > 0x7e) {
529 : : usehex = 1;
530 : : break;
531 : : }
532 : : /* In ASCII isspace is only these chars: "\t\n\v\f\r".
533 : : * They happen to have ASCII codes 9,10,11,12,13.
534 : : */
535 [ + - ]: 1460 : if (c < ' ' && (unsigned)(c - 9) >= 5) {
536 : : usehex = 1;
537 : : break;
538 : : }
539 : : }
540 : : }
541 : :
542 [ + + ]: 251731 : if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
543 : 251639 : *s++ = '\"';
544 : :
545 [ + + ]: 251731 : if (usehex) {
546 : : /* Hex-quote the whole string. */
547 [ + + ]: 1206 : for (i = 0; i < size; ++i) {
548 : 1074 : c = ustr[i];
549 : : /* Check for NUL-terminated string. */
550 [ + + ]: 1074 : if (c == eol)
551 : : goto asciz_ended;
552 : 1066 : *s++ = '\\';
553 : 1066 : *s++ = 'x';
554 : 1066 : *s++ = "0123456789abcdef"[c >> 4];
555 : 1066 : *s++ = "0123456789abcdef"[c & 0xf];
556 : : }
557 : : } else {
558 [ + + ]: 1453544 : for (i = 0; i < size; ++i) {
559 : 1209181 : c = ustr[i];
560 : : /* Check for NUL-terminated string. */
561 [ + + ]: 1209181 : if (c == eol)
562 : : goto asciz_ended;
563 [ + + ][ + + ]: 1201963 : if ((i == (size - 1)) &&
564 [ + + ]: 22 : (style & QUOTE_OMIT_TRAILING_0) && (c == '\0'))
565 : : goto asciz_ended;
566 [ + + + + : 1201953 : switch (c) {
+ + + ]
567 : : case '\"': case '\\':
568 : 888 : *s++ = '\\';
569 : 888 : *s++ = c;
570 : 888 : break;
571 : : case '\f':
572 : 80 : *s++ = '\\';
573 : 80 : *s++ = 'f';
574 : 80 : break;
575 : : case '\n':
576 : 1357 : *s++ = '\\';
577 : 1357 : *s++ = 'n';
578 : 1357 : break;
579 : : case '\r':
580 : 76 : *s++ = '\\';
581 : 76 : *s++ = 'r';
582 : 76 : break;
583 : : case '\t':
584 : 92 : *s++ = '\\';
585 : 92 : *s++ = 't';
586 : 92 : break;
587 : : case '\v':
588 : 84 : *s++ = '\\';
589 : 84 : *s++ = 'v';
590 : 84 : break;
591 : : default:
592 [ + + ]: 1199376 : if (c >= ' ' && c <= 0x7e)
593 : 1185528 : *s++ = c;
594 : : else {
595 : : /* Print \octal */
596 : 13848 : *s++ = '\\';
597 [ + + ]: 13848 : if (i + 1 < size
598 [ + + ]: 13091 : && ustr[i + 1] >= '0'
599 [ + + ]: 1174 : && ustr[i + 1] <= '9'
600 : : ) {
601 : : /* Print \ooo */
602 : 11 : *s++ = '0' + (c >> 6);
603 : 11 : *s++ = '0' + ((c >> 3) & 0x7);
604 : : } else {
605 : : /* Print \[[o]o]o */
606 [ + + ]: 13837 : if ((c >> 3) != 0) {
607 [ + + ]: 9701 : if ((c >> 6) != 0)
608 : 1008 : *s++ = '0' + (c >> 6);
609 : 9701 : *s++ = '0' + ((c >> 3) & 0x7);
610 : : }
611 : : }
612 : 13848 : *s++ = '0' + (c & 0x7);
613 : : }
614 : : break;
615 : : }
616 : : }
617 : : }
618 : :
619 [ + + ]: 244495 : if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
620 : 244403 : *s++ = '\"';
621 : 244495 : *s = '\0';
622 : :
623 : : /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
624 [ + + ][ + + ]: 244495 : if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
625 : : /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
626 : : * but next char is NUL.
627 : : */
628 : : return 0;
629 : : }
630 : :
631 : 243982 : return 1;
632 : :
633 : : asciz_ended:
634 [ + - ]: 7236 : if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
635 : 7236 : *s++ = '\"';
636 : 7236 : *s = '\0';
637 : : /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
638 : 7236 : return 0;
639 : : }
640 : :
641 : : #ifndef ALLOCA_CUTOFF
642 : : # define ALLOCA_CUTOFF 4032
643 : : #endif
644 : : #define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
645 : :
646 : : /*
647 : : * Quote string `str' of length `size' and print the result.
648 : : *
649 : : * If QUOTE_0_TERMINATED `style' flag is set,
650 : : * treat `str' as a NUL-terminated string and
651 : : * quote at most (`size' - 1) bytes.
652 : : *
653 : : * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
654 : : * do not add leading and trailing quoting symbols.
655 : : *
656 : : * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
657 : : * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
658 : : */
659 : : int
660 : 6567 : print_quoted_string(const char *str, unsigned int size,
661 : : const unsigned int style)
662 : : {
663 : : char *buf;
664 : : char *outstr;
665 : : unsigned int alloc_size;
666 : : int rc;
667 : :
668 [ + - ][ + + ]: 6567 : if (size && style & QUOTE_0_TERMINATED)
669 : 4907 : --size;
670 : :
671 : 6567 : alloc_size = 4 * size;
672 [ - + ]: 6567 : if (alloc_size / 4 != size) {
673 : 0 : error_msg("Out of memory");
674 : 0 : tprints("???");
675 : 0 : return -1;
676 : : }
677 [ + + ]: 6567 : alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
678 : :
679 [ + + ]: 6567 : if (use_alloca(alloc_size)) {
680 : 4968 : outstr = alloca(alloc_size);
681 : 4968 : buf = NULL;
682 : : } else {
683 : 1599 : outstr = buf = malloc(alloc_size);
684 [ - + ]: 1599 : if (!buf) {
685 : 0 : error_msg("Out of memory");
686 : 0 : tprints("???");
687 : 0 : return -1;
688 : : }
689 : : }
690 : :
691 : 6567 : rc = string_quote(str, outstr, size, style);
692 : 6567 : tprints(outstr);
693 : :
694 : 6567 : free(buf);
695 : 6567 : return rc;
696 : : }
697 : :
698 : : /*
699 : : * Quote a NUL-terminated string `str' of length up to `size' - 1
700 : : * and print the result.
701 : : *
702 : : * Returns 0 if NUL was seen, 1 otherwise.
703 : : */
704 : : int
705 : 2106 : print_quoted_cstring(const char *str, unsigned int size)
706 : : {
707 : 2106 : int unterminated =
708 : : print_quoted_string(str, size, QUOTE_0_TERMINATED);
709 : :
710 [ + + ]: 2106 : if (unterminated)
711 : 22 : tprints("...");
712 : :
713 : 2106 : return unterminated;
714 : : }
715 : :
716 : : /*
717 : : * Print path string specified by address `addr' and length `n'.
718 : : * If path length exceeds `n', append `...' to the output.
719 : : */
720 : : void
721 : 11458 : printpathn(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int n)
722 : : {
723 : : char path[PATH_MAX + 1];
724 : : int nul_seen;
725 : :
726 [ + + ]: 11458 : if (!addr) {
727 : 584 : tprints("NULL");
728 : 584 : return;
729 : : }
730 : :
731 : : /* Cap path length to the path buffer size */
732 [ - + ]: 10874 : if (n > sizeof(path) - 1)
733 : 0 : n = sizeof(path) - 1;
734 : :
735 : : /* Fetch one byte more to find out whether path length > n. */
736 : 10874 : nul_seen = umovestr(tcp, addr, n + 1, path);
737 [ + + ]: 10874 : if (nul_seen < 0)
738 : 9350 : printaddr(addr);
739 : : else {
740 : 1524 : path[n++] = !nul_seen;
741 : 10874 : print_quoted_cstring(path, n);
742 : : }
743 : : }
744 : :
745 : : void
746 : 11453 : printpath(struct tcb *const tcp, const kernel_ulong_t addr)
747 : : {
748 : : /* Size must correspond to char path[] size in printpathn */
749 : 11453 : printpathn(tcp, addr, PATH_MAX);
750 : 11453 : }
751 : :
752 : : /*
753 : : * Print string specified by address `addr' and length `len'.
754 : : * If `user_style' has QUOTE_0_TERMINATED bit set, treat the string
755 : : * as a NUL-terminated string.
756 : : * Pass `user_style' on to `string_quote'.
757 : : * Append `...' to the output if either the string length exceeds `max_strlen',
758 : : * or QUOTE_0_TERMINATED bit is set and the string length exceeds `len'.
759 : : */
760 : : void
761 : 250018 : printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
762 : : const kernel_ulong_t len, const unsigned int user_style)
763 : : {
764 : : static char *str;
765 : : static char *outstr;
766 : :
767 : : unsigned int size;
768 : 250018 : unsigned int style = user_style;
769 : : int rc;
770 : : int ellipsis;
771 : :
772 [ + + ]: 250018 : if (!addr) {
773 : 1588 : tprints("NULL");
774 : 1588 : return;
775 : : }
776 : : /* Allocate static buffers if they are not allocated yet. */
777 [ + + ]: 248430 : if (!str) {
778 : 1335 : const unsigned int outstr_size =
779 : 1335 : 4 * max_strlen + /* for quotes and NUL */ 3;
780 : : /*
781 : : * We can assume that outstr_size / 4 == max_strlen
782 : : * since we have a guarantee that max_strlen <= -1U / 4.
783 : : */
784 : :
785 : 1335 : str = xmalloc(max_strlen + 1);
786 : 1335 : outstr = xmalloc(outstr_size);
787 : : }
788 : :
789 : : /* Fetch one byte more because string_quote may look one byte ahead. */
790 : 248430 : size = max_strlen + 1;
791 : :
792 [ + + ]: 248430 : if (size > len)
793 : 239383 : size = len;
794 [ + + ]: 248430 : if (style & QUOTE_0_TERMINATED)
795 : 8472 : rc = umovestr(tcp, addr, size, str);
796 : : else
797 : 239958 : rc = umoven(tcp, addr, size, str);
798 : :
799 [ + + ]: 248430 : if (rc < 0) {
800 : 3274 : printaddr(addr);
801 : 3274 : return;
802 : : }
803 : :
804 [ + + ]: 245156 : if (size > max_strlen)
805 : : size = max_strlen;
806 : : else
807 : 239098 : str[size] = '\xff';
808 : :
809 : : /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
810 : : * or we were requested to print more than -s NUM chars)...
811 : : */
812 : 245156 : ellipsis = string_quote(str, outstr, size, style)
813 [ + + ]: 240468 : && len
814 [ + + ][ + + ]: 485329 : && ((style & QUOTE_0_TERMINATED)
815 [ + + ]: 244060 : || len > max_strlen);
816 : :
817 : 245156 : tprints(outstr);
818 [ + + ]: 245156 : if (ellipsis)
819 : 1424 : tprints("...");
820 : : }
821 : :
822 : : void
823 : 88 : dumpiov_upto(struct tcb *const tcp, const int len, const kernel_ulong_t addr,
824 : : kernel_ulong_t data_size)
825 : : {
826 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
827 : : union {
828 : : struct { uint32_t base; uint32_t len; } *iov32;
829 : : struct { uint64_t base; uint64_t len; } *iov64;
830 : : } iovu;
831 : : #define iov iovu.iov64
832 : : #define sizeof_iov \
833 : : (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
834 : : #define iov_iov_base(i) \
835 : : (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
836 : : #define iov_iov_len(i) \
837 : : (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
838 : : #else
839 : : struct iovec *iov;
840 : : #define sizeof_iov sizeof(*iov)
841 : : #define iov_iov_base(i) ptr_to_kulong(iov[i].iov_base)
842 : : #define iov_iov_len(i) iov[i].iov_len
843 : : #endif
844 : : int i;
845 : : unsigned size;
846 : :
847 [ + + ]: 88 : size = sizeof_iov * len;
848 : : /* Assuming no sane program has millions of iovs */
849 [ + - ]: 88 : if ((unsigned)len > 1024*1024 /* insane or negative size? */
850 [ - + ]: 88 : || (iov = malloc(size)) == NULL) {
851 : 0 : error_msg("Out of memory");
852 : 88 : return;
853 : : }
854 [ + - ]: 88 : if (umoven(tcp, addr, size, iov) >= 0) {
855 [ + + ]: 204 : for (i = 0; i < len; i++) {
856 [ + + ]: 138 : kernel_ulong_t iov_len = iov_iov_len(i);
857 [ + + ]: 138 : if (iov_len > data_size)
858 : 44 : iov_len = data_size;
859 [ + + ]: 138 : if (!iov_len)
860 : : break;
861 : 116 : data_size -= iov_len;
862 : : /* include the buffer number to make it easy to
863 : : * match up the trace with the source */
864 : 116 : tprintf(" * %" PRI_klu " bytes in buffer %d\n", iov_len, i);
865 [ + + ]: 116 : dumpstr(tcp, iov_iov_base(i), iov_len);
866 : : }
867 : : }
868 : 88 : free(iov);
869 : : #undef sizeof_iov
870 : : #undef iov_iov_base
871 : : #undef iov_iov_len
872 : : #undef iov
873 : : }
874 : :
875 : : void
876 : 414 : dumpstr(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
877 : : {
878 : : static int strsize = -1;
879 : : static unsigned char *str;
880 : :
881 : : char outbuf[
882 : : (
883 : : (sizeof(
884 : : "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
885 : : "1234567890123456") + /*in case I'm off by few:*/ 4)
886 : : /*align to 8 to make memset easier:*/ + 7) & -8
887 : : ];
888 : : const unsigned char *src;
889 : : int i;
890 : :
891 : 414 : memset(outbuf, ' ', sizeof(outbuf));
892 : :
893 [ + + ]: 414 : if (strsize < len + 16) {
894 : 181 : free(str);
895 : 181 : str = malloc(len + 16);
896 [ - + ]: 181 : if (!str) {
897 : 0 : strsize = -1;
898 : 0 : error_msg("Out of memory");
899 : 0 : return;
900 : : }
901 : 181 : strsize = len + 16;
902 : : }
903 : :
904 [ + - ]: 414 : if (umoven(tcp, addr, len, str) < 0)
905 : : return;
906 : :
907 : : /* Space-pad to 16 bytes */
908 : : i = len;
909 [ + + ]: 3640 : while (i & 0xf)
910 : 3226 : str[i++] = ' ';
911 : :
912 : 414 : i = 0;
913 : 414 : src = str;
914 [ + + ]: 958 : while (i < len) {
915 : : char *dst = outbuf;
916 : : /* Hex dump */
917 : : do {
918 [ + + ]: 8704 : if (i < len) {
919 : 5478 : *dst++ = "0123456789abcdef"[*src >> 4];
920 : 5478 : *dst++ = "0123456789abcdef"[*src & 0xf];
921 : : } else {
922 : 3226 : *dst++ = ' ';
923 : 3226 : *dst++ = ' ';
924 : : }
925 : 8704 : dst++; /* space is there by memset */
926 : 8704 : i++;
927 [ + + ]: 8704 : if ((i & 7) == 0)
928 : 1088 : dst++; /* space is there by memset */
929 : 8704 : src++;
930 [ + + ]: 8704 : } while (i & 0xf);
931 : : /* ASCII dump */
932 : 544 : i -= 16;
933 : 544 : src -= 16;
934 : : do {
935 [ + + ]: 8704 : if (*src >= ' ' && *src < 0x7f)
936 : 4192 : *dst++ = *src;
937 : : else
938 : 4512 : *dst++ = '.';
939 : 8704 : src++;
940 [ + + ]: 8704 : } while (++i & 0xf);
941 : 544 : *dst = '\0';
942 : 544 : tprintf(" | %05x %s |\n", i - 16, outbuf);
943 : : }
944 : : }
945 : :
946 : : static bool process_vm_readv_not_supported;
947 : :
948 : : #ifndef HAVE_PROCESS_VM_READV
949 : : /*
950 : : * Need to do this since process_vm_readv() is not yet available in libc.
951 : : * When libc is be updated, only "static bool process_vm_readv_not_supported"
952 : : * line should remain.
953 : : */
954 : : /* Have to avoid duplicating with the C library headers. */
955 : : static ssize_t strace_process_vm_readv(pid_t pid,
956 : : const struct iovec *lvec,
957 : : unsigned long liovcnt,
958 : : const struct iovec *rvec,
959 : : unsigned long riovcnt,
960 : : unsigned long flags)
961 : : {
962 : : return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
963 : : }
964 : : # define process_vm_readv strace_process_vm_readv
965 : :
966 : : /*
967 : : * The same goes for process_vm_writev().
968 : : */
969 : : static ssize_t strace_process_vm_writev(pid_t pid,
970 : : const struct iovec *lvec,
971 : : unsigned long liovcnt,
972 : : const struct iovec *rvec,
973 : : unsigned long riovcnt,
974 : : unsigned long flags)
975 : : {
976 : : return syscall(__NR_process_vm_writev, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
977 : : }
978 : : # define process_vm_writev strace_process_vm_writev
979 : : #endif /* !HAVE_PROCESS_VM_READV */
980 : :
981 : : static ssize_t
982 : 858650 : vm_read_mem(const pid_t pid, void *const laddr,
983 : : const kernel_ulong_t raddr, const size_t len)
984 : : {
985 : 858650 : const unsigned long truncated_raddr = raddr;
986 : :
987 : : if (raddr != (kernel_ulong_t) truncated_raddr) {
988 : : errno = EIO;
989 : : return -1;
990 : : }
991 : :
992 : 858650 : const struct iovec local = {
993 : : .iov_base = laddr,
994 : : .iov_len = len
995 : : };
996 : 858650 : const struct iovec remote = {
997 : 858650 : .iov_base = (void *) truncated_raddr,
998 : : .iov_len = len
999 : : };
1000 : :
1001 : 858650 : return process_vm_readv(pid, &local, 1, &remote, 1, 0);
1002 : : }
1003 : :
1004 : : static ssize_t
1005 : 19 : vm_write_mem(const pid_t pid, const void *const laddr,
1006 : : const kernel_ulong_t raddr, const size_t len)
1007 : : {
1008 : 19 : const unsigned long truncated_raddr = raddr;
1009 : :
1010 : : if (raddr != (kernel_ulong_t) truncated_raddr) {
1011 : : errno = EIO;
1012 : : return -1;
1013 : : }
1014 : :
1015 : 19 : const struct iovec local = {
1016 : : .iov_base = (void *) laddr,
1017 : : .iov_len = len
1018 : : };
1019 : 19 : const struct iovec remote = {
1020 : 19 : .iov_base = (void *) truncated_raddr,
1021 : : .iov_len = len
1022 : : };
1023 : :
1024 : 19 : return process_vm_writev(pid, &local, 1, &remote, 1, 0);
1025 : : }
1026 : :
1027 : : /*
1028 : : * move `len' bytes of data from process `pid'
1029 : : * at address `addr' to our space at `our_addr'
1030 : : */
1031 : : int
1032 : 828379 : umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len,
1033 : : void *const our_addr)
1034 : : {
1035 : 828379 : char *laddr = our_addr;
1036 : 828379 : int pid = tcp->pid;
1037 : : unsigned int n, m, nread;
1038 : : union {
1039 : : long val;
1040 : : char x[sizeof(long)];
1041 : : } u;
1042 : :
1043 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
1044 [ + + ]: 828379 : if (current_wordsize < sizeof(addr)
1045 [ + - ]: 499434 : && (addr & (~(kernel_ulong_t) -1U))) {
1046 : : return -1;
1047 : : }
1048 : : #endif
1049 : :
1050 [ + - ]: 828379 : if (!process_vm_readv_not_supported) {
1051 : 828379 : int r = vm_read_mem(pid, laddr, addr, len);
1052 [ + + ]: 828379 : if ((unsigned int) r == len)
1053 : : return 0;
1054 [ + + ]: 1591 : if (r >= 0) {
1055 : 418 : error_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
1056 : : (unsigned int) r, len, addr);
1057 : 418 : return -1;
1058 : : }
1059 [ - - - + ]: 1173 : switch (errno) {
1060 : : case ENOSYS:
1061 : 0 : process_vm_readv_not_supported = 1;
1062 : 0 : break;
1063 : : case EPERM:
1064 : : /* operation not permitted, try PTRACE_PEEKDATA */
1065 : : break;
1066 : : case ESRCH:
1067 : : /* the process is gone */
1068 : : return -1;
1069 : : case EFAULT: case EIO:
1070 : : /* address space is inaccessible */
1071 : : return -1;
1072 : : default:
1073 : : /* all the rest is strange and should be reported */
1074 : 0 : perror_msg("process_vm_readv");
1075 : 0 : return -1;
1076 : : }
1077 : : }
1078 : :
1079 : 0 : nread = 0;
1080 [ # # ]: 0 : if (addr & (sizeof(long) - 1)) {
1081 : : /* addr not a multiple of sizeof(long) */
1082 : 0 : n = addr & (sizeof(long) - 1); /* residue */
1083 : 0 : addr &= -sizeof(long); /* aligned address */
1084 : 0 : errno = 0;
1085 : 0 : u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1086 [ # # ][ # # ]: 0 : switch (errno) {
[ # # ]
1087 : : case 0:
1088 : : break;
1089 : : case ESRCH: case EINVAL:
1090 : : /* these could be seen if the process is gone */
1091 : : return -1;
1092 : : case EFAULT: case EIO: case EPERM:
1093 : : /* address space is inaccessible */
1094 : : return -1;
1095 : : default:
1096 : : /* all the rest is strange and should be reported */
1097 : 0 : perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1098 : : pid, addr);
1099 : 0 : return -1;
1100 : : }
1101 : 0 : m = MIN(sizeof(long) - n, len);
1102 : 0 : memcpy(laddr, &u.x[n], m);
1103 : 0 : addr += sizeof(long);
1104 : 0 : laddr += m;
1105 : 0 : nread += m;
1106 : 0 : len -= m;
1107 : : }
1108 [ # # ]: 0 : while (len) {
1109 : 0 : errno = 0;
1110 : 0 : u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1111 [ # # ][ # # ]: 0 : switch (errno) {
[ # # ][ # # ]
1112 : : case 0:
1113 : : break;
1114 : : case ESRCH: case EINVAL:
1115 : : /* these could be seen if the process is gone */
1116 : : return -1;
1117 : : case EFAULT: case EIO: case EPERM:
1118 : : /* address space is inaccessible */
1119 [ # # ]: 0 : if (nread) {
1120 : 0 : perror_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
1121 : : nread, nread + len, addr - nread);
1122 : : }
1123 : : return -1;
1124 : : default:
1125 : : /* all the rest is strange and should be reported */
1126 : 0 : perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1127 : : pid, addr);
1128 : 0 : return -1;
1129 : : }
1130 : 0 : m = MIN(sizeof(long), len);
1131 : 0 : memcpy(laddr, u.x, m);
1132 : 0 : addr += sizeof(long);
1133 : 0 : laddr += m;
1134 : 0 : nread += m;
1135 : 0 : len -= m;
1136 : : }
1137 : :
1138 : : return 0;
1139 : : }
1140 : :
1141 : : int
1142 : 12004 : umoven_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr,
1143 : : const unsigned int len, void *const our_addr)
1144 : : {
1145 [ + + ][ + + ]: 21789 : if (!addr || !verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
[ + + ]
[ + + + + ]
1146 : 9785 : umoven(tcp, addr, len, our_addr) < 0) {
1147 : 2781 : printaddr(addr);
1148 : 2781 : return -1;
1149 : : }
1150 : : return 0;
1151 : : }
1152 : :
1153 : : int
1154 : 238361 : umoven_or_printaddr_ignore_syserror(struct tcb *const tcp,
1155 : : const kernel_ulong_t addr,
1156 : : const unsigned int len,
1157 : : void *const our_addr)
1158 : : {
1159 [ + - ][ + - ]: 238361 : if (!addr || !verbose(tcp) || umoven(tcp, addr, len, our_addr) < 0) {
[ + + ]
1160 : 105 : printaddr(addr);
1161 : 105 : return -1;
1162 : : }
1163 : : return 0;
1164 : : }
1165 : :
1166 : : /*
1167 : : * Like `umove' but make the additional effort of looking
1168 : : * for a terminating zero byte.
1169 : : *
1170 : : * Returns < 0 on error, > 0 if NUL was seen,
1171 : : * (TODO if useful: return count of bytes including NUL),
1172 : : * else 0 if len bytes were read but no NUL byte seen.
1173 : : *
1174 : : * Note: there is no guarantee we won't overwrite some bytes
1175 : : * in laddr[] _after_ terminating NUL (but, of course,
1176 : : * we never write past laddr[len-1]).
1177 : : */
1178 : : int
1179 : 20161 : umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *laddr)
1180 : : {
1181 : 20161 : const unsigned long x01010101 = (unsigned long) 0x0101010101010101ULL;
1182 : 20161 : const unsigned long x80808080 = (unsigned long) 0x8080808080808080ULL;
1183 : :
1184 : 20161 : int pid = tcp->pid;
1185 : : unsigned int n, m, nread;
1186 : : union {
1187 : : unsigned long val;
1188 : : char x[sizeof(long)];
1189 : : } u;
1190 : :
1191 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
1192 [ + + ]: 20161 : if (current_wordsize < sizeof(addr)
1193 [ + - ]: 9097 : && (addr & (~(kernel_ulong_t) -1U))) {
1194 : : return -1;
1195 : : }
1196 : : #endif
1197 : :
1198 : 20161 : nread = 0;
1199 [ + - ]: 20161 : if (!process_vm_readv_not_supported) {
1200 : 20161 : const size_t page_size = get_pagesize();
1201 : 20161 : const size_t page_mask = page_size - 1;
1202 : :
1203 [ + + ]: 31369 : while (len > 0) {
1204 : : unsigned int chunk_len;
1205 : : unsigned int end_in_page;
1206 : :
1207 : : /*
1208 : : * Don't cross pages, otherwise we can get EFAULT
1209 : : * and fail to notice that terminating NUL lies
1210 : : * in the existing (first) page.
1211 : : */
1212 : 30271 : chunk_len = len > page_size ? page_size : len;
1213 : 30271 : end_in_page = (addr + chunk_len) & page_mask;
1214 [ + + ]: 30271 : if (chunk_len > end_in_page) /* crosses to the next page */
1215 : 13984 : chunk_len -= end_in_page;
1216 : :
1217 : 30271 : int r = vm_read_mem(pid, laddr, addr, chunk_len);
1218 [ + + ]: 30271 : if (r > 0) {
1219 [ + + ]: 18225 : if (memchr(laddr, '\0', r))
1220 : : return 1;
1221 : 11208 : addr += r;
1222 : 11208 : laddr += r;
1223 : 11208 : nread += r;
1224 : 11208 : len -= r;
1225 : 11208 : continue;
1226 : : }
1227 [ - - + - : 12046 : switch (errno) {
- ]
1228 : : case ENOSYS:
1229 : 0 : process_vm_readv_not_supported = 1;
1230 : 0 : goto vm_readv_didnt_work;
1231 : : case ESRCH:
1232 : : /* the process is gone */
1233 : : return -1;
1234 : : case EPERM:
1235 : : /* operation not permitted, try PTRACE_PEEKDATA */
1236 [ # # ]: 0 : if (!nread)
1237 : : goto vm_readv_didnt_work;
1238 : : /* fall through */
1239 : : case EFAULT: case EIO:
1240 : : /* address space is inaccessible */
1241 [ + + ]: 12046 : if (nread) {
1242 : 10102 : perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
1243 : : nread, nread + len, addr - nread);
1244 : : }
1245 : : return -1;
1246 : : default:
1247 : : /* all the rest is strange and should be reported */
1248 : 0 : perror_msg("process_vm_readv");
1249 : 0 : return -1;
1250 : : }
1251 : : }
1252 : : return 0;
1253 : : }
1254 : : vm_readv_didnt_work:
1255 : :
1256 [ # # ]: 0 : if (addr & (sizeof(long) - 1)) {
1257 : : /* addr not a multiple of sizeof(long) */
1258 : 0 : n = addr & (sizeof(long) - 1); /* residue */
1259 : 0 : addr &= -sizeof(long); /* aligned address */
1260 : 0 : errno = 0;
1261 : 0 : u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1262 [ # # ][ # # ]: 0 : switch (errno) {
[ # # ]
1263 : : case 0:
1264 : : break;
1265 : : case ESRCH: case EINVAL:
1266 : : /* these could be seen if the process is gone */
1267 : : return -1;
1268 : : case EFAULT: case EIO: case EPERM:
1269 : : /* address space is inaccessible */
1270 : : return -1;
1271 : : default:
1272 : : /* all the rest is strange and should be reported */
1273 : 0 : perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1274 : : pid, addr);
1275 : 0 : return -1;
1276 : : }
1277 : 0 : m = MIN(sizeof(long) - n, len);
1278 : 0 : memcpy(laddr, &u.x[n], m);
1279 [ # # ]: 0 : while (n & (sizeof(long) - 1))
1280 [ # # ]: 0 : if (u.x[n++] == '\0')
1281 : : return 1;
1282 : 0 : addr += sizeof(long);
1283 : 0 : laddr += m;
1284 : 0 : nread += m;
1285 : 0 : len -= m;
1286 : : }
1287 : :
1288 [ # # ]: 0 : while (len) {
1289 : 0 : errno = 0;
1290 : 0 : u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1291 [ # # ][ # # ]: 0 : switch (errno) {
[ # # ][ # # ]
1292 : : case 0:
1293 : : break;
1294 : : case ESRCH: case EINVAL:
1295 : : /* these could be seen if the process is gone */
1296 : : return -1;
1297 : : case EFAULT: case EIO: case EPERM:
1298 : : /* address space is inaccessible */
1299 [ # # ]: 0 : if (nread) {
1300 : 0 : perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
1301 : : nread, nread + len, addr - nread);
1302 : : }
1303 : : return -1;
1304 : : default:
1305 : : /* all the rest is strange and should be reported */
1306 : 0 : perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1307 : : pid, addr);
1308 : 0 : return -1;
1309 : : }
1310 : 0 : m = MIN(sizeof(long), len);
1311 : 0 : memcpy(laddr, u.x, m);
1312 : : /* "If a NUL char exists in this word" */
1313 [ # # ]: 0 : if ((u.val - x01010101) & ~u.val & x80808080)
1314 : : return 1;
1315 : 0 : addr += sizeof(long);
1316 : 0 : laddr += m;
1317 : 0 : nread += m;
1318 : 0 : len -= m;
1319 : : }
1320 : : return 0;
1321 : : }
1322 : :
1323 : : static bool
1324 : 0 : partial_poke(int pid, kernel_ulong_t addr, unsigned int len, const void *laddr,
1325 : : unsigned int off)
1326 : : {
1327 : : union {
1328 : : long val;
1329 : : char x[sizeof(long)];
1330 : : } u;
1331 : 0 : errno = 0;
1332 : 0 : u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1333 [ # # ][ # # ]: 0 : switch (errno) {
[ # # ]
1334 : : case 0:
1335 : : break;
1336 : : case ESRCH: case EINVAL:
1337 : : /* these could be seen if the process is gone */
1338 : : return false;
1339 : : case EFAULT: case EIO: case EPERM:
1340 : : /* address space is inaccessible */
1341 : : return false;
1342 : : default:
1343 : : /* all the rest is strange and should be reported */
1344 : 0 : perror_msg("partial_poke: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1345 : : pid, addr);
1346 : 0 : return false;
1347 : : }
1348 : :
1349 : 0 : memcpy(u.x + off, laddr, len);
1350 : :
1351 : : /* now write it back */
1352 [ # # ]: 0 : if (ptrace(PTRACE_POKEDATA, pid, addr, u.val) < 0) {
1353 [ # # ][ # # ]: 0 : switch (errno) {
1354 : : case ESRCH: case EINVAL:
1355 : : /* these could be seen if the process is gone */
1356 : : return -1;
1357 : : case EFAULT: case EIO: case EPERM:
1358 : : /* address space is inaccessible, or write is prohibited */
1359 : : return -1;
1360 : : default:
1361 : : /* all the rest is strange and should be reported */
1362 : 0 : perror_msg("partial_poke: PTRACE_POKEDATA pid:%d @0x%" PRI_klx,
1363 : : pid, addr);
1364 : 0 : return -1;
1365 : : }
1366 : : }
1367 : :
1368 : : return true;
1369 : : }
1370 : :
1371 : : int
1372 : 20 : upoken(struct tcb *tcp, kernel_ulong_t addr, unsigned int len,
1373 : : const void *const our_addr)
1374 : : {
1375 [ + + ]: 20 : if (!len)
1376 : : return 0;
1377 : :
1378 : 19 : const char *laddr = our_addr;
1379 : 19 : int pid = tcp->pid;
1380 : :
1381 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
1382 [ - + ]: 19 : if (current_wordsize < sizeof(addr)
1383 [ # # ]: 0 : && (addr & (~(kernel_ulong_t) -1U))) {
1384 : : return -1;
1385 : : }
1386 : : #endif
1387 : :
1388 [ + - ]: 19 : if (!process_vm_readv_not_supported) {
1389 : 19 : int r = vm_write_mem(pid, laddr, addr, len);
1390 [ - + ]: 19 : if ((unsigned int) r == len)
1391 : : return 0;
1392 [ # # ]: 0 : if (r >= 0) {
1393 : 0 : error_msg("upoken: short write (%u < %u) @0x%" PRI_klx,
1394 : : (unsigned int) r, len, addr);
1395 : 0 : return -1;
1396 : : }
1397 [ # # # # ]: 0 : switch (errno) {
1398 : : case ENOSYS:
1399 : 0 : process_vm_readv_not_supported = 1;
1400 : 0 : break;
1401 : : case EPERM:
1402 : : /* operation not permitted, try PTRACE_POKEDATA */
1403 : : break;
1404 : : case ESRCH:
1405 : : /* the process is gone */
1406 : : return -1;
1407 : : case EFAULT: case EIO:
1408 : : /* address space is inaccessible */
1409 : : return -1;
1410 : : default:
1411 : : /* all the rest is strange and should be reported */
1412 : 0 : perror_msg("process_vm_writev");
1413 : 0 : return -1;
1414 : : }
1415 : : }
1416 : :
1417 [ # # ]: 0 : if (addr & (sizeof(long) - 1)) {
1418 : : /* addr not a multiple of sizeof(long) */
1419 : 0 : unsigned n = addr & (sizeof(long) - 1); /* residue */
1420 : 0 : addr &= -sizeof(long); /* aligned address */
1421 : 0 : unsigned m = MIN(sizeof(long) - n, len);
1422 [ # # ]: 0 : if (!partial_poke(pid, addr, m, laddr, n))
1423 : : return -1;
1424 : 0 : addr += sizeof(long);
1425 : 0 : laddr += m;
1426 : 0 : len -= m;
1427 : : }
1428 : :
1429 [ # # ]: 0 : while (len >= sizeof(long)) {
1430 [ # # ]: 0 : if (ptrace(PTRACE_POKEDATA, pid, addr, * (const long *) laddr) < 0) {
1431 [ # # ][ # # ]: 0 : switch (errno) {
1432 : : case ESRCH: case EINVAL:
1433 : : /* these could be seen if the process is gone */
1434 : : return -1;
1435 : : case EFAULT: case EIO: case EPERM:
1436 : : /* address space is inaccessible, or write is prohibited */
1437 : : return -1;
1438 : : default:
1439 : : /* all the rest is strange and should be reported */
1440 : 0 : perror_msg("upoken: PTRACE_POKEDATA pid:%d @0x%" PRI_klx,
1441 : : pid, addr);
1442 : 0 : return -1;
1443 : : }
1444 : : }
1445 : 0 : addr += sizeof(long);
1446 : 0 : laddr += sizeof(long);
1447 : 0 : len -= sizeof(long);
1448 : : }
1449 : :
1450 [ # # ]: 0 : if (len) {
1451 [ # # ]: 0 : if (!partial_poke(pid, addr, len, laddr, 0))
1452 : : return -1;
1453 : : }
1454 : :
1455 : : return 0;
1456 : : }
1457 : :
1458 : : /*
1459 : : * Iteratively fetch and print up to nmemb elements of elem_size size
1460 : : * from the array that starts at tracee's address start_addr.
1461 : : *
1462 : : * Array elements are being fetched to the address specified by elem_buf.
1463 : : *
1464 : : * The fetcher callback function specified by umoven_func should follow
1465 : : * the same semantics as umoven_or_printaddr function.
1466 : : *
1467 : : * The printer callback function specified by print_func is expected
1468 : : * to print something; if it returns false, no more iterations will be made.
1469 : : *
1470 : : * The pointer specified by opaque_data is passed to each invocation
1471 : : * of print_func callback function.
1472 : : *
1473 : : * This function prints:
1474 : : * - "NULL", if start_addr is NULL;
1475 : : * - "[]", if nmemb is 0;
1476 : : * - start_addr, if nmemb * elem_size overflows or wraps around;
1477 : : * - nothing, if the first element cannot be fetched
1478 : : * (if umoven_func returns non-zero), but it is assumed that
1479 : : * umoven_func has printed the address it failed to fetch data from;
1480 : : * - elements of the array, delimited by ", ", with the array itself
1481 : : * enclosed with [] brackets.
1482 : : *
1483 : : * If abbrev(tcp) is true, then
1484 : : * - the maximum number of elements printed equals to max_strlen;
1485 : : * - "..." is printed instead of max_strlen+1 element
1486 : : * and no more iterations will be made.
1487 : : *
1488 : : * This function returns true only if
1489 : : * - umoven_func has been called at least once AND
1490 : : * - umoven_func has not returned false.
1491 : : */
1492 : : bool
1493 : 303669 : print_array(struct tcb *const tcp,
1494 : : const kernel_ulong_t start_addr,
1495 : : const size_t nmemb,
1496 : : void *const elem_buf,
1497 : : const size_t elem_size,
1498 : : int (*const umoven_func)(struct tcb *,
1499 : : kernel_ulong_t,
1500 : : unsigned int,
1501 : : void *),
1502 : : bool (*const print_func)(struct tcb *,
1503 : : void *elem_buf,
1504 : : size_t elem_size,
1505 : : void *opaque_data),
1506 : : void *const opaque_data)
1507 : : {
1508 [ + + ]: 303669 : if (!start_addr) {
1509 : 65162 : tprints("NULL");
1510 : 65162 : return false;
1511 : : }
1512 : :
1513 [ + + ]: 238507 : if (!nmemb) {
1514 : 69 : tprints("[]");
1515 : 69 : return false;
1516 : : }
1517 : :
1518 : 238438 : const size_t size = nmemb * elem_size;
1519 : 238438 : const kernel_ulong_t end_addr = start_addr + size;
1520 : :
1521 [ + + ][ + + ]: 238438 : if (end_addr <= start_addr || size / elem_size != nmemb) {
1522 : 20 : printaddr(start_addr);
1523 : 20 : return false;
1524 : : }
1525 : :
1526 : 238418 : const kernel_ulong_t abbrev_end =
1527 [ + + ]: 233710 : (abbrev(tcp) && max_strlen < nmemb) ?
1528 [ + + ]: 238624 : start_addr + elem_size * max_strlen : end_addr;
1529 : : kernel_ulong_t cur;
1530 : :
1531 [ + + ]: 482453 : for (cur = start_addr; cur < end_addr; cur += elem_size) {
1532 [ + + ]: 244406 : if (cur != start_addr)
1533 : 5988 : tprints(", ");
1534 : :
1535 [ + + ]: 244406 : if (umoven_func(tcp, cur, elem_size, elem_buf))
1536 : : break;
1537 : :
1538 [ + + ]: 244155 : if (cur == start_addr)
1539 : 238283 : tprints("[");
1540 : :
1541 [ + + ]: 244155 : if (cur >= abbrev_end) {
1542 : 112 : tprints("...");
1543 : 112 : cur = end_addr;
1544 : 112 : break;
1545 : : }
1546 : :
1547 [ + + ]: 244043 : if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
1548 : : cur = end_addr;
1549 : : break;
1550 : : }
1551 : : }
1552 [ + + ]: 238418 : if (cur != start_addr)
1553 : 238283 : tprints("]");
1554 : :
1555 : 238418 : return cur >= end_addr;
1556 : : }
1557 : :
1558 : : int
1559 : 120804 : printargs(struct tcb *tcp)
1560 : : {
1561 : 120804 : const int n = tcp->s_ent->nargs;
1562 : : int i;
1563 [ + + ]: 526226 : for (i = 0; i < n; ++i)
1564 [ + + ]: 405422 : tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
1565 : 120804 : return RVAL_DECODED;
1566 : : }
1567 : :
1568 : : int
1569 : 2 : printargs_u(struct tcb *tcp)
1570 : : {
1571 : 2 : const int n = tcp->s_ent->nargs;
1572 : : int i;
1573 [ + + ]: 4 : for (i = 0; i < n; ++i)
1574 [ + - ]: 2 : tprintf("%s%u", i ? ", " : "",
1575 : 2 : (unsigned int) tcp->u_arg[i]);
1576 : 2 : return RVAL_DECODED;
1577 : : }
1578 : :
1579 : : int
1580 : 44 : printargs_d(struct tcb *tcp)
1581 : : {
1582 : 44 : const int n = tcp->s_ent->nargs;
1583 : : int i;
1584 [ + + ]: 90 : for (i = 0; i < n; ++i)
1585 [ + + ]: 46 : tprintf("%s%d", i ? ", " : "",
1586 : 46 : (int) tcp->u_arg[i]);
1587 : 44 : return RVAL_DECODED;
1588 : : }
1589 : :
1590 : : /* Print abnormal high bits of a kernel_ulong_t value. */
1591 : : void
1592 : 0 : print_abnormal_hi(const kernel_ulong_t val)
1593 : : {
1594 [ # # ]: 0 : if (current_klongsize > 4) {
1595 : 0 : const unsigned int hi = (unsigned int) ((uint64_t) val >> 32);
1596 [ # # ]: 0 : if (hi)
1597 : 0 : tprintf("%#x<<32|", hi);
1598 : : }
1599 : 0 : }
1600 : :
1601 : : #if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
1602 : : # define open_file open64
1603 : : #else
1604 : : # define open_file open
1605 : : #endif
1606 : :
1607 : : int
1608 : 8 : read_int_from_file(const char *const fname, int *const pvalue)
1609 : : {
1610 : 8 : const int fd = open_file(fname, O_RDONLY);
1611 [ + - ]: 8 : if (fd < 0)
1612 : : return -1;
1613 : :
1614 : : long lval;
1615 : : char buf[sizeof(lval) * 3];
1616 : 8 : int n = read(fd, buf, sizeof(buf) - 1);
1617 : 8 : int saved_errno = errno;
1618 : 8 : close(fd);
1619 : :
1620 [ - + ]: 8 : if (n < 0) {
1621 : 0 : errno = saved_errno;
1622 : 0 : return -1;
1623 : : }
1624 : :
1625 : 8 : buf[n] = '\0';
1626 : 8 : char *endptr = 0;
1627 : 8 : errno = 0;
1628 : 8 : lval = strtol(buf, &endptr, 10);
1629 [ + - ][ + - ]: 8 : if (!endptr || (*endptr && '\n' != *endptr)
1630 : : #if INT_MAX < LONG_MAX
1631 [ + - ]: 8 : || lval > INT_MAX || lval < INT_MIN
1632 : : #endif
1633 [ - + ]: 8 : || ERANGE == errno) {
1634 [ # # ]: 0 : if (!errno)
1635 : 0 : errno = EINVAL;
1636 : : return -1;
1637 : : }
1638 : :
1639 : 8 : *pvalue = (int) lval;
1640 : 8 : return 0;
1641 : : }
|