(root)/
strace-6.5/
src/
mem.c
       1  /*
       2   * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
       7   *                    port by Greg Banks <gbanks@pocketpenguins.com>
       8   * Copyright (c) 1999-2023 The strace developers.
       9   * All rights reserved.
      10   *
      11   * SPDX-License-Identifier: LGPL-2.1-or-later
      12   */
      13  
      14  #include "defs.h"
      15  #include <linux/mman.h>
      16  #include <sys/mman.h>
      17  
      18  unsigned long
      19  get_pagesize(void)
      20  {
      21  	static unsigned long pagesize;
      22  
      23  	if (!pagesize) {
      24  		long ret = sysconf(_SC_PAGESIZE);
      25  
      26  		if (ret < 0)
      27  			perror_func_msg_and_die("sysconf(_SC_PAGESIZE)");
      28  		if (ret == 0)
      29  			error_func_msg_and_die("sysconf(_SC_PAGESIZE) "
      30  					       "returned 0");
      31  
      32  		pagesize = (unsigned long) ret;
      33  	}
      34  
      35  	return pagesize;
      36  }
      37  
      38  SYS_FUNC(brk)
      39  {
      40  	printaddr(tcp->u_arg[0]);
      41  
      42  	return RVAL_DECODED | RVAL_HEX;
      43  }
      44  
      45  #include "xlat/mmap_prot.h"
      46  #include "xlat/mmap_flags.h"
      47  
      48  #ifndef MAP_HUGE_SHIFT
      49  # define MAP_HUGE_SHIFT 26
      50  #endif
      51  
      52  #ifndef MAP_HUGE_MASK
      53  # define MAP_HUGE_MASK 0x3f
      54  #endif
      55  
      56  static void
      57  print_mmap_flags(kernel_ulong_t flags)
      58  {
      59  	if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
      60  		PRINT_VAL_X(flags);
      61  
      62  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
      63  		return;
      64  
      65  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
      66  		tprint_comment_begin();
      67  
      68  	tprint_flags_begin();
      69  
      70  	printxvals_ex(flags & MAP_TYPE, "MAP_???", XLAT_STYLE_ABBREV,
      71  		      mmap_flags, NULL);
      72  	flags &= ~MAP_TYPE;
      73  
      74  	const unsigned int mask = MAP_HUGE_MASK << MAP_HUGE_SHIFT;
      75  	const unsigned int hugetlb_value = flags & mask;
      76  
      77  	flags &= ~mask;
      78  	if (flags) {
      79  		tprint_flags_or();
      80  		printflags_ex(flags, NULL, XLAT_STYLE_ABBREV,
      81  			      mmap_flags, NULL);
      82  	}
      83  
      84  	if (hugetlb_value) {
      85  		tprint_flags_or();
      86  		tprint_shift_begin();
      87  		PRINT_VAL_U(hugetlb_value >> MAP_HUGE_SHIFT);
      88  		tprint_shift();
      89  		/*
      90  		 * print_xlat_u is not used here because the whole thing
      91  		 * is potentially inside a comment already.
      92  		 */
      93  		tprints_string("MAP_HUGE_SHIFT");
      94  		tprint_shift_end();
      95  	}
      96  
      97  	tprint_flags_end();
      98  
      99  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
     100                  tprint_comment_end();
     101  }
     102  
     103  static void
     104  print_mmap(struct tcb *tcp, kernel_ulong_t *u_arg, unsigned long long offset)
     105  {
     106  	const kernel_ulong_t addr = u_arg[0];
     107  	const kernel_ulong_t len = u_arg[1];
     108  	const kernel_ulong_t prot = u_arg[2];
     109  	const kernel_ulong_t flags = u_arg[3];
     110  	const int fd = u_arg[4];
     111  
     112  	/* addr */
     113  	printaddr(addr);
     114  	tprint_arg_next();
     115  
     116  	/* length */
     117  	PRINT_VAL_U(len);
     118  	tprint_arg_next();
     119  
     120  	/* prot */
     121  	printflags64(mmap_prot, prot, "PROT_???");
     122  	tprint_arg_next();
     123  
     124  	/* flags */
     125  	print_mmap_flags(flags);
     126  	tprint_arg_next();
     127  
     128  	/* fd */
     129  	printfd(tcp, fd);
     130  	tprint_arg_next();
     131  
     132  	/* offset */
     133  	PRINT_VAL_X(offset);
     134  }
     135  
     136  /* Syscall name<->function correspondence is messed up on many arches.
     137   * For example:
     138   * i386 has __NR_mmap == 90, and it is "old mmap", and
     139   * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets".
     140   * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets".
     141   * Confused? Me too!
     142   */
     143  
     144  #if HAVE_ARCH_OLD_MMAP
     145  /* Params are pointed to by u_arg[0], offset is in bytes */
     146  SYS_FUNC(old_mmap)
     147  {
     148  	kernel_ulong_t *args =
     149  		fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
     150  
     151  	if (args)
     152  		print_mmap(tcp, args, args[5]);
     153  	else
     154  		printaddr(tcp->u_arg[0]);
     155  
     156  	return RVAL_DECODED | RVAL_HEX;
     157  }
     158  
     159  # if HAVE_ARCH_OLD_MMAP_PGOFF
     160  /* Params are pointed to by u_arg[0], offset is in pages */
     161  SYS_FUNC(old_mmap_pgoff)
     162  {
     163  	kernel_ulong_t *args =
     164  		fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
     165  
     166  	if (args) {
     167  		unsigned long long offset;
     168  
     169  		offset = args[5];
     170  		offset *= get_pagesize();
     171  
     172  		print_mmap(tcp, args, offset);
     173  	} else {
     174  		printaddr(tcp->u_arg[0]);
     175  	}
     176  
     177  	return RVAL_DECODED | RVAL_HEX;
     178  }
     179  # endif /* HAVE_ARCH_OLD_MMAP_PGOFF */
     180  #endif /* HAVE_ARCH_OLD_MMAP */
     181  
     182  /* Params are passed directly, offset is in bytes */
     183  SYS_FUNC(mmap)
     184  {
     185  	/* Example of kernel-side handling of this variety of mmap:
     186  	 * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls
     187  	 * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes,
     188  	 * since the above code converts off to pages.
     189  	 */
     190  	print_mmap(tcp, tcp->u_arg, tcp->u_arg[5]);
     191  
     192  	return RVAL_DECODED | RVAL_HEX;
     193  }
     194  
     195  /* Params are passed directly, offset is in pages */
     196  SYS_FUNC(mmap_pgoff)
     197  {
     198  	/* Try test/mmap_offset_decode.c */
     199  	unsigned long long offset;
     200  	offset = tcp->u_arg[5];
     201  	offset *= get_pagesize();
     202  	print_mmap(tcp, tcp->u_arg, offset);
     203  
     204  	return RVAL_DECODED | RVAL_HEX;
     205  }
     206  
     207  /* Params are passed directly, offset is in 4k units */
     208  SYS_FUNC(mmap_4koff)
     209  {
     210  	unsigned long long offset;
     211  	offset = tcp->u_arg[5];
     212  	offset <<= 12;
     213  	print_mmap(tcp, tcp->u_arg, offset);
     214  
     215  	return RVAL_DECODED | RVAL_HEX;
     216  }
     217  
     218  SYS_FUNC(munmap)
     219  {
     220  	/* addr */
     221  	printaddr(tcp->u_arg[0]);
     222  	tprint_arg_next();
     223  
     224  	/* length */
     225  	PRINT_VAL_U(tcp->u_arg[1]);
     226  
     227  	return RVAL_DECODED;
     228  }
     229  
     230  static int
     231  do_mprotect(struct tcb *tcp, bool has_pkey)
     232  {
     233  	/* addr */
     234  	printaddr(tcp->u_arg[0]);
     235  	tprint_arg_next();
     236  
     237  	/* length */
     238  	PRINT_VAL_U(tcp->u_arg[1]);
     239  	tprint_arg_next();
     240  
     241  	/* prot */
     242  	printflags64(mmap_prot, tcp->u_arg[2], "PROT_???");
     243  
     244  	if (has_pkey) {
     245  		tprint_arg_next();
     246  		/* pkey */
     247  		PRINT_VAL_D((int) tcp->u_arg[3]);
     248  	}
     249  
     250  	return RVAL_DECODED;
     251  }
     252  
     253  SYS_FUNC(mprotect)
     254  {
     255  	return do_mprotect(tcp, false);
     256  }
     257  
     258  SYS_FUNC(pkey_mprotect)
     259  {
     260  	return do_mprotect(tcp, true);
     261  }
     262  
     263  #include "xlat/mremap_flags.h"
     264  
     265  SYS_FUNC(mremap)
     266  {
     267  	/* old_address */
     268  	printaddr(tcp->u_arg[0]);
     269  	tprint_arg_next();
     270  
     271  	/* old_size */
     272  	PRINT_VAL_U(tcp->u_arg[1]);
     273  	tprint_arg_next();
     274  
     275  	/* new_size */
     276  	PRINT_VAL_U(tcp->u_arg[2]);
     277  	tprint_arg_next();
     278  
     279  	/* flags */
     280  	printflags64(mremap_flags, tcp->u_arg[3], "MREMAP_???");
     281  
     282  	if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) ==
     283  	    (MREMAP_MAYMOVE | MREMAP_FIXED)) {
     284  		/* new_address */
     285  		tprint_arg_next();
     286  		printaddr(tcp->u_arg[4]);
     287  	}
     288  
     289  	return RVAL_DECODED | RVAL_HEX;
     290  }
     291  
     292  #include "xlat/madvise_cmds.h"
     293  #include "xlat/madvise_hppa_generic_cmds.h"
     294  
     295  #if defined HPPA
     296  # include "xlat/madvise_hppa_old_cmds.h"
     297  #endif
     298  
     299  SYS_FUNC(madvise)
     300  {
     301  	/* addr */
     302  	printaddr(tcp->u_arg[0]);
     303  	tprint_arg_next();
     304  
     305  	/* length */
     306  	PRINT_VAL_U(tcp->u_arg[1]);
     307  	tprint_arg_next();
     308  
     309  	/* advice */
     310  	const unsigned int advice = tcp->u_arg[2];
     311  #if defined HPPA
     312  	/*
     313  	 * hppa decided to be very special:  it used to have its own
     314  	 * definitions for some MADV_* constants (just like Alpha,
     315  	 * for example), but then (see Linux commit v6.2-rc1~39^2~7)
     316  	 * decided to change their values, so their symbolic names
     317  	 * are meaningless for the user now (which would also probably
     318  	 * add spice to debugging old binaries with the newer kernels
     319  	 * "in year 2025 (or later)"), and that forces us to state
     320  	 * explicitly which variant of the constant value is used.
     321  	 */
     322  	const char *old_cmd = xlookup(madvise_hppa_old_cmds, advice);
     323  
     324  	if (old_cmd) {
     325  		PRINT_VAL_X(advice);
     326  		if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
     327  			tprintf_comment("old %s", old_cmd);
     328  	} else {
     329  		const char *new_cmd = xlookup(madvise_hppa_generic_cmds,
     330  					      advice);
     331  
     332  		if (new_cmd) {
     333  			PRINT_VAL_X(advice);
     334  			if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
     335  				tprintf_comment("generic %s", new_cmd);
     336  		} else {
     337  			printxval(madvise_cmds, advice, "MADV_???");
     338  		}
     339  	}
     340  #else
     341  	printxvals(advice, "MADV_???",
     342  		   madvise_cmds, madvise_hppa_generic_cmds, NULL);
     343  #endif
     344  
     345  	return RVAL_DECODED;
     346  }
     347  
     348  SYS_FUNC(process_madvise)
     349  {
     350  	const int pidfd = tcp->u_arg[0];
     351  	const kernel_ulong_t addr = tcp->u_arg[1];
     352  	const kernel_ulong_t len = tcp->u_arg[2];
     353  	const unsigned int advice = tcp->u_arg[3];
     354  	const unsigned int flags = tcp->u_arg[4];
     355  
     356  	printfd(tcp, pidfd);
     357  	tprint_arg_next();
     358  
     359  	tprint_iov(tcp, len, addr, iov_decode_addr);
     360  	tprint_arg_next();
     361  
     362  	PRINT_VAL_U(len);
     363  	tprint_arg_next();
     364  
     365  	printxval(madvise_cmds, advice, "MADV_???");
     366  	tprint_arg_next();
     367  
     368  	PRINT_VAL_X(flags);
     369  
     370  	return RVAL_DECODED;
     371  }
     372  
     373  SYS_FUNC(process_mrelease)
     374  {
     375  	const int pidfd = tcp->u_arg[0];
     376  	const unsigned int flags = tcp->u_arg[1];
     377  
     378  	printfd(tcp, pidfd);
     379  	tprint_arg_next();
     380  
     381  	PRINT_VAL_X(flags);
     382  
     383  	return RVAL_DECODED;
     384  }
     385  
     386  #include "xlat/mlockall_flags.h"
     387  
     388  SYS_FUNC(mlockall)
     389  {
     390  	printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
     391  
     392  	return RVAL_DECODED;
     393  }
     394  
     395  #include "xlat/mctl_sync.h"
     396  
     397  SYS_FUNC(msync)
     398  {
     399  	/* addr */
     400  	printaddr(tcp->u_arg[0]);
     401  	tprint_arg_next();
     402  
     403  	/* length */
     404  	PRINT_VAL_U(tcp->u_arg[1]);
     405  	tprint_arg_next();
     406  
     407  	/* flags */
     408  	printflags(mctl_sync, tcp->u_arg[2], "MS_???");
     409  
     410  	return RVAL_DECODED;
     411  }
     412  
     413  #include "xlat/mlock_flags.h"
     414  
     415  SYS_FUNC(mlock2)
     416  {
     417  	/* addr */
     418  	printaddr(tcp->u_arg[0]);
     419  	tprint_arg_next();
     420  
     421  	/* length */
     422  	PRINT_VAL_U(tcp->u_arg[1]);
     423  	tprint_arg_next();
     424  
     425  	/* flags */
     426  	printflags(mlock_flags, tcp->u_arg[2], "MLOCK_???");
     427  
     428  	return RVAL_DECODED;
     429  }
     430  
     431  static bool
     432  print_mincore_entry(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     433  {
     434  	uint8_t val = (*(uint8_t *) elem_buf) & 1;
     435  	PRINT_VAL_U(val);
     436  
     437  	return true;
     438  }
     439  
     440  SYS_FUNC(mincore)
     441  {
     442  	if (entering(tcp)) {
     443  		/* addr */
     444  		printaddr(tcp->u_arg[0]);
     445  		tprint_arg_next();
     446  
     447  		/* length */
     448  		PRINT_VAL_U(tcp->u_arg[1]);
     449  		tprint_arg_next();
     450  	} else {
     451  		/* vec */
     452  		const unsigned long page_size = get_pagesize();
     453  		const unsigned long page_mask = page_size - 1;
     454  		const kernel_ulong_t len = tcp->u_arg[1];
     455  		const kernel_ulong_t nmemb =
     456  			len / page_size + ((len & page_mask) ? 1 : 0);
     457  		const kernel_ulong_t vec = tcp->u_arg[2];
     458  		uint8_t entry;
     459  		print_array(tcp, vec, nmemb, &entry, sizeof(entry),
     460  			    tfetch_mem, print_mincore_entry, 0);
     461  	}
     462  	return 0;
     463  }
     464  
     465  SYS_FUNC(remap_file_pages)
     466  {
     467  	const kernel_ulong_t addr = tcp->u_arg[0];
     468  	const kernel_ulong_t size = tcp->u_arg[1];
     469  	const kernel_ulong_t prot = tcp->u_arg[2];
     470  	const kernel_ulong_t pgoff = tcp->u_arg[3];
     471  	const kernel_ulong_t flags = tcp->u_arg[4];
     472  
     473  	/* addr */
     474  	printaddr(addr);
     475  	tprint_arg_next();
     476  
     477  	/* size */
     478  	PRINT_VAL_U(size);
     479  	tprint_arg_next();
     480  
     481  	/* prot */
     482  	printflags64(mmap_prot, prot, "PROT_???");
     483  	tprint_arg_next();
     484  
     485  	/* pgoff */
     486  	PRINT_VAL_U(pgoff);
     487  	tprint_arg_next();
     488  
     489  	/* flags */
     490  	print_mmap_flags(flags);
     491  
     492  	return RVAL_DECODED;
     493  }
     494  
     495  #if defined(POWERPC)
     496  static bool
     497  print_protmap_entry(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     498  {
     499  	PRINT_VAL_X(*(unsigned int *) elem_buf);
     500  
     501  	return true;
     502  }
     503  
     504  SYS_FUNC(subpage_prot)
     505  {
     506  	kernel_ulong_t addr = tcp->u_arg[0];
     507  	kernel_ulong_t len = tcp->u_arg[1];
     508  	kernel_ulong_t nmemb = len >> 16;
     509  	kernel_ulong_t map = tcp->u_arg[2];
     510  
     511  	/* addr */
     512  	printaddr(addr);
     513  	tprint_arg_next();
     514  
     515  	/* length */
     516  	PRINT_VAL_U(len);
     517  	tprint_arg_next();
     518  
     519  	/* map */
     520  	unsigned int entry;
     521  	print_array(tcp, map, nmemb, &entry, sizeof(entry),
     522  		    tfetch_mem, print_protmap_entry, 0);
     523  
     524  	return RVAL_DECODED;
     525  }
     526  #endif