xref: /titanic_44/usr/src/tools/ctf/dwarf/common/pro_section.c (revision f05d7fc81533be643136e12ce92516d1d4292921)
1 /*
2 
3   Copyright (C) 2000 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 "libdwarfdefs.h"
40 #include <stdio.h>
41 #include <string.h>
42 #ifdef   HAVE_ELFACCESS_H
43 #include <elfaccess.h>
44 #endif
45 #include "pro_incl.h"
46 #include "pro_section.h"
47 #include "pro_line.h"
48 #include "pro_frame.h"
49 #include "pro_die.h"
50 #include "pro_macinfo.h"
51 #include "pro_types.h"
52 
53 #ifndef SHF_MIPS_NOSTRIP
54 /* if this is not defined, we probably don't need it: just use 0 */
55 #define SHF_MIPS_NOSTRIP 0
56 #endif
57 #ifndef R_MIPS_NONE
58 #define R_MIPS_NONE 0
59 #endif
60 
61 #ifndef TRUE
62 #define TRUE 1
63 #endif
64 #ifndef FALSE
65 #define FALSE 0
66 #endif
67 
68 /* must match up with pro_section.h defines of DEBUG_INFO etc
69 and sectnames (below)
70 */
71 char *_dwarf_rel_section_names[] = {
72     ".rel.debug_info",
73     ".rel.debug_line",
74     ".rel.debug_abbrev",	/* no relocations on this, really */
75     ".rel.debug_frame",
76     ".rel.debug_aranges",
77     ".rel.debug_pubnames",
78     ".rel.debug_str",
79     ".rel.debug_funcnames",	/* sgi extension */
80     ".rel.debug_typenames",	/* sgi extension */
81     ".rel.debug_varnames",	/* sgi extension */
82     ".rel.debug_weaknames",	/* sgi extension */
83     ".rel.debug_macinfo",
84     ".rel.debug_loc"
85 };
86 
87 /* names of sections. Ensure that it matches the defines
88    in pro_section.h, in the same order
89    Must match also _dwarf_rel_section_names above
90 */
91 char *_dwarf_sectnames[] = {
92     ".debug_info",
93     ".debug_line",
94     ".debug_abbrev",
95     ".debug_frame",
96     ".debug_aranges",
97     ".debug_pubnames",
98     ".debug_str",
99     ".debug_funcnames",		/* sgi extension */
100     ".debug_typenames",		/* sgi extension */
101     ".debug_varnames",		/* sgi extension */
102     ".debug_weaknames",		/* sgi extension */
103     ".debug_macinfo",
104     ".debug_loc"
105 };
106 
107 
108 
109 
110 static Dwarf_Ubyte std_opcode_len[] = { 0,	/* DW_LNS_copy */
111     1,				/* DW_LNS_advance_pc */
112     1,				/* DW_LNS_advance_line */
113     1,				/* DW_LNS_set_file */
114     1,				/* DW_LNS_set_column */
115     0,				/* DW_LNS_negate_stmt */
116     0,				/* DW_LNS_set_basic_block */
117     0,				/* DW_LNS_const_add_pc */
118     1,				/* DW_LNS_fixed_advance_pc */
119 };
120 
121 /* struct to hold relocation entries. Its mantained as a linked
122    list of relocation structs, and will then be written at as a
123    whole into the relocation section. Whether its 32 bit or
124    64 bit will be obtained from Dwarf_Debug pointer.
125 */
126 
127 typedef struct Dwarf_P_Rel_s *Dwarf_P_Rel;
128 struct Dwarf_P_Rel_s {
129     Dwarf_P_Rel dr_next;
130     void *dr_rel_datap;
131 };
132 typedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head;
133 struct Dwarf_P_Rel_Head_s {
134     struct Dwarf_P_Rel_s *drh_head;
135     struct Dwarf_P_Rel_s *drh_tail;
136 };
137 
138 static int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
139 					 Dwarf_Error * error);
140 static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
141 					  Dwarf_Error * error);
142 static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
143 					 Dwarf_Error * error);
144 static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev);
145 static int _dwarf_pro_match_attr
146     (Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr);
147 
148 /* these macros used as return value for below functions */
149 #define		OPC_INCS_ZERO		-1
150 #define		OPC_OUT_OF_RANGE	-2
151 #define		LINE_OUT_OF_RANGE	-3
152 static int _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv);
153 
154 
155 
156 /*
157 	Return TRUE if we need the section, FALSE otherwise
158 
159         If any of the 'line-data-related' calls were made
160         including file or directory entries,
161         produce .debug_line .
162 
163 */
164 static int
165 dwarf_need_debug_line_section(Dwarf_P_Debug dbg)
166 {
167     if (dbg->de_lines == NULL && dbg->de_file_entries == NULL
168 	&& dbg->de_inc_dirs == NULL) {
169 	return FALSE;
170     }
171     return TRUE;
172 }
173 
174 /*
175     Convert debug information to  a format such that
176     it can be written on disk.
177     Called exactly once per execution.
178 */
179 Dwarf_Signed
180 dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error)
181 {
182     /*
183        Section data in written out in a number of buffers. Each
184        _generate_*() function returns a cumulative count of buffers for
185        all the sections. get_section_bytes() returns pointers to these
186        buffers one at a time. */
187     int nbufs;
188     int sect;
189     int name_idx;
190     int err;
191     Dwarf_Unsigned du;
192 
193     if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
194 	DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT);
195     }
196 
197     /* Create dwarf section headers */
198     for (sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) {
199 	long flags = 0;
200 
201 	switch (sect) {
202 
203 	case DEBUG_INFO:
204 	    if (dbg->de_dies == NULL)
205 		continue;
206 	    break;
207 
208 	case DEBUG_LINE:
209 	    if (dwarf_need_debug_line_section(dbg) == FALSE) {
210 		continue;
211 	    }
212 	    break;
213 
214 	case DEBUG_ABBREV:
215 	    if (dbg->de_dies == NULL)
216 		continue;
217 	    break;
218 
219 	case DEBUG_FRAME:
220 	    if (dbg->de_frame_cies == NULL)
221 		continue;
222 	    flags = SHF_MIPS_NOSTRIP;
223 	    break;
224 
225 	case DEBUG_ARANGES:
226 	    if (dbg->de_arange == NULL)
227 		continue;
228 	    break;
229 
230 	case DEBUG_PUBNAMES:
231 	    if (dbg->de_simple_name_headers[dwarf_snk_pubname].
232 		sn_head == NULL)
233 		continue;
234 	    break;
235 
236 	case DEBUG_STR:
237 	    if (dbg->de_strings == NULL)
238 		continue;
239 	    break;
240 
241 	case DEBUG_FUNCNAMES:
242 	    if (dbg->de_simple_name_headers[dwarf_snk_funcname].
243 		sn_head == NULL)
244 		continue;
245 	    break;
246 
247 	case DEBUG_TYPENAMES:
248 	    if (dbg->de_simple_name_headers[dwarf_snk_typename].
249 		sn_head == NULL)
250 		continue;
251 	    break;
252 
253 	case DEBUG_VARNAMES:
254 	    if (dbg->de_simple_name_headers[dwarf_snk_varname].
255 		sn_head == NULL)
256 		continue;
257 	    break;
258 
259 	case DEBUG_WEAKNAMES:
260 	    if (dbg->de_simple_name_headers[dwarf_snk_weakname].
261 		sn_head == NULL)
262 		continue;
263 	    break;
264 
265 	case DEBUG_MACINFO:
266 	    if (dbg->de_first_macinfo == NULL)
267 		continue;
268 	    break;
269 	case DEBUG_LOC:
270 	    /* not handled yet */
271 	    continue;
272 	default:
273 	    /* logic error: missing a case */
274 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT);
275 	}
276 	{
277 	    int new_base_elf_sect;
278 
279 	    if (dbg->de_func_b) {
280 		new_base_elf_sect =
281 		    dbg->de_func_b(_dwarf_sectnames[sect],
282 				   /* rec size */ 1,
283 				   SECTION_TYPE,
284 				   flags, SHN_UNDEF, 0, &du, &err);
285 
286 	    } else {
287 		new_base_elf_sect = dbg->de_func(_dwarf_sectnames[sect],
288 						 dbg->
289 						 de_relocation_record_size,
290 						 SECTION_TYPE, flags,
291 						 SHN_UNDEF, 0,
292 						 &name_idx, &err);
293 		du = name_idx;
294 	    }
295 	    if (new_base_elf_sect == -1) {
296 		DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR,
297 				  DW_DLV_NOCOUNT);
298 	    }
299 	    dbg->de_elf_sects[sect] = new_base_elf_sect;
300 
301 	    dbg->de_sect_name_idx[sect] = du;
302 	}
303     }
304 
305     nbufs = 0;
306 
307     /*
308        Changing the order in which the sections are generated may
309        cause problems because of relocations. */
310 
311     if (dwarf_need_debug_line_section(dbg) == TRUE) {
312 	nbufs = _dwarf_pro_generate_debugline(dbg, error);
313 	if (nbufs < 0) {
314 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR,
315 			      DW_DLV_NOCOUNT);
316 	}
317     }
318 
319     if (dbg->de_frame_cies) {
320 	nbufs = _dwarf_pro_generate_debugframe(dbg, error);
321 	if (nbufs < 0) {
322 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR,
323 			      DW_DLV_NOCOUNT);
324 	}
325     }
326     if (dbg->de_first_macinfo) {
327 	nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error);
328 	if (nbufs < 0) {
329 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR,
330 			      DW_DLV_NOCOUNT);
331 	}
332     }
333 
334     if (dbg->de_dies) {
335 	nbufs = _dwarf_pro_generate_debuginfo(dbg, error);
336 	if (nbufs < 0) {
337 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
338 			      DW_DLV_NOCOUNT);
339 	}
340     }
341 
342     if (dbg->de_arange) {
343 	nbufs = _dwarf_transform_arange_to_disk(dbg, error);
344 	if (nbufs < 0) {
345 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
346 			      DW_DLV_NOCOUNT);
347 	}
348     }
349 
350     if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) {
351 	nbufs = _dwarf_transform_simplename_to_disk(dbg,
352 						    dwarf_snk_pubname,
353 						    DEBUG_PUBNAMES,
354 						    error);
355 
356 
357 	if (nbufs < 0) {
358 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
359 			      DW_DLV_NOCOUNT);
360 	}
361     }
362 
363     if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) {
364 	nbufs = _dwarf_transform_simplename_to_disk(dbg,
365 						    dwarf_snk_funcname,
366 						    DEBUG_FUNCNAMES,
367 						    error);
368 	if (nbufs < 0) {
369 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
370 			      DW_DLV_NOCOUNT);
371 	}
372     }
373 
374     if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) {
375 	nbufs = _dwarf_transform_simplename_to_disk(dbg,
376 						    dwarf_snk_typename,
377 						    DEBUG_TYPENAMES,
378 						    error);
379 	if (nbufs < 0) {
380 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
381 			      DW_DLV_NOCOUNT);
382 	}
383     }
384 
385     if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) {
386 	nbufs = _dwarf_transform_simplename_to_disk(dbg,
387 						    dwarf_snk_varname,
388 						    DEBUG_VARNAMES,
389 						    error);
390 
391 	if (nbufs < 0) {
392 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
393 			      DW_DLV_NOCOUNT);
394 	}
395     }
396 
397     if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) {
398 	nbufs = _dwarf_transform_simplename_to_disk(dbg,
399 						    dwarf_snk_weakname,
400 						    DEBUG_WEAKNAMES,
401 						    error);
402 
403 	if (nbufs < 0) {
404 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
405 			      DW_DLV_NOCOUNT);
406 	}
407     }
408 
409     {
410 	Dwarf_Signed new_secs;
411 	int res;
412 
413 	res = dbg->de_transform_relocs_to_disk(dbg, &new_secs);
414 	if (res != DW_DLV_OK) {
415 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
416 			      DW_DLV_NOCOUNT);
417 	}
418 	nbufs += new_secs;
419     }
420     return nbufs;
421 }
422 
423 
424 /*---------------------------------------------------------------
425 	Generate debug_line section
426 ---------------------------------------------------------------*/
427 static int
428 _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error)
429 {
430     Dwarf_P_Inc_Dir curdir;
431     Dwarf_P_F_Entry curentry;
432     Dwarf_P_Line curline, prevline;
433 
434     /* all data named cur* are used to loop thru linked lists */
435 
436     int sum_bytes;
437     int prolog_size;
438     unsigned char *data;	/* holds disk form data */
439     int elfsectno;
440     unsigned char *start_line_sec;	/* pointer to the buffer at
441 					   section start */
442     /* temps for memcpy */
443     Dwarf_Unsigned du;
444     Dwarf_Ubyte db;
445     Dwarf_Half dh;
446     int res;
447     int uwordb_size = dbg->de_offset_size;
448     int extension_size = dbg->de_64bit_extension ? 4 : 0;
449     int upointer_size = dbg->de_pointer_size;
450     char buff1[ENCODE_SPACE_NEEDED];
451 
452 
453     sum_bytes = 0;
454 
455     elfsectno = dbg->de_elf_sects[DEBUG_LINE];
456 
457     /* statement prologue information */
458     prolog_size = 0;
459     /* include directories */
460     curdir = dbg->de_inc_dirs;
461     while (curdir) {
462 	prolog_size += strlen(curdir->did_name) + 1;
463 	curdir = curdir->did_next;
464     }
465     prolog_size++;		/* last null following last directory
466 				   entry. */
467 
468     /* file entries */
469     curentry = dbg->de_file_entries;
470     while (curentry) {
471 	prolog_size +=
472 	    strlen(curentry->dfe_name) + 1 + curentry->dfe_nbytes;
473 	curentry = curentry->dfe_next;
474     }
475     prolog_size++;		/* last null byte */
476 
477 
478     prolog_size += extension_size +	/* DISTINGUISHED VALUE */
479 	sizeof_uhalf(dbg) +	/* version # */
480 	uwordb_size +		/* prologue length */
481 	sizeof_ubyte(dbg) +	/* min_instr length */
482 	sizeof_ubyte(dbg) +	/* default is_stmt */
483 	sizeof_ubyte(dbg) +	/* linebase */
484 	sizeof_ubyte(dbg) +	/* linerange */
485 	sizeof_ubyte(dbg);	/* opcode base */
486 
487     /* length of table specifying # of opnds */
488     prolog_size += sizeof(std_opcode_len);
489     prolog_size += uwordb_size;	/* for total length field */
490 
491     GET_CHUNK(dbg, elfsectno, data, prolog_size, error);
492     start_line_sec = data;
493 
494     /* copy over the data */
495     /* total_length */
496     du = 0;
497     if (extension_size) {
498 	Dwarf_Word x = DISTINGUISHED_VALUE;
499 
500 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x,
501 			sizeof(x), extension_size);
502 	data += extension_size;
503     }
504 
505     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
506 		    sizeof(du), uwordb_size);
507     data += uwordb_size;
508 
509     dh = VERSION;
510     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh,
511 		    sizeof(dh), sizeof(Dwarf_Half));
512     data += sizeof(Dwarf_Half);
513 
514     /* prologue length */
515     du = prolog_size - (uwordb_size + sizeof(Dwarf_Half) + uwordb_size);
516     {
517 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
518 			sizeof(du), uwordb_size);
519 	data += uwordb_size;
520     }
521     db = MIN_INST_LENGTH;
522     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
523 		    sizeof(db), sizeof(Dwarf_Ubyte));
524     data += sizeof(Dwarf_Ubyte);
525     db = DEFAULT_IS_STMT;
526     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
527 		    sizeof(db), sizeof(Dwarf_Ubyte));
528     data += sizeof(Dwarf_Ubyte);
529     db = (Dwarf_Ubyte) LINE_BASE;
530     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
531 		    sizeof(db), sizeof(Dwarf_Ubyte));
532     data += sizeof(Dwarf_Ubyte);
533     db = LINE_RANGE;
534     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
535 		    sizeof(db), sizeof(Dwarf_Ubyte));
536     data += sizeof(Dwarf_Ubyte);
537     db = OPCODE_BASE;
538     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
539 		    sizeof(db), sizeof(Dwarf_Ubyte));
540     data += sizeof(Dwarf_Ubyte);
541     WRITE_UNALIGNED(dbg, (void *) data, (const void *) std_opcode_len,
542 		    sizeof(std_opcode_len), sizeof(std_opcode_len));
543     data += sizeof(std_opcode_len);
544 
545     /* copy over include directories */
546     curdir = dbg->de_inc_dirs;
547     while (curdir) {
548 	strcpy((char *) data, curdir->did_name);
549 	data += strlen(curdir->did_name) + 1;
550 	curdir = curdir->did_next;
551     }
552     *data = '\0';		/* last null */
553     data++;
554 
555     /* copy file entries */
556     curentry = dbg->de_file_entries;
557     while (curentry) {
558 	strcpy((char *) data, curentry->dfe_name);
559 	data += strlen(curentry->dfe_name) + 1;
560 	/* copies of leb numbers, no endian issues */
561 	memcpy((void *) data,
562 	       (const void *) curentry->dfe_args, curentry->dfe_nbytes);
563 	data += curentry->dfe_nbytes;
564 	curentry = curentry->dfe_next;
565     }
566     *data = '\0';
567     data++;
568 
569     sum_bytes += prolog_size;
570 
571     curline = dbg->de_lines;
572     prevline = (Dwarf_P_Line)
573 	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
574     if (prevline == NULL) {
575 	DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, -1);
576     }
577     _dwarf_pro_reg_init(prevline);
578     /* generate opcodes for line numbers */
579     while (curline) {
580 	int nbytes;
581 	char *arg;
582 	int opc;
583 	int no_lns_copy;	/* if lns copy opcode doesnt need to be
584 				   generated, if special opcode or end
585 				   sequence */
586 	Dwarf_Unsigned addr_adv;
587 	int line_adv;		/* supposed to be a reasonably small
588 				   number, so the size should not be a
589 				   problem. ? */
590 
591 	no_lns_copy = 0;
592 	if (curline->dpl_opc != 0) {
593 	    int inst_bytes;	/* no of bytes in extended opcode */
594 	    char *str;		/* hold leb encoded inst_bytes */
595 	    int str_nbytes;	/* no of bytes in str */
596 
597 	    switch (curline->dpl_opc) {
598 	    case DW_LNE_end_sequence:
599 
600 		/* Advance pc to end of text section. */
601 		addr_adv = curline->dpl_address - prevline->dpl_address;
602 		if (addr_adv > 0) {
603 		    db = DW_LNS_advance_pc;
604 		    res =
605 			_dwarf_pro_encode_leb128_nm(addr_adv /
606 						    MIN_INST_LENGTH,
607 						    &nbytes, buff1,
608 						    sizeof(buff1));
609 		    if (res != DW_DLV_OK) {
610 			DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
611 		    }
612 		    GET_CHUNK(dbg, elfsectno, data,
613 			      nbytes + sizeof(Dwarf_Ubyte), error);
614 		    WRITE_UNALIGNED(dbg, (void *) data,
615 				    (const void *) &db, sizeof(db),
616 				    sizeof(Dwarf_Ubyte));
617 		    data += sizeof(Dwarf_Ubyte);
618 		    /* leb, no endianness issue */
619 		    memcpy((void *) data, (const void *) buff1, nbytes);
620 		    data += nbytes + sizeof(Dwarf_Ubyte);
621 		    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
622 		    prevline->dpl_address = curline->dpl_address;
623 		}
624 
625 		/* first null byte */
626 		db = 0;
627 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
628 			  error);
629 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
630 				sizeof(db), sizeof(Dwarf_Ubyte));
631 		data += sizeof(Dwarf_Ubyte);
632 		sum_bytes += sizeof(Dwarf_Ubyte);
633 
634 		/* write length of extended opcode */
635 		inst_bytes = sizeof(Dwarf_Ubyte);
636 		res =
637 		    _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
638 						buff1, sizeof(buff1));
639 		if (res != DW_DLV_OK) {
640 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
641 		}
642 		GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
643 		memcpy((void *) data, (const void *) buff1, str_nbytes);
644 		data += str_nbytes;
645 		sum_bytes += str_nbytes;
646 
647 		/* write extended opcode */
648 		db = DW_LNE_end_sequence;
649 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
650 			  error);
651 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
652 				sizeof(db), sizeof(Dwarf_Ubyte));
653 		data += sizeof(Dwarf_Ubyte);
654 		sum_bytes += sizeof(Dwarf_Ubyte);
655 		/* reset value to original values */
656 		_dwarf_pro_reg_init(prevline);
657 		no_lns_copy = 1;
658 		/* this is set only for end_sequence, so that a
659 		   dw_lns_copy is not generated */
660 		break;
661 
662 	    case DW_LNE_set_address:
663 
664 		/* first null byte */
665 		db = 0;
666 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
667 			  error);
668 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
669 				sizeof(db), sizeof(Dwarf_Ubyte));
670 		data += sizeof(Dwarf_Ubyte);
671 		sum_bytes += sizeof(Dwarf_Ubyte);
672 
673 		/* write length of extended opcode */
674 		inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size;
675 		res =
676 		    _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
677 						buff1, sizeof(buff1));
678 		if (res != DW_DLV_OK) {
679 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
680 		}
681 		GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
682 		str = buff1;
683 		/* leb number, no endian issue */
684 		memcpy((void *) data, (const void *) str, str_nbytes);
685 		data += str_nbytes;
686 		sum_bytes += str_nbytes;
687 
688 		/* write extended opcode */
689 		db = DW_LNE_set_address;
690 		GET_CHUNK(dbg, elfsectno, data, upointer_size +
691 			  sizeof(Dwarf_Ubyte), error);
692 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
693 				sizeof(db), sizeof(Dwarf_Ubyte));
694 		data += sizeof(Dwarf_Ubyte);
695 		sum_bytes += sizeof(Dwarf_Ubyte);
696 
697 		/* reloc for address */
698 		res = dbg->de_reloc_name(dbg, DEBUG_LINE, sum_bytes,	/* r_offset
699 									 */
700 					 curline->dpl_r_symidx,
701 					 dwarf_drt_data_reloc,
702 					 uwordb_size);
703 		if (res != DW_DLV_OK) {
704 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
705 		}
706 
707 		/* write offset (address) */
708 		du = curline->dpl_address;
709 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
710 				sizeof(du), upointer_size);
711 		data += upointer_size;
712 		sum_bytes += upointer_size;
713 		prevline->dpl_address = curline->dpl_address;
714 		no_lns_copy = 1;
715 		break;
716 	    }
717 	} else {
718 	    if (curline->dpl_file != prevline->dpl_file) {
719 		db = DW_LNS_set_file;
720 		res =
721 		    _dwarf_pro_encode_leb128_nm(curline->dpl_file,
722 						&nbytes, buff1,
723 						sizeof(buff1));
724 		if (res != DW_DLV_OK) {
725 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
726 		}
727 		arg = buff1;
728 		GET_CHUNK(dbg, elfsectno, data,
729 			  nbytes + sizeof(Dwarf_Ubyte), error);
730 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
731 				sizeof(db), sizeof(Dwarf_Ubyte));
732 		data += sizeof(Dwarf_Ubyte);
733 		memcpy((void *) data, (const void *) arg, nbytes);
734 		data += nbytes;
735 		sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
736 		prevline->dpl_file = curline->dpl_file;
737 	    }
738 	    if (curline->dpl_column != prevline->dpl_column) {
739 		db = DW_LNS_set_column;
740 		res = _dwarf_pro_encode_leb128_nm(curline->dpl_column,
741 						  &nbytes,
742 						  buff1, sizeof(buff1));
743 		if (res != DW_DLV_OK) {
744 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
745 		}
746 
747 		arg = buff1;
748 		GET_CHUNK(dbg, elfsectno, data,
749 			  nbytes + sizeof(Dwarf_Ubyte), error);
750 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
751 				sizeof(db), sizeof(Dwarf_Ubyte));
752 		data += sizeof(Dwarf_Ubyte);
753 		memcpy((void *) data, (const void *) arg, nbytes);
754 		data += nbytes;
755 		sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
756 		prevline->dpl_column = curline->dpl_column;
757 	    }
758 	    if (curline->dpl_is_stmt != prevline->dpl_is_stmt) {
759 		db = DW_LNS_negate_stmt;
760 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
761 			  error);
762 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
763 				sizeof(db), sizeof(Dwarf_Ubyte));
764 		data += sizeof(Dwarf_Ubyte);
765 		sum_bytes += sizeof(Dwarf_Ubyte);
766 		prevline->dpl_is_stmt = curline->dpl_is_stmt;
767 	    }
768 	    if (curline->dpl_basic_block == true &&
769 		prevline->dpl_basic_block == false) {
770 		db = DW_LNS_set_basic_block;
771 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
772 			  error);
773 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
774 				sizeof(db), sizeof(Dwarf_Ubyte));
775 		data += sizeof(Dwarf_Ubyte);
776 		sum_bytes += sizeof(Dwarf_Ubyte);
777 		prevline->dpl_basic_block = curline->dpl_basic_block;
778 	    }
779 	    addr_adv = curline->dpl_address - prevline->dpl_address;
780 
781 	    line_adv = (int) (curline->dpl_line - prevline->dpl_line);
782 	    if ((addr_adv % MIN_INST_LENGTH) != 0) {
783 		DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, -1);
784 	    }
785 	    if ((opc = _dwarf_pro_get_opc(addr_adv, line_adv)) > 0) {
786 		no_lns_copy = 1;
787 		db = opc;
788 		GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
789 			  error);
790 		WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
791 				sizeof(db), sizeof(Dwarf_Ubyte));
792 		data += sizeof(Dwarf_Ubyte);
793 		sum_bytes += sizeof(Dwarf_Ubyte);
794 		prevline->dpl_basic_block = false;
795 		prevline->dpl_address = curline->dpl_address;
796 		prevline->dpl_line = curline->dpl_line;
797 	    } else {
798 		if (addr_adv > 0) {
799 		    db = DW_LNS_advance_pc;
800 		    res =
801 			_dwarf_pro_encode_leb128_nm(addr_adv /
802 						    MIN_INST_LENGTH,
803 						    &nbytes, buff1,
804 						    sizeof(buff1));
805 		    if (res != DW_DLV_OK) {
806 			DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
807 		    }
808 
809 		    arg = buff1;
810 		    GET_CHUNK(dbg, elfsectno, data,
811 			      nbytes + sizeof(Dwarf_Ubyte), error);
812 		    WRITE_UNALIGNED(dbg, (void *) data,
813 				    (const void *) &db,
814 				    sizeof(db), sizeof(Dwarf_Ubyte));
815 		    data += sizeof(Dwarf_Ubyte);
816 		    memcpy((void *) data, (const void *) arg, nbytes);
817 		    data += nbytes + sizeof(Dwarf_Ubyte);
818 		    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
819 		    prevline->dpl_basic_block = false;
820 		    prevline->dpl_address = curline->dpl_address;
821 		}
822 		if (line_adv != 0) {
823 		    db = DW_LNS_advance_line;
824 		    res = _dwarf_pro_encode_signed_leb128_nm(line_adv,
825 							     &nbytes,
826 							     buff1,
827 							     sizeof
828 							     (buff1));
829 		    if (res != DW_DLV_OK) {
830 			DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
831 		    }
832 
833 		    arg = buff1;
834 		    GET_CHUNK(dbg, elfsectno, data,
835 			      nbytes + sizeof(Dwarf_Ubyte), error);
836 		    WRITE_UNALIGNED(dbg, (void *) data,
837 				    (const void *) &db, sizeof(db),
838 				    sizeof(Dwarf_Ubyte));
839 		    data += sizeof(Dwarf_Ubyte);
840 		    memcpy((void *) data, (const void *) arg, nbytes);
841 		    data += nbytes + sizeof(Dwarf_Ubyte);
842 		    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
843 		    prevline->dpl_basic_block = false;
844 		    prevline->dpl_line = curline->dpl_line;
845 		}
846 	    }
847 	}			/* ends else for opc != 0 */
848 	if (no_lns_copy == 0) {	/* if not a special or dw_lne_end_seq
849 				   generate a matrix line */
850 	    db = DW_LNS_copy;
851 	    GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), error);
852 	    WRITE_UNALIGNED(dbg, (void *) data,
853 			    (const void *) &db,
854 			    sizeof(db), sizeof(Dwarf_Ubyte));
855 	    data += sizeof(Dwarf_Ubyte);
856 	    sum_bytes += sizeof(Dwarf_Ubyte);
857 	    prevline->dpl_basic_block = false;
858 	}
859 	curline = curline->dpl_next;
860     }
861 
862     /* write total length field */
863     du = sum_bytes - uwordb_size - extension_size;	/* subtract
864 							   length field
865 							 */
866     {
867 	start_line_sec += extension_size;
868 	WRITE_UNALIGNED(dbg, (void *) start_line_sec,
869 			(const void *) &du, sizeof(du), uwordb_size);
870     }
871 
872     return (int) dbg->de_n_debug_sect;
873 }
874 
875 /*---------------------------------------------------------------
876 	Generate debug_frame section
877 ---------------------------------------------------------------*/
878 static int
879 _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error)
880 {
881     int elfsectno;
882     int i;
883     int firsttime = 1;
884     int pad;			/* pad for padding to align cies and
885 				   fdes */
886     Dwarf_P_Cie curcie;
887     Dwarf_P_Fde curfde;
888     unsigned char *data;
889     Dwarf_sfixed dsw;
890     Dwarf_Unsigned du;
891     Dwarf_Ubyte db;
892     long *cie_offs;		/* holds byte offsets for links to
893 				   fde's */
894     unsigned long cie_length;
895     int cie_no;
896     int uwordb_size = dbg->de_offset_size;
897     int extension_size = dbg->de_64bit_extension ? 4 : 0;
898     int upointer_size = dbg->de_pointer_size;
899     Dwarf_Unsigned cur_off;	/* current offset of written data,
900 				   held for relocation info */
901 
902     elfsectno = dbg->de_elf_sects[DEBUG_FRAME];
903 
904     curcie = dbg->de_frame_cies;
905     cie_length = 0;
906     cur_off = 0;
907     cie_offs = (long *)
908 	_dwarf_p_get_alloc(dbg, sizeof(long) * dbg->de_n_cie);
909     if (cie_offs == NULL) {
910 	DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
911     }
912     /* generate cie number as we go along */
913     cie_no = 1;
914     while (curcie) {
915 	char *code_al;
916 	int c_bytes;
917 	char *data_al;
918 	int d_bytes;
919 	int res;
920 	char buff1[ENCODE_SPACE_NEEDED];
921 	char buff2[ENCODE_SPACE_NEEDED];
922 	char buff3[ENCODE_SPACE_NEEDED];
923 	char *augmentation;
924 	char *augmented_al;
925 	long augmented_fields_length;
926 	int a_bytes;
927 
928 	res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align,
929 					  &c_bytes,
930 					  buff1, sizeof(buff1));
931 	if (res != DW_DLV_OK) {
932 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
933 	}
934 	/* Before April 1999, the following was using an unsigned
935 	   encode. That worked ok even though the decoder used the
936 	   correct signed leb read, but doing the encode correctly
937 	   (according to the dwarf spec) saves space in the output file
938 	   and is completely compatible.
939 
940 	   Note the actual stored amount on MIPS was 10 bytes (!) to
941 	   store the value -4. (hex)fc ffffffff ffffffff 01 The
942 	   libdwarf consumer consumed all 10 bytes too!
943 
944 	   old version res =
945 	   _dwarf_pro_encode_leb128_nm(curcie->cie_data_align,
946 
947 	   below is corrected signed version. */
948 	res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align,
949 						 &d_bytes,
950 						 buff2, sizeof(buff2));
951 	if (res != DW_DLV_OK) {
952 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
953 	}
954 	code_al = buff1;
955 	data_al = buff2;
956 
957 	/* get the correct offset */
958 	if (firsttime) {
959 	    cie_offs[cie_no - 1] = 0;
960 	    firsttime = 0;
961 	} else {
962 	    cie_offs[cie_no - 1] = cie_offs[cie_no - 2] +
963 		(long) cie_length + uwordb_size + extension_size;
964 	}
965 	cie_no++;
966 	augmentation = curcie->cie_aug;
967 	if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
968 	    augmented_fields_length = 0;
969 	    res = _dwarf_pro_encode_leb128_nm(augmented_fields_length,
970 					      &a_bytes, buff3,
971 					      sizeof(buff3));
972 	    augmented_al = buff3;
973 	    if (res != DW_DLV_OK) {
974 		DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
975 	    }
976 	    cie_length = uwordb_size +	/* cie_id */
977 		sizeof(Dwarf_Ubyte) +	/* cie version */
978 		strlen(curcie->cie_aug) + 1 +	/* augmentation */
979 		c_bytes +	/* code alignment factor */
980 		d_bytes +	/* data alignment factor */
981 		sizeof(Dwarf_Ubyte) +	/* return reg address */
982 		a_bytes +	/* augmentation length */
983 		curcie->cie_inst_bytes;
984 	} else {
985 	    cie_length = uwordb_size +	/* cie_id */
986 		sizeof(Dwarf_Ubyte) +	/* cie version */
987 		strlen(curcie->cie_aug) + 1 +	/* augmentation */
988 		c_bytes + d_bytes + sizeof(Dwarf_Ubyte) +	/* return
989 								   reg
990 								   address
991 								 */
992 		curcie->cie_inst_bytes;
993 	}
994 	pad = (int) PADDING(cie_length, upointer_size);
995 	cie_length += pad;
996 	GET_CHUNK(dbg, elfsectno, data, cie_length + uwordb_size
997 		  + extension_size, error);
998 	if (extension_size) {
999 	    Dwarf_Unsigned x = DISTINGUISHED_VALUE;
1000 
1001 	    WRITE_UNALIGNED(dbg, (void *) data,
1002 			    (const void *) &x,
1003 			    sizeof(x), extension_size);
1004 	    data += extension_size;
1005 
1006 	}
1007 	du = cie_length;
1008 	/* total length of cie */
1009 	WRITE_UNALIGNED(dbg, (void *) data,
1010 			(const void *) &du, sizeof(du), uwordb_size);
1011 	data += uwordb_size;
1012 
1013 	/* cie-id is a special value. */
1014 	du = DW_CIE_ID;
1015 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
1016 			sizeof(du), uwordb_size);
1017 	data += uwordb_size;
1018 
1019 	db = curcie->cie_version;
1020 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
1021 			sizeof(db), sizeof(Dwarf_Ubyte));
1022 	data += sizeof(Dwarf_Ubyte);
1023 	strcpy((char *) data, curcie->cie_aug);
1024 	data += strlen(curcie->cie_aug) + 1;
1025 	memcpy((void *) data, (const void *) code_al, c_bytes);
1026 	data += c_bytes;
1027 	memcpy((void *) data, (const void *) data_al, d_bytes);
1028 	data += d_bytes;
1029 	db = curcie->cie_ret_reg;
1030 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
1031 			sizeof(db), sizeof(Dwarf_Ubyte));
1032 	data += sizeof(Dwarf_Ubyte);
1033 
1034 	if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
1035 	    memcpy((void *) data, (const void *) augmented_al, a_bytes);
1036 	    data += a_bytes;
1037 	}
1038 	memcpy((void *) data, (const void *) curcie->cie_inst,
1039 	       curcie->cie_inst_bytes);
1040 	data += curcie->cie_inst_bytes;
1041 	for (i = 0; i < pad; i++) {
1042 	    *data = DW_CFA_nop;
1043 	    data++;
1044 	}
1045 	curcie = curcie->cie_next;
1046     }
1047     /* calculate current offset */
1048     cur_off = cie_offs[cie_no - 2] + cie_length + uwordb_size
1049 	+ extension_size;
1050 
1051     /* write out fde's */
1052     curfde = dbg->de_frame_fdes;
1053     while (curfde) {
1054 	Dwarf_P_Frame_Pgm curinst;
1055 	long fde_length;
1056 	int pad;
1057 	Dwarf_P_Cie cie_ptr;
1058 	Dwarf_Word cie_index, index;
1059 	int oet_length, afl_length, res;
1060 	int v0_augmentation = 0;
1061 
1062 #if 0
1063 	unsigned char *fde_start_point;
1064 #endif
1065 
1066 	char afl_buff[ENCODE_SPACE_NEEDED];
1067 
1068 	/* Find the CIE associated with this fde. */
1069 	cie_ptr = dbg->de_frame_cies;
1070 	cie_index = curfde->fde_cie;
1071 	index = 1;		/* The cie_index of the first cie is 1,
1072 				   not 0. */
1073 	while (cie_ptr && index < cie_index) {
1074 	    cie_ptr = cie_ptr->cie_next;
1075 	    index++;
1076 	}
1077 	if (cie_ptr == NULL) {
1078 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1);
1079 	}
1080 
1081 	if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) {
1082 	    v0_augmentation = 1;
1083 	    oet_length = sizeof(Dwarf_sfixed);
1084 	    /* encode the length of augmented fields. */
1085 	    res = _dwarf_pro_encode_leb128_nm(oet_length,
1086 					      &afl_length, afl_buff,
1087 					      sizeof(afl_buff));
1088 	    if (res != DW_DLV_OK) {
1089 		DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
1090 	    }
1091 
1092 	    fde_length = curfde->fde_n_bytes + uwordb_size +	/* cie
1093 								   pointer
1094 								 */
1095 		upointer_size +	/* initial loc */
1096 		upointer_size +	/* address range */
1097 		afl_length +	/* augmented field length */
1098 		oet_length;	/* exception_table offset */
1099 	} else {
1100 	    fde_length = curfde->fde_n_bytes + uwordb_size +	/* cie
1101 								   pointer
1102 								 */
1103 		upointer_size +	/* initial loc */
1104 		upointer_size;	/* address range */
1105 	}
1106 
1107 	/* using fde offset, generate DW_AT_MIPS_fde attribute for the
1108 	   die corresponding to this fde */
1109 	if (_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off, error)
1110 	    < 0)
1111 	    return -1;
1112 
1113 	/* store relocation for cie pointer */
1114 	res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off + uwordb_size,	/* r_offset
1115 										 */
1116 				 dbg->de_sect_name_idx[DEBUG_FRAME],
1117 				 dwarf_drt_data_reloc, uwordb_size);
1118 	if (res != DW_DLV_OK) {
1119 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
1120 	}
1121 
1122 	/* store relocation information for initial location */
1123 	res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off + uwordb_size + upointer_size,	/* r_offset
1124 												 */
1125 				 curfde->fde_r_symidx,
1126 				 dwarf_drt_data_reloc, upointer_size);
1127 	if (res != DW_DLV_OK) {
1128 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
1129 	}
1130 	/* Store the relocation information for the
1131 	   offset_into_exception_info field, if the offset is valid (0
1132 	   is a valid offset). */
1133 	if (v0_augmentation &&
1134 	    curfde->fde_offset_into_exception_tables >= 0) {
1135 
1136 	    res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
1137 				     /* r_offset, where in cie this
1138 				        field starts */
1139 				     cur_off + 2 * uwordb_size +
1140 				     2 * upointer_size + afl_length,
1141 				     curfde->fde_exception_table_symbol,
1142 				     dwarf_drt_segment_rel,
1143 				     sizeof(Dwarf_sfixed));
1144 	    if (res != DW_DLV_OK) {
1145 		DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
1146 	    }
1147 	}
1148 
1149 	/* adjust for padding */
1150 	pad = (int) PADDING(fde_length, upointer_size);
1151 	fde_length += pad;
1152 
1153 
1154 	/* write out fde */
1155 	GET_CHUNK(dbg, elfsectno, data, fde_length + uwordb_size +
1156 		  extension_size, error);
1157 #if 0
1158 	fde_start_point = data;
1159 #endif
1160 	du = fde_length;
1161 	{
1162 	    if (extension_size) {
1163 		Dwarf_Word x = DISTINGUISHED_VALUE;
1164 
1165 		WRITE_UNALIGNED(dbg, (void *) data,
1166 				(const void *) &x,
1167 				sizeof(x), extension_size);
1168 		data += extension_size;
1169 	    }
1170 	    /* length */
1171 	    WRITE_UNALIGNED(dbg, (void *) data,
1172 			    (const void *) &du,
1173 			    sizeof(du), uwordb_size);
1174 	    data += uwordb_size;
1175 
1176 	    /* offset to cie */
1177 	    du = cie_offs[curfde->fde_cie - 1];
1178 	    WRITE_UNALIGNED(dbg, (void *) data,
1179 			    (const void *) &du,
1180 			    sizeof(du), uwordb_size);
1181 	    data += uwordb_size;
1182 
1183 	    du = curfde->fde_initloc;
1184 	    WRITE_UNALIGNED(dbg, (void *) data,
1185 			    (const void *) &du,
1186 			    sizeof(du), upointer_size);
1187 	    data += upointer_size;
1188 
1189 	    if (dbg->de_reloc_pair &&
1190 		curfde->fde_end_symbol != 0 &&
1191 		curfde->fde_addr_range == 0) {
1192 		/* symbolic reloc, need reloc for length What if we
1193 		   really know the length? If so, should use the other
1194 		   part of 'if'. */
1195 		Dwarf_Unsigned val;
1196 
1197 		res = dbg->de_reloc_pair(dbg,
1198 					 /* DEBUG_ARANGES, */
1199 					 DEBUG_FRAME, cur_off + 2 * uwordb_size + upointer_size,	/* r_offset
1200 													 */
1201 					 curfde->fde_r_symidx,
1202 					 curfde->fde_end_symbol,
1203 					 dwarf_drt_first_of_length_pair,
1204 					 upointer_size);
1205 		if (res != DW_DLV_OK) {
1206 		    {
1207 			_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
1208 			return (0);
1209 		    }
1210 		}
1211 
1212 		/* arrange pre-calc so assem text can do .word end -
1213 		   begin + val (gets val from stream) */
1214 		val = curfde->fde_end_symbol_offset -
1215 		    curfde->fde_initloc;
1216 		WRITE_UNALIGNED(dbg, data,
1217 				(const void *) &val,
1218 				sizeof(val), upointer_size);
1219 		data += upointer_size;
1220 	    } else {
1221 
1222 		du = curfde->fde_addr_range;
1223 		WRITE_UNALIGNED(dbg, (void *) data,
1224 				(const void *) &du,
1225 				sizeof(du), upointer_size);
1226 		data += upointer_size;
1227 	    }
1228 	}
1229 
1230 	if (v0_augmentation) {
1231 	    /* write the encoded augmented field length. */
1232 	    memcpy((void *) data, (const void *) afl_buff, afl_length);
1233 	    data += afl_length;
1234 	    /* write the offset_into_exception_tables field. */
1235 	    dsw =
1236 		(Dwarf_sfixed) curfde->fde_offset_into_exception_tables;
1237 	    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw,
1238 			    sizeof(dsw), sizeof(Dwarf_sfixed));
1239 	    data += sizeof(Dwarf_sfixed);
1240 	}
1241 
1242 	curinst = curfde->fde_inst;
1243 	while (curinst) {
1244 	    db = curinst->dfp_opcode;
1245 	    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
1246 			    sizeof(db), sizeof(Dwarf_Ubyte));
1247 	    data += sizeof(Dwarf_Ubyte);
1248 #if 0
1249 	    if (curinst->dfp_sym_index) {
1250 		int res;
1251 
1252 		res = dbg->de_reloc_name(dbg,
1253 					 DEBUG_FRAME,
1254 					 (data - fde_start_point)
1255 					 + cur_off + uwordb_size,	/* r_offset
1256 									 */
1257 					 curinst->dfp_sym_index,
1258 					 dwarf_drt_data_reloc,
1259 					 upointer_size);
1260 		if (res != DW_DLV_OK) {
1261 		    {
1262 			_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
1263 			return (0);
1264 		    }
1265 		}
1266 	    }
1267 #endif
1268 	    memcpy((void *) data,
1269 		   (const void *) curinst->dfp_args,
1270 		   curinst->dfp_nbytes);
1271 	    data += curinst->dfp_nbytes;
1272 	    curinst = curinst->dfp_next;
1273 	}
1274 	/* padding */
1275 	for (i = 0; i < pad; i++) {
1276 	    *data = DW_CFA_nop;
1277 	    data++;
1278 	}
1279 	cur_off += fde_length + uwordb_size;
1280 	curfde = curfde->fde_next;
1281     }
1282 
1283 
1284     return (int) dbg->de_n_debug_sect;
1285 }
1286 
1287 
1288 
1289 /*---------------------------------------------------------------
1290 	Generate debug_info and debug_abbrev sections
1291 ---------------------------------------------------------------*/
1292 static int
1293 _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error)
1294 {
1295     int elfsectno_of_debug_info;
1296     int abbrevsectno;
1297     unsigned char *data;
1298     int cu_header_size;
1299     Dwarf_P_Abbrev curabbrev, abbrev_head, abbrev_tail;
1300     Dwarf_P_Die curdie;
1301     Dwarf_P_Die first_child;
1302     Dwarf_Word dw;
1303     Dwarf_Unsigned du;
1304     Dwarf_Half dh;
1305     Dwarf_Ubyte db;
1306     Dwarf_Half version;		/* need 2 byte quantity */
1307     Dwarf_Unsigned die_off;	/* offset of die in debug_info */
1308     int n_abbrevs;
1309     int res;
1310 
1311     Dwarf_Small *start_info_sec;
1312 
1313     int uword_size = dbg->de_offset_size;
1314     int extension_size = dbg->de_64bit_extension ? 4 : 0;
1315 
1316     abbrev_head = abbrev_tail = NULL;
1317     elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
1318 
1319     /* write cu header */
1320     cu_header_size = extension_size + uword_size +	/* length of
1321 							   info section
1322 							 */
1323 	sizeof(Dwarf_Half) +	/* version stamp */
1324 	uword_size +		/* offset into abbrev table */
1325 	sizeof(Dwarf_Ubyte);	/* size of target address */
1326     GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size,
1327 	      error);
1328     start_info_sec = data;
1329     if (extension_size) {
1330 	du = DISTINGUISHED_VALUE;
1331 	WRITE_UNALIGNED(dbg, (void *) data,
1332 			(const void *) &du, sizeof(du), extension_size);
1333 	data += extension_size;
1334     }
1335     du = 0;			/* length of debug_info, not counting
1336 				   this field itself (unknown at this
1337 				   point). */
1338     WRITE_UNALIGNED(dbg, (void *) data,
1339 		    (const void *) &du, sizeof(du), uword_size);
1340     data += uword_size;
1341 
1342     version = CURRENT_VERSION_STAMP;	/* assume this length will not
1343 					   change */
1344     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version,
1345 		    sizeof(version), sizeof(Dwarf_Half));
1346     data += sizeof(Dwarf_Half);
1347 
1348     du = 0;			/* offset into abbrev table, not yet
1349 				   known. */
1350     WRITE_UNALIGNED(dbg, (void *) data,
1351 		    (const void *) &du, sizeof(du), uword_size);
1352     data += uword_size;
1353 
1354 
1355     db = dbg->de_pointer_size;
1356 
1357     WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
1358 		    sizeof(db), 1);
1359 
1360     /* We have filled the chunk we got with GET_CHUNK. At this point we
1361        no longer dare use "data" or "start_info_sec" as a pointer any
1362        longer except to refer to that first small chunk for the cu
1363        header. */
1364 
1365     curdie = dbg->de_dies;
1366 
1367     /* create AT_macro_info if appropriate */
1368     if (dbg->de_first_macinfo != NULL) {
1369 	if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0)
1370 	    return -1;
1371     }
1372 
1373     /* create AT_stmt_list attribute if necessary */
1374     if (dwarf_need_debug_line_section(dbg) == TRUE)
1375 	if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0)
1376 	    return -1;
1377 
1378     die_off = cu_header_size;
1379 
1380     /*
1381        Relocation for abbrev offset in cu header store relocation
1382        record in linked list */
1383     res = dbg->de_reloc_name(dbg, DEBUG_INFO, extension_size + uword_size + sizeof(Dwarf_Half),	/* r_offset
1384 												 */
1385 			     dbg->de_sect_name_idx[DEBUG_ABBREV],
1386 			     dwarf_drt_data_reloc, uword_size);
1387     if (res != DW_DLV_OK) {
1388 	DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
1389     }
1390 
1391     /* pass 0: only top level dies, add at_sibling attribute to those
1392        dies with children */
1393     first_child = curdie->di_child;
1394     while (first_child && first_child->di_right) {
1395 	if (first_child->di_child)
1396 	    dwarf_add_AT_reference(dbg,
1397 				   first_child,
1398 				   DW_AT_sibling,
1399 				   first_child->di_right, error);
1400 	first_child = first_child->di_right;
1401     }
1402 
1403     /* pass 1: create abbrev info, get die offsets, calc relocations */
1404     while (curdie != NULL) {
1405 	int nbytes;
1406 	Dwarf_P_Attribute curattr;
1407 	char *space;
1408 	int res;
1409 	char buff1[ENCODE_SPACE_NEEDED];
1410 
1411 	curdie->di_offset = die_off;
1412 	curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head);
1413 	if (curabbrev == NULL) {
1414 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1415 	}
1416 	if (abbrev_head == NULL) {
1417 	    n_abbrevs = 1;
1418 	    curabbrev->abb_idx = n_abbrevs;
1419 	    abbrev_tail = abbrev_head = curabbrev;
1420 	} else {
1421 	    /* check if its a new abbreviation, if yes, add to tail */
1422 	    if (curabbrev->abb_idx == 0) {
1423 		n_abbrevs++;
1424 		curabbrev->abb_idx = n_abbrevs;
1425 		abbrev_tail->abb_next = curabbrev;
1426 		abbrev_tail = curabbrev;
1427 	    }
1428 	}
1429 	res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx,
1430 					  &nbytes,
1431 					  buff1, sizeof(buff1));
1432 	if (res != DW_DLV_OK) {
1433 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1434 	}
1435 	space = _dwarf_p_get_alloc(dbg, nbytes);
1436 	if (space == NULL) {
1437 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1438 	}
1439 	memcpy(space, buff1, nbytes);
1440 	curdie->di_abbrev = space;
1441 	curdie->di_abbrev_nbytes = nbytes;
1442 	die_off += nbytes;
1443 	curattr = curdie->di_attrs;
1444 	while (curattr) {
1445 	    if (curattr->ar_rel_type != R_MIPS_NONE) {
1446 		switch (curattr->ar_attribute) {
1447 		case DW_AT_stmt_list:
1448 		    curattr->ar_rel_symidx =
1449 			dbg->de_sect_name_idx[DEBUG_LINE];
1450 		    break;
1451 		case DW_AT_MIPS_fde:
1452 		    curattr->ar_rel_symidx =
1453 			dbg->de_sect_name_idx[DEBUG_FRAME];
1454 		    break;
1455 		case DW_AT_macro_info:
1456 		    curattr->ar_rel_symidx =
1457 			dbg->de_sect_name_idx[DEBUG_MACINFO];
1458 		    break;
1459 		default:
1460 		    break;
1461 		}
1462 		res = dbg->de_reloc_name(dbg, DEBUG_INFO, die_off + curattr->ar_rel_offset,	/* r_offset
1463 												 */
1464 					 curattr->ar_rel_symidx,
1465 					 dwarf_drt_data_reloc,
1466 					 curattr->ar_reloc_len);
1467 
1468 		if (res != DW_DLV_OK) {
1469 		    DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
1470 		}
1471 
1472 	    }
1473 	    die_off += curattr->ar_nbytes;
1474 	    curattr = curattr->ar_next;
1475 	}
1476 	/* depth first search */
1477 	if (curdie->di_child)
1478 	    curdie = curdie->di_child;
1479 	else {
1480 	    while (curdie != NULL && curdie->di_right == NULL) {
1481 		curdie = curdie->di_parent;
1482 		die_off++;	/* since we are writing a null die at
1483 				   the end of each sibling chain */
1484 	    }
1485 	    if (curdie != NULL)
1486 		curdie = curdie->di_right;
1487 	}
1488     }
1489 
1490     /* Pass 2: Write out the die information Here 'data' is a
1491        temporary, one block for each GET_CHUNK.  'data' is overused. */
1492     curdie = dbg->de_dies;
1493     while (curdie != NULL) {
1494 	Dwarf_P_Attribute curattr;
1495 
1496 	/* index to abbreviation table */
1497 	GET_CHUNK(dbg, elfsectno_of_debug_info,
1498 		  data, curdie->di_abbrev_nbytes, error);
1499 
1500 	memcpy((void *) data,
1501 	       (const void *) curdie->di_abbrev,
1502 	       curdie->di_abbrev_nbytes);
1503 
1504 	/* Attribute values - need to fill in all form attributes */
1505 	curattr = curdie->di_attrs;
1506 	while (curattr) {
1507 	    GET_CHUNK(dbg, elfsectno_of_debug_info, data,
1508 		      (unsigned long) curattr->ar_nbytes, error);
1509 	    switch (curattr->ar_attribute_form) {
1510 	    case DW_FORM_ref1:
1511 		{
1512 		    if (curattr->ar_ref_die->di_offset >
1513 			(unsigned) 0xff) {
1514 			DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
1515 		    }
1516 		    db = curattr->ar_ref_die->di_offset;
1517 		    WRITE_UNALIGNED(dbg, (void *) data,
1518 				    (const void *) &db,
1519 				    sizeof(db), sizeof(Dwarf_Ubyte));
1520 		    break;
1521 		}
1522 	    case DW_FORM_ref2:
1523 		{
1524 		    if (curattr->ar_ref_die->di_offset >
1525 			(unsigned) 0xffff) {
1526 			DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
1527 		    }
1528 		    dh = curattr->ar_ref_die->di_offset;
1529 		    WRITE_UNALIGNED(dbg, (void *) data,
1530 				    (const void *) &dh,
1531 				    sizeof(dh), sizeof(Dwarf_Half));
1532 		    break;
1533 		}
1534 	    case DW_FORM_ref_addr:
1535 		{
1536 		    du = curattr->ar_ref_die->di_offset;
1537 		    {
1538 			/* ref to offset of die */
1539 			WRITE_UNALIGNED(dbg, (void *) data,
1540 					(const void *) &du,
1541 					sizeof(du), uword_size);
1542 		    }
1543 		    break;
1544 
1545 		}
1546 	    case DW_FORM_ref4:
1547 		{
1548 		    if (curattr->ar_ref_die->di_offset >
1549 			(unsigned) 0xffffffff) {
1550 			DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
1551 		    }
1552 		    dw = (Dwarf_Word) curattr->ar_ref_die->di_offset;
1553 		    WRITE_UNALIGNED(dbg, (void *) data,
1554 				    (const void *) &dw,
1555 				    sizeof(dw), sizeof(Dwarf_ufixed));
1556 		    break;
1557 		}
1558 	    case DW_FORM_ref8:
1559 		du = curattr->ar_ref_die->di_offset;
1560 		WRITE_UNALIGNED(dbg, (void *) data,
1561 				(const void *) &du,
1562 				sizeof(du), sizeof(Dwarf_Unsigned));
1563 		break;
1564 	    case DW_FORM_ref_udata:
1565 		{		/* unsigned leb128 offset */
1566 
1567 		    int nbytes;
1568 		    char buff1[ENCODE_SPACE_NEEDED];
1569 
1570 		    res =
1571 			_dwarf_pro_encode_leb128_nm(curattr->
1572 						    ar_ref_die->
1573 						    di_offset, &nbytes,
1574 						    buff1,
1575 						    sizeof(buff1));
1576 		    if (res != DW_DLV_OK) {
1577 			DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1578 		    }
1579 
1580 		    memcpy(data, buff1, nbytes);
1581 		    break;
1582 		}
1583 	    default:
1584 		memcpy((void *) data,
1585 		       (const void *) curattr->ar_data,
1586 		       curattr->ar_nbytes);
1587 		break;
1588 	    }
1589 	    curattr = curattr->ar_next;
1590 	}
1591 
1592 	/* depth first search */
1593 	if (curdie->di_child)
1594 	    curdie = curdie->di_child;
1595 	else {
1596 	    while (curdie != NULL && curdie->di_right == NULL) {
1597 		GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error);
1598 		*data = '\0';
1599 		curdie = curdie->di_parent;
1600 	    }
1601 	    if (curdie != NULL)
1602 		curdie = curdie->di_right;
1603 	}
1604     }
1605 
1606     /* Write out debug_info size */
1607     /* Dont include length field or extension bytes */
1608     du = die_off - uword_size - extension_size;
1609     WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size),
1610 		    (const void *) &du, sizeof(du), uword_size);
1611 
1612 
1613     data = 0;			/* Emphasise not usable now */
1614 
1615     /* Write out debug_abbrev section */
1616     abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV];
1617 
1618     curabbrev = abbrev_head;
1619     while (curabbrev) {
1620 	char *val;
1621 	int nbytes;
1622 	int idx;
1623 	int res;
1624 	char buff1[ENCODE_SPACE_NEEDED];
1625 
1626 	res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, &nbytes,
1627 					  buff1, sizeof(buff1));
1628 	if (res != DW_DLV_OK) {
1629 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1630 	}
1631 
1632 	GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
1633 	val = buff1;
1634 	memcpy((void *) data, (const void *) val, nbytes);
1635 	res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_tag, &nbytes,
1636 					  buff1, sizeof(buff1));
1637 	if (res != DW_DLV_OK) {
1638 	    DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1639 	}
1640 	val = buff1;
1641 	GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
1642 	memcpy((void *) data, (const void *) val, nbytes);
1643 	db = curabbrev->abb_children;
1644 	GET_CHUNK(dbg, abbrevsectno, data, sizeof(Dwarf_Ubyte), error);
1645 	WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
1646 			sizeof(db), sizeof(Dwarf_Ubyte));
1647 
1648 	/* add attributes and forms */
1649 	for (idx = 0; idx < curabbrev->abb_n_attr; idx++) {
1650 	    res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_attrs[idx],
1651 					      &nbytes,
1652 					      buff1, sizeof(buff1));
1653 	    if (res != DW_DLV_OK) {
1654 		DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1655 	    }
1656 	    val = buff1;
1657 	    GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
1658 	    memcpy((void *) data, (const void *) val, nbytes);
1659 	    res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_forms[idx],
1660 					      &nbytes,
1661 					      buff1, sizeof(buff1));
1662 	    if (res != DW_DLV_OK) {
1663 		DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
1664 	    }
1665 	    val = buff1;
1666 	    GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
1667 	    memcpy((void *) data, (const void *) val, nbytes);
1668 	}
1669 	GET_CHUNK(dbg, abbrevsectno, data, 2, error);	/* two zeros,
1670 			for last
1671 			entry, see dwarf2 sec 7.5.3 */
1672 	*data = 0;
1673 	data++;
1674 	*data = 0;
1675 
1676 	curabbrev = curabbrev->abb_next;
1677     }
1678 
1679     GET_CHUNK(dbg,abbrevsectno,data,1,error);       /* one zero,
1680                         for end of cu, see dwarf2 sec 7.5.3 */
1681     *data = 0;
1682 
1683 
1684     return (int) dbg->de_n_debug_sect;
1685 }
1686 
1687 
1688 /*---------------------------------------------------------------------
1689 	Get a buffer of section data.
1690 	section_idx is the elf-section number that this data applies to.
1691 	length shows length of returned data
1692 ----------------------------------------------------------------------*/
1693  /*ARGSUSED*/			/* pretend all args used */
1694     Dwarf_Ptr
1695 dwarf_get_section_bytes(Dwarf_P_Debug dbg,
1696 			Dwarf_Signed dwarf_section,
1697 			Dwarf_Signed * section_idx,
1698 			Dwarf_Unsigned * length, Dwarf_Error * error)
1699 {
1700     Dwarf_Ptr buf;
1701 
1702     if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
1703 	DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL);
1704     }
1705 
1706     if (dbg->de_debug_sects == 0) {
1707 	/* no more data !! */
1708 	return NULL;
1709     }
1710     if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
1711 	/* no data ever entered !! */
1712 	return NULL;
1713     }
1714     *section_idx = dbg->de_debug_sects->ds_elf_sect_no;
1715     *length = dbg->de_debug_sects->ds_nbytes;
1716 
1717     buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data;
1718 
1719     dbg->de_debug_sects = dbg->de_debug_sects->ds_next;
1720 
1721     /* We may want to call the section stuff more than once: see
1722        dwarf_reset_section_bytes() do not do: dbg->de_n_debug_sect--; */
1723 
1724     return buf;
1725 }
1726 
1727 /*
1728 	No errors possible.
1729 */
1730 void
1731 dwarf_reset_section_bytes(Dwarf_P_Debug dbg)
1732 {
1733     dbg->de_debug_sects = dbg->de_first_debug_sect;
1734     /* No need to reset; commented out decrement. dbg->de_n_debug_sect
1735        = ???; */
1736     dbg->de_reloc_next_to_return = 0;
1737 }
1738 
1739 /*
1740     Storage handler. Gets either a new chunk of memory, or
1741     a pointer in existing memory, from the linked list attached
1742     to dbg at de_debug_sects, depending on size of nbytes
1743 
1744     Assume dbg not null, checked in top level routine
1745 
1746     Returns a pointer to the allocated buffer space for the
1747     lib to fill in,  predincrements next-to-use count so the
1748     space requested is already counted 'used'
1749     when this returns (ie, reserved).
1750 
1751 */
1752 Dwarf_Small *
1753 _dwarf_pro_buffer(Dwarf_P_Debug dbg,
1754 		  int elfsectno, unsigned long nbytes)
1755 {
1756     Dwarf_P_Section_Data cursect;
1757 
1758 
1759     cursect = dbg->de_current_active_section;
1760     /* By using MAGIC_SECT_NO we allow the following MAGIC_SECT_NO must
1761        not match any legit section number. test to have just two
1762        clauses (no NULL pointer test) See dwarf_producer_init(). */
1763     if ((cursect->ds_elf_sect_no != elfsectno) ||
1764 	((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc)
1765 	) {
1766 
1767 	/* Either the elf section has changed or there is not enough
1768 	   space in the current section.
1769 
1770 	   Create a new Dwarf_P_Section_Data_s for the chunk. and have
1771 	   space 'on the end' for the buffer itself so we just do one
1772 	   malloc (not two).
1773 
1774 	 */
1775 	unsigned long space = nbytes;
1776 
1777 	if (nbytes < CHUNK_SIZE)
1778 	    space = CHUNK_SIZE;
1779 
1780 	cursect = (Dwarf_P_Section_Data)
1781 	    _dwarf_p_get_alloc(dbg,
1782 			       sizeof(struct Dwarf_P_Section_Data_s)
1783 			       + space);
1784 
1785 
1786 	if (cursect == NULL)
1787 	    return (NULL);
1788 
1789 	/* _dwarf_p_get_alloc zeroes the space... */
1790 
1791 	cursect->ds_data = (char *) cursect +
1792 	    sizeof(struct Dwarf_P_Section_Data_s);
1793 	cursect->ds_orig_alloc = space;
1794 	cursect->ds_elf_sect_no = elfsectno;
1795 	cursect->ds_nbytes = nbytes;	/* reserve this number of bytes
1796 					   of space for caller to fill
1797 					   in */
1798 
1799 	/* Now link on the end of the list, and mark this one as the
1800 	   current one */
1801 
1802 	if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
1803 	    /* the only entry is the special one for 'no entry' so
1804 	       delete that phony one while adding this initial real
1805 	       one. */
1806 	    dbg->de_debug_sects = cursect;
1807 	    dbg->de_current_active_section = cursect;
1808 	    dbg->de_first_debug_sect = cursect;
1809 	} else {
1810 	    dbg->de_current_active_section->ds_next = cursect;
1811 	    dbg->de_current_active_section = cursect;
1812 	}
1813 	dbg->de_n_debug_sect++;
1814 
1815 	return ((Dwarf_Small *) cursect->ds_data);
1816     }
1817 
1818     /* There is enough space in the current buffer */
1819     {
1820 	Dwarf_Small *space_for_caller = (Dwarf_Small *)
1821 	    (cursect->ds_data + cursect->ds_nbytes);
1822 
1823 	cursect->ds_nbytes += nbytes;
1824 	return space_for_caller;
1825     }
1826 }
1827 
1828 
1829 /*------------------------------------------------------------
1830 	Given address advance and line advance, it gives
1831 	either special opcode, or a number < 0
1832 ------------------------------------------------------------*/
1833 static int
1834 _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv)
1835 {
1836     int opc;
1837 
1838     addr_adv = addr_adv / MIN_INST_LENGTH;
1839     if (line_adv == 0 && addr_adv == 0)
1840 	return OPC_INCS_ZERO;
1841     if (line_adv >= LINE_BASE && line_adv < LINE_BASE + LINE_RANGE) {
1842 	opc =
1843 	    (line_adv - LINE_BASE) + (addr_adv * LINE_RANGE) +
1844 	    OPCODE_BASE;
1845 	if (opc > 255)
1846 	    return OPC_OUT_OF_RANGE;
1847 	return opc;
1848     } else
1849 	return LINE_OUT_OF_RANGE;
1850 }
1851 
1852 /*-----------------------------------------------------------------------
1853 	Handles abbreviations. It takes a die, searches through
1854 	current list of abbreviations for matching one. If it
1855 	finds one, it returns a pointer to it, and if it doesnt,
1856 	it returns a new one. Upto the user of this function to
1857 	link it up to the abbreviation head. If its a new one,
1858 	abb_idx has 0.
1859 -----------------------------------------------------------------------*/
1860 static Dwarf_P_Abbrev
1861 _dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head)
1862 {
1863     Dwarf_P_Abbrev curabbrev;
1864     Dwarf_P_Attribute curattr;
1865     int res1;
1866     int nattrs;
1867     int match;
1868     Dwarf_ufixed *forms = 0;
1869     Dwarf_ufixed *attrs = 0;
1870 
1871     curabbrev = head;
1872     while (curabbrev) {
1873 	if ((die->di_tag == curabbrev->abb_tag) &&
1874 	    ((die->di_child != NULL &&
1875 	      curabbrev->abb_children == DW_CHILDREN_yes) ||
1876 	     (die->di_child == NULL &&
1877 	      curabbrev->abb_children == DW_CHILDREN_no)) &&
1878 	    (die->di_n_attr == curabbrev->abb_n_attr)) {
1879 
1880 	    /* There is a chance of a match. */
1881 	    curattr = die->di_attrs;
1882 	    match = 1;		/* Assume match found. */
1883 	    while (match && curattr) {
1884 		res1 = _dwarf_pro_match_attr(curattr,
1885 					     curabbrev,
1886 					     (int) curabbrev->
1887 					     abb_n_attr);
1888 		if (res1 == 0)
1889 		    match = 0;
1890 		curattr = curattr->ar_next;
1891 	    }
1892 	    if (match == 1)
1893 		return curabbrev;
1894 	}
1895 	curabbrev = curabbrev->abb_next;
1896     }
1897 
1898     /* no match, create new abbreviation */
1899     if (die->di_n_attr != 0) {
1900 	forms = (Dwarf_ufixed *)
1901 	    _dwarf_p_get_alloc(NULL,
1902 			       sizeof(Dwarf_ufixed) * die->di_n_attr);
1903 	if (forms == NULL)
1904 	    return NULL;
1905 	attrs = (Dwarf_ufixed *)
1906 	    _dwarf_p_get_alloc(NULL,
1907 			       sizeof(Dwarf_ufixed) * die->di_n_attr);
1908 	if (attrs == NULL)
1909 	    return NULL;
1910     }
1911     nattrs = 0;
1912     curattr = die->di_attrs;
1913     while (curattr) {
1914 	attrs[nattrs] = curattr->ar_attribute;
1915 	forms[nattrs] = curattr->ar_attribute_form;
1916 	nattrs++;
1917 	curattr = curattr->ar_next;
1918     }
1919 
1920     curabbrev = (Dwarf_P_Abbrev)
1921 	_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Abbrev_s));
1922     if (curabbrev == NULL)
1923 	return NULL;
1924 
1925     if (die->di_child == NULL)
1926 	curabbrev->abb_children = DW_CHILDREN_no;
1927     else
1928 	curabbrev->abb_children = DW_CHILDREN_yes;
1929     curabbrev->abb_tag = die->di_tag;
1930     curabbrev->abb_attrs = attrs;
1931     curabbrev->abb_forms = forms;
1932     curabbrev->abb_n_attr = die->di_n_attr;
1933     curabbrev->abb_idx = 0;
1934     curabbrev->abb_next = NULL;
1935 
1936     return curabbrev;
1937 }
1938 
1939 /*------------------------------------------------------------------
1940 	Tries to see if given attribute and form combination
1941 	exists in the given abbreviation
1942 -------------------------------------------------------------------*/
1943 static int
1944 _dwarf_pro_match_attr(Dwarf_P_Attribute attr,
1945 		      Dwarf_P_Abbrev abbrev, int no_attr)
1946 {
1947     int i;
1948     int found = 0;
1949 
1950     for (i = 0; i < no_attr; i++) {
1951 	if (attr->ar_attribute == abbrev->abb_attrs[i] &&
1952 	    attr->ar_attribute_form == abbrev->abb_forms[i]) {
1953 	    found = 1;
1954 	    break;
1955 	}
1956     }
1957     return found;
1958 }
1959