]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/mmap.c
xfs: convert to new timestamp accessors
[thirdparty/xfsprogs-dev.git] / io / mmap.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2004-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7 #include "command.h"
8 #include "input.h"
9 #include <sys/mman.h>
10 #include <signal.h>
11 #include "init.h"
12 #include "io.h"
13
14 static cmdinfo_t mmap_cmd;
15 static cmdinfo_t mread_cmd;
16 static cmdinfo_t msync_cmd;
17 static cmdinfo_t munmap_cmd;
18 static cmdinfo_t mwrite_cmd;
19 #ifdef HAVE_MREMAP
20 static cmdinfo_t mremap_cmd;
21 #endif /* HAVE_MREMAP */
22
23 mmap_region_t *maptable;
24 int mapcount;
25 mmap_region_t *mapping;
26
27 static void
28 print_mapping(
29 mmap_region_t *map,
30 int index,
31 int braces)
32 {
33 char buffer[8] = { 0 };
34 int i;
35
36 static struct {
37 int prot;
38 int mode;
39 } *p, pflags[] = {
40 { PROT_READ, 'r' },
41 { PROT_WRITE, 'w' },
42 { PROT_EXEC, 'x' },
43 { PROT_NONE, 0 }
44 };
45
46 for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
47 buffer[i] = (map->prot & p->prot) ? p->mode : '-';
48
49 #ifdef HAVE_MAP_SYNC
50 if ((map->flags & (MAP_SYNC | MAP_SHARED_VALIDATE)) ==
51 (MAP_SYNC | MAP_SHARED_VALIDATE))
52 sprintf(&buffer[i], " S");
53 #endif
54
55 printf("%c%03d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n",
56 braces? '[' : ' ', index, braces? ']' : ' ',
57 (unsigned long)map->addr,
58 (unsigned long)((char *)map->addr + map->length),
59 buffer, map->name ? map->name : "???",
60 (long long)map->offset, (long)map->length);
61 }
62
63 void *
64 check_mapping_range(
65 mmap_region_t *map,
66 off64_t offset,
67 size_t length,
68 int pagealign)
69 {
70 off64_t relative;
71
72 if (offset < mapping->offset) {
73 printf(_("offset (%lld) is before start of mapping (%lld)\n"),
74 (long long)offset, (long long)mapping->offset);
75 return NULL;
76 }
77 relative = offset - mapping->offset;
78 if (relative > mapping->length) {
79 printf(_("offset (%lld) is beyond end of mapping (%lld)\n"),
80 (long long)relative, (long long)mapping->offset);
81 return NULL;
82 }
83 if ((relative + length) > (mapping->offset + mapping->length)) {
84 printf(_("range (%lld:%lld) is beyond mapping (%lld:%ld)\n"),
85 (long long)offset, (long long)relative,
86 (long long)mapping->offset, (long)mapping->length);
87 return NULL;
88 }
89 if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) {
90 printf(_("offset address (%p) is not page aligned\n"),
91 (char *)mapping->addr + relative);
92 return NULL;
93 }
94
95 return (char *)mapping->addr + relative;
96 }
97
98 int
99 maplist_f(void)
100 {
101 int i;
102
103 for (i = 0; i < mapcount; i++)
104 print_mapping(&maptable[i], i, &maptable[i] == mapping);
105 return 0;
106 }
107
108 static int
109 mapset_f(
110 int argc,
111 char **argv)
112 {
113 int i;
114
115 ASSERT(argc == 2);
116 i = atoi(argv[1]);
117 if (i < 0 || i >= mapcount) {
118 printf("value %d is out of range (0-%d)\n", i, mapcount);
119 exitcode = 1;
120 } else {
121 mapping = &maptable[i];
122 maplist_f();
123 }
124 return 0;
125 }
126
127 static void
128 mmap_help(void)
129 {
130 printf(_(
131 "\n"
132 " maps a range within the current file into memory\n"
133 "\n"
134 " Example:\n"
135 " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n"
136 "\n"
137 " Memory maps a range of a file for subsequent use by other xfs_io commands.\n"
138 " With no arguments, mmap shows the current mappings. The current mapping\n"
139 " can be set by using the single argument form (mapping number or address).\n"
140 " If two arguments are specified (a range), a new mapping is created and the\n"
141 " following options are available:\n"
142 " -r -- map with PROT_READ protection\n"
143 " -w -- map with PROT_WRITE protection\n"
144 " -x -- map with PROT_EXEC protection\n"
145 #ifdef HAVE_MAP_SYNC
146 " -S -- map with MAP_SYNC and MAP_SHARED_VALIDATE flags\n"
147 #endif
148 " -s <size> -- first do mmap(size)/munmap(size), try to reserve some free space\n"
149 " If no protection mode is specified, all are used by default.\n"
150 "\n"));
151 }
152
153 static int
154 mmap_f(
155 int argc,
156 char **argv)
157 {
158 off64_t offset;
159 ssize_t length = 0, length2 = 0;
160 void *address = NULL;
161 char *filename;
162 size_t blocksize, sectsize;
163 int c, prot = 0, flags = MAP_SHARED;
164
165 if (argc == 1) {
166 if (mapping)
167 return maplist_f();
168 fprintf(stderr, file ?
169 _("no mapped regions, try 'help mmap'\n") :
170 _("no files are open, try 'help open'\n"));
171 exitcode = 1;
172 return 0;
173 } else if (argc == 2) {
174 if (mapping)
175 return mapset_f(argc, argv);
176 fprintf(stderr, file ?
177 _("no mapped regions, try 'help mmap'\n") :
178 _("no files are open, try 'help open'\n"));
179 exitcode = 1;
180 return 0;
181 } else if (!file) {
182 fprintf(stderr, _("no files are open, try 'help open'\n"));
183 exitcode = 1;
184 return 0;
185 }
186
187 init_cvtnum(&blocksize, &sectsize);
188
189 while ((c = getopt(argc, argv, "rwxSs:")) != EOF) {
190 switch (c) {
191 case 'r':
192 prot |= PROT_READ;
193 break;
194 case 'w':
195 prot |= PROT_WRITE;
196 break;
197 case 'x':
198 prot |= PROT_EXEC;
199 break;
200 case 'S':
201 #ifdef HAVE_MAP_SYNC
202 flags = MAP_SYNC | MAP_SHARED_VALIDATE;
203 break;
204 #else
205 printf("MAP_SYNC not supported\n");
206 exitcode = 1;
207 return command_usage(&mmap_cmd);
208 #endif
209 case 's':
210 length2 = cvtnum(blocksize, sectsize, optarg);
211 break;
212 default:
213 exitcode = 1;
214 return command_usage(&mmap_cmd);
215 }
216 }
217 if (!prot)
218 prot = PROT_READ | PROT_WRITE | PROT_EXEC;
219
220 if (optind != argc - 2) {
221 exitcode = 1;
222 return command_usage(&mmap_cmd);
223 }
224
225 offset = cvtnum(blocksize, sectsize, argv[optind]);
226 if (offset < 0) {
227 printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
228 exitcode = 1;
229 return 0;
230 }
231 optind++;
232 length = cvtnum(blocksize, sectsize, argv[optind]);
233 if (length < 0) {
234 printf(_("non-numeric length argument -- %s\n"), argv[optind]);
235 exitcode = 1;
236 return 0;
237 }
238
239 filename = strdup(file->name);
240 if (!filename) {
241 perror("strdup");
242 exitcode = 1;
243 return 0;
244 }
245
246 /*
247 * mmap and munmap memory area of length2 region is helpful to
248 * make a region of extendible free memory. It's generally used
249 * for later mremap operation(no MREMAP_MAYMOVE flag). But there
250 * isn't guarantee that the memory after length (up to length2)
251 * will stay free.
252 */
253 if (length2 > length) {
254 address = mmap(NULL, length2, prot,
255 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
256 munmap(address, length2);
257 }
258 address = mmap(address, length, prot, flags, file->fd, offset);
259 if (address == MAP_FAILED) {
260 perror("mmap");
261 free(filename);
262 exitcode = 1;
263 return 0;
264 }
265
266 /* Extend the control array of mmap'd regions */
267 maptable = (mmap_region_t *)realloc(maptable, /* growing */
268 ++mapcount * sizeof(mmap_region_t));
269 if (!maptable) {
270 perror("realloc");
271 mapcount = 0;
272 munmap(address, length);
273 free(filename);
274 exitcode = 1;
275 return 0;
276 }
277
278 /* Finally, make this the new active mapping */
279 mapping = &maptable[mapcount - 1];
280 mapping->addr = address;
281 mapping->length = length;
282 mapping->offset = offset;
283 mapping->name = filename;
284 mapping->prot = prot;
285 mapping->flags = flags;
286 return 0;
287 }
288
289 static void
290 msync_help(void)
291 {
292 printf(_(
293 "\n"
294 " flushes a range of bytes in the current memory mapping\n"
295 "\n"
296 " Writes all modified copies of pages over the specified range (or entire\n"
297 " mapping if no range specified) to their backing storage locations. Also,\n"
298 " optionally invalidates so that subsequent references to the pages will be\n"
299 " obtained from their backing storage locations (instead of cached copies).\n"
300 " -a -- perform asynchronous writes (MS_ASYNC)\n"
301 " -i -- invalidate mapped pages (MS_INVALIDATE)\n"
302 " -s -- perform synchronous writes (MS_SYNC)\n"
303 "\n"));
304 }
305
306 static int
307 msync_f(
308 int argc,
309 char **argv)
310 {
311 off64_t offset;
312 ssize_t length;
313 void *start;
314 int c, flags = 0;
315 size_t blocksize, sectsize;
316
317 while ((c = getopt(argc, argv, "ais")) != EOF) {
318 switch (c) {
319 case 'a':
320 flags |= MS_ASYNC;
321 break;
322 case 'i':
323 flags |= MS_INVALIDATE;
324 break;
325 case 's':
326 flags |= MS_SYNC;
327 break;
328 default:
329 exitcode = 1;
330 return command_usage(&msync_cmd);
331 }
332 }
333
334 if (optind == argc) {
335 offset = mapping->offset;
336 length = mapping->length;
337 } else if (optind == argc - 2) {
338 init_cvtnum(&blocksize, &sectsize);
339 offset = cvtnum(blocksize, sectsize, argv[optind]);
340 if (offset < 0) {
341 printf(_("non-numeric offset argument -- %s\n"),
342 argv[optind]);
343 exitcode = 1;
344 return 0;
345 }
346 optind++;
347 length = cvtnum(blocksize, sectsize, argv[optind]);
348 if (length < 0) {
349 printf(_("non-numeric length argument -- %s\n"),
350 argv[optind]);
351 exitcode = 1;
352 return 0;
353 }
354 } else {
355 exitcode = 1;
356 return command_usage(&msync_cmd);
357 }
358
359 start = check_mapping_range(mapping, offset, length, 1);
360 if (!start) {
361 exitcode = 1;
362 return 0;
363 }
364
365 if (msync(start, length, flags) < 0) {
366 perror("msync");
367 exitcode = 1;
368 return 0;
369 }
370
371 return 0;
372 }
373
374 static void
375 mread_help(void)
376 {
377 printf(_(
378 "\n"
379 " reads a range of bytes in the current memory mapping\n"
380 "\n"
381 " Example:\n"
382 " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n"
383 "\n"
384 " Accesses a range of the current memory mapping, optionally dumping it to\n"
385 " the standard output stream (with -v option) for subsequent inspection.\n"
386 " -f -- verbose mode, dump bytes with offsets relative to start of file.\n"
387 " -r -- reverse order; start accessing from the end of range, moving backward\n"
388 " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n"
389 " The accesses are performed sequentially from the start offset by default.\n"
390 " Notes:\n"
391 " References to whole pages following the end of the backing file results\n"
392 " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n"
393 " on various filesystem conditions, including quota exceeded errors, and\n"
394 " for physical device errors (such as unreadable disk blocks). No attempt\n"
395 " has been made to catch signals at this stage...\n"
396 "\n"));
397 }
398
399 static int
400 mread_f(
401 int argc,
402 char **argv)
403 {
404 off64_t offset, tmp, dumpoffset, printoffset;
405 ssize_t length;
406 size_t dumplen, cnt = 0;
407 char *bp;
408 void *start;
409 int dump = 0, rflag = 0, c;
410 size_t blocksize, sectsize;
411
412 while ((c = getopt(argc, argv, "frv")) != EOF) {
413 switch (c) {
414 case 'f':
415 dump = 2; /* file offset dump */
416 break;
417 case 'r':
418 rflag = 1; /* read in reverse */
419 break;
420 case 'v':
421 dump = 1; /* mapping offset dump */
422 break;
423 default:
424 exitcode = 1;
425 return command_usage(&mread_cmd);
426 }
427 }
428
429 if (optind == argc) {
430 offset = mapping->offset;
431 length = mapping->length;
432 } else if (optind == argc - 2) {
433 init_cvtnum(&blocksize, &sectsize);
434 offset = cvtnum(blocksize, sectsize, argv[optind]);
435 if (offset < 0) {
436 printf(_("non-numeric offset argument -- %s\n"),
437 argv[optind]);
438 exitcode = 1;
439 return 0;
440 }
441 optind++;
442 length = cvtnum(blocksize, sectsize, argv[optind]);
443 if (length < 0) {
444 printf(_("non-numeric length argument -- %s\n"),
445 argv[optind]);
446 exitcode = 1;
447 return 0;
448 }
449 } else {
450 return command_usage(&mread_cmd);
451 }
452
453 start = check_mapping_range(mapping, offset, length, 0);
454 if (!start) {
455 exitcode = 1;
456 return 0;
457 }
458 dumpoffset = offset - mapping->offset;
459 if (dump == 2)
460 printoffset = offset;
461 else
462 printoffset = dumpoffset;
463
464 if (alloc_buffer(pagesize, 0, 0) < 0) {
465 exitcode = 1;
466 return 0;
467 }
468 bp = (char *)io_buffer;
469
470 dumplen = length % pagesize;
471 if (!dumplen)
472 dumplen = pagesize;
473
474 if (rflag) {
475 for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) {
476 *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
477 cnt++;
478 if (c && cnt == dumplen) {
479 if (dump) {
480 dump_buffer(printoffset, dumplen);
481 printoffset += dumplen;
482 }
483 bp = (char *)io_buffer;
484 dumplen = pagesize;
485 cnt = 0;
486 } else {
487 bp++;
488 }
489 }
490 } else {
491 for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) {
492 *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
493 cnt++;
494 if (c && cnt == dumplen) {
495 if (dump)
496 dump_buffer(printoffset + tmp -
497 (dumplen - 1), dumplen);
498 bp = (char *)io_buffer;
499 dumplen = pagesize;
500 cnt = 0;
501 } else {
502 bp++;
503 }
504 }
505 }
506 return 0;
507 }
508
509 static int
510 munmap_f(
511 int argc,
512 char **argv)
513 {
514 ssize_t length;
515 unsigned int offset;
516
517 if (munmap(mapping->addr, mapping->length) < 0) {
518 perror("munmap");
519 exitcode = 1;
520 return 0;
521 }
522 free(mapping->name);
523
524 /* Shuffle the mapping table entries down over the removed entry */
525 offset = mapping - &maptable[0];
526 length = mapcount * sizeof(mmap_region_t);
527 length -= (offset + 1) * sizeof(mmap_region_t);
528 if (length)
529 memmove(mapping, mapping + 1, length);
530
531 /* Resize the memory allocated for the table, possibly freeing */
532 if (--mapcount) {
533 maptable = (mmap_region_t *)realloc(maptable, /* shrinking */
534 mapcount * sizeof(mmap_region_t));
535 if (offset == mapcount)
536 offset--;
537 mapping = maptable + offset;
538 } else {
539 free(maptable);
540 mapping = maptable = NULL;
541 }
542 maplist_f();
543 return 0;
544 }
545
546 static void
547 mwrite_help(void)
548 {
549 printf(_(
550 "\n"
551 " dirties a range of bytes in the current memory mapping\n"
552 "\n"
553 " Example:\n"
554 " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n"
555 "\n"
556 " Stores a byte into memory for a range within a mapping.\n"
557 " The default stored value is 'X', repeated to fill the range specified.\n"
558 " -S -- use an alternate seed character\n"
559 " -r -- reverse order; start storing from the end of range, moving backward\n"
560 " The stores are performed sequentially from the start offset by default.\n"
561 "\n"));
562 }
563
564 static int
565 mwrite_f(
566 int argc,
567 char **argv)
568 {
569 off64_t offset, tmp;
570 ssize_t length;
571 void *start;
572 char *sp;
573 int seed = 'X';
574 int rflag = 0;
575 int c;
576 size_t blocksize, sectsize;
577
578 while ((c = getopt(argc, argv, "rS:")) != EOF) {
579 switch (c) {
580 case 'r':
581 rflag = 1;
582 break;
583 case 'S':
584 seed = (int)strtol(optarg, &sp, 0);
585 if (!sp || sp == optarg) {
586 printf(_("non-numeric seed -- %s\n"), optarg);
587 return 0;
588 }
589 break;
590 default:
591 exitcode = 1;
592 return command_usage(&mwrite_cmd);
593 }
594 }
595
596 if (optind == argc) {
597 offset = mapping->offset;
598 length = mapping->length;
599 } else if (optind == argc - 2) {
600 init_cvtnum(&blocksize, &sectsize);
601 offset = cvtnum(blocksize, sectsize, argv[optind]);
602 if (offset < 0) {
603 printf(_("non-numeric offset argument -- %s\n"),
604 argv[optind]);
605 exitcode = 1;
606 return 0;
607 }
608 optind++;
609 length = cvtnum(blocksize, sectsize, argv[optind]);
610 if (length < 0) {
611 printf(_("non-numeric length argument -- %s\n"),
612 argv[optind]);
613 exitcode = 1;
614 return 0;
615 }
616 } else {
617 exitcode = 1;
618 return command_usage(&mwrite_cmd);
619 }
620
621 start = check_mapping_range(mapping, offset, length, 0);
622 if (!start) {
623 exitcode = 1;
624 return 0;
625 }
626
627 offset -= mapping->offset;
628 if (rflag) {
629 for (tmp = offset + length -1; tmp >= offset; tmp--)
630 ((char *)mapping->addr)[tmp] = seed;
631 } else {
632 for (tmp = offset; tmp < offset + length; tmp++)
633 ((char *)mapping->addr)[tmp] = seed;
634 }
635
636 return 0;
637 }
638
639 #ifdef HAVE_MREMAP
640 static void
641 mremap_help(void)
642 {
643 printf(_(
644 "\n"
645 " resizes the current memory mapping\n"
646 "\n"
647 " Examples:\n"
648 " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n"
649 "\n"
650 " Resizes the mapping, growing or shrinking from the current size.\n"
651 " The default stored value is 'X', repeated to fill the range specified.\n"
652 " -f <new_address> -- use MREMAP_FIXED flag to mremap on new_address\n"
653 " -m -- use the MREMAP_MAYMOVE flag\n"
654 "\n"));
655 }
656
657 static int
658 mremap_f(
659 int argc,
660 char **argv)
661 {
662 ssize_t new_length;
663 void *new_addr = NULL;
664 int flags = 0;
665 int c;
666 size_t blocksize, sectsize;
667
668 init_cvtnum(&blocksize, &sectsize);
669
670 while ((c = getopt(argc, argv, "f:m")) != EOF) {
671 switch (c) {
672 case 'f':
673 flags = MREMAP_FIXED|MREMAP_MAYMOVE;
674 new_addr = (void *)(unsigned long)cvtnum(blocksize,
675 sectsize, optarg);
676 break;
677 case 'm':
678 flags = MREMAP_MAYMOVE;
679 break;
680 default:
681 exitcode = 1;
682 return command_usage(&mremap_cmd);
683 }
684 }
685
686 if (optind != argc - 1) {
687 exitcode = 1;
688 return command_usage(&mremap_cmd);
689 }
690
691 new_length = cvtnum(blocksize, sectsize, argv[optind]);
692 if (new_length < 0) {
693 printf(_("non-numeric offset argument -- %s\n"),
694 argv[optind]);
695 exitcode = 1;
696 return 0;
697 }
698
699 if (!new_addr)
700 new_addr = mremap(mapping->addr, mapping->length,
701 new_length, flags);
702 else
703 new_addr = mremap(mapping->addr, mapping->length,
704 new_length, flags, new_addr);
705 if (new_addr == MAP_FAILED) {
706 perror("mremap");
707 exitcode = 1;
708 return 0;
709 }
710
711 mapping->addr = new_addr;
712 mapping->length = new_length;
713 return 0;
714 }
715 #endif /* HAVE_MREMAP */
716
717 void
718 mmap_init(void)
719 {
720 mmap_cmd.name = "mmap";
721 mmap_cmd.altname = "mm";
722 mmap_cmd.cfunc = mmap_f;
723 mmap_cmd.argmin = 0;
724 mmap_cmd.argmax = -1;
725 mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK |
726 CMD_FOREIGN_OK | CMD_FLAG_ONESHOT;
727 mmap_cmd.args = _("[N] | [-rwxS] [-s size] [off len]");
728 mmap_cmd.oneline =
729 _("mmap a range in the current file, show mappings");
730 mmap_cmd.help = mmap_help;
731
732 mread_cmd.name = "mread";
733 mread_cmd.altname = "mr";
734 mread_cmd.cfunc = mread_f;
735 mread_cmd.argmin = 0;
736 mread_cmd.argmax = -1;
737 mread_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
738 mread_cmd.args = _("[-r] [off len]");
739 mread_cmd.oneline =
740 _("reads data from a region in the current memory mapping");
741 mread_cmd.help = mread_help;
742
743 msync_cmd.name = "msync";
744 msync_cmd.altname = "ms";
745 msync_cmd.cfunc = msync_f;
746 msync_cmd.argmin = 0;
747 msync_cmd.argmax = -1;
748 msync_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
749 msync_cmd.args = _("[-ais] [off len]");
750 msync_cmd.oneline = _("flush a region in the current memory mapping");
751 msync_cmd.help = msync_help;
752
753 munmap_cmd.name = "munmap";
754 munmap_cmd.altname = "mu";
755 munmap_cmd.cfunc = munmap_f;
756 munmap_cmd.argmin = 0;
757 munmap_cmd.argmax = 0;
758 munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
759 munmap_cmd.oneline = _("unmaps the current memory mapping");
760
761 mwrite_cmd.name = "mwrite";
762 mwrite_cmd.altname = "mw";
763 mwrite_cmd.cfunc = mwrite_f;
764 mwrite_cmd.argmin = 0;
765 mwrite_cmd.argmax = -1;
766 mwrite_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
767 mwrite_cmd.args = _("[-r] [-S seed] [off len]");
768 mwrite_cmd.oneline =
769 _("writes data into a region in the current memory mapping");
770 mwrite_cmd.help = mwrite_help;
771
772 #ifdef HAVE_MREMAP
773 mremap_cmd.name = "mremap";
774 mremap_cmd.altname = "mrm";
775 mremap_cmd.cfunc = mremap_f;
776 mremap_cmd.argmin = 1;
777 mremap_cmd.argmax = 3;
778 mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
779 mremap_cmd.args = _("[-m|-f <new_address>] newsize");
780 mremap_cmd.oneline =
781 _("alters the size of the current memory mapping");
782 mremap_cmd.help = mremap_help;
783 #endif /* HAVE_MREMAP */
784
785 add_command(&mmap_cmd);
786 add_command(&mread_cmd);
787 add_command(&msync_cmd);
788 add_command(&munmap_cmd);
789 add_command(&mwrite_cmd);
790 #ifdef HAVE_MREMAP
791 add_command(&mremap_cmd);
792 #endif /* HAVE_MREMAP */
793 }