xref: /titanic_41/usr/src/tools/ctf/dwarf/common/dwarf_frame.c (revision 49d3bc91e27cd871b950d56c01398fa2f2e12ab4)
1 /*
2 
3   Copyright (C) 2000, 2002 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 <stdio.h>
41 #include <stdlib.h>
42 #include "dwarf_frame.h"
43 #include "dwarf_arange.h"	/* using Arange as a way to build a
44 				   list */
45 
46 
47 static int
48   __dwarf_get_fde_list_internal(Dwarf_Debug dbg,
49 				Dwarf_Cie ** cie_data,
50 				Dwarf_Signed * cie_element_count,
51 				Dwarf_Fde ** fde_data,
52 				Dwarf_Signed * fde_element_count,
53 				Dwarf_Small * section_ptr,
54 				Dwarf_Unsigned section_length,
55 				Dwarf_Unsigned cie_id_value,
56 				int use_gnu_cie_calc,
57 				Dwarf_Error * error);
58 
59 /*
60     This function is the heart of the debug_frame stuff.  Don't even
61     think of reading this without reading both the Libdwarf and
62     consumer API carefully first.  This function basically executes
63     frame instructions contained in a Cie or an Fde, but does in a
64     number of different ways depending on the information sought.
65     Start_instr_ptr points to the first byte of the frame instruction
66     stream, and final_instr_ptr to the to the first byte after the
67     last.
68 
69     The offsets returned in the frame instructions are factored.  That
70     is they need to be multiplied by either the code_alignment_factor
71     or the data_alignment_factor, as appropriate to obtain the actual
72     offset.  This makes it possible to expand an instruction stream
73     without the corresponding Cie.  However, when an Fde frame instr
74     sequence is being expanded there must be a valid Cie with a pointer
75     to an initial table row.
76 
77 
78     If successful, returns DW_DLV_OK
79 		And sets returned_count thru the pointer
80 		 if make_instr is true.
81 		If make_instr is false returned_count
82 		 should NOT be used by the caller (returned_count
83 		 is set to 0 thru the pointer by this routine...)
84     If unsuccessful, returns DW_DLV_ERROR
85 		and sets returned_error to the error code
86 
87     It does not do a whole lot of input validation being a private
88     function.  Please make sure inputs are valid.
89 
90     (1) If make_instr is true, it makes a list of pointers to
91     Dwarf_Frame_Op structures containing the frame instructions
92     executed.  A pointer to this list is returned in ret_frame_instr.
93     Make_instr is true only when a list of frame instructions is to be
94     returned.  In this case since we are not interested in the contents
95     of the table, the input Cie can be NULL.  This is the only case
96     where the inpute Cie can be NULL.
97 
98     (2) If search_pc is true, frame instructions are executed till
99     either a location is reached that is greater than the search_pc_val
100     provided, or all instructions are executed.  At this point the
101     last row of the table generated is returned in a structure.
102     A pointer to this structure is supplied in table.
103 
104     (3) This function is also used to create the initial table row
105     defined by a Cie.  In this case, the Dwarf_Cie pointer cie, is
106     NULL.  For an FDE, however, cie points to the associated Cie.
107 */
108 static int
109 _dwarf_exec_frame_instr(Dwarf_Bool make_instr,	/* Make list of frame
110 						   instr? */
111 			Dwarf_Frame_Op ** ret_frame_instr,	/* Ptr
112 								   to
113 								   list
114 								   of
115 								   ptrs
116 								   to
117 								   fr
118 								   instrs
119 								 */
120 			Dwarf_Bool search_pc,	/* Search for a pc
121 						   value? */
122 			Dwarf_Addr search_pc_val,	/* Search for
123 							   this pc
124 							   value */
125 			Dwarf_Addr loc,	/* initial location value */
126 			Dwarf_Small * start_instr_ptr,	/* Ptr to start
127 							   of frame
128 							   instrs.  */
129 			Dwarf_Small * final_instr_ptr,	/* Ptr just
130 							   past frame
131 							   instrs.  */
132 			Dwarf_Frame table,	/* Ptr to struct with
133 						   last row.  */
134 			Dwarf_Cie cie,	/* Ptr to Cie used by the Fde.
135 					   */
136 			Dwarf_Debug dbg,	/* Associated
137 						   Dwarf_Debug */
138 			Dwarf_Sword * returned_count,
139 			int *returned_error)
140 {
141     /* Sweeps the frame instructions. */
142     Dwarf_Small *instr_ptr;
143 
144     /* Obvious from the documents. */
145     Dwarf_Small instr, opcode;
146     Dwarf_Small reg_no, reg_noA, reg_noB;
147     Dwarf_Unsigned factored_N_value;
148     Dwarf_Addr new_loc;		/* must be min de_pointer_size bytes */
149     Dwarf_Unsigned adv_loc;	/* must be min de_pointer_size bytes
150 				   and must be at least sizeof
151 				   Dwarf_ufixed */
152 
153     struct Dwarf_Reg_Rule_s reg[DW_FRAME_LAST_REG_NUM];
154 
155 
156     /* This is used to end executing frame instructions.  */
157     /* Becomes true when search_pc is true and loc */
158     /* is greater than search_pc_val.  */
159     Dwarf_Bool search_over = false;
160 
161     /* Used by the DW_FRAME_advance_loc instr */
162     /* to hold the increment in pc value.  */
163     Dwarf_Addr adv_pc;
164 
165     /* Contains the length in bytes of */
166     /* an leb128 encoded number.  */
167     Dwarf_Word leb128_length;
168 
169     /* Counts the number of frame instructions executed.  */
170     Dwarf_Word instr_count = 0;
171 
172     /*
173        These contain the current fields of the current frame
174        instruction. */
175     Dwarf_Small fp_base_op = 0;
176     Dwarf_Small fp_extended_op;
177     Dwarf_Half fp_register;
178     Dwarf_Unsigned fp_offset;
179     Dwarf_Off fp_instr_offset;
180 
181     /*
182        Stack_table points to the row (Dwarf_Frame ie) being pushed or
183        popped by a remember or restore instruction. Top_stack points to
184        the top of the stack of rows. */
185     Dwarf_Frame stack_table;
186     Dwarf_Frame top_stack = NULL;
187 
188     /*
189        These are used only when make_instr is true. Curr_instr is a
190        pointer to the current frame instruction executed.
191        Curr_instr_ptr, head_instr_list, and curr_instr_list are used
192        to form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr
193        is used to deallocate the structs used to form the chain.
194        Head_instr_block points to a contiguous list of pointers to the
195        Dwarf_Frame_Op structs executed. */
196     Dwarf_Frame_Op *curr_instr;
197     Dwarf_Chain curr_instr_item, dealloc_instr_item;
198     Dwarf_Chain head_instr_chain = NULL;
199     Dwarf_Chain tail_instr_chain = NULL;
200     Dwarf_Frame_Op *head_instr_block;
201 
202     /*
203        These are the alignment_factors taken from the Cie provided.
204        When no input Cie is provided they are set to 1, because only
205        factored offsets are required. */
206     Dwarf_Sword code_alignment_factor = 1;
207     Dwarf_Sword data_alignment_factor = 1;
208 
209     /*
210        This flag indicates when an actual alignment factor is needed.
211        So if a frame instruction that computes an offset using an
212        alignment factor is encountered when this flag is set, an error
213        is returned because the Cie did not have a valid augmentation. */
214     Dwarf_Bool need_augmentation = false;
215 
216     Dwarf_Word i;
217 
218     /* Initialize first row from associated Cie. Using temp regs
219        explicity */
220     struct Dwarf_Reg_Rule_s *t1reg;
221     struct Dwarf_Reg_Rule_s *t1end;
222     struct Dwarf_Reg_Rule_s *t2reg;
223 
224 
225     t1reg = reg;
226     t1end = t1reg + DW_FRAME_LAST_REG_NUM;
227     if (cie != NULL && cie->ci_initial_table != NULL) {
228 	t2reg = cie->ci_initial_table->fr_reg;
229 	for (; t1reg < t1end; t1reg++, t2reg++) {
230 	    *t1reg = *t2reg;
231 	}
232     } else {			/* initialize with same_value */
233 	for (; t1reg < t1end; t1reg++) {
234 	    t1reg->ru_is_off = 0;
235 	    t1reg->ru_register = DW_FRAME_SAME_VAL;
236 	    t1reg->ru_offset = 0;
237 	}
238     }
239 
240     /*
241        The idea here is that the code_alignment_factor and
242        data_alignment_factor which are needed for certain instructions
243        are valid only when the Cie has a proper augmentation string.
244        So if the augmentation is not right, only Frame instruction can
245        be read. */
246     if (cie != NULL && cie->ci_augmentation != NULL) {
247 	code_alignment_factor = cie->ci_code_alignment_factor;
248 	data_alignment_factor = cie->ci_data_alignment_factor;
249     } else
250 	need_augmentation = !make_instr;
251 
252     instr_ptr = start_instr_ptr;
253     while ((instr_ptr < final_instr_ptr) && (!search_over)) {
254 
255 
256 	fp_instr_offset = instr_ptr - start_instr_ptr;
257 	instr = *(Dwarf_Small *) instr_ptr;
258 	instr_ptr += sizeof(Dwarf_Small);
259 
260 	fp_base_op = (instr & 0xc0) >> 6;
261 	if ((instr & 0xc0) == 0x00) {
262 	    opcode = instr;	/* is really extended op */
263 	    fp_extended_op = (instr & (~(0xc0))) & 0xff;
264 	} else {
265 	    opcode = instr & 0xc0;	/* is base op */
266 	    fp_extended_op = 0;
267 	}
268 
269 	fp_register = 0;
270 	fp_offset = 0;
271 	switch (opcode) {
272 
273 	case DW_CFA_advance_loc:{
274 				/* base op */
275 		fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK;
276 
277 		if (need_augmentation) {
278 
279 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
280 		    return DW_DLV_ERROR;
281 		}
282 		adv_pc = adv_pc * code_alignment_factor;
283 
284 		search_over = search_pc &&
285 		    (loc + adv_pc > search_pc_val);
286 		/* If gone past pc needed, retain old pc.  */
287 		if (!search_over)
288 		    loc = loc + adv_pc;
289 		break;
290 	    }
291 
292 	case DW_CFA_offset:{	/* base op */
293 		reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
294 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
295 		    *returned_error = DW_DLE_DF_REG_NUM_TOO_HIGH;
296 		    return DW_DLV_ERROR;
297 		}
298 
299 		factored_N_value =
300 		    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
301 		instr_ptr = instr_ptr + leb128_length;
302 
303 		fp_register = reg_no;
304 		fp_offset = factored_N_value;
305 
306 		if (need_augmentation) {
307 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
308 		    return DW_DLV_ERROR;
309 		}
310 
311 		reg[reg_no].ru_is_off = 1;
312 		reg[reg_no].ru_register = DW_FRAME_CFA_COL;
313 		reg[reg_no].ru_offset = factored_N_value *
314 		    data_alignment_factor;
315 
316 		break;
317 	    }
318 
319 	case DW_CFA_restore:{	/* base op */
320 		reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
321 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
322 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
323 		    return DW_DLV_ERROR;
324 		}
325 
326 		fp_register = reg_no;
327 
328 		if (cie != NULL && cie->ci_initial_table != NULL)
329 		    reg[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
330 		else if (!make_instr) {
331 		    *returned_error = (DW_DLE_DF_MAKE_INSTR_NO_INIT);
332 		    return DW_DLV_ERROR;
333 		}
334 
335 		break;
336 	    }
337 	case DW_CFA_set_loc:{
338 		READ_UNALIGNED(dbg, new_loc, Dwarf_Addr,
339 			       instr_ptr, dbg->de_pointer_size);
340 		instr_ptr += dbg->de_pointer_size;
341 		if (new_loc <= loc) {
342 		    *returned_error = (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC);
343 		    return DW_DLV_ERROR;
344 		}
345 
346 		search_over = search_pc && (new_loc > search_pc_val);
347 
348 		/* If gone past pc needed, retain old pc.  */
349 		if (!search_over)
350 		    loc = new_loc;
351 		fp_offset = new_loc;
352 		break;
353 	    }
354 
355 	case DW_CFA_advance_loc1:{
356 		fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr;
357 		instr_ptr += sizeof(Dwarf_Small);
358 
359 		if (need_augmentation) {
360 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
361 		    return DW_DLV_ERROR;
362 		}
363 		adv_loc *= code_alignment_factor;
364 
365 		search_over = search_pc &&
366 		    (loc + adv_loc > search_pc_val);
367 
368 		/* If gone past pc needed, retain old pc.  */
369 		if (!search_over)
370 		    loc = loc + adv_loc;
371 		break;
372 	    }
373 
374 	case DW_CFA_advance_loc2:{
375 		READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
376 			       instr_ptr, sizeof(Dwarf_Half));
377 		instr_ptr += sizeof(Dwarf_Half);
378 		fp_offset = adv_loc;
379 
380 		if (need_augmentation) {
381 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
382 		    return DW_DLV_ERROR;
383 		}
384 		adv_loc *= code_alignment_factor;
385 
386 		search_over = search_pc &&
387 		    (loc + adv_loc > search_pc_val);
388 
389 		/* If gone past pc needed, retain old pc.  */
390 		if (!search_over)
391 		    loc = loc + adv_loc;
392 		break;
393 	    }
394 
395 	case DW_CFA_advance_loc4:{
396 		READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
397 			       instr_ptr, sizeof(Dwarf_ufixed));
398 		instr_ptr += sizeof(Dwarf_ufixed);
399 		fp_offset = adv_loc;
400 
401 		if (need_augmentation) {
402 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
403 		    return DW_DLV_ERROR;
404 		}
405 		adv_loc *= code_alignment_factor;
406 
407 		search_over = search_pc &&
408 		    (loc + adv_loc > search_pc_val);
409 
410 		/* If gone past pc needed, retain old pc.  */
411 		if (!search_over)
412 		    loc = loc + adv_loc;
413 		break;
414 	    }
415 
416 	case DW_CFA_offset_extended:{
417 		Dwarf_Unsigned lreg;
418 
419 		DECODE_LEB128_UWORD(instr_ptr, lreg)
420 		    reg_no = (Dwarf_Small) lreg;
421 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
422 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
423 		    return DW_DLV_ERROR;
424 		}
425 		factored_N_value =
426 		    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
427 		instr_ptr += leb128_length;
428 
429 		if (need_augmentation) {
430 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
431 		    return DW_DLV_ERROR;
432 		}
433 		reg[reg_no].ru_is_off = 1;
434 		reg[reg_no].ru_register = DW_FRAME_CFA_COL;
435 		reg[reg_no].ru_offset = factored_N_value *
436 		    data_alignment_factor;
437 
438 		fp_register = reg_no;
439 		fp_offset = factored_N_value;
440 		break;
441 	    }
442 
443 	case DW_CFA_restore_extended:{
444 		Dwarf_Unsigned lreg;
445 
446 		DECODE_LEB128_UWORD(instr_ptr, lreg)
447 		    reg_no = (Dwarf_Small) lreg;
448 
449 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
450 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
451 		    return DW_DLV_ERROR;
452 		}
453 
454 		if (cie != NULL && cie->ci_initial_table != NULL) {
455 		    reg[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
456 		} else {
457 		    if (!make_instr) {
458 			*returned_error =
459 			    (DW_DLE_DF_MAKE_INSTR_NO_INIT);
460 			return DW_DLV_ERROR;
461 		    }
462 		}
463 
464 		fp_register = reg_no;
465 		break;
466 	    }
467 
468 	case DW_CFA_undefined:{
469 		Dwarf_Unsigned lreg;
470 
471 		DECODE_LEB128_UWORD(instr_ptr, lreg)
472 		    reg_no = (Dwarf_Small) lreg;
473 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
474 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
475 		    return DW_DLV_ERROR;
476 		}
477 
478 		reg[reg_no].ru_is_off = 0;
479 		reg[reg_no].ru_register = DW_FRAME_UNDEFINED_VAL;
480 		reg[reg_no].ru_offset = 0;
481 
482 		fp_register = reg_no;
483 		break;
484 	    }
485 
486 	case DW_CFA_same_value:{
487 		Dwarf_Unsigned lreg;
488 
489 		DECODE_LEB128_UWORD(instr_ptr, lreg)
490 		    reg_no = (Dwarf_Small) lreg;
491 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
492 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
493 		    return DW_DLV_ERROR;
494 		}
495 
496 		reg[reg_no].ru_is_off = 0;
497 		reg[reg_no].ru_register = DW_FRAME_SAME_VAL;
498 		reg[reg_no].ru_offset = 0;
499 		fp_register = reg_no;
500 		break;
501 	    }
502 
503 	case DW_CFA_register:{
504 		Dwarf_Unsigned lreg;
505 
506 		DECODE_LEB128_UWORD(instr_ptr, lreg)
507 		    reg_noA = (Dwarf_Small) lreg;
508 
509 		if (reg_noA > DW_FRAME_LAST_REG_NUM) {
510 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
511 		    return DW_DLV_ERROR;
512 		}
513 
514 		DECODE_LEB128_UWORD(instr_ptr, lreg)
515 		    reg_noB = (Dwarf_Small) lreg;
516 
517 		if (reg_noB > DW_FRAME_LAST_REG_NUM) {
518 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
519 		    return DW_DLV_ERROR;
520 		}
521 
522 
523 		reg[reg_noA].ru_is_off = 0;
524 		reg[reg_noA].ru_register = reg_noB;
525 
526 		reg[reg_noA].ru_offset = 0;
527 
528 		fp_register = reg_noA;
529 		fp_offset = reg_noB;
530 		break;
531 	    }
532 
533 	case DW_CFA_remember_state:{
534 		stack_table = (Dwarf_Frame)
535 		    _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
536 		if (stack_table == NULL) {
537 		    *returned_error = (DW_DLE_DF_ALLOC_FAIL);
538 		    return DW_DLV_ERROR;
539 		}
540 
541 		for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
542 		    stack_table->fr_reg[i] = reg[i];
543 
544 		if (top_stack != NULL)
545 		    stack_table->fr_next = top_stack;
546 		top_stack = stack_table;
547 
548 		break;
549 	    }
550 
551 	case DW_CFA_restore_state:{
552 		if (top_stack == NULL) {
553 		    *returned_error = (DW_DLE_DF_POP_EMPTY_STACK);
554 		    return DW_DLV_ERROR;
555 		}
556 		stack_table = top_stack;
557 		top_stack = stack_table->fr_next;
558 
559 		for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
560 		    reg[i] = stack_table->fr_reg[i];
561 
562 		dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
563 		break;
564 	    }
565 
566 	case DW_CFA_def_cfa:{
567 		Dwarf_Unsigned lreg;
568 
569 		DECODE_LEB128_UWORD(instr_ptr, lreg)
570 		    reg_no = (Dwarf_Small) lreg;
571 
572 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
573 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
574 		    return (DW_DLV_ERROR);
575 		}
576 
577 		factored_N_value =
578 		    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
579 		instr_ptr += leb128_length;
580 
581 		if (need_augmentation) {
582 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
583 		    return DW_DLV_ERROR;
584 		}
585 		reg[DW_FRAME_CFA_COL].ru_is_off = 1;
586 		reg[DW_FRAME_CFA_COL].ru_register = reg_no;
587 		reg[DW_FRAME_CFA_COL].ru_offset = factored_N_value;
588 
589 		fp_register = reg_no;
590 		fp_offset = factored_N_value;
591 		break;
592 	    }
593 
594 	case DW_CFA_def_cfa_register:{
595 		Dwarf_Unsigned lreg;
596 
597 		DECODE_LEB128_UWORD(instr_ptr, lreg)
598 		    reg_no = (Dwarf_Small) lreg;
599 
600 		if (reg_no > DW_FRAME_LAST_REG_NUM) {
601 		    *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
602 		    return DW_DLV_ERROR;
603 		}
604 
605 		reg[DW_FRAME_CFA_COL].ru_is_off = 0;
606 		reg[DW_FRAME_CFA_COL].ru_register = reg_no;
607 		reg[DW_FRAME_CFA_COL].ru_offset = 0;
608 		fp_register = reg_no;
609 		break;
610 	    }
611 
612 	case DW_CFA_def_cfa_offset:{
613 		factored_N_value =
614 		    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
615 		instr_ptr += leb128_length;
616 
617 		if (need_augmentation) {
618 		    *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
619 		    return DW_DLV_ERROR;
620 		}
621 		reg[DW_FRAME_CFA_COL].ru_offset = factored_N_value;
622 
623 		fp_offset = factored_N_value;
624 		break;
625 	    }
626 
627 	case DW_CFA_nop:{
628 		break;
629 	    }
630 
631 #ifdef DW_CFA_GNU_window_save
632 	case DW_CFA_GNU_window_save:{
633 		/* no information: this just tells unwinder to restore
634 		   the window registers from the previous frame's
635 		   window save area */
636 		break;
637 	    }
638 #endif
639 #ifdef  DW_CFA_GNU_args_size
640 	    /* single uleb128 is the current arg area size in bytes. No
641 	       register exists yet to save this in */
642 	case DW_CFA_GNU_args_size:{
643 		Dwarf_Unsigned lreg;
644 
645 		DECODE_LEB128_UWORD(instr_ptr, lreg)
646 		    reg_no = (Dwarf_Small) lreg;
647 
648 		break;
649 	    }
650 #endif
651 	}
652 
653 	if (make_instr) {
654 	    instr_count++;
655 
656 	    curr_instr = (Dwarf_Frame_Op *)
657 		_dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1);
658 	    if (curr_instr == NULL) {
659 		*returned_error = (DW_DLE_DF_ALLOC_FAIL);
660 		return DW_DLV_ERROR;
661 	    }
662 
663 	    curr_instr->fp_base_op = fp_base_op;
664 	    curr_instr->fp_extended_op = fp_extended_op;
665 	    curr_instr->fp_register = fp_register;
666 	    curr_instr->fp_offset = fp_offset;
667 	    curr_instr->fp_instr_offset = fp_instr_offset;
668 
669 	    curr_instr_item = (Dwarf_Chain)
670 		_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
671 	    if (curr_instr_item == NULL) {
672 		*returned_error = (DW_DLE_DF_ALLOC_FAIL);
673 		return DW_DLV_ERROR;
674 	    }
675 
676 	    curr_instr_item->ch_item = curr_instr;
677 	    if (head_instr_chain == NULL)
678 		head_instr_chain = tail_instr_chain = curr_instr_item;
679 	    else {
680 		tail_instr_chain->ch_next = curr_instr_item;
681 		tail_instr_chain = curr_instr_item;
682 	    }
683 	}
684     }
685 
686     /*
687        If frame instruction decoding was right we would stop exactly
688        at final_instr_ptr. */
689     if (instr_ptr > final_instr_ptr) {
690 	*returned_error = (DW_DLE_DF_FRAME_DECODING_ERROR);
691 	return DW_DLV_ERROR;
692     }
693 
694     /* Create the last row generated.  */
695     if (table != NULL) {
696 	t1reg = reg;
697 	t1end = t1reg + DW_FRAME_LAST_REG_NUM;
698 	table->fr_loc = loc;
699 	t2reg = table->fr_reg;
700 	for (; t1reg < t1end; t1reg++, t2reg++) {
701 	    *t2reg = *t1reg;
702 	}
703     }
704 
705     /* Dealloc anything remaining on stack. */
706     for (; top_stack != NULL;) {
707 	stack_table = top_stack;
708 	top_stack = top_stack->fr_next;
709 	dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
710     }
711 
712     if (make_instr) {
713 	/* Allocate list of pointers to Dwarf_Frame_Op's.  */
714 	head_instr_block = (Dwarf_Frame_Op *)
715 	    _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count);
716 	if (head_instr_block == NULL) {
717 	    *returned_error = DW_DLE_DF_ALLOC_FAIL;
718 	    return DW_DLV_ERROR;
719 	}
720 
721 	/*
722 	   Store pointers to Dwarf_Frame_Op's in this list and
723 	   deallocate the structs that chain the Dwarf_Frame_Op's. */
724 	curr_instr_item = head_instr_chain;
725 	for (i = 0; i < instr_count; i++) {
726 	    *(head_instr_block + i) =
727 		*(Dwarf_Frame_Op *) curr_instr_item->ch_item;
728 	    dealloc_instr_item = curr_instr_item;
729 	    curr_instr_item = curr_instr_item->ch_next;
730 	    dwarf_dealloc(dbg, dealloc_instr_item->ch_item,
731 			  DW_DLA_FRAME_OP);
732 	    dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN);
733 	}
734 	*ret_frame_instr = head_instr_block;
735 
736 	*returned_count = (Dwarf_Sword) instr_count;
737     } else {
738 	*returned_count = 0;
739     }
740     return DW_DLV_OK;
741 }
742 
743 static int
744 qsort_compare(const void *elem1, const void *elem2)
745 {
746     Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1;
747     Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2;
748     Dwarf_Addr addr1 = fde1->fd_initial_location;
749     Dwarf_Addr addr2 = fde2->fd_initial_location;
750 
751     if (addr1 < addr2) {
752 	return -1;
753     } else if (addr1 > addr2) {
754 	return 1;
755     }
756     return 0;
757 }
758 
759 /*
760  * This function expects as input a pointer to Dwarf_Debug (dbg) and a
761  * a pointer to Cie. It finds the augmentation string and returns after
762  * setting *augmentation to point to it.
763  */
764 static int
765 get_augmentation_string(Dwarf_Debug dbg,
766 			Dwarf_Small * cie_ptr,
767 			Dwarf_Unsigned cie_id_value,
768 			Dwarf_Small ** augmentation,
769 			Dwarf_Error * error)
770 {
771     Dwarf_Unsigned cie_id;	/* must be min de_length_size bytes in
772 				   size */
773     Dwarf_Small version;
774     int local_length_size;
775     Dwarf_Unsigned length;
776     /*REFERENCED*/ /* Not used in this instance of the macro */
777     int local_extension_size;
778 
779 
780     /* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
781     READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
782 		     cie_ptr, local_length_size, local_extension_size);
783 
784 
785 
786     /* Read the Cie Id field. */
787     READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
788 		   cie_ptr, local_length_size);
789     SIGN_EXTEND(cie_id, local_length_size);
790     if (cie_id != cie_id_value) {
791 	/* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi
792 	   uses -1 in .debug_frame. .eh_frame not quite identical to
793 	   .debug_frame */
794 	_dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
795 	return (DW_DLV_ERROR);
796     }
797     cie_ptr += local_length_size;
798 
799 
800     /* Read the version. */
801     version = *(Dwarf_Small *) cie_ptr;
802     cie_ptr++;
803     if (version != DW_CIE_VERSION) {
804 	_dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
805 	return (DW_DLV_ERROR);
806     }
807 
808     /* At this point, cie_ptr is pointing at the augmentation string. */
809     *augmentation = cie_ptr;
810     return DW_DLV_OK;
811 }
812 
813 int
814 dwarf_get_cie_of_fde(Dwarf_Fde fde,
815 		     Dwarf_Cie * cie_returned, Dwarf_Error * error)
816 {
817     if (fde == NULL) {
818 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
819 	return (DW_DLV_ERROR);
820     }
821 
822     *cie_returned = fde->fd_cie;
823     return DW_DLV_OK;
824 
825 }
826 
827 /*
828   For g++ .eh_frame fde and cie.
829   the cie id is different as the
830   definition of the cie_id in an fde
831 	is the distance back from the address of the
832 	value to the cie.
833   Or 0 if this is a true cie.
834   Non standard dwarf, designed this way to be
835   convenient at run time for an allocated
836   (mapped into memory as part of the running image) section.
837 */
838 int
839 dwarf_get_fde_list_eh(Dwarf_Debug dbg,
840 		      Dwarf_Cie ** cie_data,
841 		      Dwarf_Signed * cie_element_count,
842 		      Dwarf_Fde ** fde_data,
843 		      Dwarf_Signed * fde_element_count,
844 		      Dwarf_Error * error)
845 {
846     int res;
847 
848     res =
849         _dwarf_load_section(dbg,
850 			    dbg->de_debug_frame_eh_gnu_index,
851 			    &dbg->de_debug_frame_eh_gnu,
852 			    error);
853 
854     if (res != DW_DLV_OK) {
855       return res;
856     }
857 
858     res =
859 	__dwarf_get_fde_list_internal(dbg,
860 				      cie_data,
861 				      cie_element_count,
862 				      fde_data,
863 				      fde_element_count,
864 				      dbg->de_debug_frame_eh_gnu,
865 				      dbg->de_debug_frame_size_eh_gnu,
866 				      /* cie_id_value */ 0,
867 				      /* use_gnu_cie_calc= */ 1,
868 				      error);
869     return res;
870 }
871 
872 
873 
874 /*
875   For standard dwarf .debug_frame
876   cie_id is -1  in a cie, and
877   is the section offset in the .debug_frame section
878   of the cie otherwise.  Standard dwarf
879 */
880 int
881 dwarf_get_fde_list(Dwarf_Debug dbg,
882 		   Dwarf_Cie ** cie_data,
883 		   Dwarf_Signed * cie_element_count,
884 		   Dwarf_Fde ** fde_data,
885 		   Dwarf_Signed * fde_element_count,
886 		   Dwarf_Error * error)
887 {
888     int res;
889 
890     res =
891         _dwarf_load_section(dbg,
892 			    dbg->de_debug_frame_index,
893 			    &dbg->de_debug_frame,
894 			    error);
895 
896     if (res != DW_DLV_OK) {
897       return res;
898     }
899 
900     res =
901 	__dwarf_get_fde_list_internal(dbg, cie_data,
902 				      cie_element_count,
903 				      fde_data,
904 				      fde_element_count,
905 				      dbg->de_debug_frame,
906 				      dbg->de_debug_frame_size,
907 				      DW_CIE_ID,
908 				      /* use_gnu_cie_calc= */ 0,
909 				      error);
910     return res;
911 }
912 
913 static int
914 __dwarf_get_fde_list_internal(Dwarf_Debug dbg,
915 			      Dwarf_Cie ** cie_data,
916 			      Dwarf_Signed * cie_element_count,
917 			      Dwarf_Fde ** fde_data,
918 			      Dwarf_Signed * fde_element_count,
919 			      Dwarf_Small * section_ptr,
920 			      Dwarf_Unsigned section_length,
921 			      Dwarf_Unsigned cie_id_value,
922 			      int use_gnu_cie_calc, Dwarf_Error * error)
923 {
924     /* Scans the debug_frame section. */
925     Dwarf_Small *frame_ptr = 0;
926 
927     /* Points to the start of the current Fde or Cie. */
928     Dwarf_Small *start_frame_ptr = 0;
929 
930     /* Points to the start of the augmented entries of Fde or Cie. */
931     Dwarf_Small *saved_frame_ptr = 0;
932 
933     /* Fields for the current Cie being read. */
934     Dwarf_Unsigned length = 0;	/* READ_UNALIGNED needs min
935 				   de_length_size byte dest */
936     Dwarf_Unsigned cie_base_offset = 0;	/* needs to be min
937 					   de_length_size byte dest */
938     Dwarf_Unsigned cie_id;
939     Dwarf_Small version = 0;
940     Dwarf_Small *augmentation = 0;
941     Dwarf_Word code_alignment_factor = 4;
942     Dwarf_Sword data_alignment_factor = -1;
943     Dwarf_Small return_address_register = 31;
944     Dwarf_Word length_of_augmented_fields = 0;
945 
946     /*
947        New_cie points to the Cie being read, and head_cie_ptr and
948        cur_cie_ptr are used for chaining them up in sequence. */
949     Dwarf_Cie new_cie;
950     Dwarf_Cie head_cie_ptr = NULL;
951     Dwarf_Cie cur_cie_ptr;
952     Dwarf_Word cie_count = 0;
953 
954     /*
955        Points to a list of contiguous pointers to Dwarf_Cie
956        structures. */
957     Dwarf_Cie *cie_list_ptr;
958 
959     /* Fields for the current Fde being read.  */
960     Dwarf_Addr initial_location;	/* must be min de_pointer_size
961 					   bytes in size */
962     Dwarf_Addr address_range;	/* must be min de_pointer_size bytes in
963 				   size */
964 
965     /*
966        New_fde points to the current Fde being read, and head_fde_ptr
967        and cur_fde_ptr are used to chain them up. */
968     Dwarf_Fde new_fde;
969     Dwarf_Fde head_fde_ptr = NULL;
970     Dwarf_Fde cur_fde_ptr;
971     Dwarf_Word fde_count = 0;
972 
973     /*
974        Points to a list of contiguous pointers to Dwarf_Fde
975        structures. */
976     Dwarf_Fde *fde_list_ptr;
977 
978     /*
979        Is used to check the offset field in the Fde by checking for a
980        Cie at this address. */
981     Dwarf_Small *fde_cie_ptr;
982 
983     Dwarf_Word leb128_length;
984     Dwarf_Word i, j;
985     int res;
986     Dwarf_Word last_cie_index;
987 
988 
989     Dwarf_Small *prev_augmentation_cie_ptr = 0;
990     Dwarf_Small *prev_augmentation_ptr = 0;
991 
992 
993     frame_ptr = section_ptr;
994 
995     if (frame_ptr == 0) {
996 	return DW_DLV_NO_ENTRY;
997     }
998 
999     while (frame_ptr < section_ptr + section_length) {
1000 	Dwarf_Small *cie_ptr_addr = 0;
1001 	int local_extension_size = 0;
1002 	int local_length_size = 0;
1003 
1004 	start_frame_ptr = frame_ptr;
1005 
1006 	/* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
1007 	READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
1008 			 frame_ptr, local_length_size,
1009 			 local_extension_size);
1010 
1011 
1012 	if (length % local_length_size != 0) {
1013 	    _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1014 	    return (DW_DLV_ERROR);
1015 	}
1016 
1017 	if (length == 0) {
1018 	    /* nul bytes at end of section, seen at end of egcs
1019 	       eh_frame sections (in a.out). Take this as meaning no
1020 	       more CIE/FDE data. We should be very close to end of
1021 	       section. */
1022 	    break;
1023 	}
1024 
1025 	cie_ptr_addr = frame_ptr;
1026 	READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
1027 		       frame_ptr, local_length_size);
1028 	SIGN_EXTEND(cie_id, local_length_size);
1029 	cie_base_offset = cie_id;	/* if this is a CIE, this is
1030 					   ignored.  If it is an FDE,
1031 					   this is the section offset
1032 					   that allows us to get to the
1033 					   cie of this fde. Save it for
1034 					   the fde part of the 'if'
1035 					   below */
1036 
1037 	frame_ptr += local_length_size;
1038 
1039 	if (cie_id == cie_id_value) {
1040 	    /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id.
1041 	       sgi uses -1 (in .debug_frame). .eh_frame not quite
1042 	       identical to .debug_frame */
1043 
1044 
1045 
1046 	    /* this is a CIE, Common Information Entry: See the dwarf
1047 	       spec, section 6.4.1 */
1048 	    version = *(Dwarf_Small *) frame_ptr;
1049 	    frame_ptr++;
1050 	    if (version != DW_CIE_VERSION) {
1051 		_dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
1052 		return (DW_DLV_ERROR);
1053 	    }
1054 
1055 	    augmentation = frame_ptr;
1056 	    frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
1057 	    if ((strcmp((char *) augmentation,
1058 			DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
1059 		(strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
1060 
1061 		Dwarf_Unsigned lreg;
1062 
1063 		DECODE_LEB128_UWORD(frame_ptr, lreg)
1064 		    code_alignment_factor = (Dwarf_Word) lreg;
1065 
1066 
1067 		data_alignment_factor =
1068 		    (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
1069 							 &leb128_length);
1070 
1071 		frame_ptr = frame_ptr + leb128_length;
1072 
1073 		return_address_register = *(Dwarf_Small *) frame_ptr;
1074 		if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1075 		    _dwarf_error(dbg, error,
1076 				 DW_DLE_CIE_RET_ADDR_REG_ERROR);
1077 		    return (DW_DLV_ERROR);
1078 		}
1079 		frame_ptr++;
1080 	    } else if (augmentation[0] == 'z') {
1081 		/* The augmentation starts with a known prefix. See the
1082 		   dwarf_frame.h for details on the layout. */
1083 
1084 		Dwarf_Unsigned lreg;
1085 
1086 		DECODE_LEB128_UWORD(frame_ptr, lreg)
1087 		    code_alignment_factor = (Dwarf_Word) lreg;
1088 
1089 
1090 		data_alignment_factor =
1091 		    (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
1092 							 &leb128_length);
1093 		frame_ptr = frame_ptr + leb128_length;
1094 
1095 		return_address_register = *(Dwarf_Small *) frame_ptr;
1096 		if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1097 		    _dwarf_error(dbg, error,
1098 				 DW_DLE_CIE_RET_ADDR_REG_ERROR);
1099 		    return (DW_DLV_ERROR);
1100 		}
1101 		frame_ptr++;
1102 
1103 		/* Decode the length of augmented fields. */
1104 		DECODE_LEB128_UWORD(frame_ptr, lreg)
1105 		    length_of_augmented_fields = (Dwarf_Word) lreg;
1106 
1107 
1108 		/* set the frame_ptr to point at the instruction start.
1109 		 */
1110 		frame_ptr += length_of_augmented_fields;
1111 	    } else if (0 == strcmp((const char *) augmentation, "eh")) {
1112 
1113     	    	/*REFERENCED*/ /* Not used in this instance of the macro */
1114 		Dwarf_Unsigned exception_table_addr;
1115 
1116 		/* this is per egcs-1.1.2 as on RH 6.0 */
1117 		READ_UNALIGNED(dbg, exception_table_addr,
1118 			       Dwarf_Unsigned, frame_ptr,
1119 			       local_length_size);
1120 		frame_ptr += local_length_size;
1121 
1122 		code_alignment_factor =
1123 		    (Dwarf_Word) _dwarf_decode_s_leb128(frame_ptr,
1124 							&leb128_length);
1125 		frame_ptr = frame_ptr + leb128_length;
1126 
1127 
1128 		data_alignment_factor =
1129 		    (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
1130 							 &leb128_length);
1131 
1132 		frame_ptr = frame_ptr + leb128_length;
1133 
1134 		return_address_register = *(Dwarf_Small *) frame_ptr;
1135 		if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1136 		    _dwarf_error(dbg, error,
1137 				 DW_DLE_CIE_RET_ADDR_REG_ERROR);
1138 		    return (DW_DLV_ERROR);
1139 		}
1140 		frame_ptr++;
1141 
1142 	    } else {
1143 		/* We do not understand the augmentation string. No
1144 		   assumption can be made about any fields other than
1145 		   what we have already read. */
1146 		frame_ptr = start_frame_ptr + length + local_length_size
1147 		    + local_extension_size;
1148 		/* FIX -- What are the values of data_alignment_factor,
1149 		   code_alignement_factor, return_address_register and
1150 		   instruction start? They were clearly uninitalized in
1151 		   the previous version and I am leaving them the same
1152 		   way. */
1153 	    }
1154 
1155 	    new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
1156 	    if (new_cie == NULL) {
1157 		_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1158 		return (DW_DLV_ERROR);
1159 	    }
1160 
1161 	    new_cie->ci_initial_table = NULL;
1162 	    new_cie->ci_length = (Dwarf_Word) length;
1163 	    new_cie->ci_length_size = local_length_size;
1164 	    new_cie->ci_extension_size = local_extension_size;
1165 	    new_cie->ci_augmentation = (char *) augmentation;
1166 
1167 	    new_cie->ci_data_alignment_factor =
1168 		(Dwarf_Sbyte) data_alignment_factor;
1169 	    new_cie->ci_code_alignment_factor =
1170 		(Dwarf_Small) code_alignment_factor;
1171 	    new_cie->ci_return_address_register =
1172 		return_address_register;
1173 	    new_cie->ci_cie_start = start_frame_ptr;
1174 	    new_cie->ci_cie_instr_start = frame_ptr;
1175 	    new_cie->ci_dbg = dbg;
1176 
1177 	    cie_count++;
1178 	    if (head_cie_ptr == NULL)
1179 		head_cie_ptr = cur_cie_ptr = new_cie;
1180 	    else {
1181 		cur_cie_ptr->ci_next = new_cie;
1182 		cur_cie_ptr = new_cie;
1183 	    }
1184 	} else {
1185 
1186 
1187 
1188 	    /* this is an FDE, Frame Description Entry, see the Dwarf
1189 	       Spec, section 6.4.1 */
1190 	    Dwarf_Small *cieptr;
1191 
1192 	    Dwarf_Small *initloc = frame_ptr;
1193 	    Dwarf_Signed offset_into_exception_tables
1194 		/* must be min dwarf_sfixed in size */
1195 		= (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
1196 
1197 	    READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
1198 			   frame_ptr, dbg->de_pointer_size);
1199 	    frame_ptr += dbg->de_pointer_size;
1200 
1201 	    READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
1202 			   frame_ptr, dbg->de_pointer_size);
1203 	    frame_ptr += dbg->de_pointer_size;
1204 	    /* Get the augmentation string from Cie to identify the
1205 	       layout of this Fde.  */
1206 	    if (use_gnu_cie_calc) {
1207 		/* cie_id value is offset, in section, of the cie_id
1208 		   itself, to use vm ptr of the value, less the value,
1209 		   to get to the cie itself. In addition, munge
1210 		   cie_base_offset to look *as if* it was from real
1211 		   dwarf. */
1212 		cieptr = cie_ptr_addr - cie_base_offset;
1213 		cie_base_offset = cieptr - section_ptr;
1214 	    } else {
1215 		/* Traditional dwarf section offset is in cie_id */
1216 		cieptr =
1217 		    (Dwarf_Small *) (section_ptr + cie_base_offset);
1218 	    }
1219 
1220 
1221 	    if (prev_augmentation_cie_ptr == cieptr &&
1222 		prev_augmentation_ptr != NULL) {
1223 		augmentation = prev_augmentation_ptr;
1224 	    } else {
1225 		res = get_augmentation_string(dbg,
1226 					      cieptr,
1227 					      cie_id_value,
1228 					      &augmentation, error);
1229 		if (res != DW_DLV_OK) {
1230 		    return res;
1231 		}
1232 		prev_augmentation_cie_ptr = cieptr;
1233 		prev_augmentation_ptr = augmentation;
1234 	    }
1235 	    if ((strcmp((char *) augmentation,
1236 			DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
1237 		(strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
1238 		/* We are pointing at the start of instructions. Do
1239 		   nothing. */
1240 	    } else if (augmentation[0] == 'z') {
1241 		Dwarf_Unsigned lreg;
1242 
1243 		DECODE_LEB128_UWORD(frame_ptr, lreg)
1244 		    length_of_augmented_fields = (Dwarf_Word) lreg;
1245 
1246 		saved_frame_ptr = frame_ptr;
1247 		if (strcmp((char *) augmentation,
1248 			   DW_CIE_AUGMENTER_STRING_V0) == 0) {
1249 		    /* The first word is an offset into execption
1250 		       tables. */
1251 		    /* ?? THis presumes that the offset is always 32
1252 		       bits */
1253 		    READ_UNALIGNED(dbg, offset_into_exception_tables,
1254 				   Dwarf_Addr, frame_ptr,
1255 				   sizeof(Dwarf_sfixed));
1256 		    SIGN_EXTEND(offset_into_exception_tables,
1257 				sizeof(Dwarf_sfixed));
1258 		    frame_ptr += local_length_size;
1259 		}
1260 		frame_ptr =
1261 		    saved_frame_ptr + length_of_augmented_fields;
1262 	    } else if (strcmp((const char *) augmentation, "eh") == 0) {
1263 		/* gnu eh fde case. we do not need to do anything */
1264     	    	/*REFERENCED*/ /* Not used in this instance of the macro */
1265 		Dwarf_Unsigned exception_table_addr;
1266 
1267 		READ_UNALIGNED(dbg, exception_table_addr,
1268 			       Dwarf_Unsigned, frame_ptr,
1269 			       dbg->de_pointer_size);
1270 		frame_ptr += dbg->de_pointer_size;
1271 	    } else {
1272 		/* We do not understand the augmentation string. No
1273 		   assumption can be made about if the instructions is
1274 		   present. */
1275 		/* FIX -- The old code assumed that the instruction
1276 		   table starts at the location pointed to by
1277 		   frame_ptr, clearly incorrect. */
1278 	    }
1279 	    new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
1280 	    if (new_fde == NULL) {
1281 		_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1282 		return (DW_DLV_ERROR);
1283 	    }
1284 
1285 	    new_fde->fd_length = (Dwarf_Word) length;
1286 	    new_fde->fd_length_size = local_length_size;
1287 	    new_fde->fd_extension_size = local_extension_size;
1288 	    new_fde->fd_cie_offset = cie_base_offset;
1289 	    new_fde->fd_initial_location = initial_location;
1290 	    new_fde->fd_initial_loc_pos = initloc;
1291 	    new_fde->fd_address_range = address_range;
1292 	    new_fde->fd_fde_start = start_frame_ptr;
1293 	    new_fde->fd_fde_instr_start = frame_ptr;
1294 	    new_fde->fd_dbg = dbg;
1295 	    new_fde->fd_offset_into_exception_tables =
1296 		offset_into_exception_tables;
1297 
1298 	    fde_count++;
1299 	    if (head_fde_ptr == NULL)
1300 		head_fde_ptr = cur_fde_ptr = new_fde;
1301 	    else {
1302 		cur_fde_ptr->fd_next = new_fde;
1303 		cur_fde_ptr = new_fde;
1304 	    }
1305 	}
1306 
1307 	/* Skip over instructions to start of next frame. */
1308 	frame_ptr = start_frame_ptr + length + local_length_size +
1309 	    local_extension_size;
1310     }
1311 
1312     if (cie_count > 0) {
1313 	cie_list_ptr = (Dwarf_Cie *)
1314 	    _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
1315     } else {
1316 	return (DW_DLV_NO_ENTRY);
1317     }
1318     if (cie_list_ptr == NULL) {
1319 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1320 	return (DW_DLV_ERROR);
1321     }
1322     /* Return arguments. */
1323     *cie_data = cie_list_ptr;
1324     *cie_element_count = cie_count;
1325     dbg->de_cie_data = cie_list_ptr;
1326     dbg->de_cie_count = cie_count;
1327 
1328     cur_cie_ptr = head_cie_ptr;
1329     for (i = 0; i < cie_count; i++) {
1330 	*(cie_list_ptr + i) = cur_cie_ptr;
1331 	cur_cie_ptr = cur_cie_ptr->ci_next;
1332     }
1333 
1334     if (fde_count > 0) {
1335 	fde_list_ptr = (Dwarf_Fde *)
1336 	    _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
1337     } else {
1338 	return (DW_DLV_NO_ENTRY);
1339     }
1340     if (fde_list_ptr == NULL) {
1341 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1342 	return (DW_DLV_ERROR);
1343     }
1344     /* Return arguments. */
1345     *fde_data = fde_list_ptr;
1346     *fde_element_count = fde_count;
1347     dbg->de_fde_data = fde_list_ptr;
1348     dbg->de_fde_count = fde_count;
1349     last_cie_index = 0;
1350 
1351     cur_fde_ptr = head_fde_ptr;
1352     for (i = 0; i < fde_count; i++) {
1353 	Dwarf_Sword new_cie_index = (Dwarf_Sword) cie_count;
1354 
1355 	*(fde_list_ptr + i) = cur_fde_ptr;
1356 
1357 	fde_cie_ptr = (Dwarf_Small *) (section_ptr +
1358 				       cur_fde_ptr->fd_cie_offset);
1359 
1360 
1361 	/* we assume that the next fde has the same cie as the ** last
1362 	   fde and resume the search where we left off */
1363 	for (j = last_cie_index; j < cie_count; j++) {
1364 	    Dwarf_Cie ciep = (Dwarf_Cie) * (cie_list_ptr + j);
1365 
1366 	    if (ciep->ci_cie_start == fde_cie_ptr) {
1367 		new_cie_index = (Dwarf_Sword) j;
1368 		break;
1369 	    }
1370 	}
1371 	/* did not find it above, start from 0 and try again */
1372 	if (new_cie_index == cie_count) {
1373 	    for (j = 0; j < last_cie_index; ++j) {
1374 		Dwarf_Cie ciep = (Dwarf_Cie) * (cie_list_ptr + j);
1375 
1376 		if (ciep->ci_cie_start == fde_cie_ptr) {
1377 		    new_cie_index = (Dwarf_Sword) j;
1378 		    break;
1379 		}
1380 	    }
1381 	}
1382 	j = new_cie_index;
1383 	last_cie_index = new_cie_index;
1384 	if (j == cie_count) {
1385 	    _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
1386 	    return (DW_DLV_ERROR);
1387 	} else {
1388 	    cur_fde_ptr->fd_cie_index = (Dwarf_Sword) j;
1389 	    cur_fde_ptr->fd_cie = *(cie_list_ptr + j);
1390 	}
1391 
1392 	cur_fde_ptr = cur_fde_ptr->fd_next;
1393     }
1394 
1395     /* sort the list by the address, so that dwarf_get_fde_at_pc() can
1396        binary search this list. */
1397     qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
1398 	  qsort_compare);
1399 
1400     return (DW_DLV_OK);
1401 }
1402 
1403 /*
1404    Only works on dwarf sections, not eh_frame
1405 */
1406 int
1407 dwarf_get_fde_for_die(Dwarf_Debug dbg,
1408 		      Dwarf_Die die,
1409 		      Dwarf_Fde * ret_fde, Dwarf_Error * error)
1410 {
1411     Dwarf_Attribute attr;
1412     Dwarf_Unsigned fde_offset;
1413     Dwarf_Signed signdval;
1414     Dwarf_Unsigned length;	/* must be min de_length_size bytes */
1415     Dwarf_Signed signed_offset;	/* must be min de_length_size bytes */
1416     Dwarf_Addr initial_location;	/* must be min de_pointer_size
1417 					   bytes */
1418     Dwarf_Addr address_range;	/* must be min de_pointer_size bytes */
1419     Dwarf_Fde new_fde;
1420     unsigned char *fde_ptr;
1421     Dwarf_Small *saved_fde_ptr;
1422     unsigned char *cie_ptr;
1423     unsigned char *start_cie_ptr;
1424     Dwarf_Cie new_cie;
1425 
1426     /* Fields for the current Cie being read. */
1427     Dwarf_Small version;
1428     Dwarf_Small *augmentation;
1429     Dwarf_Word code_alignment_factor;
1430     Dwarf_Sword data_alignment_factor;
1431     Dwarf_Small return_address_register;
1432     Dwarf_Word length_of_augmented_fields;
1433     Dwarf_Signed offset_into_exception_tables =
1434 	(Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
1435     int res;
1436     int resattr;
1437     int sdatares;
1438     int fde_local_extension_size = 0;
1439     int fde_local_length_size = 0;
1440     int cie_local_extension_size = 0;
1441     int cie_local_length_size = 0;
1442 
1443 
1444     Dwarf_Word leb128_length;
1445 
1446     if (die == NULL) {
1447 	_dwarf_error(NULL, error, DW_DLE_DIE_NULL);
1448 	return (DW_DLV_ERROR);
1449     }
1450 
1451     resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error);
1452     if (resattr != DW_DLV_OK) {
1453 	return resattr;
1454     }
1455 
1456     /* why is this formsdata? FIX */
1457     sdatares = dwarf_formsdata(attr, &signdval, error);
1458     if (sdatares != DW_DLV_OK) {
1459 	return sdatares;
1460     }
1461 
1462     res =
1463         _dwarf_load_section(dbg,
1464 			    dbg->de_debug_frame_index,
1465 			    &dbg->de_debug_frame,
1466 			    error);
1467     if (res != DW_DLV_OK) {
1468       return res;
1469     }
1470 
1471     fde_offset = signdval;
1472     fde_ptr = (dbg->de_debug_frame + fde_offset);
1473 
1474     /* READ_AREA_LENGTH updates fde_ptr for consumed bytes */
1475     READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
1476 		     fde_ptr, fde_local_length_size,
1477 		     fde_local_extension_size);
1478 
1479 
1480     if (length % fde_local_length_size != 0) {
1481 	_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1482 	return (DW_DLV_ERROR);
1483     }
1484 
1485     READ_UNALIGNED(dbg, signed_offset, Dwarf_Signed,
1486 		   fde_ptr, fde_local_length_size);
1487     SIGN_EXTEND(signed_offset, fde_local_length_size);
1488     fde_ptr += fde_local_length_size;
1489 
1490     READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
1491 		   fde_ptr, dbg->de_pointer_size);
1492     fde_ptr += dbg->de_pointer_size;
1493 
1494     READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
1495 		   fde_ptr, dbg->de_pointer_size);
1496     fde_ptr += dbg->de_pointer_size;
1497 
1498     res = get_augmentation_string(dbg,
1499 				  (Dwarf_Small *) (dbg->de_debug_frame +
1500 						   signed_offset),
1501 				  DW_CIE_ID, &augmentation, error);
1502     if (res != DW_DLV_OK) {
1503 	return res;
1504     }
1505 
1506     if ((strcmp((char *) augmentation, DW_DEBUG_FRAME_AUGMENTER_STRING)
1507 	 == 0) ||
1508 	(strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
1509 	/* Do nothing. The fde_ptr is pointing at start of
1510 	   instructions. */
1511     } else if (augmentation[0] == 'z') {
1512 	/* The augmentation starts with a known prefix. See the
1513 	   dwarf_frame.h for details on the layout. */
1514 
1515 	Dwarf_Unsigned lreg;
1516 
1517 	DECODE_LEB128_UWORD(fde_ptr, lreg)
1518 	    length_of_augmented_fields = (Dwarf_Word) lreg;
1519 
1520 	saved_fde_ptr = fde_ptr;
1521 	if (strcmp((char *) augmentation, DW_CIE_AUGMENTER_STRING_V0) ==
1522 	    0) {
1523 	    /* The first word is an offset into execption tables. */
1524 	    READ_UNALIGNED(dbg, offset_into_exception_tables,
1525 			   Dwarf_Signed, fde_ptr, sizeof(Dwarf_sfixed));
1526 	    SIGN_EXTEND(offset_into_exception_tables,
1527 			sizeof(Dwarf_sfixed));
1528 	    fde_ptr += sizeof(Dwarf_sfixed);
1529 	}
1530 	fde_ptr = saved_fde_ptr + length_of_augmented_fields;
1531     } else {
1532 	/* We do not understand the augmentation string. No assumption
1533 	   can be made about if the instructions is present. */
1534 	/* FIX -- The old code assumed that the instruction table
1535 	   starts at location pointed to by fde_ptr, clearly incorrect.
1536 	 */
1537     }
1538 
1539     new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
1540     if (new_fde == NULL) {
1541 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1542 	return (DW_DLV_ERROR);
1543     }
1544 
1545     new_fde->fd_length = (Dwarf_Word) length;
1546     new_fde->fd_length_size = fde_local_length_size;
1547     new_fde->fd_extension_size = fde_local_extension_size;
1548     new_fde->fd_cie_offset = signed_offset;
1549     new_fde->fd_initial_location = initial_location;
1550     new_fde->fd_address_range = address_range;
1551     new_fde->fd_fde_start = dbg->de_debug_frame + fde_offset;
1552     new_fde->fd_fde_instr_start = (Dwarf_Small *) fde_ptr;
1553     new_fde->fd_dbg = dbg;
1554     new_fde->fd_offset_into_exception_tables =
1555 	offset_into_exception_tables;
1556 
1557     /* now read the cie corresponding to the fde */
1558     cie_ptr = (dbg->de_debug_frame + signed_offset);
1559     start_cie_ptr = cie_ptr;
1560 
1561     /* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
1562     READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
1563 		     cie_ptr, cie_local_length_size,
1564 		     cie_local_extension_size);
1565 
1566 
1567     if (length % cie_local_length_size != 0) {
1568 	_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1569 	return (DW_DLV_ERROR);
1570     }
1571 
1572     READ_UNALIGNED(dbg, signed_offset, Dwarf_Signed,
1573 		   cie_ptr, cie_local_length_size);
1574     SIGN_EXTEND(signed_offset, cie_local_length_size);
1575     cie_ptr += cie_local_length_size;
1576 
1577     if (signed_offset == DW_CIE_ID) {
1578 
1579 	version = *(Dwarf_Small *) cie_ptr;
1580 	cie_ptr++;
1581 	if (version != DW_CIE_VERSION) {
1582 	    _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
1583 	    return (DW_DLV_ERROR);
1584 	}
1585 
1586 	augmentation = cie_ptr;
1587 	cie_ptr = cie_ptr + strlen((char *) cie_ptr) + 1;
1588 	if ((strcmp((char *) augmentation,
1589 		    DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
1590 	    (strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
1591 
1592 	    Dwarf_Unsigned lreg;
1593 
1594 	    DECODE_LEB128_UWORD(cie_ptr, lreg)
1595 		code_alignment_factor = (Dwarf_Word) lreg;
1596 
1597 
1598 	    data_alignment_factor = (Dwarf_Sword)
1599 		_dwarf_decode_s_leb128(cie_ptr, &leb128_length);
1600 	    cie_ptr = cie_ptr + leb128_length;
1601 
1602 	    return_address_register = *(Dwarf_Small *) cie_ptr;
1603 	    if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1604 		_dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
1605 		return (DW_DLV_ERROR);
1606 	    }
1607 	    cie_ptr++;
1608 	} else if (augmentation[0] == 'z') {
1609 	    /* The augmentation starts with a known prefix. We can
1610 	       asssume that the first field is the length of the
1611 	       augmented fields. */
1612 
1613 	    Dwarf_Unsigned lreg;
1614 
1615 	    DECODE_LEB128_UWORD(cie_ptr, lreg)
1616 		code_alignment_factor = (Dwarf_Word) lreg;
1617 	    data_alignment_factor = (Dwarf_Sword)
1618 		_dwarf_decode_s_leb128(cie_ptr, &leb128_length);
1619 	    cie_ptr = cie_ptr + leb128_length;
1620 
1621 	    return_address_register = *(Dwarf_Small *) cie_ptr;
1622 	    if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1623 		_dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
1624 		return (DW_DLV_ERROR);
1625 	    }
1626 	    cie_ptr++;
1627 	    /* Decode the length of augmented fields. */
1628 	    DECODE_LEB128_UWORD(cie_ptr, lreg)
1629 		length_of_augmented_fields = (Dwarf_Word) lreg;
1630 
1631 	    /* set the cie_ptr to point at the instruction start. */
1632 	    cie_ptr += length_of_augmented_fields;
1633 	} else if (strcmp((const char *) augmentation, "eh") == 0) {
1634 	    Dwarf_Unsigned lreg;
1635 
1636 	    DECODE_LEB128_UWORD(cie_ptr, lreg)
1637 		code_alignment_factor = (Dwarf_Word) lreg;
1638 
1639 
1640 	    data_alignment_factor = (Dwarf_Sword)
1641 		_dwarf_decode_s_leb128(cie_ptr, &leb128_length);
1642 	    cie_ptr = cie_ptr + leb128_length;
1643 
1644 	    return_address_register = *(Dwarf_Small *) cie_ptr;
1645 	    if (return_address_register > DW_FRAME_LAST_REG_NUM) {
1646 		_dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
1647 		return (DW_DLV_ERROR);
1648 	    }
1649 	    cie_ptr++;
1650 
1651 	} else {
1652 	    /* We do not understand the augmentation string. No
1653 	       assumption can be made about any fields other than what
1654 	       we have already read. */
1655 	    cie_ptr = start_cie_ptr + length + cie_local_length_size
1656 		+ cie_local_extension_size;
1657 	    /* FIX -- What are the values of data_alignment_factor,
1658 	       code_alignement_factor, return_address_register and
1659 	       instruction start? They were clearly uninitalized in
1660 	       the previous version and I am leaving them the same way.
1661 	     */
1662 	}
1663 
1664 	new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
1665 	if (new_cie == NULL) {
1666 	    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1667 	    return (DW_DLV_ERROR);
1668 	}
1669 
1670 	new_cie->ci_initial_table = NULL;
1671 	new_cie->ci_length = (Dwarf_Word) length;
1672 	new_cie->ci_length_size = cie_local_length_size;
1673 	new_cie->ci_extension_size = cie_local_extension_size;
1674 	new_cie->ci_augmentation = (char *) augmentation;
1675 	new_cie->ci_data_alignment_factor =
1676 	    (Dwarf_Sbyte) data_alignment_factor;
1677 	new_cie->ci_code_alignment_factor =
1678 	    (Dwarf_Small) code_alignment_factor;
1679 	new_cie->ci_return_address_register = return_address_register;
1680 	new_cie->ci_cie_start = start_cie_ptr;
1681 	new_cie->ci_cie_instr_start = cie_ptr;
1682 	new_cie->ci_dbg = dbg;
1683     } else {
1684 	_dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
1685 	return (DW_DLV_ERROR);
1686     }
1687     new_fde->fd_cie = new_cie;
1688 
1689     *ret_fde = new_fde;
1690     return DW_DLV_OK;
1691 }
1692 
1693 
1694 int
1695 dwarf_get_fde_range(Dwarf_Fde fde,
1696 		    Dwarf_Addr * low_pc,
1697 		    Dwarf_Unsigned * func_length,
1698 		    Dwarf_Ptr * fde_bytes,
1699 		    Dwarf_Unsigned * fde_byte_length,
1700 		    Dwarf_Off * cie_offset,
1701 		    Dwarf_Signed * cie_index,
1702 		    Dwarf_Off * fde_offset, Dwarf_Error * error)
1703 {
1704     int res;
1705     Dwarf_Debug dbg;
1706 
1707     if (fde == NULL) {
1708 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
1709 	return (DW_DLV_ERROR);
1710     }
1711 
1712     dbg = fde->fd_dbg;
1713     if (dbg == NULL) {
1714 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
1715 	return (DW_DLV_ERROR);
1716     }
1717 
1718     res =
1719         _dwarf_load_section(dbg,
1720 			    dbg->de_debug_frame_index,
1721 			    &dbg->de_debug_frame,
1722 			    error);
1723     if (res != DW_DLV_OK) {
1724         return res;
1725     }
1726 
1727     if (low_pc != NULL)
1728 	*low_pc = fde->fd_initial_location;
1729     if (func_length != NULL)
1730 	*func_length = fde->fd_address_range;
1731     if (fde_bytes != NULL)
1732 	*fde_bytes = fde->fd_fde_start;
1733     if (fde_byte_length != NULL)
1734 	*fde_byte_length = fde->fd_length;
1735     if (cie_offset != NULL)
1736 	*cie_offset = fde->fd_cie_offset;
1737     if (cie_index != NULL)
1738 	*cie_index = fde->fd_cie_index;
1739     if (fde_offset != NULL)
1740 	*fde_offset = fde->fd_fde_start - dbg->de_debug_frame;
1741 
1742     return DW_DLV_OK;
1743 }
1744 
1745 int
1746 dwarf_get_fde_exception_info(Dwarf_Fde fde,
1747 			     Dwarf_Signed *
1748 			     offset_into_exception_tables,
1749 			     Dwarf_Error * error)
1750 {
1751     Dwarf_Debug dbg;
1752 
1753     dbg = fde->fd_dbg;
1754     if (dbg == NULL) {
1755 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
1756 	return (DW_DLV_ERROR);
1757     }
1758     *offset_into_exception_tables =
1759 	fde->fd_offset_into_exception_tables;
1760     return DW_DLV_OK;
1761 }
1762 
1763 
1764 int
1765 dwarf_get_cie_info(Dwarf_Cie cie,
1766 		   Dwarf_Unsigned * bytes_in_cie,
1767 		   Dwarf_Small * version,
1768 		   char **augmenter,
1769 		   Dwarf_Unsigned * code_alignment_factor,
1770 		   Dwarf_Signed * data_alignment_factor,
1771 		   Dwarf_Half * return_address_register,
1772 		   Dwarf_Ptr * initial_instructions,
1773 		   Dwarf_Unsigned * initial_instructions_length,
1774 		   Dwarf_Error * error)
1775 {
1776     Dwarf_Debug dbg;
1777 
1778     if (cie == NULL) {
1779 	_dwarf_error(NULL, error, DW_DLE_CIE_NULL);
1780 	return (DW_DLV_ERROR);
1781     }
1782 
1783     dbg = cie->ci_dbg;
1784     if (dbg == NULL) {
1785 	_dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL);
1786 	return (DW_DLV_ERROR);
1787     }
1788 
1789     if (version != NULL)
1790 	*version = DW_CIE_VERSION;
1791     if (augmenter != NULL)
1792 	*augmenter = cie->ci_augmentation;
1793     if (code_alignment_factor != NULL)
1794 	*code_alignment_factor = cie->ci_code_alignment_factor;
1795     if (data_alignment_factor != NULL)
1796 	*data_alignment_factor = cie->ci_data_alignment_factor;
1797     if (return_address_register != NULL)
1798 	*return_address_register = cie->ci_return_address_register;
1799     if (initial_instructions != NULL)
1800 	*initial_instructions = cie->ci_cie_instr_start;
1801     if (initial_instructions_length != NULL) {
1802 	*initial_instructions_length = cie->ci_length +
1803 	    cie->ci_length_size +
1804 	    cie->ci_extension_size -
1805 	    (cie->ci_cie_instr_start - cie->ci_cie_start);
1806 
1807     }
1808     *bytes_in_cie = (cie->ci_length);
1809     return (DW_DLV_OK);
1810 }
1811 
1812 static int
1813 _dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde,
1814 				 Dwarf_Addr pc_requested,
1815 				 Dwarf_Frame table, Dwarf_Error * error)
1816 /* Return the register rules for all registers at a given pc. */
1817 {
1818     Dwarf_Debug dbg;
1819     Dwarf_Cie cie;
1820     Dwarf_Sword i;
1821     int dw_err;
1822     Dwarf_Sword icount;
1823     int res;
1824 
1825     if (fde == NULL) {
1826 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
1827 	return (DW_DLV_ERROR);
1828     }
1829 
1830     dbg = fde->fd_dbg;
1831     if (dbg == NULL) {
1832 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
1833 	return (DW_DLV_ERROR);
1834     }
1835 
1836     if (pc_requested < fde->fd_initial_location ||
1837 	pc_requested >=
1838 	fde->fd_initial_location + fde->fd_address_range) {
1839 	_dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
1840 	return (DW_DLV_ERROR);
1841     }
1842 
1843     cie = fde->fd_cie;
1844     if (cie->ci_initial_table == NULL) {
1845 	cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
1846 	if (cie->ci_initial_table == NULL) {
1847 	    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1848 	    return (DW_DLV_ERROR);
1849 	}
1850 	for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++) {
1851 	    cie->ci_initial_table->fr_reg[i].ru_is_off = 0;
1852 	    cie->ci_initial_table->fr_reg[i].ru_register =
1853 		DW_FRAME_SAME_VAL;
1854 	    cie->ci_initial_table->fr_reg[i].ru_offset = 0;
1855 	}
1856 
1857 	res = _dwarf_exec_frame_instr( /* make_instr= */ false,
1858 				      /* ret_frame_instr= */ NULL,
1859 				      /* search_pc */ false,
1860 				      /* search_pc_val */ 0,
1861 				      /* location */ 0,
1862 				      cie->ci_cie_instr_start,
1863 				      cie->ci_cie_instr_start +
1864 				      (cie->ci_length +
1865 				       cie->ci_length_size +
1866 				       cie->ci_extension_size -
1867 				       (cie->ci_cie_instr_start -
1868 					cie->ci_cie_start)),
1869 				      cie->ci_initial_table, cie, dbg,
1870 				      &icount, &dw_err);
1871 	if (res == DW_DLV_ERROR) {
1872 	    _dwarf_error(dbg, error, dw_err);
1873 	    return (res);
1874 	} else if (res == DW_DLV_NO_ENTRY) {
1875 	    return res;
1876 	}
1877     }
1878 
1879     res = _dwarf_exec_frame_instr( /* make_instr= */ false,
1880 				  /* ret_frame_instr= */ NULL,
1881 				  /* search_pc */ true,
1882 				  /* search_pc_val */ pc_requested,
1883 				  fde->fd_initial_location,
1884 				  fde->fd_fde_instr_start,
1885 				  fde->fd_fde_start + fde->fd_length +
1886 				  fde->fd_length_size +
1887 				  fde->fd_extension_size,
1888 				  table, cie, dbg, &icount, &dw_err);
1889     if (res == DW_DLV_ERROR) {
1890 	_dwarf_error(dbg, error, dw_err);
1891 	return (res);
1892     } else if (res == DW_DLV_NO_ENTRY) {
1893 	return res;
1894     }
1895 
1896     return DW_DLV_OK;
1897 }
1898 
1899 int
1900 dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde,
1901 				Dwarf_Addr pc_requested,
1902 				Dwarf_Regtable * reg_table,
1903 				Dwarf_Addr * row_pc,
1904 				Dwarf_Error * error)
1905 {
1906 
1907     struct Dwarf_Frame_s fde_table;
1908     Dwarf_Sword i;
1909     int res;
1910 
1911     /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
1912      */
1913     res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
1914 					   &fde_table, error);
1915     if (res != DW_DLV_OK) {
1916 	return res;
1917     }
1918 
1919     for (i = 0; i < DW_REG_TABLE_SIZE; i++) {
1920 	reg_table->rules[i].dw_offset_relevant =
1921 	    fde_table.fr_reg[i].ru_is_off;
1922 	reg_table->rules[i].dw_regnum = fde_table.fr_reg[i].ru_register;
1923 	reg_table->rules[i].dw_offset = fde_table.fr_reg[i].ru_offset;
1924     }
1925 
1926     if (row_pc != NULL)
1927 	*row_pc = fde_table.fr_loc;
1928 
1929     return DW_DLV_OK;
1930 }
1931 
1932 
1933 int
1934 dwarf_get_fde_info_for_reg(Dwarf_Fde fde,
1935 			   Dwarf_Half table_column,
1936 			   Dwarf_Addr pc_requested,
1937 			   Dwarf_Signed * offset_relevant,
1938 			   Dwarf_Signed * register_num,
1939 			   Dwarf_Signed * offset,
1940 			   Dwarf_Addr * row_pc, Dwarf_Error * error)
1941 {
1942     struct Dwarf_Frame_s fde_table;
1943     int res;
1944 
1945 
1946     if (table_column > DW_FRAME_LAST_REG_NUM) {
1947 	_dwarf_error(NULL, error, DW_DLE_FRAME_TABLE_COL_BAD);
1948 	return (DW_DLV_ERROR);
1949     }
1950 
1951     /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
1952      */
1953     res =
1954 	_dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
1955 					 error);
1956     if (res != DW_DLV_OK) {
1957 	return res;
1958     }
1959 
1960     if (register_num != NULL)
1961 	*register_num = fde_table.fr_reg[table_column].ru_register;
1962     if (offset != NULL)
1963 	*offset = fde_table.fr_reg[table_column].ru_offset;
1964     if (row_pc != NULL)
1965 	*row_pc = fde_table.fr_loc;
1966 
1967     *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off);
1968     return DW_DLV_OK;
1969 }
1970 
1971 /*
1972 	Return pointer to the instructions in the dwarf
1973 	fde.
1974 */
1975 int
1976 dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr,
1977 			  Dwarf_Unsigned * outaddrlen,
1978 			  Dwarf_Error * error)
1979 {
1980     Dwarf_Unsigned len;
1981     unsigned char *instrs;
1982     Dwarf_Debug dbg;
1983 
1984     if (inFde == NULL) {
1985 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
1986 	return (DW_DLV_ERROR);
1987     }
1988 
1989     dbg = inFde->fd_dbg;
1990     if (dbg == NULL) {
1991 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
1992 	return (DW_DLV_ERROR);
1993     }
1994 
1995     instrs = inFde->fd_fde_instr_start,
1996 	len = (inFde->fd_fde_start + inFde->fd_length +
1997 	       inFde->fd_length_size + inFde->fd_extension_size)
1998 	- instrs;
1999 
2000     *outinstraddr = instrs;
2001     *outaddrlen = len;
2002     return DW_DLV_OK;
2003 }
2004 
2005 int
2006 dwarf_get_fde_n(Dwarf_Fde * fde_data,
2007 		Dwarf_Unsigned fde_index,
2008 		Dwarf_Fde * returned_fde, Dwarf_Error * error)
2009 {
2010     Dwarf_Debug dbg;
2011 
2012     if (fde_data == NULL) {
2013 	_dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
2014 	return (DW_DLV_ERROR);
2015     }
2016 
2017     if (*fde_data == NULL) {
2018 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
2019 	return (DW_DLV_ERROR);
2020     }
2021 
2022     dbg = (*fde_data)->fd_dbg;
2023     if (dbg == NULL) {
2024 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
2025 	return (DW_DLV_ERROR);
2026     }
2027 
2028     if (fde_index >= dbg->de_fde_count) {
2029 	return (DW_DLV_NO_ENTRY);
2030     }
2031     *returned_fde = (*(fde_data + fde_index));
2032     return DW_DLV_OK;
2033 }
2034 
2035 
2036 /*
2037     Lopc and hipc are extensions to the interface to
2038     return the range of addresses that are described
2039     by the returned fde.
2040 */
2041 int
2042 dwarf_get_fde_at_pc(Dwarf_Fde * fde_data,
2043 		    Dwarf_Addr pc_of_interest,
2044 		    Dwarf_Fde * returned_fde,
2045 		    Dwarf_Addr * lopc,
2046 		    Dwarf_Addr * hipc, Dwarf_Error * error)
2047 {
2048     Dwarf_Debug dbg;
2049     Dwarf_Fde fde = NULL;
2050 
2051     if (fde_data == NULL) {
2052 	_dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
2053 	return (DW_DLV_ERROR);
2054     }
2055 
2056     if (*fde_data == NULL) {
2057 	_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
2058 	return (DW_DLV_ERROR);
2059     }
2060 
2061     dbg = (*fde_data)->fd_dbg;
2062     if (dbg == NULL) {
2063 	_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
2064 	return (DW_DLV_ERROR);
2065     }
2066     {
2067 	/* The fde's are sorted by their addresses. Binary search to
2068 	   find correct fde. */
2069 	int low = 0;
2070 	int high = dbg->de_fde_count - 1;
2071 	int middle = 0;
2072 	Dwarf_Fde cur_fde;
2073 
2074 	while (low <= high) {
2075 	    middle = (low + high) / 2;
2076 	    cur_fde = fde_data[middle];
2077 	    if (pc_of_interest < cur_fde->fd_initial_location) {
2078 		high = middle - 1;
2079 	    } else if (pc_of_interest >=
2080 		       (cur_fde->fd_initial_location +
2081 			cur_fde->fd_address_range)) {
2082 		low = middle + 1;
2083 	    } else {
2084 		fde = fde_data[middle];
2085 		break;
2086 	    }
2087 	}
2088     }
2089 
2090     if (fde) {
2091 	if (lopc != NULL)
2092 	    *lopc = fde->fd_initial_location;
2093 	if (hipc != NULL)
2094 	    *hipc = fde->fd_initial_location +
2095 		fde->fd_address_range - 1;
2096 	*returned_fde = fde;
2097 	return (DW_DLV_OK);
2098     }
2099 
2100     return (DW_DLV_NO_ENTRY);
2101 }
2102 
2103 
2104 int
2105 dwarf_expand_frame_instructions(Dwarf_Debug dbg,
2106 				Dwarf_Ptr instruction,
2107 				Dwarf_Unsigned i_length,
2108 				Dwarf_Frame_Op ** returned_op_list,
2109 				Dwarf_Signed * returned_op_count,
2110 				Dwarf_Error * error)
2111 {
2112     Dwarf_Sword instr_count;
2113     int res;
2114     int dw_err;
2115 
2116     if (dbg == 0) {
2117 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
2118 	return (DW_DLV_ERROR);
2119     }
2120 
2121     if (returned_op_list == 0 || returned_op_count == 0) {
2122 	_dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL);
2123 	return (DW_DLV_ERROR);
2124     }
2125 
2126     /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe
2127        as it is just an i_length offset from 'instruction' itself. A
2128        caller has made a big mistake if the result is not a valid
2129        pointer. */
2130     res = _dwarf_exec_frame_instr( /* make_instr= */ true,
2131 				  returned_op_list,
2132 				  /* search_pc */ false,
2133 				  /* search_pc_val */ 0,
2134 				  /* location */ 0,
2135 				  instruction,
2136 				  (Dwarf_Ptr)((char *)instruction + i_length),
2137 				  /* Dwarf_Frame */ NULL,
2138 				  /* cie_ptr */ NULL,
2139 				  dbg, &instr_count, &dw_err);
2140     if (res != DW_DLV_OK) {
2141 	if (res == DW_DLV_ERROR) {
2142 	    _dwarf_error(dbg, error, dw_err);
2143 	}
2144 	return (res);
2145     }
2146 
2147     *returned_op_count = instr_count;
2148     return DW_DLV_OK;
2149 }
2150 
2151 
2152 
2153 /*
2154 	Used by rqs.  Returns DW_DLV_OK if returns the arrays.
2155 	Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
2156 	Returns DW_DLV_ERROR if there is an error.
2157 
2158 */
2159 int
2160 _dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
2161 			     Dwarf_Off ** offsetlist,
2162 			     Dwarf_Signed * returncount,
2163 			     Dwarf_Error * err)
2164 {
2165     int retval = DW_DLV_OK;
2166     int res;
2167     Dwarf_Cie *cie_data;
2168     Dwarf_Signed cie_count;
2169     Dwarf_Fde *fde_data;
2170     Dwarf_Signed fde_count;
2171     Dwarf_Signed i;
2172     Dwarf_Frame_Op *frame_inst;
2173     Dwarf_Fde fdep;
2174     Dwarf_Cie ciep;
2175     Dwarf_Chain curr_chain = 0;
2176     Dwarf_Chain head_chain = 0;
2177     Dwarf_Chain prev_chain = 0;
2178     Dwarf_Arange arange;
2179     Dwarf_Unsigned arange_count = 0;
2180     Dwarf_Addr *arange_addrs = 0;
2181     Dwarf_Off *arange_offsets = 0;
2182 
2183     res = dwarf_get_fde_list(dbg, &cie_data, &cie_count,
2184 			     &fde_data, &fde_count, err);
2185     if (res != DW_DLV_OK) {
2186 	return res;
2187     }
2188 
2189     res =
2190         _dwarf_load_section(dbg,
2191 			    dbg->de_debug_frame_index,
2192 			    &dbg->de_debug_frame,
2193 			    err);
2194     if (res != DW_DLV_OK) {
2195       return res;
2196     }
2197 
2198     for (i = 0; i < cie_count; i++) {
2199 	Dwarf_Off instoff = 0;
2200 	Dwarf_Signed initial_instructions_length = 0;
2201 	Dwarf_Small *instr_end = 0;
2202 	Dwarf_Sword icount = 0;
2203 	int j;
2204 	int dw_err;
2205 
2206 	ciep = cie_data[i];
2207 	instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame;
2208 	initial_instructions_length = ciep->ci_length +
2209 	    ciep->ci_length_size + ciep->ci_extension_size -
2210 	    (ciep->ci_cie_instr_start - ciep->ci_cie_start);
2211 	instr_end = ciep->ci_cie_instr_start +
2212 	    initial_instructions_length;
2213 	res = _dwarf_exec_frame_instr( /* make_instr */ true,
2214 				      &frame_inst,
2215 				      /* search_pc= */ false,
2216 				      /* search_pc_val= */ 0,
2217 				      /* location */ 0,
2218 				      ciep->ci_cie_instr_start,
2219 				      instr_end,
2220 				      /* Dwarf_frame= */ 0,
2221 				      /* cie= */ 0,
2222 				      dbg, &icount, &dw_err);
2223 	if (res == DW_DLV_ERROR) {
2224 	    _dwarf_error(dbg, err, dw_err);
2225 	    return (res);
2226 	} else if (res == DW_DLV_NO_ENTRY) {
2227 	    continue;
2228 	}
2229 
2230 	for (j = 0; j < icount; ++j) {
2231 	    Dwarf_Frame_Op *finst = frame_inst + j;
2232 
2233 	    if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) {
2234 		/* is DW_CFA_set_loc */
2235 		Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset;
2236 		Dwarf_Off off = finst->fp_instr_offset + instoff;
2237 
2238 		arange = (Dwarf_Arange)
2239 		    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
2240 		if (arange == NULL) {
2241 		    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2242 		    return (DW_DLV_ERROR);
2243 		}
2244 		arange->ar_address = add;
2245 		arange->ar_info_offset = off;
2246 		arange_count++;
2247 		curr_chain = (Dwarf_Chain)
2248 		    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
2249 		if (curr_chain == NULL) {
2250 		    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2251 		    return (DW_DLV_ERROR);
2252 		}
2253 		curr_chain->ch_item = arange;
2254 		if (head_chain == NULL)
2255 		    head_chain = prev_chain = curr_chain;
2256 		else {
2257 		    prev_chain->ch_next = curr_chain;
2258 		    prev_chain = curr_chain;
2259 		}
2260 	    }
2261 	}
2262 	dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
2263 
2264     }
2265     for (i = 0; i < fde_count; i++) {
2266 	Dwarf_Small *instr_end = 0;
2267 	Dwarf_Sword icount = 0;
2268 	Dwarf_Signed instructions_length = 0;
2269 	Dwarf_Off instoff = 0;
2270 	Dwarf_Off off = 0;
2271 	Dwarf_Addr addr = 0;
2272 	int j;
2273 	int dw_err;
2274 
2275 	fdep = fde_data[i];
2276 	off = fdep->fd_initial_loc_pos - dbg->de_debug_frame;
2277 	addr = fdep->fd_initial_location;
2278 	arange = (Dwarf_Arange)
2279 	    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
2280 	if (arange == NULL) {
2281 	    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2282 	    return (DW_DLV_ERROR);
2283 	}
2284 	arange->ar_address = addr;
2285 	arange->ar_info_offset = off;
2286 	arange_count++;
2287 	curr_chain = (Dwarf_Chain)
2288 	    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
2289 	if (curr_chain == NULL) {
2290 	    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2291 	    return (DW_DLV_ERROR);
2292 	}
2293 	curr_chain->ch_item = arange;
2294 	if (head_chain == NULL)
2295 	    head_chain = prev_chain = curr_chain;
2296 	else {
2297 	    prev_chain->ch_next = curr_chain;
2298 	    prev_chain = curr_chain;
2299 	}
2300 
2301 
2302 	instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame;
2303 	instructions_length = fdep->fd_length +
2304 	    fdep->fd_length_size + fdep->fd_extension_size -
2305 	    (fdep->fd_fde_instr_start - fdep->fd_fde_start);
2306 	instr_end = fdep->fd_fde_instr_start + instructions_length;
2307 	res = _dwarf_exec_frame_instr( /* make_instr */ true,
2308 				      &frame_inst,
2309 				      /* search_pc= */ false,
2310 				      /* search_pc_val= */ 0,
2311 				      /* location */ 0,
2312 				      fdep->fd_fde_instr_start,
2313 				      instr_end,
2314 				      /* Dwarf_frame= */ 0,
2315 				      /* cie= */ 0,
2316 				      dbg, &icount, &dw_err);
2317 	if (res == DW_DLV_ERROR) {
2318 	    _dwarf_error(dbg, err, dw_err);
2319 	    return (res);
2320 	} else if (res == DW_DLV_NO_ENTRY) {
2321 	    continue;
2322 	}
2323 
2324 	for (j = 0; j < icount; ++j) {
2325 	    Dwarf_Frame_Op *finst2 = frame_inst + j;
2326 
2327 	    if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) {
2328 		/* is DW_CFA_set_loc */
2329 		Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset;
2330 		Dwarf_Off off = finst2->fp_instr_offset + instoff;
2331 
2332 		arange = (Dwarf_Arange)
2333 		    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
2334 		if (arange == NULL) {
2335 		    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2336 		    return (DW_DLV_ERROR);
2337 		}
2338 		arange->ar_address = add;
2339 		arange->ar_info_offset = off;
2340 		arange_count++;
2341 		curr_chain = (Dwarf_Chain)
2342 		    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
2343 		if (curr_chain == NULL) {
2344 		    _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2345 		    return (DW_DLV_ERROR);
2346 		}
2347 		curr_chain->ch_item = arange;
2348 		if (head_chain == NULL)
2349 		    head_chain = prev_chain = curr_chain;
2350 		else {
2351 		    prev_chain->ch_next = curr_chain;
2352 		    prev_chain = curr_chain;
2353 		}
2354 
2355 	    }
2356 	}
2357 	dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
2358 
2359     }
2360     dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
2361     dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
2362     arange_addrs = (Dwarf_Addr *)
2363 	_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
2364     if (arange_addrs == NULL) {
2365 	_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2366 	return (DW_DLV_ERROR);
2367     }
2368     arange_offsets = (Dwarf_Off *)
2369 	_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
2370     if (arange_offsets == NULL) {
2371 	_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
2372 	return (DW_DLV_ERROR);
2373     }
2374 
2375     curr_chain = head_chain;
2376     for (i = 0; i < arange_count; i++) {
2377 	Dwarf_Arange ar = curr_chain->ch_item;
2378 
2379 	arange_addrs[i] = ar->ar_address;
2380 	arange_offsets[i] = ar->ar_info_offset;
2381 	prev_chain = curr_chain;
2382 	curr_chain = curr_chain->ch_next;
2383 	dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
2384 	dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
2385     }
2386     *returncount = arange_count;
2387     *offsetlist = arange_offsets;
2388     *addrlist = arange_addrs;
2389     return retval;
2390 }
2391 
2392 /* Used by dwarfdump -v to print offsets, for debugging
2393    dwarf info
2394 */
2395 /* ARGSUSED 4 */
2396 int
2397 _dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
2398 			  Dwarf_Off * fde_off, Dwarf_Off * cie_off,
2399 			  Dwarf_Error * err)
2400 {
2401     int res;
2402     char *start;
2403     char *loc;
2404 
2405     res =
2406         _dwarf_load_section(dbg,
2407 			    dbg->de_debug_frame_index,
2408 			    &dbg->de_debug_frame,
2409 			    err);
2410     if (res != DW_DLV_OK) {
2411         return res;
2412     }
2413 
2414     start = (char *) dbg->de_debug_frame;
2415     loc = (char *) in_fde->fd_fde_start;
2416 
2417     *fde_off = (loc - start);
2418     *cie_off = in_fde->fd_cie_offset;
2419     return DW_DLV_OK;
2420 }
2421 
2422 /* Used by dwarfdump -v to print offsets, for debugging
2423    dwarf info
2424 */
2425 /* ARGSUSED 4 */
2426 int
2427 _dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
2428 			  Dwarf_Off * cie_off, Dwarf_Error * err)
2429 {
2430     int res;
2431     char *start;
2432     char *loc;
2433 
2434     res =
2435         _dwarf_load_section(dbg,
2436 			    dbg->de_debug_frame_index,
2437 			    &dbg->de_debug_frame,
2438 			    err);
2439     if (res != DW_DLV_OK) {
2440         return res;
2441     }
2442 
2443     start = (char *) dbg->de_debug_frame;
2444     loc = (char *) in_cie->ci_cie_start;
2445 
2446     *cie_off = (loc - start);
2447     return DW_DLV_OK;
2448 }
2449