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