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