Page MenuHomeFreeBSD

libdwarf: Add DW_AT_specification handling to dwarf_attrval_*
ClosedPublic

Authored by markj on Dec 27 2016, 1:18 AM.

Details

Summary

These functions will currently search the DIE referenced by a
DW_AT_abstract_origin attribute for a DW_AT_type attribute. GCC 6 plus
ctfconvert turned up some problems with this:

  • libdwarf will crash if asked to fetch the value of DW_AT_type and neither DW_AT_type or DW_AT_abstract_origin are present in the DIE.
  • GCC 6 emits variable DIEs whose type is defined in the DIE referenced by a DW_AT_specification attribute. ctfconvert fails process such DIEs since it doesn't know to follow DW_AT_specification attributes.
  • We might have to traverse multiple DIEs to find a DW_AT_type value.
  • The documentation states that libdwarf will search referenced DIEs for any attribute, but it only searches for DW_AT_type. Note that DW_AT_abstract_origin is used in multiple DIE types; the intent here seems to be to allow lookups for DW_TAG_formal_parameter DIEs.

This change addresses these issues. I think it would also make sense to
allow lookups of DW_AT_name this way, but did not implement that. In
particular, it would allow some simplification of addr2line and nm.

I'm not sure what the original motivation for this handling is. It seems to
be present in the first revision of dwarf_attrval.c.

Test Plan

I can build a kernel (except for ConcurrencyKit) with GCC 6 and get valid CTF.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

markj retitled this revision from to libdwarf: Add DW_AT_specification handling to dwarf_attrval_*.
markj edited the test plan for this revision. (Show Details)
markj updated this object.
markj added reviewers: emaste, kaiw.
markj updated this object.

Looks OK to me but would really like @kaiw review for commit upstream

contrib/elftoolchain/libdwarf/dwarf_attrval.c
176 ↗(On Diff #23288)

Maybe first = (die1 == NULL); to be more explicit?

contrib/elftoolchain/libdwarf/dwarf_attrval.c
176 ↗(On Diff #23288)

It turns out that the loop isn't needed for CTF generation, so I'm just going to commit the NULL check and DW_AT_specification handling.

contrib/elftoolchain/libdwarf/dwarf_attrval.c
176 ↗(On Diff #23288)

Hm, never mind - I didn't rebuild libdwarf properly after testing a change. The loop is needed: one example is the local var "status" in an inlined instance of cam_periph_acquire(). The instance defines a lexical block containing variable DIE referencing another variable DIE with DW_AT_const_value 4 (CAM_REQ_CMP_ERR), which references the DIE for "status".

This revision was automatically updated to reflect the committed changes.

Patch looks good to me. thanks!

dwarf_attrval_unsigned() was invented especially for FreeBSD's ctfconvert (only present
in this libdwarf implementation), which means we always can/should modify it to
make ctfconvert work better.

I realize this is old, but I figure the same group is still likely to be interested. I think we'll need more like this to support GCC6+ ctfconvert. E.g.,

$ llvm-dwarfdump60 -v .../subr_param.o
...
0x000047c4:   DW_TAG_variable [46]
                DW_AT_name [DW_FORM_string]     ("hz")
                DW_AT_decl_file [DW_FORM_data1] ("/usr/home/conrad/src/freebsd/sys/sys/kernel.h")
                DW_AT_decl_line [DW_FORM_data1] (66)
                DW_AT_type [DW_FORM_ref4]       (cu + 0x006a => {0x0000006a} "int")
                DW_AT_external [DW_FORM_flag]   (0x01)
                DW_AT_declaration [DW_FORM_flag]        (0x01)
...
0x0000507c:   DW_TAG_variable [51]
                DW_AT_specification [DW_FORM_ref4]      (cu + 0x47c4 => {0x000047c4} "hz")
                DW_AT_decl_file [DW_FORM_data1] ("/usr/home/conrad/src/freebsd/sys/kern/subr_param.c")
                DW_AT_decl_line [DW_FORM_data1] (87)
                DW_AT_location [DW_FORM_block1] (DW_OP_addr 0x0)

CTF ignores the first version because die_isdecl() (DW_AT_declaration = 0x1).

CTF ignores the second version because (name = die_name(dw, die)) == NULL (because die_name()dwarf_attrval_string() does not chase up the DW_AT_specification reference.

We'll need information from both to make a complete CTF variable; it seems like we basically always want to search for attributes in a DW_AT_specification if we cannot find them in the current Die. Not just for unsigned values and only for DW_AT_type.

(It seems like we will want at least DW_AT_external and DW_AT_name forwarded up the specification chain. Maybe not DW_AT_declaration, I guess!)