----- Original Message -----
>
> Thanks for detailed explaination. :)
> I made another patch to address the mentioned issues.
>
> Thanks,
> Lei
OK Lei, I've attached what I have queued for crash-5.1.9.
I made these changes to your last patch:
- Reworded the "help rd" output.
- Created an exported set_tmpfile2() function that allows
the caller to pass in their own FILE pointer of an open file
that only exists during the execution of a command. It will
afford the recursive-use protection of open_tmpfile2() plus
the automatic closure of the file if the command fails prior
to completion or if the user forgets to close it with
close_tmpfile2().
- Call close_tmpfile2() display_memory() after the copy is complete.
- Passed the filename in an additional "opt" parameter to display_memory(),
which can be used in the future for any new features that come along.
- Enforced the use of either a "count" argument or the use of
"-e ending-addr", since a default copy of 1 byte doesn't make
much sense.
- Made the output loop use an fwrite() of the whole buffer instead
of fputc() of each byte.
Thanks,
Dave
--- crash-5.1.8/defs.h.orig
+++ crash-5.1.8/defs.h
@@ -3818,6 +3818,7 @@ char *search_directory_tree(char *, char
void open_tmpfile(void);
void close_tmpfile(void);
void open_tmpfile2(void);
+void set_tmpfile2(FILE *);
void close_tmpfile2(void);
void open_files_dump(ulong, int, struct reference *);
void get_pathname(ulong, char *, int, int, ulong);
--- crash-5.1.8/help.c.orig
+++ crash-5.1.8/help.c
@@ -1396,7 +1396,8 @@ NULL
char *help_rd[] = {
"rd",
"read memory",
-"[-adDsSupxmfN][-8|-16|-32|-64][-o offs][-e addr] [address|symbol] [count]",
+"[-adDsSupxmfN][-8|-16|-32|-64][-o offs][-e addr][-r file][address|symbol]\n"
+" [count]",
" This command displays the contents of memory, with the output formatted",
" in several different manners. The starting address may be entered either",
" symbolically or by address. The default output size is the size of a long",
@@ -1428,14 +1429,19 @@ char *help_rd[] = {
" values)",
" -o offs offset the starting address by offs.",
" -e addr display memory until reaching specified ending hexadecimal address.",
+" -r file dumps raw data to the specified output file; the number of bytes that",
+" are copied to the file must be specified either by a count argument",
+" or by the -e option.",
" address starting hexadecimal address:",
" 1 the default presumes a kernel virtual address.",
" 2. -p specifies a physical address.",
" 3. -u specifies a user virtual address, but is only necessary on",
" processors with common user and kernel virtual address spaces.",
" symbol symbol of starting address to read.",
-" count number of memory locations to display; if entered, must be the last",
-" argument on the command line (default is 1; unlimited for -a).",
+" count number of memory locations to display; if entered, it must be the",
+" last argument on the command line; if not entered, the count defaults",
+" to 1, or unlimited for -a; when used with the -r option, it is the",
+" number of bytes to be written to the file.",
"\nEXAMPLES",
" Display the kernel's version string:\n",
" %s> rd -a linux_banner",
--- crash-5.1.8/memory.c.orig
+++ crash-5.1.8/memory.c
@@ -175,7 +175,7 @@ static void dump_vmlist(struct meminfo *
static int dump_page_lists(struct meminfo *);
static void dump_kmeminfo(void);
static int page_to_phys(ulong, physaddr_t *);
-static void display_memory(ulonglong, long, ulong, int);
+static void display_memory(ulonglong, long, ulong, int, void *);
static ulong search_ulong(ulong *, ulong, int, struct searchinfo *);
static ulong search_uint(ulong *, ulong, int, struct searchinfo *);
static ulong search_ushort(ulong *, ulong, int, struct searchinfo *);
@@ -264,7 +264,9 @@ static void dump_page_flags(ulonglong);
#define SLAB_CACHE (0x1000)
#define DISPLAY_ASCII (0x2000)
#define NET_ENDIAN (0x4000)
-#define DISPLAY_TYPES (DISPLAY_ASCII|DISPLAY_8|DISPLAY_16|DISPLAY_32|DISPLAY_64)
+#define DISPLAY_RAW (0x8000)
+#define DISPLAY_TYPES (DISPLAY_RAW|DISPLAY_ASCII|DISPLAY_8|\
+ DISPLAY_16|DISPLAY_32|DISPLAY_64)
#define ASCII_UNLIMITED ((ulong)(-1) >> 1)
@@ -966,14 +968,18 @@ cmd_rd(void)
ulonglong addr, endaddr;
ulong offset;
struct syment *sp;
+ FILE *tmpfp;
+ char *outputfile;
flag = HEXADECIMAL|DISPLAY_DEFAULT;
endaddr = 0;
offset = 0;
memtype = KVADDR;
+ tmpfp = NULL;
+ outputfile = NULL;
count = -1;
- while ((c = getopt(argcnt, args, "axme:pfudDusSNo:81:3:6:")) != EOF) {
+ while ((c = getopt(argcnt, args, "axme:r:pfudDusSNo:81:3:6:")) != EOF) {
switch(c)
{
case 'a':
@@ -1023,6 +1029,16 @@ cmd_rd(void)
endaddr = htoll(optarg, FAULT_ON_ERROR, NULL);
break;
+ case 'r':
+ flag &= ~DISPLAY_TYPES;
+ flag |= DISPLAY_RAW;
+ outputfile = optarg;
+ if ((tmpfp = fopen(outputfile, "w")) == NULL)
+ error(FATAL, "cannot open output file: %s\n",
+ outputfile);
+ set_tmpfile2(tmpfp);
+ break;
+
case 's':
case 'S':
if (flag & DISPLAY_DEFAULT) {
@@ -1138,14 +1154,19 @@ cmd_rd(void)
break;
case DISPLAY_8:
case DISPLAY_ASCII:
+ case DISPLAY_RAW:
count = bcnt;
break;
}
if (bcnt == 0)
count = 1;
- } else
+ } else {
+ if ((flag & DISPLAY_TYPES) == DISPLAY_RAW)
+ error(FATAL, "-r option requires either a count"
+ " argument or the -e option\n");
count = (flag & DISPLAY_ASCII) ? ASCII_UNLIMITED : 1;
+ }
} else if (endaddr)
error(WARNING,
"ending address ignored when count is specified\n");
@@ -1159,7 +1180,7 @@ cmd_rd(void)
memtype = UVADDR;
}
- display_memory(addr, count, flag, memtype);
+ display_memory(addr, count, flag, memtype, outputfile);
}
/*
@@ -1190,10 +1211,11 @@ struct memloc { /* comm
};
static void
-display_memory(ulonglong addr, long count, ulong flag, int memtype)
+display_memory(ulonglong addr, long count, ulong flag, int memtype, void *opt)
{
int i, a, j;
- size_t typesz;
+ size_t typesz, sz;
+ long written;
void *location;
char readtype[20];
char *addrtype;
@@ -1239,6 +1261,23 @@ display_memory(ulonglong addr, long coun
fprintf(fp, "<addr: %llx count: %ld flag: %lx (%s)>\n",
addr, count, flag, addrtype);
+ if (flag & DISPLAY_RAW) {
+ for (written = 0; written < count; written += sz) {
+ sz = BUFSIZE > (count - written) ?
+ (size_t)(count - written) : (size_t)BUFSIZE;
+ readmem(addr + written, memtype, buf, (long)sz,
+ "raw dump to file", FAULT_ON_ERROR);
+ if (fwrite(buf, 1, sz, pc->tmpfile2) != sz)
+ error(FATAL, "cannot write to: %s\n",
+ (char *)opt);
+ }
+ close_tmpfile2();
+
+ fprintf(fp, "%ld bytes copied from 0x%llx to %s\n",
+ count, addr, (char *)opt);
+ return;
+ }
+
BZERO(&mem, sizeof(struct memloc));
hx = linelen = typesz = per_line = ascii_start = 0;
location = NULL;
@@ -1758,7 +1797,7 @@ void
raw_stack_dump(ulong stackbase, ulong size)
{
display_memory(stackbase, size/sizeof(ulong),
- HEXADECIMAL|DISPLAY_DEFAULT|SYMBOLIC, KVADDR);
+ HEXADECIMAL|DISPLAY_DEFAULT|SYMBOLIC, KVADDR, NULL);
}
/*
@@ -1802,7 +1841,7 @@ raw_data_dump(ulong addr, long count, in
display_memory(address, wordcnt,
HEXADECIMAL|DISPLAY_DEFAULT|(symbolic ? SYMBOLIC : ASCII_ENDLINE),
- memtype);
+ memtype, NULL);
}
/*
--- crash-5.1.8/filesys.c.orig
+++ crash-5.1.8/filesys.c
@@ -1099,12 +1099,13 @@ close_tmpfile(void)
#endif
/*
- * open_tmpfile2() and close_tmpfile2() do not use a permanent tmpfile,
- * and do NOT modify the global fp pointer or pc->saved_fp. That being the
- * case, all wrapped functions must be aware of it, or fp has to manipulated
- * by the calling function. The secondary tmpfile should only be used by
- * common functions that might be called by a higher-level function using
- * the primary permanent tmpfile.
+ * open_tmpfile2(), set_tmpfile2() and close_tmpfile2() do not use a
+ * permanent tmpfile, and do NOT modify the global fp pointer or pc->saved_fp.
+ * That being the case, all wrapped functions must be aware of it, or the
+ * global fp pointer has to explicitly manipulated by the calling function.
+ * The secondary tmpfile should only be used by common functions that might
+ * be called by a higher-level function using the primary permanent tmpfile,
+ * or alternatively a caller may pass in a FILE pointer to set_tmpfile2().
*/
void
open_tmpfile2(void)
@@ -1128,6 +1129,15 @@ close_tmpfile2(void)
}
}
+void
+set_tmpfile2(FILE *fptr)
+{
+ if (pc->tmpfile2)
+ error(FATAL, "secondary temporary file already in use\n");
+
+ pc->tmpfile2 = fptr;
+}
+
#define MOUNT_PRINT_INODES 0x1
#define MOUNT_PRINT_FILES 0x2
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility