xref: /titanic_50/usr/src/lib/libdwarf/common/dwarf_loc.c (revision f3e7f55e73a39377d55a030f124cc86b3b66a9cc)
1 /*
2 
3   Copyright (C) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
4   Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of version 2.1 of the GNU Lesser General Public License
8   as published by the Free Software Foundation.
9 
10   This program is distributed in the hope that it would be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14   Further, this software is distributed without any warranty that it is
15   free of the rightful claim of any third person regarding infringement
16   or the like.  Any license provided herein, whether implied or
17   otherwise, applies only to this software file.  Patent licenses, if
18   any, provided herein do not apply to combinations of this program with
19   other software, or any other product whatsoever.
20 
21   You should have received a copy of the GNU Lesser General Public
22   License along with this program; if not, write the Free Software
23   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24   USA.
25 
26   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
27   Mountain View, CA 94043, or:
28 
29   http://www.sgi.com
30 
31   For further information regarding this notice, see:
32 
33   http://oss.sgi.com/projects/GenInfo/NoticeExplan
34 
35 */
36 /* The address of the Free Software Foundation is
37    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
38    Boston, MA 02110-1301, USA.
39    SGI has moved from the Crittenden Lane address.
40 */
41 
42 
43 
44 
45 #include "config.h"
46 #include "dwarf_incl.h"
47 #include "dwarf_loc.h"
48 #include <stdio.h> /* for debugging only. */
49 #include <sys/types.h>
50 
51 /*
52     Given a Dwarf_Block that represents a location expression,
53     this function returns a pointer to a Dwarf_Locdesc struct
54     that has its ld_cents field set to the number of location
55     operators in the block, and its ld_s field pointing to a
56     contiguous block of Dwarf_Loc structs.  However, the
57     ld_lopc and ld_hipc values are uninitialized.  Returns
58     NULL on error.  This function assumes that the length of
59     the block is greater than 0.  Zero length location expressions
60     to represent variables that have been optimized away are
61     handled in the calling function.
62 */
63 static Dwarf_Locdesc *
_dwarf_get_locdesc(Dwarf_Debug dbg,Dwarf_Block * loc_block,Dwarf_Half address_size,Dwarf_Addr lowpc,Dwarf_Addr highpc,Dwarf_Error * error)64 _dwarf_get_locdesc(Dwarf_Debug dbg,
65     Dwarf_Block * loc_block,
66     Dwarf_Half address_size,
67     Dwarf_Addr lowpc,
68     Dwarf_Addr highpc,
69     Dwarf_Error * error)
70 {
71     /* Size of the block containing the location expression. */
72     Dwarf_Unsigned loc_len = 0;
73 
74     /* Sweeps the block containing the location expression. */
75     Dwarf_Small *loc_ptr = 0;
76 
77     /* Current location operator. */
78     Dwarf_Small atom = 0;
79 
80     /* Offset of current operator from start of block. */
81     Dwarf_Unsigned offset = 0;
82 
83     /* Operands of current location operator. */
84     Dwarf_Unsigned operand1, operand2;
85 
86     /* Used to chain the Dwarf_Loc_Chain_s structs. */
87     Dwarf_Loc_Chain curr_loc = NULL;
88     Dwarf_Loc_Chain prev_loc = NULL;
89     Dwarf_Loc_Chain head_loc = NULL;
90 
91     /* Count of the number of location operators. */
92     Dwarf_Unsigned op_count = 0;
93 
94     /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */
95     Dwarf_Loc *block_loc = 0;
96 
97     /* Dwarf_Locdesc pointer to be returned. */
98     Dwarf_Locdesc *locdesc = 0;
99 
100     Dwarf_Word leb128_length = 0;
101     Dwarf_Unsigned i = 0;
102 
103     /* ***** BEGIN CODE ***** */
104 
105     loc_len = loc_block->bl_len;
106     loc_ptr = loc_block->bl_data;
107 
108     offset = 0;
109     op_count = 0;
110     while (offset < loc_len) {
111 
112         operand1 = 0;
113         operand2 = 0;
114         op_count++;
115 
116         atom = *(Dwarf_Small *) loc_ptr;
117         loc_ptr++;
118         offset++;
119 
120         curr_loc =
121             (Dwarf_Loc_Chain) _dwarf_get_alloc(dbg, DW_DLA_LOC_CHAIN,
122                                                1);
123         if (curr_loc == NULL) {
124             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
125             return (NULL);
126         }
127         curr_loc->lc_offset = offset;
128         curr_loc->lc_atom = atom;
129         switch (atom) {
130 
131         case DW_OP_reg0:
132         case DW_OP_reg1:
133         case DW_OP_reg2:
134         case DW_OP_reg3:
135         case DW_OP_reg4:
136         case DW_OP_reg5:
137         case DW_OP_reg6:
138         case DW_OP_reg7:
139         case DW_OP_reg8:
140         case DW_OP_reg9:
141         case DW_OP_reg10:
142         case DW_OP_reg11:
143         case DW_OP_reg12:
144         case DW_OP_reg13:
145         case DW_OP_reg14:
146         case DW_OP_reg15:
147         case DW_OP_reg16:
148         case DW_OP_reg17:
149         case DW_OP_reg18:
150         case DW_OP_reg19:
151         case DW_OP_reg20:
152         case DW_OP_reg21:
153         case DW_OP_reg22:
154         case DW_OP_reg23:
155         case DW_OP_reg24:
156         case DW_OP_reg25:
157         case DW_OP_reg26:
158         case DW_OP_reg27:
159         case DW_OP_reg28:
160         case DW_OP_reg29:
161         case DW_OP_reg30:
162         case DW_OP_reg31:
163             break;
164 
165         case DW_OP_regx:
166             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
167             loc_ptr = loc_ptr + leb128_length;
168             offset = offset + leb128_length;
169             break;
170 
171         case DW_OP_lit0:
172         case DW_OP_lit1:
173         case DW_OP_lit2:
174         case DW_OP_lit3:
175         case DW_OP_lit4:
176         case DW_OP_lit5:
177         case DW_OP_lit6:
178         case DW_OP_lit7:
179         case DW_OP_lit8:
180         case DW_OP_lit9:
181         case DW_OP_lit10:
182         case DW_OP_lit11:
183         case DW_OP_lit12:
184         case DW_OP_lit13:
185         case DW_OP_lit14:
186         case DW_OP_lit15:
187         case DW_OP_lit16:
188         case DW_OP_lit17:
189         case DW_OP_lit18:
190         case DW_OP_lit19:
191         case DW_OP_lit20:
192         case DW_OP_lit21:
193         case DW_OP_lit22:
194         case DW_OP_lit23:
195         case DW_OP_lit24:
196         case DW_OP_lit25:
197         case DW_OP_lit26:
198         case DW_OP_lit27:
199         case DW_OP_lit28:
200         case DW_OP_lit29:
201         case DW_OP_lit30:
202         case DW_OP_lit31:
203             operand1 = atom - DW_OP_lit0;
204             break;
205 
206         case DW_OP_addr:
207             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned,
208                            loc_ptr, address_size);
209             loc_ptr += address_size;
210             offset += address_size;
211             break;
212 
213         case DW_OP_const1u:
214             operand1 = *(Dwarf_Small *) loc_ptr;
215             loc_ptr = loc_ptr + 1;
216             offset = offset + 1;
217             break;
218 
219         case DW_OP_const1s:
220             operand1 = *(Dwarf_Sbyte *) loc_ptr;
221             SIGN_EXTEND(operand1,1);
222             loc_ptr = loc_ptr + 1;
223             offset = offset + 1;
224             break;
225 
226         case DW_OP_const2u:
227             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
228             loc_ptr = loc_ptr + 2;
229             offset = offset + 2;
230             break;
231 
232         case DW_OP_const2s:
233             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
234             SIGN_EXTEND(operand1,2);
235             loc_ptr = loc_ptr + 2;
236             offset = offset + 2;
237             break;
238 
239         case DW_OP_const4u:
240             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
241             loc_ptr = loc_ptr + 4;
242             offset = offset + 4;
243             break;
244 
245         case DW_OP_const4s:
246             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
247             SIGN_EXTEND(operand1,4);
248             loc_ptr = loc_ptr + 4;
249             offset = offset + 4;
250             break;
251 
252         case DW_OP_const8u:
253             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8);
254             loc_ptr = loc_ptr + 8;
255             offset = offset + 8;
256             break;
257 
258         case DW_OP_const8s:
259             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8);
260             loc_ptr = loc_ptr + 8;
261             offset = offset + 8;
262             break;
263 
264         case DW_OP_constu:
265             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
266             loc_ptr = loc_ptr + leb128_length;
267             offset = offset + leb128_length;
268             break;
269 
270         case DW_OP_consts:
271             operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
272             loc_ptr = loc_ptr + leb128_length;
273             offset = offset + leb128_length;
274             break;
275 
276         case DW_OP_fbreg:
277             operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
278             loc_ptr = loc_ptr + leb128_length;
279             offset = offset + leb128_length;
280             break;
281 
282         case DW_OP_breg0:
283         case DW_OP_breg1:
284         case DW_OP_breg2:
285         case DW_OP_breg3:
286         case DW_OP_breg4:
287         case DW_OP_breg5:
288         case DW_OP_breg6:
289         case DW_OP_breg7:
290         case DW_OP_breg8:
291         case DW_OP_breg9:
292         case DW_OP_breg10:
293         case DW_OP_breg11:
294         case DW_OP_breg12:
295         case DW_OP_breg13:
296         case DW_OP_breg14:
297         case DW_OP_breg15:
298         case DW_OP_breg16:
299         case DW_OP_breg17:
300         case DW_OP_breg18:
301         case DW_OP_breg19:
302         case DW_OP_breg20:
303         case DW_OP_breg21:
304         case DW_OP_breg22:
305         case DW_OP_breg23:
306         case DW_OP_breg24:
307         case DW_OP_breg25:
308         case DW_OP_breg26:
309         case DW_OP_breg27:
310         case DW_OP_breg28:
311         case DW_OP_breg29:
312         case DW_OP_breg30:
313         case DW_OP_breg31:
314             operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
315             loc_ptr = loc_ptr + leb128_length;
316             offset = offset + leb128_length;
317             break;
318 
319         case DW_OP_bregx:
320             /* uleb reg num followed by sleb offset */
321             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
322             loc_ptr = loc_ptr + leb128_length;
323             offset = offset + leb128_length;
324 
325             operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
326             loc_ptr = loc_ptr + leb128_length;
327             offset = offset + leb128_length;
328             break;
329 
330         case DW_OP_dup:
331         case DW_OP_drop:
332             break;
333 
334         case DW_OP_pick:
335             operand1 = *(Dwarf_Small *) loc_ptr;
336             loc_ptr = loc_ptr + 1;
337             offset = offset + 1;
338             break;
339 
340         case DW_OP_over:
341         case DW_OP_swap:
342         case DW_OP_rot:
343         case DW_OP_deref:
344             break;
345 
346         case DW_OP_deref_size:
347             operand1 = *(Dwarf_Small *) loc_ptr;
348             loc_ptr = loc_ptr + 1;
349             offset = offset + 1;
350             break;
351 
352         case DW_OP_xderef:
353             break;
354 
355         case DW_OP_xderef_size:
356             operand1 = *(Dwarf_Small *) loc_ptr;
357             loc_ptr = loc_ptr + 1;
358             offset = offset + 1;
359             break;
360 
361         case DW_OP_abs:
362         case DW_OP_and:
363         case DW_OP_div:
364         case DW_OP_minus:
365         case DW_OP_mod:
366         case DW_OP_mul:
367         case DW_OP_neg:
368         case DW_OP_not:
369         case DW_OP_or:
370         case DW_OP_plus:
371             break;
372 
373         case DW_OP_plus_uconst:
374             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
375             loc_ptr = loc_ptr + leb128_length;
376             offset = offset + leb128_length;
377             break;
378 
379         case DW_OP_shl:
380         case DW_OP_shr:
381         case DW_OP_shra:
382         case DW_OP_xor:
383             break;
384 
385         case DW_OP_le:
386         case DW_OP_ge:
387         case DW_OP_eq:
388         case DW_OP_lt:
389         case DW_OP_gt:
390         case DW_OP_ne:
391             break;
392 
393         case DW_OP_skip:
394         case DW_OP_bra:
395             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
396             loc_ptr = loc_ptr + 2;
397             offset = offset + 2;
398             break;
399 
400         case DW_OP_piece:
401             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
402             loc_ptr = loc_ptr + leb128_length;
403             offset = offset + leb128_length;
404             break;
405 
406         case DW_OP_nop:
407             break;
408         case DW_OP_push_object_address: /* DWARF3 */
409             break;
410         case DW_OP_call2:       /* DWARF3 */
411             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
412             loc_ptr = loc_ptr + 2;
413             offset = offset + 2;
414             break;
415 
416         case DW_OP_call4:       /* DWARF3 */
417             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
418             loc_ptr = loc_ptr + 4;
419             offset = offset + 4;
420             break;
421         case DW_OP_call_ref:    /* DWARF3 */
422             READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr,
423                            dbg->de_length_size);
424             loc_ptr = loc_ptr + dbg->de_length_size;
425             offset = offset + dbg->de_length_size;
426             break;
427 
428         case DW_OP_form_tls_address:    /* DWARF3f */
429             break;
430         case DW_OP_call_frame_cfa:      /* DWARF3f */
431             break;
432         case DW_OP_bit_piece:   /* DWARF3f */
433             /* uleb size in bits followed by uleb offset in bits */
434             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
435             loc_ptr = loc_ptr + leb128_length;
436             offset = offset + leb128_length;
437 
438             operand2 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
439             loc_ptr = loc_ptr + leb128_length;
440             offset = offset + leb128_length;
441             break;
442         case DW_OP_implicit_value: /* DWARF4 */
443             /* uleb length of value bytes followed by that
444                number of bytes of the value. */
445             operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
446             loc_ptr = loc_ptr + leb128_length;
447             offset = offset + leb128_length;
448 
449             /* Second operand is block of 'operand1' bytes of stuff. */
450             /* This using the second operand as a pointer
451                is quite ugly. */
452             /* This gets an ugly compiler warning. Sorry. */
453             operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr;
454             offset = offset + operand1;
455             loc_ptr = loc_ptr + operand1;
456             break;
457         case DW_OP_stack_value:  /* DWARF4 */
458             break;
459 
460 
461         default:
462             _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
463             return (NULL);
464         }
465 
466 
467         curr_loc->lc_number = operand1;
468         curr_loc->lc_number2 = operand2;
469 
470         if (head_loc == NULL)
471             head_loc = prev_loc = curr_loc;
472         else {
473             prev_loc->lc_next = curr_loc;
474             prev_loc = curr_loc;
475         }
476     }
477 
478     block_loc =
479         (Dwarf_Loc *) _dwarf_get_alloc(dbg, DW_DLA_LOC_BLOCK, op_count);
480     if (block_loc == NULL) {
481         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
482         return (NULL);
483     }
484 
485     curr_loc = head_loc;
486     for (i = 0; i < op_count; i++) {
487         (block_loc + i)->lr_atom = curr_loc->lc_atom;
488         (block_loc + i)->lr_number = curr_loc->lc_number;
489         (block_loc + i)->lr_number2 = curr_loc->lc_number2;
490         (block_loc + i)->lr_offset = curr_loc->lc_offset;
491 
492         prev_loc = curr_loc;
493         curr_loc = curr_loc->lc_next;
494         dwarf_dealloc(dbg, prev_loc, DW_DLA_LOC_CHAIN);
495     }
496 
497     locdesc =
498         (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1);
499     if (locdesc == NULL) {
500         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
501         return (NULL);
502     }
503 
504     locdesc->ld_cents = op_count;
505     locdesc->ld_s = block_loc;
506     locdesc->ld_from_loclist = loc_block->bl_from_loclist;
507     locdesc->ld_section_offset = loc_block->bl_section_offset;
508     locdesc->ld_lopc = lowpc;
509     locdesc->ld_hipc = highpc;
510 
511     return (locdesc);
512 }
513 
514 /* Using a loclist offset to get the in-memory
515    address of .debug_loc data to read, returns the loclist
516    'header' info in return_block.
517 */
518 
519 #define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
520 
521 static int
_dwarf_read_loc_section(Dwarf_Debug dbg,Dwarf_Block * return_block,Dwarf_Addr * lowpc,Dwarf_Addr * hipc,Dwarf_Off sec_offset,Dwarf_Half address_size,Dwarf_Error * error)522 _dwarf_read_loc_section(Dwarf_Debug dbg,
523                         Dwarf_Block * return_block,
524                         Dwarf_Addr * lowpc, Dwarf_Addr * hipc,
525                         Dwarf_Off sec_offset,
526                         Dwarf_Half address_size,
527                         Dwarf_Error * error)
528 {
529     Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset;
530 
531     Dwarf_Addr start_addr = 0;
532     Dwarf_Addr end_addr = 0;
533     Dwarf_Half exprblock_size = 0;
534     Dwarf_Unsigned exprblock_off =
535         2 * address_size + sizeof(Dwarf_Half);
536 
537     if (sec_offset >= dbg->de_debug_loc.dss_size) {
538         /* We're at the end. No more present. */
539         return DW_DLV_NO_ENTRY;
540     }
541 
542     /* If it goes past end, error */
543     if (exprblock_off > dbg->de_debug_loc.dss_size) {
544         _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
545         return DW_DLV_ERROR;
546     }
547 
548     READ_UNALIGNED(dbg, start_addr, Dwarf_Addr, beg, address_size);
549     READ_UNALIGNED(dbg, end_addr, Dwarf_Addr,
550                    beg + address_size, address_size);
551     if (start_addr == 0 && end_addr == 0) {
552         /* If start_addr and end_addr are 0, it's the end and no
553            exprblock_size field follows. */
554         exprblock_size = 0;
555         exprblock_off -= sizeof(Dwarf_Half);
556     } else if (start_addr == MAX_ADDR) {
557         /* end address is a base address, no exprblock_size field here
558            either */
559         exprblock_size = 0;
560         exprblock_off -= sizeof(Dwarf_Half);
561     } else {
562 
563         READ_UNALIGNED(dbg, exprblock_size, Dwarf_Half,
564                        beg + 2 * address_size, sizeof(Dwarf_Half));
565         /* exprblock_size can be zero, means no expression */
566         if ((exprblock_off + exprblock_size) > dbg->de_debug_loc.dss_size) {
567             _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
568             return DW_DLV_ERROR;
569         }
570     }
571 #undef MAX_ADDR
572     *lowpc = start_addr;
573     *hipc = end_addr;
574 
575     return_block->bl_len = exprblock_size;
576     return_block->bl_from_loclist = 1;
577     return_block->bl_data = beg + exprblock_off;
578     return_block->bl_section_offset =
579         ((Dwarf_Small *) return_block->bl_data) - dbg->de_debug_loc.dss_data;
580 
581     return DW_DLV_OK;
582 
583 }
584 static int
_dwarf_get_loclist_count(Dwarf_Debug dbg,Dwarf_Off loclist_offset,Dwarf_Half address_size,int * loclist_count,Dwarf_Error * error)585 _dwarf_get_loclist_count(Dwarf_Debug dbg,
586                          Dwarf_Off loclist_offset,
587                          Dwarf_Half address_size,
588                          int *loclist_count, Dwarf_Error * error)
589 {
590     int count = 0;
591     Dwarf_Off offset = loclist_offset;
592 
593 
594     for (;;) {
595         Dwarf_Block b;
596         Dwarf_Addr lowpc;
597         Dwarf_Addr highpc;
598         int res = _dwarf_read_loc_section(dbg, &b,
599                   &lowpc, &highpc,
600                   offset, address_size,error);
601 
602         if (res != DW_DLV_OK) {
603             return res;
604         }
605         offset = b.bl_len + b.bl_section_offset;
606         if (lowpc == 0 && highpc == 0) {
607             break;
608         }
609         count++;
610     }
611     *loclist_count = count;
612     return DW_DLV_OK;
613 }
614 
615 /* Helper routine to avoid code duplication.
616 */
617 static int
_dwarf_setup_loc(Dwarf_Attribute attr,Dwarf_Debug * dbg_ret,Dwarf_CU_Context * cucontext_ret,Dwarf_Half * form_ret,Dwarf_Error * error)618 _dwarf_setup_loc(Dwarf_Attribute attr,
619                  Dwarf_Debug * dbg_ret,
620                  Dwarf_CU_Context *cucontext_ret,
621                  Dwarf_Half * form_ret, Dwarf_Error * error)
622 {
623     Dwarf_Debug dbg = 0;
624     Dwarf_Half form = 0;
625     int blkres = DW_DLV_ERROR;
626 
627     if (attr == NULL) {
628         _dwarf_error(NULL, error, DW_DLE_ATTR_NULL);
629         return (DW_DLV_ERROR);
630     }
631     if (attr->ar_cu_context == NULL) {
632         _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT);
633         return (DW_DLV_ERROR);
634     }
635     *cucontext_ret = attr->ar_cu_context;
636 
637     dbg = attr->ar_cu_context->cc_dbg;
638     if (dbg == NULL) {
639         _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
640         return (DW_DLV_ERROR);
641     }
642     *dbg_ret = dbg;
643     blkres = dwarf_whatform(attr, &form, error);
644     if (blkres != DW_DLV_OK) {
645         _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
646         return blkres;
647     }
648     *form_ret = form;
649     return DW_DLV_OK;
650 }
651 
652 /* Helper routine  to avoid code duplication.
653 */
654 static int
_dwarf_get_loclist_header_start(Dwarf_Debug dbg,Dwarf_Attribute attr,Dwarf_Unsigned * loclist_offset,Dwarf_Error * error)655 _dwarf_get_loclist_header_start(Dwarf_Debug dbg,
656                                 Dwarf_Attribute attr,
657                                 Dwarf_Unsigned * loclist_offset,
658                                 Dwarf_Error * error)
659 {
660     int blkres = dwarf_formudata(attr, loclist_offset, error);
661     if (blkres != DW_DLV_OK) {
662         return (blkres);
663     }
664 
665     if (!dbg->de_debug_loc.dss_data) {
666         int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error);
667         if (secload != DW_DLV_OK) {
668             return secload;
669         }
670     }
671     return DW_DLV_OK;
672 }
673 
674 /* When llbuf (see dwarf_loclist_n) is partially set up
675    and an error is encountered, tear it down as it
676    won't be used.
677 */
678 static void
_dwarf_cleanup_llbuf(Dwarf_Debug dbg,Dwarf_Locdesc ** llbuf,int count)679 _dwarf_cleanup_llbuf(Dwarf_Debug dbg, Dwarf_Locdesc ** llbuf, int count)
680 {
681     int i;
682     for (i = 0; i < count; ++i) {
683         dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
684         dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC);
685     }
686     dwarf_dealloc(dbg, llbuf, DW_DLA_LIST);
687 }
688 
689 /*
690         Handles simple location entries and loclists.
691         Returns all the Locdesc's thru llbuf.
692 
693 */
694 int
dwarf_loclist_n(Dwarf_Attribute attr,Dwarf_Locdesc *** llbuf_out,Dwarf_Signed * listlen_out,Dwarf_Error * error)695 dwarf_loclist_n(Dwarf_Attribute attr,
696                 Dwarf_Locdesc *** llbuf_out,
697                 Dwarf_Signed * listlen_out, Dwarf_Error * error)
698 {
699     Dwarf_Debug dbg;
700 
701     /*
702        Dwarf_Attribute that describes the DW_AT_location in die, if
703        present. */
704     Dwarf_Attribute loc_attr = attr;
705 
706     /* Dwarf_Block that describes a single location expression. */
707     Dwarf_Block loc_block;
708 
709     /* A pointer to the current Dwarf_Locdesc read. */
710     Dwarf_Locdesc *locdesc = 0;
711 
712     Dwarf_Half form = 0;
713     Dwarf_Addr lowpc = 0;
714     Dwarf_Addr highpc = 0;
715     Dwarf_Signed listlen = 0;
716     Dwarf_Locdesc **llbuf = 0;
717     Dwarf_CU_Context cucontext = 0;
718     unsigned address_size = 0;
719 
720     int blkres = DW_DLV_ERROR;
721     int setup_res = DW_DLV_ERROR;
722 
723     /* ***** BEGIN CODE ***** */
724     setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error);
725     if (setup_res != DW_DLV_OK) {
726         return setup_res;
727     }
728     address_size = cucontext->cc_address_size;
729     /* If this is a form_block then it's a location expression. If it's
730        DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */
731     if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP ||
732           cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) &&
733           (form == DW_FORM_data4 || form == DW_FORM_data8)) ||
734          (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 &&
735             form == DW_FORM_sec_offset))
736         {
737 
738 
739         /* A reference to .debug_loc, with an offset in .debug_loc of a
740            loclist */
741         Dwarf_Unsigned loclist_offset = 0;
742         int off_res  = DW_DLV_ERROR;
743         int count_res = DW_DLV_ERROR;
744         int loclist_count;
745         int lli;
746 
747         off_res = _dwarf_get_loclist_header_start(dbg,
748                                                   attr, &loclist_offset,
749                                                   error);
750         if (off_res != DW_DLV_OK) {
751             return off_res;
752         }
753         count_res = _dwarf_get_loclist_count(dbg, loclist_offset,
754                                              address_size,
755                                              &loclist_count, error);
756         listlen = loclist_count;
757         if (count_res != DW_DLV_OK) {
758             return count_res;
759         }
760         if (loclist_count == 0) {
761             return DW_DLV_NO_ENTRY;
762         }
763 
764         llbuf = (Dwarf_Locdesc **)
765             _dwarf_get_alloc(dbg, DW_DLA_LIST, loclist_count);
766         if (!llbuf) {
767             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
768             return (DW_DLV_ERROR);
769         }
770 
771         for (lli = 0; lli < loclist_count; ++lli) {
772             blkres = _dwarf_read_loc_section(dbg, &loc_block,
773                 &lowpc,
774                 &highpc,
775                 loclist_offset,
776                 address_size,
777                 error);
778             if (blkres != DW_DLV_OK) {
779                 _dwarf_cleanup_llbuf(dbg, llbuf, lli);
780                 return (blkres);
781             }
782             locdesc = _dwarf_get_locdesc(dbg, &loc_block,
783                 address_size,
784                 lowpc, highpc, error);
785             if (locdesc == NULL) {
786                 _dwarf_cleanup_llbuf(dbg, llbuf, lli);
787                 /* low level error already set: let it be passed back */
788                 return (DW_DLV_ERROR);
789             }
790             llbuf[lli] = locdesc;
791 
792             /* Now get to next loclist entry offset. */
793             loclist_offset = loc_block.bl_section_offset +
794                 loc_block.bl_len;
795         }
796 
797 
798     } else {
799         Dwarf_Block *tblock = 0;
800 
801         blkres = dwarf_formblock(loc_attr, &tblock, error);
802         if (blkres != DW_DLV_OK) {
803             return (blkres);
804         }
805         loc_block = *tblock;
806         /* We copied tblock contents to the stack var, so can dealloc
807            tblock now.  Avoids leaks. */
808         dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK);
809         listlen = 1; /* One by definition of a location entry. */
810         lowpc = 0;   /* HACK */
811         highpc = (Dwarf_Unsigned) (-1LL); /* HACK */
812 
813         /* An empty location description (block length 0) means the
814            code generator emitted no variable, the variable was not
815            generated, it was unused or perhaps never tested after being
816            set. Dwarf2, section 2.4.1 In other words, it is not an
817            error, and we don't test for block length 0 specially here. */
818         locdesc = _dwarf_get_locdesc(dbg, &loc_block,
819             address_size,
820             lowpc, highpc, error);
821         if (locdesc == NULL) {
822             /* low level error already set: let it be passed back */
823             return (DW_DLV_ERROR);
824         }
825         llbuf = (Dwarf_Locdesc **)
826             _dwarf_get_alloc(dbg, DW_DLA_LIST, listlen);
827         if (!llbuf) {
828             /* Free the locdesc we allocated but won't use. */
829             dwarf_dealloc(dbg, locdesc, DW_DLA_LOCDESC);
830             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
831             return (DW_DLV_ERROR);
832         }
833         llbuf[0] = locdesc;
834     }
835 
836     *llbuf_out = llbuf;
837     *listlen_out = listlen;
838     return (DW_DLV_OK);
839 }
840 
841 
842 /*
843         Handles only a location expression.
844         If called on a loclist, just returns one of those.
845         Cannot not handle a real loclist.
846         It returns the location expression as a loclist with
847         a single entry.
848         See dwarf_loclist_n() which handles any number
849         of location list entries.
850 
851         This is the original definition, and it simply
852         does not work for loclists. Kept for compatibility.
853 */
854 int
dwarf_loclist(Dwarf_Attribute attr,Dwarf_Locdesc ** llbuf,Dwarf_Signed * listlen,Dwarf_Error * error)855 dwarf_loclist(Dwarf_Attribute attr,
856     Dwarf_Locdesc ** llbuf,
857     Dwarf_Signed * listlen, Dwarf_Error * error)
858 {
859     Dwarf_Debug dbg;
860 
861     /* Dwarf_Attribute that describes the DW_AT_location in die, if
862        present. */
863     Dwarf_Attribute loc_attr = attr;
864 
865     /* Dwarf_Block that describes a single location expression. */
866     Dwarf_Block loc_block;
867 
868     /* A pointer to the current Dwarf_Locdesc read. */
869     Dwarf_Locdesc *locdesc = 0;
870 
871     Dwarf_Half form = 0;
872     Dwarf_Addr lowpc = 0;
873     Dwarf_Addr highpc = 0;
874     Dwarf_CU_Context cucontext = 0;
875     unsigned address_size = 0;
876 
877     int blkres = DW_DLV_ERROR;
878     int setup_res = DW_DLV_ERROR;
879 
880     /* ***** BEGIN CODE ***** */
881     setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error);
882     if (setup_res != DW_DLV_OK) {
883         return setup_res;
884     }
885     address_size = cucontext->cc_address_size;
886     /* If this is a form_block then it's a location expression. If it's
887        DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */
888     if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP ||
889           cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) &&
890           (form == DW_FORM_data4 || form == DW_FORM_data8)) ||
891          (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 &&
892             form == DW_FORM_sec_offset))
893         {
894 
895         /* A reference to .debug_loc, with an offset in .debug_loc of a
896            loclist */
897         Dwarf_Unsigned loclist_offset = 0;
898         int off_res = DW_DLV_ERROR;
899 
900         off_res = _dwarf_get_loclist_header_start(dbg,
901             attr, &loclist_offset,
902             error);
903         if (off_res != DW_DLV_OK) {
904             return off_res;
905         }
906 
907         /* With dwarf_loclist, just read a single entry */
908         blkres = _dwarf_read_loc_section(dbg, &loc_block,
909             &lowpc,
910             &highpc,
911             loclist_offset,
912             address_size,
913             error);
914         if (blkres != DW_DLV_OK) {
915             return (blkres);
916         }
917     } else {
918         Dwarf_Block *tblock = 0;
919 
920         blkres = dwarf_formblock(loc_attr, &tblock, error);
921         if (blkres != DW_DLV_OK) {
922             return (blkres);
923         }
924         loc_block = *tblock;
925         /* We copied tblock contents to the stack var, so can dealloc
926            tblock now.  Avoids leaks. */
927         dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK);
928         lowpc = 0;              /* HACK */
929         highpc = (Dwarf_Unsigned) (-1LL);       /* HACK */
930     }
931 
932     /* An empty location description (block length 0) means the code
933        generator emitted no variable, the variable was not generated,
934        it was unused or perhaps never tested after being set. Dwarf2,
935        section 2.4.1 In other words, it is not an error, and we don't
936        test for block length 0 specially here.
937        See *dwarf_loclist_n() which handles the general case, this case
938        handles only a single location expression.  */
939     locdesc = _dwarf_get_locdesc(dbg, &loc_block,
940         address_size,
941         lowpc, highpc, error);
942     if (locdesc == NULL) {
943         /* low level error already set: let it be passed back */
944         return (DW_DLV_ERROR);
945     }
946 
947     *llbuf = locdesc;
948     *listlen = 1;
949     return (DW_DLV_OK);
950 }
951 
952 
953 
954 /*
955         Handles only a location expression.
956         It returns the location expression as a loclist with
957         a single entry.
958 
959         Usable to access dwarf expressions from any source, but
960         specifically from
961             DW_CFA_def_cfa_expression
962             DW_CFA_expression
963             DW_CFA_val_expression
964 
965         expression_in must point to a valid dwarf expression
966         set of bytes of length expression_length. Not
967         a DW_FORM_block*, just the expression bytes.
968 
969         If the address_size != de_pointer_size this will not work
970         right. FIXME.
971 */
972 int
dwarf_loclist_from_expr(Dwarf_Debug dbg,Dwarf_Ptr expression_in,Dwarf_Unsigned expression_length,Dwarf_Locdesc ** llbuf,Dwarf_Signed * listlen,Dwarf_Error * error)973 dwarf_loclist_from_expr(Dwarf_Debug dbg,
974     Dwarf_Ptr expression_in,
975     Dwarf_Unsigned expression_length,
976     Dwarf_Locdesc ** llbuf,
977     Dwarf_Signed * listlen, Dwarf_Error * error)
978 {
979     int res = 0;
980     Dwarf_Half addr_size =  dbg->de_pointer_size;
981     res = dwarf_loclist_from_expr_a(dbg,expression_in,
982         expression_length, addr_size,llbuf,listlen,error);
983     return res;
984 }
985 /* New April 27 2009. Adding addr_size argument for the rare
986  * cases where an object has CUs with a different address_size. */
987 int
dwarf_loclist_from_expr_a(Dwarf_Debug dbg,Dwarf_Ptr expression_in,Dwarf_Unsigned expression_length,Dwarf_Half addr_size,Dwarf_Locdesc ** llbuf,Dwarf_Signed * listlen,Dwarf_Error * error)988 dwarf_loclist_from_expr_a(Dwarf_Debug dbg,
989     Dwarf_Ptr expression_in,
990     Dwarf_Unsigned expression_length,
991     Dwarf_Half addr_size,
992     Dwarf_Locdesc ** llbuf,
993     Dwarf_Signed * listlen, Dwarf_Error * error)
994 {
995     /* Dwarf_Block that describes a single location expression. */
996     Dwarf_Block loc_block;
997 
998     /* A pointer to the current Dwarf_Locdesc read. */
999     Dwarf_Locdesc *locdesc = 0;
1000     Dwarf_Addr lowpc = 0;
1001     Dwarf_Addr highpc = (Dwarf_Unsigned) (-1LL);
1002 
1003     memset(&loc_block,0,sizeof(loc_block));
1004     loc_block.bl_len = expression_length;
1005     loc_block.bl_data = expression_in;
1006     loc_block.bl_from_loclist = 0; /* Not from loclist. */
1007     loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */
1008 
1009     /* An empty location description (block length 0) means the code
1010     generator emitted no variable, the variable was not generated,
1011     it was unused or perhaps never tested after being set. Dwarf2,
1012     section 2.4.1 In other words, it is not an error, and we don't
1013     test for block length 0 specially here.  */
1014     locdesc = _dwarf_get_locdesc(dbg, &loc_block,
1015         addr_size,lowpc, highpc, error);
1016     if (locdesc == NULL) {
1017         /* low level error already set: let it be passed back */
1018         return (DW_DLV_ERROR);
1019     }
1020 
1021     *llbuf = locdesc;
1022     *listlen = 1;
1023     return (DW_DLV_OK);
1024 }
1025 
1026 /* Usable to read a single loclist or to read a block of them
1027    or to read an entire section's loclists.
1028 
1029    It's broken because it's not safe to read a loclist entry
1030    when we do not know the address size (in any object where
1031    address size can vary by compilation unit).
1032 */
1033 
1034  /*ARGSUSED*/ int
dwarf_get_loclist_entry(Dwarf_Debug dbg,Dwarf_Unsigned offset,Dwarf_Addr * hipc_offset,Dwarf_Addr * lopc_offset,Dwarf_Ptr * data,Dwarf_Unsigned * entry_len,Dwarf_Unsigned * next_entry,Dwarf_Error * error)1035 dwarf_get_loclist_entry(Dwarf_Debug dbg,
1036     Dwarf_Unsigned offset,
1037     Dwarf_Addr * hipc_offset,
1038     Dwarf_Addr * lopc_offset,
1039     Dwarf_Ptr * data,
1040     Dwarf_Unsigned * entry_len,
1041     Dwarf_Unsigned * next_entry,
1042     Dwarf_Error * error)
1043 {
1044     Dwarf_Block b;
1045     Dwarf_Addr lowpc = 0;
1046     Dwarf_Addr highpc = 0;
1047     Dwarf_Half address_size = 0;
1048     int res = DW_DLV_ERROR;
1049 
1050     if (!dbg->de_debug_loc.dss_data) {
1051         int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error);
1052         if (secload != DW_DLV_OK) {
1053             return secload;
1054         }
1055     }
1056 
1057     /* FIXME: address_size is not necessarily the same in every frame. */
1058     address_size = dbg->de_pointer_size;
1059     res = _dwarf_read_loc_section(dbg,
1060          &b, &lowpc, &highpc, offset,
1061          address_size,error);
1062     if (res != DW_DLV_OK) {
1063         return res;
1064     }
1065     *hipc_offset = highpc;
1066     *lopc_offset = lowpc;
1067     *entry_len = b.bl_len;
1068     *data = b.bl_data;
1069     *next_entry = b.bl_len + b.bl_section_offset;
1070     return DW_DLV_OK;
1071 }
1072 
1073 
1074