echo 'inline namespace A { enum E { X0,X1,X2,X3,X4,X5 }; } int main() { return X0; }'|g++ -Wall -g -x c++ -;cp -p a.out a.out.dup;dwz -m a.out.dwz a.out a.out.dup;readelf -wi a.out.dwz|grep DW_AT_export_symbols Actual: (nothing) Expected: <XX> DW_AT_export_symbols: 1 Context: a.out: <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) ... <1><22>: Abbrev Number: 5 (DW_TAG_imported_unit) <23> DW_AT_import : <alt 0xb> <1><27>: Abbrev Number: 4 (DW_TAG_namespace) <28> DW_AT_name : A ... <2d> DW_AT_export_symbols: 1 <2><2e>: Abbrev Number: 0 a.out.dwz: <0><b>: Abbrev Number: 4 (DW_TAG_partial_unit) ... <1><14>: Abbrev Number: 2 (DW_TAG_namespace) <15> DW_AT_name : A ... <2><18>: Abbrev Number: 6 (DW_TAG_enumeration_type) This breaks libc++ which is using namespace 'std::__1::' -> 'std::'
Yes, the code assumes the only relevant attribute of a DW_TAG_namespace is the DW_AT_name. This is both in the build_abbrevs_for_die, write_die and partition_dups_1 functions. It only allows for an optional DW_AT_sibling attribute. It should carry over the DW_AT_export_symbols (which is new in DWARF5).