Changeset d8eef0a in rtems-tools


Ignore:
Timestamp:
May 10, 2018, 6:12:27 PM (12 months ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
1c5206b
Parents:
1318c11
git-author:
Chris Johns <chrisj@…> (05/10/18 18:12:27)
git-committer:
Chris Johns <chrisj@…> (06/18/18 02:26:16)
Message:

rtemstoolkit: Add DWARF function support.

Load the functions in each CU.

Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • linkers/rtems-addr2line.cpp

    r1318c11 rd8eef0a  
    5555  { "verbose",      no_argument,            NULL,           'v' },
    5656  { "executable",   required_argument,      NULL,           'e' },
     57  { "functions" ,   no_argument,            NULL,           'f' },
    5758  { "addresses",    no_argument,            NULL,           'a' },
    5859  { "pretty-print", no_argument,            NULL,           'p' },
     
    7071            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
    7172            << "             to increase verbosity (also --verbose)" << std::endl
    72             << " -e        : executable (also --executablewarn)" << std::endl
     73            << " -e        : executable (also --executable)" << std::endl
     74            << " -f        : show function names (also --functions)" << std::endl
    7375            << " -a        : show addresses (also --addresses)" << std::endl
    7476            << " -p        : human readable format (also --pretty-print)" << std::endl
     
    128130  {
    129131    std::string exe_name = "a.out";
     132    bool        show_functions = false;
    130133    bool        show_addresses = false;
    131134    bool        pretty_print = false;
     
    136139    while (true)
    137140    {
    138       int opt = ::getopt_long (argc, argv, "hvVe:aps", rld_opts, NULL);
     141      int opt = ::getopt_long (argc, argv, "hvVe:faps", rld_opts, NULL);
    139142      if (opt < 0)
    140143        break;
     
    155158        case 'e':
    156159          exe_name = optarg;
     160          break;
     161
     162        case 'f':
     163          show_functions = true;
    157164          break;
    158165
     
    214221      debug.begin (exe.elf ());
    215222      debug.load_debug ();
     223      debug.load_types ();
     224      debug.load_functions ();
    216225
    217226      for (int arg = 0; arg < argc; ++arg)
     
    243252          else
    244253            std::cout << std::endl;
     254        }
     255
     256        if (show_functions)
     257        {
     258          std::string function;
     259          debug.get_function (location, function);
     260          std::cout << function << " at ";
    245261        }
    246262
  • linkers/rtems-exeinfo.cpp

    r1318c11 rd8eef0a  
    294294      exe.load_symbols (symbols, true);
    295295      debug.load_debug ();
     296      debug.load_types ();
    296297      symbols.globals (addresses);
    297298      symbols.weaks (addresses);
     
    322323                                       "-fbuilding-libgcc",
    323324                                       "-fno-implicit-templates",
     325                                       "-fimplicit-templates",
    324326                                       "-ffunction-sections",
    325327                                       "-fdata-sections",
  • rtemstoolkit/elftoolchain/libdwarf/dwarf_die.c

    r1318c11 rd8eef0a  
    7979
    8080        ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
    81         cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
     81        if (die != NULL && die->die_cu != NULL)
     82                cu = die->die_cu;
     83        else
     84                cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
    8285
    8386        if (cu == NULL) {
  • rtemstoolkit/rld-dwarf-types.h

    r1318c11 rd8eef0a  
    3636     * Hide the types from libdwarf we use.
    3737     */
    38     typedef ::Dwarf_Debug    dwarf;
    39     typedef ::Dwarf_Handler  dwarf_handler;
    40     typedef ::Dwarf_Error    dwarf_error;
    41     typedef ::Dwarf_Die      dwarf_die;
    42     typedef ::Dwarf_Line     dwarf_line;
    43     typedef ::Dwarf_Ptr      dwarf_pointer;
    44     typedef ::Dwarf_Addr     dwarf_address;
    45     typedef ::Dwarf_Off      dwarf_offset;
    46     typedef ::Dwarf_Half     dwarf_half;
    47     typedef ::Dwarf_Signed   dwarf_signed;
    48     typedef ::Dwarf_Unsigned dwarf_unsigned;
    49     typedef ::Dwarf_Bool     dwarf_bool;
    50     typedef ::Dwarf_Sig8     dwarf_sig8;
    51     typedef ::Dwarf_Line     dwarf_line;
    52     typedef ::Dwarf_Half     dwarf_tag;
    53     typedef ::Dwarf_Half     dwarf_attr;
     38    typedef ::Dwarf_Debug                  dwarf;
     39    typedef ::Dwarf_Handler                dwarf_handler;
     40    typedef ::Dwarf_Error                  dwarf_error;
     41    typedef ::Dwarf_Die                    dwarf_die;
     42    typedef ::Dwarf_Line                   dwarf_line;
     43    typedef ::Dwarf_Ptr                    dwarf_pointer;
     44    typedef ::Dwarf_Addr                   dwarf_address;
     45    typedef ::Dwarf_Off                    dwarf_offset;
     46    typedef ::Dwarf_Half                   dwarf_half;
     47    typedef ::Dwarf_Signed                 dwarf_signed;
     48    typedef ::Dwarf_Unsigned               dwarf_unsigned;
     49    typedef ::Dwarf_Bool                   dwarf_bool;
     50    typedef ::Dwarf_Sig8                   dwarf_sig8;
     51    typedef ::Dwarf_Line                   dwarf_line;
     52    typedef ::Dwarf_Half                   dwarf_tag;
     53    typedef ::Dwarf_Attribute              dwarf_attribute;
     54    typedef ::Dwarf_Half                   dwarf_attr;
     55    typedef ::Dwarf_Ranges                 dwarf_ranges;
     56    typedef enum ::Dwarf_Ranges_Entry_Type dwarf_ranges_type;
     57    typedef enum ::Dwarf_Form_Class        dwarf_form_class;
     58    typedef ::Dwarf_Type                   dwarf_type;
    5459  }
    5560}
  • rtemstoolkit/rld-dwarf.cpp

    r1318c11 rd8eef0a  
    3838  namespace dwarf
    3939  {
     40    typedef std::vector < dwarf_die > dies_active;
     41    dies_active active_dies;
     42
     43    bool active_dies_present (dwarf_die die)
     44    {
     45      return std::find (active_dies.begin(), active_dies.end(), die) != active_dies.end();
     46    }
     47
     48    void dies_active_add (dwarf_die die)
     49    {
     50      if (active_dies_present (die))
     51      {
     52        std::cout << "DDdd : dup : " << die << std::endl;
     53      }
     54      else
     55      {
     56        active_dies.push_back (die);
     57      }
     58    }
     59
     60    void dies_active_remove (dwarf_die die)
     61    {
     62      dies_active::iterator di = std::find (active_dies.begin(), active_dies.end(), die);
     63      if (di == active_dies.end ())
     64      {
     65        std::cout << "DDdd : no found : " << die << std::endl;
     66      }
     67      else
     68      {
     69        active_dies.erase (di);
     70      }
     71    }
     72
    4073    /**
    4174     * The libdwarf error.
     
    202235    }
    203236
     237    range::range (const dwarf_ranges* range)
     238      : range_ (range)
     239    {
     240    }
     241
     242    range::range (const range& orig)
     243      : range_ (orig.range_)
     244    {
     245    }
     246
     247    range::~range ()
     248    {
     249    }
     250
     251    dwarf_unsigned
     252    range::addr1 () const
     253    {
     254      if (range_ == nullptr)
     255        throw rld::error ("No valid range", "rld:dwarf:range:addr1");
     256      return range_->dwr_addr1;
     257    }
     258
     259    dwarf_unsigned
     260    range::addr2 () const
     261    {
     262      if (range_ == nullptr)
     263        throw rld::error ("No valid range", "rld:dwarf:range:addr2");
     264      return range_->dwr_addr2;
     265    }
     266
     267    dwarf_ranges_type
     268    range::type () const
     269    {
     270      if (range_ == nullptr)
     271        throw rld::error ("No valid range", "rld:dwarf:range:type");
     272      return range_->dwr_type;
     273    }
     274
     275    bool
     276    range::empty () const
     277    {
     278      /**
     279       * See DWARF 2.17.3.
     280       *
     281       * A bounded range entry whose beginning and ending address offsets are
     282       * equal (including zero) indicates an empty range and may be ignored.
     283       */
     284      return type () == DW_RANGES_ENTRY && addr1 () == addr2 ();
     285    }
     286
     287    bool
     288    range::end () const
     289    {
     290      return type () == DW_RANGES_END;
     291    }
     292
     293    range&
     294    range::operator = (const range& rhs)
     295    {
     296      if (this != &rhs)
     297        range_ = rhs.range_;
     298      return *this;
     299    }
     300
     301    void
     302    range::dump ()
     303    {
     304      dwarf_ranges_type type_ = type ();
     305      const char*       type_s = "invalid";
     306      const char*       type_labels[] = {
     307        "BOUNDED",
     308        "BASE",
     309        "END"
     310      };
     311      if (type_ <= DW_RANGES_END)
     312        type_s = type_labels[type_];
     313      std::cout << type_s << '-'
     314                << std::hex << std::setfill ('0')
     315                << "0x" << std::setw (8) << addr1 ()
     316                << ":0x" << std::setw (8) << addr2 ();
     317    }
     318
     319    address_ranges::address_ranges (file& debug)
     320      : debug (debug),
     321        offset (-1),
     322        dranges (nullptr),
     323        dranges_count (0)
     324    {
     325    }
     326
     327    address_ranges::address_ranges (debug_info_entry& die)
     328      : debug (die.get_debug ()),
     329        offset (-1),
     330        dranges (nullptr),
     331        dranges_count (0)
     332    {
     333      load (die);
     334    }
     335
     336    address_ranges::address_ranges (file& debug, dwarf_offset offset)
     337      : debug (debug),
     338        offset (offset),
     339        dranges (nullptr),
     340        dranges_count (0)
     341    {
     342      load (offset);
     343    }
     344
     345    address_ranges::address_ranges (const address_ranges& orig)
     346      : debug (orig.debug),
     347        offset (orig.offset)
     348    {
     349      load (orig.offset);
     350    }
     351
     352    address_ranges::~address_ranges ()
     353    {
     354      if (dranges != nullptr)
     355      {
     356        ::dwarf_ranges_dealloc (debug, dranges, dranges_count);
     357        dranges = nullptr;
     358        dranges_count = 0;
     359        ranges_.clear ();
     360      }
     361    }
     362
     363    bool
     364    address_ranges::load (debug_info_entry& die, bool error)
     365    {
     366      dwarf_attribute attr;
     367      dwarf_error     de;
     368      int             dr;
     369      dr = ::dwarf_attr (die, DW_AT_ranges, &attr, &de);
     370      if (dr != DW_DLV_OK)
     371      {
     372        if (!error)
     373          return false;
     374        libdwarf_error_check ("rld:dwarf::address_ranges:load", dr, de);
     375      }
     376      dr = ::dwarf_global_formref (attr, &offset, &de);
     377      if (dr != DW_DLV_OK)
     378      {
     379        if (!error)
     380          return false;
     381        libdwarf_error_check ("rld:dwarf::address_ranges:load", dr, de);
     382      }
     383      load (offset);
     384      return true;
     385    }
     386
     387    bool
     388    address_ranges::load (dwarf_offset offset_, bool error)
     389    {
     390      if (offset_ > 0)
     391      {
     392        if (dranges != nullptr)
     393          ::dwarf_ranges_dealloc (debug, dranges, dranges_count);
     394
     395        dranges = nullptr;
     396        dranges_count = 0;
     397
     398        offset = offset_;
     399
     400        dwarf_error de;
     401        int         dr;
     402
     403        dr = ::dwarf_get_ranges (debug, offset,
     404                                 &dranges, &dranges_count, nullptr, &de);
     405        if (dr != DW_DLV_OK)
     406        {
     407          if (!error)
     408            return false;
     409          libdwarf_error_check ("rld:dwarf::ranges:load", dr, de);
     410        }
     411
     412        if (dranges != nullptr && dranges_count > 0)
     413        {
     414          for (dwarf_signed r = 0; r < dranges_count; ++r)
     415            ranges_.push_back (range (&dranges[r]));
     416        }
     417      }
     418
     419      return true;
     420    }
     421
     422    const ranges&
     423    address_ranges::get () const
     424    {
     425      return ranges_;
     426    }
     427
     428    bool
     429    address_ranges::empty () const
     430    {
     431      return ranges_.empty ();
     432    }
     433
     434    address_ranges&
     435    address_ranges::operator = (const address_ranges& rhs)
     436    {
     437      if (this != &rhs)
     438      {
     439        if (debug != rhs.debug)
     440          throw rld::error ("invalid debug", "address_ranges:=");
     441        load (rhs.offset);
     442      }
     443      return *this;
     444    }
     445
     446    void
     447    address_ranges::dump ()
     448    {
     449      bool first = true;
     450      std::cout << '[';
     451      for (auto& r : ranges_)
     452      {
     453        if (!first)
     454          std::cout << ',';
     455        r.dump ();
     456        first = false;
     457      }
     458      std::cout << ']';
     459    }
     460
    204461    line_addresses::line_addresses (file&             debug,
    205462                                    debug_info_entry& die)
     
    313570    }
    314571
     572
     573    function::function (file& debug, debug_info_entry& die)
     574      : debug (debug),
     575        machine_code_ (false),
     576        external_ (false),
     577        declaration_ (false),
     578        inline_ (DW_INL_not_inlined),
     579        pc_low_ (0),
     580        pc_high_ (0),
     581        ranges_ (debug)
     582    {
     583      dwarf_bool db;
     584
     585      if (die.attribute (DW_AT_external, db, false))
     586        external_ = db ? true : false;
     587
     588      if (die.attribute (DW_AT_declaration, db, false))
     589        declaration_ = db ? true : false;
     590
     591      die.attribute (DW_AT_linkage_name, linkage_name_, false);
     592
     593      if (!die.attribute (DW_AT_inline, inline_, false))
     594        inline_ = DW_INL_not_inlined;
     595
     596      if (inline_ == DW_INL_declared_inlined)
     597      {
     598        die_dump_children (die, " +");
     599      }
     600
     601      /*
     602       * If ranges are not found see if the PC low and PC high attributes
     603       * can be found.
     604       */
     605      ranges_.load (die, false);
     606      if (ranges_.empty ())
     607      {
     608        bool is_address;
     609        if (die.get_lowpc (pc_low_) && die.get_highpc (pc_high_, is_address))
     610        {
     611          machine_code_ = true;
     612          if (!is_address)
     613            pc_high_ += pc_low_;
     614        }
     615      }
     616      else
     617      {
     618        for (auto& r : ranges_.get ())
     619        {
     620          if (!r.end () && !r.empty ())
     621          {
     622            machine_code_ = true;
     623            break;
     624          }
     625        }
     626      }
     627
     628      if (declaration_)
     629      {
     630        die.attribute (DW_AT_name, name_);
     631      }
     632      else
     633      {
     634        /*
     635         * Get the name attribute. (if present)
     636         */
     637        if (!die.attribute (DW_AT_name, name_, false))
     638        {
     639          bool found = false;
     640
     641          /*
     642           * For inlined function, the actual name is probably in the DIE
     643           * referenced by DW_AT_abstract_origin. (if present)
     644           */
     645          dwarf_attribute abst_at;
     646          if (die.attribute (DW_AT_abstract_origin, abst_at, false))
     647          {
     648            dwarf_offset abst_at_die_offset;
     649            dwarf_error  de;
     650            int          dr;
     651            dr = ::dwarf_global_formref (abst_at, &abst_at_die_offset, &de);
     652            if (dr == DW_DLV_OK)
     653            {
     654              debug_info_entry abst_at_die (debug, abst_at_die_offset);
     655              if (abst_at_die.attribute (DW_AT_name, name_, false))
     656                found = true;
     657            }
     658          }
     659
     660          /*
     661           * If DW_AT_name is not present, but DW_AT_specification is present,
     662           * then probably the actual name is in the DIE referenced by
     663           * DW_AT_specification.
     664           */
     665          if (!found)
     666          {
     667            dwarf_attribute spec;
     668            if (die.attribute (DW_AT_specification, spec, false))
     669            {
     670              dwarf_offset spec_die_offset;
     671              dwarf_error  de;
     672              int          dr;
     673              dr = ::dwarf_global_formref (abst_at, &spec_die_offset, &de);
     674              if (dr == DW_DLV_OK)
     675              {
     676                debug_info_entry spec_die (debug, spec_die_offset);
     677                if (spec_die.attribute (DW_AT_name, name_, false))
     678                  found = true;
     679              }
     680            }
     681          }
     682        }
     683
     684        if (die.tag () == DW_TAG_inlined_subroutine)
     685        {
     686          die.attribute (DW_AT_call_file, call_file_, false);
     687        }
     688      }
     689
     690      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
     691      {
     692        std::cout << "dwarf::function: ";
     693        if (name_.empty ())
     694          std::cout << "NO NAME";
     695        else
     696          std::cout << name_;
     697        if (!has_machine_code ())
     698          std::cout << " NO MACHINE CODE";
     699        else
     700          std::cout << std::hex << std::setfill ('0')
     701                    << " pc_low = 0x" << std::setw (8) << pc_low ()
     702                    << " pc_high = 0x" << std::setw (8) << pc_high ()
     703                    << std::dec << std::setfill (' ');
     704        std::cout << std::endl;
     705      }
     706    }
     707
     708    function::~function ()
     709    {
     710    }
     711
     712    std::string
     713    function::name () const
     714    {
     715      return name_;
     716    }
     717
     718    const address_ranges&
     719    function::get_ranges () const
     720    {
     721      return ranges_;
     722    }
     723
     724    dwarf_unsigned
     725    function::pc_low () const
     726    {
     727      if (ranges_.empty ())
     728        return pc_low_;
     729      dwarf_address addr = ~0;
     730      for (auto& r : ranges_.get ())
     731      {
     732        if (!r.end () && !r.empty () && r.addr1 () < addr)
     733          addr = r.addr1 ();
     734      }
     735      return addr;
     736    }
     737
     738    dwarf_unsigned
     739    function::pc_high () const
     740    {
     741      if (ranges_.empty ())
     742        return pc_high_;
     743      dwarf_address addr = 0;
     744      for (auto& r : ranges_.get ())
     745      {
     746        if (!r.end () && !r.empty () && r.addr2 () > addr)
     747          addr = r.addr1 ();
     748      }
     749      return addr;
     750    }
     751
     752    bool
     753    function::has_machine_code () const
     754    {
     755      return machine_code_;
     756    }
     757
     758    bool
     759    function::is_external () const
     760    {
     761      return external_;
     762    }
     763
     764    bool
     765    function::is_declaration () const
     766    {
     767      return declaration_;
     768    }
     769
     770    bool
     771    function::is_inlined () const
     772    {
     773      return inline_ == DW_INL_declared_inlined;
     774    }
     775
     776    std::string
     777    function::call_file () const
     778    {
     779      return call_file_;
     780    }
     781
     782    bool
     783    function::inside (dwarf_address addr) const
     784    {
     785      return !name_.empty () && has_machine_code () &&
     786        addr >= pc_low () && addr <= pc_high ();
     787    }
     788
    315789    debug_info_entry::debug_info_entry (file& debug)
    316790      : debug (debug),
     
    335809        offset_ (offset__)
    336810    {
     811      dwarf_die   ddie;
     812      dwarf_error de;
     813      int         dr;
     814      dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
     815      libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
     816      die = ddie;
     817    }
     818
     819    debug_info_entry::debug_info_entry (const debug_info_entry& orig)
     820      : debug (orig.debug),
     821        die (nullptr),
     822        tag_ (orig.tag_),
     823        offset_ (orig.offset_)
     824    {
     825      if (offset_ != 0)
     826      {
     827        dwarf_die   ddie;
    337828        dwarf_error de;
    338829        int         dr;
    339         dr = ::dwarf_offdie (debug, offset_, &die, &de);
     830        dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
    340831        libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
     832        die = ddie;
     833      }
    341834    }
    342835
     
    379872    }
    380873
     874    debug_info_entry&
     875    debug_info_entry::operator = (dwarf_offset offset__)
     876    {
     877      dealloc ();
     878      if (offset__ != 0)
     879      {
     880        dwarf_die   ddie;
     881        dwarf_error de;
     882        int         dr;
     883        offset_ = offset__;
     884        tag_ = 0;
     885        dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
     886        libdwarf_error_check ("debug_info_entry:operator=", dr, de);
     887        die = ddie;
     888      }
     889      return *this;
     890    }
     891
    381892    bool
    382893    debug_info_entry::operator == (debug_info_entry& rhs) const
     
    399910        dwarf_error de;
    400911        int         dr;
    401         dr = ::dwarf_tag(die, &tag_, &de);
     912        dr = ::dwarf_tag (die, &tag_, &de);
    402913        libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
    403914      }
     
    419930
    420931    bool
     932    debug_info_entry::get_lowpc (dwarf_address& addr, bool error) const
     933    {
     934      dwarf_error de;
     935      int         dr;
     936      dr = ::dwarf_lowpc (die, &addr, &de);
     937      if (error)
     938        libdwarf_error_check ("debug_info_entry:lowpc", dr, de);
     939      return dr == DW_DLV_OK;
     940    }
     941
     942    bool
     943    debug_info_entry::get_highpc (dwarf_address& addr,
     944                                  bool&          is_address,
     945                                  bool           error) const
     946    {
     947      dwarf_half       form;
     948      dwarf_form_class class_;
     949      dwarf_error      de;
     950      int              dr;
     951      dr = ::dwarf_highpc_b (die, &addr, &form, &class_, &de);
     952      if (error)
     953        libdwarf_error_check ("debug_info_entry:highpc", dr, de);
     954      is_address = class_ == DW_FORM_CLASS_ADDRESS;
     955      return dr == DW_DLV_OK;
     956    }
     957
     958    bool
     959    debug_info_entry::attribute (dwarf_attr       attr,
     960                                 dwarf_attribute& value,
     961                                 bool             error) const
     962    {
     963      dwarf_error de;
     964      int         dr;
     965      dr = ::dwarf_attr (die, attr, &value, &de);
     966      if (error)
     967        libdwarf_error_check ("debug_info_entry:attribute(attr)", dr, de);
     968      return dr == DW_DLV_OK;
     969    }
     970
     971    bool
     972    debug_info_entry::attribute (dwarf_attr  attr,
     973                                 dwarf_bool& value,
     974                                 bool        error) const
     975    {
     976      dwarf_error de;
     977      int         dr;
     978      dr = ::dwarf_attrval_flag (die, attr, &value, &de);
     979      if (error)
     980        libdwarf_error_check ("debug_info_entry:attribute(flag)", dr, de);
     981      return dr == DW_DLV_OK;
     982    }
     983
     984    bool
    421985    debug_info_entry::attribute (dwarf_attr      attr,
    422986                                 dwarf_unsigned& value,
     
    427991      dr = ::dwarf_attrval_unsigned (die, attr, &value, &de);
    428992      if (error)
    429         libdwarf_error_check ("debug_info_entry:attribute ", dr, de);
     993        libdwarf_error_check ("debug_info_entry:attribute(unsigned)", dr, de);
    430994      return dr == DW_DLV_OK;
    431995    }
     
    4421006      dr = ::dwarf_attrval_string (die, attr, &s, &de);
    4431007      if (error)
    444         libdwarf_error_check ("debug_info_entry:attribute ", dr, de);
     1008        libdwarf_error_check ("debug_info_entry:attribute(string)", dr, de);
    4451009      if (s != nullptr)
    4461010        value = s;
     
    4741038    }
    4751039
     1040    bool
     1041    debug_info_entry::ranges (dwarf_ranges*& ranges,
     1042                              dwarf_signed&  rangescount) const
     1043    {
     1044      dwarf_unsigned ranges_off;
     1045      if (attribute (DW_AT_ranges, ranges_off, false))
     1046      {
     1047        dwarf_error de;
     1048        int         dr;
     1049        dr = ::dwarf_get_ranges (debug, ranges_off,
     1050                                 &ranges, &rangescount, nullptr, &de);
     1051        libdwarf_error_check ("debug_info_entry:ranges ", dr, de);
     1052        return ranges != nullptr && rangescount > 0;
     1053      }
     1054      return false;
     1055    }
     1056
     1057    bool
     1058    debug_info_entry::get_child (debug_info_entry& child_die)
     1059    {
     1060      dwarf_error      de;
     1061      int              dr;
     1062      dr = ::dwarf_child (die, child_die, &de);
     1063      return dr == DW_DLV_OK;
     1064    }
     1065
     1066    bool
     1067    debug_info_entry::get_sibling (debug_info_entry& sibling_die)
     1068    {
     1069      dwarf_error      de;
     1070      int              dr;
     1071      dr = ::dwarf_siblingof (debug, die, sibling_die, &de);
     1072      if (dr == DW_DLV_NO_ENTRY)
     1073        return false;
     1074      libdwarf_error_check ("compilation_unit::sibling", dr, de);
     1075      return true;
     1076    }
     1077
     1078    file&
     1079    debug_info_entry::get_debug ()
     1080    {
     1081      return debug;
     1082    }
     1083
    4761084    void
    4771085    debug_info_entry::dealloc ()
     
    4801088        ::dwarf_dealloc (debug, die, DW_DLA_DIE);
    4811089        die = nullptr;
     1090      }
     1091    }
     1092
     1093    void
     1094    debug_info_entry::dump (std::string prefix, bool newline)
     1095    {
     1096      const char* s;
     1097      ::dwarf_get_TAG_name (tag (), &s);
     1098      std::cout << prefix << s << std::endl;
     1099
     1100      dwarf_attribute* attributes;
     1101      dwarf_signed     attr_count;
     1102      dwarf_error      de;
     1103      int              dr;
     1104
     1105      dr = ::dwarf_attrlist (die, &attributes, &attr_count, &de);
     1106      if (dr == DW_DLV_OK)
     1107      {
     1108        for (int a = 0; a < attr_count; ++a)
     1109        {
     1110          dwarf_attr attr;
     1111          dr = ::dwarf_whatattr (attributes[a], &attr, &de);
     1112          libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1113          dwarf_half form;
     1114          dr = ::dwarf_whatform (attributes[a], &form, &de);
     1115          libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1116          const char* f;
     1117          dwarf_get_FORM_name (form, &f);
     1118          dwarf_get_AT_name (attr, &s);
     1119          if (a > 0)
     1120            std::cout << std::endl;
     1121          std::cout << prefix << " - " << s << " (" << attr << ") [" << f << ']';
     1122          debug_info_entry v_die (debug);
     1123          address_ranges   v_ranges (debug);
     1124          dwarf_unsigned   v_unsigned;
     1125          dwarf_bool       v_bool;
     1126          dwarf_offset     v_offset;
     1127          switch (form)
     1128          {
     1129            case DW_FORM_block:
     1130            case DW_FORM_block1:
     1131            case DW_FORM_block2:
     1132            case DW_FORM_block4:
     1133              break;
     1134            case DW_FORM_addr:
     1135            case DW_FORM_data1:
     1136            case DW_FORM_data2:
     1137            case DW_FORM_data4:
     1138            case DW_FORM_data8:
     1139            case DW_FORM_udata:
     1140              dr = ::dwarf_attrval_unsigned (die, attr, &v_unsigned, &de);
     1141              libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1142              std::cout << " : "
     1143                        << std::hex << std::setfill ('0')
     1144                        << std::setw (8) << v_unsigned
     1145                        << std::dec << std::setfill (' ')
     1146                        << " (" << v_unsigned << ')';
     1147              break;
     1148            case DW_FORM_ref1:
     1149            case DW_FORM_ref2:
     1150            case DW_FORM_ref4:
     1151            case DW_FORM_ref8:
     1152            case DW_FORM_ref_udata:
     1153              dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
     1154              libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1155              std::cout << " : "
     1156                        << std::hex << std::setfill ('0')
     1157                        << std::setw (8) << v_offset
     1158                        << std::dec << std::setfill (' ')
     1159                        << " (" << v_offset << ')';
     1160              switch (attr)
     1161              {
     1162                case DW_AT_abstract_origin:
     1163                case DW_AT_specification:
     1164                  v_die = v_offset;
     1165                  std::cout << std::endl;
     1166                  v_die.dump (' ' + prefix, false);
     1167                  break;
     1168                default:
     1169                  break;
     1170              }
     1171              break;
     1172            case DW_FORM_exprloc:
     1173              break;
     1174            case DW_FORM_flag:
     1175            case DW_FORM_flag_present:
     1176              dr = ::dwarf_attrval_flag (die, attr, &v_bool, &de);
     1177              libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1178              std::cout << " : " << v_bool;
     1179              break;
     1180              break;
     1181            case DW_FORM_string:
     1182            case DW_FORM_strp:
     1183              dr = ::dwarf_attrval_string (die, attr, &s, &de);
     1184              libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1185              std::cout << " : " << s;
     1186              break;
     1187            case DW_FORM_sec_offset:
     1188              switch (attr)
     1189              {
     1190                case DW_AT_ranges:
     1191                  dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
     1192                  libdwarf_error_check ("debug_info_entry::dump", dr, de);
     1193                  std::cout << ' ';
     1194                  v_ranges.load (v_offset);
     1195                  v_ranges.dump ();
     1196                  break;
     1197                default:
     1198                  break;
     1199              }
     1200              break;
     1201            case DW_FORM_indirect:
     1202            case DW_FORM_ref_addr:
     1203            case DW_FORM_ref_sig8:
     1204            case DW_FORM_sdata:
     1205              break;
     1206          }
     1207        }
     1208        if (newline)
     1209          std::cout << std::endl;
     1210      }
     1211    }
     1212
     1213    void
     1214    die_dump_children (debug_info_entry die,
     1215                       std::string      prefix,
     1216                       int              nesting,
     1217                       int              depth)
     1218    {
     1219      debug_info_entry child (die.get_debug ());
     1220      if (die.get_child (child))
     1221        die_dump (child, prefix, nesting, depth);
     1222    }
     1223
     1224    void
     1225    die_dump (debug_info_entry die,
     1226              std::string      prefix,
     1227              int              nesting,
     1228              int              depth)
     1229    {
     1230      ++nesting;
     1231
     1232      for (int n = 0; n < nesting; ++n)
     1233        prefix += ' ';
     1234
     1235      while (true)
     1236      {
     1237        die.dump (prefix);
     1238
     1239        if (depth < 0 || nesting < depth)
     1240          die_dump_children (die, prefix);
     1241
     1242        debug_info_entry next (die.get_debug ());
     1243
     1244        if (!die.get_sibling (next))
     1245          break;
     1246
     1247        die = next;
    4821248      }
    4831249    }
     
    4901256        pc_low_ (0),
    4911257        pc_high_ (0),
     1258        ranges_ (debug),
    4921259        die_offset (die.offset ()),
    4931260        source_ (debug, die_offset)
     
    4981265      die.attribute (DW_AT_producer, producer_);
    4991266
    500       die.attribute (DW_AT_low_pc, pc_low_, false);
    501 
    502       if (!die.attribute (DW_AT_high_pc, pc_high_, false))
    503         pc_high_ = ~0U;
    504 
    505       if (pc_high_ < pc_low_)
    506         pc_high_ += pc_low_;
     1267      ranges_.load (die, false);
     1268
     1269      if (ranges_.empty ())
     1270      {
     1271        bool is_address;
     1272        die.get_lowpc (pc_low_);
     1273        if (die.get_highpc (pc_high_, is_address))
     1274        {
     1275          if (!is_address)
     1276            pc_high_ += pc_low_;
     1277        }
     1278        else
     1279          pc_high_ = ~0U;
     1280      }
     1281      else
     1282      {
     1283        pc_low_ = ~0U;
     1284        for (auto& r : ranges_.get ())
     1285        {
     1286          if (!r.end () && !r.empty () && r.addr1 () < pc_low_)
     1287            pc_low_ = r.addr1 ();
     1288        }
     1289        pc_high_ = 0U;
     1290        for (auto& r : ranges_.get ())
     1291        {
     1292          if (!r.end () && !r.empty () && r.addr2 () > pc_high_)
     1293            pc_high_ = r.addr2 ();
     1294        }
     1295      }
    5071296
    5081297      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
     
    5131302                  << ": (0x" << std::setw (8) << offset_ << ") ";
    5141303        if (pc_low_ != 0 && pc_high_ != ~0U)
    515           std::cout << "pc_low = " << std::setw (8) << pc_low_
    516                     << " pc_high = " << std::setw (8) << pc_high_;
     1304          std::cout << "pc_low = 0x" << std::setw (8) << pc_low_
     1305                    << " pc_high = 0x" << std::setw (8) << pc_high_;
    5171306       std::cout  << std::setfill (' ') << std::dec
    5181307                  << std::endl
     
    6111400        pc_low_ (orig.pc_low_),
    6121401        pc_high_ (orig.pc_high_),
     1402        ranges_ (orig.ranges_),
    6131403        die_offset (orig.die_offset),
    6141404        source_ (debug, die_offset)
     
    6211411    compilation_unit::~compilation_unit ()
    6221412    {
     1413    }
     1414
     1415    void
     1416    compilation_unit::load_types ()
     1417    {
     1418      //dump_die ();
     1419    }
     1420
     1421    void
     1422    compilation_unit::load_functions ()
     1423    {
     1424      debug_info_entry die (debug, die_offset);
     1425      debug_info_entry ret_die (debug);
     1426      dwarf_error      de;
     1427      int              dr;
     1428      dr = ::dwarf_child(die, ret_die, &de);
     1429      if (dr == DW_DLV_OK)
     1430        load_functions (ret_die);
     1431    }
     1432
     1433    void
     1434    compilation_unit::load_functions (debug_info_entry& die)
     1435    {
     1436      while (true)
     1437      {
     1438        if (die.tag () == DW_TAG_subprogram ||
     1439            die.tag () == DW_TAG_entry_point ||
     1440            die.tag () == DW_TAG_inlined_subroutine)
     1441        {
     1442          function func (debug, die);
     1443          if (func.has_machine_code () &&
     1444              func.pc_low () >= pc_low_ && func.pc_high () <= pc_high_)
     1445          {
     1446            functions_.push_back (func);
     1447          }
     1448        }
     1449
     1450        debug_info_entry ret_die (debug);
     1451        dwarf_error      de;
     1452        int              dr;
     1453
     1454        dr = ::dwarf_child(die, ret_die, &de);
     1455        if (dr == DW_DLV_OK)
     1456          load_functions (ret_die);
     1457
     1458        dr = ::dwarf_siblingof (debug, die, ret_die, &de);
     1459        if (dr == DW_DLV_NO_ENTRY)
     1460          break;
     1461        libdwarf_error_check ("compilation_unit:load_functions", dr, de);
     1462
     1463        die = ret_die;
     1464      }
    6231465    }
    6241466
     
    6701512    }
    6711513
     1514    functions&
     1515    compilation_unit::get_functions ()
     1516    {
     1517      return functions_;
     1518    }
     1519
    6721520    bool
    6731521    compilation_unit::inside (dwarf_unsigned addr) const
    6741522    {
    675       if (!addr_lines_.empty ())
    676       {
    677         auto first = addr_lines_.begin ();
    678         auto last = addr_lines_.end () - 1;
    679         return first->location () <= addr && addr <= last->location ();
    680       }
    6811523      return addr >= pc_low_ && addr < pc_high_;
    6821524    }
     
    7011543        pc_low_ = rhs.pc_low_;
    7021544        pc_high_ = rhs.pc_high_;
     1545        ranges_ = rhs.ranges_;
    7031546        die_offset = rhs.die_offset;
    7041547      }
    7051548      return *this;
     1549    }
     1550
     1551    void
     1552    compilation_unit::dump_die ()
     1553    {
     1554      debug_info_entry die (debug, die_offset);
     1555      std::cout << "CU @ 0x" << std::hex << offset_ << std::dec << std::endl;
     1556      die_dump_children (die, "");
    7061557    }
    7071558
     
    7371588      : debug (nullptr),
    7381589        elf_ (nullptr)
    739       {
     1590    {
    7401591    }
    7411592
     
    8311682
    8321683        /*
    833          * Fnd the CU DIE.
     1684         * Find the CU DIE.
    8341685         */
    8351686        debug_info_entry die (*this);
     
    8531704        cu_offset = cu_next_offset;
    8541705      }
     1706    }
     1707
     1708    void
     1709    file::load_types ()
     1710    {
     1711      for (auto& cu : cus)
     1712        cu.load_types ();
     1713    }
     1714
     1715    void
     1716    file::load_functions ()
     1717    {
     1718      for (auto& cu : cus)
     1719        cu.load_functions ();
    8551720    }
    8561721
     
    8991764    }
    9001765
     1766    bool
     1767    file::get_function (const unsigned int addr,
     1768                        std::string&       name)
     1769    {
     1770      name = "unknown";
     1771
     1772      for (auto& cu : cus)
     1773      {
     1774        for (auto& func : cu.get_functions ())
     1775        {
     1776          if (func.inside (addr))
     1777          {
     1778            name = func.name ();
     1779            return true;
     1780          }
     1781        }
     1782      }
     1783
     1784      return false;
     1785    }
     1786
    9011787    void
    9021788    file::get_producer_sources (producer_sources& producers)
  • rtemstoolkit/rld-dwarf.h

    r1318c11 rd8eef0a  
    115115
    116116    /**
     117     * Range, one entry in an address range container.
     118     */
     119    class range
     120    {
     121    public:
     122      range (const dwarf_ranges* range);
     123      range (const range& orig);
     124      ~range ();
     125
     126      /**
     127       * Address 1 in the range.
     128       */
     129      dwarf_unsigned addr1 () const;
     130      dwarf_unsigned addr2 () const;
     131
     132      /**
     133       * Get the type of range.
     134       */
     135      dwarf_ranges_type type () const;
     136
     137      /**
     138       * Is the range the end?
     139       */
     140      bool end () const;
     141
     142      /**
     143       * Is the range empty? See DWARF 2.17.3.
     144       */
     145      bool empty () const;
     146
     147      /**
     148       * Assigment operator.
     149       */
     150      range& operator = (const range& rhs);
     151
     152      /**
     153       * Dump the range.
     154       */
     155      void dump ();
     156
     157    private:
     158
     159      const dwarf_ranges* range_;
     160    };
     161
     162    typedef std::vector < range > ranges;
     163
     164    /**
     165     * Address ranges, is a range of addresses.
     166     */
     167    class address_ranges
     168    {
     169    public:
     170      address_ranges (file& debug);
     171      address_ranges (debug_info_entry& die);
     172      address_ranges (file& debug, dwarf_offset offset);
     173      address_ranges (const address_ranges& orig);
     174      ~address_ranges ();
     175
     176      /**
     177       * Load the ranges from the DIE.
     178       */
     179      bool load (debug_info_entry& die, bool error = true);
     180
     181      /**
     182       * Load the ranges from the debug info.
     183       */
     184      bool load (dwarf_offset offset, bool error = true);
     185
     186      /**
     187       * Get the container.
     188       */
     189      const ranges& get () const;
     190
     191      /**
     192       * Address range empty?
     193       */
     194      bool empty () const;
     195
     196      /**
     197       * Assigment operator.
     198       */
     199      address_ranges& operator = (const address_ranges& rhs);
     200
     201      /**
     202       * Dump the address ranges.
     203       */
     204      void dump ();
     205
     206    private:
     207
     208      file&         debug;
     209      dwarf_offset  offset;
     210      dwarf_ranges* dranges;
     211      dwarf_signed  dranges_count;
     212      ranges        ranges_;
     213    };
     214
     215    /**
    117216     * Line addresses.
    118217     */
     
    151250      sources (file& debug, dwarf_offset die_offset);
    152251      sources (const sources& orig);
    153       //sources (sources&& orig);
    154252      ~sources ();
    155253
     
    178276
    179277    /**
     278     * Function.
     279     */
     280    class function
     281    {
     282    public:
     283      function (file& debug, debug_info_entry& die);
     284      ~function ();
     285
     286      /**
     287       * Get the name of the function.
     288       */
     289      std::string name () const;
     290
     291      /**
     292       * Get the linkage name of the function.
     293       */
     294      std::string linkage_name () const;
     295
     296      /**
     297       * Get the ranges for the funcion, if empty the PC low and PC high values
     298       * will be valid.
     299       */
     300      const address_ranges& get_ranges () const;
     301
     302      /**
     303       * Get the PC low address, valid if ranges is empty.
     304       */
     305      dwarf_unsigned pc_low () const;
     306
     307      /**
     308       * Get the PC high address, valid if ranges is empty.
     309       */
     310      dwarf_unsigned pc_high () const;
     311
     312      /**
     313       * Does the function have machine code in the image?
     314       */
     315      bool has_machine_code () const;
     316
     317      /**
     318       * Is the function external?
     319       */
     320      bool is_external () const;
     321
     322      /**
     323       * Is this just a declaration?
     324       */
     325      bool is_declaration () const;
     326
     327      /**
     328       * Is the function inlined?
     329       */
     330      bool is_inlined () const;
     331
     332      /**
     333       * Get the call file of the inlined function.
     334       */
     335      std::string call_file () const;
     336
     337      /**
     338       * Is the address inside the function.
     339       */
     340      bool inside (dwarf_address addr) const;
     341
     342    private:
     343
     344      file&          debug;
     345      bool           machine_code_;
     346      bool           external_;
     347      bool           declaration_;
     348      dwarf_unsigned inline_;
     349      dwarf_unsigned pc_low_;
     350      dwarf_unsigned pc_high_;
     351      address_ranges ranges_;
     352      std::string    name_;
     353      std::string    linkage_name_;
     354      std::string    call_file_;
     355    };
     356
     357    typedef std::vector < function > functions;
     358
     359    /**
    180360     * Debug Information Element (DIE).
    181361     *
     
    191371      debug_info_entry (file& debug, dwarf_die& die);
    192372      debug_info_entry (file& debug, dwarf_offset offset);
     373      debug_info_entry (const debug_info_entry& orig);
    193374
    194375      /**
     
    212393       */
    213394      debug_info_entry& operator = (debug_info_entry& rhs);
     395      debug_info_entry& operator = (dwarf_offset offset);
    214396
    215397      /**
     
    228410       */
    229411      dwarf_offset offset ();
     412
     413      /**
     414       * Get the low PC.
     415       */
     416      bool get_lowpc (dwarf_address& addr, bool error = false) const;
     417
     418      /**
     419       * Get the high PC.
     420       */
     421      bool get_highpc (dwarf_address& addr,
     422                       bool&          is_address,
     423                       bool           error = false) const;
     424
     425      /**
     426       * Get an attribute.
     427       */
     428      bool attribute (dwarf_attr       attr,
     429                      dwarf_attribute& value,
     430                      bool             error = true) const;
     431
     432      /**
     433       * Get a flag.
     434       */
     435      bool attribute (dwarf_attr  attr,
     436                      dwarf_bool& value,
     437                      bool        error = true) const;
    230438
    231439      /**
     
    258466
    259467      /**
     468       * Get the ranges.
     469       */
     470      bool ranges (dwarf_ranges*& ranges, dwarf_signed& rangescount) const;
     471
     472      /**
     473       * Get the child.
     474       */
     475      bool get_child (debug_info_entry& child_die);
     476
     477      /**
     478       * Get the silbing
     479       */
     480      bool get_sibling (debug_info_entry& sibling_die);
     481
     482      /**
     483       * Get the debug info for this DIE.
     484       */
     485      file& get_debug ();
     486
     487      /**
    260488       * deallocate the DIE.
    261489       */
    262490      void dealloc ();
     491
     492      /**
     493       * Dump this DIE.
     494       */
     495      void dump (std::string prefix, bool newline = true);
    263496
    264497    private:
     
    270503
    271504    };
     505
     506    /**
     507     * Dump the DIE and all it's children and siblings.
     508     */
     509    void die_dump_children (debug_info_entry die,
     510                            std::string      prefix,
     511                            int              nesting = 0,
     512                            int              depth = -1);
     513
     514    /**
     515     * Dump the DIE and all it's children and siblings.
     516     */
     517    void die_dump (debug_info_entry die,
     518                   std::string      prefix,
     519                   int              nesting = 0,
     520                   int              depth = -1);
    272521
    273522    /**
     
    284533
    285534      /**
     535       * Load the types.
     536       */
     537      void load_types ();
     538
     539      /**
     540       * Load the functions.
     541       */
     542      void load_functions ();
     543
     544      /**
    286545       * Name of the CU.
    287546       */
     
    312571
    313572      /**
     573       * Get the functions.
     574       */
     575      functions& get_functions ();
     576
     577      /**
    314578       * Is the address inside the CU? If the PC low and high attributes are
    315579       * valid they are used or the lines are checked.
     
    322586      compilation_unit& operator = (const compilation_unit& rhs);
    323587
    324     private:
     588      /**
     589       * Output the DIE tree.
     590       */
     591      void dump_die ();
     592
     593    private:
     594
     595      void load_functions (debug_info_entry& die);
    325596
    326597      file&          debug;       ///< The DWARF debug handle.
     
    330601      dwarf_unsigned pc_low_;     ///< The PC low address
    331602      dwarf_unsigned pc_high_;    ///< The PC high address.
     603      address_ranges ranges_;     ///< Non-continous address range.
    332604
    333605      dwarf_offset   die_offset;  ///< The offset of the DIE in the image.
     
    335607      sources        source_;     ///< Sources table for this CU.
    336608      addresses      addr_lines_; ///< Address table.
     609
     610      functions      functions_;  ///< The functions in the CU.
    337611    };
    338612
     
    413687
    414688      /**
     689       * Load the DWARF type information.
     690       */
     691      void load_types ();
     692
     693      /**
     694       * Load the DWARF functions information.
     695       */
     696      void load_functions ();
     697
     698      /**
    415699       * Get the source location given an address.
    416700       */
     
    420704
    421705      /**
     706       * Get the function given an address.
     707       */
     708      bool get_function (const unsigned int address,
     709                         std::string&       name);
     710
     711      /**
    422712       * Get the producer sources from the compilation units.
    423713       */
Note: See TracChangeset for help on using the changeset viewer.