1 /* Return location expression list.
2 Copyright (C) 2000-2010, 2013-2015, 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 <dwarf.h>
34 #include <search.h>
35 #include <stdlib.h>
36 #include <assert.h>
37
38 #include <libdwP.h>
39
40
41 static bool
attr_ok(Dwarf_Attribute * attr)42 attr_ok (Dwarf_Attribute *attr)
43 {
44 if (attr == NULL)
45 return false;
46
47 /* If it is an exprloc, it is obviously OK. */
48 if (dwarf_whatform (attr) == DW_FORM_exprloc)
49 return true;
50
51 /* Otherwise must be one of the attributes listed below. Older
52 DWARF versions might have encoded the exprloc as block, and we
53 cannot easily distinquish attributes in the loclist class because
54 the same forms are used for different classes. */
55 switch (attr->code)
56 {
57 case DW_AT_location:
58 case DW_AT_byte_size:
59 case DW_AT_bit_offset:
60 case DW_AT_bit_size:
61 case DW_AT_lower_bound:
62 case DW_AT_bit_stride:
63 case DW_AT_upper_bound:
64 case DW_AT_count:
65 case DW_AT_allocated:
66 case DW_AT_associated:
67 case DW_AT_data_location:
68 case DW_AT_byte_stride:
69 case DW_AT_rank:
70 case DW_AT_call_value:
71 case DW_AT_call_target:
72 case DW_AT_call_target_clobbered:
73 case DW_AT_call_data_location:
74 case DW_AT_call_data_value:
75 case DW_AT_data_member_location:
76 case DW_AT_vtable_elem_location:
77 case DW_AT_string_length:
78 case DW_AT_use_location:
79 case DW_AT_frame_base:
80 case DW_AT_return_addr:
81 case DW_AT_static_link:
82 case DW_AT_segment:
83 case DW_AT_GNU_call_site_value:
84 case DW_AT_GNU_call_site_data_value:
85 case DW_AT_GNU_call_site_target:
86 case DW_AT_GNU_call_site_target_clobbered:
87 break;
88
89 default:
90 __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
91 return false;
92 }
93
94 return true;
95 }
96
97
98 struct loclist
99 {
100 uint8_t atom;
101 Dwarf_Word number;
102 Dwarf_Word number2;
103 Dwarf_Word offset;
104 struct loclist *next;
105 };
106
107
108 static int
loc_compare(const void * p1,const void * p2)109 loc_compare (const void *p1, const void *p2)
110 {
111 const struct loc_s *l1 = (const struct loc_s *) p1;
112 const struct loc_s *l2 = (const struct loc_s *) p2;
113
114 if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
115 return -1;
116 if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
117 return 1;
118
119 return 0;
120 }
121
122 /* For each DW_OP_implicit_value, we store a special entry in the cache.
123 This points us directly to the block data for later fetching.
124 Returns zero on success, -1 on bad DWARF or 1 if tsearch failed. */
125 static int
store_implicit_value(Dwarf * dbg,void ** cache,Dwarf_Op * op)126 store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
127 {
128 if (dbg == NULL)
129 return -1;
130 struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
131 sizeof (struct loc_block_s), 1);
132 const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
133 uint64_t len = __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
134 if (unlikely (len != op->number))
135 return -1;
136 block->addr = op;
137 block->data = (unsigned char *) data;
138 block->length = op->number;
139 if (unlikely (tsearch (block, cache, loc_compare) == NULL))
140 return 1;
141 return 0;
142 }
143
144 int
dwarf_getlocation_implicit_value(Dwarf_Attribute * attr,const Dwarf_Op * op,Dwarf_Block * return_block)145 dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
146 Dwarf_Block *return_block)
147 {
148 if (attr == NULL)
149 return -1;
150
151 struct loc_block_s fake = { .addr = (void *) op };
152 struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
153 if (unlikely (found == NULL))
154 {
155 __libdw_seterrno (DWARF_E_NO_BLOCK);
156 return -1;
157 }
158
159 return_block->length = (*found)->length;
160 return_block->data = (*found)->data;
161 return 0;
162 }
163
164 /* DW_AT_data_member_location can be a constant as well as a loclistptr.
165 Only data[48] indicate a loclistptr. */
166 static int
check_constant_offset(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)167 check_constant_offset (Dwarf_Attribute *attr,
168 Dwarf_Op **llbuf, size_t *listlen)
169 {
170 if (attr->code != DW_AT_data_member_location)
171 return 1;
172
173 switch (attr->form)
174 {
175 /* Punt for any non-constant form. */
176 default:
177 return 1;
178
179 /* Note, we don't regard DW_FORM_data16 as a constant form,
180 even though technically it is according to the standard. */
181 case DW_FORM_data1:
182 case DW_FORM_data2:
183 case DW_FORM_data4:
184 case DW_FORM_data8:
185 case DW_FORM_sdata:
186 case DW_FORM_udata:
187 break;
188 }
189
190 /* Check whether we already cached this location. */
191 struct loc_s fake = { .addr = attr->valp };
192 struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
193
194 if (found == NULL)
195 {
196 Dwarf_Word offset;
197 if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
198 return -1;
199
200 Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
201 Dwarf_Op, sizeof (Dwarf_Op), 1);
202
203 result->atom = DW_OP_plus_uconst;
204 result->number = offset;
205 result->number2 = 0;
206 result->offset = 0;
207
208 /* Insert a record in the search tree so we can find it again later. */
209 struct loc_s *newp = libdw_alloc (attr->cu->dbg,
210 struct loc_s, sizeof (struct loc_s),
211 1);
212 newp->addr = attr->valp;
213 newp->loc = result;
214 newp->nloc = 1;
215
216 found = tsearch (newp, &attr->cu->locs, loc_compare);
217 }
218
219 assert ((*found)->nloc == 1);
220
221 if (llbuf != NULL)
222 {
223 *llbuf = (*found)->loc;
224 *listlen = 1;
225 }
226
227 return 0;
228 }
229
230 int
231 internal_function
__libdw_intern_expression(Dwarf * dbg,bool other_byte_order,unsigned int address_size,unsigned int ref_size,void ** cache,const Dwarf_Block * block,bool cfap,bool valuep,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)232 __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
233 unsigned int address_size, unsigned int ref_size,
234 void **cache, const Dwarf_Block *block,
235 bool cfap, bool valuep,
236 Dwarf_Op **llbuf, size_t *listlen, int sec_index)
237 {
238 /* Empty location expressions don't have any ops to intern. */
239 if (block->length == 0)
240 {
241 *listlen = 0;
242 return 0;
243 }
244
245 /* Check whether we already looked at this list. */
246 struct loc_s fake = { .addr = block->data };
247 struct loc_s **found = tfind (&fake, cache, loc_compare);
248 if (found != NULL)
249 {
250 /* We already saw it. */
251 *llbuf = (*found)->loc;
252 *listlen = (*found)->nloc;
253
254 if (valuep)
255 {
256 assert (*listlen > 1);
257 assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
258 }
259
260 return 0;
261 }
262
263 const unsigned char *data = block->data;
264 const unsigned char *const end_data = data + block->length;
265
266 const struct { bool other_byte_order; } bo = { other_byte_order };
267
268 struct loclist *loclist = NULL;
269 unsigned int n = 0;
270
271 /* Stack allocate at most this many locs. */
272 #define MAX_STACK_LOCS 256
273 struct loclist stack_locs[MAX_STACK_LOCS];
274 #define NEW_LOC() ({ struct loclist *ll; \
275 ll = (likely (n < MAX_STACK_LOCS) \
276 ? &stack_locs[n] \
277 : malloc (sizeof (struct loclist))); \
278 if (unlikely (ll == NULL)) \
279 goto nomem; \
280 n++; \
281 ll->next = loclist; \
282 loclist = ll; \
283 ll; })
284
285 if (cfap)
286 {
287 /* Synthesize the operation to push the CFA before the expression. */
288 struct loclist *newloc = NEW_LOC ();
289 newloc->atom = DW_OP_call_frame_cfa;
290 newloc->number = 0;
291 newloc->number2 = 0;
292 newloc->offset = -1;
293 }
294
295 /* Decode the opcodes. It is possible in some situations to have a
296 block of size zero. */
297 while (data < end_data)
298 {
299 struct loclist *newloc;
300 newloc = NEW_LOC ();
301 newloc->number = 0;
302 newloc->number2 = 0;
303 newloc->offset = data - block->data;
304
305 switch ((newloc->atom = *data++))
306 {
307 case DW_OP_addr:
308 /* Address, depends on address size of CU. */
309 if (dbg == NULL)
310 {
311 // XXX relocation?
312 if (address_size == 4)
313 {
314 if (unlikely (data + 4 > end_data))
315 goto invalid;
316 else
317 newloc->number = read_4ubyte_unaligned_inc (&bo, data);
318 }
319 else
320 {
321 if (unlikely (data + 8 > end_data))
322 goto invalid;
323 else
324 newloc->number = read_8ubyte_unaligned_inc (&bo, data);
325 }
326 }
327 else if (__libdw_read_address_inc (dbg, sec_index, &data,
328 address_size, &newloc->number))
329 goto invalid;
330 break;
331
332 case DW_OP_call_ref:
333 case DW_OP_GNU_variable_value:
334 /* DW_FORM_ref_addr, depends on offset size of CU. */
335 if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
336 ref_size,
337 &newloc->number,
338 IDX_debug_info, 0))
339 goto invalid;
340 break;
341
342 case DW_OP_deref:
343 case DW_OP_dup:
344 case DW_OP_drop:
345 case DW_OP_over:
346 case DW_OP_swap:
347 case DW_OP_rot:
348 case DW_OP_xderef:
349 case DW_OP_abs:
350 case DW_OP_and:
351 case DW_OP_div:
352 case DW_OP_minus:
353 case DW_OP_mod:
354 case DW_OP_mul:
355 case DW_OP_neg:
356 case DW_OP_not:
357 case DW_OP_or:
358 case DW_OP_plus:
359 case DW_OP_shl:
360 case DW_OP_shr:
361 case DW_OP_shra:
362 case DW_OP_xor:
363 case DW_OP_eq:
364 case DW_OP_ge:
365 case DW_OP_gt:
366 case DW_OP_le:
367 case DW_OP_lt:
368 case DW_OP_ne:
369 case DW_OP_lit0 ... DW_OP_lit31:
370 case DW_OP_reg0 ... DW_OP_reg31:
371 case DW_OP_nop:
372 case DW_OP_push_object_address:
373 case DW_OP_call_frame_cfa:
374 case DW_OP_form_tls_address:
375 case DW_OP_GNU_push_tls_address:
376 case DW_OP_stack_value:
377 /* No operand. */
378 break;
379
380 case DW_OP_const1u:
381 case DW_OP_pick:
382 case DW_OP_deref_size:
383 case DW_OP_xderef_size:
384 if (unlikely (data >= end_data))
385 {
386 invalid:
387 __libdw_seterrno (DWARF_E_INVALID_DWARF);
388 returnmem:
389 /* Free any dynamicly allocated loclists, if any. */
390 while (n > MAX_STACK_LOCS)
391 {
392 struct loclist *loc = loclist;
393 loclist = loc->next;
394 free (loc);
395 n--;
396 }
397 return -1;
398 }
399
400 newloc->number = *data++;
401 break;
402
403 case DW_OP_const1s:
404 if (unlikely (data >= end_data))
405 goto invalid;
406
407 newloc->number = *((int8_t *) data);
408 ++data;
409 break;
410
411 case DW_OP_const2u:
412 if (unlikely (data + 2 > end_data))
413 goto invalid;
414
415 newloc->number = read_2ubyte_unaligned_inc (&bo, data);
416 break;
417
418 case DW_OP_const2s:
419 case DW_OP_skip:
420 case DW_OP_bra:
421 case DW_OP_call2:
422 if (unlikely (data + 2 > end_data))
423 goto invalid;
424
425 newloc->number = read_2sbyte_unaligned_inc (&bo, data);
426 break;
427
428 case DW_OP_const4u:
429 if (unlikely (data + 4 > end_data))
430 goto invalid;
431
432 newloc->number = read_4ubyte_unaligned_inc (&bo, data);
433 break;
434
435 case DW_OP_const4s:
436 case DW_OP_call4:
437 case DW_OP_GNU_parameter_ref:
438 if (unlikely (data + 4 > end_data))
439 goto invalid;
440
441 newloc->number = read_4sbyte_unaligned_inc (&bo, data);
442 break;
443
444 case DW_OP_const8u:
445 if (unlikely (data + 8 > end_data))
446 goto invalid;
447
448 newloc->number = read_8ubyte_unaligned_inc (&bo, data);
449 break;
450
451 case DW_OP_const8s:
452 if (unlikely (data + 8 > end_data))
453 goto invalid;
454
455 newloc->number = read_8sbyte_unaligned_inc (&bo, data);
456 break;
457
458 case DW_OP_constu:
459 case DW_OP_plus_uconst:
460 case DW_OP_regx:
461 case DW_OP_piece:
462 case DW_OP_convert:
463 case DW_OP_GNU_convert:
464 case DW_OP_reinterpret:
465 case DW_OP_GNU_reinterpret:
466 case DW_OP_addrx:
467 case DW_OP_GNU_addr_index:
468 case DW_OP_constx:
469 case DW_OP_GNU_const_index:
470 get_uleb128 (newloc->number, data, end_data);
471 break;
472
473 case DW_OP_consts:
474 case DW_OP_breg0 ... DW_OP_breg31:
475 case DW_OP_fbreg:
476 get_sleb128 (newloc->number, data, end_data);
477 break;
478
479 case DW_OP_bregx:
480 get_uleb128 (newloc->number, data, end_data);
481 if (unlikely (data >= end_data))
482 goto invalid;
483 get_sleb128 (newloc->number2, data, end_data);
484 break;
485
486 case DW_OP_bit_piece:
487 case DW_OP_regval_type:
488 case DW_OP_GNU_regval_type:
489 get_uleb128 (newloc->number, data, end_data);
490 if (unlikely (data >= end_data))
491 goto invalid;
492 get_uleb128 (newloc->number2, data, end_data);
493 break;
494
495 case DW_OP_implicit_value:
496 case DW_OP_entry_value:
497 case DW_OP_GNU_entry_value:
498 /* This cannot be used in a CFI expression. */
499 if (unlikely (dbg == NULL))
500 goto invalid;
501
502 /* start of block inc. len. */
503 newloc->number2 = (Dwarf_Word) (uintptr_t) data;
504 get_uleb128 (newloc->number, data, end_data); /* Block length. */
505 if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
506 goto invalid;
507 data += newloc->number; /* Skip the block. */
508 break;
509
510 case DW_OP_implicit_pointer:
511 case DW_OP_GNU_implicit_pointer:
512 /* DW_FORM_ref_addr, depends on offset size of CU. */
513 if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
514 ref_size,
515 &newloc->number,
516 IDX_debug_info, 0))
517 goto invalid;
518 if (unlikely (data >= end_data))
519 goto invalid;
520 get_uleb128 (newloc->number2, data, end_data); /* Byte offset. */
521 break;
522
523 case DW_OP_deref_type:
524 case DW_OP_GNU_deref_type:
525 case DW_OP_xderef_type:
526 if (unlikely (data + 1 >= end_data))
527 goto invalid;
528 newloc->number = *data++;
529 get_uleb128 (newloc->number2, data, end_data);
530 break;
531
532 case DW_OP_const_type:
533 case DW_OP_GNU_const_type:
534 {
535 size_t size;
536 get_uleb128 (newloc->number, data, end_data);
537 if (unlikely (data >= end_data))
538 goto invalid;
539
540 /* start of block inc. len. */
541 newloc->number2 = (Dwarf_Word) (uintptr_t) data;
542 size = *data++;
543 if (unlikely ((Dwarf_Word) (end_data - data) < size))
544 goto invalid;
545 data += size; /* Skip the block. */
546 }
547 break;
548
549 default:
550 goto invalid;
551 }
552 }
553
554 if (unlikely (n == 0))
555 {
556 /* This is not allowed.
557 It would mean an empty location expression, which we handled
558 already as a special case above. */
559 goto invalid;
560 }
561
562 if (valuep)
563 {
564 struct loclist *newloc = NEW_LOC ();
565 newloc->atom = DW_OP_stack_value;
566 newloc->number = 0;
567 newloc->number2 = 0;
568 newloc->offset = data - block->data;
569 }
570
571 /* Allocate the array. */
572 Dwarf_Op *result;
573 if (dbg != NULL)
574 result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
575 else
576 {
577 result = malloc (sizeof *result * n);
578 if (result == NULL)
579 {
580 nomem:
581 __libdw_seterrno (DWARF_E_NOMEM);
582 goto returnmem;
583 }
584 }
585
586 /* Store the result. */
587 *llbuf = result;
588 *listlen = n;
589
590 do
591 {
592 /* We populate the array from the back since the list is backwards. */
593 --n;
594 result[n].atom = loclist->atom;
595 result[n].number = loclist->number;
596 result[n].number2 = loclist->number2;
597 result[n].offset = loclist->offset;
598
599 if (result[n].atom == DW_OP_implicit_value)
600 {
601 int store = store_implicit_value (dbg, cache, &result[n]);
602 if (unlikely (store != 0))
603 {
604 if (store < 0)
605 goto invalid;
606 else
607 goto nomem;
608 }
609 }
610
611 struct loclist *loc = loclist;
612 loclist = loclist->next;
613 if (unlikely (n + 1 > MAX_STACK_LOCS))
614 free (loc);
615 }
616 while (n > 0);
617
618 /* Insert a record in the search tree so that we can find it again later. */
619 struct loc_s *newp;
620 if (dbg != NULL)
621 newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
622 else
623 {
624 newp = malloc (sizeof *newp);
625 if (newp == NULL)
626 {
627 free (result);
628 goto nomem;
629 }
630 }
631
632 newp->addr = block->data;
633 newp->loc = result;
634 newp->nloc = *listlen;
635 (void) tsearch (newp, cache, loc_compare);
636
637 /* We did it. */
638 return 0;
639 }
640
641 static int
getlocation(struct Dwarf_CU * cu,const Dwarf_Block * block,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)642 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
643 Dwarf_Op **llbuf, size_t *listlen, int sec_index)
644 {
645 /* Empty location expressions don't have any ops to intern.
646 Note that synthetic empty_cu doesn't have an associated DWARF dbg. */
647 if (block->length == 0)
648 {
649 *listlen = 0;
650 return 0;
651 }
652
653 return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
654 cu->address_size, (cu->version == 2
655 ? cu->address_size
656 : cu->offset_size),
657 &cu->locs, block,
658 false, false,
659 llbuf, listlen, sec_index);
660 }
661
662 int
dwarf_getlocation(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)663 dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
664 {
665 if (! attr_ok (attr))
666 return -1;
667
668 int result = check_constant_offset (attr, llbuf, listlen);
669 if (result != 1)
670 return result;
671
672 /* If it has a block form, it's a single location expression.
673 Except for DW_FORM_data16, which is a 128bit constant. */
674 if (attr->form == DW_FORM_data16)
675 {
676 __libdw_seterrno (DWARF_E_NO_BLOCK);
677 return -1;
678 }
679 Dwarf_Block block;
680 if (INTUSE(dwarf_formblock) (attr, &block) != 0)
681 return -1;
682
683 return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
684 }
685
686 Dwarf_Addr
__libdw_cu_base_address(Dwarf_CU * cu)687 __libdw_cu_base_address (Dwarf_CU *cu)
688 {
689 if (cu->base_address == (Dwarf_Addr) -1)
690 {
691 Dwarf_Addr base;
692
693 /* Fetch the CU's base address. */
694 Dwarf_Die cudie = CUDIE (cu);
695
696 /* Find the base address of the compilation unit. It will
697 normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
698 the base address could be overridden by DW_AT_entry_pc. It's
699 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
700 for compilation units with discontinuous ranges. */
701 Dwarf_Attribute attr_mem;
702 if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
703 && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
704 DW_AT_entry_pc,
705 &attr_mem),
706 &base) != 0)
707 {
708 /* The compiler provided no base address when it should
709 have. Buggy GCC does this when it used absolute
710 addresses in the location list and no DW_AT_ranges. */
711 base = 0;
712 }
713 cu->base_address = base;
714 }
715
716 return cu->base_address;
717 }
718
719 static int
initial_offset(Dwarf_Attribute * attr,ptrdiff_t * offset)720 initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
721 {
722 size_t secidx = (attr->cu->version < 5
723 ? IDX_debug_loc : IDX_debug_loclists);
724
725 Dwarf_Word start_offset;
726 if (attr->form == DW_FORM_loclistx)
727 {
728 Dwarf_Word idx;
729 Dwarf_CU *cu = attr->cu;
730 const unsigned char *datap = attr->valp;
731 const unsigned char *endp = cu->endp;
732 if (datap >= endp)
733 {
734 __libdw_seterrno (DWARF_E_INVALID_DWARF);
735 return -1;
736 }
737 get_uleb128 (idx, datap, endp);
738
739 Elf_Data *data = cu->dbg->sectiondata[secidx];
740 if (data == NULL && cu->unit_type == DW_UT_split_compile)
741 {
742 cu = __libdw_find_split_unit (cu);
743 if (cu != NULL)
744 data = cu->dbg->sectiondata[secidx];
745 }
746
747 if (data == NULL)
748 {
749 __libdw_seterrno (secidx == IDX_debug_loc
750 ? DWARF_E_NO_DEBUG_LOC
751 : DWARF_E_NO_DEBUG_LOCLISTS);
752 return -1;
753 }
754
755 Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
756
757 /* The section should at least contain room for one offset. */
758 size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
759 size_t offset_size = cu->offset_size;
760 if (offset_size > sec_size)
761 {
762 invalid_offset:
763 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
764 return -1;
765 }
766
767 /* And the base offset should be at least inside the section. */
768 if (loc_base_off > (sec_size - offset_size))
769 goto invalid_offset;
770
771 size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
772 if (idx > max_idx)
773 goto invalid_offset;
774
775 datap = (cu->dbg->sectiondata[secidx]->d_buf
776 + loc_base_off + (idx * offset_size));
777 if (offset_size == 4)
778 start_offset = read_4ubyte_unaligned (cu->dbg, datap);
779 else
780 start_offset = read_8ubyte_unaligned (cu->dbg, datap);
781
782 start_offset += loc_base_off;
783 }
784 else
785 {
786 if (__libdw_formptr (attr, secidx,
787 (secidx == IDX_debug_loc
788 ? DWARF_E_NO_DEBUG_LOC
789 : DWARF_E_NO_DEBUG_LOCLISTS),
790 NULL, &start_offset) == NULL)
791 return -1;
792 }
793
794 *offset = start_offset;
795 return 0;
796 }
797
798 static ptrdiff_t
getlocations_addr(Dwarf_Attribute * attr,ptrdiff_t offset,Dwarf_Addr * basep,Dwarf_Addr * startp,Dwarf_Addr * endp,Dwarf_Addr address,const Elf_Data * locs,Dwarf_Op ** expr,size_t * exprlen)799 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
800 Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
801 Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
802 size_t *exprlen)
803 {
804 Dwarf_CU *cu = attr->cu;
805 Dwarf *dbg = cu->dbg;
806 size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
807 const unsigned char *readp = locs->d_buf + offset;
808 const unsigned char *readendp = locs->d_buf + locs->d_size;
809
810 Dwarf_Addr begin;
811 Dwarf_Addr end;
812
813 next:
814 switch (__libdw_read_begin_end_pair_inc (cu, secidx,
815 &readp, readendp,
816 cu->address_size,
817 &begin, &end, basep))
818 {
819 case 0: /* got location range. */
820 break;
821 case 1: /* base address setup. */
822 goto next;
823 case 2: /* end of loclist */
824 return 0;
825 default: /* error */
826 return -1;
827 }
828
829 /* We have a location expression. */
830 Dwarf_Block block;
831 if (secidx == IDX_debug_loc)
832 {
833 if (readendp - readp < 2)
834 {
835 invalid:
836 __libdw_seterrno (DWARF_E_INVALID_DWARF);
837 return -1;
838 }
839 block.length = read_2ubyte_unaligned_inc (dbg, readp);
840 }
841 else
842 {
843 if (readendp - readp < 1)
844 goto invalid;
845 get_uleb128 (block.length, readp, readendp);
846 }
847 block.data = (unsigned char *) readp;
848 if (readendp - readp < (ptrdiff_t) block.length)
849 goto invalid;
850 readp += block.length;
851
852 /* Note these addresses include any base (if necessary) already. */
853 *startp = begin;
854 *endp = end;
855
856 /* If address is minus one we want them all, otherwise only matching. */
857 if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
858 goto next;
859
860 if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
861 return -1;
862
863 return readp - (unsigned char *) locs->d_buf;
864 }
865
866 int
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)867 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
868 Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
869 {
870 if (! attr_ok (attr))
871 return -1;
872
873 if (llbufs == NULL)
874 maxlocs = SIZE_MAX;
875
876 /* If it has a block form, it's a single location expression.
877 Except for DW_FORM_data16, which is a 128bit constant. */
878 Dwarf_Block block;
879 if (attr->form != DW_FORM_data16
880 && INTUSE(dwarf_formblock) (attr, &block) == 0)
881 {
882 if (maxlocs == 0)
883 return 0;
884 if (llbufs != NULL &&
885 getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
886 cu_sec_idx (attr->cu)) != 0)
887 return -1;
888 return listlens[0] == 0 ? 0 : 1;
889 }
890
891 if (attr->form != DW_FORM_data16)
892 {
893 int error = INTUSE(dwarf_errno) ();
894 if (unlikely (error != DWARF_E_NO_BLOCK))
895 {
896 __libdw_seterrno (error);
897 return -1;
898 }
899 }
900
901 int result = check_constant_offset (attr, llbufs, listlens);
902 if (result != 1)
903 return result ?: 1;
904
905 Dwarf_Addr base, start, end;
906 Dwarf_Op *expr;
907 size_t expr_len;
908 ptrdiff_t off = 0;
909 size_t got = 0;
910
911 /* This is a true loclistptr, fetch the initial base address and offset. */
912 base = __libdw_cu_base_address (attr->cu);
913 if (base == (Dwarf_Addr) -1)
914 return -1;
915
916 if (initial_offset (attr, &off) != 0)
917 return -1;
918
919 size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
920 const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
921
922 while (got < maxlocs
923 && (off = getlocations_addr (attr, off, &base, &start, &end,
924 address, d, &expr, &expr_len)) > 0)
925 {
926 /* This one matches the address. */
927 if (llbufs != NULL)
928 {
929 llbufs[got] = expr;
930 listlens[got] = expr_len;
931 }
932 ++got;
933 }
934
935 /* We might stop early, so off can be zero or positive on success. */
936 if (off < 0)
937 return -1;
938
939 return got;
940 }
941
942 ptrdiff_t
dwarf_getlocations(Dwarf_Attribute * attr,ptrdiff_t offset,Dwarf_Addr * basep,Dwarf_Addr * startp,Dwarf_Addr * endp,Dwarf_Op ** expr,size_t * exprlen)943 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
944 Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
945 size_t *exprlen)
946 {
947 if (! attr_ok (attr))
948 return -1;
949
950 /* 1 is an invalid offset, meaning no more locations. */
951 if (offset == 1)
952 return 0;
953
954 if (offset == 0)
955 {
956 /* If it has a block form, it's a single location expression.
957 Except for DW_FORM_data16, which is a 128bit constant. */
958 Dwarf_Block block;
959 if (attr->form != DW_FORM_data16
960 && INTUSE(dwarf_formblock) (attr, &block) == 0)
961 {
962 if (getlocation (attr->cu, &block, expr, exprlen,
963 cu_sec_idx (attr->cu)) != 0)
964 return -1;
965
966 /* This is the one and only location covering everything. */
967 *startp = 0;
968 *endp = -1;
969 return 1;
970 }
971
972 if (attr->form != DW_FORM_data16)
973 {
974 int error = INTUSE(dwarf_errno) ();
975 if (unlikely (error != DWARF_E_NO_BLOCK))
976 {
977 __libdw_seterrno (error);
978 return -1;
979 }
980 }
981
982 int result = check_constant_offset (attr, expr, exprlen);
983 if (result != 1)
984 {
985 if (result == 0)
986 {
987 /* This is the one and only location covering everything. */
988 *startp = 0;
989 *endp = -1;
990 return 1;
991 }
992 return result;
993 }
994
995 /* We must be looking at a true loclistptr, fetch the initial
996 base address and offset. */
997 *basep = __libdw_cu_base_address (attr->cu);
998 if (*basep == (Dwarf_Addr) -1)
999 return -1;
1000
1001 if (initial_offset (attr, &offset) != 0)
1002 return -1;
1003 }
1004
1005 size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1006 const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1007
1008 return getlocations_addr (attr, offset, basep, startp, endp,
1009 (Dwarf_Word) -1, d, expr, exprlen);
1010 }
1011