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