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