1 | // Copyright (c) 2013 Austin T. Clements. All rights reserved. |
2 | // Use of this source code is governed by an MIT license |
3 | // that can be found in the LICENSE file. |
4 | |
5 | #ifndef _DWARFPP_HH_ |
6 | #define _DWARFPP_HH_ |
7 | |
8 | #ifndef DWARFPP_BEGIN_NAMESPACE |
9 | #define DWARFPP_BEGIN_NAMESPACE namespace dwarf { |
10 | #define DWARFPP_END_NAMESPACE } |
11 | #endif |
12 | |
13 | #include "data.hh" |
14 | #include "small_vector.hh" |
15 | |
16 | #include <initializer_list> |
17 | #include <map> |
18 | #include <memory> |
19 | #include <stdexcept> |
20 | #include <string> |
21 | #include <vector> |
22 | |
23 | DWARFPP_BEGIN_NAMESPACE |
24 | |
25 | // Forward declarations |
26 | class dwarf; |
27 | class loader; |
28 | class compilation_unit; |
29 | class type_unit; |
30 | class die; |
31 | class value; |
32 | class expr; |
33 | class expr_context; |
34 | class expr_result; |
35 | class rangelist; |
36 | class line_table; |
37 | |
38 | // Internal type forward-declarations |
39 | struct section; |
40 | struct abbrev_entry; |
41 | struct cursor; |
42 | |
43 | // XXX Audit for binary-compatibility |
44 | |
45 | // XXX Might be able to reduce private coupling by making class |
46 | // section public (and clean it up and maybe rename it slice) and |
47 | // provide methods to get the backing data of things. |
48 | // |
49 | // XXX Make slice generic, without formatting information? Still want |
50 | // lightweight cursors, so maybe the cursor methods that need the |
51 | // format should take a const reference to a format stored in the |
52 | // compilation unit? |
53 | |
54 | // XXX operator==/!= and hash functions |
55 | |
56 | // XXX Indicate DWARF4 in all spec references |
57 | |
58 | // XXX Big missing support: .debug_aranges, .debug_frame, loclists, |
59 | // macros |
60 | |
61 | ////////////////////////////////////////////////////////////////// |
62 | // DWARF files |
63 | // |
64 | |
65 | /** |
66 | * An exception indicating malformed DWARF data. |
67 | */ |
68 | class format_error : public std::runtime_error |
69 | { |
70 | public: |
71 | explicit format_error(const std::string &what_arg) |
72 | : std::runtime_error(what_arg) { } |
73 | explicit format_error(const char *what_arg) |
74 | : std::runtime_error(what_arg) { } |
75 | }; |
76 | |
77 | /** |
78 | * DWARF section types. These correspond to the names of ELF |
79 | * sections, though DWARF can be embedded in other formats. |
80 | */ |
81 | enum class section_type |
82 | { |
83 | abbrev, |
84 | aranges, |
85 | frame, |
86 | info, |
87 | line, |
88 | loc, |
89 | macinfo, |
90 | pubnames, |
91 | pubtypes, |
92 | ranges, |
93 | str, |
94 | types, |
95 | }; |
96 | |
97 | std::string |
98 | to_string(section_type v); |
99 | |
100 | /** |
101 | * A DWARF file. This class is internally reference counted and can |
102 | * be efficiently copied. |
103 | * |
104 | * Objects retrieved from this object may depend on it; the caller is |
105 | * responsible for keeping this object live as long as any retrieved |
106 | * object may be in use. |
107 | */ |
108 | class dwarf |
109 | { |
110 | public: |
111 | /** |
112 | * Construct a DWARF file that is backed by sections read from |
113 | * the given loader. |
114 | */ |
115 | explicit dwarf(const std::shared_ptr<loader> &l); |
116 | |
117 | /** |
118 | * Construct a DWARF file that is initially not valid. |
119 | */ |
120 | dwarf() = default; |
121 | dwarf(const dwarf&) = default; |
122 | dwarf(dwarf&&) = default; |
123 | ~dwarf(); |
124 | |
125 | dwarf& operator=(const dwarf &o) = default; |
126 | dwarf& operator=(dwarf &&o) = default; |
127 | |
128 | bool operator==(const dwarf &o) const |
129 | { |
130 | return m == o.m; |
131 | } |
132 | |
133 | bool operator!=(const dwarf &o) const |
134 | { |
135 | return m != o.m; |
136 | } |
137 | |
138 | /** |
139 | * Return true if this object represents a DWARF file. |
140 | * Default constructed dwarf objects are not valid. |
141 | */ |
142 | bool valid() const |
143 | { |
144 | return !!m; |
145 | } |
146 | |
147 | // XXX This allows the compilation units to be modified and |
148 | // ties us to a vector. Probably should return an opaque |
149 | // iterable collection over const references. |
150 | /** |
151 | * Return the list of compilation units in this DWARF file. |
152 | */ |
153 | const std::vector<compilation_unit> &compilation_units() const; |
154 | |
155 | /** |
156 | * Return the type unit with the given signature. If the |
157 | * signature does not correspond to a type unit, throws |
158 | * out_of_range. |
159 | */ |
160 | const type_unit &get_type_unit(uint64_t type_signature) const; |
161 | |
162 | /** |
163 | * \internal Retrieve the specified section from this file. |
164 | * If the section does not exist, throws format_error. |
165 | */ |
166 | std::shared_ptr<section> get_section(section_type type) const; |
167 | |
168 | private: |
169 | struct impl; |
170 | std::shared_ptr<impl> m; |
171 | }; |
172 | |
173 | /** |
174 | * An interface for lazily loading DWARF sections. |
175 | */ |
176 | class loader |
177 | { |
178 | public: |
179 | virtual ~loader() { } |
180 | |
181 | /** |
182 | * Load the requested DWARF section into memory and return a |
183 | * pointer to the beginning of it. This memory must remain |
184 | * valid and unchanged until the loader is destroyed. If the |
185 | * requested section does not exist, this should return |
186 | * nullptr. If the section exists but cannot be loaded for |
187 | * any reason, this should throw an exception. |
188 | */ |
189 | virtual const void *load(section_type section, size_t *size_out) = 0; |
190 | }; |
191 | |
192 | /** |
193 | * The base class for a compilation unit or type unit within a DWARF |
194 | * file. A unit consists of a rooted tree of DIEs, plus additional |
195 | * metadata that depends on the type of unit. |
196 | */ |
197 | class unit |
198 | { |
199 | public: |
200 | virtual ~unit() = 0; |
201 | |
202 | bool operator==(const unit &o) const |
203 | { |
204 | return m == o.m; |
205 | } |
206 | |
207 | bool operator!=(const unit &o) const |
208 | { |
209 | return m != o.m; |
210 | } |
211 | |
212 | /** |
213 | * Return true if this object is valid. Default constructed |
214 | * unit objects are not valid. |
215 | */ |
216 | bool valid() const |
217 | { |
218 | return !!m; |
219 | } |
220 | |
221 | /** |
222 | * Return the dwarf file this unit is in. |
223 | */ |
224 | const dwarf &get_dwarf() const; |
225 | |
226 | /** |
227 | * Return the byte offset of this unit's header in its |
228 | * section (.debug_info or .debug_types). |
229 | */ |
230 | section_offset get_section_offset() const; |
231 | |
232 | /** |
233 | * Return the root DIE of this unit. For a compilation unit, |
234 | * this should be a DW_TAG::compilation_unit or |
235 | * DW_TAG::partial_unit. |
236 | */ |
237 | const die &root() const; |
238 | |
239 | /** |
240 | * \internal Return the data for this unit. |
241 | */ |
242 | const std::shared_ptr<section> &data() const; |
243 | |
244 | /** |
245 | * \internal Return the abbrev for the specified abbrev |
246 | * code. |
247 | */ |
248 | const abbrev_entry &get_abbrev(std::uint64_t acode) const; |
249 | |
250 | protected: |
251 | friend struct ::std::hash<unit>; |
252 | struct impl; |
253 | std::shared_ptr<impl> m; |
254 | }; |
255 | |
256 | /** |
257 | * A compilation unit within a DWARF file. Most of the information |
258 | * in a DWARF file is divided up by compilation unit. This class is |
259 | * internally reference counted and can be efficiently copied. |
260 | */ |
261 | class compilation_unit : public unit |
262 | { |
263 | public: |
264 | compilation_unit() = default; |
265 | compilation_unit(const compilation_unit &o) = default; |
266 | compilation_unit(compilation_unit &&o) = default; |
267 | |
268 | compilation_unit& operator=(const compilation_unit &o) = default; |
269 | compilation_unit& operator=(compilation_unit &&o) = default; |
270 | |
271 | /** |
272 | * \internal Construct a compilation unit whose header begins |
273 | * offset bytes into the .debug_info section of file. |
274 | */ |
275 | compilation_unit(const dwarf &file, section_offset offset); |
276 | |
277 | /** |
278 | * Return the line number table of this compilation unit. |
279 | * Returns an invalid line table if this unit has no line |
280 | * table. |
281 | */ |
282 | const line_table &get_line_table() const; |
283 | }; |
284 | |
285 | /** |
286 | * A type unit. Type units allow complex type information to be |
287 | * shared between compilation units. |
288 | */ |
289 | class type_unit : public unit |
290 | { |
291 | public: |
292 | type_unit() = default; |
293 | type_unit(const type_unit &o) = default; |
294 | type_unit(type_unit &&o) = default; |
295 | |
296 | type_unit &operator=(const type_unit &o) = default; |
297 | type_unit &operator=(type_unit &&o) = default; |
298 | |
299 | /** |
300 | * \internal Construct a type unit whose header begins offset |
301 | * bytes into the .debug_types section of file. |
302 | */ |
303 | type_unit(const dwarf &file, section_offset offset); |
304 | |
305 | /** |
306 | * Return the 64-bit unique signature that identifies this |
307 | * type unit. This is how DIEs from other units refer to type |
308 | * described by this unit. |
309 | */ |
310 | uint64_t get_type_signature() const; |
311 | |
312 | // XXX Can a type unit contain more than one top-level DIE? |
313 | // The description of type_offset makes it sound like it |
314 | // might. |
315 | |
316 | /** |
317 | * Return the DIE of the type described by this type unit. |
318 | * This may not be the root DIE of this unit if the type is |
319 | * nested in namespaces or other structures. |
320 | */ |
321 | const die &type() const; |
322 | }; |
323 | |
324 | ////////////////////////////////////////////////////////////////// |
325 | // Debugging information entries (DIEs) |
326 | // |
327 | |
328 | /** |
329 | * A Debugging Information Entry, or DIE. The basic unit of |
330 | * information in a DWARF file. |
331 | */ |
332 | class die |
333 | { |
334 | // XXX Make this class better for use in maps. Currently dies |
335 | // are fairly big and expensive to copy, but most of that |
336 | // information can be constructed lazily. This is also bad |
337 | // for use in caches since it will keep the DWARF file alive. |
338 | // OTOH, maybe caches need eviction anyway. |
339 | public: |
340 | DW_TAG tag; |
341 | |
342 | die() : cu(nullptr), abbrev(nullptr) { } |
343 | die(const die &o) = default; |
344 | die(die &&o) = default; |
345 | |
346 | die& operator=(const die &o) = default; |
347 | die& operator=(die &&o) = default; |
348 | |
349 | /** |
350 | * Return true if this object represents a DIE in a DWARF |
351 | * file. Default constructed objects are not valid and some |
352 | * methods return invalid DIEs to indicate failures. |
353 | */ |
354 | bool valid() const |
355 | { |
356 | return abbrev != nullptr; |
357 | } |
358 | |
359 | /** |
360 | * Return the unit containing this DIE. |
361 | */ |
362 | const unit &get_unit() const; |
363 | |
364 | /** |
365 | * Return this DIE's byte offset within its compilation unit. |
366 | */ |
367 | section_offset get_unit_offset() const |
368 | { |
369 | return offset; |
370 | } |
371 | |
372 | /** |
373 | * Return this DIE's byte offset within its section. |
374 | */ |
375 | section_offset get_section_offset() const; |
376 | |
377 | /** |
378 | * Return true if this DIE has the requested attribute. |
379 | */ |
380 | bool has(DW_AT attr) const; |
381 | |
382 | /** |
383 | * Return the value of attr. Throws out_of_range if this DIE |
384 | * does not have the specified attribute. It is generally |
385 | * better to use the type-safe attribute getters (the global |
386 | * functions beginning with at_*) when possible. |
387 | */ |
388 | value operator[](DW_AT attr) const; |
389 | |
390 | /** |
391 | * Return the value of attr after resolving specification and |
392 | * abstract origin references. If the attribute cannot be |
393 | * resolved, returns an invalid value. Declaration DIEs can |
394 | * "complete" a previous non-defining declaration DIE and |
395 | * similarly inherit the non-defining declaration's attributes |
396 | * (DWARF4 section 2.13) Likewise, any DIE that is a child of |
397 | * a concrete inlined instance can specify another DIE as its |
398 | * "abstract origin" and the original DIE will inherit the |
399 | * attributes of its abstract origin (DWARF4 section 3.3.8.2). |
400 | */ |
401 | value resolve(DW_AT attr) const; |
402 | |
403 | class iterator; |
404 | |
405 | /** |
406 | * Return an iterator over the children of this DIE. Note |
407 | * that the DIEs returned by this iterator are temporary, so |
408 | * if you need to store a DIE for more than one loop |
409 | * iteration, you must copy it. |
410 | */ |
411 | iterator begin() const; |
412 | iterator end() const; |
413 | |
414 | /** |
415 | * Return a vector of the attributes of this DIE. |
416 | */ |
417 | const std::vector<std::pair<DW_AT, value> > attributes() const; |
418 | |
419 | bool operator==(const die &o) const; |
420 | bool operator!=(const die &o) const; |
421 | |
422 | private: |
423 | friend class unit; |
424 | friend class type_unit; |
425 | friend class value; |
426 | // XXX If we can get the CU, we don't need this |
427 | friend struct ::std::hash<die>; |
428 | |
429 | const unit *cu; |
430 | // The abbrev of this DIE. By convention, if this DIE |
431 | // represents a sibling list terminator, this is null. This |
432 | // object is kept live by the CU. |
433 | const abbrev_entry *abbrev; |
434 | // The beginning of this DIE, relative to the CU. |
435 | section_offset offset; |
436 | // Offsets of attributes, relative to cu's subsection. The |
437 | // vast majority of DIEs tend to have six or fewer attributes, |
438 | // so we reserve space in the DIE itself for six attributes. |
439 | small_vector<section_offset, 6> attrs; |
440 | // The offset of the next DIE, relative to cu'd subsection. |
441 | // This is set even for sibling list terminators. |
442 | section_offset next; |
443 | |
444 | die(const unit *cu); |
445 | |
446 | /** |
447 | * Read this DIE from the given offset in cu. |
448 | */ |
449 | void read(section_offset off); |
450 | }; |
451 | |
452 | /** |
453 | * An iterator over a sequence of sibling DIEs. |
454 | */ |
455 | class die::iterator |
456 | { |
457 | public: |
458 | iterator() = default; |
459 | iterator(const iterator &o) = default; |
460 | iterator(iterator &&o) = default; |
461 | |
462 | iterator& operator=(const iterator &o) = default; |
463 | iterator& operator=(iterator &&o) = default; |
464 | |
465 | const die &operator*() const |
466 | { |
467 | return d; |
468 | } |
469 | |
470 | const die *operator->() const |
471 | { |
472 | return &d; |
473 | } |
474 | |
475 | // XXX Make this less confusing by implementing operator== instead |
476 | bool operator!=(const iterator &o) const |
477 | { |
478 | // Quick test of abbrevs. In particular, this weeds |
479 | // out non-end against end, which is a common |
480 | // comparison while iterating, though it also weeds |
481 | // out many other things. |
482 | if (d.abbrev != o.d.abbrev) |
483 | return true; |
484 | |
485 | // Same, possibly NULL abbrev. If abbrev is NULL, |
486 | // then next's are uncomparable, so we need to stop |
487 | // now. We consider all ends to be the same, without |
488 | // comparing cu's. |
489 | if (d.abbrev == nullptr) |
490 | return false; |
491 | |
492 | // Comparing two non-end abbrevs. |
493 | return d.next != o.d.next || d.cu != o.d.cu; |
494 | } |
495 | |
496 | iterator &operator++(); |
497 | |
498 | private: |
499 | friend class die; |
500 | |
501 | iterator(const unit *cu, section_offset off); |
502 | |
503 | die d; |
504 | }; |
505 | |
506 | inline die::iterator |
507 | die::end() const |
508 | { |
509 | return iterator(); |
510 | } |
511 | |
512 | /** |
513 | * An exception indicating that a value is not of the requested type. |
514 | */ |
515 | class value_type_mismatch : public std::logic_error |
516 | { |
517 | public: |
518 | explicit value_type_mismatch(const std::string &what_arg) |
519 | : std::logic_error(what_arg) { } |
520 | explicit value_type_mismatch(const char *what_arg) |
521 | : std::logic_error(what_arg) { } |
522 | }; |
523 | |
524 | /** |
525 | * The value of a DIE attribute. |
526 | * |
527 | * This is logically a union of many different types. Each type has a |
528 | * corresponding as_* methods that will return the value as that type |
529 | * or throw value_type_mismatch if the attribute is not of the |
530 | * requested type. |
531 | * |
532 | * Values of "constant" type are somewhat ambiguous and |
533 | * context-dependent. Constant forms with specified signed-ness have |
534 | * type "uconstant" or "sconstant", while other constant forms have |
535 | * type "constant". If the value's type is "constant", it can be |
536 | * retrieved using either as_uconstant or as_sconstant. |
537 | * |
538 | * Some other types can also be coerced. These are documented on the |
539 | * individual as_* methods. |
540 | * |
541 | * There is no as_line; while there is an attribute for line tables, |
542 | * line tables are really associated with compilation units (and |
543 | * require additional context from the compilation unit). Use |
544 | * compilation_unit::get_line_table instead. |
545 | */ |
546 | class value |
547 | { |
548 | public: |
549 | enum class type |
550 | { |
551 | invalid, |
552 | address, |
553 | block, |
554 | constant, |
555 | uconstant, |
556 | sconstant, |
557 | exprloc, |
558 | flag, |
559 | line, |
560 | loclist, |
561 | mac, |
562 | rangelist, |
563 | reference, |
564 | string |
565 | }; |
566 | |
567 | /** |
568 | * Construct a value with type `type::invalid`. |
569 | */ |
570 | value() : cu(nullptr), typ(type::invalid) { } |
571 | |
572 | value(const value &o) = default; |
573 | value(value &&o) = default; |
574 | |
575 | value& operator=(const value &o) = default; |
576 | value& operator=(value &&o) = default; |
577 | |
578 | /** |
579 | * Return true if this object represents a valid value. |
580 | * Default constructed line tables are not valid. |
581 | */ |
582 | bool valid() const |
583 | { |
584 | return typ != type::invalid; |
585 | } |
586 | |
587 | /** |
588 | * Return this value's byte offset within its compilation |
589 | * unit. |
590 | */ |
591 | section_offset get_unit_offset() const |
592 | { |
593 | return offset; |
594 | } |
595 | |
596 | /** |
597 | * Return this value's byte offset within its section. |
598 | */ |
599 | section_offset get_section_offset() const; |
600 | |
601 | type get_type() const |
602 | { |
603 | return typ; |
604 | } |
605 | |
606 | /** |
607 | * Return this value's attribute encoding. This automatically |
608 | * resolves indirect encodings, so this will never return |
609 | * DW_FORM::indirect. Note that the mapping from forms to |
610 | * types is non-trivial and often depends on the attribute |
611 | * (especially prior to DWARF 4). |
612 | */ |
613 | DW_FORM get_form() const |
614 | { |
615 | return form; |
616 | } |
617 | |
618 | /** |
619 | * Return this value as a target machine address. |
620 | */ |
621 | taddr as_address() const; |
622 | |
623 | /** |
624 | * Return this value as a block. The returned pointer points |
625 | * directly into the section data, so the caller must ensure |
626 | * that remains valid as long as the data is in use. |
627 | * *size_out is set to the length of the returned block, in |
628 | * bytes. |
629 | * |
630 | * This automatically coerces "exprloc" type values by |
631 | * returning the raw bytes of the encoded expression. |
632 | */ |
633 | const void *as_block(size_t *size_out) const; |
634 | |
635 | /** |
636 | * Return this value as an unsigned constant. This |
637 | * automatically coerces "constant" type values by |
638 | * interpreting their bytes as unsigned. |
639 | */ |
640 | uint64_t as_uconstant() const; |
641 | |
642 | /** |
643 | * Return this value as a signed constant. This automatically |
644 | * coerces "constant" type values by interpreting their bytes |
645 | * as twos-complement signed values. |
646 | */ |
647 | int64_t as_sconstant() const; |
648 | |
649 | /** |
650 | * Return this value as an expression. This automatically |
651 | * coerces "block" type values by interpreting the bytes in |
652 | * the block as an expression (prior to DWARF 4, exprlocs were |
653 | * always encoded as blocks, though the library automatically |
654 | * distinguishes these types based on context). |
655 | */ |
656 | expr as_exprloc() const; |
657 | |
658 | /** |
659 | * Return this value as a boolean flag. |
660 | */ |
661 | bool as_flag() const; |
662 | |
663 | // XXX loclistptr, macptr |
664 | |
665 | /** |
666 | * Return this value as a rangelist. |
667 | */ |
668 | rangelist as_rangelist() const; |
669 | |
670 | /** |
671 | * For a reference type value, return the referenced DIE. |
672 | * This DIE may be in a different compilation unit or could |
673 | * be a DIE in a type unit. |
674 | */ |
675 | die as_reference() const; |
676 | |
677 | /** |
678 | * Return this value as a string. |
679 | */ |
680 | std::string as_string() const; |
681 | |
682 | /** |
683 | * Fill the given string buffer with the string value of this |
684 | * value. This is useful to minimize allocation when reading |
685 | * several string-type values. |
686 | */ |
687 | void as_string(std::string &buf) const; |
688 | |
689 | /** |
690 | * Return this value as a NUL-terminated character string. |
691 | * The returned pointer points directly into the section data, |
692 | * so the caller must ensure that remains valid as long as the |
693 | * data is in use. *size_out, if not NULL, is set to the |
694 | * length of the returned string without the NUL-terminator. |
695 | */ |
696 | const char *as_cstr(size_t *size_out = nullptr) const; |
697 | |
698 | /** |
699 | * Return this value as a section offset. This is applicable |
700 | * to lineptr, loclistptr, macptr, and rangelistptr. |
701 | */ |
702 | section_offset as_sec_offset() const; |
703 | |
704 | private: |
705 | friend class die; |
706 | |
707 | value(const unit *cu, |
708 | DW_AT name, DW_FORM form, type typ, section_offset offset); |
709 | |
710 | void resolve_indirect(DW_AT name); |
711 | |
712 | const unit *cu; |
713 | DW_FORM form; |
714 | type typ; |
715 | section_offset offset; |
716 | }; |
717 | |
718 | std::string |
719 | to_string(value::type v); |
720 | |
721 | std::string |
722 | to_string(const value &v); |
723 | |
724 | ////////////////////////////////////////////////////////////////// |
725 | // Expressions and location descriptions |
726 | // |
727 | |
728 | /** |
729 | * An exception during expression evaluation. |
730 | */ |
731 | class expr_error : public std::runtime_error |
732 | { |
733 | public: |
734 | explicit expr_error(const std::string &what_arg) |
735 | : std::runtime_error(what_arg) { } |
736 | explicit expr_error(const char *what_arg) |
737 | : std::runtime_error(what_arg) { } |
738 | }; |
739 | |
740 | /** |
741 | * A DWARF expression or location description. |
742 | */ |
743 | class expr |
744 | { |
745 | public: |
746 | /** |
747 | * Short-hand for evaluate(ctx, {}). |
748 | */ |
749 | expr_result evaluate(expr_context *ctx) const; |
750 | |
751 | /** |
752 | * Short-hand for evaluate(ctx, {argument}). |
753 | */ |
754 | expr_result evaluate(expr_context *ctx, taddr argument) const; |
755 | |
756 | /** |
757 | * Return the result of evaluating this expression using the |
758 | * specified expression context. The expression stack will be |
759 | * initialized with the given arguments such that the first |
760 | * arguments is at the top of the stack and the last argument |
761 | * at the bottom of the stack. |
762 | * |
763 | * Throws expr_error if there is an error evaluating the |
764 | * expression (such as an unknown operation, stack underflow, |
765 | * bounds error, etc.) |
766 | */ |
767 | expr_result evaluate(expr_context *ctx, const std::initializer_list<taddr> &arguments) const; |
768 | |
769 | private: |
770 | // XXX This will need more information for some operations |
771 | expr(const unit *cu, |
772 | section_offset offset, section_length len); |
773 | |
774 | friend class value; |
775 | |
776 | const unit *cu; |
777 | section_offset offset; |
778 | section_length len; |
779 | }; |
780 | |
781 | /** |
782 | * An interface that provides contextual information for expression |
783 | * evaluation. Callers of expr::evaluate are expected to subclass |
784 | * this in order to provide this information to the expression |
785 | * evaluation engine. The default implementation throws expr_error |
786 | * for all methods. |
787 | */ |
788 | class expr_context |
789 | { |
790 | public: |
791 | virtual ~expr_context() { } |
792 | |
793 | /** |
794 | * Return the value stored in register regnum. This is used |
795 | * to implement DW_OP_breg* operations. |
796 | */ |
797 | virtual taddr reg(unsigned regnum) |
798 | { |
799 | (void)regnum; |
800 | throw expr_error("DW_OP_breg* operations not supported" ); |
801 | } |
802 | |
803 | /** |
804 | * Implement DW_OP_deref_size. |
805 | */ |
806 | virtual taddr deref_size(taddr address, unsigned size) |
807 | { |
808 | (void)address; |
809 | (void)size; |
810 | throw expr_error("DW_OP_deref_size operations not supported" ); |
811 | } |
812 | |
813 | /** |
814 | * Implement DW_OP_xderef_size. |
815 | */ |
816 | virtual taddr xderef_size(taddr address, taddr asid, unsigned size) |
817 | { |
818 | (void)address; |
819 | (void)asid; |
820 | (void)size; |
821 | throw expr_error("DW_OP_xderef_size operations not supported" ); |
822 | } |
823 | |
824 | /** |
825 | * Implement DW_OP_form_tls_address. |
826 | */ |
827 | virtual taddr form_tls_address(taddr address) |
828 | { |
829 | (void)address; |
830 | throw expr_error("DW_OP_form_tls_address operations not supported" ); |
831 | } |
832 | }; |
833 | |
834 | /** |
835 | * An instance of expr_context that throws expr_error for all methods. |
836 | * This is equivalent to the default construction of expr_context, but |
837 | * often more convenient to use. |
838 | */ |
839 | extern expr_context no_expr_context; |
840 | |
841 | // XXX Provide methods to check type and fetch value? |
842 | /** |
843 | * The result of evaluating a DWARF expression or location |
844 | * description. |
845 | */ |
846 | class expr_result |
847 | { |
848 | public: |
849 | enum class type { |
850 | /** |
851 | * value specifies the address in memory of an object. |
852 | * This is also the result type used for general |
853 | * expressions that do not refer to object locations. |
854 | */ |
855 | address, |
856 | /** |
857 | * value specifies a register storing an object. |
858 | */ |
859 | reg, |
860 | /** |
861 | * The object does not have a location. value is the |
862 | * value of the object. |
863 | */ |
864 | literal, |
865 | /** |
866 | * The object does not have a location. Its value is |
867 | * pointed to by the 'implicit' field. |
868 | */ |
869 | implicit, |
870 | /** |
871 | * The object is present in the source, but not in the |
872 | * object code, and hence does not have a location or |
873 | * a value. |
874 | */ |
875 | empty, |
876 | }; |
877 | |
878 | /** |
879 | * For location descriptions, the type of location this result |
880 | * describes. |
881 | */ |
882 | type location_type; |
883 | |
884 | /** |
885 | * For general-purpose expressions, the result of expression. |
886 | * For address location descriptions, the address in memory of |
887 | * the object. For register location descriptions, the |
888 | * register storing the object. For literal location |
889 | * descriptions, the value of the object. |
890 | */ |
891 | taddr value; |
892 | |
893 | /** |
894 | * For implicit location descriptions, a pointer to a block |
895 | * representing the value in the memory representation of the |
896 | * target machine. |
897 | */ |
898 | const char *implicit; |
899 | size_t implicit_len; |
900 | |
901 | // XXX Composite locations |
902 | }; |
903 | |
904 | std::string |
905 | to_string(expr_result::type v); |
906 | |
907 | ////////////////////////////////////////////////////////////////// |
908 | // Range lists |
909 | // |
910 | |
911 | /** |
912 | * A DWARF range list describing a set of possibly non-contiguous |
913 | * addresses. |
914 | */ |
915 | class rangelist |
916 | { |
917 | public: |
918 | /** |
919 | * \internal Construct a range list whose data begins at the |
920 | * given offset in sec. cu_addr_size is the address size of |
921 | * the associated compilation unit. cu_low_pc is the |
922 | * DW_AT::low_pc attribute of the compilation unit containing |
923 | * the referring DIE or 0 (this is used as the base address of |
924 | * the range list). |
925 | */ |
926 | rangelist(const std::shared_ptr<section> &sec, section_offset off, |
927 | unsigned cu_addr_size, taddr cu_low_pc); |
928 | |
929 | /** |
930 | * Construct a range list from a sequence of {low, high} |
931 | * pairs. |
932 | */ |
933 | rangelist(const std::initializer_list<std::pair<taddr, taddr> > &ranges); |
934 | |
935 | /** |
936 | * Construct an empty range list. |
937 | */ |
938 | rangelist() = default; |
939 | |
940 | /** Copy constructor */ |
941 | rangelist(const rangelist &o) = default; |
942 | /** Move constructor */ |
943 | rangelist(rangelist &&o) = default; |
944 | |
945 | rangelist& operator=(const rangelist &o) = default; |
946 | rangelist& operator=(rangelist &&o) = default; |
947 | |
948 | class entry; |
949 | typedef entry value_type; |
950 | |
951 | class iterator; |
952 | |
953 | /** |
954 | * Return an iterator over the entries in this range list. |
955 | * The ranges returned by this iterator are temporary, so if |
956 | * you need to store a range for more than one loop iteration, |
957 | * you must copy it. |
958 | */ |
959 | iterator begin() const; |
960 | |
961 | /** |
962 | * Return an iterator to one past the last entry in this range |
963 | * list. |
964 | */ |
965 | iterator end() const; |
966 | |
967 | /** |
968 | * Return true if this range list contains the given address. |
969 | */ |
970 | bool contains(taddr addr) const; |
971 | |
972 | private: |
973 | std::vector<taddr> synthetic; |
974 | std::shared_ptr<section> sec; |
975 | taddr base_addr; |
976 | }; |
977 | |
978 | /** |
979 | * An entry in a range list. The range spans addresses [low, high). |
980 | */ |
981 | class rangelist::entry |
982 | { |
983 | public: |
984 | taddr low, high; |
985 | |
986 | /** |
987 | * Return true if addr is within this entry's bounds. |
988 | */ |
989 | bool contains(taddr addr) const |
990 | { |
991 | return low <= addr && addr < high; |
992 | } |
993 | }; |
994 | |
995 | /** |
996 | * An iterator over a sequence of ranges in a range list. |
997 | */ |
998 | class rangelist::iterator |
999 | { |
1000 | public: |
1001 | /** |
1002 | * \internal Construct an end iterator. |
1003 | */ |
1004 | iterator() : sec(nullptr), base_addr(0), pos(0) { } |
1005 | |
1006 | /** |
1007 | * \internal Construct an iterator that reads rangelist data |
1008 | * from the beginning of the given section and starts with the |
1009 | * given base address. |
1010 | */ |
1011 | iterator(const std::shared_ptr<section> &sec, taddr base_addr); |
1012 | |
1013 | /** Copy constructor */ |
1014 | iterator(const iterator &o) = default; |
1015 | /** Move constructor */ |
1016 | iterator(iterator &&o) = default; |
1017 | |
1018 | iterator& operator=(const iterator &o) = default; |
1019 | iterator& operator=(iterator &&o) = default; |
1020 | |
1021 | /** |
1022 | * Return the current range list entry. This entry is reused |
1023 | * internally, so the caller should copy it if it needs to |
1024 | * persist past the next increment. |
1025 | */ |
1026 | const rangelist::entry &operator*() const |
1027 | { |
1028 | return entry; |
1029 | } |
1030 | |
1031 | /** Dereference operator */ |
1032 | const rangelist::entry *operator->() const |
1033 | { |
1034 | return &entry; |
1035 | } |
1036 | |
1037 | /** Equality operator */ |
1038 | bool operator==(const iterator &o) const |
1039 | { |
1040 | return sec == o.sec && pos == o.pos; |
1041 | } |
1042 | |
1043 | /** Inequality operator */ |
1044 | bool operator!=(const iterator &o) const |
1045 | { |
1046 | return !(*this == o); |
1047 | } |
1048 | |
1049 | /** |
1050 | * Increment this iterator to point to the next range list |
1051 | * entry. |
1052 | */ |
1053 | iterator &operator++(); |
1054 | |
1055 | private: |
1056 | std::shared_ptr<section> sec; |
1057 | taddr base_addr; |
1058 | section_offset pos; |
1059 | rangelist::entry entry; |
1060 | }; |
1061 | |
1062 | ////////////////////////////////////////////////////////////////// |
1063 | // Line number tables |
1064 | // |
1065 | |
1066 | /** |
1067 | * A DWARF line number table. A line number table is a list of line |
1068 | * table entries, broken up into "sequences". Within a sequence, |
1069 | * entries are in order of increasing program counter ("address") and |
1070 | * an entry provides information for all program counters between the |
1071 | * entry's address and the address of the next entry. Each sequence |
1072 | * is terminated by a special entry with its |
1073 | * line_table::entry::end_sequence flag set. The line number table |
1074 | * also records the set of source files for a given compilation unit, |
1075 | * which can be referred to from other DIE attributes. |
1076 | */ |
1077 | class line_table |
1078 | { |
1079 | public: |
1080 | /** |
1081 | * \internal Construct a line number table whose header begins |
1082 | * at the given offset in sec. cu_addr_size is the address |
1083 | * size of the associated compilation unit. cu_comp_dir and |
1084 | * cu_name give the DW_AT::comp_dir and DW_AT::name attributes |
1085 | * of the associated compilation unit. |
1086 | */ |
1087 | line_table(const std::shared_ptr<section> &sec, section_offset offset, |
1088 | unsigned cu_addr_size, const std::string &cu_comp_dir, |
1089 | const std::string &cu_name); |
1090 | |
1091 | /** |
1092 | * Construct an invalid, empty line table. |
1093 | */ |
1094 | line_table() = default; |
1095 | |
1096 | /** Copy constructor */ |
1097 | line_table(const line_table &o) = default; |
1098 | /** Move constructor */ |
1099 | line_table(line_table &&o) = default; |
1100 | |
1101 | line_table &operator=(const line_table &o) = default; |
1102 | line_table &operator=(line_table &&o) = default; |
1103 | |
1104 | /** |
1105 | * Return true if this object represents an initialized line |
1106 | * table. Default constructed line tables are not valid. |
1107 | */ |
1108 | bool valid() const |
1109 | { |
1110 | return !!m; |
1111 | } |
1112 | |
1113 | class file; |
1114 | class entry; |
1115 | typedef entry value_type; |
1116 | |
1117 | class iterator; |
1118 | |
1119 | /** |
1120 | * Return an iterator to the beginning of this line number |
1121 | * table. If called on an invalid line table, this will |
1122 | * return an iterator equal to end(). |
1123 | */ |
1124 | iterator begin() const; |
1125 | |
1126 | /** |
1127 | * Return an iterator to one past the last entry in this line |
1128 | * number table. |
1129 | */ |
1130 | iterator end() const; |
1131 | |
1132 | /** |
1133 | * Return an iterator to the line table entry containing addr |
1134 | * (roughly, the entry with the highest address less than or |
1135 | * equal to addr, but accounting for end_sequence entries). |
1136 | * Returns end() if there is no such entry. |
1137 | */ |
1138 | iterator find_address(taddr addr) const; |
1139 | |
1140 | /** |
1141 | * Return the index'th file in the line table. These indexes |
1142 | * are typically used by declaration and call coordinates. If |
1143 | * index is out of range, throws out_of_range. |
1144 | */ |
1145 | const file *get_file(unsigned index) const; |
1146 | |
1147 | private: |
1148 | friend class iterator; |
1149 | |
1150 | struct impl; |
1151 | std::shared_ptr<impl> m; |
1152 | }; |
1153 | |
1154 | /** |
1155 | * A source file in a line table. |
1156 | */ |
1157 | class line_table::file |
1158 | { |
1159 | public: |
1160 | /** |
1161 | * The absolute path of this source file. |
1162 | */ |
1163 | std::string path; |
1164 | |
1165 | /** |
1166 | * The last modification time of this source file in an |
1167 | * implementation-defined encoding or 0 if unknown. |
1168 | */ |
1169 | uint64_t mtime; |
1170 | |
1171 | /** |
1172 | * The size in bytes of this source file or 0 if unknown. |
1173 | */ |
1174 | uint64_t length; |
1175 | |
1176 | /** |
1177 | * Construct a source file object. |
1178 | */ |
1179 | file(std::string path = "" , uint64_t mtime = 0, uint64_t length = 0); |
1180 | }; |
1181 | |
1182 | /** |
1183 | * An entry in the line table. |
1184 | */ |
1185 | class line_table::entry |
1186 | { |
1187 | public: |
1188 | /** |
1189 | * The program counter value corresponding to a machine |
1190 | * instruction generated by the compiler. |
1191 | */ |
1192 | taddr address; |
1193 | |
1194 | /** |
1195 | * The index of an operation within a VLIW instruction. The |
1196 | * index of the first operation is 0. For non-VLIW |
1197 | * architectures, this will always be 0. |
1198 | */ |
1199 | unsigned op_index; |
1200 | |
1201 | /** |
1202 | * The source file containing this instruction. |
1203 | */ |
1204 | const line_table::file *file; |
1205 | |
1206 | /** |
1207 | * The index of the source file containing this instruction. |
1208 | */ |
1209 | unsigned file_index; |
1210 | |
1211 | /** |
1212 | * The source line number of this instruction, starting at 1. |
1213 | * This may be 0 if this instruction cannot be attributed to |
1214 | * any source line. |
1215 | */ |
1216 | unsigned line; |
1217 | |
1218 | /** |
1219 | * The column number within this source line, starting at 1. |
1220 | * The value 0 indicates that a statement begins at the "left |
1221 | * edge" of the line, whatever that means. |
1222 | */ |
1223 | unsigned column; |
1224 | |
1225 | /** |
1226 | * True if this instruction is a recommended breakpoint |
1227 | * location. Typically this is the beginning of a statement. |
1228 | */ |
1229 | bool is_stmt; |
1230 | |
1231 | /** |
1232 | * True if this instruction is the beginning of a basic block. |
1233 | */ |
1234 | bool basic_block; |
1235 | |
1236 | /** |
1237 | * True if this address is the first byte after the end of a |
1238 | * sequence of target machine instructions. In this case, all |
1239 | * other fields besides address are not meaningful. |
1240 | */ |
1241 | bool end_sequence; |
1242 | |
1243 | /** |
1244 | * True if this address is one where execution should be |
1245 | * suspended for an entry breakpoint of a function. |
1246 | */ |
1247 | bool prologue_end; |
1248 | |
1249 | /** |
1250 | * True if this address is one where execution should be |
1251 | * suspended for an exit breakpoint of a function. |
1252 | */ |
1253 | bool epilogue_begin; |
1254 | |
1255 | /** |
1256 | * The instruction set architecture of this instruction. The |
1257 | * meaning of this field is generally defined by an |
1258 | * architecture's ABI. |
1259 | */ |
1260 | unsigned isa; |
1261 | |
1262 | /** |
1263 | * A number that identifies the block containing the current |
1264 | * instruction if multiple blocks are associated with the same |
1265 | * source file, line, and column. |
1266 | */ |
1267 | unsigned discriminator; |
1268 | |
1269 | /** |
1270 | * Reset this line info object to the default initial values |
1271 | * for all fields. is_stmt has no default value, so the |
1272 | * caller must provide it. |
1273 | */ |
1274 | void reset(bool is_stmt); |
1275 | |
1276 | /** |
1277 | * Return a descriptive string of the form |
1278 | * "filename[:line[:column]]". |
1279 | */ |
1280 | std::string get_description() const; |
1281 | }; |
1282 | |
1283 | /** |
1284 | * An iterator over the entries in a line table. |
1285 | */ |
1286 | class line_table::iterator |
1287 | { |
1288 | public: |
1289 | /** |
1290 | * \internal Construct an iterator for the given line table |
1291 | * starting pos bytes into the table's section. |
1292 | */ |
1293 | iterator(const line_table *table, section_offset pos); |
1294 | |
1295 | /** Copy constructor */ |
1296 | iterator(const iterator &o) = default; |
1297 | /** Move constructor */ |
1298 | iterator(iterator &&o) = default; |
1299 | |
1300 | iterator &operator=(const iterator &o) = default; |
1301 | iterator &operator=(iterator &&o) = default; |
1302 | |
1303 | /** |
1304 | * Return the current line table entry. This entry is reused |
1305 | * internally, so the caller should copy it if it needs to |
1306 | * persist past the next increment. |
1307 | */ |
1308 | const line_table::entry &operator*() const |
1309 | { |
1310 | return entry; |
1311 | } |
1312 | |
1313 | /** Dereference operator */ |
1314 | const line_table::entry *operator->() const |
1315 | { |
1316 | return &entry; |
1317 | } |
1318 | |
1319 | /** Equality operator */ |
1320 | bool operator==(const iterator &o) const |
1321 | { |
1322 | return o.pos == pos && o.table == table; |
1323 | } |
1324 | |
1325 | /** Inequality operator */ |
1326 | bool operator!=(const iterator &o) const |
1327 | { |
1328 | return !(*this == o); |
1329 | } |
1330 | |
1331 | /** |
1332 | * Increment this iterator to point to the next line table |
1333 | * entry. |
1334 | */ |
1335 | iterator &operator++(); |
1336 | |
1337 | /** Post-increment operator */ |
1338 | iterator operator++(int) |
1339 | { |
1340 | iterator tmp(*this); |
1341 | ++(*this); |
1342 | return tmp; |
1343 | } |
1344 | |
1345 | private: |
1346 | const line_table *table; |
1347 | line_table::entry entry, regs; |
1348 | section_offset pos; |
1349 | |
1350 | /** |
1351 | * Process the next opcode. If the opcode "adds a row to the |
1352 | * table", update entry to reflect the row and return true. |
1353 | */ |
1354 | bool step(cursor *cur); |
1355 | }; |
1356 | |
1357 | ////////////////////////////////////////////////////////////////// |
1358 | // Type-safe attribute getters |
1359 | // |
1360 | |
1361 | // XXX More |
1362 | |
1363 | die at_abstract_origin(const die &d); |
1364 | DW_ACCESS at_accessibility(const die &d); |
1365 | uint64_t at_allocated(const die &d, expr_context *ctx); |
1366 | bool at_artificial(const die &d); |
1367 | uint64_t at_associated(const die &d, expr_context *ctx); |
1368 | uint64_t at_bit_offset(const die &d, expr_context *ctx); |
1369 | uint64_t at_bit_size(const die &d, expr_context *ctx); |
1370 | uint64_t at_bit_stride(const die &d, expr_context *ctx); |
1371 | uint64_t at_byte_size(const die &d, expr_context *ctx); |
1372 | uint64_t at_byte_stride(const die &d, expr_context *ctx); |
1373 | DW_CC at_calling_convention(const die &d); |
1374 | die at_common_reference(const die &d); |
1375 | std::string at_comp_dir(const die &d); |
1376 | value at_const_value(const die &d); |
1377 | bool at_const_expr(const die &d); |
1378 | die at_containing_type(const die &d); |
1379 | uint64_t at_count(const die &d, expr_context *ctx); |
1380 | expr_result at_data_member_location(const die &d, expr_context *ctx, taddr base, taddr pc); |
1381 | bool at_declaration(const die &d); |
1382 | std::string at_description(const die &d); |
1383 | die at_discr(const die &d); |
1384 | value at_discr_value(const die &d); |
1385 | bool at_elemental(const die &d); |
1386 | DW_ATE at_encoding(const die &d); |
1387 | DW_END at_endianity(const die &d); |
1388 | taddr at_entry_pc(const die &d); |
1389 | bool at_enum_class(const die &d); |
1390 | bool at_explicit(const die &d); |
1391 | die at_extension(const die &d); |
1392 | bool at_external(const die &d); |
1393 | die at_friend(const die &d); |
1394 | taddr at_high_pc(const die &d); |
1395 | DW_ID at_identifier_case(const die &d); |
1396 | die at_import(const die &d); |
1397 | DW_INL at_inline(const die &d); |
1398 | bool at_is_optional(const die &d); |
1399 | DW_LANG at_language(const die &d); |
1400 | std::string at_linkage_name(const die &d); |
1401 | taddr at_low_pc(const die &d); |
1402 | uint64_t at_lower_bound(const die &d, expr_context *ctx); |
1403 | bool at_main_subprogram(const die &d); |
1404 | bool at_mutable(const die &d); |
1405 | std::string at_name(const die &d); |
1406 | die at_namelist_item(const die &d); |
1407 | die at_object_pointer(const die &d); |
1408 | DW_ORD at_ordering(const die &d); |
1409 | std::string at_picture_string(const die &d); |
1410 | die at_priority(const die &d); |
1411 | std::string at_producer(const die &d); |
1412 | bool at_prototyped(const die &d); |
1413 | bool at_pure(const die &d); |
1414 | rangelist at_ranges(const die &d); |
1415 | bool at_recursive(const die &d); |
1416 | die at_sibling(const die &d); |
1417 | die at_signature(const die &d); |
1418 | die at_small(const die &d); |
1419 | die at_specification(const die &d); |
1420 | bool at_threads_scaled(const die &d); |
1421 | die at_type(const die &d); |
1422 | uint64_t at_upper_bound(const die &d, expr_context *ctx); |
1423 | bool at_use_UTF8(const die &d); |
1424 | bool at_variable_parameter(const die &d); |
1425 | DW_VIRTUALITY at_virtuality(const die &d); |
1426 | DW_VIS at_visibility(const die &d); |
1427 | |
1428 | /** |
1429 | * Return the PC range spanned by the code of a DIE. The DIE must |
1430 | * either have DW_AT::ranges or DW_AT::low_pc. It may optionally have |
1431 | * DW_AT::high_pc. |
1432 | */ |
1433 | rangelist die_pc_range(const die &d); |
1434 | |
1435 | ////////////////////////////////////////////////////////////////// |
1436 | // Utilities |
1437 | // |
1438 | |
1439 | /** |
1440 | * An index of sibling DIEs by some string attribute. This index is |
1441 | * lazily constructed and space-efficient. |
1442 | */ |
1443 | class die_str_map |
1444 | { |
1445 | public: |
1446 | /** |
1447 | * Construct the index of the attr attribute of all immediate |
1448 | * children of parent whose tags are in accept. |
1449 | */ |
1450 | die_str_map(const die &parent, DW_AT attr, |
1451 | const std::initializer_list<DW_TAG> &accept); |
1452 | |
1453 | die_str_map() = default; |
1454 | die_str_map(const die_str_map &o) = default; |
1455 | die_str_map(die_str_map &&o) = default; |
1456 | |
1457 | die_str_map& operator=(const die_str_map &o) = default; |
1458 | die_str_map& operator=(die_str_map &&o) = default; |
1459 | |
1460 | /** |
1461 | * Construct a string map for the type names of parent's |
1462 | * immediate children. |
1463 | * |
1464 | * XXX This should use .debug_pubtypes if parent is a compile |
1465 | * unit's root DIE, but it currently does not. |
1466 | */ |
1467 | static die_str_map from_type_names(const die &parent); |
1468 | |
1469 | /** |
1470 | * Return the DIE whose attribute matches val. If no such DIE |
1471 | * exists, return an invalid die object. |
1472 | */ |
1473 | const die &operator[](const char *val) const; |
1474 | |
1475 | /** |
1476 | * Short-hand for [value.c_str()]. |
1477 | */ |
1478 | const die &operator[](const std::string &val) const |
1479 | { |
1480 | return (*this)[val.c_str()]; |
1481 | } |
1482 | |
1483 | private: |
1484 | struct impl; |
1485 | std::shared_ptr<impl> m; |
1486 | }; |
1487 | |
1488 | ////////////////////////////////////////////////////////////////// |
1489 | // ELF support |
1490 | // |
1491 | |
1492 | namespace elf |
1493 | { |
1494 | /** |
1495 | * Translate an ELF section name info a DWARF section type. |
1496 | * If the section is a valid DWARF section name, sets *out to |
1497 | * the type and returns true. If not, returns false. |
1498 | */ |
1499 | bool section_name_to_type(const char *name, section_type *out); |
1500 | |
1501 | /** |
1502 | * Translate a DWARF section type into an ELF section name. |
1503 | */ |
1504 | const char *section_type_to_name(section_type type); |
1505 | |
1506 | template<typename Elf> |
1507 | class elf_loader : public loader |
1508 | { |
1509 | Elf f; |
1510 | |
1511 | public: |
1512 | elf_loader(const Elf &file) : f(file) { } |
1513 | |
1514 | const void *load(section_type section, size_t *size_out) |
1515 | { |
1516 | auto sec = f.get_section(section_type_to_name(section)); |
1517 | if (!sec.valid()) |
1518 | return nullptr; |
1519 | *size_out = sec.size(); |
1520 | return sec.data(); |
1521 | } |
1522 | }; |
1523 | |
1524 | /** |
1525 | * Create a DWARF section loader backed by the given ELF |
1526 | * file. This is templatized to eliminate a static dependency |
1527 | * between the libelf++ and libdwarf++, though it can only |
1528 | * reasonably be used with elf::elf from libelf++. |
1529 | */ |
1530 | template<typename Elf> |
1531 | std::shared_ptr<elf_loader<Elf> > create_loader(const Elf &f) |
1532 | { |
1533 | return std::make_shared<elf_loader<Elf> >(f); |
1534 | } |
1535 | }; |
1536 | |
1537 | DWARFPP_END_NAMESPACE |
1538 | |
1539 | ////////////////////////////////////////////////////////////////// |
1540 | // Hash specializations |
1541 | // |
1542 | |
1543 | namespace std |
1544 | { |
1545 | template<> |
1546 | struct hash<dwarf::unit> |
1547 | { |
1548 | typedef size_t result_type; |
1549 | typedef const dwarf::unit &argument_type; |
1550 | result_type operator()(argument_type a) const |
1551 | { |
1552 | return hash<decltype(a.m)>()(a.m); |
1553 | } |
1554 | }; |
1555 | |
1556 | template<> |
1557 | struct hash<dwarf::die> |
1558 | { |
1559 | typedef size_t result_type; |
1560 | typedef const dwarf::die &argument_type; |
1561 | result_type operator()(argument_type a) const; |
1562 | }; |
1563 | } |
1564 | |
1565 | #endif |
1566 | |