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 4057881 : attr_ok (Dwarf_Attribute *attr)
43 : {
44 4057881 : if (attr == NULL)
45 : return false;
46 :
47 : /* If it is an exprloc, it is obviously OK. */
48 4057881 : 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 3958406 : 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 3076516 : default:
90 3076516 : __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
91 3076516 : 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 13725444 : loc_compare (const void *p1, const void *p2)
110 : {
111 13725444 : const struct loc_s *l1 = (const struct loc_s *) p1;
112 13725444 : const struct loc_s *l2 = (const struct loc_s *) p2;
113 :
114 13725444 : if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
115 : return -1;
116 12702076 : if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
117 : return 1;
118 :
119 212580 : 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 214 : store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
127 : {
128 214 : struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
129 : sizeof (struct loc_block_s), 1);
130 214 : const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
131 214 : uint64_t len = __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
132 214 : if (unlikely (len != op->number))
133 : return -1;
134 214 : block->addr = op;
135 214 : block->data = (unsigned char *) data;
136 214 : block->length = op->number;
137 214 : if (unlikely (tsearch (block, cache, loc_compare) == NULL))
138 : return 1;
139 214 : return 0;
140 : }
141 :
142 : int
143 572 : dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
144 : Dwarf_Block *return_block)
145 : {
146 572 : if (attr == NULL)
147 : return -1;
148 :
149 572 : struct loc_block_s fake = { .addr = (void *) op };
150 572 : struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
151 572 : if (unlikely (found == NULL))
152 : {
153 0 : __libdw_seterrno (DWARF_E_NO_BLOCK);
154 0 : return -1;
155 : }
156 :
157 572 : return_block->length = (*found)->length;
158 572 : return_block->data = (*found)->data;
159 572 : 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
165 742699 : check_constant_offset (Dwarf_Attribute *attr,
166 : Dwarf_Op **llbuf, size_t *listlen)
167 : {
168 742699 : if (attr->code != DW_AT_data_member_location)
169 : return 1;
170 :
171 150527 : 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 150527 : struct loc_s fake = { .addr = attr->valp };
190 150527 : struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
191 :
192 150527 : if (found == NULL)
193 : {
194 : Dwarf_Word offset;
195 150527 : if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
196 0 : return -1;
197 :
198 150527 : Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
199 : Dwarf_Op, sizeof (Dwarf_Op), 1);
200 :
201 150527 : result->atom = DW_OP_plus_uconst;
202 150527 : result->number = offset;
203 150527 : result->number2 = 0;
204 150527 : result->offset = 0;
205 :
206 : /* Insert a record in the search tree so we can find it again later. */
207 150527 : struct loc_s *newp = libdw_alloc (attr->cu->dbg,
208 : struct loc_s, sizeof (struct loc_s),
209 : 1);
210 150527 : newp->addr = attr->valp;
211 150527 : newp->loc = result;
212 150527 : newp->nloc = 1;
213 :
214 150527 : found = tsearch (newp, &attr->cu->locs, loc_compare);
215 : }
216 :
217 150527 : assert ((*found)->nloc == 1);
218 :
219 150527 : if (llbuf != NULL)
220 : {
221 150527 : *llbuf = (*found)->loc;
222 150527 : *listlen = 1;
223 : }
224 :
225 : return 0;
226 : }
227 :
228 : int
229 : internal_function
230 541153 : __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 541153 : if (block->length == 0)
238 : {
239 0 : *listlen = 0;
240 0 : return 0;
241 : }
242 :
243 : /* Check whether we already looked at this list. */
244 541153 : struct loc_s fake = { .addr = block->data };
245 541153 : struct loc_s **found = tfind (&fake, cache, loc_compare);
246 541153 : if (found != NULL)
247 : {
248 : /* We already saw it. */
249 212008 : *llbuf = (*found)->loc;
250 212008 : *listlen = (*found)->nloc;
251 :
252 212008 : if (valuep)
253 : {
254 0 : assert (*listlen > 1);
255 0 : assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
256 : }
257 :
258 : return 0;
259 : }
260 :
261 329145 : const unsigned char *data = block->data;
262 329145 : const unsigned char *const end_data = data + block->length;
263 :
264 329145 : const struct { bool other_byte_order; } bo = { other_byte_order };
265 :
266 329145 : struct loclist *loclist = NULL;
267 329145 : 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 329145 : if (cfap)
284 : {
285 : /* Synthesize the operation to push the CFA before the expression. */
286 9 : struct loclist *newloc = NEW_LOC ();
287 9 : newloc->atom = DW_OP_call_frame_cfa;
288 9 : newloc->number = 0;
289 9 : newloc->number2 = 0;
290 9 : newloc->offset = -1;
291 : }
292 :
293 : /* Decode the opcodes. It is possible in some situations to have a
294 : block of size zero. */
295 805329 : while (data < end_data)
296 : {
297 : struct loclist *newloc;
298 952368 : newloc = NEW_LOC ();
299 476184 : newloc->number = 0;
300 476184 : newloc->number2 = 0;
301 476184 : newloc->offset = data - block->data;
302 :
303 476184 : switch ((newloc->atom = *data++))
304 : {
305 7776 : case DW_OP_addr:
306 : /* Address, depends on address size of CU. */
307 7776 : if (dbg == NULL)
308 : {
309 : // XXX relocation?
310 0 : if (address_size == 4)
311 : {
312 0 : if (unlikely (data + 4 > end_data))
313 : goto invalid;
314 : else
315 0 : newloc->number = read_4ubyte_unaligned_inc (&bo, data);
316 : }
317 : else
318 : {
319 0 : if (unlikely (data + 8 > end_data))
320 : goto invalid;
321 : else
322 0 : newloc->number = read_8ubyte_unaligned_inc (&bo, data);
323 : }
324 : }
325 7776 : else if (__libdw_read_address_inc (dbg, sec_index, &data,
326 7776 : address_size, &newloc->number))
327 : goto invalid;
328 : break;
329 :
330 1 : case DW_OP_call_ref:
331 : case DW_OP_GNU_variable_value:
332 : /* DW_FORM_ref_addr, depends on offset size of CU. */
333 2 : if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
334 : ref_size,
335 1 : &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 10484 : case DW_OP_const1u:
379 : case DW_OP_pick:
380 : case DW_OP_deref_size:
381 : case DW_OP_xderef_size:
382 10484 : if (unlikely (data >= end_data))
383 : {
384 0 : invalid:
385 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
386 : returnmem:
387 : /* Free any dynamicly allocated loclists, if any. */
388 0 : while (n > MAX_STACK_LOCS)
389 : {
390 0 : struct loclist *loc = loclist;
391 0 : loclist = loc->next;
392 0 : free (loc);
393 0 : n--;
394 : }
395 : return -1;
396 : }
397 :
398 10484 : newloc->number = *data++;
399 10484 : break;
400 :
401 1600 : case DW_OP_const1s:
402 1600 : if (unlikely (data >= end_data))
403 : goto invalid;
404 :
405 1600 : newloc->number = *((int8_t *) data);
406 1600 : ++data;
407 1600 : break;
408 :
409 929 : case DW_OP_const2u:
410 929 : if (unlikely (data + 2 > end_data))
411 : goto invalid;
412 :
413 929 : newloc->number = read_2ubyte_unaligned_inc (&bo, data);
414 929 : break;
415 :
416 409 : case DW_OP_const2s:
417 : case DW_OP_skip:
418 : case DW_OP_bra:
419 : case DW_OP_call2:
420 409 : if (unlikely (data + 2 > end_data))
421 : goto invalid;
422 :
423 409 : newloc->number = read_2sbyte_unaligned_inc (&bo, data);
424 409 : break;
425 :
426 692 : case DW_OP_const4u:
427 692 : if (unlikely (data + 4 > end_data))
428 : goto invalid;
429 :
430 692 : newloc->number = read_4ubyte_unaligned_inc (&bo, data);
431 692 : break;
432 :
433 47 : case DW_OP_const4s:
434 : case DW_OP_call4:
435 : case DW_OP_GNU_parameter_ref:
436 47 : if (unlikely (data + 4 > end_data))
437 : goto invalid;
438 :
439 47 : newloc->number = read_4sbyte_unaligned_inc (&bo, data);
440 47 : break;
441 :
442 110 : case DW_OP_const8u:
443 110 : if (unlikely (data + 8 > end_data))
444 : goto invalid;
445 :
446 110 : newloc->number = read_8ubyte_unaligned_inc (&bo, data);
447 110 : break;
448 :
449 0 : case DW_OP_const8s:
450 0 : if (unlikely (data + 8 > end_data))
451 : goto invalid;
452 :
453 0 : newloc->number = read_8sbyte_unaligned_inc (&bo, data);
454 0 : break;
455 :
456 11722 : 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 11722 : get_uleb128 (newloc->number, data, end_data);
469 11722 : break;
470 :
471 80414 : case DW_OP_consts:
472 : case DW_OP_breg0 ... DW_OP_breg31:
473 : case DW_OP_fbreg:
474 80414 : get_sleb128 (newloc->number, data, end_data);
475 80414 : break;
476 :
477 0 : case DW_OP_bregx:
478 0 : get_uleb128 (newloc->number, data, end_data);
479 0 : if (unlikely (data >= end_data))
480 : goto invalid;
481 0 : get_sleb128 (newloc->number2, data, end_data);
482 0 : break;
483 :
484 0 : case DW_OP_bit_piece:
485 : case DW_OP_regval_type:
486 : case DW_OP_GNU_regval_type:
487 0 : get_uleb128 (newloc->number, data, end_data);
488 0 : if (unlikely (data >= end_data))
489 : goto invalid;
490 0 : get_uleb128 (newloc->number2, data, end_data);
491 0 : break;
492 :
493 32285 : 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 32285 : if (unlikely (dbg == NULL))
498 : goto invalid;
499 :
500 : /* start of block inc. len. */
501 32285 : newloc->number2 = (Dwarf_Word) (uintptr_t) data;
502 32285 : get_uleb128 (newloc->number, data, end_data); /* Block length. */
503 32285 : if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
504 : goto invalid;
505 32285 : data += newloc->number; /* Skip the block. */
506 32285 : break;
507 :
508 6667 : case DW_OP_implicit_pointer:
509 : case DW_OP_GNU_implicit_pointer:
510 : /* DW_FORM_ref_addr, depends on offset size of CU. */
511 13334 : if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
512 : ref_size,
513 6667 : &newloc->number,
514 : IDX_debug_info, 0))
515 : goto invalid;
516 6667 : if (unlikely (data >= end_data))
517 : goto invalid;
518 6667 : get_uleb128 (newloc->number2, data, end_data); /* Byte offset. */
519 6667 : break;
520 :
521 7 : case DW_OP_deref_type:
522 : case DW_OP_GNU_deref_type:
523 : case DW_OP_xderef_type:
524 7 : if (unlikely (data + 1 >= end_data))
525 : goto invalid;
526 7 : newloc->number = *data++;
527 7 : get_uleb128 (newloc->number2, data, end_data);
528 7 : break;
529 :
530 2 : case DW_OP_const_type:
531 : case DW_OP_GNU_const_type:
532 : {
533 : size_t size;
534 2 : get_uleb128 (newloc->number, data, end_data);
535 2 : if (unlikely (data >= end_data))
536 : goto invalid;
537 :
538 : /* start of block inc. len. */
539 2 : newloc->number2 = (Dwarf_Word) (uintptr_t) data;
540 2 : size = *data++;
541 2 : if (unlikely ((Dwarf_Word) (end_data - data) < size))
542 : goto invalid;
543 2 : data += size; /* Skip the block. */
544 : }
545 2 : break;
546 :
547 : default:
548 : goto invalid;
549 : }
550 : }
551 :
552 329145 : 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 329145 : if (valuep)
561 : {
562 0 : struct loclist *newloc = NEW_LOC ();
563 0 : newloc->atom = DW_OP_stack_value;
564 0 : newloc->number = 0;
565 0 : newloc->number2 = 0;
566 0 : newloc->offset = data - block->data;
567 : }
568 :
569 : /* Allocate the array. */
570 : Dwarf_Op *result;
571 329145 : if (dbg != NULL)
572 329134 : result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
573 : else
574 : {
575 11 : result = malloc (sizeof *result * n);
576 11 : if (result == NULL)
577 : {
578 0 : nomem:
579 0 : __libdw_seterrno (DWARF_E_NOMEM);
580 0 : goto returnmem;
581 : }
582 : }
583 :
584 : /* Store the result. */
585 329145 : *llbuf = result;
586 329145 : *listlen = n;
587 :
588 : do
589 : {
590 : /* We populate the array from the back since the list is backwards. */
591 476193 : --n;
592 476193 : result[n].atom = loclist->atom;
593 476193 : result[n].number = loclist->number;
594 476193 : result[n].number2 = loclist->number2;
595 476193 : result[n].offset = loclist->offset;
596 :
597 476193 : if (result[n].atom == DW_OP_implicit_value)
598 : {
599 214 : int store = store_implicit_value (dbg, cache, &result[n]);
600 214 : if (unlikely (store != 0))
601 : {
602 0 : if (store < 0)
603 : goto invalid;
604 : else
605 : goto nomem;
606 : }
607 : }
608 :
609 476193 : struct loclist *loc = loclist;
610 476193 : loclist = loclist->next;
611 476193 : if (unlikely (n + 1 > MAX_STACK_LOCS))
612 137 : free (loc);
613 : }
614 476193 : 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 329145 : if (dbg != NULL)
619 329134 : newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
620 : else
621 : {
622 11 : newp = malloc (sizeof *newp);
623 11 : if (newp == NULL)
624 : {
625 0 : free (result);
626 0 : goto nomem;
627 : }
628 : }
629 :
630 329145 : newp->addr = block->data;
631 329145 : newp->loc = result;
632 329145 : newp->nloc = *listlen;
633 329145 : (void) tsearch (newp, cache, loc_compare);
634 :
635 : /* We did it. */
636 329145 : return 0;
637 : }
638 :
639 : static int
640 541138 : 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 541138 : if (block->length == 0)
646 : {
647 6 : *listlen = 0;
648 6 : return 0;
649 : }
650 :
651 2164528 : return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
652 1082264 : cu->address_size, (cu->version == 2
653 0 : ? cu->address_size
654 541132 : : cu->offset_size),
655 : &cu->locs, block,
656 : false, false,
657 : llbuf, listlen, sec_index);
658 : }
659 :
660 : int
661 1931884 : dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
662 : {
663 1931884 : if (! attr_ok (attr))
664 : return -1;
665 :
666 393626 : int result = check_constant_offset (attr, llbuf, listlen);
667 393626 : 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 243099 : if (attr->form == DW_FORM_data16)
673 : {
674 0 : __libdw_seterrno (DWARF_E_NO_BLOCK);
675 0 : return -1;
676 : }
677 : Dwarf_Block block;
678 243099 : if (INTUSE(dwarf_formblock) (attr, &block) != 0)
679 : return -1;
680 :
681 99003 : return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
682 : }
683 :
684 : Dwarf_Addr
685 355156 : __libdw_cu_base_address (Dwarf_CU *cu)
686 : {
687 355156 : if (cu->base_address == (Dwarf_Addr) -1)
688 : {
689 : Dwarf_Addr base;
690 :
691 : /* Fetch the CU's base address. */
692 3394 : 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 1697 : if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
701 1 : && 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 1 : base = 0;
710 : }
711 1697 : cu->base_address = base;
712 : }
713 :
714 355156 : return cu->base_address;
715 : }
716 :
717 : static int
718 349073 : initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
719 : {
720 698146 : size_t secidx = (attr->cu->version < 5
721 349073 : ? IDX_debug_loc : IDX_debug_loclists);
722 :
723 : Dwarf_Word start_offset;
724 349073 : if (attr->form == DW_FORM_loclistx)
725 : {
726 : Dwarf_Word idx;
727 67 : Dwarf_CU *cu = attr->cu;
728 67 : const unsigned char *datap = attr->valp;
729 67 : const unsigned char *endp = cu->endp;
730 67 : if (datap >= endp)
731 : {
732 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
733 0 : return -1;
734 : }
735 67 : get_uleb128 (idx, datap, endp);
736 :
737 67 : Elf_Data *data = cu->dbg->sectiondata[secidx];
738 67 : if (data == NULL && cu->unit_type == DW_UT_split_compile)
739 : {
740 0 : cu = __libdw_find_split_unit (cu);
741 0 : if (cu != NULL)
742 0 : data = cu->dbg->sectiondata[secidx];
743 : }
744 :
745 67 : if (data == NULL)
746 : {
747 0 : __libdw_seterrno (secidx == IDX_debug_loc
748 : ? DWARF_E_NO_DEBUG_LOC
749 : : DWARF_E_NO_DEBUG_LOCLISTS);
750 0 : return -1;
751 : }
752 :
753 67 : Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
754 :
755 : /* The section should at least contain room for one offset. */
756 67 : size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
757 67 : size_t offset_size = cu->offset_size;
758 67 : if (offset_size > sec_size)
759 : {
760 0 : invalid_offset:
761 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET);
762 0 : return -1;
763 : }
764 :
765 : /* And the base offset should be at least inside the section. */
766 67 : if (loc_base_off > (sec_size - offset_size))
767 : goto invalid_offset;
768 :
769 67 : size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
770 67 : if (idx > max_idx)
771 : goto invalid_offset;
772 :
773 134 : datap = (cu->dbg->sectiondata[secidx]->d_buf
774 67 : + loc_base_off + (idx * offset_size));
775 67 : if (offset_size == 4)
776 67 : start_offset = read_4ubyte_unaligned (cu->dbg, datap);
777 : else
778 0 : start_offset = read_8ubyte_unaligned (cu->dbg, datap);
779 :
780 67 : start_offset += loc_base_off;
781 : }
782 : else
783 : {
784 349006 : 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 263319 : *offset = start_offset;
793 263319 : return 0;
794 : }
795 :
796 : static ptrdiff_t
797 501513 : 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 501513 : Dwarf_CU *cu = attr->cu;
803 501513 : Dwarf *dbg = cu->dbg;
804 501513 : size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
805 501513 : const unsigned char *readp = locs->d_buf + offset;
806 501513 : const unsigned char *readendp = locs->d_buf + locs->d_size;
807 :
808 : Dwarf_Addr begin;
809 : Dwarf_Addr end;
810 :
811 : next:
812 2014811 : switch (__libdw_read_begin_end_pair_inc (cu, secidx,
813 : &readp, readendp,
814 2014811 : 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 0 : default: /* error */
824 : return -1;
825 : }
826 :
827 : /* We have a location expression. */
828 : Dwarf_Block block;
829 1954942 : if (secidx == IDX_debug_loc)
830 : {
831 1954684 : if (readendp - readp < 2)
832 : {
833 0 : invalid:
834 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
835 : return -1;
836 : }
837 1954684 : block.length = read_2ubyte_unaligned_inc (dbg, readp);
838 : }
839 : else
840 : {
841 258 : if (readendp - readp < 1)
842 : goto invalid;
843 258 : get_uleb128 (block.length, readp, readendp);
844 : }
845 1954942 : block.data = (unsigned char *) readp;
846 1954942 : if (readendp - readp < (ptrdiff_t) block.length)
847 : goto invalid;
848 1954942 : readp += block.length;
849 :
850 : /* Note these addresses include any base (if necessary) already. */
851 1954942 : *startp = begin;
852 1954942 : *endp = end;
853 :
854 : /* If address is minus one we want them all, otherwise only matching. */
855 1954942 : if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
856 : goto next;
857 :
858 441663 : if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
859 : return -1;
860 :
861 441663 : return readp - (unsigned char *) locs->d_buf;
862 : }
863 :
864 : int
865 205449 : dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
866 : Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
867 : {
868 205449 : if (! attr_ok (attr))
869 : return -1;
870 :
871 205449 : if (llbufs == NULL)
872 0 : 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 205449 : if (attr->form != DW_FORM_data16
878 205449 : && INTUSE(dwarf_formblock) (attr, &block) == 0)
879 : {
880 472 : if (maxlocs == 0)
881 : return 0;
882 944 : if (llbufs != NULL &&
883 472 : getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
884 472 : cu_sec_idx (attr->cu)) != 0)
885 : return -1;
886 472 : return listlens[0] == 0 ? 0 : 1;
887 : }
888 :
889 204977 : if (attr->form != DW_FORM_data16)
890 : {
891 204977 : int error = INTUSE(dwarf_errno) ();
892 204977 : if (unlikely (error != DWARF_E_NO_BLOCK))
893 : {
894 0 : __libdw_seterrno (error);
895 0 : return -1;
896 : }
897 : }
898 :
899 204977 : int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
900 204977 : if (result != 1)
901 0 : return result ?: 1;
902 :
903 : Dwarf_Addr base, start, end;
904 : Dwarf_Op *expr;
905 : size_t expr_len;
906 204977 : ptrdiff_t off = 0;
907 204977 : size_t got = 0;
908 :
909 : /* This is a true loclistptr, fetch the initial base address and offset. */
910 204977 : base = __libdw_cu_base_address (attr->cu);
911 204977 : if (base == (Dwarf_Addr) -1)
912 : return -1;
913 :
914 204977 : if (initial_offset (attr, &off) != 0)
915 : return -1;
916 :
917 204977 : size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
918 204977 : const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
919 :
920 613423 : while (got < maxlocs
921 204977 : && (off = getlocations_addr (attr, off, &base, &start, &end,
922 : address, d, &expr, &expr_len)) > 0)
923 : {
924 : /* This one matches the address. */
925 203469 : if (llbufs != NULL)
926 : {
927 203469 : llbufs[got] = expr;
928 203469 : listlens[got] = expr_len;
929 : }
930 203469 : ++got;
931 : }
932 :
933 : /* We might stop early, so off can be zero or positive on success. */
934 204977 : if (off < 0)
935 : return -1;
936 :
937 204977 : return got;
938 : }
939 :
940 : ptrdiff_t
941 1920548 : 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 1920548 : if (! attr_ok (attr))
946 : return -1;
947 :
948 : /* 1 is an invalid offset, meaning no more locations. */
949 382290 : if (offset == 1)
950 : return 0;
951 :
952 382290 : 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 144096 : if (attr->form != DW_FORM_data16
958 144096 : && INTUSE(dwarf_formblock) (attr, &block) == 0)
959 : {
960 0 : if (getlocation (attr->cu, &block, expr, exprlen,
961 0 : cu_sec_idx (attr->cu)) != 0)
962 85754 : return -1;
963 :
964 : /* This is the one and only location covering everything. */
965 0 : *startp = 0;
966 0 : *endp = -1;
967 0 : return 1;
968 : }
969 :
970 144096 : if (attr->form != DW_FORM_data16)
971 : {
972 144096 : int error = INTUSE(dwarf_errno) ();
973 144096 : if (unlikely (error != DWARF_E_NO_BLOCK))
974 : {
975 0 : __libdw_seterrno (error);
976 0 : return -1;
977 : }
978 : }
979 :
980 144096 : int result = check_constant_offset (attr, expr, exprlen);
981 144096 : if (result != 1)
982 : {
983 0 : if (result == 0)
984 : {
985 : /* This is the one and only location covering everything. */
986 0 : *startp = 0;
987 0 : *endp = -1;
988 0 : return 1;
989 : }
990 0 : return result;
991 : }
992 :
993 : /* We must be looking at a true loclistptr, fetch the initial
994 : base address and offset. */
995 144096 : *basep = __libdw_cu_base_address (attr->cu);
996 144096 : if (*basep == (Dwarf_Addr) -1)
997 : return -1;
998 :
999 144096 : if (initial_offset (attr, &offset) != 0)
1000 : return -1;
1001 : }
1002 :
1003 296536 : size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
1004 296536 : const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
1005 :
1006 296536 : return getlocations_addr (attr, offset, basep, startp, endp,
1007 : (Dwarf_Word) -1, d, expr, exprlen);
1008 : }
|