Visibility hidden by default
[babeltrace.git] / src / plugins / lttng-utils / debug-info / dwarf.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2015 Antoine Busque <abusque@efficios.com>
5 *
6 * Babeltrace - DWARF Information Reader
7 */
8
9 #include <stdbool.h>
10
11 #include <glib.h>
12
13 #include "dwarf.h"
14
15 struct bt_dwarf_cu *bt_dwarf_cu_create(Dwarf *dwarf_info)
16 {
17 struct bt_dwarf_cu *cu;
18
19 if (!dwarf_info) {
20 goto error;
21 }
22
23 cu = g_new0(struct bt_dwarf_cu, 1);
24 if (!cu) {
25 goto error;
26 }
27 cu->dwarf_info = dwarf_info;
28 return cu;
29
30 error:
31 return NULL;
32 }
33
34 void bt_dwarf_cu_destroy(struct bt_dwarf_cu *cu)
35 {
36 g_free(cu);
37 }
38
39 int bt_dwarf_cu_next(struct bt_dwarf_cu *cu)
40 {
41 int ret;
42 Dwarf_Off next_offset;
43 size_t cu_header_size;
44
45 if (!cu) {
46 ret = -1;
47 goto end;
48 }
49
50 ret = dwarf_nextcu(cu->dwarf_info, cu->next_offset, &next_offset,
51 &cu_header_size, NULL, NULL, NULL);
52 if (ret) {
53 /* ret is -1 on error, 1 if no next CU. */
54 goto end;
55 }
56
57 cu->offset = cu->next_offset;
58 cu->next_offset = next_offset;
59 cu->header_size = cu_header_size;
60
61 end:
62 return ret;
63 }
64
65 struct bt_dwarf_die *bt_dwarf_die_create(struct bt_dwarf_cu *cu)
66 {
67 Dwarf_Die *dwarf_die = NULL;
68 struct bt_dwarf_die *die = NULL;
69
70 if (!cu) {
71 goto error;
72 }
73
74 dwarf_die = g_new0(Dwarf_Die, 1);
75 if (!dwarf_die) {
76 goto error;
77 }
78
79 dwarf_die = dwarf_offdie(cu->dwarf_info, cu->offset + cu->header_size,
80 dwarf_die);
81 if (!dwarf_die) {
82 goto error;
83 }
84
85 die = g_new0(struct bt_dwarf_die, 1);
86 if (!die) {
87 goto error;
88 }
89
90 die->cu = cu;
91 die->dwarf_die = dwarf_die;
92 die->depth = 0;
93
94 return die;
95
96 error:
97 g_free(dwarf_die);
98 g_free(die);
99 return NULL;
100 }
101
102 void bt_dwarf_die_destroy(struct bt_dwarf_die *die)
103 {
104 if (!die) {
105 return;
106 }
107
108 g_free(die->dwarf_die);
109 g_free(die);
110 }
111
112 int bt_dwarf_die_has_children(struct bt_dwarf_die *die)
113 {
114 return dwarf_haschildren(die->dwarf_die);
115 }
116
117 int bt_dwarf_die_child(struct bt_dwarf_die *die)
118 {
119 int ret;
120 Dwarf_Die *child_die = NULL;
121
122 if (!die) {
123 ret = -1;
124 goto error;
125 }
126
127 child_die = g_new0(Dwarf_Die, 1);
128 if (!child_die) {
129 ret = -1;
130 goto error;
131 }
132
133 ret = dwarf_child(die->dwarf_die, child_die);
134 if (ret) {
135 /* ret is -1 on error, 1 if no child DIE. */
136 goto error;
137 }
138
139 g_free(die->dwarf_die);
140 die->dwarf_die = child_die;
141 die->depth++;
142 return 0;
143
144 error:
145 g_free(child_die);
146 return ret;
147 }
148
149 int bt_dwarf_die_next(struct bt_dwarf_die *die)
150 {
151 int ret;
152 Dwarf_Die *next_die = NULL;
153
154 if (!die) {
155 ret = -1;
156 goto error;
157 }
158
159 next_die = g_new0(Dwarf_Die, 1);
160 if (!next_die) {
161 ret = -1;
162 goto error;
163 }
164
165 if (die->depth == 0) {
166 ret = dwarf_child(die->dwarf_die, next_die);
167 if (ret) {
168 /* ret is -1 on error, 1 if no child DIE. */
169 goto error;
170 }
171
172 die->depth = 1;
173 } else {
174 ret = dwarf_siblingof(die->dwarf_die, next_die);
175 if (ret) {
176 /* ret is -1 on error, 1 if we reached end of
177 * DIEs at this depth. */
178 goto error;
179 }
180 }
181
182 g_free(die->dwarf_die);
183 die->dwarf_die = next_die;
184 return 0;
185
186 error:
187 g_free(next_die);
188 return ret;
189 }
190
191 int bt_dwarf_die_get_tag(struct bt_dwarf_die *die, int *tag)
192 {
193 int _tag;
194
195 if (!die || !tag) {
196 goto error;
197 }
198
199 _tag = dwarf_tag(die->dwarf_die);
200 if (_tag == DW_TAG_invalid) {
201 goto error;
202 }
203
204 *tag = _tag;
205 return 0;
206
207 error:
208 return -1;
209 }
210
211 int bt_dwarf_die_get_name(struct bt_dwarf_die *die, char **name)
212 {
213 const char *_name;
214
215 if (!die || !name) {
216 goto error;
217 }
218
219 _name = dwarf_diename(die->dwarf_die);
220 if (!_name) {
221 goto error;
222 }
223
224 *name = g_strdup(_name);
225 if (!*name) {
226 goto error;
227 }
228
229 return 0;
230
231 error:
232 return -1;
233 }
234
235 int bt_dwarf_die_get_call_file(struct bt_dwarf_die *die, char **filename)
236 {
237 int ret;
238 Dwarf_Sword file_no;
239 const char *_filename = NULL;
240 Dwarf_Files *src_files = NULL;
241 Dwarf_Attribute *file_attr = NULL;
242 struct bt_dwarf_die *cu_die = NULL;
243
244 if (!die || !filename) {
245 goto error;
246 }
247
248 file_attr = g_new0(Dwarf_Attribute, 1);
249 if (!file_attr) {
250 goto error;
251 }
252
253 file_attr = dwarf_attr(die->dwarf_die, DW_AT_call_file, file_attr);
254 if (!file_attr) {
255 goto error;
256 }
257
258 ret = dwarf_formsdata(file_attr, &file_no);
259 if (ret) {
260 goto error;
261 }
262
263 cu_die = bt_dwarf_die_create(die->cu);
264 if (!cu_die) {
265 goto error;
266 }
267
268 ret = dwarf_getsrcfiles(cu_die->dwarf_die, &src_files, NULL);
269 if (ret) {
270 goto error;
271 }
272
273 _filename = dwarf_filesrc(src_files, file_no, NULL, NULL);
274 if (!_filename) {
275 goto error;
276 }
277
278 *filename = g_strdup(_filename);
279
280 bt_dwarf_die_destroy(cu_die);
281 g_free(file_attr);
282
283 return 0;
284
285 error:
286 bt_dwarf_die_destroy(cu_die);
287 g_free(file_attr);
288
289 return -1;
290 }
291
292 int bt_dwarf_die_get_call_line(struct bt_dwarf_die *die,
293 uint64_t *line_no)
294 {
295 int ret = 0;
296 Dwarf_Attribute *line_attr = NULL;
297 uint64_t _line_no;
298
299 if (!die || !line_no) {
300 goto error;
301 }
302
303 line_attr = g_new0(Dwarf_Attribute, 1);
304 if (!line_attr) {
305 goto error;
306 }
307
308 line_attr = dwarf_attr(die->dwarf_die, DW_AT_call_line, line_attr);
309 if (!line_attr) {
310 goto error;
311 }
312
313 ret = dwarf_formudata(line_attr, &_line_no);
314 if (ret) {
315 goto error;
316 }
317
318 *line_no = _line_no;
319 g_free(line_attr);
320
321 return 0;
322
323 error:
324 g_free(line_attr);
325
326 return -1;
327 }
328
329 int bt_dwarf_die_contains_addr(struct bt_dwarf_die *die, uint64_t addr,
330 bool *contains)
331 {
332 int ret;
333
334 ret = dwarf_haspc(die->dwarf_die, addr);
335 if (ret == -1) {
336 goto error;
337 }
338
339 *contains = (ret == 1);
340
341 return 0;
342
343 error:
344 return -1;
345 }
This page took 0.037092 seconds and 4 git commands to generate.