| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2004-2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "command.h" |
| #include "input.h" |
| #include <sys/mman.h> |
| #include <signal.h> |
| #include "init.h" |
| #include "io.h" |
| |
| static cmdinfo_t mmap_cmd; |
| static cmdinfo_t mread_cmd; |
| static cmdinfo_t msync_cmd; |
| static cmdinfo_t munmap_cmd; |
| static cmdinfo_t mwrite_cmd; |
| #ifdef HAVE_MREMAP |
| static cmdinfo_t mremap_cmd; |
| #endif /* HAVE_MREMAP */ |
| |
| mmap_region_t *maptable; |
| int mapcount; |
| mmap_region_t *mapping; |
| |
| static void |
| print_mapping( |
| mmap_region_t *map, |
| int index, |
| int braces) |
| { |
| char buffer[8] = { 0 }; |
| int i; |
| |
| static struct { |
| int prot; |
| int mode; |
| } *p, pflags[] = { |
| { PROT_READ, 'r' }, |
| { PROT_WRITE, 'w' }, |
| { PROT_EXEC, 'x' }, |
| { PROT_NONE, 0 } |
| }; |
| |
| for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++) |
| buffer[i] = (map->prot & p->prot) ? p->mode : '-'; |
| |
| #ifdef HAVE_MAP_SYNC |
| if ((map->flags & (MAP_SYNC | MAP_SHARED_VALIDATE)) == |
| (MAP_SYNC | MAP_SHARED_VALIDATE)) |
| sprintf(&buffer[i], " S"); |
| #endif |
| |
| printf("%c%03d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n", |
| braces? '[' : ' ', index, braces? ']' : ' ', |
| (unsigned long)map->addr, |
| (unsigned long)((char *)map->addr + map->length), |
| buffer, map->name ? map->name : "???", |
| (long long)map->offset, (long)map->length); |
| } |
| |
| void * |
| check_mapping_range( |
| mmap_region_t *map, |
| off64_t offset, |
| size_t length, |
| int pagealign) |
| { |
| off64_t relative; |
| |
| if (offset < mapping->offset) { |
| printf(_("offset (%lld) is before start of mapping (%lld)\n"), |
| (long long)offset, (long long)mapping->offset); |
| return NULL; |
| } |
| relative = offset - mapping->offset; |
| if (relative > mapping->length) { |
| printf(_("offset (%lld) is beyond end of mapping (%lld)\n"), |
| (long long)relative, (long long)mapping->offset); |
| return NULL; |
| } |
| if ((relative + length) > (mapping->offset + mapping->length)) { |
| printf(_("range (%lld:%lld) is beyond mapping (%lld:%ld)\n"), |
| (long long)offset, (long long)relative, |
| (long long)mapping->offset, (long)mapping->length); |
| return NULL; |
| } |
| if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) { |
| printf(_("offset address (%p) is not page aligned\n"), |
| (char *)mapping->addr + relative); |
| return NULL; |
| } |
| |
| return (char *)mapping->addr + relative; |
| } |
| |
| int |
| maplist_f(void) |
| { |
| int i; |
| |
| for (i = 0; i < mapcount; i++) |
| print_mapping(&maptable[i], i, &maptable[i] == mapping); |
| return 0; |
| } |
| |
| static int |
| mapset_f( |
| int argc, |
| char **argv) |
| { |
| int i; |
| |
| ASSERT(argc == 2); |
| i = atoi(argv[1]); |
| if (i < 0 || i >= mapcount) { |
| printf("value %d is out of range (0-%d)\n", i, mapcount); |
| exitcode = 1; |
| } else { |
| mapping = &maptable[i]; |
| maplist_f(); |
| } |
| return 0; |
| } |
| |
| static void |
| mmap_help(void) |
| { |
| printf(_( |
| "\n" |
| " maps a range within the current file into memory\n" |
| "\n" |
| " Example:\n" |
| " 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n" |
| "\n" |
| " Memory maps a range of a file for subsequent use by other xfs_io commands.\n" |
| " With no arguments, mmap shows the current mappings. The current mapping\n" |
| " can be set by using the single argument form (mapping number or address).\n" |
| " If two arguments are specified (a range), a new mapping is created and the\n" |
| " following options are available:\n" |
| " -r -- map with PROT_READ protection\n" |
| " -w -- map with PROT_WRITE protection\n" |
| " -x -- map with PROT_EXEC protection\n" |
| #ifdef HAVE_MAP_SYNC |
| " -S -- map with MAP_SYNC and MAP_SHARED_VALIDATE flags\n" |
| #endif |
| " -s <size> -- first do mmap(size)/munmap(size), try to reserve some free space\n" |
| " If no protection mode is specified, all are used by default.\n" |
| "\n")); |
| } |
| |
| static int |
| mmap_f( |
| int argc, |
| char **argv) |
| { |
| off64_t offset; |
| ssize_t length = 0, length2 = 0; |
| void *address = NULL; |
| char *filename; |
| size_t blocksize, sectsize; |
| int c, prot = 0, flags = MAP_SHARED; |
| |
| if (argc == 1) { |
| if (mapping) |
| return maplist_f(); |
| fprintf(stderr, file ? |
| _("no mapped regions, try 'help mmap'\n") : |
| _("no files are open, try 'help open'\n")); |
| exitcode = 1; |
| return 0; |
| } else if (argc == 2) { |
| if (mapping) |
| return mapset_f(argc, argv); |
| fprintf(stderr, file ? |
| _("no mapped regions, try 'help mmap'\n") : |
| _("no files are open, try 'help open'\n")); |
| exitcode = 1; |
| return 0; |
| } else if (!file) { |
| fprintf(stderr, _("no files are open, try 'help open'\n")); |
| exitcode = 1; |
| return 0; |
| } |
| |
| init_cvtnum(&blocksize, §size); |
| |
| while ((c = getopt(argc, argv, "rwxSs:")) != EOF) { |
| switch (c) { |
| case 'r': |
| prot |= PROT_READ; |
| break; |
| case 'w': |
| prot |= PROT_WRITE; |
| break; |
| case 'x': |
| prot |= PROT_EXEC; |
| break; |
| case 'S': |
| #ifdef HAVE_MAP_SYNC |
| flags = MAP_SYNC | MAP_SHARED_VALIDATE; |
| break; |
| #else |
| printf("MAP_SYNC not supported\n"); |
| exitcode = 1; |
| return command_usage(&mmap_cmd); |
| #endif |
| case 's': |
| length2 = cvtnum(blocksize, sectsize, optarg); |
| break; |
| default: |
| exitcode = 1; |
| return command_usage(&mmap_cmd); |
| } |
| } |
| if (!prot) |
| prot = PROT_READ | PROT_WRITE | PROT_EXEC; |
| |
| if (optind != argc - 2) { |
| exitcode = 1; |
| return command_usage(&mmap_cmd); |
| } |
| |
| offset = cvtnum(blocksize, sectsize, argv[optind]); |
| if (offset < 0) { |
| printf(_("non-numeric offset argument -- %s\n"), argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| optind++; |
| length = cvtnum(blocksize, sectsize, argv[optind]); |
| if (length < 0) { |
| printf(_("non-numeric length argument -- %s\n"), argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| |
| filename = strdup(file->name); |
| if (!filename) { |
| perror("strdup"); |
| exitcode = 1; |
| return 0; |
| } |
| |
| /* |
| * mmap and munmap memory area of length2 region is helpful to |
| * make a region of extendible free memory. It's generally used |
| * for later mremap operation(no MREMAP_MAYMOVE flag). But there |
| * isn't guarantee that the memory after length (up to length2) |
| * will stay free. |
| */ |
| if (length2 > length) { |
| address = mmap(NULL, length2, prot, |
| MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| munmap(address, length2); |
| } |
| address = mmap(address, length, prot, flags, file->fd, offset); |
| if (address == MAP_FAILED) { |
| perror("mmap"); |
| free(filename); |
| exitcode = 1; |
| return 0; |
| } |
| |
| /* Extend the control array of mmap'd regions */ |
| maptable = (mmap_region_t *)realloc(maptable, /* growing */ |
| ++mapcount * sizeof(mmap_region_t)); |
| if (!maptable) { |
| perror("realloc"); |
| mapcount = 0; |
| munmap(address, length); |
| free(filename); |
| exitcode = 1; |
| return 0; |
| } |
| |
| /* Finally, make this the new active mapping */ |
| mapping = &maptable[mapcount - 1]; |
| mapping->addr = address; |
| mapping->length = length; |
| mapping->offset = offset; |
| mapping->name = filename; |
| mapping->prot = prot; |
| mapping->flags = flags; |
| return 0; |
| } |
| |
| static void |
| msync_help(void) |
| { |
| printf(_( |
| "\n" |
| " flushes a range of bytes in the current memory mapping\n" |
| "\n" |
| " Writes all modified copies of pages over the specified range (or entire\n" |
| " mapping if no range specified) to their backing storage locations. Also,\n" |
| " optionally invalidates so that subsequent references to the pages will be\n" |
| " obtained from their backing storage locations (instead of cached copies).\n" |
| " -a -- perform asynchronous writes (MS_ASYNC)\n" |
| " -i -- invalidate mapped pages (MS_INVALIDATE)\n" |
| " -s -- perform synchronous writes (MS_SYNC)\n" |
| "\n")); |
| } |
| |
| static int |
| msync_f( |
| int argc, |
| char **argv) |
| { |
| off64_t offset; |
| ssize_t length; |
| void *start; |
| int c, flags = 0; |
| size_t blocksize, sectsize; |
| |
| while ((c = getopt(argc, argv, "ais")) != EOF) { |
| switch (c) { |
| case 'a': |
| flags |= MS_ASYNC; |
| break; |
| case 'i': |
| flags |= MS_INVALIDATE; |
| break; |
| case 's': |
| flags |= MS_SYNC; |
| break; |
| default: |
| exitcode = 1; |
| return command_usage(&msync_cmd); |
| } |
| } |
| |
| if (optind == argc) { |
| offset = mapping->offset; |
| length = mapping->length; |
| } else if (optind == argc - 2) { |
| init_cvtnum(&blocksize, §size); |
| offset = cvtnum(blocksize, sectsize, argv[optind]); |
| if (offset < 0) { |
| printf(_("non-numeric offset argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| optind++; |
| length = cvtnum(blocksize, sectsize, argv[optind]); |
| if (length < 0) { |
| printf(_("non-numeric length argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| } else { |
| exitcode = 1; |
| return command_usage(&msync_cmd); |
| } |
| |
| start = check_mapping_range(mapping, offset, length, 1); |
| if (!start) { |
| exitcode = 1; |
| return 0; |
| } |
| |
| if (msync(start, length, flags) < 0) { |
| perror("msync"); |
| exitcode = 1; |
| return 0; |
| } |
| |
| return 0; |
| } |
| |
| static void |
| mread_help(void) |
| { |
| printf(_( |
| "\n" |
| " reads a range of bytes in the current memory mapping\n" |
| "\n" |
| " Example:\n" |
| " 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n" |
| "\n" |
| " Accesses a range of the current memory mapping, optionally dumping it to\n" |
| " the standard output stream (with -v option) for subsequent inspection.\n" |
| " -f -- verbose mode, dump bytes with offsets relative to start of file.\n" |
| " -r -- reverse order; start accessing from the end of range, moving backward\n" |
| " -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n" |
| " The accesses are performed sequentially from the start offset by default.\n" |
| " Notes:\n" |
| " References to whole pages following the end of the backing file results\n" |
| " in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n" |
| " on various filesystem conditions, including quota exceeded errors, and\n" |
| " for physical device errors (such as unreadable disk blocks). No attempt\n" |
| " has been made to catch signals at this stage...\n" |
| "\n")); |
| } |
| |
| static int |
| mread_f( |
| int argc, |
| char **argv) |
| { |
| off64_t offset, tmp, dumpoffset, printoffset; |
| ssize_t length; |
| size_t dumplen, cnt = 0; |
| char *bp; |
| void *start; |
| int dump = 0, rflag = 0, c; |
| size_t blocksize, sectsize; |
| |
| while ((c = getopt(argc, argv, "frv")) != EOF) { |
| switch (c) { |
| case 'f': |
| dump = 2; /* file offset dump */ |
| break; |
| case 'r': |
| rflag = 1; /* read in reverse */ |
| break; |
| case 'v': |
| dump = 1; /* mapping offset dump */ |
| break; |
| default: |
| exitcode = 1; |
| return command_usage(&mread_cmd); |
| } |
| } |
| |
| if (optind == argc) { |
| offset = mapping->offset; |
| length = mapping->length; |
| } else if (optind == argc - 2) { |
| init_cvtnum(&blocksize, §size); |
| offset = cvtnum(blocksize, sectsize, argv[optind]); |
| if (offset < 0) { |
| printf(_("non-numeric offset argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| optind++; |
| length = cvtnum(blocksize, sectsize, argv[optind]); |
| if (length < 0) { |
| printf(_("non-numeric length argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| } else { |
| return command_usage(&mread_cmd); |
| } |
| |
| start = check_mapping_range(mapping, offset, length, 0); |
| if (!start) { |
| exitcode = 1; |
| return 0; |
| } |
| dumpoffset = offset - mapping->offset; |
| if (dump == 2) |
| printoffset = offset; |
| else |
| printoffset = dumpoffset; |
| |
| if (alloc_buffer(pagesize, 0, 0) < 0) { |
| exitcode = 1; |
| return 0; |
| } |
| bp = (char *)io_buffer; |
| |
| dumplen = length % pagesize; |
| if (!dumplen) |
| dumplen = pagesize; |
| |
| if (rflag) { |
| for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) { |
| *bp = *(((char *)mapping->addr) + dumpoffset + tmp); |
| cnt++; |
| if (c && cnt == dumplen) { |
| if (dump) { |
| dump_buffer(printoffset, dumplen); |
| printoffset += dumplen; |
| } |
| bp = (char *)io_buffer; |
| dumplen = pagesize; |
| cnt = 0; |
| } else { |
| bp++; |
| } |
| } |
| } else { |
| for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) { |
| *bp = *(((char *)mapping->addr) + dumpoffset + tmp); |
| cnt++; |
| if (c && cnt == dumplen) { |
| if (dump) |
| dump_buffer(printoffset + tmp - |
| (dumplen - 1), dumplen); |
| bp = (char *)io_buffer; |
| dumplen = pagesize; |
| cnt = 0; |
| } else { |
| bp++; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| static int |
| munmap_f( |
| int argc, |
| char **argv) |
| { |
| ssize_t length; |
| unsigned int offset; |
| |
| if (munmap(mapping->addr, mapping->length) < 0) { |
| perror("munmap"); |
| exitcode = 1; |
| return 0; |
| } |
| free(mapping->name); |
| |
| /* Shuffle the mapping table entries down over the removed entry */ |
| offset = mapping - &maptable[0]; |
| length = mapcount * sizeof(mmap_region_t); |
| length -= (offset + 1) * sizeof(mmap_region_t); |
| if (length) |
| memmove(mapping, mapping + 1, length); |
| |
| /* Resize the memory allocated for the table, possibly freeing */ |
| if (--mapcount) { |
| maptable = (mmap_region_t *)realloc(maptable, /* shrinking */ |
| mapcount * sizeof(mmap_region_t)); |
| if (offset == mapcount) |
| offset--; |
| mapping = maptable + offset; |
| } else { |
| free(maptable); |
| mapping = maptable = NULL; |
| } |
| maplist_f(); |
| return 0; |
| } |
| |
| static void |
| mwrite_help(void) |
| { |
| printf(_( |
| "\n" |
| " dirties a range of bytes in the current memory mapping\n" |
| "\n" |
| " Example:\n" |
| " 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n" |
| "\n" |
| " Stores a byte into memory for a range within a mapping.\n" |
| " The default stored value is 'X', repeated to fill the range specified.\n" |
| " -S -- use an alternate seed character\n" |
| " -r -- reverse order; start storing from the end of range, moving backward\n" |
| " The stores are performed sequentially from the start offset by default.\n" |
| "\n")); |
| } |
| |
| static int |
| mwrite_f( |
| int argc, |
| char **argv) |
| { |
| off64_t offset, tmp; |
| ssize_t length; |
| void *start; |
| char *sp; |
| int seed = 'X'; |
| int rflag = 0; |
| int c; |
| size_t blocksize, sectsize; |
| |
| while ((c = getopt(argc, argv, "rS:")) != EOF) { |
| switch (c) { |
| case 'r': |
| rflag = 1; |
| break; |
| case 'S': |
| seed = (int)strtol(optarg, &sp, 0); |
| if (!sp || sp == optarg) { |
| printf(_("non-numeric seed -- %s\n"), optarg); |
| return 0; |
| } |
| break; |
| default: |
| exitcode = 1; |
| return command_usage(&mwrite_cmd); |
| } |
| } |
| |
| if (optind == argc) { |
| offset = mapping->offset; |
| length = mapping->length; |
| } else if (optind == argc - 2) { |
| init_cvtnum(&blocksize, §size); |
| offset = cvtnum(blocksize, sectsize, argv[optind]); |
| if (offset < 0) { |
| printf(_("non-numeric offset argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| optind++; |
| length = cvtnum(blocksize, sectsize, argv[optind]); |
| if (length < 0) { |
| printf(_("non-numeric length argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| } else { |
| exitcode = 1; |
| return command_usage(&mwrite_cmd); |
| } |
| |
| start = check_mapping_range(mapping, offset, length, 0); |
| if (!start) { |
| exitcode = 1; |
| return 0; |
| } |
| |
| offset -= mapping->offset; |
| if (rflag) { |
| for (tmp = offset + length -1; tmp >= offset; tmp--) |
| ((char *)mapping->addr)[tmp] = seed; |
| } else { |
| for (tmp = offset; tmp < offset + length; tmp++) |
| ((char *)mapping->addr)[tmp] = seed; |
| } |
| |
| return 0; |
| } |
| |
| #ifdef HAVE_MREMAP |
| static void |
| mremap_help(void) |
| { |
| printf(_( |
| "\n" |
| " resizes the current memory mapping\n" |
| "\n" |
| " Examples:\n" |
| " 'mremap 8192' - resizes the current mapping to 8192 bytes.\n" |
| "\n" |
| " Resizes the mapping, growing or shrinking from the current size.\n" |
| " The default stored value is 'X', repeated to fill the range specified.\n" |
| " -f <new_address> -- use MREMAP_FIXED flag to mremap on new_address\n" |
| " -m -- use the MREMAP_MAYMOVE flag\n" |
| "\n")); |
| } |
| |
| static int |
| mremap_f( |
| int argc, |
| char **argv) |
| { |
| ssize_t new_length; |
| void *new_addr = NULL; |
| int flags = 0; |
| int c; |
| size_t blocksize, sectsize; |
| |
| init_cvtnum(&blocksize, §size); |
| |
| while ((c = getopt(argc, argv, "f:m")) != EOF) { |
| switch (c) { |
| case 'f': |
| flags = MREMAP_FIXED|MREMAP_MAYMOVE; |
| new_addr = (void *)(unsigned long)cvtnum(blocksize, |
| sectsize, optarg); |
| break; |
| case 'm': |
| flags = MREMAP_MAYMOVE; |
| break; |
| default: |
| exitcode = 1; |
| return command_usage(&mremap_cmd); |
| } |
| } |
| |
| if (optind != argc - 1) { |
| exitcode = 1; |
| return command_usage(&mremap_cmd); |
| } |
| |
| new_length = cvtnum(blocksize, sectsize, argv[optind]); |
| if (new_length < 0) { |
| printf(_("non-numeric offset argument -- %s\n"), |
| argv[optind]); |
| exitcode = 1; |
| return 0; |
| } |
| |
| if (!new_addr) |
| new_addr = mremap(mapping->addr, mapping->length, |
| new_length, flags); |
| else |
| new_addr = mremap(mapping->addr, mapping->length, |
| new_length, flags, new_addr); |
| if (new_addr == MAP_FAILED) { |
| perror("mremap"); |
| exitcode = 1; |
| return 0; |
| } |
| |
| mapping->addr = new_addr; |
| mapping->length = new_length; |
| return 0; |
| } |
| #endif /* HAVE_MREMAP */ |
| |
| void |
| mmap_init(void) |
| { |
| mmap_cmd.name = "mmap"; |
| mmap_cmd.altname = "mm"; |
| mmap_cmd.cfunc = mmap_f; |
| mmap_cmd.argmin = 0; |
| mmap_cmd.argmax = -1; |
| mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | |
| CMD_FOREIGN_OK | CMD_FLAG_ONESHOT; |
| mmap_cmd.args = _("[N] | [-rwxS] [-s size] [off len]"); |
| mmap_cmd.oneline = |
| _("mmap a range in the current file, show mappings"); |
| mmap_cmd.help = mmap_help; |
| |
| mread_cmd.name = "mread"; |
| mread_cmd.altname = "mr"; |
| mread_cmd.cfunc = mread_f; |
| mread_cmd.argmin = 0; |
| mread_cmd.argmax = -1; |
| mread_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; |
| mread_cmd.args = _("[-r] [off len]"); |
| mread_cmd.oneline = |
| _("reads data from a region in the current memory mapping"); |
| mread_cmd.help = mread_help; |
| |
| msync_cmd.name = "msync"; |
| msync_cmd.altname = "ms"; |
| msync_cmd.cfunc = msync_f; |
| msync_cmd.argmin = 0; |
| msync_cmd.argmax = -1; |
| msync_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; |
| msync_cmd.args = _("[-ais] [off len]"); |
| msync_cmd.oneline = _("flush a region in the current memory mapping"); |
| msync_cmd.help = msync_help; |
| |
| munmap_cmd.name = "munmap"; |
| munmap_cmd.altname = "mu"; |
| munmap_cmd.cfunc = munmap_f; |
| munmap_cmd.argmin = 0; |
| munmap_cmd.argmax = 0; |
| munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; |
| munmap_cmd.oneline = _("unmaps the current memory mapping"); |
| |
| mwrite_cmd.name = "mwrite"; |
| mwrite_cmd.altname = "mw"; |
| mwrite_cmd.cfunc = mwrite_f; |
| mwrite_cmd.argmin = 0; |
| mwrite_cmd.argmax = -1; |
| mwrite_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; |
| mwrite_cmd.args = _("[-r] [-S seed] [off len]"); |
| mwrite_cmd.oneline = |
| _("writes data into a region in the current memory mapping"); |
| mwrite_cmd.help = mwrite_help; |
| |
| #ifdef HAVE_MREMAP |
| mremap_cmd.name = "mremap"; |
| mremap_cmd.altname = "mrm"; |
| mremap_cmd.cfunc = mremap_f; |
| mremap_cmd.argmin = 1; |
| mremap_cmd.argmax = 3; |
| mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK; |
| mremap_cmd.args = _("[-m|-f <new_address>] newsize"); |
| mremap_cmd.oneline = |
| _("alters the size of the current memory mapping"); |
| mremap_cmd.help = mremap_help; |
| #endif /* HAVE_MREMAP */ |
| |
| add_command(&mmap_cmd); |
| add_command(&mread_cmd); |
| add_command(&msync_cmd); |
| add_command(&munmap_cmd); |
| add_command(&mwrite_cmd); |
| #ifdef HAVE_MREMAP |
| add_command(&mremap_cmd); |
| #endif /* HAVE_MREMAP */ |
| } |