Search code examples
clinux-kernelmacrosgdbarm64

struct member value zero but macro checking if it's zero returns 0, why?


in arch/arm64/include/asm/pgtable-types.h

typedef struct { pgdval_t pgd; } pgd_t;
#define pgd_val(x)  ((x).pgd)
#define __pgd(x)    ((pgd_t) { (x) } )

And in arch/arm64/include/asm/pgtable.h,

#define pgd_none(pgd)       (!pgd_val(pgd))

I was in arch/arm64/mm/mmu.c during the debug using qemu and gdb, it read pgd entry in addr pgdp and if it's empty, fills it with pointer to bm_pud.

void __init early_fixmap_init(void)
{
    pgd_t *pgdp, pgd;
    pud_t *pudp;
    pmd_t *pmdp;
    unsigned long addr = FIXADDR_START;

    pgdp = pgd_offset_k(addr);
    pgd = READ_ONCE(*pgdp);
    if (CONFIG_PGTABLE_LEVELS > 3 &&
        !(pgd_none(pgd) || pgd_page_paddr(pgd) == __pa_symbol(bm_pud))) {
        /*
         * We only end up here if the kernel mapping and the fixmap
         * share the top level pgd entry, which should only happen on
         * 16k/4 levels configurations.
         */
        BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
        pudp = pud_offset_kimg(pgdp, addr);
    } else {
        if (pgd_none(pgd))         <====== here!!
            __pgd_populate(pgdp, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
        pudp = fixmap_pud(addr);
    }

When gdb is at the line marked with <=== here!! above,

(gdb) p pgd
$4 = {pgd = 0x0}
(gdb) p pgd_none(pgd)
$5 = 0x0

The pgd value is 0, but the pgd_none output is also 0 when it should be 1(true) and it skipps the __pgd_populate function. What is wrong here?


Solution

  • What does (gdb) info func pgd_none say?

    I suspect you are calling a function, not the macro you are intending to "call".

    In fact, I am not sure GDB is even capable of evaluating a macro.

    Update:

    As ssbssa@ noted, GDB is documented to support macro evaluation, and will do that automatically if the source is compiled with -g3.

    However, there is a bug in GDB (current as of version 12.0.50.20220221-git) which prevents this from working, unless the code is compiled with -gdwarf-4.

    Here is a trivial test:

    #define FOO(x) (x - 42)
    
    int main()
    {
      int x = 42;
      return FOO(x);
    }
    

    Compile with gcc -g3 foo.c -gdwarf-4.

    Reading symbols from ./a.out...
    (gdb) start
    Temporary breakpoint 1 at 0x112d: file foo.c, line 5.
    Starting program: /tmp/a.out
    
    Temporary breakpoint 1, main () at foo.c:5
    5         int x = 42;
    (gdb) n
    6         return FOO(x);
    (gdb) p FOO(1)
    $1 = -41
    

    Update 2:

    From ssbssa@: this should work now with dwarf-5 in gdb-13 (see this bug).