]> sourceware.org Git - systemtap.git/blame - dwarf_wrappers.cxx
PR23285 (1): enable procfs probes for stapbpf
[systemtap.git] / dwarf_wrappers.cxx
CommitLineData
86bf665e 1// -*- C++ -*-
ef36f781 2// Copyright (C) 2008-2014 Red Hat Inc.
86bf665e
TM
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#include "dwarf_wrappers.h"
10#include "staptree.h"
58a834b1 11#include "util.h"
86bf665e
TM
12
13#include <cstring>
f1c8f8a5 14#include <sstream>
86bf665e
TM
15#include <string>
16#include <elfutils/libdwfl.h>
440f755a 17#include <dwarf.h>
86bf665e 18
f1c8f8a5 19using namespace std;
86bf665e 20
e1c3b13a
JL
21void dwfl_assert(const string& desc, int rc,
22 const string& file, int line)
86bf665e
TM
23{
24 if (rc == 0)
25 return;
58a834b1 26 string msg = _F("libdwfl failure (%s): ", desc.c_str());
86bf665e 27 if (rc < 0)
316ac905 28 msg += (dwfl_errmsg (rc) ?: "?");
86bf665e
TM
29 else
30 msg += std::strerror (rc);
e1c3b13a 31 throw semantic_error (file+":"+lex_cast(line), msg);
86bf665e
TM
32}
33
e1c3b13a
JL
34void dwarf_assert(const string& desc, int rc,
35 const string& file, int line)
86bf665e
TM
36{
37 if (rc == 0)
38 return;
58a834b1 39 string msg = _F("libdw failure (%s): ", desc.c_str());
86bf665e
TM
40 if (rc < 0)
41 msg += dwarf_errmsg (rc);
42 else
43 msg += std::strerror (rc);
e1c3b13a 44 throw semantic_error (file+":"+lex_cast(line), msg);
86bf665e 45}
ba53ea9f 46
440f755a 47
7f17af5c
JS
48#if !_ELFUTILS_PREREQ(0, 143)
49// Elfutils prior to 0.143 didn't use attr_integrate when looking up the
50// decl_file or decl_line, so the attributes would sometimes be missed. For
51// those old versions, we define custom implementations to do the integration.
52
53const char *
54dwarf_decl_file_integrate (Dwarf_Die *die)
55{
56 Dwarf_Attribute attr_mem;
57 Dwarf_Sword idx = 0;
58 if (dwarf_formsdata (dwarf_attr_integrate (die, DW_AT_decl_file, &attr_mem),
59 &idx) != 0
60 || idx == 0)
61 return NULL;
62
63 Dwarf_Die cudie;
64 Dwarf_Files *files = NULL;
65 if (dwarf_getsrcfiles (dwarf_diecu (die, &cudie, NULL, NULL),
66 &files, NULL) != 0)
67 return NULL;
68
69 return dwarf_filesrc(files, idx, NULL, NULL);
70}
71
72int
73dwarf_decl_line_integrate (Dwarf_Die *die, int *linep)
74{
75 Dwarf_Attribute attr_mem;
76 Dwarf_Sword line;
77
78 int res = dwarf_formsdata (dwarf_attr_integrate
79 (die, DW_AT_decl_line, &attr_mem),
80 &line);
81 if (res == 0)
82 *linep = line;
83
84 return res;
85}
86
87#endif // !_ELFUTILS_PREREQ(0, 143)
88
89
f1c8f8a5 90static bool
b6e49c97 91dwarf_type_name(Dwarf_Die *type_die, ostream& o, Dwarf_Die& subroutine)
f1c8f8a5
JS
92{
93 // if we've gotten down to a basic type, then we're done
94 bool done = true;
95 switch (dwarf_tag(type_die))
96 {
97 case DW_TAG_enumeration_type:
98 o << "enum ";
99 break;
100 case DW_TAG_structure_type:
101 o << "struct ";
102 break;
103 case DW_TAG_union_type:
104 o << "union ";
105 break;
9c119951
JS
106 case DW_TAG_class_type:
107 o << "class ";
108 break;
f1c8f8a5
JS
109 case DW_TAG_typedef:
110 case DW_TAG_base_type:
111 break;
9c119951
JS
112
113 // modifier types that require recursion first
114 case DW_TAG_reference_type:
115 case DW_TAG_rvalue_reference_type:
116 case DW_TAG_pointer_type:
117 case DW_TAG_array_type:
118 case DW_TAG_const_type:
119 case DW_TAG_volatile_type:
c69af88f 120 case DW_TAG_restrict_type:
f1c8f8a5
JS
121 done = false;
122 break;
9c119951 123
b6e49c97
JS
124 case DW_TAG_subroutine_type:
125 // Subroutine types (function pointers) are a weird case. The modifiers
126 // we've recursed so far need to go in the middle, with the return type
127 // on the left and parameter types on the right. We'll back out now to
128 // get those modifiers, getting the return and parameters separately.
129 subroutine = *type_die;
130 return true;
131
9c119951
JS
132 // unknown tag
133 default:
134 return false;
f1c8f8a5
JS
135 }
136 if (done)
137 {
138 // this follows gdb precedent that anonymous structs/unions
139 // are displayed as "struct {...}" and "union {...}".
140 o << (dwarf_diename(type_die) ?: "{...}");
141 return true;
142 }
143
144 // otherwise, this die is a type modifier.
145
146 // recurse into the referent type
9c119951
JS
147 Dwarf_Die subtype_die_mem, *subtype_die;
148 subtype_die = dwarf_attr_die(type_die, DW_AT_type, &subtype_die_mem);
149
150 // NB: va_list is a builtin type that shows up in the debuginfo as a
151 // "struct __va_list_tag*", but it has to be called only va_list.
152 if (subtype_die != NULL &&
153 dwarf_tag(type_die) == DW_TAG_pointer_type &&
154 dwarf_tag(subtype_die) == DW_TAG_structure_type &&
155 strcmp(dwarf_diename(subtype_die) ?: "", "__va_list_tag") == 0)
156 {
157 o << "va_list";
158 return true;
159 }
160
f1c8f8a5 161 // if it can't be named, just call it "void"
9c119951 162 if (subtype_die == NULL ||
b6e49c97 163 !dwarf_type_name(subtype_die, o, subroutine))
9c119951 164 o << "void";
f1c8f8a5
JS
165
166 switch (dwarf_tag(type_die))
167 {
9c119951
JS
168 case DW_TAG_reference_type:
169 o << "&";
170 break;
171 case DW_TAG_rvalue_reference_type:
172 o << "&&";
173 break;
f1c8f8a5
JS
174 case DW_TAG_pointer_type:
175 o << "*";
176 break;
177 case DW_TAG_array_type:
178 o << "[]";
179 break;
180 case DW_TAG_const_type:
9c119951
JS
181 // NB: the debuginfo may sometimes have an extra const tag
182 // on reference types, which is redundant to us.
183 if (subtype_die == NULL ||
184 (dwarf_tag(subtype_die) != DW_TAG_reference_type &&
185 dwarf_tag(subtype_die) != DW_TAG_rvalue_reference_type))
186 o << " const";
f1c8f8a5
JS
187 break;
188 case DW_TAG_volatile_type:
189 o << " volatile";
190 break;
c69af88f
MW
191 case DW_TAG_restrict_type:
192 o << " restrict";
193 break;
f1c8f8a5
JS
194 default:
195 return false;
196 }
197
f1c8f8a5
JS
198 return true;
199}
200
201
b6e49c97
JS
202static bool
203dwarf_subroutine_name(Dwarf_Die *subroutine, ostream& o, const string& modifier)
204{
205 // First add the return value.
206 Dwarf_Die ret_type;
207 string ret_string;
208 if (dwarf_attr_die (subroutine, DW_AT_type, &ret_type) == NULL)
209 o << "void";
210 else if (dwarf_type_name (&ret_type, ret_string))
211 o << ret_string;
212 else
213 return false;
214
215 // Now the subroutine modifiers.
216 o << " (" << modifier << ")";
217
218 // Then write each parameter.
219 o << " (";
220 bool first = true;
221 Dwarf_Die child;
222 if (dwarf_child (subroutine, &child) == 0)
223 do
224 {
225 auto tag = dwarf_tag (&child);
226 if (tag == DW_TAG_unspecified_parameters
227 || tag == DW_TAG_formal_parameter)
228 {
229 if (first)
230 first = false;
231 else
232 o << ", ";
233
234 if (tag == DW_TAG_unspecified_parameters)
235 o << "...";
236 else if (tag == DW_TAG_formal_parameter)
237 {
238 Dwarf_Die param_type;
239 string param_string;
240 if (dwarf_attr_die (&child, DW_AT_type, &param_type) == NULL)
241 o << "void";
242 else if (dwarf_type_name (&param_type, param_string))
243 o << param_string;
244 else
245 return false;
246 }
247 }
248 }
249 while (dwarf_siblingof (&child, &child) == 0);
250 if (first)
251 o << "void";
252 o << ")";
253
254 return true;
255}
256
257
258bool
259dwarf_type_decl(Dwarf_Die *type_die, const string& var_name, string& decl)
260{
261 ostringstream o;
262 Dwarf_Die subroutine = { 0, 0, 0, 0 };
263 if (!dwarf_type_name (type_die, o, subroutine))
264 return false;
265
266 if (!var_name.empty())
267 o << " " << var_name;
268
269 if (subroutine.addr != 0)
270 {
271 ostringstream subo;
272 if (!dwarf_subroutine_name (&subroutine, subo, o.str()))
273 return false;
274 decl = subo.str();
275 }
276 else
277 decl = o.str();
278
279 return true;
280}
281
282
f1c8f8a5
JS
283bool
284dwarf_type_name(Dwarf_Die *type_die, string& type_name)
285{
b6e49c97 286 return dwarf_type_decl(type_die, "", type_name);
f1c8f8a5
JS
287}
288
289
290string
291dwarf_type_name(Dwarf_Die *type_die)
292{
b6e49c97
JS
293 string o;
294 return dwarf_type_name (type_die, o) ? o : "<unknown>";
f1c8f8a5
JS
295}
296
297
73267b89 298/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.15096 seconds and 5 git commands to generate.