Ken'ichi Ohmichi wrote:
Hi Dave,
2007/07/25 10:28:04 -0400, Dave Anderson <anderson(a)redhat.com> 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