Ken'ichi Ohmichi wrote: > Hi Dave, > > 2007/07/25 10:28:04 -0400, Dave Anderson <anderson@xxxxxxxxxx> wrote: > >>>Here is the patch for solving the problem. If the array number is not >>>taken, the crash utility assumes that it is the defined value NR_CPUS. >>>Or, should get_array_length() be fixed to get the array number from >>>init/main.c ? >>> >> >>Ken'ichi -- thanks for tracking that down. >> >>I don't see how get_array_length() can be "fixed" in this case -- if the >>vmlinux file doesn't have the info, it doesn't have it. I'm not sure >>what you mean by getting it from init/main.c? > > > Sorry for my insufficient explanation. > On linux-2.6.22, the external declaration of i386's __per_cpu_offset[] > is in include/asm-i386/percpu.h, and the definition of __per_cpu_offset[] > is in init/main.c: > > unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; > > > There are their debugging information in the dwarf section, and the > definition's one includes the array length. > I explain by following output of the dwarfdump command. > > * The debugging information of "extern unsigned long __per_cpu_offset[];" > There is not the attribute DW_AT_upper_bound and the crash utility cannot > get the array number. > <1><32685> DW_TAG_variable > DW_AT_name __per_cpu_offset > DW_AT_decl_file 83 include/asm/percpu.h > DW_AT_decl_line 48 > DW_AT_type <32674> > DW_AT_external yes(1) > DW_AT_declaration yes(1) > <1><32674> DW_TAG_array_type > DW_AT_sibling <32685> > DW_AT_type <83> > <2><32683> DW_TAG_subrange_type > > * The debugging information of "unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;" > There is the attribute DW_AT_upper_bound and the crash utility can do it. > <1><58437> DW_TAG_variable > DW_AT_name __per_cpu_offset > DW_AT_decl_file 1 init/main.c > DW_AT_decl_line 363 > DW_AT_type <33> > DW_AT_external yes(1) > DW_AT_location DW_OP_addr 0xc03fd400 > <1>< 33> DW_TAG_array_type > DW_AT_sibling <49> > DW_AT_type <56> > <2>< 42> DW_TAG_subrange_type > DW_AT_type <49> > DW_AT_upper_bound 31 <--- Here! > > > I thought get_array_length() should retry to get the array length from > the next if it could not get it. But I prefer your following idea because > it is simple and does not make other effects. I see. But as it stands now, the crash utility has no dwarfdump-like functions to pull out such data, but rather relies on gdb to do the dirty work. There's probably something in the gdb innards that could access it, but I'm not aware of it. But it's not that important... > > > >>How about using Cliff Wickman's new get_cpus_possible() function > >>from his LKCD_KERNTYPES patch? Since get_cpus_possible() returns 0 > >>on failure, your fix below should be left in place, but it might be >>worth also trying get_cpus_possible() if get_array_length() returns 0? > > > That sounds good, but I cannot find Cliff Wickman's patch (including > get_cpus_possible() function). Can I see his patch ? > It's already in crash 4.0-4.4,in kernel.c. But as it turns out, I don't think it's necessary either. Given that: 1. this is an x86-only issue, i.e., where it's declared as as an extern without an array index, 2. the NR_CPUS is relatively small, 3. the "__per_cpu_offset" array is (empirically) located long before "_end", 4. the data types that follow it are going to be populated with non-zero data, then there's virtually no chance it will bump into a non-existent page. I also thought of simply determining the difference between the address of "__per_cpu_offset" and the address of the symbol that follows it, and dividing that by the size of a long. Anyway, I've decided that I like your original patch. If it ever causes a problem in the future, it will be simple enough to fix. Thanks, Dave -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility