]>
Commit | Line | Data |
---|---|---|
86bf665e | 1 | // -*- C++ -*- |
1e6e9ec1 | 2 | // Copyright (C) 2008-2011 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 | 19 | using namespace std; |
86bf665e TM |
20 | |
21 | void dwfl_assert(const string& desc, int rc) | |
22 | { | |
23 | if (rc == 0) | |
24 | return; | |
58a834b1 | 25 | string msg = _F("libdwfl failure (%s): ", desc.c_str()); |
86bf665e | 26 | if (rc < 0) |
316ac905 | 27 | msg += (dwfl_errmsg (rc) ?: "?"); |
86bf665e TM |
28 | else |
29 | msg += std::strerror (rc); | |
30 | throw semantic_error (msg); | |
31 | } | |
32 | ||
33 | void dwarf_assert(const string& desc, int rc) | |
34 | { | |
35 | if (rc == 0) | |
36 | return; | |
58a834b1 | 37 | string msg = _F("libdw failure (%s): ", desc.c_str()); |
86bf665e TM |
38 | if (rc < 0) |
39 | msg += dwarf_errmsg (rc); | |
40 | else | |
41 | msg += std::strerror (rc); | |
42 | throw semantic_error (msg); | |
43 | } | |
ba53ea9f | 44 | |
440f755a | 45 | |
7f17af5c JS |
46 | #if !_ELFUTILS_PREREQ(0, 143) |
47 | // Elfutils prior to 0.143 didn't use attr_integrate when looking up the | |
48 | // decl_file or decl_line, so the attributes would sometimes be missed. For | |
49 | // those old versions, we define custom implementations to do the integration. | |
50 | ||
51 | const char * | |
52 | dwarf_decl_file_integrate (Dwarf_Die *die) | |
53 | { | |
54 | Dwarf_Attribute attr_mem; | |
55 | Dwarf_Sword idx = 0; | |
56 | if (dwarf_formsdata (dwarf_attr_integrate (die, DW_AT_decl_file, &attr_mem), | |
57 | &idx) != 0 | |
58 | || idx == 0) | |
59 | return NULL; | |
60 | ||
61 | Dwarf_Die cudie; | |
62 | Dwarf_Files *files = NULL; | |
63 | if (dwarf_getsrcfiles (dwarf_diecu (die, &cudie, NULL, NULL), | |
64 | &files, NULL) != 0) | |
65 | return NULL; | |
66 | ||
67 | return dwarf_filesrc(files, idx, NULL, NULL); | |
68 | } | |
69 | ||
70 | int | |
71 | dwarf_decl_line_integrate (Dwarf_Die *die, int *linep) | |
72 | { | |
73 | Dwarf_Attribute attr_mem; | |
74 | Dwarf_Sword line; | |
75 | ||
76 | int res = dwarf_formsdata (dwarf_attr_integrate | |
77 | (die, DW_AT_decl_line, &attr_mem), | |
78 | &line); | |
79 | if (res == 0) | |
80 | *linep = line; | |
81 | ||
82 | return res; | |
83 | } | |
84 | ||
85 | #endif // !_ELFUTILS_PREREQ(0, 143) | |
86 | ||
87 | ||
f1c8f8a5 | 88 | static bool |
9c119951 | 89 | dwarf_type_name(Dwarf_Die *type_die, ostream& o) |
f1c8f8a5 JS |
90 | { |
91 | // if we've gotten down to a basic type, then we're done | |
92 | bool done = true; | |
93 | switch (dwarf_tag(type_die)) | |
94 | { | |
95 | case DW_TAG_enumeration_type: | |
96 | o << "enum "; | |
97 | break; | |
98 | case DW_TAG_structure_type: | |
99 | o << "struct "; | |
100 | break; | |
101 | case DW_TAG_union_type: | |
102 | o << "union "; | |
103 | break; | |
9c119951 JS |
104 | case DW_TAG_class_type: |
105 | o << "class "; | |
106 | break; | |
f1c8f8a5 JS |
107 | case DW_TAG_typedef: |
108 | case DW_TAG_base_type: | |
109 | break; | |
9c119951 JS |
110 | |
111 | // modifier types that require recursion first | |
112 | case DW_TAG_reference_type: | |
113 | case DW_TAG_rvalue_reference_type: | |
114 | case DW_TAG_pointer_type: | |
115 | case DW_TAG_array_type: | |
116 | case DW_TAG_const_type: | |
117 | case DW_TAG_volatile_type: | |
f1c8f8a5 JS |
118 | done = false; |
119 | break; | |
9c119951 JS |
120 | |
121 | // unknown tag | |
122 | default: | |
123 | return false; | |
f1c8f8a5 JS |
124 | } |
125 | if (done) | |
126 | { | |
127 | // this follows gdb precedent that anonymous structs/unions | |
128 | // are displayed as "struct {...}" and "union {...}". | |
129 | o << (dwarf_diename(type_die) ?: "{...}"); | |
130 | return true; | |
131 | } | |
132 | ||
133 | // otherwise, this die is a type modifier. | |
134 | ||
135 | // recurse into the referent type | |
9c119951 JS |
136 | Dwarf_Die subtype_die_mem, *subtype_die; |
137 | subtype_die = dwarf_attr_die(type_die, DW_AT_type, &subtype_die_mem); | |
138 | ||
139 | // NB: va_list is a builtin type that shows up in the debuginfo as a | |
140 | // "struct __va_list_tag*", but it has to be called only va_list. | |
141 | if (subtype_die != NULL && | |
142 | dwarf_tag(type_die) == DW_TAG_pointer_type && | |
143 | dwarf_tag(subtype_die) == DW_TAG_structure_type && | |
144 | strcmp(dwarf_diename(subtype_die) ?: "", "__va_list_tag") == 0) | |
145 | { | |
146 | o << "va_list"; | |
147 | return true; | |
148 | } | |
149 | ||
f1c8f8a5 | 150 | // if it can't be named, just call it "void" |
9c119951 JS |
151 | if (subtype_die == NULL || |
152 | !dwarf_type_name(subtype_die, o)) | |
153 | o << "void"; | |
f1c8f8a5 JS |
154 | |
155 | switch (dwarf_tag(type_die)) | |
156 | { | |
9c119951 JS |
157 | case DW_TAG_reference_type: |
158 | o << "&"; | |
159 | break; | |
160 | case DW_TAG_rvalue_reference_type: | |
161 | o << "&&"; | |
162 | break; | |
f1c8f8a5 JS |
163 | case DW_TAG_pointer_type: |
164 | o << "*"; | |
165 | break; | |
166 | case DW_TAG_array_type: | |
167 | o << "[]"; | |
168 | break; | |
169 | case DW_TAG_const_type: | |
9c119951 JS |
170 | // NB: the debuginfo may sometimes have an extra const tag |
171 | // on reference types, which is redundant to us. | |
172 | if (subtype_die == NULL || | |
173 | (dwarf_tag(subtype_die) != DW_TAG_reference_type && | |
174 | dwarf_tag(subtype_die) != DW_TAG_rvalue_reference_type)) | |
175 | o << " const"; | |
f1c8f8a5 JS |
176 | break; |
177 | case DW_TAG_volatile_type: | |
178 | o << " volatile"; | |
179 | break; | |
180 | default: | |
181 | return false; | |
182 | } | |
183 | ||
f1c8f8a5 JS |
184 | return true; |
185 | } | |
186 | ||
187 | ||
188 | bool | |
189 | dwarf_type_name(Dwarf_Die *type_die, string& type_name) | |
190 | { | |
191 | ostringstream o; | |
192 | bool ret = dwarf_type_name(type_die, o); | |
193 | type_name = o.str(); | |
194 | return ret; | |
195 | } | |
196 | ||
197 | ||
198 | string | |
199 | dwarf_type_name(Dwarf_Die *type_die) | |
200 | { | |
201 | ostringstream o; | |
202 | return dwarf_type_name(type_die, o) ? o.str() : "<unknown>"; | |
203 | } | |
204 | ||
205 | ||
73267b89 | 206 | /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |