Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
      7  *                    port by Greg Banks <gbanks (at) pocketpenguins.com>
      8  * Copyright (c) 1999-2017 The strace developers.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include "defs.h"
     35 #include <asm/mman.h>
     36 #include <sys/mman.h>
     37 
     38 unsigned long
     39 get_pagesize(void)
     40 {
     41 	static unsigned long pagesize;
     42 
     43 	if (!pagesize)
     44 		pagesize = sysconf(_SC_PAGESIZE);
     45 	return pagesize;
     46 }
     47 
     48 SYS_FUNC(brk)
     49 {
     50 	printaddr(tcp->u_arg[0]);
     51 
     52 	return RVAL_DECODED | RVAL_HEX;
     53 }
     54 
     55 #include "xlat/mmap_prot.h"
     56 #include "xlat/mmap_flags.h"
     57 
     58 static void
     59 print_mmap(struct tcb *tcp, kernel_ulong_t *u_arg, unsigned long long offset)
     60 {
     61 	const kernel_ulong_t addr = u_arg[0];
     62 	const kernel_ulong_t len = u_arg[1];
     63 	const kernel_ulong_t prot = u_arg[2];
     64 	const kernel_ulong_t flags = u_arg[3];
     65 	const int fd = u_arg[4];
     66 
     67 	printaddr(addr);
     68 	tprintf(", %" PRI_klu ", ", len);
     69 	printflags64(mmap_prot, prot, "PROT_???");
     70 	tprints(", ");
     71 #ifdef MAP_TYPE
     72 	printxval64(mmap_flags, flags & MAP_TYPE, "MAP_???");
     73 	addflags(mmap_flags, flags & ~MAP_TYPE);
     74 #else
     75 	printflags64(mmap_flags, flags, "MAP_???");
     76 #endif
     77 	tprints(", ");
     78 	printfd(tcp, fd);
     79 	tprintf(", %#llx", offset);
     80 }
     81 
     82 /* Syscall name<->function correspondence is messed up on many arches.
     83  * For example:
     84  * i386 has __NR_mmap == 90, and it is "old mmap", and
     85  * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets".
     86  * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets".
     87  * Confused? Me too!
     88  */
     89 
     90 #if defined AARCH64 || defined ARM \
     91  || defined I386 || defined X86_64 || defined X32 \
     92  || defined M68K \
     93  || defined S390 || defined S390X
     94 /* Params are pointed to by u_arg[0], offset is in bytes */
     95 SYS_FUNC(old_mmap)
     96 {
     97 	kernel_ulong_t u_arg[6];
     98 # if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
     99 	/* We are here only in a 32-bit personality. */
    100 	unsigned int narrow_arg[6];
    101 	if (umove_or_printaddr(tcp, tcp->u_arg[0], &narrow_arg))
    102 		return RVAL_DECODED | RVAL_HEX;
    103 	unsigned int i;
    104 	for (i = 0; i < 6; i++)
    105 		u_arg[i] = narrow_arg[i];
    106 # else
    107 	if (umove_or_printaddr(tcp, tcp->u_arg[0], &u_arg))
    108 		return RVAL_DECODED | RVAL_HEX;
    109 # endif
    110 	print_mmap(tcp, u_arg, u_arg[5]);
    111 
    112 	return RVAL_DECODED | RVAL_HEX;
    113 }
    114 #endif /* old_mmap architectures */
    115 
    116 #ifdef S390
    117 /* Params are pointed to by u_arg[0], offset is in pages */
    118 SYS_FUNC(old_mmap_pgoff)
    119 {
    120 	kernel_ulong_t u_arg[5];
    121 	int i;
    122 	unsigned int narrow_arg[6];
    123 	unsigned long long offset;
    124 	if (umove_or_printaddr(tcp, tcp->u_arg[0], &narrow_arg))
    125 		return RVAL_DECODED | RVAL_HEX;
    126 	for (i = 0; i < 5; i++)
    127 		u_arg[i] = narrow_arg[i];
    128 	offset = narrow_arg[5];
    129 	offset *= get_pagesize();
    130 	print_mmap(tcp, u_arg, offset);
    131 
    132 	return RVAL_DECODED | RVAL_HEX;
    133 }
    134 #endif /* S390 */
    135 
    136 /* Params are passed directly, offset is in bytes */
    137 SYS_FUNC(mmap)
    138 {
    139 	/* Example of kernel-side handling of this variety of mmap:
    140 	 * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls
    141 	 * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes,
    142 	 * since the above code converts off to pages.
    143 	 */
    144 	print_mmap(tcp, tcp->u_arg, tcp->u_arg[5]);
    145 
    146 	return RVAL_DECODED | RVAL_HEX;
    147 }
    148 
    149 /* Params are passed directly, offset is in pages */
    150 SYS_FUNC(mmap_pgoff)
    151 {
    152 	/* Try test/mmap_offset_decode.c */
    153 	unsigned long long offset;
    154 	offset = tcp->u_arg[5];
    155 	offset *= get_pagesize();
    156 	print_mmap(tcp, tcp->u_arg, offset);
    157 
    158 	return RVAL_DECODED | RVAL_HEX;
    159 }
    160 
    161 /* Params are passed directly, offset is in 4k units */
    162 SYS_FUNC(mmap_4koff)
    163 {
    164 	unsigned long long offset;
    165 	offset = tcp->u_arg[5];
    166 	offset <<= 12;
    167 	print_mmap(tcp, tcp->u_arg, offset);
    168 
    169 	return RVAL_DECODED | RVAL_HEX;
    170 }
    171 
    172 SYS_FUNC(munmap)
    173 {
    174 	printaddr(tcp->u_arg[0]);
    175 	tprintf(", %" PRI_klu, tcp->u_arg[1]);
    176 
    177 	return RVAL_DECODED;
    178 }
    179 
    180 static int
    181 do_mprotect(struct tcb *tcp, bool has_pkey)
    182 {
    183 	printaddr(tcp->u_arg[0]);
    184 	tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
    185 	printflags64(mmap_prot, tcp->u_arg[2], "PROT_???");
    186 
    187 	if (has_pkey)
    188 		tprintf(", %d", (int) tcp->u_arg[3]);
    189 
    190 	return RVAL_DECODED;
    191 }
    192 
    193 SYS_FUNC(mprotect)
    194 {
    195 	return do_mprotect(tcp, false);
    196 }
    197 
    198 SYS_FUNC(pkey_mprotect)
    199 {
    200 	return do_mprotect(tcp, true);
    201 }
    202 
    203 #include "xlat/mremap_flags.h"
    204 
    205 SYS_FUNC(mremap)
    206 {
    207 	printaddr(tcp->u_arg[0]);
    208 	tprintf(", %" PRI_klu ", %" PRI_klu ", ", tcp->u_arg[1], tcp->u_arg[2]);
    209 	printflags64(mremap_flags, tcp->u_arg[3], "MREMAP_???");
    210 #ifdef MREMAP_FIXED
    211 	if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) ==
    212 	    (MREMAP_MAYMOVE | MREMAP_FIXED)) {
    213 		tprints(", ");
    214 		printaddr(tcp->u_arg[4]);
    215 	}
    216 #endif
    217 	return RVAL_DECODED | RVAL_HEX;
    218 }
    219 
    220 #include "xlat/madvise_cmds.h"
    221 
    222 SYS_FUNC(madvise)
    223 {
    224 	printaddr(tcp->u_arg[0]);
    225 	tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
    226 	printxval(madvise_cmds, tcp->u_arg[2], "MADV_???");
    227 
    228 	return RVAL_DECODED;
    229 }
    230 
    231 #include "xlat/mlockall_flags.h"
    232 
    233 SYS_FUNC(mlockall)
    234 {
    235 	printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
    236 
    237 	return RVAL_DECODED;
    238 }
    239 
    240 #include "xlat/mctl_sync.h"
    241 
    242 SYS_FUNC(msync)
    243 {
    244 	/* addr */
    245 	printaddr(tcp->u_arg[0]);
    246 	/* len */
    247 	tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
    248 	/* flags */
    249 	printflags(mctl_sync, tcp->u_arg[2], "MS_???");
    250 
    251 	return RVAL_DECODED;
    252 }
    253 
    254 #include "xlat/mlock_flags.h"
    255 
    256 SYS_FUNC(mlock2)
    257 {
    258 	printaddr(tcp->u_arg[0]);
    259 	tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
    260 	printflags(mlock_flags, tcp->u_arg[2], "MLOCK_???");
    261 
    262 	return RVAL_DECODED;
    263 }
    264 
    265 SYS_FUNC(mincore)
    266 {
    267 	if (entering(tcp)) {
    268 		printaddr(tcp->u_arg[0]);
    269 		tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
    270 	} else {
    271 		const unsigned long page_size = get_pagesize();
    272 		const unsigned long page_mask = page_size - 1;
    273 		unsigned long len = tcp->u_arg[1];
    274 		unsigned char *vec = NULL;
    275 
    276 		len = len / page_size + (len & page_mask ? 1 : 0);
    277 		if (syserror(tcp) || !verbose(tcp) ||
    278 		    !tcp->u_arg[2] || !(vec = malloc(len)) ||
    279 		    umoven(tcp, tcp->u_arg[2], len, vec) < 0)
    280 			printaddr(tcp->u_arg[2]);
    281 		else {
    282 			unsigned long i;
    283 			tprints("[");
    284 			for (i = 0; i < len; i++) {
    285 				if (i)
    286 					tprints(", ");
    287 				if (abbrev(tcp) && i >= max_strlen) {
    288 					tprints("...");
    289 					break;
    290 				}
    291 				tprints((vec[i] & 1) ? "1" : "0");
    292 			}
    293 			tprints("]");
    294 		}
    295 		free(vec);
    296 	}
    297 	return 0;
    298 }
    299 
    300 #if defined ALPHA || defined IA64 || defined M68K \
    301  || defined SPARC || defined SPARC64
    302 SYS_FUNC(getpagesize)
    303 {
    304 	return RVAL_DECODED | RVAL_HEX;
    305 }
    306 #endif
    307 
    308 SYS_FUNC(remap_file_pages)
    309 {
    310 	const kernel_ulong_t addr = tcp->u_arg[0];
    311 	const kernel_ulong_t size = tcp->u_arg[1];
    312 	const kernel_ulong_t prot = tcp->u_arg[2];
    313 	const kernel_ulong_t pgoff = tcp->u_arg[3];
    314 	const kernel_ulong_t flags = tcp->u_arg[4];
    315 
    316 	printaddr(addr);
    317 	tprintf(", %" PRI_klu ", ", size);
    318 	printflags64(mmap_prot, prot, "PROT_???");
    319 	tprintf(", %" PRI_klu ", ", pgoff);
    320 #ifdef MAP_TYPE
    321 	printxval64(mmap_flags, flags & MAP_TYPE, "MAP_???");
    322 	addflags(mmap_flags, flags & ~MAP_TYPE);
    323 #else
    324 	printflags64(mmap_flags, flags, "MAP_???");
    325 #endif
    326 
    327 	return RVAL_DECODED;
    328 }
    329 
    330 #if defined(POWERPC)
    331 static bool
    332 print_protmap_entry(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
    333 {
    334 	tprintf("%#08x", *(unsigned int *) elem_buf);
    335 
    336 	return true;
    337 }
    338 
    339 SYS_FUNC(subpage_prot)
    340 {
    341 	kernel_ulong_t addr = tcp->u_arg[0];
    342 	kernel_ulong_t len = tcp->u_arg[1];
    343 	kernel_ulong_t nmemb = len >> 16;
    344 	kernel_ulong_t map = tcp->u_arg[2];
    345 
    346 	printaddr(addr);
    347 	tprintf(", %" PRI_klu ", ", len);
    348 
    349 	unsigned int entry;
    350 	print_array(tcp, map, nmemb, &entry, sizeof(entry),
    351 		    umoven_or_printaddr, print_protmap_entry, 0);
    352 
    353 	return RVAL_DECODED;
    354 }
    355 #endif
    356