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