+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
*/
-#include <xfs/libxfs.h>
-#include <sys/mman.h>
-#include <signal.h>
#include "command.h"
#include "input.h"
+#include <sys/mman.h>
+#include <signal.h>
#include "init.h"
#include "io.h"
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;
int index,
int braces)
{
- unsigned char buffer[8] = { 0 };
+ char buffer[8] = { 0 };
int i;
static struct {
for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
buffer[i] = (map->prot & p->prot) ? p->mode : '-';
- printf("%c%d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n",
+
+ if (map->map_sync)
+ sprintf(&buffer[i], " S");
+
+ printf("%c%03d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n",
braces? '[' : ' ', index, braces? ']' : ' ',
(unsigned long)map->addr,
- (unsigned long)(map->addr + map->length),
+ (unsigned long)((char *)map->addr + map->length),
buffer, map->name ? map->name : "???",
(long long)map->offset, (long)map->length);
}
(long long)mapping->offset, (long)mapping->length);
return NULL;
}
- if (pagealign && (long)(mapping->addr + relative) % pagesize) {
+ if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) {
printf(_("offset address (%p) is not page aligned\n"),
- mapping->addr + relative);
+ (char *)mapping->addr + relative);
return NULL;
}
- return mapping->addr + relative;
+ return (char *)mapping->addr + relative;
}
int
" -r -- map with PROT_READ protection\n"
" -w -- map with PROT_WRITE protection\n"
" -x -- map with PROT_EXEC protection\n"
+" -S -- map with MAP_SYNC and MAP_SHARED_VALIDATE flags\n"
+" -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"));
}
char **argv)
{
off64_t offset;
- size_t length;
- void *address;
+ ssize_t length = 0, length2 = 0;
+ void *address = NULL;
char *filename;
- int blocksize, sectsize;
- int c, prot = 0;
+ 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 mapped regions, try 'help mmap'\n") :
_("no files are open, try 'help open'\n"));
return 0;
} else if (argc == 2) {
return 0;
}
- while ((c = getopt(argc, argv, "rwx")) != EOF) {
+ init_cvtnum(&blocksize, §size);
+
+ while ((c = getopt(argc, argv, "rwxSs:")) != EOF) {
switch (c) {
case 'r':
prot |= PROT_READ;
case 'x':
prot |= PROT_EXEC;
break;
+ case 'S':
+ flags = MAP_SYNC | MAP_SHARED_VALIDATE;
+
+ /*
+ * If MAP_SYNC and MAP_SHARED_VALIDATE aren't defined
+ * in the system headers we will have defined them
+ * both as 0.
+ */
+ if (!flags) {
+ printf("MAP_SYNC not supported\n");
+ return 0;
+ }
+ break;
+ case 's':
+ length2 = cvtnum(blocksize, sectsize, optarg);
+ break;
default:
return command_usage(&mmap_cmd);
}
if (optind != argc - 2)
return command_usage(&mmap_cmd);
- init_cvtnum(&blocksize, §size);
offset = cvtnum(blocksize, sectsize, argv[optind]);
if (offset < 0) {
printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
return 0;
}
- address = mmap(NULL, length, prot, MAP_SHARED, file->fd, offset);
+ /*
+ * 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);
mapping->offset = offset;
mapping->name = filename;
mapping->prot = prot;
+ mapping->map_sync = (flags == (MAP_SYNC | MAP_SHARED_VALIDATE));
return 0;
}
"\n"));
}
-int
+static int
msync_f(
int argc,
char **argv)
{
off64_t offset;
- size_t length;
+ ssize_t length;
void *start;
- int c, flags = 0, blocksize, sectsize;
+ int c, flags = 0;
+ size_t blocksize, sectsize;
while ((c = getopt(argc, argv, "ais")) != EOF) {
switch (c) {
return 0;
}
-static int
-read_mapping(
- char *dest,
- off64_t offset,
- int dump,
- off64_t dumpoffset,
- size_t dumplength)
-{
- *dest = *(((char *)mapping->addr) + offset);
-
- if (offset % pagesize == 0) {
- if (dump == 2)
- dumpoffset += mapping->offset;
- if (dump)
- dump_buffer(dumpoffset, dumplength);
- return 1;
- }
- return 0;
-}
-
static void
mread_help(void)
{
" 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 fom the end of range, moving backward\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"
"\n"));
}
-int
+static int
mread_f(
int argc,
char **argv)
{
- off64_t offset, tmp;
- size_t length, dumplen;
+ off64_t offset, tmp, dumpoffset, printoffset;
+ ssize_t length;
+ size_t dumplen, cnt = 0;
char *bp;
void *start;
- int dump = 0, rflag = 0;
- int c, blocksize, sectsize;
+ int dump = 0, rflag = 0, c;
+ size_t blocksize, sectsize;
while ((c = getopt(argc, argv, "frv")) != EOF) {
switch (c) {
start = check_mapping_range(mapping, offset, length, 0);
if (!start)
return 0;
+ dumpoffset = offset - mapping->offset;
+ if (dump == 2)
+ printoffset = offset;
+ else
+ printoffset = dumpoffset;
if (alloc_buffer(pagesize, 0, 0) < 0)
return 0;
- bp = (char *)buffer;
+ bp = (char *)io_buffer;
dumplen = length % pagesize;
if (!dumplen)
dumplen = pagesize;
if (rflag) {
- for (tmp = length, c = 0; tmp > 0; tmp--, bp++, c = 1)
- if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
- bp = (char *)buffer;
+ 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++, bp++, c = 1)
- if (read_mapping(bp, tmp, c? dump:0, offset, dumplen)) {
- bp = (char *)buffer;
+ 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++;
}
- }
- /* dump the remaining (partial page) part of the read buffer */
- if (dump) {
- if (rflag)
- dumplen = length % pagesize;
- else
- dumplen = tmp % pagesize;
- if (dumplen) {
- if (dump == 2)
- tmp += mapping->offset;
- dump_buffer(tmp, dumplen);
}
}
return 0;
}
-int
+static int
munmap_f(
int argc,
char **argv)
{
- size_t length;
+ ssize_t length;
unsigned int offset;
if (munmap(mapping->addr, mapping->length) < 0) {
" 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 fom the end of range, moving backward\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"));
}
-int
+static int
mwrite_f(
int argc,
char **argv)
{
off64_t offset, tmp;
- size_t length;
+ ssize_t length;
void *start;
char *sp;
int seed = 'X';
int rflag = 0;
- int c, blocksize, sectsize;
+ int c;
+ size_t blocksize, sectsize;
while ((c = getopt(argc, argv, "rS:")) != EOF) {
switch (c) {
if (!start)
return 0;
+ offset -= mapping->offset;
if (rflag) {
- for (tmp = offset + length; tmp > offset; tmp--)
+ for (tmp = offset + length -1; tmp >= offset; tmp--)
((char *)mapping->addr)[tmp] = seed;
} else {
for (tmp = offset; tmp < offset + length; tmp++)
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:
+ return command_usage(&mremap_cmd);
+ }
+ }
+
+ if (optind != argc - 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]);
+ 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");
+ else {
+ 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.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;
- mmap_cmd.args = _("[N] | [-rwx] [off len]");
+ 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.name = "mread";
+ mread_cmd.altname = "mr";
mread_cmd.cfunc = mread_f;
mread_cmd.argmin = 0;
mread_cmd.argmax = -1;
_("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.name = "msync";
+ msync_cmd.altname = "ms";
msync_cmd.cfunc = msync_f;
msync_cmd.argmin = 0;
msync_cmd.argmax = -1;
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.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.name = "mwrite";
+ mwrite_cmd.altname = "mw";
mwrite_cmd.cfunc = mwrite_f;
mwrite_cmd.argmin = 0;
mwrite_cmd.argmax = -1;
_("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 */
}