Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mem.c 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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-2018 The strace developers.
  9. * All rights reserved.
  10. *
  11. * SPDX-License-Identifier: LGPL-2.1-or-later
  12. */
  13. #include "defs.h"
  14. #include <linux/mman.h>
  15. #include <sys/mman.h>
  16. unsigned long
  17. get_pagesize(void)
  18. {
  19. static unsigned long pagesize;
  20. if (!pagesize) {
  21. long ret = sysconf(_SC_PAGESIZE);
  22. if (ret < 0)
  23. perror_func_msg_and_die("sysconf(_SC_PAGESIZE)");
  24. if (ret == 0)
  25. error_func_msg_and_die("sysconf(_SC_PAGESIZE) "
  26. "returned 0");
  27. pagesize = (unsigned long) ret;
  28. }
  29. return pagesize;
  30. }
  31. SYS_FUNC(brk)
  32. {
  33. printaddr(tcp->u_arg[0]);
  34. return RVAL_DECODED | RVAL_HEX;
  35. }
  36. #include "xlat/mmap_prot.h"
  37. #include "xlat/mmap_flags.h"
  38. #ifndef MAP_HUGE_SHIFT
  39. # define MAP_HUGE_SHIFT 26
  40. #endif
  41. #ifndef MAP_HUGE_MASK
  42. # define MAP_HUGE_MASK 0x3f
  43. #endif
  44. static void
  45. print_mmap_flags(kernel_ulong_t flags)
  46. {
  47. if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
  48. tprintf("%#" PRI_klx, flags);
  49. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
  50. return;
  51. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  52. tprints(" /* ");
  53. printxvals_ex(flags & MAP_TYPE, "MAP_???", XLAT_STYLE_ABBREV,
  54. mmap_flags, NULL);
  55. flags &= ~MAP_TYPE;
  56. const unsigned int mask = MAP_HUGE_MASK << MAP_HUGE_SHIFT;
  57. const unsigned int hugetlb_value = flags & mask;
  58. flags &= ~mask;
  59. if (flags) {
  60. tprints("|");
  61. printflags_ex(flags, NULL, XLAT_STYLE_ABBREV,
  62. mmap_flags, NULL);
  63. }
  64. if (hugetlb_value)
  65. tprintf("|%u<<MAP_HUGE_SHIFT",
  66. hugetlb_value >> MAP_HUGE_SHIFT);
  67. if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
  68. tprints(" */");
  69. }
  70. static void
  71. print_mmap(struct tcb *tcp, kernel_ulong_t *u_arg, unsigned long long offset)
  72. {
  73. const kernel_ulong_t addr = u_arg[0];
  74. const kernel_ulong_t len = u_arg[1];
  75. const kernel_ulong_t prot = u_arg[2];
  76. const kernel_ulong_t flags = u_arg[3];
  77. const int fd = u_arg[4];
  78. printaddr(addr);
  79. tprintf(", %" PRI_klu ", ", len);
  80. printflags64(mmap_prot, prot, "PROT_???");
  81. tprints(", ");
  82. print_mmap_flags(flags);
  83. tprints(", ");
  84. printfd(tcp, fd);
  85. tprintf(", %#llx", offset);
  86. }
  87. /* Syscall name<->function correspondence is messed up on many arches.
  88. * For example:
  89. * i386 has __NR_mmap == 90, and it is "old mmap", and
  90. * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets".
  91. * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets".
  92. * Confused? Me too!
  93. */
  94. #if HAVE_ARCH_OLD_MMAP
  95. /* Params are pointed to by u_arg[0], offset is in bytes */
  96. SYS_FUNC(old_mmap)
  97. {
  98. kernel_ulong_t *args =
  99. fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
  100. if (args)
  101. print_mmap(tcp, args, args[5]);
  102. else
  103. printaddr(tcp->u_arg[0]);
  104. return RVAL_DECODED | RVAL_HEX;
  105. }
  106. # if HAVE_ARCH_OLD_MMAP_PGOFF
  107. /* Params are pointed to by u_arg[0], offset is in pages */
  108. SYS_FUNC(old_mmap_pgoff)
  109. {
  110. kernel_ulong_t *args =
  111. fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
  112. if (args) {
  113. unsigned long long offset;
  114. offset = args[5];
  115. offset *= get_pagesize();
  116. print_mmap(tcp, args, offset);
  117. } else {
  118. printaddr(tcp->u_arg[0]);
  119. }
  120. return RVAL_DECODED | RVAL_HEX;
  121. }
  122. # endif /* HAVE_ARCH_OLD_MMAP_PGOFF */
  123. #endif /* HAVE_ARCH_OLD_MMAP */
  124. /* Params are passed directly, offset is in bytes */
  125. SYS_FUNC(mmap)
  126. {
  127. /* Example of kernel-side handling of this variety of mmap:
  128. * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls
  129. * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes,
  130. * since the above code converts off to pages.
  131. */
  132. print_mmap(tcp, tcp->u_arg, tcp->u_arg[5]);
  133. return RVAL_DECODED | RVAL_HEX;
  134. }
  135. /* Params are passed directly, offset is in pages */
  136. SYS_FUNC(mmap_pgoff)
  137. {
  138. /* Try test/mmap_offset_decode.c */
  139. unsigned long long offset;
  140. offset = tcp->u_arg[5];
  141. offset *= get_pagesize();
  142. print_mmap(tcp, tcp->u_arg, offset);
  143. return RVAL_DECODED | RVAL_HEX;
  144. }
  145. /* Params are passed directly, offset is in 4k units */
  146. SYS_FUNC(mmap_4koff)
  147. {
  148. unsigned long long offset;
  149. offset = tcp->u_arg[5];
  150. offset <<= 12;
  151. print_mmap(tcp, tcp->u_arg, offset);
  152. return RVAL_DECODED | RVAL_HEX;
  153. }
  154. SYS_FUNC(munmap)
  155. {
  156. printaddr(tcp->u_arg[0]);
  157. tprintf(", %" PRI_klu, tcp->u_arg[1]);
  158. return RVAL_DECODED;
  159. }
  160. static int
  161. do_mprotect(struct tcb *tcp, bool has_pkey)
  162. {
  163. printaddr(tcp->u_arg[0]);
  164. tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
  165. printflags64(mmap_prot, tcp->u_arg[2], "PROT_???");
  166. if (has_pkey)
  167. tprintf(", %d", (int) tcp->u_arg[3]);
  168. return RVAL_DECODED;
  169. }
  170. SYS_FUNC(mprotect)
  171. {
  172. return do_mprotect(tcp, false);
  173. }
  174. SYS_FUNC(pkey_mprotect)
  175. {
  176. return do_mprotect(tcp, true);
  177. }
  178. #include "xlat/mremap_flags.h"
  179. SYS_FUNC(mremap)
  180. {
  181. printaddr(tcp->u_arg[0]);
  182. tprintf(", %" PRI_klu ", %" PRI_klu ", ", tcp->u_arg[1], tcp->u_arg[2]);
  183. printflags64(mremap_flags, tcp->u_arg[3], "MREMAP_???");
  184. #ifdef MREMAP_FIXED
  185. if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) ==
  186. (MREMAP_MAYMOVE | MREMAP_FIXED)) {
  187. tprints(", ");
  188. printaddr(tcp->u_arg[4]);
  189. }
  190. #endif
  191. return RVAL_DECODED | RVAL_HEX;
  192. }
  193. #include "xlat/madvise_cmds.h"
  194. SYS_FUNC(madvise)
  195. {
  196. printaddr(tcp->u_arg[0]);
  197. tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
  198. printxval(madvise_cmds, tcp->u_arg[2], "MADV_???");
  199. return RVAL_DECODED;
  200. }
  201. #include "xlat/mlockall_flags.h"
  202. SYS_FUNC(mlockall)
  203. {
  204. printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
  205. return RVAL_DECODED;
  206. }
  207. #include "xlat/mctl_sync.h"
  208. SYS_FUNC(msync)
  209. {
  210. /* addr */
  211. printaddr(tcp->u_arg[0]);
  212. /* len */
  213. tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
  214. /* flags */
  215. printflags(mctl_sync, tcp->u_arg[2], "MS_???");
  216. return RVAL_DECODED;
  217. }
  218. #include "xlat/mlock_flags.h"
  219. SYS_FUNC(mlock2)
  220. {
  221. printaddr(tcp->u_arg[0]);
  222. tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
  223. printflags(mlock_flags, tcp->u_arg[2], "MLOCK_???");
  224. return RVAL_DECODED;
  225. }
  226. SYS_FUNC(mincore)
  227. {
  228. if (entering(tcp)) {
  229. printaddr(tcp->u_arg[0]);
  230. tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
  231. } else {
  232. const unsigned long page_size = get_pagesize();
  233. const unsigned long page_mask = page_size - 1;
  234. unsigned long len = tcp->u_arg[1];
  235. unsigned char *vec = NULL;
  236. len = len / page_size + (len & page_mask ? 1 : 0);
  237. if (syserror(tcp) || !verbose(tcp) ||
  238. !tcp->u_arg[2] || !(vec = malloc(len)) ||
  239. umoven(tcp, tcp->u_arg[2], len, vec) < 0)
  240. printaddr(tcp->u_arg[2]);
  241. else {
  242. unsigned long i;
  243. tprints("[");
  244. for (i = 0; i < len; i++) {
  245. if (i)
  246. tprints(", ");
  247. if (abbrev(tcp) && i >= max_strlen) {
  248. tprints("...");
  249. break;
  250. }
  251. tprints((vec[i] & 1) ? "1" : "0");
  252. }
  253. tprints("]");
  254. }
  255. free(vec);
  256. }
  257. return 0;
  258. }
  259. SYS_FUNC(remap_file_pages)
  260. {
  261. const kernel_ulong_t addr = tcp->u_arg[0];
  262. const kernel_ulong_t size = tcp->u_arg[1];
  263. const kernel_ulong_t prot = tcp->u_arg[2];
  264. const kernel_ulong_t pgoff = tcp->u_arg[3];
  265. const kernel_ulong_t flags = tcp->u_arg[4];
  266. printaddr(addr);
  267. tprintf(", %" PRI_klu ", ", size);
  268. printflags64(mmap_prot, prot, "PROT_???");
  269. tprintf(", %" PRI_klu ", ", pgoff);
  270. print_mmap_flags(flags);
  271. return RVAL_DECODED;
  272. }
  273. #if defined(POWERPC)
  274. static bool
  275. print_protmap_entry(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
  276. {
  277. tprintf("%#08x", *(unsigned int *) elem_buf);
  278. return true;
  279. }
  280. SYS_FUNC(subpage_prot)
  281. {
  282. kernel_ulong_t addr = tcp->u_arg[0];
  283. kernel_ulong_t len = tcp->u_arg[1];
  284. kernel_ulong_t nmemb = len >> 16;
  285. kernel_ulong_t map = tcp->u_arg[2];
  286. printaddr(addr);
  287. tprintf(", %" PRI_klu ", ", len);
  288. unsigned int entry;
  289. print_array(tcp, map, nmemb, &entry, sizeof(entry),
  290. tfetch_mem, print_protmap_entry, 0);
  291. return RVAL_DECODED;
  292. }
  293. #endif