dfaa742c6032e4e2238fea70580e64414604c72f
[platform/upstream/elfutils.git] / libdw / dwarf_getlocation.c
1 /* Return location expression list.
2    Copyright (C) 2000-2010 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of either
8
9      * the GNU Lesser General Public License as published by the Free
10        Software Foundation; either version 3 of the License, or (at
11        your option) any later version
12
13    or
14
15      * the GNU General Public License as published by the Free
16        Software Foundation; either version 2 of the License, or (at
17        your option) any later version
18
19    or both in parallel, as here.
20
21    elfutils is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24    General Public License for more details.
25
26    You should have received copies of the GNU General Public License and
27    the GNU Lesser General Public License along with this program.  If
28    not, see <http://www.gnu.org/licenses/>.  */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <dwarf.h>
35 #include <search.h>
36 #include <stdlib.h>
37 #include <assert.h>
38
39 #include <libdwP.h>
40
41
42 static bool
43 attr_ok (Dwarf_Attribute *attr)
44 {
45   if (attr == NULL)
46     return false;
47
48   /* Must be one of the attributes listed below.  */
49   switch (attr->code)
50     {
51     case DW_AT_location:
52     case DW_AT_data_member_location:
53     case DW_AT_vtable_elem_location:
54     case DW_AT_string_length:
55     case DW_AT_use_location:
56     case DW_AT_frame_base:
57     case DW_AT_return_addr:
58     case DW_AT_static_link:
59       break;
60
61     default:
62       __libdw_seterrno (DWARF_E_NO_LOCLIST);
63       return false;
64     }
65
66   return true;
67 }
68
69
70 struct loclist
71 {
72   uint8_t atom;
73   Dwarf_Word number;
74   Dwarf_Word number2;
75   Dwarf_Word offset;
76   struct loclist *next;
77 };
78
79
80 static int
81 loc_compare (const void *p1, const void *p2)
82 {
83   const struct loc_s *l1 = (const struct loc_s *) p1;
84   const struct loc_s *l2 = (const struct loc_s *) p2;
85
86   if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
87     return -1;
88   if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
89     return 1;
90
91   return 0;
92 }
93
94 /* For each DW_OP_implicit_value, we store a special entry in the cache.
95    This points us directly to the block data for later fetching.  */
96 static void
97 store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
98                       unsigned char *data)
99 {
100   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
101                                            sizeof (struct loc_block_s), 1);
102   block->addr = op;
103   block->data = data + op->number2;
104   block->length = op->number;
105   (void) tsearch (block, cache, loc_compare);
106 }
107
108 int
109 dwarf_getlocation_implicit_value (attr, op, return_block)
110      Dwarf_Attribute *attr;
111      const Dwarf_Op *op;
112      Dwarf_Block *return_block;
113 {
114   if (attr == NULL)
115     return -1;
116
117   struct loc_block_s fake = { .addr = (void *) op };
118   struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
119   if (unlikely (found == NULL))
120     {
121       __libdw_seterrno (DWARF_E_NO_BLOCK);
122       return -1;
123     }
124
125   return_block->length = (*found)->length;
126   return_block->data = (*found)->data;
127   return 0;
128 }
129
130 /* DW_AT_data_member_location can be a constant as well as a loclistptr.
131    Only data[48] indicate a loclistptr.  */
132 static int
133 check_constant_offset (Dwarf_Attribute *attr,
134                        Dwarf_Op **llbuf, size_t *listlen)
135 {
136   if (attr->code != DW_AT_data_member_location)
137     return 1;
138
139   switch (attr->form)
140     {
141       /* Punt for any non-constant form.  */
142     default:
143       return 1;
144
145     case DW_FORM_data1:
146     case DW_FORM_data2:
147     case DW_FORM_data4:
148     case DW_FORM_data8:
149     case DW_FORM_sdata:
150     case DW_FORM_udata:
151       break;
152     }
153
154   /* Check whether we already cached this location.  */
155   struct loc_s fake = { .addr = attr->valp };
156   struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
157
158   if (found == NULL)
159     {
160       Dwarf_Word offset;
161       if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
162         return -1;
163
164       Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
165                                       Dwarf_Op, sizeof (Dwarf_Op), 1);
166
167       result->atom = DW_OP_plus_uconst;
168       result->number = offset;
169       result->number2 = 0;
170       result->offset = 0;
171
172       /* Insert a record in the search tree so we can find it again later.  */
173       struct loc_s *newp = libdw_alloc (attr->cu->dbg,
174                                         struct loc_s, sizeof (struct loc_s),
175                                         1);
176       newp->addr = attr->valp;
177       newp->loc = result;
178       newp->nloc = 1;
179
180       found = tsearch (newp, &attr->cu->locs, loc_compare);
181     }
182
183   assert ((*found)->nloc == 1);
184
185   if (llbuf != NULL)
186     {
187       *llbuf = (*found)->loc;
188       *listlen = 1;
189     }
190
191   return 0;
192 }
193
194 int
195 internal_function
196 __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
197                            unsigned int address_size, unsigned int ref_size,
198                            void **cache, const Dwarf_Block *block,
199                            bool cfap, bool valuep,
200                            Dwarf_Op **llbuf, size_t *listlen, int sec_index)
201 {
202   /* Check whether we already looked at this list.  */
203   struct loc_s fake = { .addr = block->data };
204   struct loc_s **found = tfind (&fake, cache, loc_compare);
205   if (found != NULL)
206     {
207       /* We already saw it.  */
208       *llbuf = (*found)->loc;
209       *listlen = (*found)->nloc;
210
211       if (valuep)
212         {
213           assert (*listlen > 1);
214           assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
215         }
216
217       return 0;
218     }
219
220   const unsigned char *data = block->data;
221   const unsigned char *const end_data = data + block->length;
222
223   const struct { bool other_byte_order; } bo = { other_byte_order };
224
225   struct loclist *loclist = NULL;
226   unsigned int n = 0;
227   /* Decode the opcodes.  It is possible in some situations to have a
228      block of size zero.  */
229   while (data < end_data)
230     {
231       struct loclist *newloc;
232       newloc = (struct loclist *) alloca (sizeof (struct loclist));
233       newloc->number = 0;
234       newloc->number2 = 0;
235       newloc->offset = data - block->data;
236       newloc->next = loclist;
237       loclist = newloc;
238       ++n;
239
240       switch ((newloc->atom = *data++))
241         {
242         case DW_OP_addr:
243           /* Address, depends on address size of CU.  */
244           if (__libdw_read_address_inc (dbg, sec_index, &data,
245                                         address_size, &newloc->number))
246             return -1;
247           break;
248
249         case DW_OP_call_ref:
250           /* DW_FORM_ref_addr, depends on offset size of CU.  */
251           if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
252                                        &newloc->number, IDX_debug_info, 0))
253             return -1;
254           break;
255
256         case DW_OP_deref:
257         case DW_OP_dup:
258         case DW_OP_drop:
259         case DW_OP_over:
260         case DW_OP_swap:
261         case DW_OP_rot:
262         case DW_OP_xderef:
263         case DW_OP_abs:
264         case DW_OP_and:
265         case DW_OP_div:
266         case DW_OP_minus:
267         case DW_OP_mod:
268         case DW_OP_mul:
269         case DW_OP_neg:
270         case DW_OP_not:
271         case DW_OP_or:
272         case DW_OP_plus:
273         case DW_OP_shl:
274         case DW_OP_shr:
275         case DW_OP_shra:
276         case DW_OP_xor:
277         case DW_OP_eq:
278         case DW_OP_ge:
279         case DW_OP_gt:
280         case DW_OP_le:
281         case DW_OP_lt:
282         case DW_OP_ne:
283         case DW_OP_lit0 ... DW_OP_lit31:
284         case DW_OP_reg0 ... DW_OP_reg31:
285         case DW_OP_nop:
286         case DW_OP_push_object_address:
287         case DW_OP_call_frame_cfa:
288         case DW_OP_form_tls_address:
289         case DW_OP_GNU_push_tls_address:
290         case DW_OP_stack_value:
291           /* No operand.  */
292           break;
293
294         case DW_OP_const1u:
295         case DW_OP_pick:
296         case DW_OP_deref_size:
297         case DW_OP_xderef_size:
298           if (unlikely (data >= end_data))
299             {
300             invalid:
301               __libdw_seterrno (DWARF_E_INVALID_DWARF);
302               return -1;
303             }
304
305           newloc->number = *data++;
306           break;
307
308         case DW_OP_const1s:
309           if (unlikely (data >= end_data))
310             goto invalid;
311
312           newloc->number = *((int8_t *) data);
313           ++data;
314           break;
315
316         case DW_OP_const2u:
317           if (unlikely (data + 2 > end_data))
318             goto invalid;
319
320           newloc->number = read_2ubyte_unaligned_inc (&bo, data);
321           break;
322
323         case DW_OP_const2s:
324         case DW_OP_skip:
325         case DW_OP_bra:
326         case DW_OP_call2:
327           if (unlikely (data + 2 > end_data))
328             goto invalid;
329
330           newloc->number = read_2sbyte_unaligned_inc (&bo, data);
331           break;
332
333         case DW_OP_const4u:
334           if (unlikely (data + 4 > end_data))
335             goto invalid;
336
337           newloc->number = read_4ubyte_unaligned_inc (&bo, data);
338           break;
339
340         case DW_OP_const4s:
341         case DW_OP_call4:
342           if (unlikely (data + 4 > end_data))
343             goto invalid;
344
345           newloc->number = read_4sbyte_unaligned_inc (&bo, data);
346           break;
347
348         case DW_OP_const8u:
349           if (unlikely (data + 8 > end_data))
350             goto invalid;
351
352           newloc->number = read_8ubyte_unaligned_inc (&bo, data);
353           break;
354
355         case DW_OP_const8s:
356           if (unlikely (data + 8 > end_data))
357             goto invalid;
358
359           newloc->number = read_8sbyte_unaligned_inc (&bo, data);
360           break;
361
362         case DW_OP_constu:
363         case DW_OP_plus_uconst:
364         case DW_OP_regx:
365         case DW_OP_piece:
366           /* XXX Check size.  */
367           get_uleb128 (newloc->number, data);
368           break;
369
370         case DW_OP_consts:
371         case DW_OP_breg0 ... DW_OP_breg31:
372         case DW_OP_fbreg:
373           /* XXX Check size.  */
374           get_sleb128 (newloc->number, data);
375           break;
376
377         case DW_OP_bregx:
378           /* XXX Check size.  */
379           get_uleb128 (newloc->number, data);
380           get_sleb128 (newloc->number2, data);
381           break;
382
383         case DW_OP_bit_piece:
384           /* XXX Check size.  */
385           get_uleb128 (newloc->number, data);
386           get_uleb128 (newloc->number2, data);
387           break;
388
389         case DW_OP_implicit_value:
390           /* This cannot be used in a CFI expression.  */
391           if (unlikely (dbg == NULL))
392             goto invalid;
393
394           /* XXX Check size.  */
395           get_uleb128 (newloc->number, data); /* Block length.  */
396           if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
397             goto invalid;
398           newloc->number2 = data - block->data; /* Relative block offset.  */
399           data += newloc->number;               /* Skip the block.  */
400           break;
401
402         case DW_OP_GNU_implicit_pointer:
403           /* DW_FORM_ref_addr, depends on offset size of CU.  */
404           if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
405                                        &newloc->number, IDX_debug_info, 0))
406             return -1;
407           /* XXX Check size.  */
408           get_uleb128 (newloc->number2, data); /* Byte offset.  */
409           break;
410
411         default:
412           goto invalid;
413         }
414     }
415
416   if (unlikely (n == 0))
417     {
418       /* This is not allowed.
419
420          XXX Is it?  */
421       goto invalid;
422     }
423
424   if (valuep)
425     {
426       struct loclist *newloc;
427       newloc = (struct loclist *) alloca (sizeof (struct loclist));
428       newloc->atom = DW_OP_stack_value;
429       newloc->number = 0;
430       newloc->number2 = 0;
431       newloc->offset = data - block->data;
432       newloc->next = loclist;
433       loclist = newloc;
434       ++n;
435     }
436
437   if (cfap)
438     ++n;
439
440   /* Allocate the array.  */
441   Dwarf_Op *result;
442   if (dbg != NULL)
443     result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
444   else
445     {
446       result = malloc (sizeof *result * n);
447       if (result == NULL)
448         {
449         nomem:
450           __libdw_seterrno (DWARF_E_NOMEM);
451           return -1;
452         }
453     }
454
455   /* Store the result.  */
456   *llbuf = result;
457   *listlen = n;
458
459   if (cfap)
460     {
461       /* Synthesize the operation to push the CFA before the expression.  */
462       --n;
463       result[0].atom = DW_OP_call_frame_cfa;
464       result[0].number = 0;
465       result[0].number2 = 0;
466       result[0].offset = -1;
467     }
468
469   do
470     {
471       /* We populate the array from the back since the list is backwards.  */
472       --n;
473       result[n].atom = loclist->atom;
474       result[n].number = loclist->number;
475       result[n].number2 = loclist->number2;
476       result[n].offset = loclist->offset;
477
478       if (result[n].atom == DW_OP_implicit_value)
479         store_implicit_value (dbg, cache, &result[n], block->data);
480
481       loclist = loclist->next;
482     }
483   while (n > 0);
484
485   /* Insert a record in the search tree so that we can find it again later.  */
486   struct loc_s *newp;
487   if (dbg != NULL)
488     newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
489   else
490     {
491       newp = malloc (sizeof *newp);
492       if (newp == NULL)
493         {
494           free (result);
495           goto nomem;
496         }
497     }
498
499   newp->addr = block->data;
500   newp->loc = result;
501   newp->nloc = *listlen;
502   (void) tsearch (newp, cache, loc_compare);
503
504   /* We did it.  */
505   return 0;
506 }
507
508 static int
509 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
510              Dwarf_Op **llbuf, size_t *listlen, int sec_index)
511 {
512   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
513                                     cu->address_size, (cu->version == 2
514                                                        ? cu->address_size
515                                                        : cu->offset_size),
516                                     &cu->locs, block,
517                                     false, false,
518                                     llbuf, listlen, sec_index);
519 }
520
521 int
522 dwarf_getlocation (attr, llbuf, listlen)
523      Dwarf_Attribute *attr;
524      Dwarf_Op **llbuf;
525      size_t *listlen;
526 {
527   if (! attr_ok (attr))
528     return -1;
529
530   int result = check_constant_offset (attr, llbuf, listlen);
531   if (result != 1)
532     return result;
533
534   /* If it has a block form, it's a single location expression.  */
535   Dwarf_Block block;
536   if (INTUSE(dwarf_formblock) (attr, &block) != 0)
537     return -1;
538
539   return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
540 }
541
542 int
543 dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
544      Dwarf_Attribute *attr;
545      Dwarf_Addr address;
546      Dwarf_Op **llbufs;
547      size_t *listlens;
548      size_t maxlocs;
549 {
550   if (! attr_ok (attr))
551     return -1;
552
553   if (llbufs == NULL)
554     maxlocs = SIZE_MAX;
555
556   /* If it has a block form, it's a single location expression.  */
557   Dwarf_Block block;
558   if (INTUSE(dwarf_formblock) (attr, &block) == 0)
559     {
560       if (maxlocs == 0)
561         return 0;
562       if (llbufs != NULL &&
563           getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
564                        cu_sec_idx (attr->cu)) != 0)
565         return -1;
566       return listlens[0] == 0 ? 0 : 1;
567     }
568
569   int error = INTUSE(dwarf_errno) ();
570   if (unlikely (error != DWARF_E_NO_BLOCK))
571     {
572       __libdw_seterrno (error);
573       return -1;
574     }
575
576   int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
577   if (result != 1)
578     return result ?: 1;
579
580   unsigned char *endp;
581   unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
582                                           DWARF_E_NO_LOCLIST, &endp, NULL);
583   if (readp == NULL)
584     return -1;
585
586   Dwarf_Addr base = (Dwarf_Addr) -1;
587   size_t got = 0;
588   while (got < maxlocs)
589     {
590       if (endp - readp < attr->cu->address_size * 2)
591         {
592         invalid:
593           __libdw_seterrno (DWARF_E_INVALID_DWARF);
594           return -1;
595         }
596
597       Dwarf_Addr begin;
598       Dwarf_Addr end;
599
600       int status
601         = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
602                                            &readp, attr->cu->address_size,
603                                            &begin, &end, &base);
604       if (status == 2) /* End of list entry.  */
605         break;
606       else if (status == 1) /* Base address selected.  */
607         continue;
608       else if (status < 0)
609         return status;
610
611       if (endp - readp < 2)
612         goto invalid;
613
614       /* We have a location expression.  */
615       block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
616       block.data = readp;
617       if (endp - readp < (ptrdiff_t) block.length)
618         goto invalid;
619       readp += block.length;
620
621       if (base == (Dwarf_Addr) -1)
622         {
623           /* Fetch the CU's base address.  */
624           Dwarf_Die cudie = CUDIE (attr->cu);
625
626           /* Find the base address of the compilation unit.  It will
627              normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
628              the base address could be overridden by DW_AT_entry_pc.  It's
629              been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
630              for compilation units with discontinuous ranges.  */
631           Dwarf_Attribute attr_mem;
632           if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
633               && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
634                                                              DW_AT_entry_pc,
635                                                              &attr_mem),
636                                          &base) != 0)
637             {
638               if (INTUSE(dwarf_errno) () != 0)
639                 return -1;
640
641               /* The compiler provided no base address when it should
642                  have.  Buggy GCC does this when it used absolute
643                  addresses in the location list and no DW_AT_ranges.  */
644               base = 0;
645             }
646         }
647
648       if (address >= base + begin && address < base + end)
649         {
650           /* This one matches the address.  */
651           if (llbufs != NULL
652               && unlikely (getlocation (attr->cu, &block,
653                                         &llbufs[got], &listlens[got],
654                                         IDX_debug_loc) != 0))
655             return -1;
656           ++got;
657         }
658     }
659
660   return got;
661 }