Re: add print raw data capability for rd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




----- 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
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux