lib{asm,cpu,dw,dwfl,dwelf}: Move platform depended include into system.h
[platform/upstream/elfutils.git] / libdw / dwarf_getmacros.c
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 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
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
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
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 *
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     if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
128       return NULL;
129
130   Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
131                                              macinfo_data_size, 1);
132   memcpy (table, macinfo_data, macinfo_data_size);
133
134   table->offset = macoff;
135   table->sec_index = IDX_debug_macinfo;
136   table->line_offset = line_offset;
137   table->is_64bit = cudie->cu->address_size == 8;
138   table->comp_dir = __libdw_getcompdir (cudie);
139
140   return table;
141 }
142
143 static Dwarf_Macro_Op_Table *
144 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   const unsigned char *startp = readp;
150
151   /* Request at least 3 bytes for header.  */
152   if (readp + 3 > endp)
153     {
154     invalid_dwarf:
155       __libdw_seterrno (DWARF_E_INVALID_DWARF);
156       return NULL;
157     }
158
159   uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
160   if (version != 4 && version != 5)
161     {
162       __libdw_seterrno (DWARF_E_INVALID_VERSION);
163       return NULL;
164     }
165
166   uint8_t flags = *readp++;
167   bool is_64bit = (flags & 0x1) != 0;
168
169   Dwarf_Off line_offset = (Dwarf_Off) -1;
170   if ((flags & 0x2) != 0)
171     {
172       line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
173       if (readp > endp)
174         goto invalid_dwarf;
175     }
176   else if (cudie != NULL)
177     {
178       Dwarf_Attribute attr_mem, *attr
179         = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
180       if (attr != NULL)
181         if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
182           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   MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
193   MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
194   MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup);
195   MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx);
196   MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
197   MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
198   MACRO_PROTO (p_none);
199
200   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   if ((flags & 0x4) != 0)
217     {
218       unsigned count = *readp++;
219       for (unsigned i = 0; i < count; ++i)
220         {
221           unsigned opcode = *readp++;
222
223           Dwarf_Macro_Op_Proto e;
224           if (readp >= endp)
225             goto invalid;
226           get_uleb128 (e.nforms, readp, endp);
227           e.forms = readp;
228           op_protos[opcode - 1] = e;
229
230           readp += e.nforms;
231           if (readp > endp)
232             {
233             invalid:
234               __libdw_seterrno (DWARF_E_INVALID_DWARF);
235               return NULL;
236             }
237         }
238     }
239
240   size_t ct = 0;
241   for (unsigned i = 1; i < 256; ++i)
242     if (op_protos[i - 1].forms != NULL)
243       ++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   assert (ct < 0xff);
249
250   size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
251
252   Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
253                                              macop_table_size, 1);
254
255   *table = (Dwarf_Macro_Op_Table) {
256     .offset = macoff,
257     .sec_index = IDX_debug_macro,
258     .line_offset = line_offset,
259     .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     .comp_dir = __libdw_getcompdir (cudie),
265   };
266   build_table (table, op_protos);
267
268   return table;
269 }
270
271 static Dwarf_Macro_Op_Table *
272 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   Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
278   Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
279                                         macro_op_compare);
280   if (found != NULL)
281     return *found;
282
283   Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
284     ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
285     : get_macinfo_table (dbg, macoff, cudie);
286
287   if (table == NULL)
288     return NULL;
289
290   Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
291                                         macro_op_compare);
292   if (unlikely (ret == NULL))
293     {
294       __libdw_seterrno (DWARF_E_NOMEM);
295       return NULL;
296     }
297
298   return *ret;
299 }
300
301 static ptrdiff_t
302 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   Elf_Data *d = dbg->sectiondata[sec_index];
308   if (unlikely (d == NULL || d->d_buf == NULL))
309     {
310       __libdw_seterrno (DWARF_E_NO_ENTRY);
311       return -1;
312     }
313
314   if (unlikely (macoff >= d->d_size))
315     {
316       __libdw_seterrno (DWARF_E_INVALID_DWARF);
317       return -1;
318     }
319
320   const unsigned char *const startp = d->d_buf + macoff;
321   const unsigned char *const endp = d->d_buf + d->d_size;
322
323   Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
324                                                 startp, endp, cudie);
325   if (table == NULL)
326     return -1;
327
328   if (offset == 0)
329     offset = table->header_len;
330
331   assert (offset >= 0);
332   assert (offset < endp - startp);
333   const unsigned char *readp = startp + offset;
334
335   while (readp < endp)
336     {
337       unsigned int opcode = *readp++;
338       if (opcode == 0)
339         /* Nothing more to do.  */
340         return 0;
341
342       if (unlikely (opcode == 0xff && ! accept_0xff))
343         {
344           /* See comment below at dwarf_getmacros for explanation of
345              why we are doing this.  */
346           __libdw_seterrno (DWARF_E_INVALID_OPCODE);
347           return -1;
348         }
349
350       unsigned int idx = table->opcodes[opcode - 1];
351       if (idx == 0xff)
352         {
353           __libdw_seterrno (DWARF_E_INVALID_OPCODE);
354           return -1;
355         }
356
357       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       Dwarf_CU fake_cu = {
368         .dbg = dbg,
369         .sec_idx = sec_index,
370         .version = table->version,
371         .offset_size = table->is_64bit ? 8 : 4,
372         .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       Dwarf_Attribute *attributes;
379       Dwarf_Attribute *attributesp = NULL;
380       Dwarf_Attribute nattributes[8];
381       if (unlikely (proto->nforms > 8))
382         {
383           attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms);
384           if (attributesp == NULL)
385             {
386               __libdw_seterrno (DWARF_E_NOMEM);
387               return -1;
388             }
389           attributes = attributesp;
390         }
391       else
392         attributes = &nattributes[0];
393
394       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           attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros
401                                                      : DW_AT_macros);
402           attributes[i].form = proto->forms[i];
403           attributes[i].valp = (void *) readp;
404           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           if (! libdw_valid_user_form (attributes[i].form))
409             {
410               __libdw_seterrno (DWARF_E_INVALID_DWARF);
411               free (attributesp);
412               return -1;
413             }
414
415           size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
416           if (unlikely (len == (size_t) -1))
417             {
418               free (attributesp);
419               return -1;
420             }
421
422           readp += len;
423         }
424
425       Dwarf_Macro macro = {
426         .table = table,
427         .opcode = opcode,
428         .attributes = attributes,
429       };
430
431       int res = callback (&macro, arg);
432       if (unlikely (attributesp != NULL))
433         free (attributesp);
434
435       if (res != DWARF_CB_OK)
436         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 token_from_offset (ptrdiff_t offset, bool accept_0xff)
460 {
461   if (offset == -1 || offset == 0)
462     return offset;
463
464   /* Make sure the offset didn't overflow into the flag bit.  */
465   if ((offset & DWARF_GETMACROS_START) != 0)
466     {
467       __libdw_seterrno (DWARF_E_TOO_BIG);
468       return -1;
469     }
470
471   if (accept_0xff)
472     offset |= DWARF_GETMACROS_START;
473
474   return offset;
475 }
476
477 static ptrdiff_t
478 offset_from_token (ptrdiff_t token, bool *accept_0xffp)
479 {
480   *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
481   token &= ~DWARF_GETMACROS_START;
482
483   return token;
484 }
485
486 static ptrdiff_t
487 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   assert (offset >= 0);
493
494   if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
495     {
496       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
497       return -1;
498     }
499
500   return read_macros (dbg, IDX_debug_macro, macoff,
501                       callback, arg, offset, accept_0xff, cudie);
502 }
503
504 static ptrdiff_t
505 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   assert (offset >= 0);
510
511   return read_macros (dbg, IDX_debug_macinfo, macoff,
512                       callback, arg, offset, true, cudie);
513 }
514
515 ptrdiff_t
516 dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
517                      int (*callback) (Dwarf_Macro *, void *),
518                      void *arg, ptrdiff_t token)
519 {
520   if (dbg == NULL)
521     {
522       __libdw_seterrno (DWARF_E_NO_DWARF);
523       return -1;
524     }
525
526   bool accept_0xff;
527   ptrdiff_t offset = offset_from_token (token, &accept_0xff);
528   assert (accept_0xff);
529
530   offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
531                                      accept_0xff, NULL);
532
533   return token_from_offset (offset, accept_0xff);
534 }
535
536 ptrdiff_t
537 dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *),
538                  void *arg, ptrdiff_t token)
539 {
540   if (cudie == NULL)
541     {
542       __libdw_seterrno (DWARF_E_NO_DWARF);
543       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   bool accept_0xff;
569   ptrdiff_t offset = offset_from_token (token, &accept_0xff);
570
571   /* DW_AT_macro_info */
572   if (dwarf_hasattr (cudie, DW_AT_macro_info))
573     {
574       Dwarf_Word macoff;
575       if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
576         return -1;
577       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       Dwarf_Word macoff;
584       if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0
585           && get_offset_from (cudie, DW_AT_macros, &macoff) != 0)
586         return -1;
587       offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
588                                          callback, arg, offset, accept_0xff,
589                                          cudie);
590     }
591
592   return token_from_offset (offset, accept_0xff);
593 }