----- 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