Branch data Line data Source code
1 : : /* Get macro information.
2 : : Copyright (C) 2002-2009, 2014, 2017, 2018 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include <assert.h>
34 : : #include <dwarf.h>
35 : : #include <search.h>
36 : : #include <stdlib.h>
37 : : #include <string.h>
38 : :
39 : : #include <libdwP.h>
40 : :
41 : : static int
42 : 1070 : get_offset_from (Dwarf_Die *die, int name, Dwarf_Word *retp)
43 : : {
44 : : /* Get the appropriate attribute. */
45 : 1070 : Dwarf_Attribute attr;
46 [ + - ]: 1070 : if (INTUSE(dwarf_attr) (die, name, &attr) == NULL)
47 : : return -1;
48 : :
49 : : /* Offset into the corresponding section. */
50 : 1070 : return INTUSE(dwarf_formudata) (&attr, retp);
51 : : }
52 : :
53 : : static int
54 : 2270 : macro_op_compare (const void *p1, const void *p2)
55 : : {
56 : 2270 : const Dwarf_Macro_Op_Table *t1 = (const Dwarf_Macro_Op_Table *) p1;
57 : 2270 : const Dwarf_Macro_Op_Table *t2 = (const Dwarf_Macro_Op_Table *) p2;
58 : :
59 [ + + ]: 2270 : if (t1->offset < t2->offset)
60 : : return -1;
61 [ + + ]: 2190 : if (t1->offset > t2->offset)
62 : : return 1;
63 : :
64 [ + - ]: 1394 : if (t1->sec_index < t2->sec_index)
65 : : return -1;
66 [ - + ]: 1394 : if (t1->sec_index > t2->sec_index)
67 : 0 : return 1;
68 : :
69 : : return 0;
70 : : }
71 : :
72 : : static void
73 : 34 : build_table (Dwarf_Macro_Op_Table *table,
74 : : Dwarf_Macro_Op_Proto op_protos[static 255])
75 : : {
76 : 34 : unsigned ct = 0;
77 [ + + ]: 8704 : for (unsigned i = 1; i < 256; ++i)
78 [ + + ]: 8670 : if (op_protos[i - 1].forms != NULL)
79 : 342 : table->table[table->opcodes[i - 1] = ct++] = op_protos[i - 1];
80 : : else
81 : 8328 : table->opcodes[i - 1] = 0xff;
82 : 34 : }
83 : :
84 : : #define MACRO_PROTO(NAME, ...) \
85 : : Dwarf_Macro_Op_Proto NAME = ({ \
86 : : static const uint8_t proto[] = {__VA_ARGS__}; \
87 : : (Dwarf_Macro_Op_Proto) {sizeof proto, proto}; \
88 : : })
89 : :
90 : : enum { macinfo_data_size = offsetof (Dwarf_Macro_Op_Table, table[5]) };
91 : : static unsigned char macinfo_data[macinfo_data_size]
92 : : __attribute__ ((aligned (__alignof (Dwarf_Macro_Op_Table))));
93 : :
94 : : static __attribute__ ((constructor)) void
95 : 10 : init_macinfo_table (void)
96 : : {
97 : 10 : MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
98 : 10 : MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
99 : 10 : MACRO_PROTO (p_none);
100 : :
101 : 10 : Dwarf_Macro_Op_Proto op_protos[255] =
102 : : {
103 : : [DW_MACINFO_define - 1] = p_udata_str,
104 : : [DW_MACINFO_undef - 1] = p_udata_str,
105 : : [DW_MACINFO_vendor_ext - 1] = p_udata_str,
106 : : [DW_MACINFO_start_file - 1] = p_udata_udata,
107 : : [DW_MACINFO_end_file - 1] = p_none,
108 : : /* If you are adding more elements to this array, increase
109 : : MACINFO_DATA_SIZE above. */
110 : : };
111 : :
112 : 10 : Dwarf_Macro_Op_Table *macinfo_table = (void *) macinfo_data;
113 : 10 : memset (macinfo_table, 0, sizeof macinfo_data);
114 : 10 : build_table (macinfo_table, op_protos);
115 : 10 : macinfo_table->sec_index = IDX_debug_macinfo;
116 : 10 : }
117 : :
118 : : static Dwarf_Macro_Op_Table *
119 : 4 : get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die *cudie)
120 : : {
121 [ - + ]: 4 : assert (cudie != NULL);
122 : :
123 : 4 : Dwarf_Attribute attr_mem, *attr
124 : 4 : = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
125 : 4 : Dwarf_Off line_offset = (Dwarf_Off) -1;
126 [ + - ]: 4 : if (attr != NULL)
127 [ + - ]: 4 : if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
128 : : return NULL;
129 : :
130 [ - + ]: 4 : Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
131 : : macinfo_data_size, 1);
132 : 4 : memcpy (table, macinfo_data, macinfo_data_size);
133 : :
134 : 4 : table->offset = macoff;
135 : 4 : table->sec_index = IDX_debug_macinfo;
136 : 4 : table->line_offset = line_offset;
137 : 4 : table->address_size = cudie->cu->address_size;
138 : 4 : table->offset_size = cudie->cu->offset_size;
139 : 4 : table->comp_dir = __libdw_getcompdir (cudie);
140 : :
141 : 4 : return table;
142 : : }
143 : :
144 : : static Dwarf_Macro_Op_Table *
145 : 24 : get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
146 : : const unsigned char *readp,
147 : : const unsigned char *const endp,
148 : : Dwarf_Die *cudie)
149 : : {
150 : 24 : const unsigned char *startp = readp;
151 : :
152 : : /* Request at least 3 bytes for header. */
153 [ - + ]: 24 : if (readp + 3 > endp)
154 : : {
155 : 0 : invalid_dwarf:
156 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
157 : 0 : return NULL;
158 : : }
159 : :
160 [ - + ]: 24 : uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
161 [ - + ]: 24 : if (version != 4 && version != 5)
162 : : {
163 : 0 : __libdw_seterrno (DWARF_E_INVALID_VERSION);
164 : 0 : return NULL;
165 : : }
166 : :
167 : 24 : uint8_t flags = *readp++;
168 : 24 : bool is_64bit = (flags & 0x1) != 0;
169 : :
170 : 24 : Dwarf_Off line_offset = (Dwarf_Off) -1;
171 [ + + ]: 24 : if ((flags & 0x2) != 0)
172 : : {
173 [ + - - + : 6 : line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
- - ]
174 [ - + ]: 6 : if (readp > endp)
175 : 0 : goto invalid_dwarf;
176 : : }
177 [ - + ]: 18 : else if (cudie != NULL)
178 : : {
179 : 0 : Dwarf_Attribute attr_mem, *attr
180 : 0 : = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
181 [ # # ]: 0 : if (attr != NULL)
182 [ # # ]: 0 : if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
183 : 0 : return NULL;
184 : : }
185 : :
186 : 6 : uint8_t address_size;
187 [ + - ]: 6 : if (cudie != NULL)
188 : 6 : address_size = cudie->cu->address_size;
189 : : else
190 : : {
191 : 18 : char *ident = elf_getident (dbg->elf, NULL);
192 [ + - ]: 18 : address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
193 : : }
194 : :
195 : : /* """The macinfo entry types defined in this standard may, but
196 : : might not, be described in the table""".
197 : :
198 : : I.e. these may be present. It's tempting to simply skip them,
199 : : but it's probably more correct to tolerate that a producer tweaks
200 : : the way certain opcodes are encoded, for whatever reasons. */
201 : :
202 : 24 : MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
203 : 24 : MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
204 : 24 : MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup);
205 : 24 : MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx);
206 : 24 : MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
207 : 24 : MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
208 : 24 : MACRO_PROTO (p_none);
209 : :
210 : 24 : Dwarf_Macro_Op_Proto op_protos[255] =
211 : : {
212 : : [DW_MACRO_define - 1] = p_udata_str,
213 : : [DW_MACRO_undef - 1] = p_udata_str,
214 : : [DW_MACRO_define_strp - 1] = p_udata_strp,
215 : : [DW_MACRO_undef_strp - 1] = p_udata_strp,
216 : : [DW_MACRO_start_file - 1] = p_udata_udata,
217 : : [DW_MACRO_end_file - 1] = p_none,
218 : : [DW_MACRO_import - 1] = p_secoffset,
219 : : [DW_MACRO_define_sup - 1] = p_udata_strsup,
220 : : [DW_MACRO_undef_sup - 1] = p_udata_strsup,
221 : : [DW_MACRO_import_sup - 1] = p_secoffset, /* XXX - but in sup!. */
222 : : [DW_MACRO_define_strx - 1] = p_udata_strx,
223 : : [DW_MACRO_undef_strx - 1] = p_udata_strx,
224 : : };
225 : :
226 [ + + ]: 24 : if ((flags & 0x4) != 0)
227 : : {
228 : 4 : unsigned count = *readp++;
229 [ + + ]: 8 : for (unsigned i = 0; i < count; ++i)
230 : : {
231 : 4 : unsigned opcode = *readp++;
232 : :
233 : 4 : Dwarf_Macro_Op_Proto e;
234 [ - + ]: 4 : if (readp >= endp)
235 : 0 : goto invalid;
236 : 4 : get_uleb128 (e.nforms, readp, endp);
237 : 4 : e.forms = readp;
238 : 4 : op_protos[opcode - 1] = e;
239 : :
240 : 4 : readp += e.nforms;
241 [ - + ]: 4 : if (readp > endp)
242 : : {
243 : 0 : invalid:
244 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
245 : 0 : return NULL;
246 : : }
247 : : }
248 : : }
249 : :
250 : 24 : size_t ct = 0;
251 [ + + ]: 6144 : for (unsigned i = 1; i < 256; ++i)
252 [ + + ]: 6120 : if (op_protos[i - 1].forms != NULL)
253 : 292 : ++ct;
254 : :
255 : : /* We support at most 0xfe opcodes defined in the table, as 0xff is
256 : : a value that means that given opcode is not stored at all. But
257 : : that should be fine, as opcode 0 is not allocated. */
258 [ - + ]: 24 : assert (ct < 0xff);
259 : :
260 : 24 : size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
261 : :
262 [ + + ]: 24 : Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
263 : : macop_table_size, 1);
264 : :
265 : 72 : *table = (Dwarf_Macro_Op_Table) {
266 : : .offset = macoff,
267 : : .sec_index = IDX_debug_macro,
268 : : .line_offset = line_offset,
269 [ + - ]: 24 : .header_len = readp - startp,
270 : : .version = version,
271 : : .address_size = address_size,
272 : : .offset_size = is_64bit ? 8 : 4,
273 : :
274 : : /* NULL if CUDIE is NULL or DW_AT_comp_dir is absent. */
275 : 24 : .comp_dir = __libdw_getcompdir (cudie),
276 : : };
277 : 24 : build_table (table, op_protos);
278 : :
279 : 24 : return table;
280 : : }
281 : :
282 : : static Dwarf_Macro_Op_Table *
283 : 1422 : cache_op_table (Dwarf *dbg, int sec_index, Dwarf_Off macoff,
284 : : const unsigned char *startp,
285 : : const unsigned char *const endp,
286 : : Dwarf_Die *cudie)
287 : : {
288 : 1422 : Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
289 : 1422 : Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
290 : : macro_op_compare);
291 [ + + ]: 1422 : if (found != NULL)
292 : 1394 : return *found;
293 : :
294 : 56 : Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
295 : 24 : ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
296 [ + + ]: 28 : : get_macinfo_table (dbg, macoff, cudie);
297 : :
298 [ - + ]: 28 : if (table == NULL)
299 : : return NULL;
300 : :
301 : 28 : Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
302 : : macro_op_compare);
303 [ - + ]: 28 : if (unlikely (ret == NULL))
304 : : {
305 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
306 : 0 : return NULL;
307 : : }
308 : :
309 : 28 : return *ret;
310 : : }
311 : :
312 : : static ptrdiff_t
313 : 1422 : read_macros (Dwarf *dbg, int sec_index,
314 : : Dwarf_Off macoff, int (*callback) (Dwarf_Macro *, void *),
315 : : void *arg, ptrdiff_t offset, bool accept_0xff,
316 : : Dwarf_Die *cudie)
317 : : {
318 : 1422 : Elf_Data *d = dbg->sectiondata[sec_index];
319 [ + - - + ]: 1422 : if (unlikely (d == NULL || d->d_buf == NULL))
320 : : {
321 : 0 : __libdw_seterrno (DWARF_E_NO_ENTRY);
322 : 0 : return -1;
323 : : }
324 : :
325 [ - + ]: 1422 : if (unlikely (macoff >= d->d_size))
326 : : {
327 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
328 : 0 : return -1;
329 : : }
330 : :
331 : 1422 : const unsigned char *const startp = d->d_buf + macoff;
332 : 1422 : const unsigned char *const endp = d->d_buf + d->d_size;
333 : :
334 : 1422 : Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
335 : : startp, endp, cudie);
336 [ - + ]: 1422 : if (table == NULL)
337 : : return -1;
338 : :
339 [ + + ]: 1422 : if (offset == 0)
340 : 28 : offset = table->header_len;
341 : :
342 [ - + ]: 1422 : assert (offset >= 0);
343 [ - + ]: 1422 : assert (offset < endp - startp);
344 : 1422 : const unsigned char *readp = startp + offset;
345 : :
346 [ + - ]: 1422 : while (readp < endp)
347 : : {
348 : 1422 : unsigned int opcode = *readp++;
349 [ + + ]: 1422 : if (opcode == 0)
350 : : /* Nothing more to do. */
351 : 1422 : return 0;
352 : :
353 [ + + ]: 1396 : if (unlikely (opcode == 0xff && ! accept_0xff))
354 : : {
355 : : /* See comment below at dwarf_getmacros for explanation of
356 : : why we are doing this. */
357 : 2 : __libdw_seterrno (DWARF_E_INVALID_OPCODE);
358 : 2 : return -1;
359 : : }
360 : :
361 : 1394 : unsigned int idx = table->opcodes[opcode - 1];
362 [ - + ]: 1394 : if (idx == 0xff)
363 : : {
364 : 0 : __libdw_seterrno (DWARF_E_INVALID_OPCODE);
365 : 0 : return -1;
366 : : }
367 : :
368 : 1394 : Dwarf_Macro_Op_Proto *proto = &table->table[idx];
369 : :
370 : : /* A fake CU with bare minimum data to fool dwarf_formX into
371 : : doing the right thing with the attributes that we put out.
372 : : We pretend it is the same version as the actual table.
373 : : Version 4 for the old GNU extension, version 5 for DWARF5.
374 : : To handle DW_FORM_strx[1234] we set the .str_offsets_base
375 : : from the given CU.
376 : : XXX We will need to deal with DW_MACRO_import_sup and change
377 : : out the dbg somehow for the DW_FORM_sec_offset to make sense. */
378 : 2788 : Dwarf_CU fake_cu = {
379 : : .dbg = dbg,
380 : : .sec_idx = sec_index,
381 : 1394 : .version = table->version,
382 : 1394 : .offset_size = table->offset_size,
383 [ + + ]: 1394 : .str_off_base = str_offsets_base_off (dbg, (cudie != NULL
384 : : ? cudie->cu: NULL)),
385 : : .startp = (void *) startp + offset,
386 : : .endp = (void *) endp,
387 : : };
388 : :
389 : 1394 : Dwarf_Attribute *attributes;
390 : 1394 : Dwarf_Attribute *attributesp = NULL;
391 : 1394 : Dwarf_Attribute nattributes[8];
392 [ - + ]: 1394 : if (unlikely (proto->nforms > 8))
393 : : {
394 : 0 : attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms);
395 [ # # ]: 0 : if (attributesp == NULL)
396 : : {
397 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
398 : 0 : return -1;
399 : : }
400 : : attributes = attributesp;
401 : : }
402 : : else
403 : : attributes = &nattributes[0];
404 : :
405 [ + + ]: 4108 : for (Dwarf_Word i = 0; i < proto->nforms; ++i)
406 : : {
407 : : /* We pretend this is a DW_AT[_GNU]_macros attribute so that
408 : : DW_FORM_sec_offset forms get correctly interpreted as
409 : : offset into .debug_macro. XXX Deal with DW_MACRO_import_sup
410 : : (swap .dbg) for DW_FORM_sec_offset? */
411 : 5428 : attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros
412 [ + + ]: 2714 : : DW_AT_macros);
413 : 2714 : attributes[i].form = proto->forms[i];
414 : 2714 : attributes[i].valp = (void *) readp;
415 : 2714 : attributes[i].cu = &fake_cu;
416 : :
417 : : /* We don't want forms that aren't allowed because they could
418 : : read from the "abbrev" like DW_FORM_implicit_const. */
419 [ - + ]: 2714 : if (! libdw_valid_user_form (attributes[i].form))
420 : : {
421 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
422 : 0 : free (attributesp);
423 : 0 : return -1;
424 : : }
425 : :
426 : 2714 : size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
427 [ - + ]: 2714 : if (unlikely (len == (size_t) -1))
428 : : {
429 : 0 : free (attributesp);
430 : 0 : return -1;
431 : : }
432 : :
433 : 2714 : readp += len;
434 : : }
435 : :
436 : 1394 : Dwarf_Macro macro = {
437 : : .table = table,
438 : : .opcode = opcode,
439 : : .attributes = attributes,
440 : : };
441 : :
442 : 1394 : int res = callback (¯o, arg);
443 [ - + ]: 1394 : if (unlikely (attributesp != NULL))
444 : 0 : free (attributesp);
445 : :
446 [ + - ]: 1394 : if (res != DWARF_CB_OK)
447 : 1394 : return readp - startp;
448 : : }
449 : :
450 : : return 0;
451 : : }
452 : :
453 : : /* Token layout:
454 : :
455 : : - The highest bit is used for distinguishing between callers that
456 : : know that opcode 0xff may have one of two incompatible meanings.
457 : : The mask that we use for selecting this bit is
458 : : DWARF_GETMACROS_START.
459 : :
460 : : - The rest of the token (31 or 63 bits) encodes address inside the
461 : : macro unit.
462 : :
463 : : Besides, token value of 0 signals end of iteration and -1 is
464 : : reserved for signaling errors. That means it's impossible to
465 : : represent maximum offset of a .debug_macro unit to new-style
466 : : callers (which in practice decreases the permissible macro unit
467 : : size by another 1 byte). */
468 : :
469 : : static ptrdiff_t
470 : 1422 : token_from_offset (ptrdiff_t offset, bool accept_0xff)
471 : : {
472 [ + + ]: 1422 : if (offset == -1 || offset == 0)
473 : : return offset;
474 : :
475 : : /* Make sure the offset didn't overflow into the flag bit. */
476 [ - + ]: 1394 : if ((offset & DWARF_GETMACROS_START) != 0)
477 : : {
478 : 0 : __libdw_seterrno (DWARF_E_TOO_BIG);
479 : 0 : return -1;
480 : : }
481 : :
482 [ + + ]: 1394 : if (accept_0xff)
483 : 342 : offset |= DWARF_GETMACROS_START;
484 : :
485 : : return offset;
486 : : }
487 : :
488 : : static ptrdiff_t
489 : 1422 : offset_from_token (ptrdiff_t token, bool *accept_0xffp)
490 : : {
491 : 1422 : *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
492 : 1422 : token &= ~DWARF_GETMACROS_START;
493 : :
494 : 1422 : return token;
495 : : }
496 : :
497 : : static ptrdiff_t
498 : 890 : gnu_macros_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
499 : : int (*callback) (Dwarf_Macro *, void *),
500 : : void *arg, ptrdiff_t offset, bool accept_0xff,
501 : : Dwarf_Die *cudie)
502 : : {
503 [ - + ]: 890 : assert (offset >= 0);
504 : :
505 [ - + ]: 890 : if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
506 : : {
507 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET);
508 : 0 : return -1;
509 : : }
510 : :
511 : 890 : return read_macros (dbg, IDX_debug_macro, macoff,
512 : : callback, arg, offset, accept_0xff, cudie);
513 : : }
514 : :
515 : : static ptrdiff_t
516 : 532 : macro_info_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
517 : : int (*callback) (Dwarf_Macro *, void *),
518 : : void *arg, ptrdiff_t offset, Dwarf_Die *cudie)
519 : : {
520 [ - + ]: 532 : assert (offset >= 0);
521 : :
522 : 532 : return read_macros (dbg, IDX_debug_macinfo, macoff,
523 : : callback, arg, offset, true, cudie);
524 : : }
525 : :
526 : : ptrdiff_t
527 : 352 : dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
528 : : int (*callback) (Dwarf_Macro *, void *),
529 : : void *arg, ptrdiff_t token)
530 : : {
531 [ - + ]: 352 : if (dbg == NULL)
532 : : {
533 : 0 : __libdw_seterrno (DWARF_E_NO_DWARF);
534 : 0 : return -1;
535 : : }
536 : :
537 : 352 : bool accept_0xff;
538 : 352 : ptrdiff_t offset = offset_from_token (token, &accept_0xff);
539 [ - + ]: 352 : assert (accept_0xff);
540 : :
541 : 352 : offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
542 : : accept_0xff, NULL);
543 : :
544 : 352 : return token_from_offset (offset, accept_0xff);
545 : : }
546 : :
547 : : ptrdiff_t
548 : 1070 : dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *),
549 : : void *arg, ptrdiff_t token)
550 : : {
551 [ - + ]: 1070 : if (cudie == NULL)
552 : : {
553 : 0 : __libdw_seterrno (DWARF_E_NO_DWARF);
554 : 0 : return -1;
555 : : }
556 : :
557 : : /* This function might be called from a code that expects to see
558 : : DW_MACINFO_* opcodes, not DW_MACRO_{GNU_,}* ones. It is fine to
559 : : serve most DW_MACRO_{GNU_,}* opcodes to such code, because those
560 : : whose values are the same as DW_MACINFO_* ones also have the same
561 : : behavior. It is not very likely that a .debug_macro section
562 : : would only use the part of opcode space that it shares with
563 : : .debug_macinfo, but it is possible. Serving the opcodes that are
564 : : only valid in DW_MACRO_{GNU_,}* domain is OK as well, because
565 : : clients in general need to be ready that newer standards define
566 : : more opcodes, and have coping mechanisms for unfamiliar opcodes.
567 : :
568 : : The one exception to the above rule is opcode 0xff, which has
569 : : concrete semantics in .debug_macinfo, but falls into vendor block
570 : : in .debug_macro, and can be assigned to do whatever. There is
571 : : some small probability that the two opcodes would look
572 : : superficially similar enough that a client would be confused and
573 : : misbehave as a result. For this reason, we refuse to serve
574 : : through this interface 0xff's originating from .debug_macro
575 : : unless the TOKEN that we obtained indicates the call originates
576 : : from a new-style caller. See above for details on what
577 : : information is encoded into tokens. */
578 : :
579 : 1070 : bool accept_0xff;
580 : 1070 : ptrdiff_t offset = offset_from_token (token, &accept_0xff);
581 : :
582 : : /* DW_AT_macro_info */
583 [ + + ]: 1070 : if (dwarf_hasattr (cudie, DW_AT_macro_info))
584 : : {
585 : 532 : Dwarf_Word macoff;
586 [ - + ]: 532 : if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
587 : 0 : return -1;
588 : 532 : offset = macro_info_getmacros_off (cudie->cu->dbg, macoff,
589 : : callback, arg, offset, cudie);
590 : : }
591 : : else
592 : : {
593 : : /* DW_AT_GNU_macros, DW_AT_macros */
594 : 538 : Dwarf_Word macoff;
595 [ - + ]: 538 : if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0
596 [ # # ]: 0 : && get_offset_from (cudie, DW_AT_macros, &macoff) != 0)
597 : 0 : return -1;
598 : 538 : offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
599 : : callback, arg, offset, accept_0xff,
600 : : cudie);
601 : : }
602 : :
603 : 1070 : return token_from_offset (offset, accept_0xff);
604 : : }
|