]> sourceware.org Git - systemtap.git/blame - dwarf_wrappers.cxx
PR13513: undo PR11759 PREEMPT_RT hack
[systemtap.git] / dwarf_wrappers.cxx
CommitLineData
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 19using namespace std;
86bf665e
TM
20
21void 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
33void 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
51const char *
52dwarf_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
70int
71dwarf_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 88static bool
9c119951 89dwarf_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
188bool
189dwarf_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
198string
199dwarf_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 : */
This page took 0.07398 seconds and 5 git commands to generate.