source: rtems-tools/rtemstoolkit/rld-dwarf.h @ 6d30de6

5
Last change on this file since 6d30de6 was 317d85d, checked in by Chris Johns <chrisj@…>, on 08/06/18 at 23:08:25

rtemstoolkit/dwarf: Add types of inline. Report machine code size not span.

  • Add the types of inlined functions to the interface.
  • Return the machine code for each function and not the address span.
  • Property mode set to 100644
File size: 19.2 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 libdwarf interface.
22 *
23 */
24
25#if !defined (_RLD_DWARF_H_)
26#define _RLD_DWARF_H_
27
28#include <iostream>
29
30#include <rld.h>
31#include <rld-dwarf-types.h>
32
33namespace rld
34{
35  namespace dwarf
36  {
37    /**
38     * Forward decls
39     */
40    class sources;
41    class debug_info_entry;
42    class file;
43
44    /**
45     * Address.
46     */
47    class address
48    {
49    public:
50      address (const sources& source, dwarf_line& line);
51      address (const address& orig, const sources& source);
52      address (const address& orig, dwarf_address addr);
53      address (const address& orig);
54      address ();
55      ~address ();
56
57      /**
58       * Is this address valid?
59       */
60      bool valid () const;
61
62      /**
63       * The location in the address space.
64       */
65      dwarf_address location () const;
66
67      /**
68       * Source file path. This is a full path.
69       */
70      std::string path () const;
71
72      /**
73       * Line number.
74       */
75      int line () const;
76
77      /**
78       * Is a begin statement?
79       */
80      bool is_a_begin_statement () const;
81
82      /**
83       * Is in a block?
84       */
85      bool is_in_a_block () const;
86
87      /**
88       * Is an end sequence?
89       */
90      bool is_an_end_sequence () const;
91
92      /**
93       * Assigment operator.
94       */
95      address& operator = (const address& rhs);
96
97      /**
98       * Less than operator to allow sorting.
99       */
100      bool operator < (const address& rhs) const;
101
102    private:
103
104      dwarf_address  addr;
105      sources const* source;
106      dwarf_unsigned source_index;
107      dwarf_signed   source_line;
108      bool           begin_statement;
109      bool           block;
110      bool           end_sequence;
111    };
112
113    /**
114     * The addresses table is a vector sorted from low to high addresses..
115     */
116    typedef std::vector < address > addresses;
117
118    /**
119     * Range, one entry in an address range container.
120     */
121    class range
122    {
123    public:
124      range (const dwarf_ranges* range);
125      range (const range& orig);
126      ~range ();
127
128      /**
129       * Address 1 in the range.
130       */
131      dwarf_unsigned addr1 () const;
132      dwarf_unsigned addr2 () const;
133
134      /**
135       * Get the type of range.
136       */
137      dwarf_ranges_type type () const;
138
139      /**
140       * Is the range the end?
141       */
142      bool end () const;
143
144      /**
145       * Is the range empty? See DWARF 2.17.3.
146       */
147      bool empty () const;
148
149      /**
150       * Assigment operator.
151       */
152      range& operator = (const range& rhs);
153
154      /**
155       * Dump the range.
156       */
157      void dump (std::ostream& out) const;
158
159    private:
160
161      const dwarf_ranges* range_;
162    };
163
164    typedef std::vector < range > ranges;
165
166    /**
167     * Address ranges, is a range of addresses.
168     */
169    class address_ranges
170    {
171    public:
172      address_ranges (file& debug);
173      address_ranges (debug_info_entry& die);
174      address_ranges (file& debug, dwarf_offset offset);
175      address_ranges (const address_ranges& orig);
176      ~address_ranges ();
177
178      /**
179       * Load the ranges from the DIE.
180       */
181      bool load (debug_info_entry& die, bool error = true);
182
183      /**
184       * Load the ranges from the debug info.
185       */
186      bool load (dwarf_offset offset, bool error = true);
187
188      /**
189       * Get the container.
190       */
191      const ranges& get () const;
192
193      /**
194       * Address range empty?
195       */
196      bool empty () const;
197
198      /**
199       * Assigment operator.
200       */
201      address_ranges& operator = (const address_ranges& rhs);
202
203      /**
204       * Dump the address ranges.
205       */
206      void dump (std::ostream& out) const;
207
208    private:
209
210      file&         debug;
211      dwarf_offset  offset;
212      dwarf_ranges* dranges;
213      dwarf_signed  dranges_count;
214      ranges        ranges_;
215    };
216
217    /**
218     * Line addresses.
219     */
220    class line_addresses
221    {
222    public:
223      line_addresses (file& debug, debug_info_entry& die);
224      ~line_addresses ();
225
226      /**
227       * Count of lines.
228       */
229      size_t count () const;
230
231      /**
232       * Index operator.
233       */
234      dwarf_line& operator [] (const int index);
235
236    private:
237
238      file&        debug;
239      dwarf_line*  lines;
240      dwarf_signed count_;
241    };
242
243    /**
244     * Sources.
245     *
246     * This is a CU table of sources. The address's contain an index to a
247     * string in this table.
248     */
249    class sources
250    {
251    public:
252      sources (file& debug, dwarf_offset die_offset);
253      sources (const sources& orig);
254      ~sources ();
255
256      /**
257       * Index operator.
258       */
259      std::string operator [] (const int index) const;
260
261      /**
262       * Deallocate.
263       */
264      void dealloc ();
265
266      /**
267       * Move assignment operator.
268       */
269      sources& operator = (sources&& rhs);
270
271    private:
272
273      file&        debug;
274      char**       source;
275      dwarf_signed count;
276      dwarf_offset die_offset;
277    };
278
279    /**
280     * Function.
281     */
282    class function
283    {
284    public:
285
286      /**
287       * The various inline states. See Table 3.4 DWARF 5 standard.
288       */
289      enum inlined {
290        inl_not_inlined = 0,          /**< Not declared inline nore inlined. */
291        inl_inline = 1,               /**< Not declared inline but inlined. */
292        inl_declared_not_inlined = 2, /**< Declared inline but not inlined. */
293        inl_declared_inlined = 3      /**< Declared inline and inlined */
294      };
295
296      function (file& debug, debug_info_entry& die);
297      function (const function& orig);
298      ~function ();
299
300      /**
301       * Get the name of the function.
302       */
303      std::string name () const;
304
305      /**
306       * Get the linkage name of the function.
307       */
308      std::string linkage_name () const;
309
310      /**
311       * Get the ranges for the funcion, if empty the PC low and PC high values
312       * will be valid.
313       */
314      const address_ranges& get_ranges () const;
315
316      /**
317       * Get the PC low address, valid if ranges is empty.
318       */
319      dwarf_unsigned pc_low () const;
320
321      /**
322       * Get the PC high address, valid if ranges is empty.
323       */
324      dwarf_unsigned pc_high () const;
325
326      /**
327       * Does the function have machine code in the image?
328       */
329      bool has_machine_code () const;
330
331      /**
332       * Is the function external?
333       */
334      bool is_external () const;
335
336      /**
337       * Is this just a declaration?
338       */
339      bool is_declaration () const;
340
341      /**
342       * Is the function inlined?
343       */
344      bool is_inlined () const;
345
346      /**
347       * Get the inlined state.
348       */
349      inlined get_inlined () const;
350
351      /**
352       * Get the call file of the inlined function.
353       */
354      std::string call_file () const;
355
356      /**
357       * Is the address inside the function.
358       */
359      bool inside (dwarf_address addr) const;
360
361      /**
362       * Size of the function.
363       */
364      size_t size () const;
365
366      /**
367       * Assigment operator.
368       */
369      function& operator = (const function& rhs);
370
371      /**
372       * Dump the function.
373       */
374      void dump (std::ostream& out) const;
375
376    private:
377
378      file&          debug;
379      bool           machine_code_;
380      bool           external_;
381      bool           declaration_;
382      bool           prototyped_;
383      dwarf_unsigned inline_;
384      dwarf_unsigned entry_pc_;
385      bool           has_entry_pc_;
386      dwarf_unsigned pc_low_;
387      dwarf_unsigned pc_high_;
388      address_ranges ranges_;
389      std::string    name_;
390      std::string    linkage_name_;
391      std::string    decl_file_;
392      dwarf_unsigned decl_line_;
393      std::string    call_file_;
394      dwarf_unsigned call_line_;
395    };
396
397    typedef std::vector < function > functions;
398
399    /**
400     * Worker to sort the functions.
401     */
402    struct function_compare
403    {
404      enum sort_by
405      {
406        fc_by_name,
407        fc_by_size,
408        fc_by_address
409      };
410
411      const sort_by by;
412
413      bool operator () (const function& a, const function& b) const;
414
415      function_compare (sort_by by = fc_by_name);
416    };
417
418    /**
419     * Debug Information Element (DIE).
420     *
421     * This class clean up and deallocations a DIE when it desctructs.
422     */
423    class debug_info_entry
424    {
425    public:
426      /**
427       * Construct the DIE, we need to be careful not to share the DIE pointer.
428       */
429      debug_info_entry (file& debug);
430      debug_info_entry (file& debug, dwarf_die& die);
431      debug_info_entry (file& debug, dwarf_offset offset);
432      debug_info_entry (const debug_info_entry& orig);
433
434      /**
435       * Destruct and clean up.
436       */
437      ~debug_info_entry ();
438
439      /**
440       * Is the DIE valid?
441       */
442      bool valid (bool fatal = true) const;
443
444      /**
445       * Get the DIE.
446       */
447      dwarf_die get () const;
448
449      /**
450       * Casting operators to get the DIE.
451       */
452      operator dwarf_die& ();
453      operator dwarf_die* ();
454
455      /**
456       * Assignment operators.
457       */
458      debug_info_entry& operator = (debug_info_entry& rhs);
459      debug_info_entry& operator = (dwarf_offset offset);
460
461      /**
462       * Compare operators.
463       */
464      bool operator == (debug_info_entry& rhs) const;
465      bool operator == (const dwarf_die rhs) const;
466
467      /**
468       * Get the tag.
469       */
470      dwarf_tag tag ();
471
472      /**
473       * Get the offset.
474       */
475      dwarf_offset offset ();
476
477      /**
478       * Get the low PC.
479       */
480      bool get_lowpc (dwarf_address& addr, bool error = false) const;
481
482      /**
483       * Get the high PC.
484       */
485      bool get_highpc (dwarf_address& addr,
486                       bool&          is_address,
487                       bool           error = false) const;
488
489      /**
490       * Get an attribute.
491       */
492      bool attribute (dwarf_attr       attr,
493                      dwarf_attribute& value,
494                      bool             error = true) const;
495
496      /**
497       * Get a flag.
498       */
499      bool attribute (dwarf_attr  attr,
500                      dwarf_bool& value,
501                      bool        error = true) const;
502
503      /**
504       * Get an unsigned attribute.
505       */
506      bool attribute (dwarf_attr      attr,
507                      dwarf_unsigned& value,
508                      bool            error = true) const;
509
510      /**
511       * Get a string attribute.
512       */
513      bool attribute (dwarf_attr   attr,
514                      std::string& value,
515                      bool         error = true) const;
516
517      /**
518       * Get source lines. Returns the CU line table with all columns.
519       *
520       * You need to clean this up.
521       */
522      bool source_lines (dwarf_line*&  lines,
523                         dwarf_signed& linecount) const;
524
525      /**
526       * Get the source files. This is a table of source files in a CU
527       */
528      void source_files (char**&       source,
529                         dwarf_signed& sourcecount) const;
530
531      /**
532       * Get the ranges.
533       */
534      bool ranges (dwarf_ranges*& ranges, dwarf_signed& rangescount) const;
535
536      /**
537       * Get the child.
538       */
539      bool get_child (debug_info_entry& child_die);
540
541      /**
542       * Has a child?
543       */
544      bool has_child () const;
545
546      /**
547       * Get the silbing
548       */
549      bool get_sibling (debug_info_entry& sibling_die);
550
551      /**
552       * Has a silbing?
553       */
554      bool has_sibling () const;
555
556      /**
557       * Get the debug info for this DIE.
558       */
559      file& get_debug () const;
560
561      /**
562       * deallocate the DIE.
563       */
564      void dealloc ();
565
566      /**
567       * Dump this DIE.
568       */
569      void dump (std::ostream& out,
570                 std::string   prefix,
571                 bool          newline = true);
572
573    private:
574
575      /**
576       * Update the internal DIE and offset values.
577       */
578      void update ();
579
580      file&        debug;
581      dwarf_die    die;
582      dwarf_tag    tag_;
583      dwarf_offset offset_;
584
585    };
586
587    /**
588     * Dump the DIE and all it's children and siblings.
589     */
590    void die_dump_children (debug_info_entry& die,
591                            std::ostream&     out,
592                            std::string       prefix,
593                            int               depth = -1,
594                            int               nesting = 0);
595
596    /**
597     * Dump the DIE and all it's children and siblings.
598     */
599    void die_dump (debug_info_entry& die,
600                   std::ostream&     out,
601                   std::string       prefix,
602                   int               depth = -1,
603                   int               nesting = 0);
604
605    /**
606     * Compilation Unit.
607     */
608    class compilation_unit
609    {
610    public:
611      compilation_unit (file&             debug,
612                        debug_info_entry& die,
613                        dwarf_offset      offset);
614      compilation_unit (const compilation_unit& orig);
615      ~compilation_unit ();
616
617      /**
618       * Load the types.
619       */
620      void load_types ();
621
622      /**
623       * Load the functions.
624       */
625      void load_functions ();
626
627      /**
628       * Name of the CU.
629       */
630      std::string name () const;
631
632      /**
633       * Producer of the CL, the tool that compiled it.
634       */
635      std::string producer () const;
636
637      /**
638       * The low PC value, 0 if there is no attribute.
639       */
640      unsigned int pc_low () const;
641
642      /**
643       * The high PC value, ~0 if there is no attribute.
644       */
645      unsigned int pc_high () const;
646
647      /**
648       * Get the source and line for an address. If the address does not match
649       * false is returned the file is set to 'unknown' and the line is set to
650       * 0.
651       */
652      bool get_source (const dwarf_address addr,
653                       address&            addr_line);
654
655      /**
656       * Get the functions.
657       */
658      functions& get_functions ();
659
660      /**
661       * Is the address inside the CU? If the PC low and high attributes are
662       * valid they are used or the lines are checked.
663       */
664      bool inside (dwarf_unsigned addr) const;
665
666      /**
667       * Copy assignment operator.
668       */
669      compilation_unit& operator = (const compilation_unit& rhs);
670
671      /**
672       * Output the DIE tree.
673       */
674      void dump_die (std::ostream&     out,
675                     const std::string prefix = " ",
676                     int               depth = -1);
677
678    private:
679
680      void load_functions (debug_info_entry& die);
681
682      file&          debug;       ///< The DWARF debug handle.
683      dwarf_unsigned offset_;     ///< The CU offset in .debug_info
684      std::string    name_;       ///< The name of the CU.
685      std::string    producer_;   ///< The producer of the CU.
686      dwarf_unsigned pc_low_;     ///< The PC low address
687      dwarf_unsigned pc_high_;    ///< The PC high address.
688      address_ranges ranges_;     ///< Non-continous address range.
689
690      dwarf_offset   die_offset;  ///< The offset of the DIE in the image.
691
692      sources        source_;     ///< Sources table for this CU.
693      addresses      addr_lines_; ///< Address table.
694
695      functions      functions_;  ///< The functions in the CU.
696    };
697
698    typedef std::list < compilation_unit > compilation_units;
699
700    /**
701     * A source and flags.
702     */
703    struct source_flags
704    {
705      std::string  source;  ///< The source file.
706      rld::strings flags;   ///< the flags used to build the code.
707
708      source_flags (const std::string& source);
709    };
710
711    typedef std::vector < source_flags > sources_flags;
712
713    /**
714     * Worker to sort the sources.
715     */
716    struct source_flags_compare
717    {
718      const bool by_basename;
719
720      bool operator () (const source_flags& a, const source_flags& b) const;
721
722      source_flags_compare (bool by_basename = true);
723    };
724
725    /**
726     * A container of producers and the source they build.
727     */
728    struct producer_source
729    {
730      std::string   producer; ///< The producer
731      sources_flags sources;  ///< The sources built by the producer with
732                              ///  flags.
733
734      producer_source (const std::string& producer);
735      producer_source ();
736    };
737
738    typedef std::list < producer_source > producer_sources;
739
740    /**
741     * A DWARF file.
742     */
743    class file
744    {
745    public:
746     /**
747       * Construct an DWARF file.
748       */
749      file ();
750
751      /**
752       * Destruct the DWARF file object.
753       */
754      ~file ();
755
756      /**
757       * Begin using the DWARF information in an ELF file.
758       *
759       * @param elf The ELF file.
760       */
761      void begin (rld::elf::file& elf);
762
763      /**
764       * End using the DWARF file.
765       */
766      void end ();
767
768      /**
769       * Load the DWARF debug information.
770       */
771      void load_debug ();
772
773      /**
774       * Load the DWARF type information.
775       */
776      void load_types ();
777
778      /**
779       * Load the DWARF functions information.
780       */
781      void load_functions ();
782
783      /**
784       * Get the source location given an address.
785       */
786      bool get_source (const unsigned int address,
787                       std::string&       source_file,
788                       int&               source_line);
789
790      /**
791       * Get the producer sources from the compilation units.
792       */
793      void get_producer_sources (producer_sources& producers);
794
795      /**
796       * Does the function exist.
797       */
798      bool function_valid (std::string&name);
799
800      /**
801       * Get the function given a name. Raises an exception if not found.
802       */
803      function& get_function (std::string& name);
804
805      /**
806       * Get the function given an address.
807       */
808      bool get_function (const unsigned int address,
809                         std::string&       name);
810
811      /**
812       * Get the DWARF debug information reference.
813       */
814      dwarf& get_debug ();
815
816      /**
817       * Get the compilation units.
818       */
819      compilation_units& get_cus ();
820
821      /*
822       * The DWARF debug conversion operator.
823       */
824      operator dwarf () { return get_debug (); }
825
826      /**
827       * Get the name of the file.
828       */
829      const std::string& name () const;
830
831      /**
832       * Dump the DWARF data.
833       */
834      void dump (std::ostream&     out,
835                 const std::string prefix = " ",
836                 int               depth = -1);
837
838    private:
839
840      /**
841       * Check if the file is usable. Throw an exception if not.
842       *
843       * @param where Where the check is performed.
844       */
845      void check (const char* where) const;
846
847      dwarf           debug;   ///< The libdwarf debug data
848      rld::elf::file* elf_;    ///< The libelf reference used to access the
849                               ///  DWARF data.
850
851      compilation_units cus;   ///< Image's compilation units
852    };
853
854  }
855}
856
857#endif
Note: See TracBrowser for help on using the repository browser.