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
get_offset_from(Dwarf_Die * die,int name,Dwarf_Word * retp)42 get_offset_from (Dwarf_Die *die, int name, Dwarf_Word *retp)
43 {
44 /* Get the appropriate attribute. */
45 Dwarf_Attribute attr;
46 if (INTUSE(dwarf_attr) (die, name, &attr) == NULL)
47 return -1;
48
49 /* Offset into the corresponding section. */
50 return INTUSE(dwarf_formudata) (&attr, retp);
51 }
52
53 static int
macro_op_compare(const void * p1,const void * p2)54 macro_op_compare (const void *p1, const void *p2)
55 {
56 const Dwarf_Macro_Op_Table *t1 = (const Dwarf_Macro_Op_Table *) p1;
57 const Dwarf_Macro_Op_Table *t2 = (const Dwarf_Macro_Op_Table *) p2;
58
59 if (t1->offset < t2->offset)
60 return -1;
61 if (t1->offset > t2->offset)
62 return 1;
63
64 if (t1->sec_index < t2->sec_index)
65 return -1;
66 if (t1->sec_index > t2->sec_index)
67 return 1;
68
69 return 0;
70 }
71
72 static void
build_table(Dwarf_Macro_Op_Table * table,Dwarf_Macro_Op_Proto op_protos[static255])73 build_table (Dwarf_Macro_Op_Table *table,
74 Dwarf_Macro_Op_Proto op_protos[static 255])
75 {
76 unsigned ct = 0;
77 for (unsigned i = 1; i < 256; ++i)
78 if (op_protos[i - 1].forms != NULL)
79 table->table[table->opcodes[i - 1] = ct++] = op_protos[i - 1];
80 else
81 table->opcodes[i - 1] = 0xff;
82 }
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
init_macinfo_table(void)95 init_macinfo_table (void)
96 {
97 MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
98 MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
99 MACRO_PROTO (p_none);
100
101 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 Dwarf_Macro_Op_Table *macinfo_table = (void *) macinfo_data;
113 memset (macinfo_table, 0, sizeof macinfo_data);
114 build_table (macinfo_table, op_protos);
115 macinfo_table->sec_index = IDX_debug_macinfo;
116 }
117
118 static Dwarf_Macro_Op_Table *
get_macinfo_table(Dwarf * dbg,Dwarf_Word macoff,Dwarf_Die * cudie)119 get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die *cudie)
120 {
121 assert (cudie != NULL);
122
123 Dwarf_Attribute attr_mem, *attr
124 = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
125 Dwarf_Off line_offset = (Dwarf_Off) -1;
126 if (attr != NULL)
127 {
128 if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
129 return NULL;
130 }
131 else if (cudie->cu->unit_type == DW_UT_split_compile
132 && dbg->sectiondata[IDX_debug_line] != NULL)
133 line_offset = 0;
134
135 Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
136 macinfo_data_size, 1);
137 memcpy (table, macinfo_data, macinfo_data_size);
138
139 table->dbg = dbg;
140 table->offset = macoff;
141 table->sec_index = IDX_debug_macinfo;
142 table->line_offset = line_offset;
143 table->address_size = cudie->cu->address_size;
144 table->offset_size = cudie->cu->offset_size;
145 table->comp_dir = __libdw_getcompdir (cudie);
146
147 return table;
148 }
149
150 static Dwarf_Macro_Op_Table *
get_table_for_offset(Dwarf * dbg,Dwarf_Word macoff,const unsigned char * readp,const unsigned char * const endp,Dwarf_Die * cudie)151 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 const unsigned char *startp = readp;
157
158 /* Request at least 3 bytes for header. */
159 if (readp + 3 > endp)
160 {
161 invalid_dwarf:
162 __libdw_seterrno (DWARF_E_INVALID_DWARF);
163 return NULL;
164 }
165
166 uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
167 if (version != 4 && version != 5)
168 {
169 __libdw_seterrno (DWARF_E_INVALID_VERSION);
170 return NULL;
171 }
172
173 uint8_t flags = *readp++;
174 bool is_64bit = (flags & 0x1) != 0;
175
176 Dwarf_Off line_offset = (Dwarf_Off) -1;
177 if ((flags & 0x2) != 0)
178 {
179 line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
180 if (readp > endp)
181 goto invalid_dwarf;
182 }
183 else if (cudie != NULL)
184 {
185 Dwarf_Attribute attr_mem, *attr
186 = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
187 if (attr != NULL)
188 if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
189 return NULL;
190 }
191
192 uint8_t address_size;
193 if (cudie != NULL)
194 address_size = cudie->cu->address_size;
195 else
196 {
197 char *ident = elf_getident (dbg->elf, NULL);
198 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 MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
209 MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
210 MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup);
211 MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx);
212 MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
213 MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
214 MACRO_PROTO (p_none);
215
216 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 if ((flags & 0x4) != 0)
233 {
234 unsigned count = *readp++;
235 for (unsigned i = 0; i < count; ++i)
236 {
237 unsigned opcode = *readp++;
238
239 Dwarf_Macro_Op_Proto e;
240 if (readp >= endp)
241 goto invalid;
242 get_uleb128 (e.nforms, readp, endp);
243 e.forms = readp;
244 op_protos[opcode - 1] = e;
245
246 readp += e.nforms;
247 if (readp > endp)
248 {
249 invalid:
250 __libdw_seterrno (DWARF_E_INVALID_DWARF);
251 return NULL;
252 }
253 }
254 }
255
256 size_t ct = 0;
257 for (unsigned i = 1; i < 256; ++i)
258 if (op_protos[i - 1].forms != NULL)
259 ++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 assert (ct < 0xff);
265
266 size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
267
268 Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
269 macop_table_size, 1);
270
271 *table = (Dwarf_Macro_Op_Table) {
272 .dbg = dbg,
273 .offset = macoff,
274 .sec_index = IDX_debug_macro,
275 .line_offset = line_offset,
276 .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 .comp_dir = __libdw_getcompdir (cudie),
283 };
284 build_table (table, op_protos);
285
286 return table;
287 }
288
289 static Dwarf_Macro_Op_Table *
cache_op_table(Dwarf * dbg,int sec_index,Dwarf_Off macoff,const unsigned char * startp,const unsigned char * const endp,Dwarf_Die * cudie)290 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 Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
296 Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
297 macro_op_compare);
298 if (found != NULL)
299 return *found;
300
301 Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
302 ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
303 : get_macinfo_table (dbg, macoff, cudie);
304
305 if (table == NULL)
306 return NULL;
307
308 Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
309 macro_op_compare);
310 if (unlikely (ret == NULL))
311 {
312 __libdw_seterrno (DWARF_E_NOMEM);
313 return NULL;
314 }
315
316 return *ret;
317 }
318
319 static ptrdiff_t
read_macros(Dwarf * dbg,int sec_index,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,bool accept_0xff,Dwarf_Die * cudie)320 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 Elf_Data *d = dbg->sectiondata[sec_index];
326 if (unlikely (d == NULL || d->d_buf == NULL))
327 {
328 __libdw_seterrno (DWARF_E_NO_ENTRY);
329 return -1;
330 }
331
332 if (unlikely (macoff >= d->d_size))
333 {
334 __libdw_seterrno (DWARF_E_INVALID_DWARF);
335 return -1;
336 }
337
338 const unsigned char *const startp = d->d_buf + macoff;
339 const unsigned char *const endp = d->d_buf + d->d_size;
340
341 Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
342 startp, endp, cudie);
343 if (table == NULL)
344 return -1;
345
346 if (offset == 0)
347 offset = table->header_len;
348
349 assert (offset >= 0);
350 assert (offset < endp - startp);
351 const unsigned char *readp = startp + offset;
352
353 while (readp < endp)
354 {
355 unsigned int opcode = *readp++;
356 if (opcode == 0)
357 /* Nothing more to do. */
358 return 0;
359
360 if (unlikely (opcode == 0xff && ! accept_0xff))
361 {
362 /* See comment below at dwarf_getmacros for explanation of
363 why we are doing this. */
364 __libdw_seterrno (DWARF_E_INVALID_OPCODE);
365 return -1;
366 }
367
368 unsigned int idx = table->opcodes[opcode - 1];
369 if (idx == 0xff)
370 {
371 __libdw_seterrno (DWARF_E_INVALID_OPCODE);
372 return -1;
373 }
374
375 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 Dwarf_CU fake_cu = {
386 .dbg = dbg,
387 .sec_idx = sec_index,
388 .version = table->version,
389 .offset_size = table->offset_size,
390 .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 Dwarf_Attribute *attributes;
397 Dwarf_Attribute *attributesp = NULL;
398 Dwarf_Attribute nattributes[8];
399 if (unlikely (proto->nforms > 8))
400 {
401 attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms);
402 if (attributesp == NULL)
403 {
404 __libdw_seterrno (DWARF_E_NOMEM);
405 return -1;
406 }
407 attributes = attributesp;
408 }
409 else
410 attributes = &nattributes[0];
411
412 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 attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros
419 : DW_AT_macros);
420 attributes[i].form = proto->forms[i];
421 attributes[i].valp = (void *) readp;
422 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 if (! libdw_valid_user_form (attributes[i].form))
427 {
428 __libdw_seterrno (DWARF_E_INVALID_DWARF);
429 free (attributesp);
430 return -1;
431 }
432
433 size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
434 if (unlikely (len == (size_t) -1))
435 {
436 free (attributesp);
437 return -1;
438 }
439
440 readp += len;
441 }
442
443 Dwarf_Macro macro = {
444 .table = table,
445 .opcode = opcode,
446 .attributes = attributes,
447 };
448
449 int res = callback (¯o, arg);
450 if (unlikely (attributesp != NULL))
451 free (attributesp);
452
453 if (res != DWARF_CB_OK)
454 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
token_from_offset(ptrdiff_t offset,bool accept_0xff)477 token_from_offset (ptrdiff_t offset, bool accept_0xff)
478 {
479 if (offset == -1 || offset == 0)
480 return offset;
481
482 /* Make sure the offset didn't overflow into the flag bit. */
483 if ((offset & DWARF_GETMACROS_START) != 0)
484 {
485 __libdw_seterrno (DWARF_E_TOO_BIG);
486 return -1;
487 }
488
489 if (accept_0xff)
490 offset |= DWARF_GETMACROS_START;
491
492 return offset;
493 }
494
495 static ptrdiff_t
offset_from_token(ptrdiff_t token,bool * accept_0xffp)496 offset_from_token (ptrdiff_t token, bool *accept_0xffp)
497 {
498 *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
499 token &= ~DWARF_GETMACROS_START;
500
501 return token;
502 }
503
504 static ptrdiff_t
gnu_macros_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,bool accept_0xff,Dwarf_Die * cudie)505 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 assert (offset >= 0);
511
512 if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
513 {
514 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
515 return -1;
516 }
517
518 return read_macros (dbg, IDX_debug_macro, macoff,
519 callback, arg, offset, accept_0xff, cudie);
520 }
521
522 static ptrdiff_t
macro_info_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,Dwarf_Die * cudie)523 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 assert (offset >= 0);
528
529 return read_macros (dbg, IDX_debug_macinfo, macoff,
530 callback, arg, offset, true, cudie);
531 }
532
533 ptrdiff_t
dwarf_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t token)534 dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
535 int (*callback) (Dwarf_Macro *, void *),
536 void *arg, ptrdiff_t token)
537 {
538 if (dbg == NULL)
539 {
540 __libdw_seterrno (DWARF_E_NO_DWARF);
541 return -1;
542 }
543
544 bool accept_0xff;
545 ptrdiff_t offset = offset_from_token (token, &accept_0xff);
546 assert (accept_0xff);
547
548 offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
549 accept_0xff, NULL);
550
551 return token_from_offset (offset, accept_0xff);
552 }
553
554 ptrdiff_t
dwarf_getmacros(Dwarf_Die * cudie,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t token)555 dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *),
556 void *arg, ptrdiff_t token)
557 {
558 if (cudie == NULL)
559 {
560 __libdw_seterrno (DWARF_E_NO_DWARF);
561 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 bool accept_0xff;
587 ptrdiff_t offset = offset_from_token (token, &accept_0xff);
588
589 /* DW_AT_macro_info */
590 if (dwarf_hasattr (cudie, DW_AT_macro_info))
591 {
592 Dwarf_Word macoff;
593 if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
594 return -1;
595 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 Dwarf_Word macoff;
602 if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0
603 && get_offset_from (cudie, DW_AT_macros, &macoff) != 0)
604 return -1;
605 offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
606 callback, arg, offset, accept_0xff,
607 cudie);
608 }
609
610 return token_from_offset (offset, accept_0xff);
611 }
612