xref: /aosp_15_r20/external/strace/util.c (revision cf84ac9a129d8ea9952db616b4e9b904c4bdde56)
1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1991, 1992 Paul Kranenburg <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1993 Branko Lankester <[email protected]>
4*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <[email protected]>
5*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1996-1999 Wichert Akkerman <[email protected]>
6*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7*cf84ac9aSAndroid Build Coastguard Worker  *                     Linux for s390 port by D.J. Barrow
8*cf84ac9aSAndroid Build Coastguard Worker  *                    <[email protected],[email protected]>
9*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1999-2018 The strace developers.
10*cf84ac9aSAndroid Build Coastguard Worker  * All rights reserved.
11*cf84ac9aSAndroid Build Coastguard Worker  *
12*cf84ac9aSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
13*cf84ac9aSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
14*cf84ac9aSAndroid Build Coastguard Worker  * are met:
15*cf84ac9aSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
16*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
17*cf84ac9aSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
18*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
19*cf84ac9aSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
20*cf84ac9aSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
21*cf84ac9aSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
22*cf84ac9aSAndroid Build Coastguard Worker  *
23*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24*cf84ac9aSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25*cf84ac9aSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*cf84ac9aSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27*cf84ac9aSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28*cf84ac9aSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29*cf84ac9aSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30*cf84ac9aSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*cf84ac9aSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*cf84ac9aSAndroid Build Coastguard Worker  */
34*cf84ac9aSAndroid Build Coastguard Worker 
35*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
36*cf84ac9aSAndroid Build Coastguard Worker #include <limits.h>
37*cf84ac9aSAndroid Build Coastguard Worker #include <fcntl.h>
38*cf84ac9aSAndroid Build Coastguard Worker #include <stdarg.h>
39*cf84ac9aSAndroid Build Coastguard Worker #include <sys/stat.h>
40*cf84ac9aSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
41*cf84ac9aSAndroid Build Coastguard Worker #ifdef HAVE_SYS_XATTR_H
42*cf84ac9aSAndroid Build Coastguard Worker # include <sys/xattr.h>
43*cf84ac9aSAndroid Build Coastguard Worker #endif
44*cf84ac9aSAndroid Build Coastguard Worker #include <sys/uio.h>
45*cf84ac9aSAndroid Build Coastguard Worker 
46*cf84ac9aSAndroid Build Coastguard Worker #include "largefile_wrappers.h"
47*cf84ac9aSAndroid Build Coastguard Worker #include "xlat.h"
48*cf84ac9aSAndroid Build Coastguard Worker #include "xstring.h"
49*cf84ac9aSAndroid Build Coastguard Worker 
50*cf84ac9aSAndroid Build Coastguard Worker int
ts_nz(const struct timespec * a)51*cf84ac9aSAndroid Build Coastguard Worker ts_nz(const struct timespec *a)
52*cf84ac9aSAndroid Build Coastguard Worker {
53*cf84ac9aSAndroid Build Coastguard Worker 	return a->tv_sec || a->tv_nsec;
54*cf84ac9aSAndroid Build Coastguard Worker }
55*cf84ac9aSAndroid Build Coastguard Worker 
56*cf84ac9aSAndroid Build Coastguard Worker int
ts_cmp(const struct timespec * a,const struct timespec * b)57*cf84ac9aSAndroid Build Coastguard Worker ts_cmp(const struct timespec *a, const struct timespec *b)
58*cf84ac9aSAndroid Build Coastguard Worker {
59*cf84ac9aSAndroid Build Coastguard Worker 	if (a->tv_sec < b->tv_sec
60*cf84ac9aSAndroid Build Coastguard Worker 	    || (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec))
61*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
62*cf84ac9aSAndroid Build Coastguard Worker 	if (a->tv_sec > b->tv_sec
63*cf84ac9aSAndroid Build Coastguard Worker 	    || (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec))
64*cf84ac9aSAndroid Build Coastguard Worker 		return 1;
65*cf84ac9aSAndroid Build Coastguard Worker 	return 0;
66*cf84ac9aSAndroid Build Coastguard Worker }
67*cf84ac9aSAndroid Build Coastguard Worker 
68*cf84ac9aSAndroid Build Coastguard Worker double
ts_float(const struct timespec * tv)69*cf84ac9aSAndroid Build Coastguard Worker ts_float(const struct timespec *tv)
70*cf84ac9aSAndroid Build Coastguard Worker {
71*cf84ac9aSAndroid Build Coastguard Worker 	return tv->tv_sec + tv->tv_nsec/1000000000.0;
72*cf84ac9aSAndroid Build Coastguard Worker }
73*cf84ac9aSAndroid Build Coastguard Worker 
74*cf84ac9aSAndroid Build Coastguard Worker void
ts_add(struct timespec * tv,const struct timespec * a,const struct timespec * b)75*cf84ac9aSAndroid Build Coastguard Worker ts_add(struct timespec *tv, const struct timespec *a, const struct timespec *b)
76*cf84ac9aSAndroid Build Coastguard Worker {
77*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_sec = a->tv_sec + b->tv_sec;
78*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_nsec = a->tv_nsec + b->tv_nsec;
79*cf84ac9aSAndroid Build Coastguard Worker 	if (tv->tv_nsec >= 1000000000) {
80*cf84ac9aSAndroid Build Coastguard Worker 		tv->tv_sec++;
81*cf84ac9aSAndroid Build Coastguard Worker 		tv->tv_nsec -= 1000000000;
82*cf84ac9aSAndroid Build Coastguard Worker 	}
83*cf84ac9aSAndroid Build Coastguard Worker }
84*cf84ac9aSAndroid Build Coastguard Worker 
85*cf84ac9aSAndroid Build Coastguard Worker void
ts_sub(struct timespec * tv,const struct timespec * a,const struct timespec * b)86*cf84ac9aSAndroid Build Coastguard Worker ts_sub(struct timespec *tv, const struct timespec *a, const struct timespec *b)
87*cf84ac9aSAndroid Build Coastguard Worker {
88*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_sec = a->tv_sec - b->tv_sec;
89*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_nsec = a->tv_nsec - b->tv_nsec;
90*cf84ac9aSAndroid Build Coastguard Worker 	if (tv->tv_nsec < 0) {
91*cf84ac9aSAndroid Build Coastguard Worker 		tv->tv_sec--;
92*cf84ac9aSAndroid Build Coastguard Worker 		tv->tv_nsec += 1000000000;
93*cf84ac9aSAndroid Build Coastguard Worker 	}
94*cf84ac9aSAndroid Build Coastguard Worker }
95*cf84ac9aSAndroid Build Coastguard Worker 
96*cf84ac9aSAndroid Build Coastguard Worker void
ts_div(struct timespec * tv,const struct timespec * a,int n)97*cf84ac9aSAndroid Build Coastguard Worker ts_div(struct timespec *tv, const struct timespec *a, int n)
98*cf84ac9aSAndroid Build Coastguard Worker {
99*cf84ac9aSAndroid Build Coastguard Worker 	long long nsec = (a->tv_sec % n * 1000000000LL + a->tv_nsec + n / 2) / n;
100*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_sec = a->tv_sec / n + nsec / 1000000000;
101*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_nsec = nsec % 1000000000;
102*cf84ac9aSAndroid Build Coastguard Worker }
103*cf84ac9aSAndroid Build Coastguard Worker 
104*cf84ac9aSAndroid Build Coastguard Worker void
ts_mul(struct timespec * tv,const struct timespec * a,int n)105*cf84ac9aSAndroid Build Coastguard Worker ts_mul(struct timespec *tv, const struct timespec *a, int n)
106*cf84ac9aSAndroid Build Coastguard Worker {
107*cf84ac9aSAndroid Build Coastguard Worker 	long long nsec = a->tv_nsec * n;
108*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_sec = a->tv_sec * n + nsec / 1000000000;
109*cf84ac9aSAndroid Build Coastguard Worker 	tv->tv_nsec = nsec % 1000000000;
110*cf84ac9aSAndroid Build Coastguard Worker }
111*cf84ac9aSAndroid Build Coastguard Worker 
112*cf84ac9aSAndroid Build Coastguard Worker #if !defined HAVE_STPCPY
113*cf84ac9aSAndroid Build Coastguard Worker char *
stpcpy(char * dst,const char * src)114*cf84ac9aSAndroid Build Coastguard Worker stpcpy(char *dst, const char *src)
115*cf84ac9aSAndroid Build Coastguard Worker {
116*cf84ac9aSAndroid Build Coastguard Worker 	while ((*dst = *src++) != '\0')
117*cf84ac9aSAndroid Build Coastguard Worker 		dst++;
118*cf84ac9aSAndroid Build Coastguard Worker 	return dst;
119*cf84ac9aSAndroid Build Coastguard Worker }
120*cf84ac9aSAndroid Build Coastguard Worker #endif
121*cf84ac9aSAndroid Build Coastguard Worker 
122*cf84ac9aSAndroid Build Coastguard Worker /* Find a next bit which is set.
123*cf84ac9aSAndroid Build Coastguard Worker  * Starts testing at cur_bit.
124*cf84ac9aSAndroid Build Coastguard Worker  * Returns -1 if no more bits are set.
125*cf84ac9aSAndroid Build Coastguard Worker  *
126*cf84ac9aSAndroid Build Coastguard Worker  * We never touch bytes we don't need to.
127*cf84ac9aSAndroid Build Coastguard Worker  * On big-endian, array is assumed to consist of
128*cf84ac9aSAndroid Build Coastguard Worker  * current_wordsize wide words: for example, is current_wordsize is 4,
129*cf84ac9aSAndroid Build Coastguard Worker  * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
130*cf84ac9aSAndroid Build Coastguard Worker  * On little-endian machines, word size is immaterial.
131*cf84ac9aSAndroid Build Coastguard Worker  */
132*cf84ac9aSAndroid Build Coastguard Worker int
next_set_bit(const void * bit_array,unsigned cur_bit,unsigned size_bits)133*cf84ac9aSAndroid Build Coastguard Worker next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
134*cf84ac9aSAndroid Build Coastguard Worker {
135*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned endian = 1;
136*cf84ac9aSAndroid Build Coastguard Worker 	int little_endian = *(char *) (void *) &endian;
137*cf84ac9aSAndroid Build Coastguard Worker 
138*cf84ac9aSAndroid Build Coastguard Worker 	const uint8_t *array = bit_array;
139*cf84ac9aSAndroid Build Coastguard Worker 	unsigned pos = cur_bit / 8;
140*cf84ac9aSAndroid Build Coastguard Worker 	unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
141*cf84ac9aSAndroid Build Coastguard Worker 
142*cf84ac9aSAndroid Build Coastguard Worker 	for (;;) {
143*cf84ac9aSAndroid Build Coastguard Worker 		uint8_t bitmask;
144*cf84ac9aSAndroid Build Coastguard Worker 		uint8_t cur_byte;
145*cf84ac9aSAndroid Build Coastguard Worker 
146*cf84ac9aSAndroid Build Coastguard Worker 		if (cur_bit >= size_bits)
147*cf84ac9aSAndroid Build Coastguard Worker 			return -1;
148*cf84ac9aSAndroid Build Coastguard Worker 		cur_byte = array[pos ^ pos_xor_mask];
149*cf84ac9aSAndroid Build Coastguard Worker 		if (cur_byte == 0) {
150*cf84ac9aSAndroid Build Coastguard Worker 			cur_bit = (cur_bit + 8) & (-8);
151*cf84ac9aSAndroid Build Coastguard Worker 			pos++;
152*cf84ac9aSAndroid Build Coastguard Worker 			continue;
153*cf84ac9aSAndroid Build Coastguard Worker 		}
154*cf84ac9aSAndroid Build Coastguard Worker 		bitmask = 1 << (cur_bit & 7);
155*cf84ac9aSAndroid Build Coastguard Worker 		for (;;) {
156*cf84ac9aSAndroid Build Coastguard Worker 			if (cur_byte & bitmask)
157*cf84ac9aSAndroid Build Coastguard Worker 				return cur_bit;
158*cf84ac9aSAndroid Build Coastguard Worker 			cur_bit++;
159*cf84ac9aSAndroid Build Coastguard Worker 			if (cur_bit >= size_bits)
160*cf84ac9aSAndroid Build Coastguard Worker 				return -1;
161*cf84ac9aSAndroid Build Coastguard Worker 			bitmask <<= 1;
162*cf84ac9aSAndroid Build Coastguard Worker 			/* This check *can't be* optimized out: */
163*cf84ac9aSAndroid Build Coastguard Worker 			if (bitmask == 0)
164*cf84ac9aSAndroid Build Coastguard Worker 				break;
165*cf84ac9aSAndroid Build Coastguard Worker 		}
166*cf84ac9aSAndroid Build Coastguard Worker 		pos++;
167*cf84ac9aSAndroid Build Coastguard Worker 	}
168*cf84ac9aSAndroid Build Coastguard Worker }
169*cf84ac9aSAndroid Build Coastguard Worker 
170*cf84ac9aSAndroid Build Coastguard Worker /*
171*cf84ac9aSAndroid Build Coastguard Worker  * Fetch 64bit argument at position arg_no and
172*cf84ac9aSAndroid Build Coastguard Worker  * return the index of the next argument.
173*cf84ac9aSAndroid Build Coastguard Worker  */
174*cf84ac9aSAndroid Build Coastguard Worker int
getllval(struct tcb * tcp,unsigned long long * val,int arg_no)175*cf84ac9aSAndroid Build Coastguard Worker getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
176*cf84ac9aSAndroid Build Coastguard Worker {
177*cf84ac9aSAndroid Build Coastguard Worker #if SIZEOF_KERNEL_LONG_T > 4
178*cf84ac9aSAndroid Build Coastguard Worker # ifndef current_klongsize
179*cf84ac9aSAndroid Build Coastguard Worker 	if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
180*cf84ac9aSAndroid Build Coastguard Worker #  if defined(AARCH64) || defined(POWERPC64)
181*cf84ac9aSAndroid Build Coastguard Worker 		/* Align arg_no to the next even number. */
182*cf84ac9aSAndroid Build Coastguard Worker 		arg_no = (arg_no + 1) & 0xe;
183*cf84ac9aSAndroid Build Coastguard Worker #  endif /* AARCH64 || POWERPC64 */
184*cf84ac9aSAndroid Build Coastguard Worker 		*val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
185*cf84ac9aSAndroid Build Coastguard Worker 		arg_no += 2;
186*cf84ac9aSAndroid Build Coastguard Worker 	} else
187*cf84ac9aSAndroid Build Coastguard Worker # endif /* !current_klongsize */
188*cf84ac9aSAndroid Build Coastguard Worker 	{
189*cf84ac9aSAndroid Build Coastguard Worker 		*val = tcp->u_arg[arg_no];
190*cf84ac9aSAndroid Build Coastguard Worker 		arg_no++;
191*cf84ac9aSAndroid Build Coastguard Worker 	}
192*cf84ac9aSAndroid Build Coastguard Worker #else /* SIZEOF_KERNEL_LONG_T == 4 */
193*cf84ac9aSAndroid Build Coastguard Worker # if defined __ARM_EABI__	\
194*cf84ac9aSAndroid Build Coastguard Worker   || defined LINUX_MIPSO32	\
195*cf84ac9aSAndroid Build Coastguard Worker   || defined POWERPC		\
196*cf84ac9aSAndroid Build Coastguard Worker   || defined XTENSA
197*cf84ac9aSAndroid Build Coastguard Worker 	/* Align arg_no to the next even number. */
198*cf84ac9aSAndroid Build Coastguard Worker 	arg_no = (arg_no + 1) & 0xe;
199*cf84ac9aSAndroid Build Coastguard Worker # elif defined SH
200*cf84ac9aSAndroid Build Coastguard Worker 	/*
201*cf84ac9aSAndroid Build Coastguard Worker 	 * The SH4 ABI does allow long longs in odd-numbered registers, but
202*cf84ac9aSAndroid Build Coastguard Worker 	 * does not allow them to be split between registers and memory - and
203*cf84ac9aSAndroid Build Coastguard Worker 	 * there are only four argument registers for normal functions.  As a
204*cf84ac9aSAndroid Build Coastguard Worker 	 * result, pread, for example, takes an extra padding argument before
205*cf84ac9aSAndroid Build Coastguard Worker 	 * the offset.  This was changed late in the 2.4 series (around 2.4.20).
206*cf84ac9aSAndroid Build Coastguard Worker 	 */
207*cf84ac9aSAndroid Build Coastguard Worker 	if (arg_no == 3)
208*cf84ac9aSAndroid Build Coastguard Worker 		arg_no++;
209*cf84ac9aSAndroid Build Coastguard Worker # endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
210*cf84ac9aSAndroid Build Coastguard Worker 	*val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
211*cf84ac9aSAndroid Build Coastguard Worker 	arg_no += 2;
212*cf84ac9aSAndroid Build Coastguard Worker #endif
213*cf84ac9aSAndroid Build Coastguard Worker 
214*cf84ac9aSAndroid Build Coastguard Worker 	return arg_no;
215*cf84ac9aSAndroid Build Coastguard Worker }
216*cf84ac9aSAndroid Build Coastguard Worker 
217*cf84ac9aSAndroid Build Coastguard Worker /*
218*cf84ac9aSAndroid Build Coastguard Worker  * Print 64bit argument at position arg_no and
219*cf84ac9aSAndroid Build Coastguard Worker  * return the index of the next argument.
220*cf84ac9aSAndroid Build Coastguard Worker  */
221*cf84ac9aSAndroid Build Coastguard Worker int
printllval(struct tcb * tcp,const char * format,int arg_no)222*cf84ac9aSAndroid Build Coastguard Worker printllval(struct tcb *tcp, const char *format, int arg_no)
223*cf84ac9aSAndroid Build Coastguard Worker {
224*cf84ac9aSAndroid Build Coastguard Worker 	unsigned long long val = 0;
225*cf84ac9aSAndroid Build Coastguard Worker 
226*cf84ac9aSAndroid Build Coastguard Worker 	arg_no = getllval(tcp, &val, arg_no);
227*cf84ac9aSAndroid Build Coastguard Worker 	tprintf(format, val);
228*cf84ac9aSAndroid Build Coastguard Worker 	return arg_no;
229*cf84ac9aSAndroid Build Coastguard Worker }
230*cf84ac9aSAndroid Build Coastguard Worker 
231*cf84ac9aSAndroid Build Coastguard Worker void
printaddr64(const uint64_t addr)232*cf84ac9aSAndroid Build Coastguard Worker printaddr64(const uint64_t addr)
233*cf84ac9aSAndroid Build Coastguard Worker {
234*cf84ac9aSAndroid Build Coastguard Worker 	if (!addr)
235*cf84ac9aSAndroid Build Coastguard Worker 		tprints("NULL");
236*cf84ac9aSAndroid Build Coastguard Worker 	else
237*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%#" PRIx64, addr);
238*cf84ac9aSAndroid Build Coastguard Worker }
239*cf84ac9aSAndroid Build Coastguard Worker 
240*cf84ac9aSAndroid Build Coastguard Worker #define DEF_PRINTNUM(name, type) \
241*cf84ac9aSAndroid Build Coastguard Worker bool									\
242*cf84ac9aSAndroid Build Coastguard Worker printnum_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,	\
243*cf84ac9aSAndroid Build Coastguard Worker 		  const char *const fmt)				\
244*cf84ac9aSAndroid Build Coastguard Worker {									\
245*cf84ac9aSAndroid Build Coastguard Worker 	type num;							\
246*cf84ac9aSAndroid Build Coastguard Worker 	if (umove_or_printaddr(tcp, addr, &num))			\
247*cf84ac9aSAndroid Build Coastguard Worker 		return false;						\
248*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");							\
249*cf84ac9aSAndroid Build Coastguard Worker 	tprintf(fmt, num);						\
250*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");							\
251*cf84ac9aSAndroid Build Coastguard Worker 	return true;							\
252*cf84ac9aSAndroid Build Coastguard Worker }
253*cf84ac9aSAndroid Build Coastguard Worker 
254*cf84ac9aSAndroid Build Coastguard Worker #define DEF_PRINTNUM_ADDR(name, type) \
255*cf84ac9aSAndroid Build Coastguard Worker bool									\
256*cf84ac9aSAndroid Build Coastguard Worker printnum_addr_ ## name(struct tcb *tcp, const kernel_ulong_t addr)	\
257*cf84ac9aSAndroid Build Coastguard Worker {									\
258*cf84ac9aSAndroid Build Coastguard Worker 	type num;							\
259*cf84ac9aSAndroid Build Coastguard Worker 	if (umove_or_printaddr(tcp, addr, &num))			\
260*cf84ac9aSAndroid Build Coastguard Worker 		return false;						\
261*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");							\
262*cf84ac9aSAndroid Build Coastguard Worker 	printaddr64(num);						\
263*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");							\
264*cf84ac9aSAndroid Build Coastguard Worker 	return true;							\
265*cf84ac9aSAndroid Build Coastguard Worker }
266*cf84ac9aSAndroid Build Coastguard Worker 
267*cf84ac9aSAndroid Build Coastguard Worker #define DEF_PRINTPAIR(name, type) \
268*cf84ac9aSAndroid Build Coastguard Worker bool									\
269*cf84ac9aSAndroid Build Coastguard Worker printpair_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,	\
270*cf84ac9aSAndroid Build Coastguard Worker 		   const char *const fmt)				\
271*cf84ac9aSAndroid Build Coastguard Worker {									\
272*cf84ac9aSAndroid Build Coastguard Worker 	type pair[2];							\
273*cf84ac9aSAndroid Build Coastguard Worker 	if (umove_or_printaddr(tcp, addr, &pair))			\
274*cf84ac9aSAndroid Build Coastguard Worker 		return false;						\
275*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");							\
276*cf84ac9aSAndroid Build Coastguard Worker 	tprintf(fmt, pair[0]);						\
277*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");							\
278*cf84ac9aSAndroid Build Coastguard Worker 	tprintf(fmt, pair[1]);						\
279*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");							\
280*cf84ac9aSAndroid Build Coastguard Worker 	return true;							\
281*cf84ac9aSAndroid Build Coastguard Worker }
282*cf84ac9aSAndroid Build Coastguard Worker 
DEF_PRINTNUM(int,int)283*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTNUM(int, int)
284*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTNUM_ADDR(int, unsigned int)
285*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTPAIR(int, int)
286*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTNUM(short, short)
287*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTNUM(int64, uint64_t)
288*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTNUM_ADDR(int64, uint64_t)
289*cf84ac9aSAndroid Build Coastguard Worker DEF_PRINTPAIR(int64, uint64_t)
290*cf84ac9aSAndroid Build Coastguard Worker 
291*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
292*cf84ac9aSAndroid Build Coastguard Worker bool
293*cf84ac9aSAndroid Build Coastguard Worker printnum_long_int(struct tcb *const tcp, const kernel_ulong_t addr,
294*cf84ac9aSAndroid Build Coastguard Worker 		  const char *const fmt_long, const char *const fmt_int)
295*cf84ac9aSAndroid Build Coastguard Worker {
296*cf84ac9aSAndroid Build Coastguard Worker 	if (current_wordsize > sizeof(int)) {
297*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_int64(tcp, addr, fmt_long);
298*cf84ac9aSAndroid Build Coastguard Worker 	} else {
299*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_int(tcp, addr, fmt_int);
300*cf84ac9aSAndroid Build Coastguard Worker 	}
301*cf84ac9aSAndroid Build Coastguard Worker }
302*cf84ac9aSAndroid Build Coastguard Worker 
303*cf84ac9aSAndroid Build Coastguard Worker bool
printnum_addr_long_int(struct tcb * tcp,const kernel_ulong_t addr)304*cf84ac9aSAndroid Build Coastguard Worker printnum_addr_long_int(struct tcb *tcp, const kernel_ulong_t addr)
305*cf84ac9aSAndroid Build Coastguard Worker {
306*cf84ac9aSAndroid Build Coastguard Worker 	if (current_wordsize > sizeof(int)) {
307*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_addr_int64(tcp, addr);
308*cf84ac9aSAndroid Build Coastguard Worker 	} else {
309*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_addr_int(tcp, addr);
310*cf84ac9aSAndroid Build Coastguard Worker 	}
311*cf84ac9aSAndroid Build Coastguard Worker }
312*cf84ac9aSAndroid Build Coastguard Worker #endif /* !current_wordsize */
313*cf84ac9aSAndroid Build Coastguard Worker 
314*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_klongsize
315*cf84ac9aSAndroid Build Coastguard Worker bool
printnum_addr_klong_int(struct tcb * tcp,const kernel_ulong_t addr)316*cf84ac9aSAndroid Build Coastguard Worker printnum_addr_klong_int(struct tcb *tcp, const kernel_ulong_t addr)
317*cf84ac9aSAndroid Build Coastguard Worker {
318*cf84ac9aSAndroid Build Coastguard Worker 	if (current_klongsize > sizeof(int)) {
319*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_addr_int64(tcp, addr);
320*cf84ac9aSAndroid Build Coastguard Worker 	} else {
321*cf84ac9aSAndroid Build Coastguard Worker 		return printnum_addr_int(tcp, addr);
322*cf84ac9aSAndroid Build Coastguard Worker 	}
323*cf84ac9aSAndroid Build Coastguard Worker }
324*cf84ac9aSAndroid Build Coastguard Worker #endif /* !current_klongsize */
325*cf84ac9aSAndroid Build Coastguard Worker 
326*cf84ac9aSAndroid Build Coastguard Worker /**
327*cf84ac9aSAndroid Build Coastguard Worker  * Prints time to a (static internal) buffer and returns pointer to it.
328*cf84ac9aSAndroid Build Coastguard Worker  * Returns NULL if the provided time specification is not correct.
329*cf84ac9aSAndroid Build Coastguard Worker  *
330*cf84ac9aSAndroid Build Coastguard Worker  * @param sec		Seconds since epoch.
331*cf84ac9aSAndroid Build Coastguard Worker  * @param part_sec	Amount of second parts since the start of a second.
332*cf84ac9aSAndroid Build Coastguard Worker  * @param max_part_sec	Maximum value of a valid part_sec.
333*cf84ac9aSAndroid Build Coastguard Worker  * @param width		1 + floor(log10(max_part_sec)).
334*cf84ac9aSAndroid Build Coastguard Worker  * @return		Pointer to a statically allocated string on success,
335*cf84ac9aSAndroid Build Coastguard Worker  *			NULL on error.
336*cf84ac9aSAndroid Build Coastguard Worker  */
337*cf84ac9aSAndroid Build Coastguard Worker static const char *
sprinttime_ex(const long long sec,const unsigned long long part_sec,const unsigned int max_part_sec,const int width)338*cf84ac9aSAndroid Build Coastguard Worker sprinttime_ex(const long long sec, const unsigned long long part_sec,
339*cf84ac9aSAndroid Build Coastguard Worker 	      const unsigned int max_part_sec, const int width)
340*cf84ac9aSAndroid Build Coastguard Worker {
341*cf84ac9aSAndroid Build Coastguard Worker 	static char buf[sizeof(int) * 3 * 6 + sizeof(part_sec) * 3
342*cf84ac9aSAndroid Build Coastguard Worker 			+ sizeof("+0000")];
343*cf84ac9aSAndroid Build Coastguard Worker 
344*cf84ac9aSAndroid Build Coastguard Worker 	if ((sec == 0 && part_sec == 0) || part_sec > max_part_sec)
345*cf84ac9aSAndroid Build Coastguard Worker 		return NULL;
346*cf84ac9aSAndroid Build Coastguard Worker 
347*cf84ac9aSAndroid Build Coastguard Worker 	time_t t = (time_t) sec;
348*cf84ac9aSAndroid Build Coastguard Worker 	struct tm *tmp = (sec == t) ? localtime(&t) : NULL;
349*cf84ac9aSAndroid Build Coastguard Worker 	if (!tmp)
350*cf84ac9aSAndroid Build Coastguard Worker 		return NULL;
351*cf84ac9aSAndroid Build Coastguard Worker 
352*cf84ac9aSAndroid Build Coastguard Worker 	size_t pos = strftime(buf, sizeof(buf), "%FT%T", tmp);
353*cf84ac9aSAndroid Build Coastguard Worker 	if (!pos)
354*cf84ac9aSAndroid Build Coastguard Worker 		return NULL;
355*cf84ac9aSAndroid Build Coastguard Worker 
356*cf84ac9aSAndroid Build Coastguard Worker 	if (part_sec > 0)
357*cf84ac9aSAndroid Build Coastguard Worker 		pos += xsnprintf(buf + pos, sizeof(buf) - pos, ".%0*llu",
358*cf84ac9aSAndroid Build Coastguard Worker 				 width, part_sec);
359*cf84ac9aSAndroid Build Coastguard Worker 
360*cf84ac9aSAndroid Build Coastguard Worker 	return strftime(buf + pos, sizeof(buf) - pos, "%z", tmp) ? buf : NULL;
361*cf84ac9aSAndroid Build Coastguard Worker }
362*cf84ac9aSAndroid Build Coastguard Worker 
363*cf84ac9aSAndroid Build Coastguard Worker const char *
sprinttime(long long sec)364*cf84ac9aSAndroid Build Coastguard Worker sprinttime(long long sec)
365*cf84ac9aSAndroid Build Coastguard Worker {
366*cf84ac9aSAndroid Build Coastguard Worker 	return sprinttime_ex(sec, 0, 0, 0);
367*cf84ac9aSAndroid Build Coastguard Worker }
368*cf84ac9aSAndroid Build Coastguard Worker 
369*cf84ac9aSAndroid Build Coastguard Worker const char *
sprinttime_usec(long long sec,unsigned long long usec)370*cf84ac9aSAndroid Build Coastguard Worker sprinttime_usec(long long sec, unsigned long long usec)
371*cf84ac9aSAndroid Build Coastguard Worker {
372*cf84ac9aSAndroid Build Coastguard Worker 	return sprinttime_ex(sec, usec, 999999, 6);
373*cf84ac9aSAndroid Build Coastguard Worker }
374*cf84ac9aSAndroid Build Coastguard Worker 
375*cf84ac9aSAndroid Build Coastguard Worker const char *
sprinttime_nsec(long long sec,unsigned long long nsec)376*cf84ac9aSAndroid Build Coastguard Worker sprinttime_nsec(long long sec, unsigned long long nsec)
377*cf84ac9aSAndroid Build Coastguard Worker {
378*cf84ac9aSAndroid Build Coastguard Worker 	return sprinttime_ex(sec, nsec, 999999999, 9);
379*cf84ac9aSAndroid Build Coastguard Worker }
380*cf84ac9aSAndroid Build Coastguard Worker 
381*cf84ac9aSAndroid Build Coastguard Worker enum sock_proto
getfdproto(struct tcb * tcp,int fd)382*cf84ac9aSAndroid Build Coastguard Worker getfdproto(struct tcb *tcp, int fd)
383*cf84ac9aSAndroid Build Coastguard Worker {
384*cf84ac9aSAndroid Build Coastguard Worker #ifdef HAVE_SYS_XATTR_H
385*cf84ac9aSAndroid Build Coastguard Worker 	size_t bufsize = 256;
386*cf84ac9aSAndroid Build Coastguard Worker 	char buf[bufsize];
387*cf84ac9aSAndroid Build Coastguard Worker 	ssize_t r;
388*cf84ac9aSAndroid Build Coastguard Worker 	char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
389*cf84ac9aSAndroid Build Coastguard Worker 
390*cf84ac9aSAndroid Build Coastguard Worker 	if (fd < 0)
391*cf84ac9aSAndroid Build Coastguard Worker 		return SOCK_PROTO_UNKNOWN;
392*cf84ac9aSAndroid Build Coastguard Worker 
393*cf84ac9aSAndroid Build Coastguard Worker 	xsprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
394*cf84ac9aSAndroid Build Coastguard Worker 	r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
395*cf84ac9aSAndroid Build Coastguard Worker 	if (r <= 0)
396*cf84ac9aSAndroid Build Coastguard Worker 		return SOCK_PROTO_UNKNOWN;
397*cf84ac9aSAndroid Build Coastguard Worker 	else {
398*cf84ac9aSAndroid Build Coastguard Worker 		/*
399*cf84ac9aSAndroid Build Coastguard Worker 		 * This is a protection for the case when the kernel
400*cf84ac9aSAndroid Build Coastguard Worker 		 * side does not append a null byte to the buffer.
401*cf84ac9aSAndroid Build Coastguard Worker 		 */
402*cf84ac9aSAndroid Build Coastguard Worker 		buf[r] = '\0';
403*cf84ac9aSAndroid Build Coastguard Worker 
404*cf84ac9aSAndroid Build Coastguard Worker 		return get_proto_by_name(buf);
405*cf84ac9aSAndroid Build Coastguard Worker 	}
406*cf84ac9aSAndroid Build Coastguard Worker #else
407*cf84ac9aSAndroid Build Coastguard Worker 	return SOCK_PROTO_UNKNOWN;
408*cf84ac9aSAndroid Build Coastguard Worker #endif
409*cf84ac9aSAndroid Build Coastguard Worker }
410*cf84ac9aSAndroid Build Coastguard Worker 
411*cf84ac9aSAndroid Build Coastguard Worker unsigned long
getfdinode(struct tcb * tcp,int fd)412*cf84ac9aSAndroid Build Coastguard Worker getfdinode(struct tcb *tcp, int fd)
413*cf84ac9aSAndroid Build Coastguard Worker {
414*cf84ac9aSAndroid Build Coastguard Worker 	char path[PATH_MAX + 1];
415*cf84ac9aSAndroid Build Coastguard Worker 
416*cf84ac9aSAndroid Build Coastguard Worker 	if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
417*cf84ac9aSAndroid Build Coastguard Worker 		const char *str = STR_STRIP_PREFIX(path, "socket:[");
418*cf84ac9aSAndroid Build Coastguard Worker 
419*cf84ac9aSAndroid Build Coastguard Worker 		if (str != path) {
420*cf84ac9aSAndroid Build Coastguard Worker 			const size_t str_len = strlen(str);
421*cf84ac9aSAndroid Build Coastguard Worker 			if (str_len && str[str_len - 1] == ']')
422*cf84ac9aSAndroid Build Coastguard Worker 				return strtoul(str, NULL, 10);
423*cf84ac9aSAndroid Build Coastguard Worker 		}
424*cf84ac9aSAndroid Build Coastguard Worker 	}
425*cf84ac9aSAndroid Build Coastguard Worker 
426*cf84ac9aSAndroid Build Coastguard Worker 	return 0;
427*cf84ac9aSAndroid Build Coastguard Worker }
428*cf84ac9aSAndroid Build Coastguard Worker 
429*cf84ac9aSAndroid Build Coastguard Worker static bool
printsocket(struct tcb * tcp,int fd,const char * path)430*cf84ac9aSAndroid Build Coastguard Worker printsocket(struct tcb *tcp, int fd, const char *path)
431*cf84ac9aSAndroid Build Coastguard Worker {
432*cf84ac9aSAndroid Build Coastguard Worker 	const char *str = STR_STRIP_PREFIX(path, "socket:[");
433*cf84ac9aSAndroid Build Coastguard Worker 	size_t len;
434*cf84ac9aSAndroid Build Coastguard Worker 	unsigned long inode;
435*cf84ac9aSAndroid Build Coastguard Worker 
436*cf84ac9aSAndroid Build Coastguard Worker 	return (str != path)
437*cf84ac9aSAndroid Build Coastguard Worker 		&& (len = strlen(str))
438*cf84ac9aSAndroid Build Coastguard Worker 		&& (str[len - 1] == ']')
439*cf84ac9aSAndroid Build Coastguard Worker 		&& (inode = strtoul(str, NULL, 10))
440*cf84ac9aSAndroid Build Coastguard Worker 		&& print_sockaddr_by_inode(tcp, fd, inode);
441*cf84ac9aSAndroid Build Coastguard Worker }
442*cf84ac9aSAndroid Build Coastguard Worker 
443*cf84ac9aSAndroid Build Coastguard Worker static bool
printdev(struct tcb * tcp,int fd,const char * path)444*cf84ac9aSAndroid Build Coastguard Worker printdev(struct tcb *tcp, int fd, const char *path)
445*cf84ac9aSAndroid Build Coastguard Worker {
446*cf84ac9aSAndroid Build Coastguard Worker 	struct_stat st;
447*cf84ac9aSAndroid Build Coastguard Worker 
448*cf84ac9aSAndroid Build Coastguard Worker 	if (path[0] != '/')
449*cf84ac9aSAndroid Build Coastguard Worker 		return false;
450*cf84ac9aSAndroid Build Coastguard Worker 
451*cf84ac9aSAndroid Build Coastguard Worker 	if (stat_file(path, &st)) {
452*cf84ac9aSAndroid Build Coastguard Worker 		debug_func_perror_msg("stat(\"%s\")", path);
453*cf84ac9aSAndroid Build Coastguard Worker 		return false;
454*cf84ac9aSAndroid Build Coastguard Worker 	}
455*cf84ac9aSAndroid Build Coastguard Worker 
456*cf84ac9aSAndroid Build Coastguard Worker 	switch (st.st_mode & S_IFMT) {
457*cf84ac9aSAndroid Build Coastguard Worker 	case S_IFBLK:
458*cf84ac9aSAndroid Build Coastguard Worker 	case S_IFCHR:
459*cf84ac9aSAndroid Build Coastguard Worker 		print_quoted_string_ex(path, strlen(path),
460*cf84ac9aSAndroid Build Coastguard Worker 				       QUOTE_OMIT_LEADING_TRAILING_QUOTES,
461*cf84ac9aSAndroid Build Coastguard Worker 				       "<>");
462*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("<%s %u:%u>",
463*cf84ac9aSAndroid Build Coastguard Worker 			S_ISBLK(st.st_mode)? "block" : "char",
464*cf84ac9aSAndroid Build Coastguard Worker 			major(st.st_rdev), minor(st.st_rdev));
465*cf84ac9aSAndroid Build Coastguard Worker 		return true;
466*cf84ac9aSAndroid Build Coastguard Worker 	}
467*cf84ac9aSAndroid Build Coastguard Worker 
468*cf84ac9aSAndroid Build Coastguard Worker 	return false;
469*cf84ac9aSAndroid Build Coastguard Worker }
470*cf84ac9aSAndroid Build Coastguard Worker 
471*cf84ac9aSAndroid Build Coastguard Worker void
printfd(struct tcb * tcp,int fd)472*cf84ac9aSAndroid Build Coastguard Worker printfd(struct tcb *tcp, int fd)
473*cf84ac9aSAndroid Build Coastguard Worker {
474*cf84ac9aSAndroid Build Coastguard Worker 	char path[PATH_MAX + 1];
475*cf84ac9aSAndroid Build Coastguard Worker 	if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
476*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%d<", fd);
477*cf84ac9aSAndroid Build Coastguard Worker 		if (show_fd_path <= 1
478*cf84ac9aSAndroid Build Coastguard Worker 		    || (!printsocket(tcp, fd, path)
479*cf84ac9aSAndroid Build Coastguard Worker 		         && !printdev(tcp, fd, path))) {
480*cf84ac9aSAndroid Build Coastguard Worker 			print_quoted_string_ex(path, strlen(path),
481*cf84ac9aSAndroid Build Coastguard Worker 				QUOTE_OMIT_LEADING_TRAILING_QUOTES, "<>");
482*cf84ac9aSAndroid Build Coastguard Worker 		}
483*cf84ac9aSAndroid Build Coastguard Worker 		tprints(">");
484*cf84ac9aSAndroid Build Coastguard Worker 	} else
485*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%d", fd);
486*cf84ac9aSAndroid Build Coastguard Worker }
487*cf84ac9aSAndroid Build Coastguard Worker 
488*cf84ac9aSAndroid Build Coastguard Worker /*
489*cf84ac9aSAndroid Build Coastguard Worker  * Quote string `instr' of length `size'
490*cf84ac9aSAndroid Build Coastguard Worker  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
491*cf84ac9aSAndroid Build Coastguard Worker  *
492*cf84ac9aSAndroid Build Coastguard Worker  * `escape_chars' specifies characters (in addition to characters with
493*cf84ac9aSAndroid Build Coastguard Worker  * codes 0..31, 127..255, single and double quotes) that should be escaped.
494*cf84ac9aSAndroid Build Coastguard Worker  *
495*cf84ac9aSAndroid Build Coastguard Worker  * If QUOTE_0_TERMINATED `style' flag is set,
496*cf84ac9aSAndroid Build Coastguard Worker  * treat `instr' as a NUL-terminated string,
497*cf84ac9aSAndroid Build Coastguard Worker  * checking up to (`size' + 1) bytes of `instr'.
498*cf84ac9aSAndroid Build Coastguard Worker  *
499*cf84ac9aSAndroid Build Coastguard Worker  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
500*cf84ac9aSAndroid Build Coastguard Worker  * do not add leading and trailing quoting symbols.
501*cf84ac9aSAndroid Build Coastguard Worker  *
502*cf84ac9aSAndroid Build Coastguard Worker  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
503*cf84ac9aSAndroid Build Coastguard Worker  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
504*cf84ac9aSAndroid Build Coastguard Worker  */
505*cf84ac9aSAndroid Build Coastguard Worker int
string_quote(const char * instr,char * outstr,const unsigned int size,const unsigned int style,const char * escape_chars)506*cf84ac9aSAndroid Build Coastguard Worker string_quote(const char *instr, char *outstr, const unsigned int size,
507*cf84ac9aSAndroid Build Coastguard Worker 	     const unsigned int style, const char *escape_chars)
508*cf84ac9aSAndroid Build Coastguard Worker {
509*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned char *ustr = (const unsigned char *) instr;
510*cf84ac9aSAndroid Build Coastguard Worker 	char *s = outstr;
511*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int i;
512*cf84ac9aSAndroid Build Coastguard Worker 	int usehex, c, eol;
513*cf84ac9aSAndroid Build Coastguard Worker 	bool escape;
514*cf84ac9aSAndroid Build Coastguard Worker 
515*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_0_TERMINATED)
516*cf84ac9aSAndroid Build Coastguard Worker 		eol = '\0';
517*cf84ac9aSAndroid Build Coastguard Worker 	else
518*cf84ac9aSAndroid Build Coastguard Worker 		eol = 0x100; /* this can never match a char */
519*cf84ac9aSAndroid Build Coastguard Worker 
520*cf84ac9aSAndroid Build Coastguard Worker 	usehex = 0;
521*cf84ac9aSAndroid Build Coastguard Worker 	if ((xflag > 1) || (style & QUOTE_FORCE_HEX)) {
522*cf84ac9aSAndroid Build Coastguard Worker 		usehex = 1;
523*cf84ac9aSAndroid Build Coastguard Worker 	} else if (xflag) {
524*cf84ac9aSAndroid Build Coastguard Worker 		/* Check for presence of symbol which require
525*cf84ac9aSAndroid Build Coastguard Worker 		   to hex-quote the whole string. */
526*cf84ac9aSAndroid Build Coastguard Worker 		for (i = 0; i < size; ++i) {
527*cf84ac9aSAndroid Build Coastguard Worker 			c = ustr[i];
528*cf84ac9aSAndroid Build Coastguard Worker 			/* Check for NUL-terminated string. */
529*cf84ac9aSAndroid Build Coastguard Worker 			if (c == eol)
530*cf84ac9aSAndroid Build Coastguard Worker 				break;
531*cf84ac9aSAndroid Build Coastguard Worker 
532*cf84ac9aSAndroid Build Coastguard Worker 			/* Force hex unless c is printable or whitespace */
533*cf84ac9aSAndroid Build Coastguard Worker 			if (c > 0x7e) {
534*cf84ac9aSAndroid Build Coastguard Worker 				usehex = 1;
535*cf84ac9aSAndroid Build Coastguard Worker 				break;
536*cf84ac9aSAndroid Build Coastguard Worker 			}
537*cf84ac9aSAndroid Build Coastguard Worker 			/* In ASCII isspace is only these chars: "\t\n\v\f\r".
538*cf84ac9aSAndroid Build Coastguard Worker 			 * They happen to have ASCII codes 9,10,11,12,13.
539*cf84ac9aSAndroid Build Coastguard Worker 			 */
540*cf84ac9aSAndroid Build Coastguard Worker 			if (c < ' ' && (unsigned)(c - 9) >= 5) {
541*cf84ac9aSAndroid Build Coastguard Worker 				usehex = 1;
542*cf84ac9aSAndroid Build Coastguard Worker 				break;
543*cf84ac9aSAndroid Build Coastguard Worker 			}
544*cf84ac9aSAndroid Build Coastguard Worker 		}
545*cf84ac9aSAndroid Build Coastguard Worker 	}
546*cf84ac9aSAndroid Build Coastguard Worker 
547*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_EMIT_COMMENT)
548*cf84ac9aSAndroid Build Coastguard Worker 		s = stpcpy(s, " /* ");
549*cf84ac9aSAndroid Build Coastguard Worker 	if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
550*cf84ac9aSAndroid Build Coastguard Worker 		*s++ = '\"';
551*cf84ac9aSAndroid Build Coastguard Worker 
552*cf84ac9aSAndroid Build Coastguard Worker 	if (usehex) {
553*cf84ac9aSAndroid Build Coastguard Worker 		/* Hex-quote the whole string. */
554*cf84ac9aSAndroid Build Coastguard Worker 		for (i = 0; i < size; ++i) {
555*cf84ac9aSAndroid Build Coastguard Worker 			c = ustr[i];
556*cf84ac9aSAndroid Build Coastguard Worker 			/* Check for NUL-terminated string. */
557*cf84ac9aSAndroid Build Coastguard Worker 			if (c == eol)
558*cf84ac9aSAndroid Build Coastguard Worker 				goto asciz_ended;
559*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
560*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 'x';
561*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = "0123456789abcdef"[c >> 4];
562*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = "0123456789abcdef"[c & 0xf];
563*cf84ac9aSAndroid Build Coastguard Worker 		}
564*cf84ac9aSAndroid Build Coastguard Worker 
565*cf84ac9aSAndroid Build Coastguard Worker 		goto string_ended;
566*cf84ac9aSAndroid Build Coastguard Worker 	}
567*cf84ac9aSAndroid Build Coastguard Worker 
568*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < size; ++i) {
569*cf84ac9aSAndroid Build Coastguard Worker 		c = ustr[i];
570*cf84ac9aSAndroid Build Coastguard Worker 		/* Check for NUL-terminated string. */
571*cf84ac9aSAndroid Build Coastguard Worker 		if (c == eol)
572*cf84ac9aSAndroid Build Coastguard Worker 			goto asciz_ended;
573*cf84ac9aSAndroid Build Coastguard Worker 		if ((i == (size - 1)) &&
574*cf84ac9aSAndroid Build Coastguard Worker 		    (style & QUOTE_OMIT_TRAILING_0) && (c == '\0'))
575*cf84ac9aSAndroid Build Coastguard Worker 			goto asciz_ended;
576*cf84ac9aSAndroid Build Coastguard Worker 		switch (c) {
577*cf84ac9aSAndroid Build Coastguard Worker 		case '\"': case '\\':
578*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
579*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = c;
580*cf84ac9aSAndroid Build Coastguard Worker 			break;
581*cf84ac9aSAndroid Build Coastguard Worker 		case '\f':
582*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
583*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 'f';
584*cf84ac9aSAndroid Build Coastguard Worker 			break;
585*cf84ac9aSAndroid Build Coastguard Worker 		case '\n':
586*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
587*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 'n';
588*cf84ac9aSAndroid Build Coastguard Worker 			break;
589*cf84ac9aSAndroid Build Coastguard Worker 		case '\r':
590*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
591*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 'r';
592*cf84ac9aSAndroid Build Coastguard Worker 			break;
593*cf84ac9aSAndroid Build Coastguard Worker 		case '\t':
594*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
595*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 't';
596*cf84ac9aSAndroid Build Coastguard Worker 			break;
597*cf84ac9aSAndroid Build Coastguard Worker 		case '\v':
598*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = '\\';
599*cf84ac9aSAndroid Build Coastguard Worker 			*s++ = 'v';
600*cf84ac9aSAndroid Build Coastguard Worker 			break;
601*cf84ac9aSAndroid Build Coastguard Worker 		default:
602*cf84ac9aSAndroid Build Coastguard Worker 			escape = (c < ' ') || (c > 0x7e);
603*cf84ac9aSAndroid Build Coastguard Worker 
604*cf84ac9aSAndroid Build Coastguard Worker 			if (!escape && escape_chars)
605*cf84ac9aSAndroid Build Coastguard Worker 				escape = !!strchr(escape_chars, c);
606*cf84ac9aSAndroid Build Coastguard Worker 
607*cf84ac9aSAndroid Build Coastguard Worker 			if (!escape) {
608*cf84ac9aSAndroid Build Coastguard Worker 				*s++ = c;
609*cf84ac9aSAndroid Build Coastguard Worker 			} else {
610*cf84ac9aSAndroid Build Coastguard Worker 				/* Print \octal */
611*cf84ac9aSAndroid Build Coastguard Worker 				*s++ = '\\';
612*cf84ac9aSAndroid Build Coastguard Worker 				if (i + 1 < size
613*cf84ac9aSAndroid Build Coastguard Worker 				    && ustr[i + 1] >= '0'
614*cf84ac9aSAndroid Build Coastguard Worker 				    && ustr[i + 1] <= '7'
615*cf84ac9aSAndroid Build Coastguard Worker 				) {
616*cf84ac9aSAndroid Build Coastguard Worker 					/* Print \ooo */
617*cf84ac9aSAndroid Build Coastguard Worker 					*s++ = '0' + (c >> 6);
618*cf84ac9aSAndroid Build Coastguard Worker 					*s++ = '0' + ((c >> 3) & 0x7);
619*cf84ac9aSAndroid Build Coastguard Worker 				} else {
620*cf84ac9aSAndroid Build Coastguard Worker 					/* Print \[[o]o]o */
621*cf84ac9aSAndroid Build Coastguard Worker 					if ((c >> 3) != 0) {
622*cf84ac9aSAndroid Build Coastguard Worker 						if ((c >> 6) != 0)
623*cf84ac9aSAndroid Build Coastguard Worker 							*s++ = '0' + (c >> 6);
624*cf84ac9aSAndroid Build Coastguard Worker 						*s++ = '0' + ((c >> 3) & 0x7);
625*cf84ac9aSAndroid Build Coastguard Worker 					}
626*cf84ac9aSAndroid Build Coastguard Worker 				}
627*cf84ac9aSAndroid Build Coastguard Worker 				*s++ = '0' + (c & 0x7);
628*cf84ac9aSAndroid Build Coastguard Worker 			}
629*cf84ac9aSAndroid Build Coastguard Worker 		}
630*cf84ac9aSAndroid Build Coastguard Worker 	}
631*cf84ac9aSAndroid Build Coastguard Worker 
632*cf84ac9aSAndroid Build Coastguard Worker  string_ended:
633*cf84ac9aSAndroid Build Coastguard Worker 	if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
634*cf84ac9aSAndroid Build Coastguard Worker 		*s++ = '\"';
635*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_EMIT_COMMENT)
636*cf84ac9aSAndroid Build Coastguard Worker 		s = stpcpy(s, " */");
637*cf84ac9aSAndroid Build Coastguard Worker 	*s = '\0';
638*cf84ac9aSAndroid Build Coastguard Worker 
639*cf84ac9aSAndroid Build Coastguard Worker 	/* Return zero if we printed entire ASCIZ string (didn't truncate it) */
640*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
641*cf84ac9aSAndroid Build Coastguard Worker 		/* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
642*cf84ac9aSAndroid Build Coastguard Worker 		 * but next char is NUL.
643*cf84ac9aSAndroid Build Coastguard Worker 		 */
644*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
645*cf84ac9aSAndroid Build Coastguard Worker 	}
646*cf84ac9aSAndroid Build Coastguard Worker 
647*cf84ac9aSAndroid Build Coastguard Worker 	return 1;
648*cf84ac9aSAndroid Build Coastguard Worker 
649*cf84ac9aSAndroid Build Coastguard Worker  asciz_ended:
650*cf84ac9aSAndroid Build Coastguard Worker 	if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
651*cf84ac9aSAndroid Build Coastguard Worker 		*s++ = '\"';
652*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_EMIT_COMMENT)
653*cf84ac9aSAndroid Build Coastguard Worker 		s = stpcpy(s, " */");
654*cf84ac9aSAndroid Build Coastguard Worker 	*s = '\0';
655*cf84ac9aSAndroid Build Coastguard Worker 	/* Return zero: we printed entire ASCIZ string (didn't truncate it) */
656*cf84ac9aSAndroid Build Coastguard Worker 	return 0;
657*cf84ac9aSAndroid Build Coastguard Worker }
658*cf84ac9aSAndroid Build Coastguard Worker 
659*cf84ac9aSAndroid Build Coastguard Worker #ifndef ALLOCA_CUTOFF
660*cf84ac9aSAndroid Build Coastguard Worker # define ALLOCA_CUTOFF	4032
661*cf84ac9aSAndroid Build Coastguard Worker #endif
662*cf84ac9aSAndroid Build Coastguard Worker #define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
663*cf84ac9aSAndroid Build Coastguard Worker 
664*cf84ac9aSAndroid Build Coastguard Worker /*
665*cf84ac9aSAndroid Build Coastguard Worker  * Quote string `str' of length `size' and print the result.
666*cf84ac9aSAndroid Build Coastguard Worker  *
667*cf84ac9aSAndroid Build Coastguard Worker  * If QUOTE_0_TERMINATED `style' flag is set,
668*cf84ac9aSAndroid Build Coastguard Worker  * treat `str' as a NUL-terminated string and
669*cf84ac9aSAndroid Build Coastguard Worker  * quote at most (`size' - 1) bytes.
670*cf84ac9aSAndroid Build Coastguard Worker  *
671*cf84ac9aSAndroid Build Coastguard Worker  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
672*cf84ac9aSAndroid Build Coastguard Worker  * do not add leading and trailing quoting symbols.
673*cf84ac9aSAndroid Build Coastguard Worker  *
674*cf84ac9aSAndroid Build Coastguard Worker  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
675*cf84ac9aSAndroid Build Coastguard Worker  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
676*cf84ac9aSAndroid Build Coastguard Worker  */
677*cf84ac9aSAndroid Build Coastguard Worker int
print_quoted_string_ex(const char * str,unsigned int size,const unsigned int style,const char * escape_chars)678*cf84ac9aSAndroid Build Coastguard Worker print_quoted_string_ex(const char *str, unsigned int size,
679*cf84ac9aSAndroid Build Coastguard Worker 		       const unsigned int style, const char *escape_chars)
680*cf84ac9aSAndroid Build Coastguard Worker {
681*cf84ac9aSAndroid Build Coastguard Worker 	char *buf;
682*cf84ac9aSAndroid Build Coastguard Worker 	char *outstr;
683*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int alloc_size;
684*cf84ac9aSAndroid Build Coastguard Worker 	int rc;
685*cf84ac9aSAndroid Build Coastguard Worker 
686*cf84ac9aSAndroid Build Coastguard Worker 	if (size && style & QUOTE_0_TERMINATED)
687*cf84ac9aSAndroid Build Coastguard Worker 		--size;
688*cf84ac9aSAndroid Build Coastguard Worker 
689*cf84ac9aSAndroid Build Coastguard Worker 	alloc_size = 4 * size;
690*cf84ac9aSAndroid Build Coastguard Worker 	if (alloc_size / 4 != size) {
691*cf84ac9aSAndroid Build Coastguard Worker 		error_func_msg("requested %u bytes exceeds %u bytes limit",
692*cf84ac9aSAndroid Build Coastguard Worker 			       size, -1U / 4);
693*cf84ac9aSAndroid Build Coastguard Worker 		tprints("???");
694*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
695*cf84ac9aSAndroid Build Coastguard Worker 	}
696*cf84ac9aSAndroid Build Coastguard Worker 	alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2) +
697*cf84ac9aSAndroid Build Coastguard Worker 		(style & QUOTE_EMIT_COMMENT ? 7 : 0);
698*cf84ac9aSAndroid Build Coastguard Worker 
699*cf84ac9aSAndroid Build Coastguard Worker 	if (use_alloca(alloc_size)) {
700*cf84ac9aSAndroid Build Coastguard Worker 		outstr = alloca(alloc_size);
701*cf84ac9aSAndroid Build Coastguard Worker 		buf = NULL;
702*cf84ac9aSAndroid Build Coastguard Worker 	} else {
703*cf84ac9aSAndroid Build Coastguard Worker 		outstr = buf = malloc(alloc_size);
704*cf84ac9aSAndroid Build Coastguard Worker 		if (!buf) {
705*cf84ac9aSAndroid Build Coastguard Worker 			error_func_msg("memory exhausted when tried to allocate"
706*cf84ac9aSAndroid Build Coastguard Worker 				       " %u bytes", alloc_size);
707*cf84ac9aSAndroid Build Coastguard Worker 			tprints("???");
708*cf84ac9aSAndroid Build Coastguard Worker 			return -1;
709*cf84ac9aSAndroid Build Coastguard Worker 		}
710*cf84ac9aSAndroid Build Coastguard Worker 	}
711*cf84ac9aSAndroid Build Coastguard Worker 
712*cf84ac9aSAndroid Build Coastguard Worker 	rc = string_quote(str, outstr, size, style, escape_chars);
713*cf84ac9aSAndroid Build Coastguard Worker 	tprints(outstr);
714*cf84ac9aSAndroid Build Coastguard Worker 
715*cf84ac9aSAndroid Build Coastguard Worker 	free(buf);
716*cf84ac9aSAndroid Build Coastguard Worker 	return rc;
717*cf84ac9aSAndroid Build Coastguard Worker }
718*cf84ac9aSAndroid Build Coastguard Worker 
719*cf84ac9aSAndroid Build Coastguard Worker inline int
print_quoted_string(const char * str,unsigned int size,const unsigned int style)720*cf84ac9aSAndroid Build Coastguard Worker print_quoted_string(const char *str, unsigned int size,
721*cf84ac9aSAndroid Build Coastguard Worker 		    const unsigned int style)
722*cf84ac9aSAndroid Build Coastguard Worker {
723*cf84ac9aSAndroid Build Coastguard Worker 	return print_quoted_string_ex(str, size, style, NULL);
724*cf84ac9aSAndroid Build Coastguard Worker }
725*cf84ac9aSAndroid Build Coastguard Worker 
726*cf84ac9aSAndroid Build Coastguard Worker /*
727*cf84ac9aSAndroid Build Coastguard Worker  * Quote a NUL-terminated string `str' of length up to `size' - 1
728*cf84ac9aSAndroid Build Coastguard Worker  * and print the result.
729*cf84ac9aSAndroid Build Coastguard Worker  *
730*cf84ac9aSAndroid Build Coastguard Worker  * Returns 0 if NUL was seen, 1 otherwise.
731*cf84ac9aSAndroid Build Coastguard Worker  */
732*cf84ac9aSAndroid Build Coastguard Worker int
print_quoted_cstring(const char * str,unsigned int size)733*cf84ac9aSAndroid Build Coastguard Worker print_quoted_cstring(const char *str, unsigned int size)
734*cf84ac9aSAndroid Build Coastguard Worker {
735*cf84ac9aSAndroid Build Coastguard Worker 	int unterminated =
736*cf84ac9aSAndroid Build Coastguard Worker 		print_quoted_string(str, size, QUOTE_0_TERMINATED);
737*cf84ac9aSAndroid Build Coastguard Worker 
738*cf84ac9aSAndroid Build Coastguard Worker 	if (unterminated)
739*cf84ac9aSAndroid Build Coastguard Worker 		tprints("...");
740*cf84ac9aSAndroid Build Coastguard Worker 
741*cf84ac9aSAndroid Build Coastguard Worker 	return unterminated;
742*cf84ac9aSAndroid Build Coastguard Worker }
743*cf84ac9aSAndroid Build Coastguard Worker 
744*cf84ac9aSAndroid Build Coastguard Worker /*
745*cf84ac9aSAndroid Build Coastguard Worker  * Print path string specified by address `addr' and length `n'.
746*cf84ac9aSAndroid Build Coastguard Worker  * If path length exceeds `n', append `...' to the output.
747*cf84ac9aSAndroid Build Coastguard Worker  *
748*cf84ac9aSAndroid Build Coastguard Worker  * Returns the result of umovenstr.
749*cf84ac9aSAndroid Build Coastguard Worker  */
750*cf84ac9aSAndroid Build Coastguard Worker int
printpathn(struct tcb * const tcp,const kernel_ulong_t addr,unsigned int n)751*cf84ac9aSAndroid Build Coastguard Worker printpathn(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int n)
752*cf84ac9aSAndroid Build Coastguard Worker {
753*cf84ac9aSAndroid Build Coastguard Worker 	char path[PATH_MAX];
754*cf84ac9aSAndroid Build Coastguard Worker 	int nul_seen;
755*cf84ac9aSAndroid Build Coastguard Worker 
756*cf84ac9aSAndroid Build Coastguard Worker 	if (!addr) {
757*cf84ac9aSAndroid Build Coastguard Worker 		tprints("NULL");
758*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
759*cf84ac9aSAndroid Build Coastguard Worker 	}
760*cf84ac9aSAndroid Build Coastguard Worker 
761*cf84ac9aSAndroid Build Coastguard Worker 	/* Cap path length to the path buffer size */
762*cf84ac9aSAndroid Build Coastguard Worker 	if (n > sizeof(path) - 1)
763*cf84ac9aSAndroid Build Coastguard Worker 		n = sizeof(path) - 1;
764*cf84ac9aSAndroid Build Coastguard Worker 
765*cf84ac9aSAndroid Build Coastguard Worker 	/* Fetch one byte more to find out whether path length > n. */
766*cf84ac9aSAndroid Build Coastguard Worker 	nul_seen = umovestr(tcp, addr, n + 1, path);
767*cf84ac9aSAndroid Build Coastguard Worker 	if (nul_seen < 0)
768*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(addr);
769*cf84ac9aSAndroid Build Coastguard Worker 	else {
770*cf84ac9aSAndroid Build Coastguard Worker 		path[n++] = !nul_seen;
771*cf84ac9aSAndroid Build Coastguard Worker 		print_quoted_cstring(path, n);
772*cf84ac9aSAndroid Build Coastguard Worker 	}
773*cf84ac9aSAndroid Build Coastguard Worker 
774*cf84ac9aSAndroid Build Coastguard Worker 	return nul_seen;
775*cf84ac9aSAndroid Build Coastguard Worker }
776*cf84ac9aSAndroid Build Coastguard Worker 
777*cf84ac9aSAndroid Build Coastguard Worker int
printpath(struct tcb * const tcp,const kernel_ulong_t addr)778*cf84ac9aSAndroid Build Coastguard Worker printpath(struct tcb *const tcp, const kernel_ulong_t addr)
779*cf84ac9aSAndroid Build Coastguard Worker {
780*cf84ac9aSAndroid Build Coastguard Worker 	/* Size must correspond to char path[] size in printpathn */
781*cf84ac9aSAndroid Build Coastguard Worker 	return printpathn(tcp, addr, PATH_MAX - 1);
782*cf84ac9aSAndroid Build Coastguard Worker }
783*cf84ac9aSAndroid Build Coastguard Worker 
784*cf84ac9aSAndroid Build Coastguard Worker /*
785*cf84ac9aSAndroid Build Coastguard Worker  * Print string specified by address `addr' and length `len'.
786*cf84ac9aSAndroid Build Coastguard Worker  * If `user_style' has QUOTE_0_TERMINATED bit set, treat the string
787*cf84ac9aSAndroid Build Coastguard Worker  * as a NUL-terminated string.
788*cf84ac9aSAndroid Build Coastguard Worker  * Pass `user_style' on to `string_quote'.
789*cf84ac9aSAndroid Build Coastguard Worker  * Append `...' to the output if either the string length exceeds `max_strlen',
790*cf84ac9aSAndroid Build Coastguard Worker  * or QUOTE_0_TERMINATED bit is set and the string length exceeds `len'.
791*cf84ac9aSAndroid Build Coastguard Worker  *
792*cf84ac9aSAndroid Build Coastguard Worker  * Returns the result of umovenstr if style has QUOTE_0_TERMINATED,
793*cf84ac9aSAndroid Build Coastguard Worker  * or the result of umoven otherwise.
794*cf84ac9aSAndroid Build Coastguard Worker  */
795*cf84ac9aSAndroid Build Coastguard Worker int
printstr_ex(struct tcb * const tcp,const kernel_ulong_t addr,const kernel_ulong_t len,const unsigned int user_style)796*cf84ac9aSAndroid Build Coastguard Worker printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
797*cf84ac9aSAndroid Build Coastguard Worker 	    const kernel_ulong_t len, const unsigned int user_style)
798*cf84ac9aSAndroid Build Coastguard Worker {
799*cf84ac9aSAndroid Build Coastguard Worker 	static char *str;
800*cf84ac9aSAndroid Build Coastguard Worker 	static char *outstr;
801*cf84ac9aSAndroid Build Coastguard Worker 
802*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int size;
803*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int style = user_style;
804*cf84ac9aSAndroid Build Coastguard Worker 	int rc;
805*cf84ac9aSAndroid Build Coastguard Worker 	int ellipsis;
806*cf84ac9aSAndroid Build Coastguard Worker 
807*cf84ac9aSAndroid Build Coastguard Worker 	if (!addr) {
808*cf84ac9aSAndroid Build Coastguard Worker 		tprints("NULL");
809*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
810*cf84ac9aSAndroid Build Coastguard Worker 	}
811*cf84ac9aSAndroid Build Coastguard Worker 	/* Allocate static buffers if they are not allocated yet. */
812*cf84ac9aSAndroid Build Coastguard Worker 	if (!str) {
813*cf84ac9aSAndroid Build Coastguard Worker 		const unsigned int outstr_size =
814*cf84ac9aSAndroid Build Coastguard Worker 			4 * max_strlen + /* for quotes and NUL */ 3;
815*cf84ac9aSAndroid Build Coastguard Worker 		/*
816*cf84ac9aSAndroid Build Coastguard Worker 		 * We can assume that outstr_size / 4 == max_strlen
817*cf84ac9aSAndroid Build Coastguard Worker 		 * since we have a guarantee that max_strlen <= -1U / 4.
818*cf84ac9aSAndroid Build Coastguard Worker 		 */
819*cf84ac9aSAndroid Build Coastguard Worker 
820*cf84ac9aSAndroid Build Coastguard Worker 		str = xmalloc(max_strlen + 1);
821*cf84ac9aSAndroid Build Coastguard Worker 		outstr = xmalloc(outstr_size);
822*cf84ac9aSAndroid Build Coastguard Worker 	}
823*cf84ac9aSAndroid Build Coastguard Worker 
824*cf84ac9aSAndroid Build Coastguard Worker 	/* Fetch one byte more because string_quote may look one byte ahead. */
825*cf84ac9aSAndroid Build Coastguard Worker 	size = max_strlen + 1;
826*cf84ac9aSAndroid Build Coastguard Worker 
827*cf84ac9aSAndroid Build Coastguard Worker 	if (size > len)
828*cf84ac9aSAndroid Build Coastguard Worker 		size = len;
829*cf84ac9aSAndroid Build Coastguard Worker 	if (style & QUOTE_0_TERMINATED)
830*cf84ac9aSAndroid Build Coastguard Worker 		rc = umovestr(tcp, addr, size, str);
831*cf84ac9aSAndroid Build Coastguard Worker 	else
832*cf84ac9aSAndroid Build Coastguard Worker 		rc = umoven(tcp, addr, size, str);
833*cf84ac9aSAndroid Build Coastguard Worker 
834*cf84ac9aSAndroid Build Coastguard Worker 	if (rc < 0) {
835*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(addr);
836*cf84ac9aSAndroid Build Coastguard Worker 		return rc;
837*cf84ac9aSAndroid Build Coastguard Worker 	}
838*cf84ac9aSAndroid Build Coastguard Worker 
839*cf84ac9aSAndroid Build Coastguard Worker 	if (size > max_strlen)
840*cf84ac9aSAndroid Build Coastguard Worker 		size = max_strlen;
841*cf84ac9aSAndroid Build Coastguard Worker 	else
842*cf84ac9aSAndroid Build Coastguard Worker 		str[size] = '\xff';
843*cf84ac9aSAndroid Build Coastguard Worker 
844*cf84ac9aSAndroid Build Coastguard Worker 	/* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
845*cf84ac9aSAndroid Build Coastguard Worker 	 * or we were requested to print more than -s NUM chars)...
846*cf84ac9aSAndroid Build Coastguard Worker 	 */
847*cf84ac9aSAndroid Build Coastguard Worker 	ellipsis = string_quote(str, outstr, size, style, NULL)
848*cf84ac9aSAndroid Build Coastguard Worker 		   && len
849*cf84ac9aSAndroid Build Coastguard Worker 		   && ((style & QUOTE_0_TERMINATED)
850*cf84ac9aSAndroid Build Coastguard Worker 		       || len > max_strlen);
851*cf84ac9aSAndroid Build Coastguard Worker 
852*cf84ac9aSAndroid Build Coastguard Worker 	tprints(outstr);
853*cf84ac9aSAndroid Build Coastguard Worker 	if (ellipsis)
854*cf84ac9aSAndroid Build Coastguard Worker 		tprints("...");
855*cf84ac9aSAndroid Build Coastguard Worker 
856*cf84ac9aSAndroid Build Coastguard Worker 	return rc;
857*cf84ac9aSAndroid Build Coastguard Worker }
858*cf84ac9aSAndroid Build Coastguard Worker 
859*cf84ac9aSAndroid Build Coastguard Worker void
dumpiov_upto(struct tcb * const tcp,const int len,const kernel_ulong_t addr,kernel_ulong_t data_size)860*cf84ac9aSAndroid Build Coastguard Worker dumpiov_upto(struct tcb *const tcp, const int len, const kernel_ulong_t addr,
861*cf84ac9aSAndroid Build Coastguard Worker 	     kernel_ulong_t data_size)
862*cf84ac9aSAndroid Build Coastguard Worker {
863*cf84ac9aSAndroid Build Coastguard Worker #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
864*cf84ac9aSAndroid Build Coastguard Worker 	union {
865*cf84ac9aSAndroid Build Coastguard Worker 		struct { uint32_t base; uint32_t len; } *iov32;
866*cf84ac9aSAndroid Build Coastguard Worker 		struct { uint64_t base; uint64_t len; } *iov64;
867*cf84ac9aSAndroid Build Coastguard Worker 	} iovu;
868*cf84ac9aSAndroid Build Coastguard Worker #define iov iovu.iov64
869*cf84ac9aSAndroid Build Coastguard Worker #define sizeof_iov \
870*cf84ac9aSAndroid Build Coastguard Worker 	(current_wordsize == 4 ? (unsigned int) sizeof(*iovu.iov32)	\
871*cf84ac9aSAndroid Build Coastguard Worker 			       : (unsigned int) sizeof(*iovu.iov64))
872*cf84ac9aSAndroid Build Coastguard Worker #define iov_iov_base(i) \
873*cf84ac9aSAndroid Build Coastguard Worker 	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
874*cf84ac9aSAndroid Build Coastguard Worker #define iov_iov_len(i) \
875*cf84ac9aSAndroid Build Coastguard Worker 	(current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
876*cf84ac9aSAndroid Build Coastguard Worker #else
877*cf84ac9aSAndroid Build Coastguard Worker 	struct iovec *iov;
878*cf84ac9aSAndroid Build Coastguard Worker #define sizeof_iov ((unsigned int) sizeof(*iov))
879*cf84ac9aSAndroid Build Coastguard Worker #define iov_iov_base(i) ptr_to_kulong(iov[i].iov_base)
880*cf84ac9aSAndroid Build Coastguard Worker #define iov_iov_len(i) iov[i].iov_len
881*cf84ac9aSAndroid Build Coastguard Worker #endif
882*cf84ac9aSAndroid Build Coastguard Worker 	int i;
883*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int size = sizeof_iov * len;
884*cf84ac9aSAndroid Build Coastguard Worker 	if (size / sizeof_iov != (unsigned int) len) {
885*cf84ac9aSAndroid Build Coastguard Worker 		error_func_msg("requested %u iovec elements exceeds"
886*cf84ac9aSAndroid Build Coastguard Worker 			       " %u iovec limit", len, -1U / sizeof_iov);
887*cf84ac9aSAndroid Build Coastguard Worker 		return;
888*cf84ac9aSAndroid Build Coastguard Worker 	}
889*cf84ac9aSAndroid Build Coastguard Worker 
890*cf84ac9aSAndroid Build Coastguard Worker 	iov = malloc(size);
891*cf84ac9aSAndroid Build Coastguard Worker 	if (!iov) {
892*cf84ac9aSAndroid Build Coastguard Worker 		error_func_msg("memory exhausted when tried to allocate"
893*cf84ac9aSAndroid Build Coastguard Worker 			       " %u bytes", size);
894*cf84ac9aSAndroid Build Coastguard Worker 		return;
895*cf84ac9aSAndroid Build Coastguard Worker 	}
896*cf84ac9aSAndroid Build Coastguard Worker 	if (umoven(tcp, addr, size, iov) >= 0) {
897*cf84ac9aSAndroid Build Coastguard Worker 		for (i = 0; i < len; i++) {
898*cf84ac9aSAndroid Build Coastguard Worker 			kernel_ulong_t iov_len = iov_iov_len(i);
899*cf84ac9aSAndroid Build Coastguard Worker 			if (iov_len > data_size)
900*cf84ac9aSAndroid Build Coastguard Worker 				iov_len = data_size;
901*cf84ac9aSAndroid Build Coastguard Worker 			if (!iov_len)
902*cf84ac9aSAndroid Build Coastguard Worker 				break;
903*cf84ac9aSAndroid Build Coastguard Worker 			data_size -= iov_len;
904*cf84ac9aSAndroid Build Coastguard Worker 			/* include the buffer number to make it easy to
905*cf84ac9aSAndroid Build Coastguard Worker 			 * match up the trace with the source */
906*cf84ac9aSAndroid Build Coastguard Worker 			tprintf(" * %" PRI_klu " bytes in buffer %d\n", iov_len, i);
907*cf84ac9aSAndroid Build Coastguard Worker 			dumpstr(tcp, iov_iov_base(i), iov_len);
908*cf84ac9aSAndroid Build Coastguard Worker 		}
909*cf84ac9aSAndroid Build Coastguard Worker 	}
910*cf84ac9aSAndroid Build Coastguard Worker 	free(iov);
911*cf84ac9aSAndroid Build Coastguard Worker #undef sizeof_iov
912*cf84ac9aSAndroid Build Coastguard Worker #undef iov_iov_base
913*cf84ac9aSAndroid Build Coastguard Worker #undef iov_iov_len
914*cf84ac9aSAndroid Build Coastguard Worker #undef iov
915*cf84ac9aSAndroid Build Coastguard Worker }
916*cf84ac9aSAndroid Build Coastguard Worker 
917*cf84ac9aSAndroid Build Coastguard Worker void
dumpstr(struct tcb * const tcp,const kernel_ulong_t addr,const int len)918*cf84ac9aSAndroid Build Coastguard Worker dumpstr(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
919*cf84ac9aSAndroid Build Coastguard Worker {
920*cf84ac9aSAndroid Build Coastguard Worker 	static int strsize = -1;
921*cf84ac9aSAndroid Build Coastguard Worker 	static unsigned char *str;
922*cf84ac9aSAndroid Build Coastguard Worker 
923*cf84ac9aSAndroid Build Coastguard Worker 	char outbuf[
924*cf84ac9aSAndroid Build Coastguard Worker 		(
925*cf84ac9aSAndroid Build Coastguard Worker 			(sizeof(
926*cf84ac9aSAndroid Build Coastguard Worker 			"xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx  "
927*cf84ac9aSAndroid Build Coastguard Worker 			"1234567890123456") + /*in case I'm off by few:*/ 4)
928*cf84ac9aSAndroid Build Coastguard Worker 		/*align to 8 to make memset easier:*/ + 7) & -8
929*cf84ac9aSAndroid Build Coastguard Worker 	];
930*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned char *src;
931*cf84ac9aSAndroid Build Coastguard Worker 	int i;
932*cf84ac9aSAndroid Build Coastguard Worker 
933*cf84ac9aSAndroid Build Coastguard Worker 	if ((len < 0) || (len > INT_MAX - 16))
934*cf84ac9aSAndroid Build Coastguard Worker 		return;
935*cf84ac9aSAndroid Build Coastguard Worker 
936*cf84ac9aSAndroid Build Coastguard Worker 	memset(outbuf, ' ', sizeof(outbuf));
937*cf84ac9aSAndroid Build Coastguard Worker 
938*cf84ac9aSAndroid Build Coastguard Worker 	if (strsize < len + 16) {
939*cf84ac9aSAndroid Build Coastguard Worker 		free(str);
940*cf84ac9aSAndroid Build Coastguard Worker 		str = malloc(len + 16);
941*cf84ac9aSAndroid Build Coastguard Worker 		if (!str) {
942*cf84ac9aSAndroid Build Coastguard Worker 			strsize = -1;
943*cf84ac9aSAndroid Build Coastguard Worker 			error_func_msg("memory exhausted when tried to allocate"
944*cf84ac9aSAndroid Build Coastguard Worker 				       " %zu bytes", (size_t) (len + 16));
945*cf84ac9aSAndroid Build Coastguard Worker 			return;
946*cf84ac9aSAndroid Build Coastguard Worker 		}
947*cf84ac9aSAndroid Build Coastguard Worker 		strsize = len + 16;
948*cf84ac9aSAndroid Build Coastguard Worker 	}
949*cf84ac9aSAndroid Build Coastguard Worker 
950*cf84ac9aSAndroid Build Coastguard Worker 	if (umoven(tcp, addr, len, str) < 0)
951*cf84ac9aSAndroid Build Coastguard Worker 		return;
952*cf84ac9aSAndroid Build Coastguard Worker 
953*cf84ac9aSAndroid Build Coastguard Worker 	/* Space-pad to 16 bytes */
954*cf84ac9aSAndroid Build Coastguard Worker 	i = len;
955*cf84ac9aSAndroid Build Coastguard Worker 	while (i & 0xf)
956*cf84ac9aSAndroid Build Coastguard Worker 		str[i++] = ' ';
957*cf84ac9aSAndroid Build Coastguard Worker 
958*cf84ac9aSAndroid Build Coastguard Worker 	i = 0;
959*cf84ac9aSAndroid Build Coastguard Worker 	src = str;
960*cf84ac9aSAndroid Build Coastguard Worker 	while (i < len) {
961*cf84ac9aSAndroid Build Coastguard Worker 		char *dst = outbuf;
962*cf84ac9aSAndroid Build Coastguard Worker 		/* Hex dump */
963*cf84ac9aSAndroid Build Coastguard Worker 		do {
964*cf84ac9aSAndroid Build Coastguard Worker 			if (i < len) {
965*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = "0123456789abcdef"[*src >> 4];
966*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = "0123456789abcdef"[*src & 0xf];
967*cf84ac9aSAndroid Build Coastguard Worker 			} else {
968*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = ' ';
969*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = ' ';
970*cf84ac9aSAndroid Build Coastguard Worker 			}
971*cf84ac9aSAndroid Build Coastguard Worker 			dst++; /* space is there by memset */
972*cf84ac9aSAndroid Build Coastguard Worker 			i++;
973*cf84ac9aSAndroid Build Coastguard Worker 			if ((i & 7) == 0)
974*cf84ac9aSAndroid Build Coastguard Worker 				dst++; /* space is there by memset */
975*cf84ac9aSAndroid Build Coastguard Worker 			src++;
976*cf84ac9aSAndroid Build Coastguard Worker 		} while (i & 0xf);
977*cf84ac9aSAndroid Build Coastguard Worker 		/* ASCII dump */
978*cf84ac9aSAndroid Build Coastguard Worker 		i -= 16;
979*cf84ac9aSAndroid Build Coastguard Worker 		src -= 16;
980*cf84ac9aSAndroid Build Coastguard Worker 		do {
981*cf84ac9aSAndroid Build Coastguard Worker 			if (*src >= ' ' && *src < 0x7f)
982*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = *src;
983*cf84ac9aSAndroid Build Coastguard Worker 			else
984*cf84ac9aSAndroid Build Coastguard Worker 				*dst++ = '.';
985*cf84ac9aSAndroid Build Coastguard Worker 			src++;
986*cf84ac9aSAndroid Build Coastguard Worker 		} while (++i & 0xf);
987*cf84ac9aSAndroid Build Coastguard Worker 		*dst = '\0';
988*cf84ac9aSAndroid Build Coastguard Worker 		tprintf(" | %05x  %s |\n", i - 16, outbuf);
989*cf84ac9aSAndroid Build Coastguard Worker 	}
990*cf84ac9aSAndroid Build Coastguard Worker }
991*cf84ac9aSAndroid Build Coastguard Worker 
992*cf84ac9aSAndroid Build Coastguard Worker bool
tfetch_mem64(struct tcb * const tcp,const uint64_t addr,const unsigned int len,void * const our_addr)993*cf84ac9aSAndroid Build Coastguard Worker tfetch_mem64(struct tcb *const tcp, const uint64_t addr,
994*cf84ac9aSAndroid Build Coastguard Worker 	     const unsigned int len, void *const our_addr)
995*cf84ac9aSAndroid Build Coastguard Worker {
996*cf84ac9aSAndroid Build Coastguard Worker 	return addr && verbose(tcp) &&
997*cf84ac9aSAndroid Build Coastguard Worker 	       (entering(tcp) || !syserror(tcp)) &&
998*cf84ac9aSAndroid Build Coastguard Worker 	       !umoven(tcp, addr, len, our_addr);
999*cf84ac9aSAndroid Build Coastguard Worker }
1000*cf84ac9aSAndroid Build Coastguard Worker 
1001*cf84ac9aSAndroid Build Coastguard Worker bool
tfetch_mem64_ignore_syserror(struct tcb * const tcp,const uint64_t addr,const unsigned int len,void * const our_addr)1002*cf84ac9aSAndroid Build Coastguard Worker tfetch_mem64_ignore_syserror(struct tcb *const tcp, const uint64_t addr,
1003*cf84ac9aSAndroid Build Coastguard Worker 			     const unsigned int len, void *const our_addr)
1004*cf84ac9aSAndroid Build Coastguard Worker {
1005*cf84ac9aSAndroid Build Coastguard Worker 	return addr && verbose(tcp) &&
1006*cf84ac9aSAndroid Build Coastguard Worker 	       !umoven(tcp, addr, len, our_addr);
1007*cf84ac9aSAndroid Build Coastguard Worker }
1008*cf84ac9aSAndroid Build Coastguard Worker 
1009*cf84ac9aSAndroid Build Coastguard Worker int
umoven_or_printaddr64(struct tcb * const tcp,const uint64_t addr,const unsigned int len,void * const our_addr)1010*cf84ac9aSAndroid Build Coastguard Worker umoven_or_printaddr64(struct tcb *const tcp, const uint64_t addr,
1011*cf84ac9aSAndroid Build Coastguard Worker 		      const unsigned int len, void *const our_addr)
1012*cf84ac9aSAndroid Build Coastguard Worker {
1013*cf84ac9aSAndroid Build Coastguard Worker 	if (tfetch_mem64(tcp, addr, len, our_addr))
1014*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
1015*cf84ac9aSAndroid Build Coastguard Worker 	printaddr64(addr);
1016*cf84ac9aSAndroid Build Coastguard Worker 	return -1;
1017*cf84ac9aSAndroid Build Coastguard Worker }
1018*cf84ac9aSAndroid Build Coastguard Worker 
1019*cf84ac9aSAndroid Build Coastguard Worker int
umoven_or_printaddr64_ignore_syserror(struct tcb * const tcp,const uint64_t addr,const unsigned int len,void * const our_addr)1020*cf84ac9aSAndroid Build Coastguard Worker umoven_or_printaddr64_ignore_syserror(struct tcb *const tcp,
1021*cf84ac9aSAndroid Build Coastguard Worker 				      const uint64_t addr,
1022*cf84ac9aSAndroid Build Coastguard Worker 				      const unsigned int len,
1023*cf84ac9aSAndroid Build Coastguard Worker 				      void *const our_addr)
1024*cf84ac9aSAndroid Build Coastguard Worker {
1025*cf84ac9aSAndroid Build Coastguard Worker 	if (tfetch_mem64_ignore_syserror(tcp, addr, len, our_addr))
1026*cf84ac9aSAndroid Build Coastguard Worker 		return 0;
1027*cf84ac9aSAndroid Build Coastguard Worker 	printaddr64(addr);
1028*cf84ac9aSAndroid Build Coastguard Worker 	return -1;
1029*cf84ac9aSAndroid Build Coastguard Worker }
1030*cf84ac9aSAndroid Build Coastguard Worker 
1031*cf84ac9aSAndroid Build Coastguard Worker bool
print_int32_array_member(struct tcb * tcp,void * elem_buf,size_t elem_size,void * data)1032*cf84ac9aSAndroid Build Coastguard Worker print_int32_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
1033*cf84ac9aSAndroid Build Coastguard Worker 			 void *data)
1034*cf84ac9aSAndroid Build Coastguard Worker {
1035*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("%" PRId32, *(int32_t *) elem_buf);
1036*cf84ac9aSAndroid Build Coastguard Worker 
1037*cf84ac9aSAndroid Build Coastguard Worker 	return true;
1038*cf84ac9aSAndroid Build Coastguard Worker }
1039*cf84ac9aSAndroid Build Coastguard Worker 
1040*cf84ac9aSAndroid Build Coastguard Worker bool
print_uint32_array_member(struct tcb * tcp,void * elem_buf,size_t elem_size,void * data)1041*cf84ac9aSAndroid Build Coastguard Worker print_uint32_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
1042*cf84ac9aSAndroid Build Coastguard Worker 			  void *data)
1043*cf84ac9aSAndroid Build Coastguard Worker {
1044*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("%" PRIu32, *(uint32_t *) elem_buf);
1045*cf84ac9aSAndroid Build Coastguard Worker 
1046*cf84ac9aSAndroid Build Coastguard Worker 	return true;
1047*cf84ac9aSAndroid Build Coastguard Worker }
1048*cf84ac9aSAndroid Build Coastguard Worker 
1049*cf84ac9aSAndroid Build Coastguard Worker bool
print_uint64_array_member(struct tcb * tcp,void * elem_buf,size_t elem_size,void * data)1050*cf84ac9aSAndroid Build Coastguard Worker print_uint64_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
1051*cf84ac9aSAndroid Build Coastguard Worker 			  void *data)
1052*cf84ac9aSAndroid Build Coastguard Worker {
1053*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("%" PRIu64, *(uint64_t *) elem_buf);
1054*cf84ac9aSAndroid Build Coastguard Worker 
1055*cf84ac9aSAndroid Build Coastguard Worker 	return true;
1056*cf84ac9aSAndroid Build Coastguard Worker }
1057*cf84ac9aSAndroid Build Coastguard Worker 
1058*cf84ac9aSAndroid Build Coastguard Worker /*
1059*cf84ac9aSAndroid Build Coastguard Worker  * Iteratively fetch and print up to nmemb elements of elem_size size
1060*cf84ac9aSAndroid Build Coastguard Worker  * from the array that starts at tracee's address start_addr.
1061*cf84ac9aSAndroid Build Coastguard Worker  *
1062*cf84ac9aSAndroid Build Coastguard Worker  * Array elements are being fetched to the address specified by elem_buf.
1063*cf84ac9aSAndroid Build Coastguard Worker  *
1064*cf84ac9aSAndroid Build Coastguard Worker  * The fetcher callback function specified by tfetch_mem_func should follow
1065*cf84ac9aSAndroid Build Coastguard Worker  * the same semantics as tfetch_mem function.
1066*cf84ac9aSAndroid Build Coastguard Worker  *
1067*cf84ac9aSAndroid Build Coastguard Worker  * The printer callback function specified by print_func is expected
1068*cf84ac9aSAndroid Build Coastguard Worker  * to print something; if it returns false, no more iterations will be made.
1069*cf84ac9aSAndroid Build Coastguard Worker  *
1070*cf84ac9aSAndroid Build Coastguard Worker  * The pointer specified by opaque_data is passed to each invocation
1071*cf84ac9aSAndroid Build Coastguard Worker  * of print_func callback function.
1072*cf84ac9aSAndroid Build Coastguard Worker  *
1073*cf84ac9aSAndroid Build Coastguard Worker  * This function prints:
1074*cf84ac9aSAndroid Build Coastguard Worker  * - "NULL", if start_addr is NULL;
1075*cf84ac9aSAndroid Build Coastguard Worker  * - "[]", if nmemb is 0;
1076*cf84ac9aSAndroid Build Coastguard Worker  * - start_addr, if nmemb * elem_size overflows or wraps around;
1077*cf84ac9aSAndroid Build Coastguard Worker  * - start_addr, if the first tfetch_mem_func invocation returned false;
1078*cf84ac9aSAndroid Build Coastguard Worker  * - elements of the array, delimited by ", ", with the array itself
1079*cf84ac9aSAndroid Build Coastguard Worker  *   enclosed with [] brackets.
1080*cf84ac9aSAndroid Build Coastguard Worker  *
1081*cf84ac9aSAndroid Build Coastguard Worker  * If abbrev(tcp) is true, then
1082*cf84ac9aSAndroid Build Coastguard Worker  * - the maximum number of elements printed equals to max_strlen;
1083*cf84ac9aSAndroid Build Coastguard Worker  * - "..." is printed instead of max_strlen+1 element
1084*cf84ac9aSAndroid Build Coastguard Worker  *   and no more iterations will be made.
1085*cf84ac9aSAndroid Build Coastguard Worker  *
1086*cf84ac9aSAndroid Build Coastguard Worker  * This function returns true only if tfetch_mem_func has returned true
1087*cf84ac9aSAndroid Build Coastguard Worker  * at least once.
1088*cf84ac9aSAndroid Build Coastguard Worker  */
1089*cf84ac9aSAndroid Build Coastguard Worker bool
print_array_ex(struct tcb * const tcp,const kernel_ulong_t start_addr,const size_t nmemb,void * const elem_buf,const size_t elem_size,tfetch_mem_fn tfetch_mem_func,print_fn print_func,void * const opaque_data,unsigned int flags,const struct xlat * index_xlat,size_t index_xlat_size,const char * index_dflt)1090*cf84ac9aSAndroid Build Coastguard Worker print_array_ex(struct tcb *const tcp,
1091*cf84ac9aSAndroid Build Coastguard Worker 	       const kernel_ulong_t start_addr,
1092*cf84ac9aSAndroid Build Coastguard Worker 	       const size_t nmemb,
1093*cf84ac9aSAndroid Build Coastguard Worker 	       void *const elem_buf,
1094*cf84ac9aSAndroid Build Coastguard Worker 	       const size_t elem_size,
1095*cf84ac9aSAndroid Build Coastguard Worker 	       tfetch_mem_fn tfetch_mem_func,
1096*cf84ac9aSAndroid Build Coastguard Worker 	       print_fn print_func,
1097*cf84ac9aSAndroid Build Coastguard Worker 	       void *const opaque_data,
1098*cf84ac9aSAndroid Build Coastguard Worker 	       unsigned int flags,
1099*cf84ac9aSAndroid Build Coastguard Worker 	       const struct xlat *index_xlat,
1100*cf84ac9aSAndroid Build Coastguard Worker 	       size_t index_xlat_size,
1101*cf84ac9aSAndroid Build Coastguard Worker 	       const char *index_dflt)
1102*cf84ac9aSAndroid Build Coastguard Worker {
1103*cf84ac9aSAndroid Build Coastguard Worker 	if (!start_addr) {
1104*cf84ac9aSAndroid Build Coastguard Worker 		tprints("NULL");
1105*cf84ac9aSAndroid Build Coastguard Worker 		return false;
1106*cf84ac9aSAndroid Build Coastguard Worker 	}
1107*cf84ac9aSAndroid Build Coastguard Worker 
1108*cf84ac9aSAndroid Build Coastguard Worker 	if (!nmemb) {
1109*cf84ac9aSAndroid Build Coastguard Worker 		tprints("[]");
1110*cf84ac9aSAndroid Build Coastguard Worker 		return false;
1111*cf84ac9aSAndroid Build Coastguard Worker 	}
1112*cf84ac9aSAndroid Build Coastguard Worker 
1113*cf84ac9aSAndroid Build Coastguard Worker 	const size_t size = nmemb * elem_size;
1114*cf84ac9aSAndroid Build Coastguard Worker 	const kernel_ulong_t end_addr = start_addr + size;
1115*cf84ac9aSAndroid Build Coastguard Worker 
1116*cf84ac9aSAndroid Build Coastguard Worker 	if (end_addr <= start_addr || size / elem_size != nmemb) {
1117*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(start_addr);
1118*cf84ac9aSAndroid Build Coastguard Worker 		return false;
1119*cf84ac9aSAndroid Build Coastguard Worker 	}
1120*cf84ac9aSAndroid Build Coastguard Worker 
1121*cf84ac9aSAndroid Build Coastguard Worker 	const kernel_ulong_t abbrev_end =
1122*cf84ac9aSAndroid Build Coastguard Worker 		(abbrev(tcp) && max_strlen < nmemb) ?
1123*cf84ac9aSAndroid Build Coastguard Worker 			start_addr + elem_size * max_strlen : end_addr;
1124*cf84ac9aSAndroid Build Coastguard Worker 	kernel_ulong_t cur;
1125*cf84ac9aSAndroid Build Coastguard Worker 	kernel_ulong_t idx = 0;
1126*cf84ac9aSAndroid Build Coastguard Worker 	enum xlat_style xlat_style = flags & XLAT_STYLE_MASK;
1127*cf84ac9aSAndroid Build Coastguard Worker 
1128*cf84ac9aSAndroid Build Coastguard Worker 	for (cur = start_addr; cur < end_addr; cur += elem_size, idx++) {
1129*cf84ac9aSAndroid Build Coastguard Worker 		if (cur != start_addr)
1130*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", ");
1131*cf84ac9aSAndroid Build Coastguard Worker 
1132*cf84ac9aSAndroid Build Coastguard Worker 		if (!tfetch_mem_func(tcp, cur, elem_size, elem_buf)) {
1133*cf84ac9aSAndroid Build Coastguard Worker 			if (cur == start_addr)
1134*cf84ac9aSAndroid Build Coastguard Worker 				printaddr(cur);
1135*cf84ac9aSAndroid Build Coastguard Worker 			else {
1136*cf84ac9aSAndroid Build Coastguard Worker 				tprints("...");
1137*cf84ac9aSAndroid Build Coastguard Worker 				printaddr_comment(cur);
1138*cf84ac9aSAndroid Build Coastguard Worker 			}
1139*cf84ac9aSAndroid Build Coastguard Worker 			break;
1140*cf84ac9aSAndroid Build Coastguard Worker 		}
1141*cf84ac9aSAndroid Build Coastguard Worker 
1142*cf84ac9aSAndroid Build Coastguard Worker 		if (cur == start_addr)
1143*cf84ac9aSAndroid Build Coastguard Worker 			tprints("[");
1144*cf84ac9aSAndroid Build Coastguard Worker 
1145*cf84ac9aSAndroid Build Coastguard Worker 		if (cur >= abbrev_end) {
1146*cf84ac9aSAndroid Build Coastguard Worker 			tprints("...");
1147*cf84ac9aSAndroid Build Coastguard Worker 			cur = end_addr;
1148*cf84ac9aSAndroid Build Coastguard Worker 			break;
1149*cf84ac9aSAndroid Build Coastguard Worker 		}
1150*cf84ac9aSAndroid Build Coastguard Worker 
1151*cf84ac9aSAndroid Build Coastguard Worker 		if (flags & PAF_PRINT_INDICES) {
1152*cf84ac9aSAndroid Build Coastguard Worker 			tprints("[");
1153*cf84ac9aSAndroid Build Coastguard Worker 
1154*cf84ac9aSAndroid Build Coastguard Worker 			if (!index_xlat) {
1155*cf84ac9aSAndroid Build Coastguard Worker 				print_xlat_ex(idx, NULL, xlat_style);
1156*cf84ac9aSAndroid Build Coastguard Worker 			} else if (flags & PAF_INDEX_XLAT_VALUE_INDEXED) {
1157*cf84ac9aSAndroid Build Coastguard Worker 				printxval_indexn_ex(index_xlat,
1158*cf84ac9aSAndroid Build Coastguard Worker 						    index_xlat_size, idx,
1159*cf84ac9aSAndroid Build Coastguard Worker 						    index_dflt, xlat_style);
1160*cf84ac9aSAndroid Build Coastguard Worker 			} else {
1161*cf84ac9aSAndroid Build Coastguard Worker 				printxvals_ex(idx, index_dflt, xlat_style,
1162*cf84ac9aSAndroid Build Coastguard Worker 					      (flags & PAF_INDEX_XLAT_SORTED)
1163*cf84ac9aSAndroid Build Coastguard Worker 						&& idx ? NULL : index_xlat,
1164*cf84ac9aSAndroid Build Coastguard Worker 					      NULL);
1165*cf84ac9aSAndroid Build Coastguard Worker 			}
1166*cf84ac9aSAndroid Build Coastguard Worker 
1167*cf84ac9aSAndroid Build Coastguard Worker 			tprints("] = ");
1168*cf84ac9aSAndroid Build Coastguard Worker 		}
1169*cf84ac9aSAndroid Build Coastguard Worker 
1170*cf84ac9aSAndroid Build Coastguard Worker 		if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
1171*cf84ac9aSAndroid Build Coastguard Worker 			cur = end_addr;
1172*cf84ac9aSAndroid Build Coastguard Worker 			break;
1173*cf84ac9aSAndroid Build Coastguard Worker 		}
1174*cf84ac9aSAndroid Build Coastguard Worker 	}
1175*cf84ac9aSAndroid Build Coastguard Worker 	if (cur != start_addr)
1176*cf84ac9aSAndroid Build Coastguard Worker 		tprints("]");
1177*cf84ac9aSAndroid Build Coastguard Worker 
1178*cf84ac9aSAndroid Build Coastguard Worker 	return cur >= end_addr;
1179*cf84ac9aSAndroid Build Coastguard Worker }
1180*cf84ac9aSAndroid Build Coastguard Worker 
1181*cf84ac9aSAndroid Build Coastguard Worker int
printargs(struct tcb * tcp)1182*cf84ac9aSAndroid Build Coastguard Worker printargs(struct tcb *tcp)
1183*cf84ac9aSAndroid Build Coastguard Worker {
1184*cf84ac9aSAndroid Build Coastguard Worker 	const int n = tcp->s_ent->nargs;
1185*cf84ac9aSAndroid Build Coastguard Worker 	int i;
1186*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i)
1187*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
1188*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_DECODED;
1189*cf84ac9aSAndroid Build Coastguard Worker }
1190*cf84ac9aSAndroid Build Coastguard Worker 
1191*cf84ac9aSAndroid Build Coastguard Worker int
printargs_u(struct tcb * tcp)1192*cf84ac9aSAndroid Build Coastguard Worker printargs_u(struct tcb *tcp)
1193*cf84ac9aSAndroid Build Coastguard Worker {
1194*cf84ac9aSAndroid Build Coastguard Worker 	const int n = tcp->s_ent->nargs;
1195*cf84ac9aSAndroid Build Coastguard Worker 	int i;
1196*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i)
1197*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%s%u", i ? ", " : "",
1198*cf84ac9aSAndroid Build Coastguard Worker 			(unsigned int) tcp->u_arg[i]);
1199*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_DECODED;
1200*cf84ac9aSAndroid Build Coastguard Worker }
1201*cf84ac9aSAndroid Build Coastguard Worker 
1202*cf84ac9aSAndroid Build Coastguard Worker int
printargs_d(struct tcb * tcp)1203*cf84ac9aSAndroid Build Coastguard Worker printargs_d(struct tcb *tcp)
1204*cf84ac9aSAndroid Build Coastguard Worker {
1205*cf84ac9aSAndroid Build Coastguard Worker 	const int n = tcp->s_ent->nargs;
1206*cf84ac9aSAndroid Build Coastguard Worker 	int i;
1207*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i)
1208*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%s%d", i ? ", " : "",
1209*cf84ac9aSAndroid Build Coastguard Worker 			(int) tcp->u_arg[i]);
1210*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_DECODED;
1211*cf84ac9aSAndroid Build Coastguard Worker }
1212*cf84ac9aSAndroid Build Coastguard Worker 
1213*cf84ac9aSAndroid Build Coastguard Worker /* Print abnormal high bits of a kernel_ulong_t value. */
1214*cf84ac9aSAndroid Build Coastguard Worker void
print_abnormal_hi(const kernel_ulong_t val)1215*cf84ac9aSAndroid Build Coastguard Worker print_abnormal_hi(const kernel_ulong_t val)
1216*cf84ac9aSAndroid Build Coastguard Worker {
1217*cf84ac9aSAndroid Build Coastguard Worker 	if (current_klongsize > 4) {
1218*cf84ac9aSAndroid Build Coastguard Worker 		const unsigned int hi = (unsigned int) ((uint64_t) val >> 32);
1219*cf84ac9aSAndroid Build Coastguard Worker 		if (hi)
1220*cf84ac9aSAndroid Build Coastguard Worker 			tprintf("%#x<<32|", hi);
1221*cf84ac9aSAndroid Build Coastguard Worker 	}
1222*cf84ac9aSAndroid Build Coastguard Worker }
1223*cf84ac9aSAndroid Build Coastguard Worker 
1224*cf84ac9aSAndroid Build Coastguard Worker #if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
1225*cf84ac9aSAndroid Build Coastguard Worker # define open_file open64
1226*cf84ac9aSAndroid Build Coastguard Worker #else
1227*cf84ac9aSAndroid Build Coastguard Worker # define open_file open
1228*cf84ac9aSAndroid Build Coastguard Worker #endif
1229*cf84ac9aSAndroid Build Coastguard Worker 
1230*cf84ac9aSAndroid Build Coastguard Worker int
read_int_from_file(struct tcb * tcp,const char * const fname,int * const pvalue)1231*cf84ac9aSAndroid Build Coastguard Worker read_int_from_file(struct tcb *tcp, const char *const fname, int *const pvalue)
1232*cf84ac9aSAndroid Build Coastguard Worker {
1233*cf84ac9aSAndroid Build Coastguard Worker 	const int fd = open_file(fname, O_RDONLY);
1234*cf84ac9aSAndroid Build Coastguard Worker 	if (fd < 0)
1235*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
1236*cf84ac9aSAndroid Build Coastguard Worker 
1237*cf84ac9aSAndroid Build Coastguard Worker 	long lval;
1238*cf84ac9aSAndroid Build Coastguard Worker 	char buf[sizeof(lval) * 3];
1239*cf84ac9aSAndroid Build Coastguard Worker 	int n = read(fd, buf, sizeof(buf) - 1);
1240*cf84ac9aSAndroid Build Coastguard Worker 	int saved_errno = errno;
1241*cf84ac9aSAndroid Build Coastguard Worker 	close(fd);
1242*cf84ac9aSAndroid Build Coastguard Worker 
1243*cf84ac9aSAndroid Build Coastguard Worker 	if (n < 0) {
1244*cf84ac9aSAndroid Build Coastguard Worker 		errno = saved_errno;
1245*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
1246*cf84ac9aSAndroid Build Coastguard Worker 	}
1247*cf84ac9aSAndroid Build Coastguard Worker 
1248*cf84ac9aSAndroid Build Coastguard Worker 	buf[n] = '\0';
1249*cf84ac9aSAndroid Build Coastguard Worker 	char *endptr = 0;
1250*cf84ac9aSAndroid Build Coastguard Worker 	errno = 0;
1251*cf84ac9aSAndroid Build Coastguard Worker 	lval = strtol(buf, &endptr, 10);
1252*cf84ac9aSAndroid Build Coastguard Worker 	if (!endptr || (*endptr && '\n' != *endptr)
1253*cf84ac9aSAndroid Build Coastguard Worker #if INT_MAX < LONG_MAX
1254*cf84ac9aSAndroid Build Coastguard Worker 	    || lval > INT_MAX || lval < INT_MIN
1255*cf84ac9aSAndroid Build Coastguard Worker #endif
1256*cf84ac9aSAndroid Build Coastguard Worker 	    || ERANGE == errno) {
1257*cf84ac9aSAndroid Build Coastguard Worker 		if (!errno)
1258*cf84ac9aSAndroid Build Coastguard Worker 			errno = EINVAL;
1259*cf84ac9aSAndroid Build Coastguard Worker 		return -1;
1260*cf84ac9aSAndroid Build Coastguard Worker 	}
1261*cf84ac9aSAndroid Build Coastguard Worker 
1262*cf84ac9aSAndroid Build Coastguard Worker 	*pvalue = (int) lval;
1263*cf84ac9aSAndroid Build Coastguard Worker 	return 0;
1264*cf84ac9aSAndroid Build Coastguard Worker }
1265