Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: acmel/dwarves
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: acmel/dwarves
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: alt_dwarf
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 16 commits
  • 9 files changed
  • 1 contributor

Commits on Jan 24, 2023

  1. dwarf_loader: Add assert for catching unexpected inline expansion type

    While working on supporting DW_TAG_imported_unit lookups for the type of
    DW_TAG_inlined_subroutine tags should return either DW_TAG_subprogram or
    DW_TAG_subroutine_type, but were returning DW_TAG_variable, this is
    probably due to the way we do the lookups using the DWARF die offset,
    that probably needs tweaking...
    
    But to avoid these problems add an assert for the expected tag type.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    515a9a7 View commit details
    Browse the repository at this point in the history
  2. core: Make the tags tables a separate object

    And allocate it in cu__new(), add a destructor, etc.
    
    To support DWARF alternate files (.dwz) we'll load the alternate file
    passing the tables for the DWARF file being processed so that we can
    append its types there while keeping a separate DWARF offset hashtable,
    as the same offset may point to different types in the main DWARF file
    and in its alternate one.
    
    We will also need to mark on the tag type if it is an alternate one or
    not, but that is already available in DWARF, i.e. like this:
    
      $ readelf -wi /usr/lib/debug/usr/lib64/libvtep-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug
    
       <2><1caf>: Abbrev Number: 33 (DW_TAG_inlined_subroutine)
          <1cb0>   DW_AT_abstract_origin: <alt 0x6a80>
          <1cb4>   DW_AT_entry_pc    : 0x1b804
          <1cbc>   DW_AT_GNU_entry_view: 1
          <1cbd>   DW_AT_ranges      : 0x1d4
          <1cc1>   DW_AT_call_file   : 1
          <1cc2>   DW_AT_call_line   : 251
          <1cc3>   DW_AT_call_column : 5
    
    Then, in its alternate file:
    
      $ rpm -qf /usr/lib/debug/usr/lib64/libvtep-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug
      openvswitch-debuginfo-2.17.0-3.fc36.x86_64
      $ rpm -ql openvswitch-debuginfo-2.17.0-3.fc36.x86_64 | grep dwz
      /usr/lib/debug/.dwz
      /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64
      $
    
      $ readelf -wi /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64 | grep '<6a80>' -A10
       <1><6a80>: Abbrev Number: 22 (DW_TAG_subprogram)
          <6a81>   DW_AT_external    : 1
          <6a81>   DW_AT_name        : (indirect string, offset: 0x1ceab): memset
          <6a85>   DW_AT_decl_file   : 90
          <6a86>   DW_AT_decl_line   : 57
          <6a87>   DW_AT_decl_column : 1
          <6a87>   DW_AT_prototyped  : 1
          <6a87>   DW_AT_type        : <0x1ed2e>
       <2><6a8b>: Abbrev Number: 23 (DW_TAG_formal_parameter)
          <6a8c>   DW_AT_name        : (indirect string, offset: 0x1eb26): __dest
          <6a90>   DW_AT_decl_file   : 90
      $
    
    So that 6a80 DWARF offset may also exist for a given DIE in
    /usr/lib/debug/usr/lib64/libvtep-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug,
    where it would appear as <0x6a80>, not as <alt 0x6a80>.
    
    There is just one alternate per DWARF file, and for
    /usr/lib/debug/usr/lib64/libvtep-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug
    is /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64.
    
    There will be two DWARF offset keyed hash tables, one for the main file
    (libvtep) and another for the alternate (.dwz/openvswitch), but just one
    'struct tags_table' instance, combining the types in both.
    
    When resolving the types for the tags from the DWARF offset to the
    small_id used in the tags_tables tables we'll do the hash lookups on the
    two tables, based in the presence of the 'alt' bit in the type for each
    tag.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    e3e79ee View commit details
    Browse the repository at this point in the history
  3. core: Add internal __cu__new() that allows passing a tag_tables instance

    And make cu__new() have the same interface as before, but allocate the
    tags table, hand it to __cu__new() and ask it to delete it at
    cu__delete() time.
    
    Next patches will introduce cu__new_with_tables() for using the tags
    table from a base CU, so that we can add more types from an alternate
    DWARF file, like with .dwz.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    03edaf3 View commit details
    Browse the repository at this point in the history
  4. core: Add cu__new_build_id() constructor, for cases where build ids _…

    …are_ available
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    b1df280 View commit details
    Browse the repository at this point in the history
  5. core: Make cu__new() lose the build id arguments

    Shorter constructor signature for simpler cases where these are not
    available.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    957811b View commit details
    Browse the repository at this point in the history
  6. dwarf_loader: Pass conf_load to all tag constructors

    We'll need this to indicate that the CU being processed is an alternate
    one, as in used with the dwz deduplication scheme.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    87a7eac View commit details
    Browse the repository at this point in the history
  7. dwarf_loader: Pass 'struct conf_load' pointer to cu__hash() to decide…

    … if it should be added or not
    
    When adding tags from alternate DWARF files handling
    DW_TAG_imported_unit we will need to look at conf_load fields to see if
    we should really hash in this specific dwarf_cu hashtable, as the key is
    the DWARF offset and that is per DWARF file.
    
    We process the alternate DWARF file (the .dwz) in its entirety, so any
    non-hashed TAG we added when processing DW_TAG_imported_unit tags in the
    main DWARF file will be there for us to find when looking up the
    small_id.
    
    We have one hashtable per DWARF file and when doing the small_id
    adjustments for the tag's types and abstract_origins, we need to look at
    the right hashtable to obtain the small id.
    
    We use the same ptr_table for both the main DWARF file and the alternate
    one, to join them.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    457bfb3 View commit details
    Browse the repository at this point in the history
  8. emit: Emit typedefs for non language defined base types

    We can have things like:
    
     <1><2b3>: Abbrev Number: 45 (DW_TAG_base_type)
        <2b4>   DW_AT_byte_size   : 4
        <2b5>   DW_AT_encoding    : 7       (unsigned)
        <2b6>   DW_AT_name        : (alt indirect string, offset: 0x1bf6f) uint32_t
    
    And we were only handling those if _Atomic was involved, cover it.
    
    Also there are things like:
    
     <1><450>: Abbrev Number: 45 (DW_TAG_base_type)
        <451>   DW_AT_byte_size   : 8
        <452>   DW_AT_encoding    : 7       (unsigned)
        <453>   DW_AT_name        : (alt indirect string, offset: 0x1c01d) rte_iova_t
    
    Where we need to use DW_AT_byte_size and DW_AT_encoding to figure out
    this needs to emit this compilable code:
    
      typedef unsigned long rte_iova_t;
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    2f2c122 View commit details
    Browse the repository at this point in the history
  9. dwarf_loader: Support alt DWARF files

    It is possible to have common DWARF tags in a separate file and then
    refer to it in other DWARF files either by means of
    DW_TAG_imported_unit, when we find the imported units
    (DW_TAG_partial_unit) in a separate file (.dwz), that in turn can't have
    DW_TAG_imported_unit tags (i.e. no recursivity) or when a tag type uses
    a DW_FORM_GNU_ref_alt form, pointing to an offset in the alt DWARF file
    (the .dwz).
    
    We combine both in a single set of tag_tables (tags, types, functions)
    by first loading the main DWARF file (the one using DW_TAG_imported_unit
    or having DW_FORM_GNU_ref_alt form types) and then looking if elfutils'
    libdwarf has used the dwarf_setalt() function due to realizing the main
    file has DW_TAG_imported_unit with DW_FORM_GNU_ref_alt or
    DW_FORM_GNU_ref_alt in some of the types.
    
    I.e. the "small_ids" are kept in a single table, first the main DWARF
    file, then the alt DWARF file tags while keeping two DWARF offset keyed
    hashtables for when needing to find what small ids are associated with
    the DWARF offsets found in the libdwarves debugging format agnostic
    representations of the DWARF tags.
    
    We do this as there are two DWARF offset "address spaces", one per DWARF
    file.
    
    FIXME: cus__merging_cu(dw, elf) now is always returning true, which
    precludes parallel CU loading with -jN, lets first try to figure out why
    the types are not being resolved for some DW_TAG_members in the alt
    DWARF.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    72f740a View commit details
    Browse the repository at this point in the history
  10. dwarf_loader: Set tag->type (small_id) from dtag->type (DWARF offset)…

    … for enumerations
    
    As DW_TAG_enumeration_type entries have DW_AT_type to cope with packed
    enums, etc, see in this example of a split DWARF (alt DWARF, .dwz):
    
      $ readelf -wi /usr/lib/debug/lib64/libopenvswitch-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug | grep -m1 -B1 -A4 dp_packet_source
       <1><64a>: Abbrev Number: 56 (DW_TAG_enumeration_type)
          <64b>   DW_AT_name        : (alt indirect string, offset: 0xe456) dp_packet_source
          <64f>   DW_AT_encoding    : 7	(unsigned)
          <650>   DW_AT_byte_size   : 1
          <651>   DW_AT_type        : <alt 0x5e>
       <1><655>: Abbrev Number: 45 (DW_TAG_base_type)
      $ readelf -wi /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64 | grep '<5e>' -A4
       <1><5e>: Abbrev Number: 57 (DW_TAG_base_type)
          <5f>   DW_AT_byte_size   : 1
          <60>   DW_AT_encoding    : 8	(unsigned char)
          <61>   DW_AT_name        : (indirect string, offset: 0x16b4a): unsigned char
       <1><65>: Abbrev Number: 0
      $
    
    This will allow us to generate compilable source when all we have is a
    enum without enumerators, as in the case above, see that the
    DW_TAG_enumeration_type has no children of type DW_TAG_enumerator, it is
    followed by a sibling, a DW_TAG_base_type. In this case all we can emit
    as source code is 'enum dp_packet_source;' but that doesn't allow the
    generated from debugging info to be compilable, see the next cset to
    see how we instead will use the enumeration type and keep the
    enumeration name just as a comment.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    6425e03 View commit details
    Browse the repository at this point in the history
  11. core: Add 'compilable' flag to 'struct conf_fprintf'

    So that when facing with things like enums without entries we can decide
    wether we should keep the output closer to the original source code or
    if we should use its base_type to produce something compilable and that
    keeps the offsets with the enum real size, as it can be one, two, 4 or 8
    bytes long.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    e19a6e4 View commit details
    Browse the repository at this point in the history
  12. fprintf: Replace non-defined enums with its base type when generating…

    … compilable source code
    
    We pretty print this, which is closer to the original source code:
    
      $ pahole -C dp_packet /usr/lib/debug/lib64/libopenvswitch-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug
      struct dp_packet {
      	struct rte_mbuf            mbuf __attribute__((__aligned__(64))); /*     0   128 */
      	/* --- cacheline 2 boundary (128 bytes) --- */
      	enum dp_packet_source      source;               /*   128     1 */
    
      	/* XXX 1 byte hole, try to pack */
    
      	uint16_t                   l2_pad_size;          /*   130     2 */
      	uint16_t                   l2_5_ofs;             /*   132     2 */
      	uint16_t                   l3_ofs;               /*   134     2 */
      	uint16_t                   l4_ofs;               /*   136     2 */
    
      	/* XXX 2 bytes hole, try to pack */
    
      	uint32_t                   cutlen;               /*   140     4 */
      	ovs_be32                   packet_type;          /*   144     4 */
    
      	/* XXX 4 bytes hole, try to pack */
    
      	union {
      		struct pkt_metadata md;                  /*   152   512 */
      		uint64_t           data[8];              /*   152    64 */
      	};                                               /*   152   512 */
    
      	/* size: 704, cachelines: 11, members: 9 */
      	/* sum members: 657, holes: 3, sum holes: 7 */
      	/* padding: 40 */
      	/* forced alignments: 1 */
      } __attribute__((__aligned__(64)));
    
      $
    
    But, when we use 'pahole --compile' to ask for compilable source code,
    in some cases we don't get the enum definition:
    
    $ pahole -C dp_packet --compile /usr/lib/debug/lib64/libopenvswitch-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug
    
    <SNIP>
    
    enum dp_packet_source;
    
    <SNIP>
    
      	enum dp_packet_source      source;               /*   128     1 */
    
    <SNIP>
    
    Because we only have:
    
      <1><64a>: Abbrev Number: 56 (DW_TAG_enumeration_type)
         <64b>   DW_AT_name        : (alt indirect string, offset: 0xe456) dp_packet_source
         <64f>   DW_AT_encoding    : 7       (unsigned)
         <650>   DW_AT_byte_size   : 1
         <651>   DW_AT_type        : <alt 0x5e>
      <1><655>: Abbrev Number: 45 (DW_TAG_base_type)
    
    Which isn't compilable, so now we produce this instead, using that <alt
    0x5e> type:
    
       $ readelf -wi /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64 | grep '<5e>' -A4
        <1><5e>: Abbrev Number: 57 (DW_TAG_base_type)
           <5f>   DW_AT_byte_size   : 1
           <60>   DW_AT_encoding    : 8      (unsigned char)
           <61>   DW_AT_name        : (indirect string, offset: 0x16b4a): unsigned char
        <1><65>: Abbrev Number: 0
       $
    
      $ pahole -C dp_packet --compile /usr/lib/debug/lib64/libopenvswitch-2.17.so.0.0.0-2.17.0-3.fc36.x86_64.debug`
      <SNIP>
      struct dp_packet {
      	struct rte_mbuf            mbuf __attribute__((__aligned__(64))); /*     0   128 */
      	/* --- cacheline 2 boundary (128 bytes) --- */
      	/* enum dp_packet_source */ unsigned char   source; /*   128     1 */
    
      	/* XXX 1 byte hole, try to pack */
    
      	uint16_t                   l2_pad_size;          /*   130     2 */
      	uint16_t                   l2_5_ofs;             /*   132     2 */
      	uint16_t                   l3_ofs;               /*   134     2 */
      	uint16_t                   l4_ofs;               /*   136     2 */
    
      	/* XXX 2 bytes hole, try to pack */
    
      	uint32_t                   cutlen;               /*   140     4 */
      	ovs_be32                   packet_type;          /*   144     4 */
    
      	/* XXX 4 bytes hole, try to pack */
    
      	union {
      		struct pkt_metadata md;                  /*   152   512 */
      		uint64_t           data[8];              /*   152    64 */
      	};                                               /*   152   512 */
    
      	/* size: 704, cachelines: 11, members: 9 */
      	/* sum members: 657, holes: 3, sum holes: 7 */
      	/* padding: 40 */
      	/* forced alignments: 1 */
      } __attribute__((__aligned__(64)));
    
      $
    
    This is an oddity of dwz produced files, as if we use the .dwz directly
    instead of via DW_TAG_GNU_alt refs from another file we _get_ that enum
    defined:
    
      $ pahole --compile -C dp_packet /usr/lib/debug/.dwz/openvswitch-2.17.0-3.fc36.x86_64
      <SNIP>
    
      enum dp_packet_source {
      	DPBUF_MALLOC = 0,
      	DPBUF_STACK  = 1,
      	DPBUF_STUB   = 2,
      	DPBUF_DPDK   = 3,
      	DPBUF_AFXDP  = 4,
      } __attribute__((__packed__));
    
      <SNIP>
    
      struct dp_packet {
      	struct rte_mbuf            mbuf __attribute__((__aligned__(64))); /*     0   128 */
      	/* --- cacheline 2 boundary (128 bytes) --- */
      	enum dp_packet_source      source;               /*   128     1 */
    
      	/* XXX 1 byte hole, try to pack */
    
      	uint16_t                   l2_pad_size;          /*   130     2 */
      	uint16_t                   l2_5_ofs;             /*   132     2 */
      	uint16_t                   l3_ofs;               /*   134     2 */
      	uint16_t                   l4_ofs;               /*   136     2 */
    
      	/* XXX 2 bytes hole, try to pack */
    
      	uint32_t                   cutlen;               /*   140     4 */
      	ovs_be32                   packet_type;          /*   144     4 */
    
      	/* XXX 4 bytes hole, try to pack */
    
      	union {
      		struct pkt_metadata md;                  /*   152   512 */
      		uint64_t           data[8];              /*   152    64 */
      	};                                               /*   152   512 */
    
      	/* size: 704, cachelines: 11, members: 9 */
      	/* sum members: 657, holes: 3, sum holes: 7 */
      	/* padding: 40 */
      	/* forced alignments: 1 */
      } __attribute__((__aligned__(64)));
    
    So perhaps, longer term one improvement should be to look for such
    enums, and if they are not with its entries, lookup the full definition
    on the alt file (the .dwz) and use that instead when emiting compilable
    code.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    97ba0a9 View commit details
    Browse the repository at this point in the history
  13. dwarf_loader: Print the line number in addition to the function when …

    …not finding the abstract origin
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    af6b978 View commit details
    Browse the repository at this point in the history
  14. dwarf_loader: Print the line number in addition to the function when …

    …not finding the type
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    95671be View commit details
    Browse the repository at this point in the history
  15. WIP: skip_DW_TAG_atomic_type

    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    2c31a0c View commit details
    Browse the repository at this point in the history
  16. WIP: Remove DW_TAG_atomic_type when encoding BTF

    As BTF has no support for those types, just point tags that have as its
    type an atomic to the type the atomic points to, i.e. removing the
    DW_TAG_atomic_type from the type chain prior to passing it to BTF to
    dedup.
    
    Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
    acmel committed Jan 24, 2023
    Configuration menu
    Copy the full SHA
    17d7dc3 View commit details
    Browse the repository at this point in the history
Loading