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