source: rtems-tools/rtemstoolkit/rld-dwarf.cpp @ ff68bcc

Last change on this file since ff68bcc was b4245dd, checked in by Chris Johns <chrisj@…>, on 09/03/21 at 04:43:47

tester/covoar: Fix clang compile errors, revert uneeded changes

  • Property mode set to 100644
File size: 56.9 KB
Line 
1/*
2 * Copyright (c) 2018, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems-ld
20 *
21 * @brief RTEMS Linker DWARF module manages the DWARF format images.
22 *
23 */
24
25#include <string.h>
26
27#include <iostream>
28#include <iomanip>
29#include <list>
30#include <map>
31
32#include <rld.h>
33#include <rld-path.h>
34#include <rld-dwarf.h>
35#include <rld-symbols.h>
36
37namespace rld
38{
39  namespace dwarf
40  {
41    typedef std::vector < dwarf_die > dies_active;
42    dies_active active_dies;
43
44    bool active_dies_present (dwarf_die die)
45    {
46      return std::find (active_dies.begin(), active_dies.end(), die) != active_dies.end();
47    }
48
49    void dies_active_add (dwarf_die die)
50    {
51      if (active_dies_present (die))
52      {
53        std::cout << "DDdd : dup : " << die << std::endl;
54      }
55      else
56      {
57        active_dies.push_back (die);
58      }
59    }
60
61    void dies_active_remove (dwarf_die die)
62    {
63      dies_active::iterator di = std::find (active_dies.begin(), active_dies.end(), die);
64      if (di == active_dies.end ())
65      {
66        std::cout << "DDdd : no found : " << die << std::endl;
67      }
68      else
69      {
70        active_dies.erase (di);
71      }
72    }
73
74    /**
75     * The libdwarf error.
76     */
77    void libdwarf_error_check (const std::string where,
78                               int               result,
79                               dwarf_error&      error)
80    {
81      if (result != DW_DLV_OK)
82      {
83        std::ostringstream exe_where;
84        std::string        what;
85        exe_where << "dwarf:" << where;
86        what = ::dwarf_errmsg (error);
87        throw rld::error (what, exe_where.str ());
88      }
89    }
90
91    address::address (const sources& source, dwarf_line& line)
92      : addr (0),
93        source (&source),
94        source_index (-1),
95        source_line (-1),
96        begin_statement (false),
97        block (false),
98        end_sequence (false)
99    {
100      dwarf_error de;
101      int         dr;
102      dr = ::dwarf_lineaddr(line, &addr, &de);
103      libdwarf_error_check ("address::address", dr, de);
104      dr = ::dwarf_line_srcfileno(line, &source_index, &de);
105      libdwarf_error_check ("address::address", dr, de);
106      dwarf_unsigned src_line;
107      dr = ::dwarf_lineno(line, &src_line, &de);
108      libdwarf_error_check ("address::address", dr, de);
109      source_line = src_line;
110      dwarf_bool b;
111      dr = ::dwarf_linebeginstatement(line, &b, &de);
112      libdwarf_error_check ("address::address", dr, de);
113      begin_statement = b ? true : false;
114      dr = ::dwarf_lineblock(line, &b, &de);
115      libdwarf_error_check ("address::address", dr, de);
116      block = b ? true : false;
117      dr = ::dwarf_lineendsequence(line, &b, &de);
118      libdwarf_error_check ("address::address", dr, de);
119      end_sequence = b ? true : false;
120    }
121
122    address::address (const address& orig, const sources& source)
123      : addr (orig.addr),
124        source (&source),
125        source_index (orig.source_index),
126        source_line (orig.source_line),
127        begin_statement (orig.begin_statement),
128        block (orig.block),
129        end_sequence (orig.end_sequence)
130    {
131    }
132
133    address::address (const address& orig, dwarf_address addr)
134      : addr (addr),
135        source (orig.source),
136        source_index (orig.source_index),
137        source_line (orig.source_line),
138        begin_statement (orig.begin_statement),
139        block (orig.block),
140        end_sequence (orig.end_sequence)
141    {
142    }
143
144    address::address (const address& orig)
145      : addr (orig.addr),
146        source (orig.source),
147        source_index (orig.source_index),
148        source_line (orig.source_line),
149        begin_statement (orig.begin_statement),
150        block (orig.block),
151        end_sequence (orig.end_sequence)
152    {
153    }
154
155    address::address ()
156      : addr (0),
157        source (nullptr),
158        source_index (-1),
159        source_line (-1),
160        begin_statement (false),
161        block (false),
162        end_sequence (false)
163    {
164    }
165
166    address::~address ()
167    {
168      source = nullptr;
169      source_line = -1;
170    }
171
172    bool
173    address::valid () const
174    {
175      return source != nullptr && source_line > 0;
176    }
177
178    dwarf_address
179    address::location () const
180    {
181      return addr;
182    }
183
184    std::string
185    address::path () const
186    {
187      if (source == nullptr)
188        throw rld::error ("invalid source pointer", "dwarf:address:path");
189      return (*source)[source_index];
190    }
191
192    int
193    address::line () const
194    {
195      return source_line;
196    }
197
198    bool
199    address::is_a_begin_statement () const
200    {
201      return begin_statement;
202    }
203
204    bool
205    address::is_in_a_block () const
206    {
207      return block;
208    }
209
210    bool
211    address::is_an_end_sequence () const
212    {
213      return end_sequence;
214    }
215
216    address&
217    address::operator = (const address& rhs)
218    {
219      if (this != &rhs)
220      {
221        addr = rhs.addr;
222        source = rhs.source;
223        source_index = rhs.source_index;
224        source_line = rhs.source_line;
225        begin_statement = rhs.begin_statement;
226        block = rhs.block;
227        end_sequence = rhs.end_sequence;
228      }
229      return *this;
230    }
231
232    bool
233    address::operator < (const address& rhs) const
234    {
235      return addr < rhs.addr;
236    }
237
238    range::range (const dwarf_ranges* range)
239      : range_ (range)
240    {
241    }
242
243    range::range (const range& orig)
244      : range_ (orig.range_)
245    {
246    }
247
248    range::~range ()
249    {
250    }
251
252    dwarf_unsigned
253    range::addr1 () const
254    {
255      if (range_ == nullptr)
256        throw rld::error ("No valid range", "rld:dwarf:range:addr1");
257      return range_->dwr_addr1;
258    }
259
260    dwarf_unsigned
261    range::addr2 () const
262    {
263      if (range_ == nullptr)
264        throw rld::error ("No valid range", "rld:dwarf:range:addr2");
265      return range_->dwr_addr2;
266    }
267
268    dwarf_ranges_type
269    range::type () const
270    {
271      if (range_ == nullptr)
272        throw rld::error ("No valid range", "rld:dwarf:range:type");
273      return range_->dwr_type;
274    }
275
276    bool
277    range::empty () const
278    {
279      /**
280       * See DWARF 2.17.3.
281       *
282       * A bounded range entry whose beginning and ending address offsets are
283       * equal (including zero) indicates an empty range and may be ignored.
284       */
285      return type () == DW_RANGES_ENTRY && addr1 () == addr2 ();
286    }
287
288    bool
289    range::end () const
290    {
291      return type () == DW_RANGES_END;
292    }
293
294    range&
295    range::operator = (const range& rhs)
296    {
297      if (this != &rhs)
298        range_ = rhs.range_;
299      return *this;
300    }
301
302    void
303    range::dump (std::ostream& out) const
304    {
305      dwarf_ranges_type type_ = type ();
306      const char*       type_s = "invalid";
307      const char*       type_labels[] = {
308        "BOUNDED",
309        "BASE",
310        "END"
311      };
312      if (type_ <= DW_RANGES_END)
313        type_s = type_labels[type_];
314      out << type_s << '-'
315          << std::hex << std::setfill ('0')
316          << "0x" << std::setw (8) << addr1 ()
317          << ":0x" << std::setw (8) << addr2 ()
318          << std::dec << std::setfill (' ');
319    }
320
321    address_ranges::address_ranges (file& debug)
322      : debug (debug),
323        offset (-1),
324        dranges (nullptr),
325        dranges_count (0)
326    {
327    }
328
329    address_ranges::address_ranges (debug_info_entry& die)
330      : debug (die.get_debug ()),
331        offset (-1),
332        dranges (nullptr),
333        dranges_count (0)
334    {
335      load (die);
336    }
337
338    address_ranges::address_ranges (file& debug, dwarf_offset offset)
339      : debug (debug),
340        offset (offset),
341        dranges (nullptr),
342        dranges_count (0)
343    {
344      load (offset);
345    }
346
347    address_ranges::address_ranges (const address_ranges& orig)
348      : debug (orig.debug),
349        offset (orig.offset),
350        dranges (nullptr),
351        dranges_count (0)
352    {
353      load (orig.offset);
354    }
355
356    address_ranges::~address_ranges ()
357    {
358      if (dranges != nullptr)
359      {
360        ::dwarf_ranges_dealloc (debug, dranges, dranges_count);
361        dranges = nullptr;
362        dranges_count = 0;
363        ranges_.clear ();
364      }
365    }
366
367    bool
368    address_ranges::load (debug_info_entry& die, bool error)
369    {
370      dwarf_attribute attr;
371      dwarf_error     de;
372      int             dr;
373      dr = ::dwarf_attr (die, DW_AT_ranges, &attr, &de);
374      if (dr != DW_DLV_OK)
375      {
376        if (!error)
377          return false;
378        libdwarf_error_check ("rld:dwarf::address_ranges:load", dr, de);
379      }
380      dr = ::dwarf_global_formref (attr, &offset, &de);
381      if (dr != DW_DLV_OK)
382      {
383        if (!error)
384          return false;
385        libdwarf_error_check ("rld:dwarf::address_ranges:load", dr, de);
386      }
387      load (offset);
388      return true;
389    }
390
391    bool
392    address_ranges::load (dwarf_offset offset_, bool error)
393    {
394      if (offset_ > 0)
395      {
396        if (dranges != nullptr)
397          ::dwarf_ranges_dealloc (debug, dranges, dranges_count);
398
399        ranges_.clear ();
400
401        dranges = nullptr;
402        dranges_count = 0;
403
404        offset = offset_;
405
406        dwarf_error de;
407        int         dr;
408
409        dr = ::dwarf_get_ranges (debug, offset,
410                                 &dranges, &dranges_count, nullptr, &de);
411        if (dr != DW_DLV_OK)
412        {
413          if (!error)
414            return false;
415          libdwarf_error_check ("rld:dwarf::ranges:load", dr, de);
416        }
417
418        if (dranges != nullptr && dranges_count > 0)
419        {
420          for (dwarf_signed r = 0; r < dranges_count; ++r)
421            ranges_.push_back (range (&dranges[r]));
422        }
423      }
424
425      return true;
426    }
427
428    const ranges&
429    address_ranges::get () const
430    {
431      return ranges_;
432    }
433
434    bool
435    address_ranges::empty () const
436    {
437      return ranges_.empty ();
438    }
439
440    address_ranges&
441    address_ranges::operator = (const address_ranges& rhs)
442    {
443      if (this != &rhs)
444      {
445        if (debug != rhs.debug)
446          throw rld::error ("invalid debug", "address_ranges:=");
447        load (rhs.offset);
448      }
449      return *this;
450    }
451
452    void
453    address_ranges::dump (std::ostream& out) const
454    {
455      bool first = true;
456      out << '[';
457      for (auto& r : ranges_)
458      {
459        if (!first)
460          out << ',';
461        r.dump (out);
462        first = false;
463      }
464      out << ']';
465    }
466
467    line_addresses::line_addresses (file&             debug,
468                                    debug_info_entry& die)
469      : debug (debug),
470        lines (nullptr),
471        count_ (0)
472    {
473      if (!die.source_lines (lines, count_))
474      {
475        lines = nullptr;
476        count_ = 0;
477      }
478    }
479
480    line_addresses::~line_addresses ()
481    {
482      if (lines && count_ > 0)
483      {
484        ::dwarf_srclines_dealloc (debug, lines, count_);
485        lines = nullptr;
486        count_ = 0;
487      }
488    }
489
490    size_t
491    line_addresses::count () const
492    {
493      return count_;
494    }
495
496    dwarf_line&
497    line_addresses::operator [] (const int index)
498    {
499      if (index < 0 || index >= count_)
500        throw rld::error ("index out of range",
501                          "line_addresses:indexing");
502      return lines[index];
503    }
504
505    sources::sources (file& debug, dwarf_offset die_offset)
506      : debug (debug),
507        source (nullptr),
508        count (0),
509        die_offset (die_offset)
510    {
511      debug_info_entry die (debug, die_offset);
512      die.source_files (source, count);
513    }
514
515    sources::sources (const sources& orig)
516      : debug (orig.debug),
517        source (nullptr),
518        count (0),
519        die_offset (orig.die_offset)
520    {
521      /*
522       * In a copy constructor we need to get our own copy of the strings. To
523       * do that we need to get the DIE at the offset in the original.
524       */
525      debug_info_entry die (debug, die_offset);
526      die.source_files (source, count);
527    }
528
529    sources::~sources ()
530    {
531      dealloc ();
532    }
533
534    std::string
535    sources::operator [] (const int index) const
536    {
537      if (index <= 0 || index > count)
538        return "unknown";
539      return std::string (source[index - 1]);
540    }
541
542    void
543    sources::dealloc ()
544    {
545      if (source && count > 0)
546      {
547        /*
548         * The elftoolchain cleans the memory up and there is no compatible
549         * call we can put here so adding the required code causes is a double
550         * free resulting in a crash.
551         */
552        if (false)
553        {
554          for (int s = 0; s < count; ++s)
555            ::dwarf_dealloc (debug, source[s], DW_DLA_STRING);
556          ::dwarf_dealloc (debug, source, DW_DLA_LIST);
557        }
558        source = nullptr;
559        count = 0;
560      }
561    }
562
563    sources&
564    sources::operator = (sources&& rhs)
565    {
566      if (this != &rhs)
567      {
568        debug = rhs.debug;
569        source = rhs.source;
570        count = rhs.count;
571        die_offset = rhs.die_offset;
572        rhs.source = nullptr;
573        rhs.count = 0;
574      }
575      return *this;
576    }
577
578    variable::variable (file& debug, debug_info_entry& die)
579      : debug (debug),
580        external_ (false),
581        declaration_ (false)
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      /*
592       * Get the name attribute. (if present)
593       */
594      die.attribute (DW_AT_name, name_);
595      die.attribute (DW_AT_decl_file, decl_file_);
596      die.attribute (DW_AT_decl_line, decl_line_);
597
598      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
599      {
600        std::cout << "dwarf::variable: ";
601        dump (std::cout);
602        std::cout << std::endl;
603      }
604    }
605
606    variable::variable (const variable& orig)
607      : debug (orig.debug),
608        external_ (orig.external_),
609        declaration_ (orig.declaration_),
610        name_ (orig.name_),
611        decl_file_ (orig.decl_file_),
612        decl_line_ (orig. decl_line_)
613    {
614    }
615
616    variable::~variable ()
617    {
618    }
619
620    std::string
621    variable::name () const
622    {
623      return name_;
624    }
625
626    bool
627    variable::is_external () const
628    {
629      return external_;
630    }
631
632    bool
633    variable::is_declaration () const
634    {
635      return declaration_;
636    }
637
638    size_t
639    variable::size () const
640    {
641      size_t s = 0;
642      return s;
643    }
644
645    variable&
646    variable::operator = (const variable& rhs)
647    {
648      if (this != &rhs)
649      {
650        debug = rhs.debug;
651        external_ = rhs.external_;
652        declaration_ = rhs.declaration_;
653        name_ = rhs.name_;
654        decl_file_ = rhs.decl_file_;
655        decl_line_ = rhs.decl_line_;
656      }
657      return *this;
658    }
659
660    void
661    variable::dump (std::ostream& out) const
662    {
663      if (name_.empty ())
664        out << "NO-NAME";
665      else
666        out << name_;
667      out << " ["
668          << (char) (external_ ? 'E' : '-')
669          << (char) (declaration_ ? 'D' : '-')
670          << "] size=" << size ()
671          << std::hex << std::setfill ('0')
672          << " (0x" << size () << ')'
673          << std::dec << std::setfill (' ');
674    }
675
676
677    function::function (file& debug, debug_info_entry& die)
678      : debug (debug),
679        machine_code_ (false),
680        external_ (false),
681        declaration_ (false),
682        prototyped_ (false),
683        inline_ (DW_INL_not_inlined),
684        entry_pc_ (0),
685        has_entry_pc_ (false),
686        pc_low_ (0),
687        pc_high_ (0),
688        ranges_ (debug),
689        linkage_name_ (),
690        decl_line_ (0),
691        call_line_ (0)
692    {
693      dwarf_bool db;
694
695      if (die.attribute (DW_AT_external, db, false))
696        external_ = db ? true : false;
697
698      if (die.attribute (DW_AT_declaration, db, false))
699        declaration_ = db ? true : false;
700
701      if (die.attribute (DW_AT_entry_pc, entry_pc_, false))
702        has_entry_pc_ = true;
703
704      die.attribute (DW_AT_linkage_name, linkage_name_, false);
705      die.attribute (DW_AT_call_file, decl_file_, false);
706      die.attribute (DW_AT_call_line, decl_line_, false);
707      die.attribute (DW_AT_call_file, call_file_, false);
708      die.attribute (DW_AT_call_line, call_line_, false);
709
710      if (!die.attribute (DW_AT_inline, inline_, false))
711        inline_ = DW_INL_not_inlined;
712
713      /*
714       * If ranges are not found see if the PC low and PC high attributes
715       * can be found.
716       */
717      ranges_.load (die, false);
718      if (ranges_.empty ())
719      {
720        bool is_address;
721        if (die.get_lowpc (pc_low_) && die.get_highpc (pc_high_, is_address))
722        {
723          machine_code_ = true;
724          if (!is_address)
725            pc_high_ += pc_low_;
726        }
727      }
728      else
729      {
730        for (auto& r : ranges_.get ())
731        {
732          if (!r.end () && !r.empty ())
733          {
734            machine_code_ = true;
735            break;
736          }
737        }
738      }
739
740      /*
741       * Get the name attribute. (if present)
742       */
743      if (!die.attribute (DW_AT_name, name_, false))
744      {
745        bool found = false;
746
747        /*
748         * For inlined function, the actual name is probably in the DIE
749         * referenced by DW_AT_abstract_origin. (if present)
750         */
751        dwarf_attribute abst_at;
752        if (die.attribute (DW_AT_abstract_origin, abst_at, false))
753        {
754          dwarf_offset abst_at_die_offset;
755          dwarf_error  de;
756          int          dr;
757          dr = ::dwarf_global_formref (abst_at, &abst_at_die_offset, &de);
758          if (dr == DW_DLV_OK)
759          {
760            debug_info_entry abst_at_die (debug, abst_at_die_offset);
761            if (abst_at_die.attribute (DW_AT_name, name_, false))
762            {
763              found = true;
764              abst_at_die.attribute (DW_AT_inline, inline_, false);
765              if (abst_at_die.attribute (DW_AT_external, db, false))
766                external_ = db ? true : false;
767              if (abst_at_die.attribute (DW_AT_declaration, db, false))
768                declaration_ = db ? true : false;
769              abst_at_die.attribute (DW_AT_linkage_name, linkage_name_, false);
770              abst_at_die.attribute (DW_AT_decl_file, decl_file_, false);
771              abst_at_die.attribute (DW_AT_decl_line, decl_line_, false);
772            }
773          }
774        }
775
776        /*
777         * If DW_AT_name is not present, but DW_AT_specification is present,
778         * then probably the actual name is in the DIE referenced by
779         * DW_AT_specification.
780         */
781        if (!found)
782        {
783          dwarf_attribute spec;
784          if (die.attribute (DW_AT_specification, spec, false))
785          {
786            dwarf_offset spec_die_offset;
787            dwarf_error  de;
788            int          dr;
789            dr = ::dwarf_global_formref (spec, &spec_die_offset, &de);
790            if (dr == DW_DLV_OK)
791            {
792              debug_info_entry spec_die (debug, spec_die_offset);
793              if (spec_die.attribute (DW_AT_name, name_, false))
794              {
795                found = true;
796                if (spec_die.attribute (DW_AT_external, db, false))
797                  external_ = db ? true : false;
798                if (spec_die.attribute (DW_AT_declaration, db, false))
799                  declaration_ = db ? true : false;
800                spec_die.attribute (DW_AT_linkage_name, linkage_name_, false);
801                spec_die.attribute (DW_AT_decl_file, decl_file_, false);
802                spec_die.attribute (DW_AT_decl_line, decl_line_, false);
803              }
804            }
805          }
806        }
807      }
808
809      if (!linkage_name_.empty() && name_.empty())
810        rld::symbols::demangle_name(linkage_name_, name_);
811
812      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
813      {
814        std::cout << "dwarf::function: ";
815        dump (std::cout);
816        std::cout << std::endl;
817      }
818    }
819
820    function::function (const function& orig)
821      : debug (orig.debug),
822        machine_code_ (orig.machine_code_),
823        external_ (orig.external_),
824        declaration_ (orig.declaration_),
825        prototyped_ (orig.prototyped_),
826        inline_ (orig.inline_),
827        entry_pc_ (orig.entry_pc_),
828        has_entry_pc_ (orig.has_entry_pc_),
829        pc_low_ (orig.pc_low_),
830        pc_high_ (orig.pc_high_),
831        ranges_ (orig.ranges_),
832        name_ (orig.name_),
833        linkage_name_ (orig.linkage_name_),
834        decl_file_ (orig.decl_file_),
835        decl_line_ (orig.decl_line_),
836        call_file_ (orig.call_file_),
837        call_line_ (orig.call_line_)
838    {
839    }
840
841    function::~function ()
842    {
843    }
844
845    std::string
846    function::name () const
847    {
848      return name_;
849    }
850
851    const address_ranges&
852    function::get_ranges () const
853    {
854      return ranges_;
855    }
856
857    dwarf_unsigned
858    function::pc_low () const
859    {
860      dwarf_address addr = pc_low_;
861      if (!ranges_.empty ())
862      {
863        addr = ~0;
864        for (auto& r : ranges_.get ())
865        {
866          if (!r.end () && !r.empty () && r.addr1 () < addr)
867            addr = r.addr1 ();
868        }
869      }
870      if (has_entry_pc_ && addr < entry_pc_)
871        addr += entry_pc_;
872      return addr;
873    }
874
875    dwarf_unsigned
876    function::pc_high () const
877    {
878      dwarf_address addr = pc_high_;
879      if (!ranges_.empty ())
880      {
881        addr = 0;
882        for (auto& r : ranges_.get ())
883        {
884          if (!r.end () && !r.empty () && r.addr2 () > addr)
885            addr = r.addr2 ();
886        }
887      }
888      if (has_entry_pc_ && addr < entry_pc_)
889        addr += entry_pc_;
890      return addr;
891    }
892
893    bool
894    function::has_entry_pc () const
895    {
896      return has_entry_pc_;
897    }
898
899    bool
900    function::has_machine_code () const
901    {
902      return machine_code_;
903    }
904
905    bool
906    function::is_external () const
907    {
908      return external_;
909    }
910
911    bool
912    function::is_declaration () const
913    {
914      return declaration_;
915    }
916
917    bool
918    function::is_inlined () const
919    {
920      return inline_ == DW_INL_inlined || inline_ == DW_INL_declared_inlined;
921    }
922
923    function::inlined
924    function::get_inlined () const
925    {
926      inlined i = inl_not_inlined;
927      switch (inline_)
928      {
929        default:
930        case DW_INL_not_inlined:
931          break;
932        case DW_INL_inlined:
933          i = inl_inline;
934          break;
935        case DW_INL_declared_not_inlined:
936          i = inl_declared_not_inlined;
937          break;
938        case DW_INL_declared_inlined:
939          i = inl_declared_inlined;
940          break;
941      }
942      return i;
943    }
944
945    std::string
946    function::call_file () const
947    {
948      return call_file_;
949    }
950
951    bool
952    function::inside (dwarf_address addr) const
953    {
954      return !name_.empty () && has_machine_code () &&
955        addr >= pc_low () && addr <= pc_high ();
956    }
957
958    size_t
959    function::size () const
960    {
961      size_t s = 0;
962      if (!name_.empty () && has_machine_code ())
963      {
964        if (ranges_.empty ())
965          s = pc_high () - pc_low ();
966        else
967        {
968          for (auto& r : ranges_.get ())
969          {
970            if (!r.end () && !r.empty ())
971              s += r.addr2 () - r.addr1 ();
972          }
973        }
974      }
975      return s;
976    }
977
978    function&
979    function::operator = (const function& rhs)
980    {
981      if (this != &rhs)
982      {
983        debug = rhs.debug;
984        machine_code_ = rhs.machine_code_;
985        external_ = rhs.external_;
986        declaration_ = rhs.declaration_;
987        inline_ = rhs.inline_;
988        entry_pc_ = rhs.entry_pc_;
989        has_entry_pc_ = rhs.has_entry_pc_;
990        pc_low_ = rhs.pc_low_;
991        pc_high_ = rhs.pc_high_;
992        ranges_ = rhs.ranges_;
993        name_ = rhs.name_;
994        linkage_name_ = rhs.linkage_name_;
995        decl_file_ = rhs.decl_file_;
996        decl_line_ = rhs.decl_line_;
997        call_file_ = rhs.call_file_;
998        call_line_ = rhs.call_line_;
999      }
1000      return *this;
1001    }
1002
1003    void
1004    function::dump (std::ostream& out) const
1005    {
1006      if (name_.empty ())
1007        out << "NO-NAME";
1008      else
1009        out << name_;
1010      out << " ["
1011          << (char) (machine_code_ ? 'M' : '-')
1012          << (char) (external_ ? 'E' : '-')
1013          << (char) (declaration_ ? 'D' : '-')
1014          << (char) (is_inlined () ? 'I' : '-')
1015          << (char) (has_entry_pc_ ? 'P' : '-')
1016          << "] size=" << size ()
1017          << std::hex << std::setfill ('0')
1018          << " (0x" << size () << ')';
1019      if (has_entry_pc_)
1020        out << " epc=0x" << entry_pc_;
1021      out << " pc_low=0x" << pc_low_
1022          << " pc_high=0x" << pc_high_;
1023      if (!linkage_name_.empty ())
1024      {
1025        std::string show_name;
1026        rld::symbols::demangle_name(linkage_name_, show_name);
1027        out << " ln=" << show_name;
1028      }
1029      out << std::dec << std::setfill (' ');
1030      if (!call_file_.empty ())
1031        out << " cf=" << call_file_ << ':' << call_line_;
1032      if (!ranges_.empty ())
1033      {
1034        out << " ranges=";
1035        ranges_.dump (out);
1036      }
1037    }
1038
1039    bool
1040    function_compare::operator () (const function& a,
1041                                   const function& b) const
1042    {
1043      bool r = true;
1044
1045      switch (by)
1046      {
1047        case fc_by_name:
1048        default:
1049          r =  a.name () < b.name ();
1050          break;
1051        case fc_by_size:
1052          r = a.size () < b.size ();
1053          break;
1054        case fc_by_address:
1055          r = a.pc_low () < b.pc_low ();
1056          break;
1057      }
1058
1059      return r;
1060    }
1061
1062    function_compare:: function_compare (const function_compare::sort_by by)
1063      : by (by)
1064    {
1065    }
1066
1067    debug_info_entry::debug_info_entry (file& debug)
1068      : debug (debug),
1069        die (nullptr),
1070        tag_ (0),
1071        offset_ (0)
1072    {
1073    }
1074
1075    debug_info_entry::debug_info_entry (file& debug, dwarf_die& die)
1076      : debug (debug),
1077        die (die),
1078        tag_ (0),
1079        offset_ (0)
1080    {
1081      update ();
1082    }
1083
1084    debug_info_entry::debug_info_entry (file& debug, dwarf_offset offset__)
1085      : debug (debug),
1086        die (nullptr),
1087        tag_ (0),
1088        offset_ (offset__)
1089    {
1090      update ();
1091    }
1092
1093    debug_info_entry::debug_info_entry (const debug_info_entry& orig)
1094      : debug (orig.debug),
1095        die (nullptr),
1096        tag_ (orig.tag_),
1097        offset_ (orig.offset_)
1098    {
1099      update ();
1100    }
1101
1102    debug_info_entry::~debug_info_entry ()
1103    {
1104      dealloc ();
1105    }
1106
1107    void
1108    debug_info_entry::update ()
1109    {
1110      dwarf_error de;
1111      int         dr;
1112      if (offset_ == 0 && die != nullptr)
1113      {
1114        dr = ::dwarf_dieoffset (die, &offset_, &de);
1115        libdwarf_error_check ("debug_info_entry:update", dr, de);
1116      }
1117      if (offset_ != 0 && die == nullptr)
1118      {
1119        dwarf_die ddie;
1120        dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
1121        libdwarf_error_check ("debug_info_entry:update", dr, de);
1122        die = ddie;
1123      }
1124      valid ();
1125    }
1126
1127    bool
1128    debug_info_entry::valid (bool fatal) const
1129    {
1130      bool r = die == nullptr || offset_ == 0;
1131      if (r && fatal)
1132      {
1133        std::string what = "no DIE and offset";
1134        if (offset_ != 0)
1135          what = "no DIE";
1136        else if (die != nullptr)
1137          what = "no offset";
1138        throw rld::error (what, "debug_info_entry:valid");
1139      }
1140      return r;
1141    }
1142
1143    dwarf_die
1144    debug_info_entry::get () const
1145    {
1146      return die;
1147    }
1148
1149    debug_info_entry::operator dwarf_die& ()
1150    {
1151      return die;
1152    }
1153
1154    debug_info_entry::operator dwarf_die* ()
1155    {
1156      return &die;
1157    }
1158
1159    debug_info_entry&
1160    debug_info_entry::operator = (debug_info_entry& rhs)
1161    {
1162      if (this != &rhs)
1163      {
1164        if (debug != rhs.debug)
1165          throw rld::error ("DIE debug info mismatch",
1166                            "dwarf:debug_info_entry:operator=");
1167        dealloc ();
1168        die = rhs.die;
1169        tag_ = rhs.tag_;
1170        offset_ = rhs.offset_;
1171        rhs.die = nullptr;
1172        if (offset_ != 0 || die != nullptr)
1173          update ();
1174      }
1175      return *this;
1176    }
1177
1178    debug_info_entry&
1179    debug_info_entry::operator = (dwarf_offset offset__)
1180    {
1181      dealloc ();
1182      if (offset__ != 0)
1183      {
1184        offset_ = offset__;
1185        tag_ = 0;
1186        update ();
1187      }
1188      return *this;
1189    }
1190
1191    bool
1192    debug_info_entry::operator == (debug_info_entry& rhs) const
1193    {
1194      return debug == rhs.debug && die == rhs.die &&
1195        tag_ == rhs.tag_ && offset_ == rhs.offset_;
1196    }
1197
1198    bool
1199    debug_info_entry::operator == (const dwarf_die rhs) const
1200    {
1201      return die == rhs;
1202    }
1203
1204    dwarf_tag
1205    debug_info_entry::tag ()
1206    {
1207      if (tag_ == 0)
1208      {
1209        dwarf_error de;
1210        int         dr;
1211        dr = ::dwarf_tag (die, &tag_, &de);
1212        libdwarf_error_check ("debug_info_entry:tag", dr, de);
1213      }
1214      return tag_;
1215    }
1216
1217    dwarf_offset
1218    debug_info_entry::offset ()
1219    {
1220      if (offset_ == 0)
1221      {
1222        dwarf_error de;
1223        int         dr;
1224        dr = ::dwarf_dieoffset (die, &offset_, &de);
1225        libdwarf_error_check ("debug_info_entry:offset", dr, de);
1226      }
1227      return offset_;
1228    }
1229
1230    bool
1231    debug_info_entry::get_lowpc (dwarf_address& addr, bool error) const
1232    {
1233      dwarf_error de;
1234      int         dr;
1235      dr = ::dwarf_lowpc (die, &addr, &de);
1236      if (error)
1237        libdwarf_error_check ("debug_info_entry:lowpc", dr, de);
1238      return dr == DW_DLV_OK;
1239    }
1240
1241    bool
1242    debug_info_entry::get_highpc (dwarf_address& addr,
1243                                  bool&          is_address,
1244                                  bool           error) const
1245    {
1246      dwarf_half       form;
1247      dwarf_form_class class_;
1248      dwarf_error      de;
1249      int              dr;
1250      dr = ::dwarf_highpc_b (die, &addr, &form, &class_, &de);
1251      if (error)
1252        libdwarf_error_check ("debug_info_entry:highpc", dr, de);
1253      is_address = class_ == DW_FORM_CLASS_ADDRESS;
1254      return dr == DW_DLV_OK;
1255    }
1256
1257    bool
1258    debug_info_entry::attribute (dwarf_attr       attr,
1259                                 dwarf_attribute& value,
1260                                 bool             error) const
1261    {
1262      dwarf_error de;
1263      int         dr;
1264      dr = ::dwarf_attr (die, attr, &value, &de);
1265      if (error)
1266        libdwarf_error_check ("debug_info_entry:attribute(attr)", dr, de);
1267      return dr == DW_DLV_OK;
1268    }
1269
1270    bool
1271    debug_info_entry::attribute (dwarf_attr  attr,
1272                                 dwarf_bool& value,
1273                                 bool        error) const
1274    {
1275      dwarf_error de;
1276      int         dr;
1277      dr = ::dwarf_attrval_flag (die, attr, &value, &de);
1278      if (error)
1279        libdwarf_error_check ("debug_info_entry:attribute(flag)", dr, de);
1280      return dr == DW_DLV_OK;
1281    }
1282
1283    bool
1284    debug_info_entry::attribute (dwarf_attr      attr,
1285                                 dwarf_unsigned& value,
1286                                 bool            error) const
1287    {
1288      dwarf_error de;
1289      int         dr;
1290      dr = ::dwarf_attrval_unsigned (die, attr, &value, &de);
1291      if (error)
1292        libdwarf_error_check ("debug_info_entry:attribute(unsigned)", dr, de);
1293      return dr == DW_DLV_OK;
1294    }
1295
1296    bool
1297    debug_info_entry::attribute (dwarf_attr   attr,
1298                                 std::string& value,
1299                                 bool         error) const
1300    {
1301      dwarf_error de;
1302      int         dr;
1303      const char* s = nullptr;
1304      value.clear ();
1305      dr = ::dwarf_attrval_string (die, attr, &s, &de);
1306      if (error)
1307        libdwarf_error_check ("debug_info_entry:attribute(string)", dr, de);
1308      if (s != nullptr)
1309        value = s;
1310      return dr == DW_DLV_OK;
1311    }
1312
1313    bool
1314    debug_info_entry::source_lines (dwarf_line*&  lines,
1315                                    dwarf_signed& linecount) const
1316    {
1317      dwarf_error de;
1318      int         dr;
1319      if (lines != nullptr)
1320        throw rld::error ("lines is not null", "debug_info_entry:source_lines");
1321      linecount = 0;
1322      dr = ::dwarf_srclines (die, &lines, &linecount, &de);
1323      if (dr ==  DW_DLV_NO_ENTRY)
1324        return false;
1325      libdwarf_error_check ("debug_info_entry:source_lines ", dr, de);
1326      return true;
1327    }
1328
1329    void
1330    debug_info_entry::source_files (char**&       sources,
1331                                    dwarf_signed& sourcecount) const
1332    {
1333      dwarf_error de;
1334      int         dr;
1335      dr = ::dwarf_srcfiles (die, &sources, &sourcecount, &de);
1336      libdwarf_error_check ("debug_info_entry:source_files ", dr, de);
1337    }
1338
1339    bool
1340    debug_info_entry::ranges (dwarf_ranges*& ranges,
1341                              dwarf_signed&  rangescount) const
1342    {
1343      dwarf_unsigned ranges_off;
1344      if (attribute (DW_AT_ranges, ranges_off, false))
1345      {
1346        dwarf_error de;
1347        int         dr;
1348        dr = ::dwarf_get_ranges (debug, ranges_off,
1349                                 &ranges, &rangescount, nullptr, &de);
1350        libdwarf_error_check ("debug_info_entry:ranges ", dr, de);
1351        return ranges != nullptr && rangescount > 0;
1352      }
1353      return false;
1354    }
1355
1356    bool
1357    debug_info_entry::get_child (debug_info_entry& child_die)
1358    {
1359      debug_info_entry ret_die (get_debug ());
1360      dwarf_error      de;
1361      int              dr;
1362      dr = ::dwarf_child (die, ret_die, &de);
1363      if (dr == DW_DLV_OK)
1364      {
1365        ret_die.update ();
1366        child_die = ret_die;
1367        child_die.valid ();
1368      }
1369      return dr == DW_DLV_OK;
1370    }
1371
1372    bool
1373    debug_info_entry::has_child () const
1374    {
1375      debug_info_entry ret_die (get_debug ());
1376      dwarf_error      de;
1377      int              dr;
1378      dr = ::dwarf_child (die, ret_die, &de);
1379      return dr == DW_DLV_OK;
1380    }
1381
1382    bool
1383    debug_info_entry::get_sibling (debug_info_entry& sibling_die)
1384    {
1385      debug_info_entry ret_die (get_debug ());
1386      dwarf_error      de;
1387      int              dr;
1388      dr = ::dwarf_siblingof (debug, die, ret_die, &de);
1389      if (dr == DW_DLV_NO_ENTRY)
1390        return false;
1391      libdwarf_error_check ("compilation_unit::sibling", dr, de);
1392      sibling_die = ret_die;
1393      return true;
1394    }
1395
1396    bool
1397    debug_info_entry::has_sibling () const
1398    {
1399      debug_info_entry ret_die (get_debug ());
1400      dwarf_error      de;
1401      int              dr;
1402      dr = ::dwarf_siblingof (debug, die, ret_die, &de);
1403      return dr == DW_DLV_OK;
1404    }
1405
1406    file&
1407    debug_info_entry::get_debug () const
1408    {
1409      return debug;
1410    }
1411
1412    void
1413    debug_info_entry::dealloc ()
1414    {
1415      if (die != nullptr) {
1416        ::dwarf_dealloc (debug, die, DW_DLA_DIE);
1417        die = nullptr;
1418      }
1419    }
1420
1421    void
1422    debug_info_entry::dump (std::ostream& out,
1423                            std::string   prefix,
1424                            bool          newline)
1425    {
1426      std::string level_prefix;
1427
1428      for (auto c : prefix)
1429      {
1430        switch (c)
1431        {
1432          case '+':
1433            c = '|';
1434            break;
1435          case '-':
1436            c = ' ';
1437            break;
1438          default:
1439            break;
1440        }
1441        level_prefix += c;
1442      }
1443
1444      const char* s;
1445      ::dwarf_get_TAG_name (tag (), &s);
1446      out << level_prefix.substr (0, level_prefix.length () - 1)
1447          << "+- " << s << " ("
1448          << std::hex << std::setfill ('0')
1449          << std::setw (8) << offset_
1450          << std::dec << std::setfill (' ')
1451          << ')' << std::endl;
1452
1453      dwarf_attribute* attributes;
1454      dwarf_signed     attr_count;
1455      dwarf_error      de;
1456      int              dr;
1457
1458      dr = ::dwarf_attrlist (die, &attributes, &attr_count, &de);
1459      if (dr == DW_DLV_OK)
1460      {
1461        for (int a = 0; a < attr_count; ++a)
1462        {
1463          dwarf_attr attr;
1464          dr = ::dwarf_whatattr (attributes[a], &attr, &de);
1465          libdwarf_error_check ("debug_info_entry::dump", dr, de);
1466          dwarf_half form;
1467          dr = ::dwarf_whatform (attributes[a], &form, &de);
1468          libdwarf_error_check ("debug_info_entry::dump", dr, de);
1469          const char* f;
1470          dwarf_get_FORM_name (form, &f);
1471          dwarf_get_AT_name (attr, &s);
1472          if (a > 0)
1473            out << std::endl;
1474          out << level_prefix << " +- "
1475              << s << " (" << attr << ") [" << f << ']';
1476          debug_info_entry v_die (debug);
1477          address_ranges   v_ranges (debug);
1478          dwarf_unsigned   v_unsigned;
1479          dwarf_bool       v_bool;
1480          dwarf_offset     v_offset;
1481          switch (form)
1482          {
1483            case DW_FORM_block:
1484            case DW_FORM_block1:
1485            case DW_FORM_block2:
1486            case DW_FORM_block4:
1487              break;
1488            case DW_FORM_addr:
1489            case DW_FORM_data1:
1490            case DW_FORM_data2:
1491            case DW_FORM_data4:
1492            case DW_FORM_data8:
1493            case DW_FORM_udata:
1494              dr = ::dwarf_attrval_unsigned (die, attr, &v_unsigned, &de);
1495              libdwarf_error_check ("debug_info_entry::dump", dr, de);
1496              s = "";
1497              switch (attr)
1498              {
1499                case DW_AT_inline:
1500                  dwarf_get_INL_name(v_unsigned, &s);
1501                  break;
1502                default:
1503                  break;
1504              }
1505              out << " : "
1506                  << std::hex << std::setfill ('0')
1507                  << std::setw (8) << v_unsigned
1508                  << std::dec << std::setfill (' ')
1509                  << " (" << v_unsigned << ") " << s;
1510              break;
1511            case DW_FORM_ref1:
1512            case DW_FORM_ref2:
1513            case DW_FORM_ref4:
1514            case DW_FORM_ref8:
1515            case DW_FORM_ref_udata:
1516              dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
1517              libdwarf_error_check ("debug_info_entry::dump", dr, de);
1518              out << " : "
1519                  << std::hex << std::setfill ('0')
1520                  << std::setw (8) << v_offset
1521                  << std::dec << std::setfill (' ')
1522                  << " (" << v_offset << ')';
1523              switch (attr)
1524              {
1525                case DW_AT_abstract_origin:
1526                case DW_AT_specification:
1527                  v_die = v_offset;
1528                  out << std::endl;
1529                  v_die.dump (out, prefix + " |  ", false);
1530                  break;
1531                default:
1532                  break;
1533              }
1534              break;
1535            case DW_FORM_exprloc:
1536              break;
1537            case DW_FORM_flag:
1538            case DW_FORM_flag_present:
1539              dr = ::dwarf_attrval_flag (die, attr, &v_bool, &de);
1540              libdwarf_error_check ("debug_info_entry::dump", dr, de);
1541              out << " : " << v_bool;
1542              break;
1543              break;
1544            case DW_FORM_string:
1545            case DW_FORM_strp:
1546              dr = ::dwarf_attrval_string (die, attr, &s, &de);
1547              libdwarf_error_check ("debug_info_entry::dump", dr, de);
1548              out << " : " << s;
1549              if (rld::symbols::is_cplusplus(s))
1550              {
1551                std::string cpps;
1552                rld::symbols::demangle_name(s, cpps);
1553                out << " `" << cpps << '`';
1554              }
1555              break;
1556            case DW_FORM_sec_offset:
1557              switch (attr)
1558              {
1559                case DW_AT_ranges:
1560                  dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
1561                  libdwarf_error_check ("debug_info_entry::dump", dr, de);
1562                  out << ' ';
1563                  v_ranges.load (v_offset);
1564                  v_ranges.dump (out);
1565                  break;
1566                default:
1567                  break;
1568              }
1569              break;
1570            case DW_FORM_indirect:
1571            case DW_FORM_ref_addr:
1572            case DW_FORM_ref_sig8:
1573            case DW_FORM_sdata:
1574              break;
1575          }
1576        }
1577        if (newline)
1578          out <<  std::endl;
1579      }
1580    }
1581
1582    void
1583    die_dump_children (debug_info_entry& die,
1584                       std::ostream&     out,
1585                       std::string       prefix,
1586                       int               depth,
1587                       int               nesting)
1588    {
1589      debug_info_entry child (die.get_debug ());
1590      if (die.get_child (child))
1591        die_dump (child, out, prefix, depth, nesting);
1592    }
1593
1594    void
1595    die_dump (debug_info_entry& die,
1596              std::ostream&     out,
1597              std::string       prefix,
1598              int               depth,
1599              int               nesting)
1600    {
1601      ++nesting;
1602
1603      while (true)
1604      {
1605        char v = die.has_sibling () || die.has_child () ? '+' : ' ';
1606
1607        die.dump (out, prefix + v);
1608
1609        if (depth < 0 || nesting < depth)
1610          die_dump_children (die, out, prefix + "+   ", depth, nesting);
1611
1612        debug_info_entry next (die.get_debug ());
1613
1614        if (!die.get_sibling (next))
1615          break;
1616
1617        die = next;
1618      }
1619    }
1620
1621    compilation_unit::compilation_unit (file&             debug,
1622                                        debug_info_entry& die,
1623                                        dwarf_unsigned    offset)
1624      : debug (debug),
1625        offset_ (offset),
1626        pc_low_ (0),
1627        pc_high_ (0),
1628        ranges_ (debug),
1629        die_offset (die.offset ()),
1630        source_ (debug, die_offset)
1631    {
1632      die.attribute (DW_AT_name, name_);
1633
1634      die.attribute (DW_AT_producer, producer_);
1635
1636      ranges_.load (die, false);
1637
1638      if (ranges_.empty ())
1639      {
1640        bool is_address;
1641        die.get_lowpc (pc_low_);
1642        if (die.get_highpc (pc_high_, is_address))
1643        {
1644          if (!is_address)
1645            pc_high_ += pc_low_;
1646        }
1647        else
1648          pc_high_ = ~0U;
1649      }
1650      else
1651      {
1652        pc_low_ = ~0U;
1653        for (auto& r : ranges_.get ())
1654        {
1655          if (!r.end () && !r.empty () && r.addr1 () < pc_low_)
1656            pc_low_ = r.addr1 ();
1657        }
1658        pc_high_ = 0U;
1659        for (auto& r : ranges_.get ())
1660        {
1661          if (!r.end () && !r.empty () && r.addr2 () > pc_high_)
1662            pc_high_ = r.addr2 ();
1663        }
1664      }
1665
1666      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1667      {
1668        std::cout << std::hex << std::setfill ('0')
1669                  << "dwarf::compilation_unit: "
1670                  << rld::path::basename (name_)
1671                  << ": (0x" << std::setw (8) << offset_ << ") ";
1672        if (pc_low_ != 0 && pc_high_ != ~0U)
1673          std::cout << "pc_low = 0x" << std::setw (8) << pc_low_
1674                    << " pc_high = 0x" << std::setw (8) << pc_high_;
1675       std::cout  << std::setfill (' ') << std::dec
1676                  << std::endl
1677                  << " ] " << producer_
1678                  << std::endl;
1679      }
1680
1681      line_addresses lines (debug, die);
1682      dwarf_address  pc = 0;
1683      bool           seq_check = true;
1684      dwarf_address  seq_base = 0;
1685
1686      for (size_t l = 0; l < lines.count (); ++l)
1687      {
1688        address       daddr (source_, lines[l]);
1689        dwarf_address loc = daddr.location ();
1690        /*
1691         * A CU's line program can have some sequences at the start where the
1692         * address is incorrectly set to 0. Ignore these entries.
1693         */
1694        if (pc == 0)
1695        {
1696          if (!seq_check)
1697          {
1698            seq_check = daddr.is_an_end_sequence ();
1699            continue;
1700          }
1701          if (loc == 0)
1702          {
1703            seq_check = false;
1704            continue;
1705          }
1706        }
1707        /*
1708         * A sequence of line program instruction may set the address to 0. Use
1709         * the last location from the previous sequence as the sequence's base
1710         * address. All locations will be offset from the that base until the
1711         * end of this sequence.
1712         */
1713        if (loc == 0 && seq_base == 0)
1714          seq_base = pc;
1715        if (seq_base != 0)
1716          loc += seq_base;
1717        if (daddr.is_an_end_sequence ())
1718          seq_base = 0;
1719        address addr (daddr, loc);
1720        if (loc >= pc_low_ && loc <= pc_high_)
1721        {
1722          pc = loc;
1723          addr_lines_.push_back (addr);
1724        }
1725      }
1726
1727      if (!addr_lines_.empty ())
1728      {
1729        std::stable_sort (addr_lines_.begin (), addr_lines_.end ());
1730        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1731        {
1732          auto first = addr_lines_.begin ();
1733          auto last = addr_lines_.end () - 1;
1734          std::cout << "dwarf::compilation_unit: line_low=0x"
1735                    << std::hex << std::setfill('0')
1736                    << std::setw (8) << first->location ()
1737                    << ", line_high=0x"
1738                    << std::setw (8) << last->location ()
1739                    << std::dec << std::setfill(' ')
1740                    << std::endl;
1741        }
1742      }
1743
1744      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
1745      {
1746        int lc = 0;
1747        for (auto& l : addr_lines_)
1748        {
1749          std::cout << "dwarf::compilation_unit: " << std::setw (3) << ++lc
1750                    << ": 0x"
1751                    << std::hex << std::setfill('0')
1752                    << std::setw (8) << l.location ()
1753                    << std::dec << std::setfill(' ')
1754                    << " - "
1755                    << (char) (l.is_a_begin_statement () ? 'B' : '.')
1756                    << (char) (l.is_in_a_block () ? 'I' : '.')
1757                    << (char) (l.is_an_end_sequence () ? 'E' : '.')
1758                    << " - "
1759                    << rld::path::basename (l.path ())
1760                    << ':' <<l.line ()
1761                    << std::endl;
1762        }
1763      }
1764    }
1765
1766    compilation_unit::compilation_unit (const compilation_unit& orig)
1767      : debug (orig.debug),
1768        offset_ (orig.offset_),
1769        name_ (orig.name_),
1770        producer_ (orig.producer_),
1771        pc_low_ (orig.pc_low_),
1772        pc_high_ (orig.pc_high_),
1773        ranges_ (orig.ranges_),
1774        die_offset (orig.die_offset),
1775        source_ (debug, die_offset)
1776    {
1777      for (auto& line : orig.addr_lines_)
1778        addr_lines_.push_back (address (line, source_));
1779      std::stable_sort (addr_lines_.begin (), addr_lines_.end ());
1780    }
1781
1782    compilation_unit::~compilation_unit ()
1783    {
1784    }
1785
1786    void
1787    compilation_unit::load_types ()
1788    {
1789      //dump_die ();
1790    }
1791
1792    void
1793    compilation_unit::load_variables ()
1794    {
1795      debug_info_entry die (debug, die_offset);
1796      debug_info_entry child (debug);
1797      if (die.get_child (child))
1798        load_variables (child);
1799    }
1800
1801    void
1802    compilation_unit::load_variables (debug_info_entry& die)
1803    {
1804      while (true)
1805      {
1806        if (die.tag () == DW_TAG_variable)
1807        {
1808          function func (debug, die);
1809          functions_.push_back (func);
1810        }
1811
1812        debug_info_entry next (die.get_debug ());
1813
1814        if (die.get_child (next))
1815          load_functions (next);
1816
1817        if (!die.get_sibling (next))
1818          break;
1819
1820        die = next;
1821      }
1822    }
1823
1824    void
1825    compilation_unit::load_functions ()
1826    {
1827      debug_info_entry die (debug, die_offset);
1828      debug_info_entry child (debug);
1829      if (die.get_child (child))
1830        load_functions (child);
1831    }
1832
1833    void
1834    compilation_unit::load_functions (debug_info_entry& die)
1835    {
1836      while (true)
1837      {
1838        if (die.tag () == DW_TAG_subprogram ||
1839            die.tag () == DW_TAG_entry_point ||
1840            die.tag () == DW_TAG_inlined_subroutine)
1841        {
1842          function func (debug, die);
1843          functions_.push_back (func);
1844        }
1845
1846        debug_info_entry next (die.get_debug ());
1847
1848        if (die.get_child (next))
1849          load_functions (next);
1850
1851        if (!die.get_sibling (next))
1852          break;
1853
1854        die = next;
1855      }
1856    }
1857
1858    std::string
1859    compilation_unit::name () const
1860    {
1861      return name_;
1862    }
1863
1864    std::string
1865    compilation_unit::producer () const
1866    {
1867      return producer_;
1868    }
1869
1870    unsigned int
1871    compilation_unit::pc_low () const
1872    {
1873      return pc_low_;
1874    }
1875
1876    unsigned int
1877    compilation_unit::pc_high () const
1878    {
1879      return pc_high_;
1880    }
1881
1882    bool
1883    compilation_unit::get_source (const dwarf_address addr,
1884                                  address&            addr_line)
1885    {
1886      if (!addr_lines_.empty () && inside (addr))
1887      {
1888        address last_loc;
1889        for (auto& loc : addr_lines_)
1890        {
1891          if (addr <= loc.location ())
1892          {
1893            if (addr == loc.location ())
1894              addr_line = loc;
1895            else
1896              addr_line = last_loc;
1897            return addr_line.valid ();
1898          }
1899          last_loc = loc;
1900        }
1901      }
1902      return false;
1903    }
1904
1905    const addresses& compilation_unit::get_addresses () const
1906    {
1907      return addr_lines_;
1908    }
1909
1910    functions&
1911    compilation_unit::get_functions ()
1912    {
1913      return functions_;
1914    }
1915
1916    bool
1917    compilation_unit::inside (dwarf_unsigned addr) const
1918    {
1919      return addr >= pc_low_ && addr < pc_high_;
1920    }
1921
1922    compilation_unit&
1923    compilation_unit::operator = (const compilation_unit& rhs)
1924    {
1925      if (this != &rhs)
1926      {
1927        debug = rhs.debug;
1928
1929        /*
1930         * This is a copy operator so we need to get a new copy of the strings,
1931         * we cannot steal the other copy.
1932         */
1933        offset_ = rhs.offset_;
1934        name_ = rhs.name_;
1935        producer_ = rhs.producer_;
1936        source_ = sources (debug, die_offset);
1937        for (auto& line : rhs.addr_lines_)
1938          addr_lines_.push_back (address (line, source_));
1939        pc_low_ = rhs.pc_low_;
1940        pc_high_ = rhs.pc_high_;
1941        ranges_ = rhs.ranges_;
1942        die_offset = rhs.die_offset;
1943      }
1944      return *this;
1945    }
1946
1947    void
1948    compilation_unit::dump_die (std::ostream&     out,
1949                                const std::string prefix,
1950                                int               depth)
1951    {
1952      debug_info_entry die (debug, die_offset);
1953      out << "CU @ 0x" << std::hex << offset_ << std::dec << std::endl;
1954      die_dump (die, out, prefix, depth);
1955    }
1956
1957    source_flags::source_flags (const std::string& source)
1958      : source (source)
1959    {
1960    }
1961
1962    bool
1963    source_flags_compare::operator () (const source_flags& a,
1964                                       const source_flags& b) const
1965    {
1966      if (by_basename)
1967        return rld::path::basename (a.source) < rld::path::basename (b.source);
1968      return a.source < b.source;
1969    }
1970
1971    source_flags_compare::source_flags_compare (bool by_basename)
1972      : by_basename (by_basename)
1973    {
1974    }
1975
1976    producer_source::producer_source (const std::string& producer)
1977      : producer (producer)
1978    {
1979    }
1980
1981    producer_source::producer_source ()
1982    {
1983    }
1984
1985    file::file ()
1986      : debug (nullptr),
1987        elf_ (nullptr)
1988    {
1989    }
1990
1991    file::~file ()
1992    {
1993      try
1994      {
1995        end ();
1996      }
1997      catch (rld::error re)
1998      {
1999        std::cerr << "error: rld::dwarf::file::~file: "
2000                  << re.where << ": " << re.what
2001                  << std::endl;
2002      }
2003      catch (...)
2004      {
2005        std::cerr << "error: rld::dwarf::file::~file: unhandled exception"
2006                  << std::endl;
2007      }
2008    }
2009
2010    void
2011    file::begin (rld::elf::file& elf__)
2012    {
2013      if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
2014        std::cout << "dwarf::begin: " << elf__.name () << std::endl;
2015
2016      if (debug != nullptr || elf_ != nullptr)
2017        throw rld::error ("Already called", "dwarf:file:begin");
2018
2019      /*
2020       * DWARF data is not writable.
2021       */
2022      if (elf__.is_writable ())
2023        throw rld::error ("Cannot write DWARF info", "dwarf:file:begin");
2024
2025      /*
2026       * Initialise the DWARF instance.
2027       */
2028      dwarf_error de;
2029      int dr = ::dwarf_elf_init (elf__.get_elf (),
2030                                 DW_DLC_READ,
2031                                 nullptr,
2032                                 this,
2033                                 &debug,
2034                                 &de);
2035      libdwarf_error_check ("file:begin", dr, de);
2036
2037      /*
2038       * Record the ELF instance and obtain a reference to it. The ELF file
2039       * cannot end while the DWARF file has not ended.
2040       */
2041      elf__.reference_obtain ();
2042      elf_ = &elf__;
2043    }
2044
2045    void
2046    file::end ()
2047    {
2048      if (debug)
2049      {
2050        if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
2051          std::cout << "dwarf::end: " << name () << std::endl;
2052
2053        cus.clear ();
2054
2055        ::dwarf_finish (debug, 0);
2056        if (elf_)
2057          elf_->reference_release ();
2058        elf_ = nullptr;
2059        debug = nullptr;
2060      }
2061    }
2062
2063    void
2064    file::dump (std::ostream&     out,
2065                const std::string prefix,
2066                int               depth)
2067    {
2068      while (true)
2069      {
2070        dwarf_unsigned cu_next_offset = 0;
2071        dwarf_error    de;
2072        int            dr;
2073
2074        dr = ::dwarf_next_cu_header_c(debug, 1,
2075                                      nullptr, nullptr, nullptr,  nullptr,
2076                                      nullptr, nullptr, nullptr,  nullptr,
2077                                      &cu_next_offset, &de);
2078        if (dr != DW_DLV_OK)
2079          break;
2080
2081        /*
2082         * Find the CU DIE by asking the CU for it's first DIE.
2083         */
2084        debug_info_entry die (*this);
2085
2086        while (true)
2087        {
2088          debug_info_entry sibling (*this);
2089          if (!die.get_sibling (sibling))
2090            break;
2091          if (sibling.tag () == DW_TAG_compile_unit)
2092            die_dump (sibling, out, prefix, depth);
2093          die = sibling;
2094        }
2095      }
2096    }
2097
2098    void
2099    file::load_debug ()
2100    {
2101      dwarf_unsigned cu_offset = 0;
2102
2103      while (true)
2104      {
2105        dwarf_unsigned cu_next_offset = 0;
2106        dwarf_error    de;
2107        int            dr;
2108
2109        dr = ::dwarf_next_cu_header_c(debug, 1,
2110                                      nullptr, nullptr, nullptr,  nullptr,
2111                                      nullptr, nullptr, nullptr,  nullptr,
2112                                      &cu_next_offset, &de);
2113        if (dr != DW_DLV_OK)
2114          break;
2115
2116        /*
2117         * Find the CU DIE.
2118         */
2119        debug_info_entry die (*this);
2120        debug_info_entry ret_die (*this);
2121
2122        while (true)
2123        {
2124          dr = ::dwarf_siblingof(debug, die, ret_die, &de);
2125          if (dr != DW_DLV_OK)
2126            break;
2127
2128          if (ret_die.tag () == DW_TAG_compile_unit)
2129          {
2130            cus.push_back (compilation_unit (*this, ret_die, cu_offset));
2131            break;
2132          }
2133
2134          die = ret_die;
2135        }
2136
2137        cu_offset = cu_next_offset;
2138      }
2139    }
2140
2141    void
2142    file::load_types ()
2143    {
2144      for (auto& cu : cus)
2145        cu.load_types ();
2146    }
2147
2148    void
2149    file::load_variables ()
2150    {
2151      for (auto& cu : cus)
2152        cu.load_variables ();
2153    }
2154
2155    void
2156    file::load_functions ()
2157    {
2158      for (auto& cu : cus)
2159        cu.load_functions ();
2160    }
2161
2162    bool
2163    file::get_source (const unsigned int addr,
2164                      std::string&       source_file,
2165                      int&               source_line)
2166    {
2167      bool r = false;
2168
2169      /*
2170       * Search the CU's collecting the addresses. An address can appear in
2171       * more than one CU. It may be the last address and the first.
2172       */
2173      source_file = "unknown";
2174      source_line = -1;
2175
2176      address match;
2177
2178      for (auto& cu : cus)
2179      {
2180        address line;
2181        r = cu.get_source (addr, line);
2182        if (r)
2183        {
2184          if (!match.valid ())
2185          {
2186            match = line;
2187          }
2188          else if (match.is_an_end_sequence () || !line.is_an_end_sequence ())
2189          {
2190            match = line;
2191          }
2192        }
2193      }
2194
2195      if (match.valid ())
2196      {
2197        source_file = match.path ();
2198        source_line = match.line ();
2199        r = true;
2200      }
2201
2202      return r;
2203    }
2204
2205    bool
2206    file::get_function (const unsigned int addr,
2207                        std::string&       name)
2208    {
2209      name = "unknown";
2210
2211      for (auto& cu : cus)
2212      {
2213        for (auto& func : cu.get_functions ())
2214        {
2215          if (func.inside (addr))
2216          {
2217            name = func.name ();
2218            return true;
2219          }
2220        }
2221      }
2222
2223      return false;
2224    }
2225
2226    void
2227    file::get_producer_sources (producer_sources& producers)
2228    {
2229      for (auto& cu : cus)
2230      {
2231        std::string     producer = cu.producer ();
2232        producer_source new_producer;
2233        source_flags    sf (cu.name ());
2234        rld::strings    parts;
2235
2236        rld::split (parts, producer);
2237
2238        for (auto& s : parts)
2239        {
2240          if (s[0] == '-')
2241            sf.flags.push_back (s);
2242          else
2243            new_producer.producer +=  ' ' + s;
2244        }
2245
2246        bool add = true;
2247
2248        for (auto& p : producers)
2249        {
2250          if (p.producer == new_producer.producer)
2251          {
2252            p.sources.push_back (sf);
2253            add = false;
2254            break;
2255          }
2256        }
2257        if (add)
2258        {
2259          new_producer.sources.push_back (sf);
2260          producers.push_back (new_producer);
2261        }
2262      }
2263    }
2264
2265    dwarf&
2266    file::get_debug ()
2267    {
2268      return debug;
2269    }
2270
2271    compilation_units&
2272    file::get_cus ()
2273    {
2274      return cus;
2275    }
2276
2277    const std::string&
2278    file::name () const
2279    {
2280      if (!elf_)
2281        throw rld::error ("No begin called", "dwarf:fie:name");
2282      return elf_->name ();
2283    }
2284
2285    void
2286    file::check (const char* where) const
2287    {
2288      if (!debug || !elf_)
2289      {
2290        std::string w = where;
2291        throw rld::error ("No DWARF or ELF file", "dwarf:file:" + w);
2292      }
2293    }
2294
2295  }
2296}
Note: See TracBrowser for help on using the repository browser.