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
76and sectnames (below).  REL_SEC_PREFIX is either ".rel" or ".rela"
77see pro_incl.h
78*/
79char *_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*/
99char *_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
118static 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
135typedef struct Dwarf_P_Rel_s *Dwarf_P_Rel;
136struct Dwarf_P_Rel_s {
137    Dwarf_P_Rel dr_next;
138    void *dr_rel_datap;
139};
140typedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head;
141struct Dwarf_P_Rel_Head_s {
142    struct Dwarf_P_Rel_s *drh_head;
143    struct Dwarf_P_Rel_s *drh_tail;
144};
145
146static int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
147                                         Dwarf_Error * error);
148static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
149                                          Dwarf_Error * error);
150static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
151                                         Dwarf_Error * error);
152static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev);
153static 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
160static 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*/
181static int
182dwarf_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*/
196Dwarf_Signed
197dwarf_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---------------------------------------------------------------*/
441static 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---------------------------------------------------------------*/
889static 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
1314static int
1315marker_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
1331static int
1332marker_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
1346Dwarf_Signed
1347dwarf_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 */
1370static int
1371string_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
1392static int
1393string_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
1409int
1410dwarf_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
1430int
1431dwarf_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---------------------------------------------------------------*/
1458static 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
1957dwarf_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*/
1992void
1993dwarf_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*/
2015Dwarf_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------------------------------------------------------------*/
2096static 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-----------------------------------------------------------------------*/
2123static 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-------------------------------------------------------------------*/
2206static 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