memory.c task.c kernel.c ia64.c x86_64.c symbols.c defs.h --- crash-5.0.2/memory.c 2010-04-08 11:04:08.000000000 -0400 +++ crash-5.0.3/memory.c 2010-04-08 10:52:10.000000000 -0400 @@ -250,6 +250,10 @@ MEMBER_OFFSET_INIT(mm_struct_rss, "mm_struct", "_rss"); MEMBER_OFFSET_INIT(mm_struct_anon_rss, "mm_struct", "_anon_rss"); MEMBER_OFFSET_INIT(mm_struct_file_rss, "mm_struct", "_file_rss"); + if (!VALID_MEMBER(mm_struct_anon_rss)) { + MEMBER_OFFSET_INIT(mm_struct_rss_stat, "mm_struct", "rss_stat"); + MEMBER_OFFSET_INIT(mm_rss_stat_count, "mm_rss_stat", "count"); + } MEMBER_OFFSET_INIT(mm_struct_total_vm, "mm_struct", "total_vm"); MEMBER_OFFSET_INIT(mm_struct_start_code, "mm_struct", "start_code"); MEMBER_OFFSET_INIT(vm_area_struct_vm_mm, "vm_area_struct", "vm_mm"); @@ -1018,7 +1022,7 @@ addr = (ulonglong)sp->value; else { fprintf(fp, "symbol not found: %s\n", args[optind]); - fprintf(fp, "possible aternatives:\n"); + fprintf(fp, "possible alternatives:\n"); if (!symbol_query(args[optind], " ", NULL)) fprintf(fp, " (none found)\n"); return; @@ -1495,7 +1499,7 @@ addr = sp->value; else { fprintf(fp, "symbol not found: %s\n", args[optind]); - fprintf(fp, "possible aternatives:\n"); + fprintf(fp, "possible alternatives:\n"); if (!symbol_query(args[optind], " ", NULL)) fprintf(fp, " (none found)\n"); return; @@ -3454,6 +3458,26 @@ */ tm->rss = ULONG(tt->mm_struct + OFFSET(mm_struct_rss)); else { + /* + * Latest kernels have mm_struct.mm_rss_stat[]. + */ + if (VALID_MEMBER(mm_struct_rss_stat)) { + long anonpages, filepages; + + if (!enumerator_value("MM_FILEPAGES", &filepages) || + !enumerator_value("MM_ANONPAGES", &anonpages)) { + filepages = 0; + anonpages = 1; + } + tm->rss += ULONG(tt->mm_struct + + OFFSET(mm_struct_rss_stat) + + OFFSET(mm_rss_stat_count) + + (filepages * sizeof(ulong))); + tm->rss += ULONG(tt->mm_struct + + OFFSET(mm_struct_rss_stat) + + OFFSET(mm_rss_stat_count) + + (anonpages * sizeof(ulong))); + } /* * mm_struct._anon_rss and mm_struct._file_rss should exist. */ @@ -5015,8 +5039,7 @@ if (!vt->page_hash_table) { if (hi->flags & VERBOSE) - error(FATAL, - "address_space page cache radix tree not supported\n"); + option_not_supported('C'); if (symbol_exists("nr_pagecache")) { buffer_pages = nr_blockdev_pages(); @@ -5025,11 +5048,9 @@ page_cache_size -= buffer_pages; fprintf(fp, "page cache size: %ld\n", page_cache_size); if (hi->flags & ADDRESS_SPECIFIED) - error(INFO, - "address_space page cache radix tree not supported: %lx: ignored\n", - hi->spec_addr); + option_not_supported('c'); } else - error(FATAL, "cannot determine page cache size\n"); + option_not_supported('c'); return; } @@ -11553,8 +11574,8 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) { int i, j; - int flags, swap_device, pages, prio, usedswap; - ulong swap_file, max, swap_map, pct; + int swap_device, pages, prio, usedswap; + ulong flags, swap_file, max, swap_map, pct; ulong vfsmnt; ulong swap_info, swap_info_ptr; ushort *smap; @@ -11590,8 +11611,12 @@ } else fill_swap_info(swap_info); - flags = INT(vt->swap_info_struct + - OFFSET(swap_info_struct_flags)); + if (MEMBER_SIZE("swap_info_struct", "flags") == sizeof(uint)) + flags = UINT(vt->swap_info_struct + + OFFSET(swap_info_struct_flags)); + else + flags = ULONG(vt->swap_info_struct + + OFFSET(swap_info_struct_flags)); if (!(flags & SWP_USED)) continue; @@ -13030,14 +13055,13 @@ } } - if ((mem_sec[SECTION_NR_TO_ROOT(nr)] == 0) || - !IS_KVADDR(mem_sec[SECTION_NR_TO_ROOT(nr)])) - return 0; - - if (IS_SPARSEMEM_EX()) + if (IS_SPARSEMEM_EX()) { + if ((mem_sec[SECTION_NR_TO_ROOT(nr)] == 0) || + !IS_KVADDR(mem_sec[SECTION_NR_TO_ROOT(nr)])) + return 0; addr = mem_sec[SECTION_NR_TO_ROOT(nr)] + (nr & SECTION_ROOT_MASK()) * SIZE(mem_section); - else + } else addr = symbol_value("mem_section") + (SECTIONS_PER_ROOT() * SECTION_NR_TO_ROOT(nr) + (nr & SECTION_ROOT_MASK())) * SIZE(mem_section); @@ -13558,7 +13582,7 @@ struct stat stat; char *namebuf, *nameptr; - if (!(sp = symbol_search("per_cpu__page_states"))) { + if (!(sp = per_cpu_symbol_search("per_cpu__page_states"))) { if (CRASHDEBUG(1)) error(INFO, "per_cpu__page_states" "not available in this kernel\n"); @@ -13666,7 +13690,7 @@ events = (ulong *)GETBUF((sizeof(ulong) * vt->nr_vm_event_items) * 2); cumulative = &events[vt->nr_vm_event_items]; - sp = symbol_search("per_cpu__vm_event_states"); + sp = per_cpu_symbol_search("per_cpu__vm_event_states"); for (c = 0; c < kt->cpus; c++) { addr = sp->value + kt->__per_cpu_offset[c]; @@ -13704,7 +13728,7 @@ return TRUE; if ((vt->nr_vm_event_items == -1) || - !symbol_exists("per_cpu__vm_event_states")) + !per_cpu_symbol_search("per_cpu__vm_event_states")) goto bailout; if (!enumerator_value("NR_VM_EVENT_ITEMS", &count)) --- crash-5.0.2/task.c 2010-04-08 11:04:08.000000000 -0400 +++ crash-5.0.3/task.c 2010-04-01 16:47:43.000000000 -0400 @@ -479,6 +479,7 @@ { int i; char *thread_info_buf; + struct syment *hard_sp, *soft_sp; if (!(tt->hardirq_ctx = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) error(FATAL, "cannot malloc hardirq_ctx space."); @@ -491,23 +492,21 @@ thread_info_buf = GETBUF(SIZE(irq_ctx)); - if (symbol_exists("hardirq_ctx")) { - i = get_array_length("hardirq_ctx", NULL, 0); - get_symbol_data("hardirq_ctx", - sizeof(long)*(i <= NR_CPUS ? i : NR_CPUS), - &tt->hardirq_ctx[0]); - } else if (symbol_exists("per_cpu__hardirq_ctx")) { + if ((hard_sp = per_cpu_symbol_search("per_cpu__hardirq_ctx"))) { if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { for (i = 0; i < NR_CPUS; i++) { if (!kt->__per_cpu_offset[i]) continue; - tt->hardirq_ctx[i] = - symbol_value("per_cpu__hardirq_ctx") + + tt->hardirq_ctx[i] = hard_sp->value + kt->__per_cpu_offset[i]; } } else - tt->hardirq_ctx[0] = - symbol_value("per_cpu__hardirq_ctx"); + tt->hardirq_ctx[0] = hard_sp->value; + } else if (symbol_exists("hardirq_ctx")) { + i = get_array_length("hardirq_ctx", NULL, 0); + get_symbol_data("hardirq_ctx", + sizeof(long)*(i <= NR_CPUS ? i : NR_CPUS), + &tt->hardirq_ctx[0]); } else error(WARNING, "cannot determine hardirq_ctx addresses\n"); @@ -527,23 +526,21 @@ ULONG(thread_info_buf+OFFSET(thread_info_task)); } - if (symbol_exists("softirq_ctx")) { - i = get_array_length("softirq_ctx", NULL, 0); - get_symbol_data("softirq_ctx", - sizeof(long)*(i <= NR_CPUS ? i : NR_CPUS), - &tt->softirq_ctx[0]); - } else if (symbol_exists("per_cpu__softirq_ctx")) { + if ((soft_sp = per_cpu_symbol_search("per_cpu__softirq_ctx"))) { if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { for (i = 0; i < NR_CPUS; i++) { if (!kt->__per_cpu_offset[i]) continue; - tt->softirq_ctx[i] = - symbol_value("per_cpu__softirq_ctx") + + tt->softirq_ctx[i] = soft_sp->value + kt->__per_cpu_offset[i]; } } else - tt->softirq_ctx[0] = - symbol_value("per_cpu__softirq_ctx"); + tt->softirq_ctx[0] = soft_sp->value; + } else if (symbol_exists("softirq_ctx")) { + i = get_array_length("softirq_ctx", NULL, 0); + get_symbol_data("softirq_ctx", + sizeof(long)*(i <= NR_CPUS ? i : NR_CPUS), + &tt->softirq_ctx[0]); } else error(WARNING, "cannot determine softirq_ctx addresses\n"); @@ -6107,20 +6104,20 @@ int i, cnt; ulong runq, runqaddr; char *runqbuf; + struct syment *rq_sp; BZERO(tasklist, sizeof(ulong) * NR_CPUS); runqbuf = NULL; cnt = 0; - if (symbol_exists("per_cpu__runqueues") && + if ((rq_sp = per_cpu_symbol_search("per_cpu__runqueues")) && VALID_MEMBER(runqueue_idle)) { runqbuf = GETBUF(SIZE(runqueue)); for (i = 0; i < nr_cpus; i++) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - runq = symbol_value("per_cpu__runqueues") + - kt->__per_cpu_offset[i]; - } else - runq = symbol_value("per_cpu__runqueues"); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + runq = rq_sp->value + kt->__per_cpu_offset[i]; + else + runq = rq_sp->value; readmem(runq, KVADDR, runqbuf, SIZE(runqueue), "runqueues entry (per_cpu)", @@ -6254,26 +6251,25 @@ int get_active_set(void) { - int i, cnt, per_cpu; + int i, cnt; ulong runq, runqaddr; char *runqbuf; + struct syment *rq_sp; if (tt->flags & ACTIVE_SET) return TRUE; - per_cpu = FALSE; - - if (symbol_exists("runqueues")) { - runq = symbol_value("runqueues"); - per_cpu = FALSE; - } else if (symbol_exists("per_cpu__runqueues")) { - runq = symbol_value("per_cpu__runqueues"); - per_cpu = TRUE; - } else if (OPENVZ()) - runq = symbol_value("pcpu_info"); - else - return FALSE; + runq = 0; + rq_sp = per_cpu_symbol_search("per_cpu__runqueues"); + if (!rq_sp) { + if (symbol_exists("runqueues")) + runq = symbol_value("runqueues"); + else if (OPENVZ()) + runq = symbol_value("pcpu_info"); + else + return FALSE; + } if (!tt->active_set && !(tt->active_set = (ulong *)calloc(NR_CPUS, sizeof(ulong)))) @@ -6304,13 +6300,12 @@ } FREEBUF(pcpu_info_buf); FREEBUF(vcpu_struct_buf); - } else if (VALID_MEMBER(runqueue_curr) && per_cpu) { + } else if (VALID_MEMBER(runqueue_curr) && rq_sp) { for (i = 0; i < kt->cpus; i++) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - runq = symbol_value("per_cpu__runqueues") + - kt->__per_cpu_offset[i]; - } else - runq = symbol_value("per_cpu__runqueues"); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + runq = rq_sp->value + kt->__per_cpu_offset[i]; + else + runq = rq_sp->value; readmem(runq, KVADDR, runqbuf, SIZE(runqueue), "active runqueues entry (per_cpu)", @@ -6661,7 +6656,7 @@ next = runqueue_head = symbol_value("init_task_union"); } else error(FATAL, - "cannot determine run queue structures being used\n"); + "cannot determine run queue structures\n"); cnt = 0; do { @@ -6707,29 +6702,27 @@ char *runqbuf; ulong active, expired, arrays; struct task_context *tc; - int per_cpu; + struct syment *rq_sp; - if (symbol_exists("runqueues")) { - runq = symbol_value("runqueues"); - per_cpu = FALSE; - } else if (symbol_exists("per_cpu__runqueues")) { - runq = symbol_value("per_cpu__runqueues"); - per_cpu = TRUE; - } else { - runq = 0; - per_cpu = FALSE; - } + runq = 0; + + rq_sp = per_cpu_symbol_search("per_cpu__runqueues"); + if (!rq_sp) { + if (symbol_exists("runqueues")) + runq = symbol_value("runqueues"); + else + error(FATAL, "cannot determine run queue structures\n"); + } get_active_set(); runqbuf = GETBUF(SIZE(runqueue)); for (cpu = 0; cpu < kt->cpus; cpu++, runq += SIZE(runqueue)) { - if (per_cpu) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - runq = symbol_value("per_cpu__runqueues") + - kt->__per_cpu_offset[cpu]; - } else - runq = symbol_value("per_cpu__runqueues"); + if (rq_sp) { + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + runq = rq_sp->value + kt->__per_cpu_offset[cpu]; + else + runq = rq_sp->value; } fprintf(fp, "%sCPU %d RUNQUEUE: %lx\n", cpu ? "\n" : "", @@ -6937,6 +6930,7 @@ long nr_running, cfs_rq_nr_running; struct rb_root *root; struct rb_node *node; + struct syment *rq_sp, *init_sp; if (!VALID_STRUCT(cfs_rq)) { STRUCT_SIZE_INIT(cfs_rq, "cfs_rq"); @@ -6956,23 +6950,22 @@ "prio"); } - if (!symbol_exists("per_cpu__runqueues")) - error(FATAL, "per_cpu__runqueues does not exist\n"); - - runq = symbol_value("per_cpu__runqueues"); + if (!(rq_sp = per_cpu_symbol_search("per_cpu__runqueues"))) + error(FATAL, "per-cpu runqueues does not exist\n"); runqbuf = GETBUF(SIZE(runqueue)); - cfs_rq_buf = symbol_exists("per_cpu__init_cfs_rq") ? - GETBUF(SIZE(cfs_rq)) : NULL; + if ((init_sp = per_cpu_symbol_search("per_cpu__init_cfs_rq"))) + cfs_rq_buf = GETBUF(SIZE(cfs_rq)); + else + cfs_rq_buf = NULL; get_active_set(); for (cpu = 0; cpu < kt->cpus; cpu++) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - runq = symbol_value("per_cpu__runqueues") + - kt->__per_cpu_offset[cpu]; - } else - runq = symbol_value("per_cpu__runqueues"); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + runq = rq_sp->value + kt->__per_cpu_offset[cpu]; + else + runq = rq_sp->value; fprintf(fp, "%sCPU %d RUNQUEUE: %lx\n", cpu ? "\n" : "", cpu, runq); @@ -6991,11 +6984,10 @@ /* * Use default task group's cfs_rq on each cpu. */ - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - cfs_rq = symbol_value("per_cpu__init_cfs_rq") + - kt->__per_cpu_offset[cpu]; - } else - cfs_rq = symbol_value("per_cpu__init_cfs_rq"); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + cfs_rq = init_sp->value + kt->__per_cpu_offset[cpu]; + else + cfs_rq = init_sp->value; readmem(cfs_rq, KVADDR, cfs_rq_buf, SIZE(cfs_rq), "per-cpu cfs_rq", FAULT_ON_ERROR); --- crash-5.0.2/kernel.c 2010-04-08 11:04:08.000000000 -0400 +++ crash-5.0.3/kernel.c 2010-04-05 10:43:28.000000000 -0400 @@ -1193,7 +1193,7 @@ req->flags |= GNU_FUNCTION_ONLY; } else { fprintf(fp, "symbol not found: %s\n", args[optind]); - fprintf(fp, "possible aternatives:\n"); + fprintf(fp, "possible alternatives:\n"); if (!symbol_query(args[optind], " ", NULL)) fprintf(fp, " (none found)\n"); FREEBUF(req->buf); @@ -5266,13 +5266,13 @@ int flen, tdx, old_timers_exist; struct tv_range tv[TVN]; - if (symbol_exists("tvec_bases")) { - dump_timer_data_tvec_bases_v1(); - return; - } else if (symbol_exists("per_cpu__tvec_bases")) { + if (per_cpu_symbol_search("per_cpu__tvec_bases")) { dump_timer_data_tvec_bases_v2(); return; - } + } else if (symbol_exists("tvec_bases")) { + dump_timer_data_tvec_bases_v1(); + return; + } BZERO(tv, sizeof(struct tv_range) * TVN); @@ -5538,6 +5538,7 @@ ulong *vec, jiffies, highest, function; ulong tvec_bases; long count; + struct syment *sp; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; @@ -5605,11 +5606,11 @@ qsort(td, tdx, sizeof(struct timer_data), compare_timer_data); + sp = per_cpu_symbol_search("per_cpu__tvec_bases"); if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) - tvec_bases = symbol_value("per_cpu__tvec_bases") + - kt->__per_cpu_offset[cpu]; + tvec_bases = sp->value + kt->__per_cpu_offset[cpu]; else - tvec_bases = symbol_value("per_cpu__tvec_bases"); + tvec_bases = sp->value; if (symbol_exists("boot_tvec_bases")) { readmem(tvec_bases, KVADDR, &tvec_bases, sizeof(void *), @@ -5690,6 +5691,7 @@ init_tv_ranges(struct tv_range *tv, int vec_root_size, int vec_size, int cpu) { ulong tvec_bases; + struct syment *sp; if (kt->flags & TVEC_BASES_V1) { tv[1].base = symbol_value("tvec_bases") + @@ -5709,11 +5711,11 @@ tv[5].base = tv[4].end; tv[5].end = tv[5].base + SIZE(tvec_s); } else if (kt->flags & TVEC_BASES_V2) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) - tvec_bases = symbol_value("per_cpu__tvec_bases") + - kt->__per_cpu_offset[cpu]; + sp = per_cpu_symbol_search("per_cpu__tvec_bases"); + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + tvec_bases = sp->value + kt->__per_cpu_offset[cpu]; else - tvec_bases = symbol_value("per_cpu__tvec_bases"); + tvec_bases = sp->value; if (symbol_exists("boot_tvec_bases")) { readmem(tvec_bases, KVADDR, &tvec_bases, sizeof(void *), --- crash-5.0.2/ia64.c 2010-04-08 11:04:08.000000000 -0400 +++ crash-5.0.3/ia64.c 2010-04-05 11:01:31.000000000 -0400 @@ -2359,15 +2359,15 @@ int cpu; ulong cpu_data; int array_location_known; + struct syment *sp; if (!(cpu_data = machdep->machspec->cpu_data_address)) { error(FATAL, "cannot find cpuinfo_ia64 location\n"); return; } - array_location_known = symbol_exists("cpu_data") || - symbol_exists("_cpu_data") || - symbol_exists("per_cpu__cpu_info"); + array_location_known = per_cpu_symbol_search("per_cpu__cpu_info") || + symbol_exists("cpu_data") || symbol_exists("_cpu_data"); for (cpu = 0; cpu < kt->cpus; cpu++) { fprintf(fp, "%sCPU %d: %s\n", cpu ? "\n" : "", cpu, @@ -2377,12 +2377,11 @@ if (!array_location_known) break; - if (symbol_exists("per_cpu__cpu_info")) { - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - cpu_data = - symbol_value("per_cpu__cpu_info") + - kt->__per_cpu_offset[cpu+1]; - } else + if ((sp = per_cpu_symbol_search("per_cpu__cpu_info"))) { + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + cpu_data = sp->value + + kt->__per_cpu_offset[cpu+1]; + else break; /* we've already done cpu 0 */ } else cpu_data += SIZE(cpuinfo_ia64); @@ -2843,6 +2842,7 @@ { struct machine_specific *ms; struct gnu_request req; + struct syment *sp; ulong flag; ms = &ia64_machine_specific; @@ -2887,15 +2887,13 @@ &ms->cpu_data_address); else if (symbol_exists("cpu_data")) ms->cpu_data_address = symbol_value("cpu_data"); - else if (symbol_exists("per_cpu__cpu_info")) - if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { - ms->cpu_data_address = - symbol_value("per_cpu__cpu_info") + - kt->__per_cpu_offset[0]; - } else - ms->cpu_data_address = - symbol_value("per_cpu__cpu_info"); - else { + else if ((sp = per_cpu_symbol_search("per_cpu__cpu_info"))) { + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) + ms->cpu_data_address = sp->value + + kt->__per_cpu_offset[0]; + else + ms->cpu_data_address = sp->value; + } else { error(WARNING, "cannot find cpuinfo_ia64 location\n"); ms->cpu_data_address = 0; } --- crash-5.0.2/x86_64.c 2010-04-08 11:04:06.000000000 -0400 +++ crash-5.0.3/x86_64.c 2010-04-01 15:17:47.000000000 -0400 @@ -798,40 +798,42 @@ { int i, cpus, cpunumber; struct machine_specific *ms; + struct syment *irq_sp, *curr_sp, *cpu_sp; ms = machdep->machspec; + irq_sp = per_cpu_symbol_search("per_cpu__irq_stack_union"); + cpu_sp = per_cpu_symbol_search("per_cpu__cpu_number"); + curr_sp = per_cpu_symbol_search("per_cpu__current_task"); + if (!(kt->flags & PER_CPU_OFF)) { /* * Presume kernel is !CONFIG_SMP. */ - if (symbol_exists("per_cpu__irq_stack_union")) { - ms->stkinfo.ibase[0] = - symbol_value("per_cpu__irq_stack_union"); + if (irq_sp) { + ms->stkinfo.ibase[0] = irq_sp->value; if ((ms->stkinfo.isize = MEMBER_SIZE("irq_stack_union", "irq_stack")) <= 0) ms->stkinfo.isize = 16384; } - if (DUMPFILE() && symbol_exists("per_cpu__current_task")) { + if (DUMPFILE() && curr_sp) { if (!(ms->current = calloc(kt->cpus, sizeof(ulong)))) error(FATAL, "cannot calloc" " %d x86_64 current pointers!\n", kt->cpus); - get_symbol_data("per_cpu__current_task", sizeof(ulong), + get_symbol_data(curr_sp->name, sizeof(ulong), &ms->current[0]); } return; } - if (!symbol_exists("per_cpu__cpu_number") || - !symbol_exists("per_cpu__irq_stack_union")) + if (!cpu_sp || !irq_sp) return; for (i = cpus = 0; i < NR_CPUS; i++) { - if (!readmem(symbol_value("per_cpu__cpu_number") + - kt->__per_cpu_offset[i], + if (!readmem(cpu_sp->value + kt->__per_cpu_offset[i], KVADDR, &cpunumber, sizeof(int), "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) break; @@ -840,9 +842,7 @@ break; cpus++; - ms->stkinfo.ibase[i] = - symbol_value("per_cpu__irq_stack_union") + - kt->__per_cpu_offset[i]; + ms->stkinfo.ibase[i] = irq_sp->value + kt->__per_cpu_offset[i]; } if ((ms->stkinfo.isize = @@ -861,15 +861,14 @@ else kt->cpus = cpus; - if (DUMPFILE() && symbol_exists("per_cpu__current_task")) { + if (DUMPFILE() && curr_sp) { if ((ms->current = calloc(kt->cpus, sizeof(ulong))) == NULL) error(FATAL, "cannot calloc %d x86_64 current pointers!\n", kt->cpus); for (i = 0; i < kt->cpus; i++) - if (!readmem(symbol_value("per_cpu__current_task") + - kt->__per_cpu_offset[i], KVADDR, - &ms->current[i], sizeof(ulong), + if (!readmem(curr_sp->value + kt->__per_cpu_offset[i], + KVADDR, &ms->current[i], sizeof(ulong), "current_task (per_cpu)", RETURN_ON_ERROR)) continue; } @@ -898,10 +897,13 @@ ulong vaddr, offset; ulong init_tss; struct machine_specific *ms; - struct syment *sp; + struct syment *boot_sp, *tss_sp, *ist_sp; ms = machdep->machspec; - if (symbol_exists("init_tss")) { + tss_sp = per_cpu_symbol_search("per_cpu__init_tss"); + ist_sp = per_cpu_symbol_search("per_cpu__orig_ist"); + + if (!tss_sp && symbol_exists("init_tss")) { init_tss = symbol_value("init_tss"); for (c = cpus = 0; c < NR_CPUS; c++) { @@ -913,15 +915,14 @@ if (ms->stkinfo.ebase[c][0] == 0) break; } - } else if (symbol_exists("per_cpu__init_tss")) { + } else if (tss_sp) { for (c = 0; c < kt->cpus; c++) { if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { if (kt->__per_cpu_offset[c] == 0) break; - vaddr = symbol_value("per_cpu__init_tss") + - kt->__per_cpu_offset[c]; + vaddr = tss_sp->value + kt->__per_cpu_offset[c]; } else - vaddr = symbol_value("per_cpu__init_tss"); + vaddr = tss_sp->value; vaddr += OFFSET(tss_struct_ist); @@ -933,16 +934,15 @@ break; } - if (symbol_exists("per_cpu__orig_ist")) { + if (ist_sp) { for (c = 0; c < kt->cpus; c++) { ulong estacks[MAX_EXCEPTION_STACKS]; if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { if (kt->__per_cpu_offset[c] == 0) break; - vaddr = symbol_value("per_cpu__orig_ist") + - kt->__per_cpu_offset[c]; + vaddr = ist_sp->value + kt->__per_cpu_offset[c]; } else - vaddr = symbol_value("per_cpu__orig_ist"); + vaddr = ist_sp->value; readmem(vaddr, KVADDR, &estacks[0], sizeof(ulong) * MAX_EXCEPTION_STACKS, @@ -993,16 +993,15 @@ * Sanity check cpu 0's first exception stack, which should be * located at: &boot_exception_stacks[0] */ - sp = value_search(ms->stkinfo.ebase[0][0], &offset); - if (!sp || offset || !STREQ(sp->name, "boot_exception_stacks")) { - if (symbol_exists("boot_exception_stacks")) { + boot_sp = value_search(ms->stkinfo.ebase[0][0], &offset); + if (!boot_sp || offset || + !STREQ(boot_sp->name, "boot_exception_stacks")) { + if ((boot_sp = symbol_search("boot_exception_stacks"))) { error(WARNING, "cpu 0 first exception stack: %lx\n boot_exception_stacks: %lx\n\n", - ms->stkinfo.ebase[0][0], - symbol_value("boot_exception_stacks")); + ms->stkinfo.ebase[0][0], boot_sp->value); if (!ms->stkinfo.ebase[0][0]) - ms->stkinfo.ebase[0][0] = - symbol_value("boot_exception_stacks"); + ms->stkinfo.ebase[0][0] = boot_sp->value; } else if (STRUCT_EXISTS("x8664_pda")) error(WARNING, "boot_exception_stacks: symbol does not exist in this kernel!\n"); @@ -1975,6 +1974,8 @@ if (STRNEQ(name, "per_cpu") || STREQ(name, "__per_cpu_end")) return TRUE; + if (type == 'V') + return TRUE; } return FALSE; @@ -4292,18 +4293,18 @@ int i, cpus, nr_pda, cpunumber, _cpu_pda, _boot_cpu_pda; char *cpu_pda_buf; ulong level4_pgt, cpu_pda_addr; + struct syment *sp; if (!VALID_STRUCT(x8664_pda)) { - if (!(kt->flags & PER_CPU_OFF) || - !symbol_exists("per_cpu__cpu_number")) + if (!(sp = per_cpu_symbol_search("per_cpu__cpu_number")) || + !(kt->flags & PER_CPU_OFF)) return 1; for (i = cpus = 0; i < NR_CPUS; i++) { if (kt->__per_cpu_offset[i] == 0) break; - if (!readmem(symbol_value("per_cpu__cpu_number") + - kt->__per_cpu_offset[i], KVADDR, - &cpunumber, sizeof(int), + if (!readmem(sp->value + kt->__per_cpu_offset[i], + KVADDR, &cpunumber, sizeof(int), "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) break; if (cpunumber != cpus) @@ -4441,23 +4442,23 @@ static void x86_64_display_cpu_data(void) { - int cpu, cpus, boot_cpu, _cpu_pda, per_cpu; + int cpu, cpus, boot_cpu, _cpu_pda; ulong cpu_data; ulong cpu_pda, cpu_pda_addr; + struct syment *per_cpu; boot_cpu = _cpu_pda = FALSE; cpu_data = cpu_pda = 0; cpus = 0; - per_cpu = FALSE; + per_cpu = NULL; if (symbol_exists("cpu_data")) { cpu_data = symbol_value("cpu_data"); cpus = kt->cpus; boot_cpu = FALSE; - } else if (symbol_exists("per_cpu__cpu_info")) { + } else if ((per_cpu = per_cpu_symbol_search("per_cpu__cpu_info"))) { cpus = kt->cpus; boot_cpu = FALSE; - per_cpu = TRUE; } else if (symbol_exists("boot_cpu_data")) { cpu_data = symbol_value("boot_cpu_data"); boot_cpu = TRUE; @@ -4478,8 +4479,7 @@ fprintf(fp, "%sCPU %d:\n", cpu ? "\n" : "", cpu); if (per_cpu) - cpu_data = symbol_value("per_cpu__cpu_info") + - kt->__per_cpu_offset[cpu]; + cpu_data = per_cpu->value + kt->__per_cpu_offset[cpu]; dump_struct("cpuinfo_x86", cpu_data, 0); --- crash-5.0.2/symbols.c 2010-04-08 11:04:07.000000000 -0400 +++ crash-5.0.3/symbols.c 2010-04-06 12:07:23.000000000 -0400 @@ -822,6 +822,11 @@ for (sp = st->symtable; sp < st->symend; sp++) symname_hash_install(sp); + + if ((sp = symbol_search("__per_cpu_start"))) + st->__per_cpu_start = sp->value; + if ((sp = symbol_search("__per_cpu_end"))) + st->__per_cpu_end = sp->value; } /* @@ -2348,6 +2353,13 @@ value_symbol(st->first_ksymbol) : ""); } else fprintf(fp, "(unused)\n"); + if (st->__per_cpu_start || st->__per_cpu_end) { + fprintf(fp, " __per_cpu_start: %lx\n", st->__per_cpu_start); + fprintf(fp, " __per_cpu_end: %lx\n", st->__per_cpu_end); + } else { + fprintf(fp, " __per_cpu_start: (unused)\n"); + fprintf(fp, " __per_cpu_end: (unused)\n"); + } fprintf(fp, " symval_hash[%d]: %lx\n", SYMVAL_HASH, (ulong)&st->symval_hash[0]); @@ -4053,6 +4065,51 @@ } /* + * Determine whether a per-cpu symbol exists. + + * The old-style per-cpu symbol names were pre-pended with + * "per_cpu__", whereas the new-style ones (as of 2.6.34) + * are not. This function allows the symbol argument to + * use either the old- or new-sytle format, and find either + * type. + */ +struct syment * +per_cpu_symbol_search(char *symbol) +{ + struct syment *sp; + char old[BUFSIZE]; + char *new; + + if (STRNEQ(symbol, "per_cpu__")) { + if ((sp = symbol_search(symbol))) + return sp; + new = symbol + strlen("per_cpu__"); + if ((sp = symbol_search(new))) { + if ((sp->type == 'V') || + ((sp->value >= st->__per_cpu_start) && + (sp->value < st->__per_cpu_end))) + return sp; + } + } else { + if ((sp = symbol_search(symbol))) { + if ((sp->type == 'V') || + ((sp->value >= st->__per_cpu_start) && + (sp->value < st->__per_cpu_end))) + return sp; + } + + sprintf(old, "per_cpu__%s", symbol); + if ((sp = symbol_search(old))) + return sp; + } + + if (CRASHDEBUG(1)) + error(INFO, "per_cpu_symbol_search(%s): NULL\n", symbol); + + return NULL; +} + +/* * Determine whether a static kernel symbol exists. */ int @@ -4643,7 +4700,7 @@ aflag++; } else { fprintf(fp, "symbol not found: %s\n", args[optind]); - fprintf(fp, "possible aternatives:\n"); + fprintf(fp, "possible alternatives:\n"); if (!symbol_query(args[optind], " ", NULL)) fprintf(fp, " (none found)\n"); goto freebuf; @@ -5159,7 +5216,7 @@ cmd_p(void) { int c; - struct syment *sp; + struct syment *sp, *percpu_sp; unsigned restore_radix; int leader, do_load_module_filter, success; char buf1[BUFSIZE]; @@ -5198,7 +5255,8 @@ cmd_usage(pc->curcmd, SYNOPSIS); if ((sp = symbol_search(args[optind])) && !args[optind+1]) { - if (STRNEQ(sp->name, "per_cpu__") && display_per_cpu_info(sp)) + if ((percpu_sp = per_cpu_symbol_search(args[optind])) && + display_per_cpu_info(percpu_sp)) return; sprintf(buf2, "%s = ", args[optind]); leader = strlen(buf2); @@ -6397,6 +6455,10 @@ OFFSET(mm_struct_env_start)); fprintf(fp, " mm_struct_env_end: %ld\n", OFFSET(mm_struct_env_end)); + fprintf(fp, " mm_struct_rss_stat: %ld\n", + OFFSET(mm_struct_rss_stat)); + fprintf(fp, " mm_rss_stat_count: %ld\n", + OFFSET(mm_rss_stat_count)); fprintf(fp, " vm_area_struct_vm_mm: %ld\n", OFFSET(vm_area_struct_vm_mm)); --- crash-5.0.2/defs.h 2010-04-08 11:04:08.000000000 -0400 +++ crash-5.0.3/defs.h 2010-04-06 14:05:20.000000000 -0400 @@ -1497,6 +1497,8 @@ long module_sections_attrs; long swap_info_struct_inuse_pages; long s390_lowcore_psw_save_area; + long mm_struct_rss_stat; + long mm_rss_stat_count; }; struct size_table { /* stash of commonly-used sizes */ @@ -1939,6 +1941,8 @@ off_t dwarf_eh_frame_file_offset; ulong dwarf_eh_frame_size; ulong first_ksymbol; + ulong __per_cpu_start; + ulong __per_cpu_end; }; /* flags for st */ @@ -3387,6 +3391,7 @@ char *value_symbol(ulong); ulong symbol_value(char *); ulong symbol_value_module(char *, char *); +struct syment *per_cpu_symbol_search(char *); int symbol_exists(char *s); int kernel_symbol_exists(char *s); int get_syment_array(char *, struct syment **, int);