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