Commit | Line | Data |
---|---|---|
c40a57e5 | 1 | /* |
0235b0db | 2 | * SPDX-License-Identifier: MIT |
c40a57e5 AB |
3 | * |
4 | * Copyright 2015 Antoine Busque <abusque@efficios.com> | |
5 | * | |
0235b0db | 6 | * Babeltrace - DWARF Information Reader |
c40a57e5 AB |
7 | */ |
8 | ||
c4f23e30 FD |
9 | #include <stdbool.h> |
10 | ||
c40a57e5 | 11 | #include <glib.h> |
c4f23e30 | 12 | |
4f45f9bb | 13 | #include "dwarf.h" |
c40a57e5 | 14 | |
c40a57e5 AB |
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 | ||
c40a57e5 AB |
34 | void bt_dwarf_cu_destroy(struct bt_dwarf_cu *cu) |
35 | { | |
36 | g_free(cu); | |
37 | } | |
38 | ||
c40a57e5 AB |
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, | |
cbb6e805 | 51 | &cu_header_size, NULL, NULL, NULL); |
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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, | |
cbb6e805 | 80 | dwarf_die); |
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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 | ||
e6365242 FD |
112 | int bt_dwarf_die_has_children(struct bt_dwarf_die *die) |
113 | { | |
114 | return dwarf_haschildren(die->dwarf_die); | |
115 | } | |
116 | ||
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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 | ||
06d1cf5d | 224 | *name = g_strdup(_name); |
c40a57e5 AB |
225 | if (!*name) { |
226 | goto error; | |
227 | } | |
228 | ||
229 | return 0; | |
230 | ||
231 | error: | |
232 | return -1; | |
233 | } | |
234 | ||
c40a57e5 AB |
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 | ||
06d1cf5d | 278 | *filename = g_strdup(_filename); |
c40a57e5 AB |
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 | ||
c40a57e5 AB |
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 | ||
c40a57e5 | 329 | int bt_dwarf_die_contains_addr(struct bt_dwarf_die *die, uint64_t addr, |
a54aa699 | 330 | bool *contains) |
c40a57e5 AB |
331 | { |
332 | int ret; | |
333 | ||
334 | ret = dwarf_haspc(die->dwarf_die, addr); | |
335 | if (ret == -1) { | |
336 | goto error; | |
337 | } | |
338 | ||
a54aa699 | 339 | *contains = (ret == 1); |
c40a57e5 AB |
340 | |
341 | return 0; | |
342 | ||
343 | error: | |
344 | return -1; | |
345 | } |