Hello Dave, While I am using 'kmem -p', I feel it is too slow, especially with a big memory. So I modify something to improve the performance. The patch is based on crash 6.0.2, and it has been tested on RHEL6.2_x86_64, RHEL6.2_i386, RHEL5.8_x86_64 and RHEL5.8_i386. Thanks, Qiao Nuohan
diff --git a/memory.c b/memory.c index 95eefc9..bc18ce1 100755 --- a/memory.c +++ b/memory.c @@ -4423,7 +4423,6 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) int print_hdr, pg_spec, phys_spec, done; int v22; char hdr[BUFSIZE]; - char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; @@ -4431,6 +4430,50 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) char *page_cache; char *pcache; ulong section, section_nr, nr_mem_sections, section_size; + long buffersize; + char *outputbuffer; + int bufferindex; + + buffersize = 1024 * 1024; + if (!(outputbuffer = malloc(buffersize + 512))) + error(FATAL, "cannot malloc outputbuffer\n"); + + char style1[100]; + char style2[100]; + char style3[100]; + char style4[100]; + + sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s", + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + VADDR_PRLEN, + space(MINSPACE), + space(MINSPACE)); + sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "), + space(MINSPACE), + mkstring(buf4, 8, CENTER|RJUST, " "), + " "); + sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"), + space(MINSPACE), + mkstring(buf4, 8, CENTER|RJUST, "-----")); + sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + VADDR_PRLEN, + space(MINSPACE)); v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */ @@ -4522,6 +4565,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) nr_mem_sections = NR_MEM_SECTIONS(); + bufferindex = 0; + /* * Iterate over all possible sections */ @@ -4681,19 +4726,9 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) page_not_mapped = phys_not_mapped = FALSE; if (v22) { - fprintf(fp, "%lx%s%s%s%s%s%8lx %2d%s", - pp, - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf2, VADDR_PRLEN, - RJUST|LONG_HEX, MKSTR(inode)), - space(MINSPACE), - offset, - count, - space(MINSPACE)); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style1, pp, phys, inode, + offset, count); } else { if ((vt->flags & V_MEM_MAP)) { if (!machdep->verify_paddr(phys)) @@ -4702,152 +4737,96 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) page_not_mapped = TRUE; } if (page_not_mapped) - fprintf(fp, "%s%s%s%s%s%s%s %2s ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf3, VADDR_PRLEN, - CENTER|RJUST, " "), - space(MINSPACE), - mkstring(buf4, 8, CENTER|RJUST, " "), - " "); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style2, pp, phys); else if (!page_mapping) - fprintf(fp, "%s%s%s%s%s%s%s %2d ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf3, VADDR_PRLEN, - CENTER|RJUST, "-------"), - space(MINSPACE), - mkstring(buf4, 8, CENTER|RJUST, "-----"), - count); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style3, pp, phys, count); else - fprintf(fp, "%s%s%s%s%s%s%8lx %2d ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf2, VADDR_PRLEN, - RJUST|LONG_HEX, MKSTR(mapping)), - space(MINSPACE), - index, - count); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style4, pp, phys, + mapping, index, count); } others = 0; +#define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "") + if (v22) { if ((flags >> v22_PG_DMA) & 1) - fprintf(fp, "%sDMA", - others++ ? "," : ""); + bufferindex += sprintflag("%sDMA"); if ((flags >> v22_PG_locked) & 1) - fprintf(fp, "%slocked", - others++ ? "," : ""); + bufferindex += sprintflag("%slocked"); if ((flags >> v22_PG_error) & 1) - fprintf(fp, "%serror", - others++ ? "," : ""); + bufferindex += sprintflag("%serror"); if ((flags >> v22_PG_referenced) & 1) - fprintf(fp, "%sreferenced", - others++ ? "," : ""); + bufferindex += sprintflag("%sreferenced"); if ((flags >> v22_PG_dirty) & 1) - fprintf(fp, "%sdirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sdirty"); if ((flags >> v22_PG_uptodate) & 1) - fprintf(fp, "%suptodate", - others++ ? "," : ""); + bufferindex += sprintflag("%suptodate"); if ((flags >> v22_PG_free_after) & 1) - fprintf(fp, "%sfree_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sfree_after"); if ((flags >> v22_PG_decr_after) & 1) - fprintf(fp, "%sdecr_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sdecr_after"); if ((flags >> v22_PG_swap_unlock_after) & 1) - fprintf(fp, "%sswap_unlock_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_unlock_after"); if ((flags >> v22_PG_Slab) & 1) - fprintf(fp, "%sslab", - others++ ? "," : ""); + bufferindex += sprintflag("%sslab"); if ((flags >> v22_PG_swap_cache) & 1) - fprintf(fp, "%sswap_cache", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_cache"); if ((flags >> v22_PG_skip) & 1) - fprintf(fp, "%sskip", - others++ ? "," : ""); + bufferindex += sprintflag("%sskip"); if ((flags >> v22_PG_reserved) & 1) - fprintf(fp, "%sreserved", - others++ ? "," : ""); - fprintf(fp, "\n"); + bufferindex += sprintflag("%sreserved"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { - fprintf(fp, "%lx\n", flags); + bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); } else { if ((flags >> v24_PG_locked) & 1) - fprintf(fp, "%slocked", - others++ ? "," : ""); + bufferindex += sprintflag("%slocked"); if ((flags >> v24_PG_error) & 1) - fprintf(fp, "%serror", - others++ ? "," : ""); + bufferindex += sprintflag("%serror"); if ((flags >> v24_PG_referenced) & 1) - fprintf(fp, "%sreferenced", - others++ ? "," : ""); + bufferindex += sprintflag("%sreferenced"); if ((flags >> v24_PG_uptodate) & 1) - fprintf(fp, "%suptodate", - others++ ? "," : ""); + bufferindex += sprintflag("%suptodate"); if ((flags >> v24_PG_dirty) & 1) - fprintf(fp, "%sdirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sdirty"); if ((flags >> v24_PG_decr_after) & 1) - fprintf(fp, "%sdecr_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sdecr_after"); if ((flags >> v24_PG_active) & 1) - fprintf(fp, "%sactive", - others++ ? "," : ""); + bufferindex += sprintflag("%sactive"); if ((flags >> v24_PG_inactive_dirty) & 1) - fprintf(fp, "%sinactive_dirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sinactive_dirty"); if ((flags >> v24_PG_slab) & 1) - fprintf(fp, "%sslab", - others++ ? "," : ""); + bufferindex += sprintflag("%sslab"); if ((flags >> v24_PG_swap_cache) & 1) - fprintf(fp, "%sswap_cache", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_cache"); if ((flags >> v24_PG_skip) & 1) - fprintf(fp, "%sskip", - others++ ? "," : ""); + bufferindex += sprintflag("%sskip"); if ((flags >> v24_PG_inactive_clean) & 1) - fprintf(fp, "%sinactive_clean", - others++ ? "," : ""); + bufferindex += sprintflag("%sinactive_clean"); if ((flags >> v24_PG_highmem) & 1) - fprintf(fp, "%shighmem", - others++ ? "," : ""); + bufferindex += sprintflag("%shighmem"); if ((flags >> v24_PG_checked) & 1) - fprintf(fp, "%schecked", - others++ ? "," : ""); + bufferindex += sprintflag("%schecked"); if ((flags >> v24_PG_bigpage) & 1) - fprintf(fp, "%sbigpage", - others++ ? "," : ""); + bufferindex += sprintflag("%sbigpage"); if ((flags >> v24_PG_arch_1) & 1) - fprintf(fp, "%sarch_1", - others++ ? "," : ""); + bufferindex += sprintflag("%sarch_1"); if ((flags >> v24_PG_reserved) & 1) - fprintf(fp, "%sreserved", - others++ ? "," : ""); + bufferindex += sprintflag("%sreserved"); if (phys_not_mapped) - fprintf(fp, "%s[NOT MAPPED]", - others++ ? " " : ""); + bufferindex += sprintflag("%s[NOT MAPPED]"); - fprintf(fp, "\n"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); + } + + if (bufferindex > buffersize) { + fprintf(fp, "%s", outputbuffer); + bufferindex = 0; } if (done) @@ -4858,6 +4837,10 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) break; } + if (bufferindex > 0) { + fprintf(fp, "%s", outputbuffer); + } + switch (mi->flags) { case GET_TOTALRAM_PAGES: @@ -4888,6 +4871,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) break; } + free(outputbuffer); FREEBUF(page_cache); } @@ -4909,19 +4893,62 @@ dump_mem_map(struct meminfo *mi) int v22; struct node_table *nt; char hdr[BUFSIZE]; - char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; char buf4[BUFSIZE]; char *page_cache; char *pcache; + long buffersize; + char *outputbuffer; + int bufferindex; + + buffersize = 1024 * 1024; + if (!(outputbuffer = malloc(buffersize + 512))) + error(FATAL, "cannot malloc outputbuffer\n"); + + char style1[100]; + char style2[100]; + char style3[100]; + char style4[100]; if (IS_SPARSEMEM()) { dump_mem_map_SPARSEMEM(mi); return; } + sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s", + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + VADDR_PRLEN, + space(MINSPACE), + space(MINSPACE)); + sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "), + space(MINSPACE), + mkstring(buf4, 8, CENTER|RJUST, " "), + " "); + sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"), + space(MINSPACE), + mkstring(buf4, 8, CENTER|RJUST, "-----")); + sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ", + VADDR_PRLEN, + space(MINSPACE), + (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")), + space(MINSPACE), + VADDR_PRLEN, + space(MINSPACE)); + v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */ if (v22) { @@ -5010,6 +5037,8 @@ dump_mem_map(struct meminfo *mi) done = FALSE; total_pages = 0; + bufferindex = 0; + for (n = 0; n < vt->numnodes; n++) { if (print_hdr) { if (!(pc->curcmd_flags & HEADER_PRINTED)) @@ -5133,19 +5162,9 @@ dump_mem_map(struct meminfo *mi) page_not_mapped = phys_not_mapped = FALSE; if (v22) { - fprintf(fp, "%lx%s%s%s%s%s%8lx %2d%s", - pp, - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf2, VADDR_PRLEN, - RJUST|LONG_HEX, MKSTR(inode)), - space(MINSPACE), - offset, - count, - space(MINSPACE)); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style1, pp, phys, inode, + offset, count); } else { if ((vt->flags & V_MEM_MAP)) { if (!machdep->verify_paddr(phys)) @@ -5154,154 +5173,98 @@ dump_mem_map(struct meminfo *mi) page_not_mapped = TRUE; } if (page_not_mapped) - fprintf(fp, "%s%s%s%s%s%s%s %2s ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf3, VADDR_PRLEN, - CENTER|RJUST, " "), - space(MINSPACE), - mkstring(buf4, 8, CENTER|RJUST, " "), - " "); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style2, pp, phys); else if (!page_mapping) - fprintf(fp, "%s%s%s%s%s%s%s %2d ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf3, VADDR_PRLEN, - CENTER|RJUST, "-------"), - space(MINSPACE), - mkstring(buf4, 8, CENTER|RJUST, "-----"), - count); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style3, pp, phys, count); else - fprintf(fp, "%s%s%s%s%s%s%8lx %2d ", - mkstring(buf0, VADDR_PRLEN, - LJUST|LONG_HEX, MKSTR(pp)), - space(MINSPACE), - mkstring(buf1, MAX(PADDR_PRLEN, - strlen("PHYSICAL")), - RJUST|LONGLONG_HEX, MKSTR(&phys)), - space(MINSPACE), - mkstring(buf2, VADDR_PRLEN, - RJUST|LONG_HEX, MKSTR(mapping)), - space(MINSPACE), - index, - count); + bufferindex += sprintf(outputbuffer+bufferindex, + (char *)&style4, pp, phys, + mapping, index, count); } others = 0; +#define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "") + if (v22) { if ((flags >> v22_PG_DMA) & 1) - fprintf(fp, "%sDMA", - others++ ? "," : ""); + bufferindex += sprintflag("%sDMA"); if ((flags >> v22_PG_locked) & 1) - fprintf(fp, "%slocked", - others++ ? "," : ""); + bufferindex += sprintflag("%slocked"); if ((flags >> v22_PG_error) & 1) - fprintf(fp, "%serror", - others++ ? "," : ""); + bufferindex += sprintflag("%serror"); if ((flags >> v22_PG_referenced) & 1) - fprintf(fp, "%sreferenced", - others++ ? "," : ""); + bufferindex += sprintflag("%sreferenced"); if ((flags >> v22_PG_dirty) & 1) - fprintf(fp, "%sdirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sdirty"); if ((flags >> v22_PG_uptodate) & 1) - fprintf(fp, "%suptodate", - others++ ? "," : ""); + bufferindex += sprintflag("%suptodate"); if ((flags >> v22_PG_free_after) & 1) - fprintf(fp, "%sfree_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sfree_after"); if ((flags >> v22_PG_decr_after) & 1) - fprintf(fp, "%sdecr_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sdecr_after"); if ((flags >> v22_PG_swap_unlock_after) & 1) - fprintf(fp, "%sswap_unlock_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_unlock_after"); if ((flags >> v22_PG_Slab) & 1) - fprintf(fp, "%sslab", - others++ ? "," : ""); + bufferindex += sprintflag("%sslab"); if ((flags >> v22_PG_swap_cache) & 1) - fprintf(fp, "%sswap_cache", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_cache"); if ((flags >> v22_PG_skip) & 1) - fprintf(fp, "%sskip", - others++ ? "," : ""); + bufferindex += sprintflag("%sskip"); if ((flags >> v22_PG_reserved) & 1) - fprintf(fp, "%sreserved", - others++ ? "," : ""); - fprintf(fp, "\n"); + bufferindex += sprintflag("%sreserved"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) { - fprintf(fp, "%lx\n", flags); + bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags); } else { if ((flags >> v24_PG_locked) & 1) - fprintf(fp, "%slocked", - others++ ? "," : ""); + bufferindex += sprintflag("%slocked"); if ((flags >> v24_PG_error) & 1) - fprintf(fp, "%serror", - others++ ? "," : ""); + bufferindex += sprintflag("%serror"); if ((flags >> v24_PG_referenced) & 1) - fprintf(fp, "%sreferenced", - others++ ? "," : ""); + bufferindex += sprintflag("%sreferenced"); if ((flags >> v24_PG_uptodate) & 1) - fprintf(fp, "%suptodate", - others++ ? "," : ""); + bufferindex += sprintflag("%suptodate"); if ((flags >> v24_PG_dirty) & 1) - fprintf(fp, "%sdirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sdirty"); if ((flags >> v24_PG_decr_after) & 1) - fprintf(fp, "%sdecr_after", - others++ ? "," : ""); + bufferindex += sprintflag("%sdecr_after"); if ((flags >> v24_PG_active) & 1) - fprintf(fp, "%sactive", - others++ ? "," : ""); + bufferindex += sprintflag("%sactive"); if ((flags >> v24_PG_inactive_dirty) & 1) - fprintf(fp, "%sinactive_dirty", - others++ ? "," : ""); + bufferindex += sprintflag("%sinactive_dirty"); if ((flags >> v24_PG_slab) & 1) - fprintf(fp, "%sslab", - others++ ? "," : ""); + bufferindex += sprintflag("%sslab"); if ((flags >> v24_PG_swap_cache) & 1) - fprintf(fp, "%sswap_cache", - others++ ? "," : ""); + bufferindex += sprintflag("%sswap_cache"); if ((flags >> v24_PG_skip) & 1) - fprintf(fp, "%sskip", - others++ ? "," : ""); + bufferindex += sprintflag("%sskip"); if ((flags >> v24_PG_inactive_clean) & 1) - fprintf(fp, "%sinactive_clean", - others++ ? "," : ""); + bufferindex += sprintflag("%sinactive_clean"); if ((flags >> v24_PG_highmem) & 1) - fprintf(fp, "%shighmem", - others++ ? "," : ""); + bufferindex += sprintflag("%shighmem"); if ((flags >> v24_PG_checked) & 1) - fprintf(fp, "%schecked", - others++ ? "," : ""); + bufferindex += sprintflag("%schecked"); if ((flags >> v24_PG_bigpage) & 1) - fprintf(fp, "%sbigpage", - others++ ? "," : ""); + bufferindex += sprintflag("%sbigpage"); if ((flags >> v24_PG_arch_1) & 1) - fprintf(fp, "%sarch_1", - others++ ? "," : ""); + bufferindex += sprintflag("%sarch_1"); if ((flags >> v24_PG_reserved) & 1) - fprintf(fp, "%sreserved", - others++ ? "," : ""); + bufferindex += sprintflag("%sreserved"); if (phys_not_mapped) - fprintf(fp, "%s[NOT MAPPED]", - others++ ? " " : ""); + bufferindex += sprintflag("%s[NOT MAPPED]"); - fprintf(fp, "\n"); + bufferindex += sprintf(outputbuffer+bufferindex, "\n"); } + if (bufferindex > buffersize) { + fprintf(fp, "%s", outputbuffer); + bufferindex = 0; + } + if (done) break; } @@ -5310,6 +5273,10 @@ dump_mem_map(struct meminfo *mi) break; } + if (bufferindex > 0) { + fprintf(fp, "%s", outputbuffer); + } + switch (mi->flags) { case GET_TOTALRAM_PAGES: @@ -5340,6 +5307,7 @@ dump_mem_map(struct meminfo *mi) break; } + free(outputbuffer); FREEBUF(page_cache); }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility