Initial implementation of the debuginfo API
[babeltrace.git] / lib / dwarf.c
1 /*
2 * dwarf.c
3 *
4 * Babeltrace - DWARF Information Reader
5 *
6 * Copyright 2015 Antoine Busque <abusque@efficios.com>
7 *
8 * Author: Antoine Busque <abusque@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #include <glib.h>
30 #include <babeltrace/dwarf.h>
31
32 BT_HIDDEN
33 struct bt_dwarf_cu *bt_dwarf_cu_create(Dwarf *dwarf_info)
34 {
35 struct bt_dwarf_cu *cu;
36
37 if (!dwarf_info) {
38 goto error;
39 }
40
41 cu = g_new0(struct bt_dwarf_cu, 1);
42 if (!cu) {
43 goto error;
44 }
45 cu->dwarf_info = dwarf_info;
46 return cu;
47
48 error:
49 return NULL;
50 }
51
52 BT_HIDDEN
53 void bt_dwarf_cu_destroy(struct bt_dwarf_cu *cu)
54 {
55 g_free(cu);
56 }
57
58 BT_HIDDEN
59 int bt_dwarf_cu_next(struct bt_dwarf_cu *cu)
60 {
61 int ret;
62 Dwarf_Off next_offset;
63 size_t cu_header_size;
64
65 if (!cu) {
66 ret = -1;
67 goto end;
68 }
69
70 ret = dwarf_nextcu(cu->dwarf_info, cu->next_offset, &next_offset,
71 &cu_header_size, NULL, NULL, NULL);
72 if (ret) {
73 /* ret is -1 on error, 1 if no next CU. */
74 goto end;
75 }
76
77 cu->offset = cu->next_offset;
78 cu->next_offset = next_offset;
79 cu->header_size = cu_header_size;
80
81 end:
82 return ret;
83 }
84
85 BT_HIDDEN
86 struct bt_dwarf_die *bt_dwarf_die_create(struct bt_dwarf_cu *cu)
87 {
88 Dwarf_Die *dwarf_die = NULL;
89 struct bt_dwarf_die *die = NULL;
90
91 if (!cu) {
92 goto error;
93 }
94
95 dwarf_die = g_new0(Dwarf_Die, 1);
96 if (!dwarf_die) {
97 goto error;
98 }
99
100 dwarf_die = dwarf_offdie(cu->dwarf_info, cu->offset + cu->header_size,
101 dwarf_die);
102 if (!dwarf_die) {
103 goto error;
104 }
105
106 die = g_new0(struct bt_dwarf_die, 1);
107 if (!die) {
108 goto error;
109 }
110
111 die->cu = cu;
112 die->dwarf_die = dwarf_die;
113 die->depth = 0;
114
115 return die;
116
117 error:
118 g_free(dwarf_die);
119 g_free(die);
120 return NULL;
121 }
122
123 BT_HIDDEN
124 void bt_dwarf_die_destroy(struct bt_dwarf_die *die)
125 {
126 if (!die) {
127 return;
128 }
129
130 g_free(die->dwarf_die);
131 g_free(die);
132 }
133
134 BT_HIDDEN
135 int bt_dwarf_die_child(struct bt_dwarf_die *die)
136 {
137 int ret;
138 Dwarf_Die *child_die = NULL;
139
140 if (!die) {
141 ret = -1;
142 goto error;
143 }
144
145 child_die = g_new0(Dwarf_Die, 1);
146 if (!child_die) {
147 ret = -1;
148 goto error;
149 }
150
151 ret = dwarf_child(die->dwarf_die, child_die);
152 if (ret) {
153 /* ret is -1 on error, 1 if no child DIE. */
154 goto error;
155 }
156
157 g_free(die->dwarf_die);
158 die->dwarf_die = child_die;
159 die->depth++;
160 return 0;
161
162 error:
163 g_free(child_die);
164 return ret;
165 }
166
167 BT_HIDDEN
168 int bt_dwarf_die_next(struct bt_dwarf_die *die)
169 {
170 int ret;
171 Dwarf_Die *next_die = NULL;
172
173 if (!die) {
174 ret = -1;
175 goto error;
176 }
177
178 next_die = g_new0(Dwarf_Die, 1);
179 if (!next_die) {
180 ret = -1;
181 goto error;
182 }
183
184 if (die->depth == 0) {
185 ret = dwarf_child(die->dwarf_die, next_die);
186 if (ret) {
187 /* ret is -1 on error, 1 if no child DIE. */
188 goto error;
189 }
190
191 die->depth = 1;
192 } else {
193 ret = dwarf_siblingof(die->dwarf_die, next_die);
194 if (ret) {
195 /* ret is -1 on error, 1 if we reached end of
196 * DIEs at this depth. */
197 goto error;
198 }
199 }
200
201 g_free(die->dwarf_die);
202 die->dwarf_die = next_die;
203 return 0;
204
205 error:
206 g_free(next_die);
207 return ret;
208 }
209
210 BT_HIDDEN
211 int bt_dwarf_die_get_tag(struct bt_dwarf_die *die, int *tag)
212 {
213 int _tag;
214
215 if (!die || !tag) {
216 goto error;
217 }
218
219 _tag = dwarf_tag(die->dwarf_die);
220 if (_tag == DW_TAG_invalid) {
221 goto error;
222 }
223
224 *tag = _tag;
225 return 0;
226
227 error:
228 return -1;
229 }
230
231 BT_HIDDEN
232 int bt_dwarf_die_get_name(struct bt_dwarf_die *die, char **name)
233 {
234 const char *_name;
235
236 if (!die || !name) {
237 goto error;
238 }
239
240 _name = dwarf_diename(die->dwarf_die);
241 if (!_name) {
242 goto error;
243 }
244
245 *name = strdup(_name);
246 if (!*name) {
247 goto error;
248 }
249
250 return 0;
251
252 error:
253 return -1;
254 }
255
256 BT_HIDDEN
257 int bt_dwarf_die_get_call_file(struct bt_dwarf_die *die, char **filename)
258 {
259 int ret;
260 Dwarf_Sword file_no;
261 const char *_filename = NULL;
262 Dwarf_Files *src_files = NULL;
263 Dwarf_Attribute *file_attr = NULL;
264 struct bt_dwarf_die *cu_die = NULL;
265
266 if (!die || !filename) {
267 goto error;
268 }
269
270 file_attr = g_new0(Dwarf_Attribute, 1);
271 if (!file_attr) {
272 goto error;
273 }
274
275 file_attr = dwarf_attr(die->dwarf_die, DW_AT_call_file, file_attr);
276 if (!file_attr) {
277 goto error;
278 }
279
280 ret = dwarf_formsdata(file_attr, &file_no);
281 if (ret) {
282 goto error;
283 }
284
285 cu_die = bt_dwarf_die_create(die->cu);
286 if (!cu_die) {
287 goto error;
288 }
289
290 ret = dwarf_getsrcfiles(cu_die->dwarf_die, &src_files, NULL);
291 if (ret) {
292 goto error;
293 }
294
295 _filename = dwarf_filesrc(src_files, file_no, NULL, NULL);
296 if (!_filename) {
297 goto error;
298 }
299
300 *filename = strdup(_filename);
301
302 bt_dwarf_die_destroy(cu_die);
303 g_free(file_attr);
304
305 return 0;
306
307 error:
308 bt_dwarf_die_destroy(cu_die);
309 g_free(file_attr);
310
311 return -1;
312 }
313
314 BT_HIDDEN
315 int bt_dwarf_die_get_call_line(struct bt_dwarf_die *die,
316 uint64_t *line_no)
317 {
318 int ret = 0;
319 Dwarf_Attribute *line_attr = NULL;
320 uint64_t _line_no;
321
322 if (!die || !line_no) {
323 goto error;
324 }
325
326 line_attr = g_new0(Dwarf_Attribute, 1);
327 if (!line_attr) {
328 goto error;
329 }
330
331 line_attr = dwarf_attr(die->dwarf_die, DW_AT_call_line, line_attr);
332 if (!line_attr) {
333 goto error;
334 }
335
336 ret = dwarf_formudata(line_attr, &_line_no);
337 if (ret) {
338 goto error;
339 }
340
341 *line_no = _line_no;
342 g_free(line_attr);
343
344 return 0;
345
346 error:
347 g_free(line_attr);
348
349 return -1;
350 }
351
352 BT_HIDDEN
353 int bt_dwarf_die_contains_addr(struct bt_dwarf_die *die, uint64_t addr,
354 int *contains)
355 {
356 int ret;
357
358 ret = dwarf_haspc(die->dwarf_die, addr);
359 if (ret == -1) {
360 goto error;
361 }
362
363 *contains = ret;
364
365 return 0;
366
367 error:
368 return -1;
369 }
This page took 0.040207 seconds and 5 git commands to generate.