[Crash-utility] [Patch] linux-2.6.22 on i386

Dave Anderson anderson at redhat.com
Fri Jul 27 13:15:27 UTC 2007


Ken'ichi Ohmichi wrote:
> Hi Dave,
> 
> 2007/07/25 10:28:04 -0400, Dave Anderson <anderson at 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





More information about the Crash-utility mailing list