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