In kernel-debuginfo-2.6.33.6-147.fc13.x86_64 /usr/lib/debug/lib/modules/2.6.33.6-147.fc13.x86_64/vmlinux Compilation unit at offset 63884337: Version: 3, Abbreviation section offset: 1655619, Address size: 8, Offset size: 4 [3cecc3c] compile_unit producer (strp) "GNU C 4.4.4 20100630 (Red Hat 4.4.4-10)" language (data1) ISO C89 (1) name (strp) "net/ipv4/tcp.c" comp_dir (strp) "/usr/src/debug/kernel-2.6.33/linux-2.6.33.x86_64"
we see:
[3d0b497] variable name (strp) "tcp_memory_pressure" decl_file (data1) 10 decl_line (data1) 247 type (ref4) [3ceccfc] external (flag) Yes declaration (flag) Yes
(extern decl in header file) and later in the same CU:
[3d0c424] variable name (strp) "tcp_memory_pressure" decl_file (data1) 1 decl_line (data2) 318 type (ref4) [3ceccfc] external (flag) Yes location (block1) [ 0] addr 0xffffffff81b8cb04
(global defn in this CU's main source file).
I guess it's kosher enough to have one DIE for the declaration and one for the definition. But it was a surprise to see this happen. In a simple test case:
extern int global_var;
static int static_var;
static int static_var = 123;
int global_var = 456;
(with plain -g) I only get one DW_TAG_variable for each.
So I would like to understand under what conditions GCC does (or should?) generate two entries in cases like these.
IMHO, it would be nice, if you're going to have both a decl and a defn, for the defn to have DW_AT_specification pointing to the decl (even for C). But that's a tangential idea.
We noticed this with systemtap, because dwarf_getscopevar (which it uses) stops at the first matching name. So it found the declaration DIE and said "this has no known location" (i.e. punt to methods for extern decls of things defined in other CUs). This is fine for this kind of case, since we do have those methods in systemtap (it looks up an ELF symbol to resolve the global between CUs).
However, if it ever generated two DIEs like that for a static variable, this would break systemtap as things stand today (if the DW_AT_declaration one appears first in the CU's DIE list).
If that is how it's going to be, then perhaps dwarf_getscopevar should do something like keep looking until it sees a match without DW_AT_declaration, only giving the (first? last?) DW_AT_declaration match if there is no later non-declaration DIE.
Petr, a check related to this is a to-do item for dwarflint high-level checks.
If you think (as I suspect) that it's just a bug for there to be two DIEs for the same variable, then I have the reproducer:
1 extern int global_var; 2 3 extern __typeof (global_var) global_var; 4 5 int global_var = 456;
Through some macro magic, this is the essence of what's happening in the kernel case. The DW_AT_declaration entry emitted is for the first decl (line 1). I'm guessing that the __typeof magic in the line 3 decl confuses it somehow into thinking that the extern on line 1 and the defn on line 5 don't go together, so line 5 fails to trump line 1 as it ordinarily would. (Perhaps this would also happen if it redeclared it with __attribute__ or something, though I haven't found another case in things I've tried.)
Thanks, Roland
21.07.2010 03:01, Roland McGrath wrote:
Petr, a check related to this is a to-do item for dwarflint high-level checks.
That's now on pmachata/dwarflint together with the test case. I also made it check duplicate DW_TAG_variable+DW_AT_declaration (duplicate decl) that's also frequently seen in that kernel tree that you mentioned.
PM
elfutils-devel@lists.fedorahosted.org