Branch data Line data Source code
1 : : /* Return location expression list.
2 : : Copyright (C) 2000-2010 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <dwarf.h>
35 : : #include <search.h>
36 : : #include <stdlib.h>
37 : : #include <assert.h>
38 : :
39 : : #include <libdwP.h>
40 : :
41 : :
42 : : static bool
43 : 7308 : attr_ok (Dwarf_Attribute *attr)
44 : : {
45 [ + - ]: 7308 : if (attr == NULL)
46 : : return false;
47 : :
48 : : /* Must be one of the attributes listed below. */
49 [ - + ]: 7308 : switch (attr->code)
50 : : {
51 : : case DW_AT_location:
52 : : case DW_AT_data_member_location:
53 : : case DW_AT_vtable_elem_location:
54 : : case DW_AT_string_length:
55 : : case DW_AT_use_location:
56 : : case DW_AT_frame_base:
57 : : case DW_AT_return_addr:
58 : : case DW_AT_static_link:
59 : : break;
60 : :
61 : : default:
62 : 0 : __libdw_seterrno (DWARF_E_NO_LOCLIST);
63 : 7308 : return false;
64 : : }
65 : :
66 : : return true;
67 : : }
68 : :
69 : :
70 : : struct loclist
71 : : {
72 : : uint8_t atom;
73 : : Dwarf_Word number;
74 : : Dwarf_Word number2;
75 : : Dwarf_Word offset;
76 : : struct loclist *next;
77 : : };
78 : :
79 : :
80 : : static int
81 : 35928 : loc_compare (const void *p1, const void *p2)
82 : : {
83 : 35928 : const struct loc_s *l1 = (const struct loc_s *) p1;
84 : 35928 : const struct loc_s *l2 = (const struct loc_s *) p2;
85 : :
86 [ + - ]: 35928 : if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
87 : : return -1;
88 [ - + ]: 35928 : if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
89 : : return 1;
90 : :
91 : 35928 : return 0;
92 : : }
93 : :
94 : : /* For each DW_OP_implicit_value, we store a special entry in the cache.
95 : : This points us directly to the block data for later fetching. */
96 : : static void
97 : 0 : store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op,
98 : : unsigned char *data)
99 : : {
100 [ # # ]: 0 : struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
101 : : sizeof (struct loc_block_s), 1);
102 : 0 : block->addr = op;
103 : 0 : block->data = data + op->number2;
104 : 0 : block->length = op->number;
105 : 0 : (void) tsearch (block, cache, loc_compare);
106 : 0 : }
107 : :
108 : : int
109 : 0 : dwarf_getlocation_implicit_value (attr, op, return_block)
110 : : Dwarf_Attribute *attr;
111 : : const Dwarf_Op *op;
112 : : Dwarf_Block *return_block;
113 : : {
114 [ # # ]: 0 : if (attr == NULL)
115 : : return -1;
116 : :
117 : 0 : struct loc_block_s fake = { .addr = (void *) op };
118 : 0 : struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
119 [ # # ]: 0 : if (unlikely (found == NULL))
120 : : {
121 : 0 : __libdw_seterrno (DWARF_E_NO_BLOCK);
122 : : return -1;
123 : : }
124 : :
125 : 0 : return_block->length = (*found)->length;
126 : 0 : return_block->data = (*found)->data;
127 : : return 0;
128 : : }
129 : :
130 : : /* DW_AT_data_member_location can be a constant as well as a loclistptr.
131 : : Only data[48] indicate a loclistptr. */
132 : : static int
133 : 7308 : check_constant_offset (Dwarf_Attribute *attr,
134 : : Dwarf_Op **llbuf, size_t *listlen)
135 : : {
136 [ - + ]: 7308 : if (attr->code != DW_AT_data_member_location)
137 : : return 1;
138 : :
139 [ # # ]: 0 : switch (attr->form)
140 : : {
141 : : /* Punt for any non-constant form. */
142 : : default:
143 : : return 1;
144 : :
145 : : case DW_FORM_data1:
146 : : case DW_FORM_data2:
147 : : case DW_FORM_data4:
148 : : case DW_FORM_data8:
149 : : case DW_FORM_sdata:
150 : : case DW_FORM_udata:
151 : : break;
152 : : }
153 : :
154 : : /* Check whether we already cached this location. */
155 : 0 : struct loc_s fake = { .addr = attr->valp };
156 : 0 : struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
157 : :
158 [ # # ]: 0 : if (found == NULL)
159 : : {
160 : : Dwarf_Word offset;
161 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
162 : : return -1;
163 : :
164 [ # # ]: 0 : Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
165 : : Dwarf_Op, sizeof (Dwarf_Op), 1);
166 : :
167 : 0 : result->atom = DW_OP_plus_uconst;
168 : 0 : result->number = offset;
169 : 0 : result->number2 = 0;
170 : 0 : result->offset = 0;
171 : :
172 : : /* Insert a record in the search tree so we can find it again later. */
173 [ # # ]: 0 : struct loc_s *newp = libdw_alloc (attr->cu->dbg,
174 : : struct loc_s, sizeof (struct loc_s),
175 : : 1);
176 : 0 : newp->addr = attr->valp;
177 : 0 : newp->loc = result;
178 : 0 : newp->nloc = 1;
179 : :
180 : 0 : found = tsearch (newp, &attr->cu->locs, loc_compare);
181 : : }
182 : :
183 [ # # ]: 0 : assert ((*found)->nloc == 1);
184 : :
185 [ # # ]: 0 : if (llbuf != NULL)
186 : : {
187 : 0 : *llbuf = (*found)->loc;
188 : 7308 : *listlen = 1;
189 : : }
190 : :
191 : : return 0;
192 : : }
193 : :
194 : : int
195 : : internal_function
196 : 7308 : __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
197 : : unsigned int address_size, unsigned int ref_size,
198 : : void **cache, const Dwarf_Block *block,
199 : : bool cfap, bool valuep,
200 : : Dwarf_Op **llbuf, size_t *listlen, int sec_index)
201 : : {
202 : : /* Check whether we already looked at this list. */
203 : 7308 : struct loc_s fake = { .addr = block->data };
204 : 7308 : struct loc_s **found = tfind (&fake, cache, loc_compare);
205 [ - + ]: 7308 : if (found != NULL)
206 : : {
207 : : /* We already saw it. */
208 : 0 : *llbuf = (*found)->loc;
209 : 0 : *listlen = (*found)->nloc;
210 : :
211 [ # # ]: 0 : if (valuep)
212 : : {
213 [ # # ]: 0 : assert (*listlen > 1);
214 [ # # ]: 0 : assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
215 : : }
216 : :
217 : : return 0;
218 : : }
219 : :
220 : 7308 : const unsigned char *data = block->data;
221 : 7308 : const unsigned char *const end_data = data + block->length;
222 : :
223 : 7308 : const struct { bool other_byte_order; } bo = { other_byte_order };
224 : :
225 : 7308 : struct loclist *loclist = NULL;
226 : 7308 : unsigned int n = 0;
227 : :
228 [ - + ]: 7308 : if (cfap)
229 : : {
230 : : /* Synthesize the operation to push the CFA before the expression. */
231 : : struct loclist *newloc;
232 : 0 : newloc = (struct loclist *) alloca (sizeof (struct loclist));
233 : 0 : newloc->atom = DW_OP_call_frame_cfa;
234 : 0 : newloc->number = 0;
235 : 0 : newloc->number2 = 0;
236 : 0 : newloc->offset = -1;
237 : 0 : newloc->next = loclist;
238 : 0 : loclist = newloc;
239 : 7308 : ++n;
240 : : }
241 : :
242 : : /* Decode the opcodes. It is possible in some situations to have a
243 : : block of size zero. */
244 [ + + ]: 14868 : while (data < end_data)
245 : : {
246 : : struct loclist *newloc;
247 : 7560 : newloc = (struct loclist *) alloca (sizeof (struct loclist));
248 : 7560 : newloc->number = 0;
249 : 7560 : newloc->number2 = 0;
250 : 7560 : newloc->offset = data - block->data;
251 : 7560 : newloc->next = loclist;
252 : 7560 : loclist = newloc;
253 : 7560 : ++n;
254 : :
255 [ + - - - : 7560 : switch ((newloc->atom = *data++))
- - - - -
+ - - - -
- - - - -
+ ]
256 : : {
257 : : case DW_OP_addr:
258 : : /* Address, depends on address size of CU. */
259 [ + - ]: 7056 : if (__libdw_read_address_inc (dbg, sec_index, &data,
260 : 7056 : address_size, &newloc->number))
261 : : return -1;
262 : : break;
263 : :
264 : : case DW_OP_call_ref:
265 : : /* DW_FORM_ref_addr, depends on offset size of CU. */
266 [ # # ]: 0 : if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
267 : 0 : &newloc->number, IDX_debug_info, 0))
268 : : return -1;
269 : : break;
270 : :
271 : : case DW_OP_deref:
272 : : case DW_OP_dup:
273 : : case DW_OP_drop:
274 : : case DW_OP_over:
275 : : case DW_OP_swap:
276 : : case DW_OP_rot:
277 : : case DW_OP_xderef:
278 : : case DW_OP_abs:
279 : : case DW_OP_and:
280 : : case DW_OP_div:
281 : : case DW_OP_minus:
282 : : case DW_OP_mod:
283 : : case DW_OP_mul:
284 : : case DW_OP_neg:
285 : : case DW_OP_not:
286 : : case DW_OP_or:
287 : : case DW_OP_plus:
288 : : case DW_OP_shl:
289 : : case DW_OP_shr:
290 : : case DW_OP_shra:
291 : : case DW_OP_xor:
292 : : case DW_OP_eq:
293 : : case DW_OP_ge:
294 : : case DW_OP_gt:
295 : : case DW_OP_le:
296 : : case DW_OP_lt:
297 : : case DW_OP_ne:
298 : : case DW_OP_lit0 ... DW_OP_lit31:
299 : : case DW_OP_reg0 ... DW_OP_reg31:
300 : : case DW_OP_nop:
301 : : case DW_OP_push_object_address:
302 : : case DW_OP_call_frame_cfa:
303 : : case DW_OP_form_tls_address:
304 : : case DW_OP_GNU_push_tls_address:
305 : : case DW_OP_stack_value:
306 : : /* No operand. */
307 : : break;
308 : :
309 : : case DW_OP_const1u:
310 : : case DW_OP_pick:
311 : : case DW_OP_deref_size:
312 : : case DW_OP_xderef_size:
313 [ # # ]: 0 : if (unlikely (data >= end_data))
314 : : {
315 : : invalid:
316 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
317 : : return -1;
318 : : }
319 : :
320 : 0 : newloc->number = *data++;
321 : 0 : break;
322 : :
323 : : case DW_OP_const1s:
324 [ # # ]: 0 : if (unlikely (data >= end_data))
325 : : goto invalid;
326 : :
327 : 0 : newloc->number = *((int8_t *) data);
328 : 0 : ++data;
329 : 0 : break;
330 : :
331 : : case DW_OP_const2u:
332 [ # # ]: 0 : if (unlikely (data + 2 > end_data))
333 : : goto invalid;
334 : :
335 [ # # ][ # # ]: 0 : newloc->number = read_2ubyte_unaligned_inc (&bo, data);
336 : 0 : break;
337 : :
338 : : case DW_OP_const2s:
339 : : case DW_OP_skip:
340 : : case DW_OP_bra:
341 : : case DW_OP_call2:
342 [ # # ]: 0 : if (unlikely (data + 2 > end_data))
343 : : goto invalid;
344 : :
345 [ # # ][ # # ]: 0 : newloc->number = read_2sbyte_unaligned_inc (&bo, data);
346 : 0 : break;
347 : :
348 : : case DW_OP_const4u:
349 [ # # ]: 0 : if (unlikely (data + 4 > end_data))
350 : : goto invalid;
351 : :
352 [ # # ]: 0 : newloc->number = read_4ubyte_unaligned_inc (&bo, data);
353 : 0 : break;
354 : :
355 : : case DW_OP_const4s:
356 : : case DW_OP_call4:
357 : : case DW_OP_GNU_parameter_ref:
358 [ # # ]: 0 : if (unlikely (data + 4 > end_data))
359 : : goto invalid;
360 : :
361 [ # # ]: 0 : newloc->number = read_4sbyte_unaligned_inc (&bo, data);
362 : 0 : break;
363 : :
364 : : case DW_OP_const8u:
365 [ - + ]: 252 : if (unlikely (data + 8 > end_data))
366 : : goto invalid;
367 : :
368 [ - + ]: 252 : newloc->number = read_8ubyte_unaligned_inc (&bo, data);
369 : 252 : break;
370 : :
371 : : case DW_OP_const8s:
372 [ # # ]: 0 : if (unlikely (data + 8 > end_data))
373 : : goto invalid;
374 : :
375 [ # # ]: 0 : newloc->number = read_8sbyte_unaligned_inc (&bo, data);
376 : 0 : break;
377 : :
378 : : case DW_OP_constu:
379 : : case DW_OP_plus_uconst:
380 : : case DW_OP_regx:
381 : : case DW_OP_piece:
382 : : case DW_OP_GNU_convert:
383 : : case DW_OP_GNU_reinterpret:
384 : : /* XXX Check size. */
385 [ # # ]: 0 : get_uleb128 (newloc->number, data);
386 : : break;
387 : :
388 : : case DW_OP_consts:
389 : : case DW_OP_breg0 ... DW_OP_breg31:
390 : : case DW_OP_fbreg:
391 : : /* XXX Check size. */
392 [ # # ]: 0 : get_sleb128 (newloc->number, data);
393 : : break;
394 : :
395 : : case DW_OP_bregx:
396 : : /* XXX Check size. */
397 [ # # ]: 0 : get_uleb128 (newloc->number, data);
398 [ # # ]: 0 : get_sleb128 (newloc->number2, data);
399 : : break;
400 : :
401 : : case DW_OP_bit_piece:
402 : : case DW_OP_GNU_regval_type:
403 : : /* XXX Check size. */
404 [ # # ]: 0 : get_uleb128 (newloc->number, data);
405 [ # # ]: 0 : get_uleb128 (newloc->number2, data);
406 : : break;
407 : :
408 : : case DW_OP_implicit_value:
409 : : case DW_OP_GNU_entry_value:
410 : : /* This cannot be used in a CFI expression. */
411 [ # # ]: 0 : if (unlikely (dbg == NULL))
412 : : goto invalid;
413 : :
414 : : /* XXX Check size. */
415 [ # # ]: 0 : get_uleb128 (newloc->number, data); /* Block length. */
416 [ # # ]: 0 : if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
417 : : goto invalid;
418 : 0 : newloc->number2 = data - block->data; /* Relative block offset. */
419 : 0 : data += newloc->number; /* Skip the block. */
420 : 0 : break;
421 : :
422 : : case DW_OP_GNU_implicit_pointer:
423 : : /* DW_FORM_ref_addr, depends on offset size of CU. */
424 [ # # ]: 0 : if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
425 : 0 : &newloc->number, IDX_debug_info, 0))
426 : : return -1;
427 : : /* XXX Check size. */
428 [ # # ]: 0 : get_uleb128 (newloc->number2, data); /* Byte offset. */
429 : : break;
430 : :
431 : : case DW_OP_GNU_deref_type:
432 [ # # ]: 0 : if (unlikely (data >= end_data))
433 : : goto invalid;
434 : 0 : newloc->number = *data++;
435 [ # # ]: 0 : get_uleb128 (newloc->number2, data);
436 : : break;
437 : :
438 : : case DW_OP_GNU_const_type:
439 : : /* XXX Check size. */
440 [ # # ]: 0 : get_uleb128 (newloc->number, data);
441 [ # # ]: 0 : if (unlikely (data >= end_data))
442 : : goto invalid;
443 : 0 : newloc->number2 = *data++; /* Block length. */
444 [ # # ]: 0 : if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number2))
445 : : goto invalid;
446 : : /* The third operand is relative block offset:
447 : : newloc->number3 = data - block->data;
448 : : We don't support this at this point. */
449 : 0 : data += newloc->number2; /* Skip the block. */
450 : 7560 : break;
451 : :
452 : : default:
453 : : goto invalid;
454 : : }
455 : : }
456 : :
457 [ - + ]: 7308 : if (unlikely (n == 0))
458 : : {
459 : : /* This is not allowed.
460 : :
461 : : XXX Is it? */
462 : : goto invalid;
463 : : }
464 : :
465 [ - + ]: 7308 : if (valuep)
466 : : {
467 : : struct loclist *newloc;
468 : 0 : newloc = (struct loclist *) alloca (sizeof (struct loclist));
469 : 0 : newloc->atom = DW_OP_stack_value;
470 : 0 : newloc->number = 0;
471 : 0 : newloc->number2 = 0;
472 : 0 : newloc->offset = data - block->data;
473 : 0 : newloc->next = loclist;
474 : 0 : loclist = newloc;
475 : 0 : ++n;
476 : : }
477 : :
478 : : /* Allocate the array. */
479 : : Dwarf_Op *result;
480 [ + - ]: 7308 : if (dbg != NULL)
481 [ + + ]: 7308 : result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
482 : : else
483 : : {
484 : 0 : result = malloc (sizeof *result * n);
485 [ # # ]: 0 : if (result == NULL)
486 : : {
487 : : nomem:
488 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
489 : : return -1;
490 : : }
491 : : }
492 : :
493 : : /* Store the result. */
494 : 7308 : *llbuf = result;
495 : 7308 : *listlen = n;
496 : :
497 : : do
498 : : {
499 : : /* We populate the array from the back since the list is backwards. */
500 : 7560 : --n;
501 : 7560 : result[n].atom = loclist->atom;
502 : 7560 : result[n].number = loclist->number;
503 : 7560 : result[n].number2 = loclist->number2;
504 : 7560 : result[n].offset = loclist->offset;
505 : :
506 [ - + ]: 7560 : if (result[n].atom == DW_OP_implicit_value)
507 : 0 : store_implicit_value (dbg, cache, &result[n], block->data);
508 : :
509 : 7560 : loclist = loclist->next;
510 : : }
511 [ + + ]: 7560 : while (n > 0);
512 : :
513 : : /* Insert a record in the search tree so that we can find it again later. */
514 : : struct loc_s *newp;
515 [ + - ]: 7308 : if (dbg != NULL)
516 [ + + ]: 7308 : newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
517 : : else
518 : : {
519 : 0 : newp = malloc (sizeof *newp);
520 [ # # ]: 0 : if (newp == NULL)
521 : : {
522 : 0 : free (result);
523 : 0 : goto nomem;
524 : : }
525 : : }
526 : :
527 : 7308 : newp->addr = block->data;
528 : 7308 : newp->loc = result;
529 : 7308 : newp->nloc = *listlen;
530 : 7308 : (void) tsearch (newp, cache, loc_compare);
531 : :
532 : : /* We did it. */
533 : : return 0;
534 : : }
535 : :
536 : : static int
537 : 7308 : getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
538 : : Dwarf_Op **llbuf, size_t *listlen, int sec_index)
539 : : {
540 [ - + ]: 7308 : return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
541 : 14616 : cu->address_size, (cu->version == 2
542 : 0 : ? cu->address_size
543 : 7308 : : cu->offset_size),
544 : : &cu->locs, block,
545 : : false, false,
546 : : llbuf, listlen, sec_index);
547 : : }
548 : :
549 : : int
550 : 7308 : dwarf_getlocation (attr, llbuf, listlen)
551 : : Dwarf_Attribute *attr;
552 : : Dwarf_Op **llbuf;
553 : : size_t *listlen;
554 : : {
555 [ + - ]: 7308 : if (! attr_ok (attr))
556 : : return -1;
557 : :
558 : 7308 : int result = check_constant_offset (attr, llbuf, listlen);
559 [ + - ]: 7308 : if (result != 1)
560 : : return result;
561 : :
562 : : /* If it has a block form, it's a single location expression. */
563 : : Dwarf_Block block;
564 [ + - ]: 7308 : if (INTUSE(dwarf_formblock) (attr, &block) != 0)
565 : : return -1;
566 : :
567 : 7308 : return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
568 : : }
569 : :
570 : : int
571 : 0 : dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
572 : : Dwarf_Attribute *attr;
573 : : Dwarf_Addr address;
574 : : Dwarf_Op **llbufs;
575 : : size_t *listlens;
576 : : size_t maxlocs;
577 : : {
578 [ # # ]: 0 : if (! attr_ok (attr))
579 : : return -1;
580 : :
581 [ # # ]: 0 : if (llbufs == NULL)
582 : 0 : maxlocs = SIZE_MAX;
583 : :
584 : : /* If it has a block form, it's a single location expression. */
585 : : Dwarf_Block block;
586 [ # # ]: 0 : if (INTUSE(dwarf_formblock) (attr, &block) == 0)
587 : : {
588 [ # # ]: 0 : if (maxlocs == 0)
589 : : return 0;
590 [ # # # # ]: 0 : if (llbufs != NULL &&
591 : 0 : getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
592 : 0 : cu_sec_idx (attr->cu)) != 0)
593 : : return -1;
594 : 0 : return listlens[0] == 0 ? 0 : 1;
595 : : }
596 : :
597 : 0 : int error = INTUSE(dwarf_errno) ();
598 [ # # ]: 0 : if (unlikely (error != DWARF_E_NO_BLOCK))
599 : : {
600 : 0 : __libdw_seterrno (error);
601 : : return -1;
602 : : }
603 : :
604 : 0 : int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
605 [ # # ]: 0 : if (result != 1)
606 [ # # ]: 0 : return result ?: 1;
607 : :
608 : : unsigned char *endp;
609 : 0 : unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
610 : : DWARF_E_NO_LOCLIST, &endp, NULL);
611 [ # # ]: 0 : if (readp == NULL)
612 : : return -1;
613 : :
614 : 0 : Dwarf_Addr base = (Dwarf_Addr) -1;
615 : 0 : size_t got = 0;
616 [ # # ]: 0 : while (got < maxlocs)
617 : : {
618 [ # # ]: 0 : if (endp - readp < attr->cu->address_size * 2)
619 : : {
620 : : invalid:
621 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
622 : : return -1;
623 : : }
624 : :
625 : : Dwarf_Addr begin;
626 : : Dwarf_Addr end;
627 : :
628 : 0 : int status
629 : 0 : = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc,
630 : : &readp, attr->cu->address_size,
631 : : &begin, &end, &base);
632 [ # # ]: 0 : if (status == 2) /* End of list entry. */
633 : : break;
634 [ # # ]: 0 : else if (status == 1) /* Base address selected. */
635 : 0 : continue;
636 [ # # ]: 0 : else if (status < 0)
637 : : return status;
638 : :
639 [ # # ]: 0 : if (endp - readp < 2)
640 : : goto invalid;
641 : :
642 : : /* We have a location expression. */
643 [ # # ][ # # ]: 0 : block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
644 : 0 : block.data = readp;
645 [ # # ]: 0 : if (endp - readp < (ptrdiff_t) block.length)
646 : : goto invalid;
647 : 0 : readp += block.length;
648 : :
649 [ # # ]: 0 : if (base == (Dwarf_Addr) -1)
650 : : {
651 : : /* Fetch the CU's base address. */
652 [ # # ]: 0 : Dwarf_Die cudie = CUDIE (attr->cu);
653 : :
654 : : /* Find the base address of the compilation unit. It will
655 : : normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
656 : : the base address could be overridden by DW_AT_entry_pc. It's
657 : : been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
658 : : for compilation units with discontinuous ranges. */
659 : : Dwarf_Attribute attr_mem;
660 [ # # ]: 0 : if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
661 [ # # ]: 0 : && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
662 : : DW_AT_entry_pc,
663 : : &attr_mem),
664 : : &base) != 0)
665 : : {
666 [ # # ]: 0 : if (INTUSE(dwarf_errno) () != 0)
667 : : return -1;
668 : :
669 : : /* The compiler provided no base address when it should
670 : : have. Buggy GCC does this when it used absolute
671 : : addresses in the location list and no DW_AT_ranges. */
672 : 0 : base = 0;
673 : : }
674 : : }
675 : :
676 [ # # ][ # # ]: 0 : if (address >= base + begin && address < base + end)
677 : : {
678 : : /* This one matches the address. */
679 [ # # ]: 0 : if (llbufs != NULL
680 [ # # ]: 0 : && unlikely (getlocation (attr->cu, &block,
681 : : &llbufs[got], &listlens[got],
682 : : IDX_debug_loc) != 0))
683 : : return -1;
684 : 0 : ++got;
685 : : }
686 : : }
687 : :
688 : 0 : return got;
689 : 7308 : }
|