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