Hello Dave,
Glab to hear the capability is desirable. I will start to implement this 
soon.
At 2012-1-9 23:50, Dave Anderson wrote:
 ----- Original Message -----
> Hello Dave,
>
> I think it is necessary to see what is hided in the union where
> _mapcount lies. However, as you said, it's hard to pick which fields are
> more important than others when adding new items to "kmem -p". So I
> think over using struct sub-command to show what I want.
>
> What if I change struct sub-command to this:
>
> 1. it can refer to anonymous members (e.g., page._mapcount)
> 2. it can refer to submembers(e.g., page._count.counter)
> 3. it can output easy-parsing format (using an option to specify), maybe
> like 'kmem -p'. For example,
> crash>  struct page.flags,_count.counter -..<  PAGE_list.txt
>      1024    0
>      1024    1
>      1024    1
>      1024    1
>
> After adding these features to struct sub-command, I guess it is more
> easier to get information hiding in structs and parsing it. Before
> implementing, I feel the necessity to ask you for some advices. So what
> about these features?
 That would certainly be useful.  The problem in getting that to work
 would be twofold:
   (1) handling a "member" request that has a "." in it.
       crash>  struct page._count.counter ffffea0000000400
       struct: invalid format: page._count.counter
       crash>
   (2) getting a successful return value from the call to arg_to_datatype()
       in cmd_datatype_common().
       crash>  struct page.private ffffea0000000400
       struct: invalid data structure reference: page.private
       crash>
 And both of the above would require getting the get_member_data()
 function in gdb-7.3.1/gdb/symtab.c to dig out the information for
 anonymous members, which it currently does not do.
 In this part of get_member_data(), the requested member name string is
 searched for:
          for (i = 0; i<  nfields; i++) {
                  if (STREQ(req->member, nextfield->name)) {
                          req->member_offset = nextfield->loc.bitpos;
                          req->member_length = TYPE_LENGTH(nextfield->type);
                          req->member_typecode = TYPE_CODE(nextfield->type);
                          if ((req->member_typecode == TYPE_CODE_TYPEDEF)&&
                              (typedef_type = check_typedef(nextfield->type)))
                                  req->member_length = TYPE_LENGTH(typedef_type);
                          return;
                  }
                  nextfield++;
          }
 When get_member_data() walks through the page stucture, it does find the
 anonymous members above, but nextfield->name points to a NULL name string.
 That seems to be related to gdb's behavior when asking it to simply
 print a page structure, which is requested with a "ptype struct page"
 gdb command:
    crash>  struct page
    struct page {
        long unsigned int flags;
        struct address_space *mapping;
        struct {
            union {...};
            union {...};
        };
        struct list_head lru;
        union {
            long unsigned int private;
            spinlock_t ptl;
            struct kmem_cache *slab;
            struct page *first_page;
        };
    }
    SIZE: 64
    crash>
 I don't know how to get gdb to display the "full" structure declaration?
 Anyway, when given an internal request to display a page structure
 from memory, it does display them:
    crash>  page ffffea0000000400
    struct page {
      flags = 0,
      mapping = 0x0,
      {
        {
          index = 18446612132314288112,
          freelist = 0xffff880000010ff0
        },
        {
          counters = 4294967168,
          {
            {
              _mapcount = {
                counter = -128
              },
              {
                inuse = 65408,
                objects = 32767,
                frozen = 1
              }
            },
            _count = {
              counter = 0
            }
          }
        }
      },
      lru = {
        next = 0xffffea00000042a0,
        prev = 0xffffea00000005a0
      },
      {
        private = 1,
        ptl = {
          {
            rlock = {
              raw_lock = {
                slock = 1
              }
            }
          }
        },
        slab = 0x1,
        first_page = 0x1
      }
    }
    crash>
 And because that works OK, the ANON_MEMBER_OFFSET_REQUEST() macro
 exists to handle cases for required offset_table entries.
 Here, if I put a debug printf each time though the member loop
 in get_member_data(), you'll see this:
    crash>  page.slab ffffea0000000400
    page ->  flags
    page ->  mapping
    page ->
    page ->  lru
    page ->
    struct: invalid data structure reference: page.slab
    crash>
 which again, reflects what happens when a page struct is printed:
    crash>  struct page
    struct page {
        long unsigned int flags;
        struct address_space *mapping;
        struct {
            union {...};
            union {...};
        };
        struct list_head lru;
        union {
            long unsigned int private;
            spinlock_t ptl;
            struct kmem_cache *slab;
            struct page *first_page;
        };
    }
    SIZE: 64
    crash>
 So, anyway, I would presume that perhaps something could be applied to
 get_member_data() to and check out the fields with NULL name strings, i.e.:
            for (i = 0; i<  nfields; i++) {
                  if (STREQ(req->member, nextfield->name)) {
                          req->member_offset = nextfield->loc.bitpos;
                          req->member_length = TYPE_LENGTH(nextfield->type);
                          req->member_typecode = TYPE_CODE(nextfield->type);
                          if ((req->member_typecode == TYPE_CODE_TYPEDEF)&&
                              (typedef_type = check_typedef(nextfield->type)))
                                  req->member_length = TYPE_LENGTH(typedef_type);
                          return;
                  }
 +               if (strlen(nextfield->name) == 0) {
 +                       ...
 +               }
                  nextfield++;
            }
 And that section would have to somehow deal with members that are part
 of anonymous struct members (like "private"), as well as with anonymous
 members that are expressed with a "." in them (like "_mapcount.counter).
 I don't expect it will be very easy to accomplish.  But it would be a
 desirable capability, so please be my guest!
 Thanks,
    Dave
> At 2012-1-6 3:37, Dave Anderson wrote:
>> I appreciate the effort, but I'm not sure whether it's worth changing
>> it at this point, or whether it could be accomplished in a different
>> manner.
>>
>> The primary purpose for "kmem -p" is to show the page structure
>> address associated with each physical address in the system -- along
>> with "basic information about each page".  It's had those basic
>> fields in it forever -- which BTW, fit into 80 columns.  I prefer not
>> to have command output exceed 80 columns unless it is impossible to
>> predict the size of an output field.
>>
>> Anyway, the page structure definition keeps changing over time, more
>> specifically the embedded anonymous structures contained within it, and
>> the fields within the anonymous structs have multiple meanings.  With
>> your patch, the output becomes cluttered and hard to understand, especially
>> due to the strange values that can be seen in the MCNT column when it's
>> not a counter value, but rather a slab-page construct:
>>
>>           union {
>>                   atomic_t _mapcount;
>>
>>                   struct {
>>                           unsigned inuse:16;
>>                           unsigned objects:15;
>>                           unsigned frozen:1;
>>                   };
>>           };
>>
>> And so it's hard to pick which fields are more important than
>> others,
>> because it pretty much depends upon what's being debugged.  You
>> have
>> picked the private field (which can have numerous meanings), but
>> for
>> example, there have been times in the past where I wanted to see
>> the
>> lru list_head contents.
>>
>> That all being said, your patch does have merit, but I wonder if
>> there
>> could be an alternate way of selecting or filtering what fields are
>> displayed?
>
>
> --
> --
> Regards
> Qiao Nuohan
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
> 
https://www.redhat.com/mailman/listinfo/crash-utility
>
 --
 Crash-utility mailing list
 Crash-utility(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/crash-utility