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