--- crash-4.0-6.1/memory.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/memory.c 2008-03-28 16:01:25.000000000 -0400 @@ -68,6 +68,7 @@ ulong addr; ulong size; } *vmlist; + ulong container; }; static char *memtype_string(int, int); @@ -96,8 +97,8 @@ static void dump_kmem_cache_slub(struct meminfo *); static void dump_kmem_cache_info_v2(struct meminfo *); static void kmem_cache_list_slub(void); -static ulong get_cpu_slab_ptr(struct meminfo *, int); -static char *vaddr_to_kmem_cache(ulong, char *); +static ulong get_cpu_slab_ptr(struct meminfo *, int, ulong *); +static char *vaddr_to_kmem_cache(ulong, char *, int); static ulong vaddr_to_slab(ulong); static void do_slab_chain(int, struct meminfo *); static void do_slab_chain_percpu_v1(long, struct meminfo *); @@ -177,6 +178,7 @@ static ulong compound_head(ulong); static long count_partial(ulong); static ulong get_freepointer(struct meminfo *, void *); +static int count_free_objects(struct meminfo *, ulong); char *is_slab_page(struct meminfo *, char *); static void do_node_lists_slub(struct meminfo *, ulong, int); @@ -195,6 +197,7 @@ #define UDECIMAL (0x200) #define ASCII_ENDLINE (0x400) #define NO_ASCII (0x800) +#define SLAB_CACHE (0x1000) static ulong DISPLAY_DEFAULT; @@ -455,6 +458,7 @@ MEMBER_OFFSET_INIT(kmem_cache_cpu_slab, "kmem_cache", "cpu_slab"); MEMBER_OFFSET_INIT(kmem_cache_list, "kmem_cache", "list"); MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name"); + MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags"); MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist"); MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page"); MEMBER_OFFSET_INIT(kmem_cache_cpu_node, "kmem_cache_cpu", "node"); @@ -869,7 +873,7 @@ memtype = KVADDR; count = -1; - while ((c = getopt(argcnt, args, "xme:pfudDuso:81:3:6:")) != EOF) { + while ((c = getopt(argcnt, args, "xme:pfudDusSo:81:3:6:")) != EOF) { switch(c) { case '8': @@ -915,12 +919,15 @@ break; case 's': - if (flag & DISPLAY_DEFAULT) + case 'S': + if (flag & DISPLAY_DEFAULT) { flag |= SYMBOLIC; - else { - error(INFO, - "-s only allowed with %d-bit display\n", - DISPLAY_DEFAULT == DISPLAY_64 ? + if (c == 'S') + flag |= SLAB_CACHE; + } else { + error(INFO, "-%c option" + " is only allowed with %d-bit display\n", + c, DISPLAY_DEFAULT == DISPLAY_64 ? 64 : 32); argerrs++; } @@ -1086,6 +1093,7 @@ char ch; int linelen; char buf[BUFSIZE]; + char slab[BUFSIZE]; int ascii_start; char *hex_64_fmt = BITS32() ? "%.*llx " : "%.*lx "; char *dec_64_fmt = BITS32() ? "%12lld " : "%15ld "; @@ -1185,6 +1193,19 @@ linelen += strlen(buf)+1; break; } + if ((flag & SLAB_CACHE) && + vaddr_to_kmem_cache(mem.u64, slab, + !VERBOSE)) { + if (CRASHDEBUG(1)) + sprintf(buf, "[%llx:%s]", + (ulonglong)mem.u64, + slab); + else + sprintf(buf, "[%s]", slab); + fprintf(fp, "%-16s ", buf); + linelen += strlen(buf)+1; + break; + } } if (flag & HEXADECIMAL) { fprintf(fp, hex_64_fmt, LONG_LONG_PRLEN, @@ -1211,6 +1232,19 @@ linelen += strlen(buf)+1; break; } + if ((flag & SLAB_CACHE) && + vaddr_to_kmem_cache(mem.u32, slab, + !VERBOSE)) { + if (CRASHDEBUG(1)) + sprintf(buf, "[%x:%s]", + mem.u32, slab); + else + sprintf(buf, "[%s]", slab); + fprintf(fp, INT_PRLEN == 16 ? + "%-16s " : "%-8s ", buf); + linelen += strlen(buf)+1; + break; + } } if (flag & HEXADECIMAL) { fprintf(fp, "%.*x ", INT_PRLEN, mem.u32 ); @@ -7141,22 +7175,25 @@ * name of the cache to which it belongs. */ static char * -vaddr_to_kmem_cache(ulong vaddr, char *buf) +vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) { physaddr_t paddr; ulong page; ulong cache; if (!kvtop(NULL, vaddr, &paddr, 0)) { - error(WARNING, - "cannot make virtual-to-physical translation: %lx\n", - vaddr); + if (verbose) + error(WARNING, + "cannot make virtual-to-physical translation: %lx\n", + vaddr); return NULL; } if (!phys_to_page(paddr, &page)) { - error(WARNING, "cannot find mem_map page for address: %lx\n", - vaddr); + if (verbose) + error(WARNING, + "cannot find mem_map page for address: %lx\n", + vaddr); return NULL; } @@ -7665,7 +7702,7 @@ si->cache = cache_cache = symbol_value("cache_cache"); if (si->flags & ADDRESS_SPECIFIED) { - if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) { + if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) { error(INFO, "address is not allocated in slab subsystem: %lx\n", si->spec_addr); @@ -7791,12 +7828,14 @@ case KMEM_OBJECT_ADDR_FREE: fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx\n", + si->container ? si->container : (ulong)si->spec_addr); break; case KMEM_OBJECT_ADDR_INUSE: fprintf(fp, free_inuse_hdr); fprintf(fp, " [%lx]\n", + si->container ? si->container : (ulong)si->spec_addr); break; } @@ -7869,7 +7908,7 @@ si->cache = cache_cache = symbol_value("cache_cache"); if (si->flags & ADDRESS_SPECIFIED) { - if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) { + if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) { error(INFO, "address is not allocated in slab subsystem: %lx\n", si->spec_addr); @@ -7996,12 +8035,14 @@ case KMEM_OBJECT_ADDR_FREE: fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx\n", + si->container ? si->container : (ulong)si->spec_addr); break; case KMEM_OBJECT_ADDR_INUSE: fprintf(fp, free_inuse_hdr); - fprintf(fp, " [%lx]\n", + fprintf(fp, " [%lx]\n", + si->container ? si->container : (ulong)si->spec_addr); break; @@ -8009,6 +8050,7 @@ fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx (cpu %d cache)\n", + si->container ? si->container : (ulong)si->spec_addr, si->cpu); break; } @@ -8091,7 +8133,7 @@ cache_end = symbol_value("cache_chain"); if (si->flags & ADDRESS_SPECIFIED) { - if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) { + if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) { error(INFO, "address is not allocated in slab subsystem: %lx\n", si->spec_addr); @@ -8225,12 +8267,14 @@ case KMEM_OBJECT_ADDR_FREE: fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx\n", + si->container ? si->container : (ulong)si->spec_addr); break; case KMEM_OBJECT_ADDR_INUSE: fprintf(fp, free_inuse_hdr); fprintf(fp, " [%lx]\n", + si->container ? si->container : (ulong)si->spec_addr); break; @@ -8238,6 +8282,7 @@ fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx (cpu %d cache)\n", + si->container ? si->container : (ulong)si->spec_addr, si->cpu); break; @@ -8245,6 +8290,7 @@ fprintf(fp, free_inuse_hdr); fprintf(fp, " %lx (shared cache)\n", + si->container ? si->container : (ulong)si->spec_addr); break; } @@ -9638,6 +9684,7 @@ if (INOBJECT(si->spec_addr, obj)) { \ si->found = \ KMEM_OBJECT_ADDR_FREE; \ + si->container = obj; \ return; \ } \ } \ @@ -9649,6 +9696,7 @@ if (INOBJECT(si->spec_addr, obj)) { \ si->found = \ KMEM_OBJECT_ADDR_INUSE; \ + si->container = obj; \ return; \ } \ } \ @@ -9670,6 +9718,7 @@ cnt = 0; expected = si->s_inuse; + si->container = 0; if (CRASHDEBUG(1)) for (i = 0; i < si->c_num; i++) { @@ -9745,6 +9794,7 @@ cnt = 0; expected = si->s_inuse; + si->container = 0; if (CRASHDEBUG(1)) for (i = 0; i < si->c_num; i++) { @@ -9796,6 +9846,7 @@ if (INOBJECT(si->spec_addr, obj)) { si->found = KMEM_OBJECT_ADDR_FREE; + si->container = obj; return; } } @@ -9808,6 +9859,7 @@ if (INOBJECT(si->spec_addr, obj)) { si->found = KMEM_OBJECT_ADDR_CACHED; + si->container = obj; return; } } @@ -9819,6 +9871,7 @@ if (INOBJECT(si->spec_addr, obj)) { si->found = KMEM_OBJECT_ADDR_SHARED; + si->container = obj; return; } } @@ -9830,6 +9883,7 @@ if (INOBJECT(si->spec_addr, obj)) { si->found = KMEM_OBJECT_ADDR_INUSE; + si->container = obj; return; } } @@ -10270,7 +10324,7 @@ */ mi->flags = orig_flags; mi->retval = 0; - if ((vaddr != BADADDR) && vaddr_to_kmem_cache(vaddr, buf)) { + if ((vaddr != BADADDR) && vaddr_to_kmem_cache(vaddr, buf, VERBOSE)) { BZERO(&tmp_meminfo, sizeof(struct meminfo)); tmp_meminfo.spec_addr = vaddr; tmp_meminfo.memtype = KVADDR; @@ -10889,6 +10943,10 @@ case 'k': if (!sflag) { start = machdep->kvbase; + if (machine_type("IA64") && + (start < machdep->identity_map_base) && + (kt->stext > start)) + start = kt->stext; sflag++; } memtype = KVADDR; @@ -13353,7 +13411,8 @@ if ((p1 = is_slab_page(si, kbuf))) { si->flags |= VERBOSE; si->slab = (ulong)si->spec_addr; - } else if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) { + } else if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, + VERBOSE))) { error(INFO, "address is not allocated in slab subsystem: %lx\n", si->spec_addr); @@ -13453,7 +13512,7 @@ total_slabs = total_objects = 0; for (i = 0; i < kt->cpus; i++) { - cpu_slab_ptr = get_cpu_slab_ptr(si, i); + cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL); if (!cpu_slab_ptr) continue; @@ -13558,7 +13617,7 @@ per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes); for (i = 0; i < kt->cpus; i++) { - cpu_slab_ptr = get_cpu_slab_ptr(si, i); + cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL); fprintf(fp, "CPU %d SLAB:\n%s", i, cpu_slab_ptr ? "" : " (empty)\n"); @@ -13626,7 +13685,7 @@ physaddr_t paddr; ulong vaddr; ushort inuse; - ulong freelist, cpu_slab_ptr; + ulong freelist, cpu_freelist, cpu_slab_ptr; int i, cpu_slab, is_free, node; ulong p, q; @@ -13657,30 +13716,63 @@ sizeof(void *), "page.freelist", RETURN_ON_ERROR)) return; - DUMP_SLAB_INFO_SLUB(); - - if (!verbose) + if (!verbose) { + DUMP_SLAB_INFO_SLUB(); return; + } for (i = 0, cpu_slab = -1; i < kt->cpus; i++) { - cpu_slab_ptr = get_cpu_slab_ptr(si, i); + cpu_slab_ptr = get_cpu_slab_ptr(si, i, &cpu_freelist); if (!cpu_slab_ptr) continue; if (cpu_slab_ptr == si->slab) { cpu_slab = i; + /* + * Later slub scheme uses the per-cpu freelist + * and keeps page->inuse maxed out, so count + * the free objects by hand. + */ + if (cpu_freelist) + freelist = cpu_freelist; + if ((si->objects - inuse) == 0) + inuse = si->objects - + count_free_objects(si, freelist); break; } } + DUMP_SLAB_INFO_SLUB(); + fprintf(fp, " %s", free_inuse_hdr); +#define PAGE_MAPPING_ANON 1 + + if (CRASHDEBUG(1)) { + fprintf(fp, "< SLUB: free list START: >\n"); + i = 0; + for (q = freelist; q; q = get_freepointer(si, (void *)q)) { + if (q & PAGE_MAPPING_ANON) { + fprintf(fp, + "< SLUB: free list END: %lx (%d found) >\n", + q, i); + break; + } + fprintf(fp, " %lx\n", q); + i++; + } + if (!q) + fprintf(fp, "< SLUB: free list END (%d found) >\n", i); + } + for (p = vaddr; p < vaddr + si->objects * si->size; p += si->size) { is_free = FALSE; for (is_free = 0, q = freelist; q; q = get_freepointer(si, (void *)q)) { if (q == BADADDR) return; + if (q & PAGE_MAPPING_ANON) + break; if (p == q) { is_free = TRUE; break; @@ -13705,6 +13797,23 @@ } } +static int +count_free_objects(struct meminfo *si, ulong freelist) +{ + int c; + ulong q; + + c = 0; + for (q = freelist; q; q = get_freepointer(si, (void *)q)) { + if (q & PAGE_MAPPING_ANON) + break; + c++; + } + + return c; +} + + static ulong get_freepointer(struct meminfo *si, void *object) { @@ -13721,7 +13830,7 @@ static void do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) { - ulong next, list_head; + ulong next, list_head, flags; int first; list_head = node_ptr + OFFSET(kmem_cache_node_partial); @@ -13746,7 +13855,11 @@ return; } - if (INVALID_MEMBER(kmem_cache_node_full)) { +#define SLAB_STORE_USER (0x00010000UL) + flags = ULONG(si->cache_buf + OFFSET(kmem_cache_flags)); + + if (INVALID_MEMBER(kmem_cache_node_full) || + !(flags & SLAB_STORE_USER)) { fprintf(fp, "NODE %d FULL:\n (not tracked)\n", node); return; } @@ -13938,7 +14051,7 @@ RETURN_ON_ERROR|QUIET)) return NULL; - if (!(page_flags & vt->PG_slab)) + if (!(page_flags & (1 << vt->PG_slab))) return NULL; if (!readmem(si->spec_addr + OFFSET(page_slab), KVADDR, @@ -13976,12 +14089,16 @@ /* * Figure out which of the kmem_cache.cpu_slab declarations * is used by this kernel, and return a pointer to the slab - * page being used. + * page being used. Return the kmem_cache_cpu.freelist pointer + * if requested. */ static ulong -get_cpu_slab_ptr(struct meminfo *si, int cpu) +get_cpu_slab_ptr(struct meminfo *si, int cpu, ulong *cpu_freelist) { - ulong cpu_slab_ptr, page; + ulong cpu_slab_ptr, page, freelist; + + if (cpu_freelist) + *cpu_freelist = 0; switch (vt->cpu_slab_type) { @@ -13989,11 +14106,23 @@ cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab) + OFFSET(kmem_cache_cpu_page)); + if (cpu_freelist && VALID_MEMBER(kmem_cache_cpu_freelist)) + *cpu_freelist = ULONG(si->cache_buf + + OFFSET(kmem_cache_cpu_slab) + + OFFSET(kmem_cache_cpu_freelist)); break; case TYPE_CODE_ARRAY: cpu_slab_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*cpu)); + + if (cpu_slab_ptr && cpu_freelist && + VALID_MEMBER(kmem_cache_cpu_freelist)) { + if (readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_freelist), + KVADDR, &freelist, sizeof(void *), + "kmem_cache_cpu.freelist", RETURN_ON_ERROR)) + *cpu_freelist = freelist; + } if (cpu_slab_ptr && VALID_MEMBER(kmem_cache_cpu_page)) { if (!readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_page), --- crash-4.0-6.1/filesys.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/filesys.c 2008-03-14 09:44:37.000000000 -0400 @@ -240,7 +240,7 @@ if (match_file_string(pc->namelist, kt->proc_version, buffer)) { if (CRASHDEBUG(1)) { - fprintf(fp, "/proc/version:\n%s", kt->proc_version); + fprintf(fp, "/proc/version:\n%s\n", kt->proc_version); fprintf(fp, "%s:\n%s", pc->namelist, buffer); } return; @@ -709,6 +709,8 @@ fclose(version); + strip_linefeeds(kt->proc_version); + return TRUE; } --- crash-4.0-6.1/help.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/help.c 2008-03-18 14:47:57.000000000 -0400 @@ -1116,7 +1116,7 @@ char *help_rd[] = { "rd", "read memory", -"[-dDsupxmf][-8|-16|-32|-64][-o offs][-e addr] [address|symbol] [count]", +"[-dDsSupxmf][-8|-16|-32|-64][-o offs][-e addr] [address|symbol] [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", @@ -1130,6 +1130,9 @@ " -d display output in signed decimal format (default is hexadecimal).", " -D display output in unsigned decimal format (default is hexadecimal).", " -s displays output symbolically when appropriate.", +" -S displays output symbolically when appropriate; if the address", +" references a slab cache object, the name of the slab cache will", +" be displayed in brackets.", " -x do not display ASCII translation at end of each line.", #ifdef NOTDEF " -o Shows offset value from the starting address.", @@ -1152,35 +1155,38 @@ " Display the kernel_version string:\n", " %s> rd kernel_version 4 ", " c0226a6c: 2e322e32 35312d35 00000000 00000001 2.2.5-15........\n", -" Display the same block of memory, with and without symbols:\n", -" %s> rd c1157f00 52 ", -" c1157f00: c0131f7a 00000400 00000015 c013206e z...........n ..", -" c1157f10: 00000100 c3d4c140 00000100 00000246 ....@.......F...", -" c1157f20: 019b2065 c2a5bb90 080ac618 c02a83d0 e ............*.", -" c1157f30: 40000025 01a45067 c1156000 00000000 %..@gP...`......", -" c1157f40: c011b4f7 c1156000 c2a5bb90 080ac618 .....`..........", -" c1157f50: 00000001 00000000 c1a45000 c19b2000 .........P... ..", -" c1157f60: c1157f84 0000003b c022c000 c1156000 ....;.....\"..`..", -" c1157f70: 00000000 fffffe00 bffff6fc 0000002e ................", -" c1157f80: c022c000 ffffffff c01178ba c1156000 ..\"......x...`..", -" c1157f90: 00000000 080ac618 bffff6ac 00000001 ................", -" c1157fa0: c1156000 c1156000 c1157fb8 c1156000 .`...`.......`..", -" c1157fb0: c1157fb8 c1156000 c1156000 c115608c .....`...`...`..", -" c1157fc0: c01096c8 ffffffff bffff6fc 00000002 ................\n", -" %s> rd -s c1157f00 52", -" c1157f00: alloc_fd_array+0x1a 00000400 00000015 expand_fd_array+0x72 ", -" c1157f10: 00000100 c3d4c140 00000100 00000246 ", -" c1157f20: 019b2065 c2a5bb90 080ac618 c02a83d0 ", -" c1157f30: 40000025 01a45067 c1156000 00000000 ", -" c1157f40: do_wp_page+0x17f c1156000 c2a5bb90 080ac618 ", -" c1157f50: 00000001 00000000 c1a45000 c19b2000 ", -" c1157f60: c1157f84 0000003b init_task_union c1156000 ", -" c1157f70: 00000000 fffffe00 bffff6fc 0000002e ", -" c1157f80: init_task_union ffffffff sys_wait4+0x2be c1156000 ", -" c1157f90: 00000000 080ac618 bffff6ac 00000001 ", -" c1157fa0: c1156000 c1156000 c1157fb8 c1156000 ", -" c1157fb0: c1157fb8 c1156000 c1156000 c115608c ", -" c1157fc0: system_call+0x34 ffffffff bffff6fc 00000002\n", +" Display the same block of memory, first without symbols, again", +" with symbols, and then with symbols and slab cache references:\n", +" %s> rd dff12e80 36", +" dff12e80: dff12e94 00000000 c05a363a dff12ed0 ........:6Z.....", +" dff12e90: 00000001 dff12e98 0041fe3f ffffffff ........?.A.....", +" dff12ea0: 00000001 d5147800 00000000 def8abc0 .....x..........", +" dff12eb0: dff12ebc c05a4aa0 00000000 dff12ed0 .....JZ.........", +" dff12ec0: 00000001 00000000 00000000 00000000 ................", +" dff12ed0: 0808b353 00000000 dff12efc c0698220 S........... .i.", +" dff12ee0: dff12efc df7c6480 00000001 c046f99b .....d|.......F.", +" dff12ef0: 00000000 00000000 0808b352 dff12f68 ........R...h/..", +" dff12f00: c155a128 00000000 00000001 ffffffff (.U.............", +" %s> rd -s dff12e80 36", +" dff12e80: dff12e94 00000000 sock_aio_write+83 dff12ed0 ", +" dff12e90: 00000001 dff12e98 0041fe3f ffffffff ", +" dff12ea0: 00000001 d5147800 00000000 def8abc0 ", +" dff12eb0: dff12ebc sys_recvfrom+207 00000000 dff12ed0 ", +" dff12ec0: 00000001 00000000 00000000 00000000 ", +" dff12ed0: 0808b353 00000000 dff12efc socket_file_ops ", +" dff12ee0: dff12efc df7c6480 00000001 do_sync_write+182 ", +" dff12ef0: 00000000 00000000 0808b352 dff12f68 ", +" dff12f00: c155a128 00000000 00000001 ffffffff ", +" %s> rd -S dff12e80 36", +" dff12e80: [size-4096] 00000000 sock_aio_write+83 [size-4096] ", +" dff12e90: 00000001 [size-4096] 0041fe3f ffffffff ", +" dff12ea0: 00000001 [sock_inode_cache] 00000000 [filp] ", +" dff12eb0: [size-4096] sys_recvfrom+207 00000000 [size-4096] ", +" dff12ec0: 00000001 00000000 00000000 00000000 ", +" dff12ed0: 0808b353 00000000 [size-4096] socket_file_ops ", +" dff12ee0: [size-4096] [filp] 00000001 do_sync_write+182 ", +" dff12ef0: 00000000 00000000 0808b352 [size-4096] ", +" dff12f00: [vm_area_struct] 00000000 00000001 ffffffff\n", " Read jiffies in hexadecimal and decimal format:\n", " %s> rd jiffies", " c0213ae0: 0008cc3a :...\n", --- crash-4.0-6.1/task.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/task.c 2008-03-23 17:52:26.000000000 -0400 @@ -34,6 +34,7 @@ static void refresh_context(ulong, ulong); static void parent_list(ulong); static void child_list(ulong); +static void initialize_task_state(void); static void show_task_times(struct task_context *, ulong); static void show_task_args(struct task_context *); static void show_task_rlimit(struct task_context *); @@ -446,6 +447,9 @@ sort_context_array(); + if (pc->flags & SILENT) + initialize_task_state(); + tt->flags |= TASK_INIT_DONE; } --- crash-4.0-6.1/kernel.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/kernel.c 2008-03-14 09:46:54.000000000 -0400 @@ -540,10 +540,10 @@ error(WARNING, "cannot read linux_banner string\n"); if (ACTIVE()) { - len = strlen(kt->proc_version) - 1; + len = strlen(kt->proc_version); if ((len > 0) && (strncmp(buf, kt->proc_version, len) != 0)) { if (CRASHDEBUG(1)) { - fprintf(fp, "/proc/version:\n%s", + fprintf(fp, "/proc/version:\n%s\n", kt->proc_version); fprintf(fp, "linux_banner:\n%s\n", buf); } @@ -558,7 +558,7 @@ fprintf(fp, "linux_banner:\n%s\n", buf); goto bad_match; } - strcpy(kt->proc_version, buf); + strcpy(kt->proc_version, strip_linefeeds(buf)); } verify_namelist(); @@ -776,7 +776,7 @@ if (!strstr(buffer, "Linux version 2.")) continue; - if (STREQ(buffer, kt->proc_version)) { + if (strstr(buffer, kt->proc_version)) { found = TRUE; break; } @@ -823,7 +823,7 @@ if (found) { if (CRASHDEBUG(1)) { fprintf(fp, "verify_namelist:\n"); - fprintf(fp, "/proc/version:\n%s", kt->proc_version); + fprintf(fp, "/proc/version:\n%s\n", kt->proc_version); fprintf(fp, "utsname version: %s\n", kt->utsname.version); fprintf(fp, "%s:\n%s\n", namelist, buffer); @@ -833,7 +833,7 @@ if (CRASHDEBUG(1)) { fprintf(fp, "verify_namelist:\n"); - fprintf(fp, "/proc/version:\n%s", kt->proc_version); + fprintf(fp, "/proc/version:\n%s\n", kt->proc_version); fprintf(fp, "utsname version: %s\n", kt->utsname.version); fprintf(fp, "%s:\n%s\n", namelist, buffer2); } --- crash-4.0-6.1/net.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/net.c 2008-03-17 16:58:26.000000000 -0400 @@ -65,6 +65,8 @@ #define BYTES_IP_TUPLE (BYTES_IP_ADDR + BYTES_PORT_NUM + 1) static void show_net_devices(void); +static void show_net_devices_v2(void); +static void show_net_devices_v3(void); static void print_neighbour_q(ulong, int); static void get_netdev_info(ulong, struct devinfo *); static void get_device_name(ulong, char *); @@ -111,6 +113,8 @@ "net_device", "addr_len"); net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr, "net_device", "ip_ptr"); + MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list"); + MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head"); ARRAY_LENGTH_INIT(net->net_device_name_index, net_device_name, "net_device.name", NULL, sizeof(char)); net->flags |= (NETDEV_INIT|STRUCT_NET_DEVICE); @@ -355,8 +359,16 @@ long flen; char buf[BUFSIZE]; + if (symbol_exists("dev_base_head")) { + show_net_devices_v2(); + return; + } else if (symbol_exists("init_net")) { + show_net_devices_v3(); + return; + } + if (!symbol_exists("dev_base")) - error(FATAL, "dev_base does not exist!\n"); + error(FATAL, "dev_base, dev_base_head or init_net do not exist!\n"); get_symbol_data("dev_base", sizeof(void *), &next); @@ -384,6 +396,114 @@ } while (next); } +static void +show_net_devices_v2(void) +{ + struct list_data list_data, *ld; + char *net_device_buf; + char buf[BUFSIZE]; + ulong *ndevlist; + int ndevcnt, i; + long flen; + + if (!net->netdevice) /* initialized in net_init() */ + return; + + flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); + + fprintf(fp, "%s NAME IP ADDRESS(ES)\n", + mkstring(upper_case(net->netdevice, buf), + flen, CENTER|LJUST, NULL)); + + net_device_buf = GETBUF(SIZE(net_device)); + + ld = &list_data; + BZERO(ld, sizeof(struct list_data)); + get_symbol_data("dev_base_head", sizeof(void *), &ld->start); + ld->end = symbol_value("dev_base_head"); + ld->list_head_offset = OFFSET(net_device_dev_list); + + hq_open(); + ndevcnt = do_list(ld); + ndevlist = (ulong *)GETBUF(ndevcnt * sizeof(ulong)); + ndevcnt = retrieve_list(ndevlist, ndevcnt); + hq_close(); + + for (i = 0; i < ndevcnt; ++i) { + readmem(ndevlist[i], KVADDR, net_device_buf, + SIZE(net_device), "net_device buffer", + FAULT_ON_ERROR); + + fprintf(fp, "%s ", + mkstring(buf, flen, CENTER|RJUST|LONG_HEX, + MKSTR(ndevlist[i]))); + + get_device_name(ndevlist[i], buf); + fprintf(fp, "%-6s ", buf); + + get_device_address(ndevlist[i], buf); + fprintf(fp, "%s\n", buf); + } + + FREEBUF(ndevlist); + FREEBUF(net_device_buf); +} + +static void +show_net_devices_v3(void) +{ + struct list_data list_data, *ld; + char *net_device_buf; + char buf[BUFSIZE]; + ulong *ndevlist; + int ndevcnt, i; + long flen; + + if (!net->netdevice) /* initialized in net_init() */ + return; + + flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); + + fprintf(fp, "%s NAME IP ADDRESS(ES)\n", + mkstring(upper_case(net->netdevice, buf), + flen, CENTER|LJUST, NULL)); + + net_device_buf = GETBUF(SIZE(net_device)); + + ld = &list_data; + BZERO(ld, sizeof(struct list_data)); + ld->start = ld->end = + symbol_value("init_net") + OFFSET(net_dev_base_head); + ld->list_head_offset = OFFSET(net_device_dev_list); + + hq_open(); + ndevcnt = do_list(ld); + ndevlist = (ulong *)GETBUF(ndevcnt * sizeof(ulong)); + ndevcnt = retrieve_list(ndevlist, ndevcnt); + hq_close(); + + /* + * Skip the first entry (init_net). + */ + for (i = 1; i < ndevcnt; ++i) { + readmem(ndevlist[i], KVADDR, net_device_buf, + SIZE(net_device), "net_device buffer", + FAULT_ON_ERROR); + + fprintf(fp, "%s ", + mkstring(buf, flen, CENTER|RJUST|LONG_HEX, + MKSTR(ndevlist[i]))); + + get_device_name(ndevlist[i], buf); + fprintf(fp, "%-6s ", buf); + + get_device_address(ndevlist[i], buf); + fprintf(fp, "%s\n", buf); + } + + FREEBUF(ndevlist); + FREEBUF(net_device_buf); +} /* * Perform the actual work of dumping the ARP table... --- crash-4.0-6.1/symbols.c 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/symbols.c 2008-03-18 09:42:32.000000000 -0400 @@ -6618,6 +6618,8 @@ OFFSET(kmem_cache_cpu_page)); fprintf(fp, " kmem_cache_cpu_node: %ld\n", OFFSET(kmem_cache_cpu_node)); + fprintf(fp, " kmem_cache_flags: %ld\n", + OFFSET(kmem_cache_flags)); fprintf(fp, " net_device_next: %ld\n", OFFSET(net_device_next)); @@ -6629,6 +6631,11 @@ OFFSET(net_device_addr_len)); fprintf(fp, " net_device_ip_ptr: %ld\n", OFFSET(net_device_ip_ptr)); + fprintf(fp, " net_device_dev_list: %ld\n", + OFFSET(net_device_dev_list)); + fprintf(fp, " net_dev_base_head: %ld\n", + OFFSET(net_dev_base_head)); + fprintf(fp, " device_next: %ld\n", OFFSET(device_next)); fprintf(fp, " device_name: %ld\n", --- crash-4.0-6.1/defs.h 2008-03-31 13:31:29.000000000 -0400 +++ crash-4.0-6.2/defs.h 2008-03-28 16:04:28.000000000 -0400 @@ -1234,6 +1234,8 @@ long net_device_type; long net_device_addr_len; long net_device_ip_ptr; + long net_device_dev_list; + long net_dev_base_head; long device_next; long device_name; long device_type; @@ -1433,6 +1435,7 @@ long kmem_cache_cpu_freelist; long kmem_cache_cpu_page; long kmem_cache_cpu_node; + long kmem_cache_flags; long zone_nr_active; long zone_nr_inactive; long zone_all_unreclaimable;