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 case DW_OP_GNU_uninit:
400 /* No operand. */
401 break;
402
403 case DW_OP_const1u:
404 case DW_OP_pick:
405 case DW_OP_deref_size:
406 case DW_OP_xderef_size:
407 if (unlikely (data >= end_data))
408 {
409 invalid:
410 __libdw_seterrno (DWARF_E_INVALID_DWARF);
411 returnmem:
412 /* Free any dynamically allocated loclists, if any. */
413 while (n > MAX_STACK_LOCS)
414 {
415 struct loclist *loc = loclist;
416 loclist = loc->next;
417 free (loc);
418 n--;
419 }
420 return -1;
421 }
422
423 newloc->number = *data++;
424 break;
425
426 case DW_OP_const1s:
427 if (unlikely (data >= end_data))
428 goto invalid;
429
430 newloc->number = *((int8_t *) data);
431 ++data;
432 break;
433
434 case DW_OP_const2u:
435 if (unlikely (data + 2 > end_data))
436 goto invalid;
437
438 newloc->number = read_2ubyte_unaligned_inc (&bo, data);
439 break;
440
441 case DW_OP_const2s:
442 case DW_OP_skip:
443 case DW_OP_bra:
444 case DW_OP_call2:
445 if (unlikely (data + 2 > end_data))
446 goto invalid;
447
448 newloc->number = read_2sbyte_unaligned_inc (&bo, data);
449 break;
450
451 case DW_OP_const4u:
452 if (unlikely (data + 4 > end_data))
453 goto invalid;
454
455 newloc->number = read_4ubyte_unaligned_inc (&bo, data);
456 break;
457
458 case DW_OP_const4s:
459 case DW_OP_call4:
460 case DW_OP_GNU_parameter_ref:
461 if (unlikely (data + 4 > end_data))
462 goto invalid;
463
464 newloc->number = read_4sbyte_unaligned_inc (&bo, data);
465 break;
466
467 case DW_OP_const8u:
468 if (unlikely (data + 8 > end_data))
469 goto invalid;
470
471 newloc->number = read_8ubyte_unaligned_inc (&bo, data);
472 break;
473
474 case DW_OP_const8s:
475 if (unlikely (data + 8 > end_data))
476 goto invalid;
477
478 newloc->number = read_8sbyte_unaligned_inc (&bo, data);
479 break;
480
481 case DW_OP_constu:
482 case DW_OP_plus_uconst:
483 case DW_OP_regx:
484 case DW_OP_piece:
485 case DW_OP_convert:
486 case DW_OP_GNU_convert:
487 case DW_OP_reinterpret:
488 case DW_OP_GNU_reinterpret:
489 case DW_OP_addrx:
490 case DW_OP_GNU_addr_index:
491 case DW_OP_constx:
492 case DW_OP_GNU_const_index:
493 get_uleb128 (newloc->number, data, end_data);
494 break;
495
496 case DW_OP_consts:
497 case DW_OP_breg0 ... DW_OP_breg31:
498 case DW_OP_fbreg:
499 get_sleb128 (newloc->number, data, end_data);
500 break;
501
502 case DW_OP_bregx:
503 get_uleb128 (newloc->number, data, end_data);
504 if (unlikely (data >= end_data))
505 goto invalid;
506 get_sleb128 (newloc->number2, data, end_data);
507 break;
508
509 case DW_OP_bit_piece:
510 case DW_OP_regval_type:
511 case DW_OP_GNU_regval_type:
512 get_uleb128 (newloc->number, data, end_data);
513 if (unlikely (data >= end_data))
514 goto invalid;
515 get_uleb128 (newloc->number2, data, end_data);
516 break;
517
518 case DW_OP_implicit_value:
519 case DW_OP_entry_value:
520 case DW_OP_GNU_entry_value:
521 /* This cannot be used in a CFI expression. */
522 if (unlikely (dbg == NULL))
523 goto invalid;
524
525 /* start of block inc. len. */
526 newloc->number2 = (Dwarf_Word) (uintptr_t) data;
527 get_uleb128 (newloc->number, data, end_data); /* Block length. */
528 if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
529 goto invalid;
530 data += newloc->number; /* Skip the block. */
531 break;
532
533 case DW_OP_implicit_pointer:
534 case DW_OP_GNU_implicit_pointer:
535 /* DW_FORM_ref_addr, depends on offset size of CU. */
536 if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
537 ref_size,
538 &newloc->number,
539 IDX_debug_info, 0))
540 goto invalid;
541 if (unlikely (data >= end_data))
542 goto invalid;
543 get_uleb128 (newloc->number2, data, end_data); /* Byte offset. */
544 break;
545
546 case DW_OP_deref_type:
547 case DW_OP_GNU_deref_type:
548 case DW_OP_xderef_type:
549 if (unlikely (data + 1 >= end_data))
550 goto invalid;
551 newloc->number = *data++;
552 get_uleb128 (newloc->number2, data, end_data);
553 break;
554
555 case DW_OP_const_type:
556 case DW_OP_GNU_const_type:
557 {
558 size_t size;
559 get_uleb128 (newloc->number, data, end_data);
560 if (unlikely (data >= end_data))
561 goto invalid;
562
563 /* start of block inc. len. */
564 newloc->number2 = (Dwarf_Word) (uintptr_t) data;
565 size = *data++;
566 if (unlikely ((Dwarf_Word) (end_data - data) < size))
567 goto invalid;
568 data += size; /* Skip the block. */
569 }
570 break;
571
572 default:
573 goto invalid;
574 }
575 }
576
577 if (unlikely (n == 0))
578 {
579 /* This is not allowed.
580 It would mean an empty location expression, which we handled
581 already as a special case above. */
582 goto invalid;
583 }
584
585 if (valuep)
586 {
587 struct loclist *newloc = NEW_LOC ();
588 newloc->atom = DW_OP_stack_value;
589 newloc->number = 0;
590 newloc->number2 = 0;
591 newloc->offset = data - block->data;
592 }
593
594 /* Allocate the array. */
595 Dwarf_Op *result;
596 if (dbg != NULL)
597 result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
598 else
599 {
600 result = malloc (sizeof *result * n);
601 if (result == NULL)
602 {
603 nomem:
604 __libdw_seterrno (DWARF_E_NOMEM);
605 goto returnmem;
606 }
607 }
608
609 /* Store the result. */
610 *llbuf = result;
611 *listlen = n;
612
613 do
614 {
615 /* We populate the array from the back since the list is backwards. */
616 --n;
617 result[n].atom = loclist->atom;
618 result[n].number = loclist->number;
619 result[n].number2 = loclist->number2;
620 result[n].offset = loclist->offset;
621
622 if (result[n].atom == DW_OP_implicit_value)
623 {
624 int store = store_implicit_value (dbg, cache, &result[n]);
625 if (unlikely (store != 0))
626 {
627 if (store < 0)
628 goto invalid;
629 else
630 goto nomem;
631 }
632 }
633
634 struct loclist *loc = loclist;
635 loclist = loclist->next;
636 if (unlikely (n + 1 > MAX_STACK_LOCS))
637 free (loc);
638 }
639 while (n > 0);
640
641 /* Insert a record in the search tree so that we can find it again later. */
642 struct loc_s *newp;
643 if (dbg != NULL)
644 newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
645 else
646 {
647 newp = malloc (sizeof *newp);
648 if (newp == NULL)
649 {
650 free (result);
651 goto nomem;
652 }
653 }
654
655 newp->addr = block->data;
656 newp->loc = result;
657 newp->nloc = *listlen;
658 (void) tsearch (newp, cache, loc_compare);
659
660 /* We did it. */
661 return 0;
662 }
663
664 static int
getlocation(struct Dwarf_CU * cu,const Dwarf_Block * block,Dwarf_Op ** llbuf,size_t * listlen,int sec_index)665 getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
666 Dwarf_Op **llbuf, size_t *listlen, int sec_index)
667 {
668 /* Empty location expressions don't have any ops to intern.
669 Note that synthetic empty_cu doesn't have an associated DWARF dbg. */
670 if (block->length == 0)
671 {
672 *listlen = 0;
673 return 0;
674 }
675
676 return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
677 cu->address_size, (cu->version == 2
678 ? cu->address_size
679 : cu->offset_size),
680 &cu->locs, block,
681 false, false,
682 llbuf, listlen, sec_index);
683 }
684
685 int
dwarf_getlocation(Dwarf_Attribute * attr,Dwarf_Op ** llbuf,size_t * listlen)686 dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
687 {
688 if (! attr_ok (attr))
689 return -1;
690
691 int result = is_constant_offset (attr, llbuf, listlen);
692 if (result != 1)
693 return result; /* Either success 0, or -1 to indicate error. */
694
695 /* If it has a block form, it's a single location expression.
696 Except for DW_FORM_data16, which is a 128bit constant. */
697 if (attr->form == DW_FORM_data16)
698 {
699 __libdw_seterrno (DWARF_E_NO_BLOCK);
700 return -1;
701 }
702 Dwarf_Block block;
703 if (INTUSE(dwarf_formblock) (attr, &block) != 0)
704 return -1;
705
706 return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
707 }
708
709 Dwarf_Addr
__libdw_cu_base_address(Dwarf_CU * cu)710 __libdw_cu_base_address (Dwarf_CU *cu)
711 {
712 if (cu->base_address == (Dwarf_Addr) -1)
713 {
714 Dwarf_Addr base;
715
716 /* Fetch the CU's base address. */
717 Dwarf_Die cudie = CUDIE (cu);
718
719 /* Find the base address of the compilation unit. It will
720 normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
721 the base address could be overridden by DW_AT_entry_pc. It's
722 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
723 for compilation units with discontinuous ranges. */
724 Dwarf_Attribute attr_mem;
725 if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
726 && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
727 DW_AT_entry_pc,
728 &attr_mem),
729 &base) != 0)
730 {
731 /* The compiler provided no base address when it should
732 have. Buggy GCC does this when it used absolute
733 addresses in the location list and no DW_AT_ranges. */
734 base = 0;
735 }
736 cu->base_address = base;
737 }
738
739 return cu->base_address;
740 }
741
742 static int
initial_offset(Dwarf_Attribute * attr,ptrdiff_t * offset)743 initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
744 {
745 size_t secidx = (attr->cu->version < 5
746 ? IDX_debug_loc : IDX_debug_loclists);
747
748 Dwarf_Word start_offset;
749 if (attr->form == DW_FORM_loclistx)
750 {
751 Dwarf_Word idx;
752 Dwarf_CU *cu = attr->cu;
753 const unsigned char *datap = attr->valp;
754 const unsigned char *endp = cu->endp;
755 if (datap >= endp)
756 {
757 __libdw_seterrno (DWARF_E_INVALID_DWARF);
758 return -1;
759 }
760 get_uleb128 (idx, datap, endp);
761
762 Elf_Data *data = cu->dbg->sectiondata[secidx];
763 if (data == NULL && cu->unit_type == DW_UT_split_compile)
764 {
765 cu = __libdw_find_split_unit (cu);
766 if (cu != NULL)
767 data = cu->dbg->sectiondata[secidx];
768 }
769
770 if (data == NULL)
771 {
772 __libdw_seterrno (secidx == IDX_debug_loc
773 ? DWARF_E_NO_DEBUG_LOC
774 : DWARF_E_NO_DEBUG_LOCLISTS);
775 return -1;
776 }
777
778 Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
779
780 /* The section should at least contain room for one offset. */
781 size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
782 size_t offset_size = cu->offset_size;
783 if (offset_size > sec_size)
784 {
785 invalid_offset:
786 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
787 return -1;
788 }
789
790 /* And the base offset should be at least inside the section. */
791 if (loc_base_off > (sec_size - offset_size))
792 goto invalid_offset;
793
794 size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
795 if (idx > max_idx)
796 goto invalid_offset;
797
798 datap = (cu->dbg->sectiondata[secidx]->d_buf
799 + loc_base_off + (idx * offset_size));
800 if (offset_size == 4)
801 start_offset = read_4ubyte_unaligned (cu->dbg, datap);
802 else
803 start_offset = read_8ubyte_unaligned (cu->dbg, datap);
804
805 start_offset += loc_base_off;
806 }
807 else
808 {
809 if (__libdw_formptr (attr, secidx,
810 (secidx == IDX_debug_loc
811 ? DWARF_E_NO_DEBUG_LOC
812 : DWARF_E_NO_DEBUG_LOCLISTS),
813 NULL, &start_offset) == NULL)
814 return -1;
815
816 Dwarf_Off loc_off;
817 if (INTUSE(dwarf_cu_dwp_section_info) (attr->cu, DW_SECT_LOCLISTS,
818 &loc_off, NULL) != 0)
819 return -1;
820 start_offset += loc_off;
821 }
822
823 *offset = start_offset;
824 return 0;
825 }
826
827 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)828 getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
829 Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
830 Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
831 size_t *exprlen)
832 {
833 Dwarf_CU *cu = attr->cu;
834 Dwarf *dbg = cu->dbg;
835 size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
836 const unsigned char *readp = locs->d_buf + offset;
837 const unsigned char *readendp = locs->d_buf + locs->d_size;
838
839 Dwarf_Addr begin;
840 Dwarf_Addr end;
841
842 next:
843 switch (__libdw_read_begin_end_pair_inc (cu, secidx,
844 &readp, readendp,
845 cu->address_size,
846 &begin, &end, basep))
847 {
848 case 0: /* got location range. */
849 break;
850 case 1: /* base address setup. */
851 goto next;
852 case 2: /* end of loclist */
853 return 0;
854 default: /* error */
855 return -1;
856 }
857
858 /* We have a location expression. */
859 Dwarf_Block block;
860 if (secidx == IDX_debug_loc)
861 {
862 if (readendp - readp < 2)
863 {
864 invalid:
865 __libdw_seterrno (DWARF_E_INVALID_DWARF);
866 return -1;
867 }
868 block.length = read_2ubyte_unaligned_inc (dbg, readp);
869 }
870 else
871 {
872 if (readendp - readp < 1)
873 goto invalid;
874 get_uleb128 (block.length, readp, readendp);
875 }
876 block.data = (unsigned char *) readp;
877 if (readendp - readp < (ptrdiff_t) block.length)
878 goto invalid;
879 readp += block.length;
880
881 /* Note these addresses include any base (if necessary) already. */
882 *startp = begin;
883 *endp = end;
884
885 /* If address is minus one we want them all, otherwise only matching. */
886 if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
887 goto next;
888
889 if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
890 return -1;
891
892 return readp - (unsigned char *) locs->d_buf;
893 }
894
895 int
dwarf_getlocation_addr(Dwarf_Attribute * attr,Dwarf_Addr address,Dwarf_Op ** llbufs,size_t * listlens,size_t maxlocs)896 dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
897 Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
898 {
899 if (! attr_ok (attr))
900 return -1;
901
902 if (llbufs == NULL)
903 maxlocs = SIZE_MAX;
904
905 /* If it has a block form, it's a single location expression.
906 Except for DW_FORM_data16, which is a 128bit constant. */
907 Dwarf_Block block;
908 if (attr->form != DW_FORM_data16
909 && INTUSE(dwarf_formblock) (attr, &block) == 0)
910 {
911 if (maxlocs == 0)
912 return 0;
913 if (llbufs != NULL &&
914 getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
915 cu_sec_idx (attr->cu)) != 0)
916 return -1;
917 return listlens[0] == 0 ? 0 : 1;
918 }
919
920 if (attr->form != DW_FORM_data16)
921 {
922 int error = INTUSE(dwarf_errno) ();
923 if (unlikely (error != DWARF_E_NO_BLOCK))
924 {
925 __libdw_seterrno (error);
926 return -1;
927 }
928 }
929
930 /* If is_constant_offset is successful, we are done with 1 result. */
931 int result = is_constant_offset (attr, llbufs, listlens);
932 if (result != 1)
933 return result ?: 1;
934
935 Dwarf_Addr base, start, end;
936 Dwarf_Op *expr;
937 size_t expr_len;
938 ptrdiff_t off = 0;
939 size_t got = 0;
940
941 /* This is a true loclistptr, fetch the initial base address and offset. */
942 base = __libdw_cu_base_address (attr->cu);
943 if (base == (Dwarf_Addr) -1)
944 return -1;
945
946 if (initial_offset (attr, &off) != 0)
947 return -1;
948
949 size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
950 const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
951
952 while (got < maxlocs
953 && (off = getlocations_addr (attr, off, &base, &start, &end,
954 address, d, &expr, &expr_len)) > 0)
955 {
956 /* This one matches the address. */
957 if (llbufs != NULL)
958 {
959 llbufs[got] = expr;
960 listlens[got] = expr_len;
961 }
962 ++got;
963 }
964
965 /* We might stop early, so off can be zero or positive on success. */
966 if (off < 0)
967 return -1;
968
969 return got;
970 }
971
972 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)973 dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
974 Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
975 size_t *exprlen)
976 {
977 if (! attr_ok (attr))
978 return -1;
979
980 /* 1 is an invalid offset, meaning no more locations. */
981 if (offset == 1)
982 return 0;
983
984 if (offset == 0)
985 {
986 /* If it has a block form, it's a single location expression.
987 Except for DW_FORM_data16, which is a 128bit constant. */
988 Dwarf_Block block;
989 if (attr->form != DW_FORM_data16
990 && INTUSE(dwarf_formblock) (attr, &block) == 0)
991 {
992 if (getlocation (attr->cu, &block, expr, exprlen,
993 cu_sec_idx (attr->cu)) != 0)
994 return -1;
995
996 /* This is the one and only location covering everything. */
997 *startp = 0;
998 *endp = -1;
999 return 1;
1000 }
1001
1002 if (attr->form != DW_FORM_data16)
1003 {
1004 int error = INTUSE(dwarf_errno) ();
1005 if (unlikely (error != DWARF_E_NO_BLOCK))
1006 {
1007 __libdw_seterrno (error);
1008 return -1;
1009 }
1010 }
1011
1012 int result = is_constant_offset (attr, expr, exprlen);
1013 if (result != 1)
1014 {
1015 if (result == 0)
1016 {
1017 /* This is the one and only location covering everything. */
1018 *startp = 0;
1019 *endp = -1;
1020 return 1;
1021 }
1022 return result; /* Something bad, dwarf_errno has been set. */
1023 }
1024
1025 /* We must be looking at a true loclistptr, fetch the initial
1026 base address and offset. */
1027 *basep = __libdw_cu_base_address (attr->cu);
1028 if (*basep == (Dwarf_Addr) -1)
1029 return -1;
1030
1031 if (initial_offset (attr, &offset) != 0)
1032 return -1;
1033 }
1034
1035 size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1036 const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1037
1038 return getlocations_addr (attr, offset, basep, startp, endp,
1039 (Dwarf_Word) -1, d, expr, exprlen);
1040 }
1041