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