source: rtems-tools/rtemstoolkit/rld-dwarf.h @ 3618a62

Last change on this file since 3618a62 was 558cab8, checked in by Chris Johns <chrisj@…>, on May 8, 2018 at 5:09:38 AM

rtemstoolkit: Add libdwarf C++ interface.

Provide a C++ interface to libdwarf to:

  • Manage DWARF debug data
  • Manage CU
  • Manage DIE
  • Handle CU line addresses
  • Handle CU source files

Update #3417

  • Property mode set to 100644
File size: 10.6 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 <rld.h>
29#include <rld-dwarf-types.h>
30
31namespace rld
32{
33  namespace dwarf
34  {
35    /**
36     * Forward decls
37     */
38    class sources;
39    class debug_info_entry;
40    class file;
41
42    /**
43     * Address.
44     */
45    class address
46    {
47    public:
48      address (const sources& source, dwarf_line& line);
49      address (const address& orig);
50      address ();
51      ~address ();
52
53      /**
54       * Is this address valid?
55       */
56      bool valid () const;
57
58      /**
59       * The location in the address space.
60       */
61      dwarf_address location () const;
62
63      /**
64       * Source file path. This is a full path.
65       */
66      std::string path () const;
67
68      /**
69       * Line number.
70       */
71      int line () const;
72
73      /**
74       * Is a begin statement?
75       */
76      bool is_a_begin_statement () const;
77
78      /**
79       * Is in a block?
80       */
81      bool is_in_a_block () const;
82
83      /**
84       * Is an end sequence?
85       */
86      bool is_an_end_sequence () const;
87
88      /**
89       * Assigment operator.
90       */
91      address& operator = (address& rhs);
92
93    private:
94
95      dwarf_address  addr;
96      sources const* source;
97      dwarf_unsigned source_index;
98      dwarf_unsigned source_line;
99      bool           begin_statement;
100      bool           block;
101      bool           end_sequence;
102    };
103
104    /**
105     * The addresses table is a map of the addresses in a CU to their line
106     * number.
107     */
108    typedef std::map < const dwarf_address, address > addresses;
109
110
111    /**
112     * Line addresses.
113     */
114    class line_addresses
115    {
116    public:
117      line_addresses (file& debug, debug_info_entry& die);
118      line_addresses (line_addresses&& orig);
119      ~line_addresses ();
120
121      /**
122       * Count of lines.
123       */
124      size_t count () const;
125
126      /**
127       * Index operator.
128       */
129      dwarf_line& operator [] (const int index);
130
131    private:
132
133      file&        debug;
134      dwarf_line*  lines;
135      dwarf_signed count_;
136    };
137
138    /**
139     * Sources.
140     *
141     * This is a CU table of sources. The address's contain an index to a
142     * string in this table.
143     */
144    class sources
145    {
146    public:
147      sources (file& debug, debug_info_entry& die);
148      sources (const sources& orig);
149      sources (sources&& orig);
150      ~sources ();
151
152      /**
153       * Index operator.
154       */
155      std::string operator [] (const int index) const;
156
157      /**
158       * Deallocate.
159       */
160      void dealloc ();
161
162      /**
163       * Move assignment operator.
164       */
165      sources& operator = (sources&& rhs);
166
167    private:
168
169      file&        debug;
170      char**       source;
171      dwarf_signed count;
172      dwarf_offset die_offset;
173    };
174
175    /**
176     * Debug Information Element (DIE).
177     *
178     * This class clean up and deallocations a DIE when it desctructs.
179     */
180    class debug_info_entry
181    {
182    public:
183      /**
184       * Construct the DIE, we need to be careful not to share the DIE pointer.
185       */
186      debug_info_entry (file& debug);
187      debug_info_entry (file& debug, dwarf_die& die);
188      debug_info_entry (file& debug, dwarf_offset offset);
189      debug_info_entry (debug_info_entry&& orig);
190
191      /**
192       * Destruct and clean up.
193       */
194      ~debug_info_entry ();
195
196      /**
197       * Get the DIE.
198       */
199      dwarf_die get () const;
200
201      /**
202       * Casting operators to get the DIE.
203       */
204      operator dwarf_die& ();
205      operator dwarf_die* ();
206
207      /**
208       * Assignment operators.
209       */
210      debug_info_entry& operator = (debug_info_entry& rhs);
211
212      /**
213       * Compare operators.
214       */
215      bool operator == (debug_info_entry& rhs) const;
216      bool operator == (const dwarf_die rhs) const;
217
218      /**
219       * Get the tag.
220       */
221      dwarf_tag tag ();
222
223      /**
224       * Get the offset.
225       */
226      dwarf_offset offset ();
227
228      /**
229       * Get an unsigned attribute.
230       */
231      bool attribute (dwarf_attr      attr,
232                      dwarf_unsigned& value,
233                      bool            error = true) const;
234
235      /**
236       * Get a string attribute.
237       */
238      bool attribute (dwarf_attr   attr,
239                      std::string& value,
240                      bool         error = true) const;
241
242      /**
243       * Get source lines. Returns the CU line table with all columns.
244       *
245       * You need to clean this up.
246       */
247      bool source_lines (dwarf_line*&  lines,
248                         dwarf_signed& linecount) const;
249
250      /**
251       * Get the source files. This is a table of source files in a CU
252       */
253      void source_files (char**&       source,
254                         dwarf_signed& sourcecount) const;
255
256      /**
257       * deallocate the DIE.
258       */
259      void dealloc ();
260
261    private:
262
263      file&        debug;
264      dwarf_die    die;
265      dwarf_tag    tag_;
266      dwarf_offset offset_;
267
268    };
269
270    /**
271     * Compilation Unit.
272     */
273    class compilation_unit
274    {
275    public:
276      compilation_unit (file&             debug,
277                        debug_info_entry& die,
278                        dwarf_offset      offset);
279      compilation_unit (const compilation_unit& orig);
280      compilation_unit (compilation_unit&& orig);
281      ~compilation_unit ();
282
283      /**
284       * Name of the CU.
285       */
286      std::string name () const;
287
288      /**
289       * Producer of the CL, the tool that compiled it.
290       */
291      std::string producer () const;
292
293      /**
294       * The low PC value, 0 if there is no attribute.
295       */
296      unsigned int pc_low () const;
297
298      /**
299       * The high PC value, ~0 if there is no attribute.
300       */
301      unsigned int pc_high () const;
302
303      /**
304       * Get the source and line for an address. If the address does not match
305       * false is returned the file is set to 'unknown' and the line is set to
306       * 0.
307       */
308      bool get_source (const dwarf_address addr,
309                       address&            addr_line);
310
311      /**
312       * Is the address inside the CU? Becareful using this because not all CUs
313       * have these attributes set and the address range will be the entire
314       * address space.
315       */
316      bool inside (dwarf_unsigned addr) const;
317
318      /**
319       * Move assignment operator.
320       */
321      compilation_unit& operator = (compilation_unit&& rhs);
322
323      /**
324       * Copy assignment operator.
325       */
326      compilation_unit& operator = (const compilation_unit& rhs);
327
328    private:
329
330      file&          debug;       ///< The DWARF debug handle.
331      dwarf_unsigned offset_;     ///< The CU offset in .debug_info
332      std::string    name_;       ///< The name of the CU.
333      std::string    producer_;   ///< The producer of the CU.
334      dwarf_unsigned pc_low_;     ///< The PC low address
335      dwarf_unsigned pc_high_;    ///< The PC high address.
336
337      sources        source_;     ///< Sources table for this CU.
338      addresses      addr_lines_; ///< Address table.
339
340      dwarf_offset   die_offset;  ///< The offset of the DIE in the image.
341    };
342
343    typedef std::list < compilation_unit > compilation_units;
344
345    /**
346     * A source and flags.
347     */
348    struct source_flags
349    {
350      std::string  source;  ///< The source file.
351      rld::strings flags;   ///< the flags used to build the code.
352
353      source_flags (const std::string& source);
354    };
355
356    typedef std::vector < source_flags > sources_flags;
357
358    /**
359     * Worker to sort the sources.
360     */
361    struct source_flags_compare
362    {
363      const bool by_basename;
364
365      bool operator () (const source_flags& a, const source_flags& b) const;
366
367      source_flags_compare (bool by_basename = true);
368    };
369
370    /**
371     * A container of producers and the source they build.
372     */
373    struct producer_source
374    {
375      std::string   producer; ///< The producer
376      sources_flags sources;  ///< The sources built by the producer with
377                              ///  flags.
378
379      producer_source (const std::string& producer);
380      producer_source ();
381    };
382
383    typedef std::list < producer_source > producer_sources;
384
385    /**
386     * A DWARF file.
387     */
388    class file
389    {
390    public:
391     /**
392       * Construct an DWARF file.
393       */
394      file ();
395
396      /**
397       * Destruct the DWARF file object.
398       */
399      ~file ();
400
401      /**
402       * Begin using the DWARF information in an ELF file.
403       *
404       * @param elf The ELF file.
405       */
406      void begin (rld::elf::file& elf);
407
408      /**
409       * End using the DWARF file.
410       */
411      void end ();
412
413      /**
414       * Load the DWARF debug information.
415       */
416      void load_debug ();
417
418      /**
419       * Get the source location given an address.
420       */
421      bool get_source (const unsigned int address,
422                       std::string&       source_file,
423                       int&               source_line);
424
425      /**
426       * Get the producer sources from the compilation units.
427       */
428      void get_producer_sources (producer_sources& producers);
429
430      /**
431       * Get the DWARF debug information reference.
432       */
433      dwarf& get_debug ();
434
435      /**
436       * Get the compilation units.
437       */
438      compilation_units& get_cus ();
439
440      /*
441       * The DWARF debug conversion operator.
442       */
443      operator dwarf () { return get_debug (); }
444
445      /**
446       * Get the name of the file.
447       */
448      const std::string& name () const;
449
450    private:
451
452      /**
453       * Check if the file is usable. Throw an exception if not.
454       *
455       * @param where Where the check is performed.
456       */
457      void check (const char* where) const;
458
459      dwarf           debug;   ///< The libdwarf debug data
460      rld::elf::file* elf_;    ///< The libelf reference used to access the
461                               ///  DWARF data.
462
463      compilation_units cus;   ///< Image's compilation units
464    };
465
466  }
467}
468
469#endif
Note: See TracBrowser for help on using the repository browser.