]>
Commit | Line | Data |
---|---|---|
1 | // -*- C++ -*- | |
2 | // Copyright (C) 2008-2014 Red Hat Inc. | |
3 | // | |
4 | // This file is part of systemtap, and is free software. You can | |
5 | // redistribute it and/or modify it under the terms of the GNU General | |
6 | // Public License (GPL); either version 2, or (at your option) any | |
7 | // later version. | |
8 | ||
9 | #ifndef DWARF_WRAPPERS_H | |
10 | #define DWARF_WRAPPERS_H 1 | |
11 | ||
12 | #include "config.h" | |
13 | ||
14 | extern "C" { | |
15 | #include <elfutils/libdw.h> | |
16 | #include <elfutils/version.h> | |
17 | #include <dwarf.h> | |
18 | } | |
19 | ||
20 | #include <string> | |
21 | ||
22 | #if ! _ELFUTILS_PREREQ(0, 148) | |
23 | #define DW_AT_linkage_name 0x6e | |
24 | #endif | |
25 | ||
26 | #if ! _ELFUTILS_PREREQ(0, 153) | |
27 | #define DW_TAG_GNU_call_site 0x4109 | |
28 | #define DW_AT_GNU_tail_call 0x2115 | |
29 | #endif | |
30 | ||
31 | #if ! _ELFUTILS_PREREQ(0, 155) | |
32 | #define DW_ATE_UTF 0x10 | |
33 | #endif | |
34 | ||
35 | #define DWFL_ASSERT(desc, arg) \ | |
36 | dwfl_assert(desc, arg, __FILE__, __LINE__) | |
37 | ||
38 | // NB: "rc == 0" means OK in this case | |
39 | void dwfl_assert(const std::string& desc, int rc, | |
40 | const std::string& file, int line); | |
41 | ||
42 | // Throw error if pointer is NULL | |
43 | inline void | |
44 | dwfl_assert(const std::string& desc, const void* ptr, | |
45 | const std::string& file, int line) | |
46 | { | |
47 | if (!ptr) | |
48 | dwfl_assert(desc, -1, file, line); | |
49 | } | |
50 | ||
51 | // Throw error if condition is false | |
52 | inline void | |
53 | dwfl_assert(const std::string& desc, bool condition, | |
54 | const std::string& file, int line) | |
55 | { | |
56 | if (!condition) | |
57 | dwfl_assert(desc, -1, file, line); | |
58 | } | |
59 | ||
60 | #define DWARF_ASSERT(desc, arg) \ | |
61 | dwarf_assert(desc, arg, __FILE__, __LINE__) | |
62 | ||
63 | // NB: "rc == 0" means OK in this case | |
64 | void dwarf_assert(const std::string& desc, int rc, | |
65 | const std::string& file, int line); | |
66 | ||
67 | // Throw error if pointer is NULL | |
68 | inline void | |
69 | dwarf_assert(const std::string& desc, const void* ptr, | |
70 | const std::string& file, int line) | |
71 | { | |
72 | if (!ptr) | |
73 | dwarf_assert(desc, -1, file, line); | |
74 | } | |
75 | ||
76 | #define DWARF_LINENO(line) \ | |
77 | safe_dwarf_lineno(line, __FILE__, __LINE__) | |
78 | ||
79 | inline int | |
80 | safe_dwarf_lineno(const Dwarf_Line* line, | |
81 | const std::string& errfile, int errline) | |
82 | { | |
83 | int lineno; | |
84 | dwarf_assert("dwarf_lineno", | |
85 | dwarf_lineno(const_cast<Dwarf_Line*>(line), &lineno), | |
86 | errfile, errline); | |
87 | return lineno; | |
88 | } | |
89 | ||
90 | #define DWARF_LINEADDR(line) \ | |
91 | safe_dwarf_lineaddr(line, __FILE__, __LINE__) | |
92 | ||
93 | inline Dwarf_Addr | |
94 | safe_dwarf_lineaddr(const Dwarf_Line* line, | |
95 | const std::string& errfile, int errline) | |
96 | { | |
97 | Dwarf_Addr addr; | |
98 | dwarf_assert("dwarf_lineaddr", | |
99 | dwarf_lineaddr(const_cast<Dwarf_Line*>(line), &addr), | |
100 | errfile, errline); | |
101 | return addr; | |
102 | } | |
103 | ||
104 | #define DWARF_LINESRC(line) \ | |
105 | safe_dwarf_linesrc(line, NULL, NULL, __FILE__, __LINE__) | |
106 | #define DWARF_LINESRC2(line, mtime) \ | |
107 | safe_dwarf_linesrc(line, mtime, NULL, __FILE__, __LINE__) | |
108 | #define DWARF_LINESRC3(line, mtime, length) \ | |
109 | safe_dwarf_linesrc(line, mtime, length, __FILE__, __LINE__) | |
110 | ||
111 | inline const char* | |
112 | safe_dwarf_linesrc(const Dwarf_Line* line, | |
113 | Dwarf_Word* mtime, | |
114 | Dwarf_Word* length, | |
115 | const std::string& errfile, int errline) | |
116 | { | |
117 | const char* linesrc = | |
118 | dwarf_linesrc(const_cast<Dwarf_Line*>(line), mtime, length); | |
119 | dwarf_assert("dwarf_linesrc", linesrc, errfile, errline); | |
120 | return linesrc; | |
121 | } | |
122 | ||
123 | #define DWARF_LINEPROLOGUEEND(line) \ | |
124 | safe_dwarf_lineprologueend(line, __FILE__, __LINE__) | |
125 | ||
126 | inline bool | |
127 | safe_dwarf_lineprologueend(const Dwarf_Line* line, | |
128 | const std::string& errfile, int errline) | |
129 | { | |
130 | bool flag; | |
131 | dwarf_assert("is_prologue_end", | |
132 | dwarf_lineprologueend(const_cast<Dwarf_Line*>(line), &flag), | |
133 | errfile, errline); | |
134 | return flag; | |
135 | } | |
136 | ||
137 | ||
138 | // Look up the DIE for a reference-form attribute name | |
139 | inline Dwarf_Die * | |
140 | dwarf_attr_die (Dwarf_Die *die, unsigned int attr, Dwarf_Die *result) | |
141 | { | |
142 | Dwarf_Attribute attr_mem; | |
143 | if (dwarf_formref_die (dwarf_attr_integrate (die, attr, &attr_mem), | |
144 | result) != NULL) | |
145 | { | |
146 | /* If we want a type make sure we get the actual DIE describing | |
147 | the real type. */ | |
148 | if (attr == DW_AT_type) | |
149 | { | |
150 | Dwarf_Attribute sigm; | |
151 | Dwarf_Attribute *sig = dwarf_attr (result, DW_AT_signature, &sigm); | |
152 | if (sig != NULL) | |
153 | result = dwarf_formref_die (sig, result); | |
154 | ||
155 | /* A DW_AT_signature might point to a type_unit, then | |
156 | the actual type DIE we want is the first child. */ | |
157 | if (result != NULL && dwarf_tag (result) == DW_TAG_type_unit) | |
158 | DWFL_ASSERT("type_unit child", dwarf_child (result, result)); | |
159 | } | |
160 | return result; | |
161 | } | |
162 | return NULL; | |
163 | } | |
164 | ||
165 | ||
166 | // Retrieve the linkage name of a die, either by the MIPS vendor extension or | |
167 | // DWARF4's standardized attribute. | |
168 | inline const char * | |
169 | dwarf_linkage_name (Dwarf_Die *die) | |
170 | { | |
171 | Dwarf_Attribute attr_mem; | |
172 | return dwarf_formstring | |
173 | (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name, &attr_mem) | |
174 | ?: dwarf_attr_integrate (die, DW_AT_linkage_name, &attr_mem)); | |
175 | } | |
176 | ||
177 | ||
178 | #if !_ELFUTILS_PREREQ(0, 143) | |
179 | // Elfutils prior to 0.143 didn't use attr_integrate when looking up the | |
180 | // decl_file or decl_line, so the attributes would sometimes be missed. For | |
181 | // those old versions, we define custom implementations to do the integration. | |
182 | ||
183 | const char *dwarf_decl_file_integrate (Dwarf_Die *die); | |
184 | #define dwarf_decl_file dwarf_decl_file_integrate | |
185 | ||
186 | int dwarf_decl_line_integrate (Dwarf_Die *die, int *linep) | |
187 | __nonnull_attribute__ (2); | |
188 | #define dwarf_decl_line dwarf_decl_line_integrate | |
189 | ||
190 | #endif // !_ELFUTILS_PREREQ(0, 143) | |
191 | ||
192 | ||
193 | // Resolve a C declaration for dwarf types | |
194 | bool dwarf_type_decl(Dwarf_Die *type_die, const std::string& var_name, std::string& decl); | |
195 | ||
196 | // Resolve a full name for dwarf types | |
197 | bool dwarf_type_name(Dwarf_Die *type_die, std::string& type_name); | |
198 | std::string dwarf_type_name(Dwarf_Die *type_die); | |
199 | ||
200 | ||
201 | #endif | |
202 | ||
203 | /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |