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