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