Branch data Line data Source code
1 : : // -*- C++ -*-
2 : : // Copyright (C) 2008-2011 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 : : #include "dwarf_wrappers.h"
10 : : #include "staptree.h"
11 : : #include "util.h"
12 : :
13 : : #include <cstring>
14 : : #include <sstream>
15 : : #include <string>
16 : : #include <elfutils/libdwfl.h>
17 : : #include <dwarf.h>
18 : :
19 : : using namespace std;
20 : :
21 : 378484 : void dwfl_assert(const string& desc, int rc)
22 : : {
23 [ - + ]: 378484 : if (rc == 0)
24 : 378484 : return;
25 [ # # ][ # # ]: 0 : string msg = _F("libdwfl failure (%s): ", desc.c_str());
26 [ # # ]: 0 : if (rc < 0)
27 [ # # ][ # # ]: 0 : msg += (dwfl_errmsg (rc) ?: "?");
[ # # ]
28 : : else
29 [ # # ]: 0 : msg += std::strerror (rc);
30 [ # # ]: 378484 : throw semantic_error (msg);
31 : : }
32 : :
33 : 121956 : void dwarf_assert(const string& desc, int rc)
34 : : {
35 [ - + ]: 121956 : if (rc == 0)
36 : 121956 : return;
37 [ # # ][ # # ]: 0 : string msg = _F("libdw failure (%s): ", desc.c_str());
38 [ # # ]: 0 : if (rc < 0)
39 [ # # ][ # # ]: 0 : msg += dwarf_errmsg (rc);
40 : : else
41 [ # # ]: 0 : msg += std::strerror (rc);
42 [ # # ]: 121956 : throw semantic_error (msg);
43 : : }
44 : :
45 : :
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 : :
88 : : static bool
89 : 67778 : dwarf_type_name(Dwarf_Die *type_die, ostream& o)
90 : : {
91 : : // if we've gotten down to a basic type, then we're done
92 : 67778 : bool done = true;
93 [ + - ][ + + : 67778 : switch (dwarf_tag(type_die))
+ + + +
+ ]
94 : : {
95 : : case DW_TAG_enumeration_type:
96 [ + - ]: 154 : o << "enum ";
97 : 154 : break;
98 : : case DW_TAG_structure_type:
99 [ + - ]: 12885 : o << "struct ";
100 : 12885 : break;
101 : : case DW_TAG_union_type:
102 [ + - ]: 32 : o << "union ";
103 : 32 : break;
104 : : case DW_TAG_class_type:
105 [ + - ]: 7031 : o << "class ";
106 : 7031 : break;
107 : : case DW_TAG_typedef:
108 : : case DW_TAG_base_type:
109 : 7865 : break;
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:
118 : 39774 : done = false;
119 : 39774 : break;
120 : :
121 : : // unknown tag
122 : : default:
123 : 37 : return false;
124 : : }
125 [ + + ]: 67741 : if (done)
126 : : {
127 : : // this follows gdb precedent that anonymous structs/unions
128 : : // are displayed as "struct {...}" and "union {...}".
129 [ + - ][ + + ]: 27967 : o << (dwarf_diename(type_die) ?: "{...}");
[ + - ]
130 : 27967 : return true;
131 : : }
132 : :
133 : : // otherwise, this die is a type modifier.
134 : :
135 : : // recurse into the referent type
136 : : Dwarf_Die subtype_die_mem, *subtype_die;
137 [ + - ]: 39774 : 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 [ + + ][ + + ]: 105175 : if (subtype_die != NULL &&
[ + + ][ - + ]
[ - + ]
142 [ + - ]: 39609 : dwarf_tag(type_die) == DW_TAG_pointer_type &&
143 [ + - ]: 17836 : dwarf_tag(subtype_die) == DW_TAG_structure_type &&
144 [ + - ][ + - ]: 7956 : strcmp(dwarf_diename(subtype_die) ?: "", "__va_list_tag") == 0)
145 : : {
146 [ # # ]: 0 : o << "va_list";
147 : 0 : return true;
148 : : }
149 : :
150 : : // if it can't be named, just call it "void"
151 [ + + ][ + + ]: 79383 : if (subtype_die == NULL ||
[ + + ]
152 [ + - ]: 39609 : !dwarf_type_name(subtype_die, o))
153 [ + - ]: 202 : o << "void";
154 : :
155 [ + - ][ + - : 39774 : switch (dwarf_tag(type_die))
+ + + +
- ]
156 : : {
157 : : case DW_TAG_reference_type:
158 [ + - ]: 3801 : o << "&";
159 : 3801 : break;
160 : : case DW_TAG_rvalue_reference_type:
161 [ # # ]: 0 : o << "&&";
162 : 0 : break;
163 : : case DW_TAG_pointer_type:
164 [ + - ]: 17930 : o << "*";
165 : 17930 : break;
166 : : case DW_TAG_array_type:
167 [ + - ]: 15 : o << "[]";
168 : 15 : break;
169 : : case DW_TAG_const_type:
170 : : // NB: the debuginfo may sometimes have an extra const tag
171 : : // on reference types, which is redundant to us.
172 [ + + ][ + + ]: 50111 : if (subtype_die == NULL ||
[ + - ][ + + ]
173 [ + - ]: 17947 : (dwarf_tag(subtype_die) != DW_TAG_reference_type &&
174 [ + - ]: 14146 : dwarf_tag(subtype_die) != DW_TAG_rvalue_reference_type))
175 [ + - ]: 14217 : o << " const";
176 : 18018 : break;
177 : : case DW_TAG_volatile_type:
178 [ + - ]: 10 : o << " volatile";
179 : 10 : break;
180 : : default:
181 : 0 : return false;
182 : : }
183 : :
184 : 67778 : return true;
185 : : }
186 : :
187 : :
188 : : bool
189 : 25257 : dwarf_type_name(Dwarf_Die *type_die, string& type_name)
190 : : {
191 [ + - ]: 25257 : ostringstream o;
192 [ + - ]: 25257 : bool ret = dwarf_type_name(type_die, o);
193 [ + - ][ + - ]: 25257 : type_name = o.str();
[ + - ]
194 [ + - ]: 25257 : return ret;
195 : : }
196 : :
197 : :
198 : : string
199 : 2912 : dwarf_type_name(Dwarf_Die *type_die)
200 : : {
201 [ + - ]: 2912 : ostringstream o;
202 [ + - ][ + - ]: 2912 : return dwarf_type_name(type_die, o) ? o.str() : "<unknown>";
[ + - ][ # # ]
[ - + ][ + - ]
[ # # ]
203 [ + - ][ + - ]: 7242 : }
204 : :
205 : :
206 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|