[Crash-utility] kmem -s issue (gdb can't get offest of struct page lru member)

Michael Holzheu holzheu at linux.vnet.ibm.com
Mon Jan 9 18:00:28 UTC 2012


Hello Dave,

When issuing "kmem -s" with crash 6.0.2 (same with 6.0.0) on a s390x
linux-3.2 kernel dump, I get the following:

...
1ff0a600         signal_cache            1104        112       150      6    32k
1ff0a540         sighand_cache           2088         82        98      7    32k

kmem: invalid structure member offset: page_lru
      FILE: memory.c  LINE: 15856  FUNCTION: count_partial()

[./crash] error trace: 80099674 => 80097156 => 80083c40 => 801206ba

  801206ba: OFFSET_verify+138
  80083c40: get_kmem_cache_slub_data+1028
  80097156: dump_kmem_cache_slub+902
  80099674: cmd_kmem+6636

kmem: invalid structure member offset: page_lru
      FILE: memory.c  LINE: 15856  FUNCTION: count_partial()



I think the reason is that MEMBER_OFFSET_INIT(page_lru, "page", "lru") fails.
See the following gdb session:


Breakpoint 1, vm_init () at memory.c:375
375             MEMBER_OFFSET_INIT(page_lru, "page", "lru");
(gdb) s
datatype_info (name=0x80415c4a "page", member=0x803ce36c "lru", dm=0x0)
    at symbols.c:4919
4919            if (dm == ANON_MEMBER_OFFSET_REQUEST)
(gdb) n
4922            strcpy(buf, name);
(gdb) n
4924            req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
(gdb) n
4925            req->command = GNU_GET_DATATYPE;
(gdb) n
4926            req->flags |= GNU_RETURN_ON_ERROR;
(gdb) n
4927            req->name = buf;
(gdb) n
4928            req->member = member;
(gdb) n
4929            req->fp = pc->nullfp;
(gdb) n
4931            gdb_interface(req);
(gdb) n
4932            if (req->flags & GNU_COMMAND_FAILED) {
(gdb) print *req
$1 = {command = 5, buf = 0x0, fp = 0x8060d540, addr = 0, addr2 = 0, count = 0, 
  flags = 8, name = 0x3ffffffda94 "page", length = 56, typecode = 3, 
  typename = 0x0, target_typename = 0x0, target_length = 0, 
  target_typecode = 0, is_typedef = 0, member = 0x803ce36c "lru", 
  member_offset = -1, member_length = 0, member_typecode = 0, value = 0, 
  tagname = 0x0, pc = 0, sp = 0, ra = 0, curframe = 0, frame = 0, prevsp = 0, 
  prevpc = 0, lastsp = 0, task = 0, debug = 0, hookp = 0x0}

---> member_offset = -1

(gdb) n
4937            if (!req->typecode) {
(gdb) n
4942            if (!req->typecode) {
(gdb) n
4947            member_typecode = TYPE_CODE_UNDEF;
(gdb) n
4948            member_size = 0;
(gdb) n
4949            type_found = 0;
(gdb) n
4951            if (CRASHDEBUG(2)) {
(gdb) n
4965            switch (req->typecode)
(gdb) n
4968                    type_found = STRUCT_REQUEST;
(gdb) n
4969                    size = req->length;
(gdb) n
4970                    if (req->member_offset >= 0) {
(gdb) n
4975                            offset = -1;
(gdb) n
4976                            member_size = 0;

Also crash can't evaluate the offset of the "lru" member:

crash> struct page
struct page {
    long unsigned int flags;
    struct address_space *mapping;
    struct {
        union {...};
        union {...};
    };
    union {
        struct list_head lru;
        struct {...};
    };
    union {
        long unsigned int private;
        spinlock_t ptl;
        struct kmem_cache *slab;
        struct page *first_page;
    };
}
SIZE: 56

crash> struct page.mapping
struct page {
   [8] struct address_space *mapping;
}

crash> struct page.lru  
struct: invalid data structure reference: page.lru

Any idea why we do not get the offset from gdb?
Perhaps a problem with the anonymous union?

Michael




More information about the Crash-utility mailing list