1/*
2
3  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
4  Portions Copyright 2011-2017  David Anderson. All Rights Reserved.
5  Portions Copyright 2012 SN Systems Ltd. All rights reserved.
6
7  This program is free software; you can redistribute it
8  and/or modify it under the terms of version 2.1 of the
9  GNU Lesser General Public License as published by the Free
10  Software Foundation.
11
12  This program is distributed in the hope that it would be
13  useful, but WITHOUT ANY WARRANTY; without even the implied
14  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE.
16
17  Further, this software is distributed without any warranty
18  that it is free of the rightful claim of any third person
19  regarding infringement or the like.  Any license provided
20  herein, whether implied or otherwise, applies only to this
21  software file.  Patent licenses, if any, provided herein
22  do not apply to combinations of this program with other
23  software, or any other product whatsoever.
24
25  You should have received a copy of the GNU Lesser General
26  Public License along with this program; if not, write the
27  Free Software Foundation, Inc., 51 Franklin Street - Fifth
28  Floor, Boston MA 02110-1301, USA.
29
30*/
31
32#include "config.h"
33#include "libdwarfdefs.h"
34#include <stdio.h>
35#include <string.h>
36#include <limits.h>
37#include "pro_incl.h"
38#include <stddef.h>
39#include "dwarf.h"
40#include "libdwarf.h"
41#include "pro_opaque.h"
42#include "pro_error.h"
43#include "pro_alloc.h"
44#include "pro_encode_nm.h"
45#include "pro_frame.h"
46
47#define SIZEOFT16 2
48#define SIZEOFT32 4
49#define SIZEOFT64 8
50
51#ifdef WORDS_BIGENDIAN
52#define ASNOUT(t,s,l)                       \
53    do {                                    \
54        unsigned sbyte = 0;                 \
55        const char *p = 0;                        \
56        if (l > sizeof(s)) {                \
57            _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
58            return DW_DLV_ERROR;            \
59        }                                   \
60        sbyte = sizeof(s) - l;              \
61        p = (const char *)(&s);             \
62        dbg->de_copy_word(t,(const void *)(p+sbyte),l);\
63    } while (0)
64#else /* LITTLEENDIAN */
65#define ASNOUT(t,s,l)                       \
66    do {                                    \
67        const char *p = 0;                  \
68        if (l > sizeof(s)) {                \
69            _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
70            return DW_DLV_ERROR;            \
71        }                                   \
72        p = (const char *)(&s);             \
73        dbg->de_copy_word(t,(const void *)p,l);  \
74    } while (0)
75#endif /* ENDIANNESS */
76
77
78static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
79    Dwarf_P_Frame_Pgm inst);
80
81/*  This function adds a cie struct to the debug pointer. Its in the
82    form of a linked list.
83    augmenter: string reps augmentation (implementation defined)
84    code_align: alignment of code
85    data_align: alignment of data
86    init_bytes: byts having initial instructions
87    init_n_bytes: number of bytes of initial instructions */
88
89
90Dwarf_Unsigned
91dwarf_add_frame_cie(Dwarf_P_Debug dbg,
92    char *augmenter,
93    Dwarf_Small code_align,
94    Dwarf_Small data_align,
95    Dwarf_Small return_reg,
96    Dwarf_Ptr init_bytes,
97    Dwarf_Unsigned init_n_bytes,
98    Dwarf_Error * error)
99{
100    Dwarf_Unsigned index = 0;
101    int res = 0;
102
103    res = dwarf_add_frame_cie_a(dbg,augmenter, code_align,
104        data_align,return_reg,init_bytes,
105        init_n_bytes,
106        &index,error);
107    if (res != DW_DLV_OK) {
108        return DW_DLV_NOCOUNT;
109    }
110    return index;
111}
112
113
114int
115dwarf_add_frame_cie_a(Dwarf_P_Debug dbg,
116    char *augmenter,
117    Dwarf_Small code_align,
118    Dwarf_Small data_align,
119    Dwarf_Small return_reg,
120    Dwarf_Ptr init_bytes,
121    Dwarf_Unsigned init_n_bytes,
122    Dwarf_Unsigned * cie_index_out,
123    Dwarf_Error * error)
124{
125    Dwarf_P_Cie curcie;
126    char *tmpaug = 0;
127
128    if (dbg->de_frame_cies == NULL) {
129        dbg->de_frame_cies = (Dwarf_P_Cie)
130            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
131        if (dbg->de_frame_cies == NULL) {
132            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
133        }
134        curcie = dbg->de_frame_cies;
135        dbg->de_n_cie = 1;
136        dbg->de_last_cie = curcie;
137    } else {
138        curcie = dbg->de_last_cie;
139        curcie->cie_next = (Dwarf_P_Cie)
140            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
141        if (curcie->cie_next == NULL) {
142            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
143        }
144        curcie = curcie->cie_next;
145        dbg->de_n_cie++;
146        dbg->de_last_cie = curcie;
147    }
148    curcie->cie_version = 1;
149    if (dbg->de_output_version > 2) {
150        curcie->cie_version = dbg->de_output_version;
151    } else {
152        /*  V2 dwarf has debug_frame as version 1, there
153            is no 2 used in this section. */
154        curcie->cie_version = 1;
155    }
156    tmpaug = (char *)_dwarf_p_get_alloc(dbg,strlen(augmenter)+1);
157    if (!tmpaug) {
158        DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
159    }
160    strcpy(tmpaug,augmenter);
161    curcie->cie_aug = tmpaug;
162    curcie->cie_code_align = code_align;
163    curcie->cie_data_align = data_align;
164    curcie->cie_ret_reg = return_reg;
165    curcie->cie_inst = (char *) init_bytes;
166    curcie->cie_inst_bytes = (long) init_n_bytes;
167    curcie->cie_next = NULL;
168    *cie_index_out =  dbg->de_n_cie;
169    return DW_DLV_OK;
170}
171
172
173/*  This functions adds a fde struct to the debug pointer. Its in the
174    form of a linked list.
175    die: subprogram/function die corresponding to this fde
176    cie: cie referred to by this fde, obtained from call to
177        add_frame_cie() routine.
178    virt_addr: beginning address
179    code_len: length of code reps by the fde */
180/*ARGSUSED*/                   /* pretend all args used */
181Dwarf_Unsigned
182dwarf_add_frame_fde(Dwarf_P_Debug dbg,
183    Dwarf_P_Fde fde,
184    Dwarf_P_Die die,
185    Dwarf_Unsigned cie,
186    Dwarf_Unsigned virt_addr,
187    Dwarf_Unsigned code_len,
188    Dwarf_Unsigned symidx, Dwarf_Error * error)
189{
190    Dwarf_Unsigned index = 0;
191    int res = 0;
192
193    res = dwarf_add_frame_fde_c(dbg, fde, die, cie, virt_addr,
194        code_len, symidx, 0, 0,&index, error);
195    if (res != DW_DLV_OK) {
196        return DW_DLV_NOCOUNT;
197    }
198    return index;
199}
200
201/*  There is no dwarf_add_frame_fde_a */
202/*ARGSUSED10*/
203Dwarf_Unsigned
204dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
205    Dwarf_P_Fde fde,
206    Dwarf_P_Die die,
207    Dwarf_Unsigned cie,
208    Dwarf_Unsigned virt_addr,
209    Dwarf_Unsigned code_len,
210    Dwarf_Unsigned symidx,
211    Dwarf_Unsigned symidx_of_end,
212    Dwarf_Addr offset_from_end_sym,
213    Dwarf_Error * error)
214{
215    Dwarf_Unsigned index = 0;
216    int res = 0;
217
218    res = dwarf_add_frame_fde_c(dbg,fde,die,cie,
219        virt_addr,code_len,symidx,symidx_of_end,
220        offset_from_end_sym,&index,error);
221    if (res != DW_DLV_OK) {
222        return DW_DLV_NOCOUNT;
223    }
224    return index;
225}
226
227/*  New December 2018 */
228int
229dwarf_add_frame_fde_c(Dwarf_P_Debug dbg,
230    Dwarf_P_Fde fde,
231    Dwarf_P_Die die,
232    Dwarf_Unsigned cie,
233    Dwarf_Unsigned virt_addr,
234    Dwarf_Unsigned code_len,
235    Dwarf_Unsigned symidx,
236    Dwarf_Unsigned symidx_of_end,
237    Dwarf_Addr offset_from_end_sym,
238    Dwarf_Unsigned *index_to_fde,
239    UNUSEDARG Dwarf_Error * error)
240{
241    Dwarf_P_Fde curfde;
242
243    fde->fde_die = die;
244    fde->fde_cie = (long) cie;
245    fde->fde_initloc = virt_addr;
246    fde->fde_r_symidx = symidx;
247    fde->fde_addr_range = code_len;
248    fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
249    fde->fde_exception_table_symbol = 0;
250    fde->fde_end_symbol_offset = offset_from_end_sym;
251    fde->fde_end_symbol = symidx_of_end;
252    fde->fde_dbg = dbg;
253
254    curfde = dbg->de_last_fde;
255    if (curfde == NULL) {
256        dbg->de_frame_fdes = fde;
257        dbg->de_last_fde = fde;
258        dbg->de_n_fde = 1;
259    } else {
260        curfde->fde_next = fde;
261        dbg->de_last_fde = fde;
262        dbg->de_n_fde++;
263    }
264    *index_to_fde = dbg->de_n_fde;
265    return DW_DLV_OK;
266}
267
268/*  This function adds information to an fde. The fde is
269    linked into the linked list of fde's maintained in the Dwarf_P_Debug
270    structure.
271    dbg: The debug descriptor.
272    fde: The fde to be added.
273    die: subprogram/function die corresponding to this fde
274    cie: cie referred to by this fde, obtained from call to
275        add_frame_cie() routine.
276    virt_addr: beginning address
277    code_len: length of code reps by the fde
278    symidx: The symbol id of the symbol wrt to which relocation needs
279        to be performed for 'virt_addr'.
280    offset_into_exception_tables: The start of exception tables for
281        this function (indicated as an offset into the exception
282        tables). A value of -1 indicates that there is no exception
283        table entries associated with this function.
284    exception_table_symbol: The symbol id of the section for exception
285        tables wrt to which the offset_into_exception_tables will
286        be relocated. */
287Dwarf_Unsigned
288dwarf_add_frame_info(Dwarf_P_Debug dbg,
289    Dwarf_P_Fde fde,
290    Dwarf_P_Die die,
291    Dwarf_Unsigned cie,
292    Dwarf_Unsigned virt_addr,
293    Dwarf_Unsigned code_len,
294    Dwarf_Unsigned symidx,
295    Dwarf_Signed offset_into_exception_tables,
296    Dwarf_Unsigned exception_table_symbol,
297    Dwarf_Error * error)
298{
299    Dwarf_Unsigned fde_index = 0;
300    int res = 0;
301
302    res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr,
303        code_len, symidx,
304        /* end_symbol */ 0,
305        /* offset_from_end */ 0,
306        offset_into_exception_tables,
307        exception_table_symbol,
308        &fde_index, error);
309    if (res != DW_DLV_OK) {
310        return DW_DLV_NOCOUNT;
311    }
312    return fde_index;
313}
314
315/*ARGSUSED*/                   /* pretend all args used */
316Dwarf_Unsigned
317dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
318    Dwarf_P_Fde fde,
319    Dwarf_P_Die die,
320    Dwarf_Unsigned cie,
321    Dwarf_Unsigned virt_addr,
322    Dwarf_Unsigned code_len,
323    Dwarf_Unsigned symidx,
324    Dwarf_Unsigned end_symidx,
325    Dwarf_Unsigned offset_from_end_symbol,
326    Dwarf_Signed offset_into_exception_tables,
327    Dwarf_Unsigned exception_table_symbol,
328    UNUSEDARG Dwarf_Error * error)
329{
330    Dwarf_Unsigned fde_index = 0;
331    int res = 0;
332
333    res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr,
334        code_len, symidx, end_symidx,
335        offset_from_end_symbol,
336        offset_into_exception_tables,
337        exception_table_symbol,
338        &fde_index, error);
339    if (res != DW_DLV_OK) {
340        return DW_DLV_NOCOUNT;
341    }
342    return fde_index;
343}
344
345int
346dwarf_add_frame_info_c(Dwarf_P_Debug dbg,
347    Dwarf_P_Fde fde,
348    Dwarf_P_Die die,
349    Dwarf_Unsigned cie,
350    Dwarf_Unsigned virt_addr,
351    Dwarf_Unsigned code_len,
352    Dwarf_Unsigned symidx,
353    Dwarf_Unsigned end_symidx,
354    Dwarf_Unsigned offset_from_end_symbol,
355    Dwarf_Signed offset_into_exception_tables,
356    Dwarf_Unsigned exception_table_symbol,
357    Dwarf_Unsigned *fde_index_out,
358    UNUSEDARG Dwarf_Error * error)
359{
360    Dwarf_P_Fde curfde;
361
362    fde->fde_die = die;
363    fde->fde_cie = (long) cie;
364    fde->fde_initloc = virt_addr;
365    fde->fde_r_symidx = symidx;
366    fde->fde_addr_range = code_len;
367    fde->fde_offset_into_exception_tables =
368        offset_into_exception_tables;
369    fde->fde_exception_table_symbol = exception_table_symbol;
370    fde->fde_end_symbol_offset = offset_from_end_symbol;
371    fde->fde_end_symbol = end_symidx;
372    fde->fde_dbg = dbg;
373
374    curfde = dbg->de_last_fde;
375    if (curfde == NULL) {
376        dbg->de_frame_fdes = fde;
377        dbg->de_last_fde = fde;
378        dbg->de_n_fde = 1;
379    } else {
380        curfde->fde_next = fde;
381        dbg->de_last_fde = fde;
382        dbg->de_n_fde++;
383    }
384    *fde_index_out = dbg->de_n_fde;
385    return DW_DLV_OK;
386}
387
388/* This is an alternate to inserting frame instructions
389   one instruction at a time.  But use either this
390   or instruction level, not both in one fde. */
391int
392dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
393    Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
394    Dwarf_Error *error)
395{
396    if (len == 0) {
397        return DW_DLV_OK;
398    }
399    if (fde->fde_block || fde->fde_inst) {
400        DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
401            DW_DLV_ERROR);
402    }
403    fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
404    memcpy(fde->fde_block,ibytes,len);
405    fde->fde_inst_block_size = len;
406    fde->fde_n_bytes += len;
407    return DW_DLV_OK;
408}
409
410
411
412/* Create a new fde. */
413Dwarf_P_Fde
414dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
415{
416    Dwarf_P_Fde fde = 0;
417    int res = 0;
418
419    res = dwarf_new_fde_a(dbg,&fde,error);
420    if (res != DW_DLV_OK) {
421        return (Dwarf_P_Fde) DW_DLV_BADADDR;
422    }
423    return fde;
424}
425int
426dwarf_new_fde_a(Dwarf_P_Debug dbg,
427    Dwarf_P_Fde *fde_out,
428    Dwarf_Error * error)
429{
430    Dwarf_P_Fde fde;
431
432    fde = (Dwarf_P_Fde)
433        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
434    if (fde == NULL) {
435        DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, DW_DLV_ERROR);
436    }
437    fde->fde_dbg = dbg;
438    fde->fde_uwordb_size = dbg->de_dwarf_offset_size;
439    *fde_out = fde;
440    return DW_DLV_OK;
441}
442
443
444/*  Add a cfe_offset instruction to the fde passed in. */
445Dwarf_P_Fde
446dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
447    Dwarf_Unsigned reg,
448    Dwarf_Signed offset,
449    Dwarf_Error * error)
450{
451    int res = 0;
452
453    res = dwarf_fde_cfa_offset_a(fde,reg,offset,error);
454    if (res != DW_DLV_OK) {
455        return (Dwarf_P_Fde) DW_DLV_BADADDR;
456    }
457    return fde;
458}
459
460
461int
462dwarf_fde_cfa_offset_a(Dwarf_P_Fde fde,
463    Dwarf_Unsigned reg,
464    Dwarf_Signed offset,
465    Dwarf_Error * error)
466{
467    Dwarf_Ubyte opc, regno;
468    char *ptr = 0;
469    Dwarf_P_Frame_Pgm curinst;
470    int nbytes = 0;
471    int res = 0;
472    char buff1[ENCODE_SPACE_NEEDED];
473    Dwarf_P_Debug dbg = fde->fde_dbg;
474
475    curinst = (Dwarf_P_Frame_Pgm)
476        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
477    if (curinst == NULL) {
478        DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, DW_DLV_ERROR);
479    }
480    opc = DW_CFA_offset;
481    regno = reg;
482    if (regno & 0xc0) {
483        DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,DW_DLV_ERROR);
484    }
485    opc = opc | regno;          /* lower 6 bits are register number */
486    curinst->dfp_opcode = opc;
487    res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
488        buff1, sizeof(buff1));
489    if (res != DW_DLV_OK) {
490        _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
491        return DW_DLV_ERROR;
492    }
493    ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
494    if (ptr == NULL) {
495        _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
496        return DW_DLV_ERROR;
497    }
498    memcpy(ptr, buff1, nbytes);
499
500    curinst->dfp_args = ptr;
501    curinst->dfp_nbytes = nbytes;
502    curinst->dfp_next = NULL;
503
504    _dwarf_pro_add_to_fde(fde, curinst);
505    return DW_DLV_OK;
506}
507
508/*  Generic routine to add opcode to fde instructions. val1 and
509    val2 are parameters whose interpretation depends on the 'op'.
510
511    This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
512    for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
513    these ops normally are addresses or (DW_CFA_set_loc)
514    or code lengths (DW_DVA_advance_loc*) and such must be
515    represented with relocations and symbol indices for
516    DW_DLC_SYMBOLIC_RELOCATIONS.
517
518    This does not treat all DW_CFA instructions yet.
519
520    For certain operations a val? value must be
521    signed (though passed in as unsigned here).
522
523    Does not check that the frame
524    version is 3(for dwarf3) or 4 (for dwarf4) or 5
525    when applying operations that are only valid for
526    particular versions. */
527Dwarf_P_Fde
528dwarf_add_fde_inst(Dwarf_P_Fde fde,
529    Dwarf_Small op,
530    Dwarf_Unsigned val1,
531    Dwarf_Unsigned val2, Dwarf_Error * error)
532{
533    int res = 0;
534
535    res = dwarf_add_fde_inst_a(fde,op,val1,val2,error);
536    if (res != DW_DLV_OK) {
537        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
538    }
539    return fde;
540}
541
542/*  December 2018. A more sensible return value. */
543int
544dwarf_add_fde_inst_a(Dwarf_P_Fde fde,
545    Dwarf_Small op,
546    Dwarf_Unsigned val1,
547    Dwarf_Unsigned val2,
548    Dwarf_Error * error)
549{
550    Dwarf_P_Frame_Pgm curinst;
551    int nbytes = 0;
552    int nbytes1 = 0;
553    int nbytes2 = 0;
554    Dwarf_Ubyte db = 0;
555    Dwarf_Half dh = 0;
556    Dwarf_Unsigned du = 0;
557    char *ptr = 0;
558    int res = 0;
559    char buff1[ENCODE_SPACE_NEEDED];
560    char buff2[ENCODE_SPACE_NEEDED];
561    Dwarf_P_Debug dbg = fde->fde_dbg;
562    /*  This is a hack telling the code when to transform
563        a value to a signed leb number. */
564    int signed_second = 0;
565    int signed_first = 0;
566
567
568    buff1[0] = 0;
569    buff2[0] = 0;
570    curinst = (Dwarf_P_Frame_Pgm)
571        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
572    if (curinst == NULL) {
573        _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
574        return DW_DLV_ERROR;
575    }
576    switch (op) {
577
578    case DW_CFA_advance_loc: {
579        if (val1 <= 0x3f) {
580            db = val1;
581            op |= db;
582        } else if (!(val1& ~0xff)) {
583            op = DW_CFA_advance_loc1;
584            db = val1;
585            ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
586            if (ptr == NULL) {
587                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
588                return DW_DLV_ERROR;
589            }
590            memcpy((void *) ptr, (const void *) &db, 1);
591            nbytes = 1;
592        } else if (!(val1& (~(Dwarf_Unsigned)0xffff))) {
593            if (sizeof(dh) < SIZEOFT16) {
594                _dwarf_p_error(dbg, error,
595                    DW_DLE_DEBUG_FRAME_LENGTH_BAD);
596                return DW_DLV_ERROR;
597            }
598            op = DW_CFA_advance_loc2;
599            dh = val1;
600            ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT16);
601            if (ptr == NULL) {
602                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
603                return DW_DLV_ERROR;
604            }
605            /*  No byte swapping, assuming running at
606                target endianness. */
607            ASNOUT((void *) ptr, dh, SIZEOFT16);
608            nbytes = SIZEOFT16;
609        } else if (!(val1& ~(Dwarf_Unsigned)0xffffffff)) {
610            if (sizeof(du) < SIZEOFT32) {
611                _dwarf_p_error(dbg, error,
612                    DW_DLE_DEBUG_FRAME_LENGTH_BAD);
613                return DW_DLV_ERROR;
614            }
615            op = DW_CFA_advance_loc4;
616            du = val1;
617            ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT32);
618            if (ptr == NULL) {
619                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
620                return DW_DLV_ERROR;
621            }
622            ASNOUT((void *) ptr, du, SIZEOFT32);
623            nbytes = SIZEOFT32;
624        } else {
625            if (sizeof(du) < SIZEOFT64) {
626                _dwarf_p_error(dbg, error,
627                    DW_DLE_DEBUG_FRAME_LENGTH_BAD);
628                return DW_DLV_ERROR;
629            }
630            op = DW_CFA_MIPS_advance_loc8;
631            du = val1;
632            ptr = (char *) _dwarf_p_get_alloc(dbg,
633                SIZEOFT64);
634            if (ptr == NULL) {
635                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
636                return DW_DLV_ERROR;
637            }
638            /*  No byte swapping, assuming running at
639                target endianness. */
640            ASNOUT((void *) ptr, du, SIZEOFT64);
641            nbytes = SIZEOFT64;
642        }
643        break;
644    }
645    case DW_CFA_offset:
646        if (val1 <= MAX_6_BIT_VALUE) {
647            db = val1;
648            op |= db;
649            res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
650                buff1, sizeof(buff1));
651            if (res != DW_DLV_OK) {
652                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
653                return DW_DLV_ERROR;
654            }
655            ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
656            if (ptr == NULL) {
657                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
658                return DW_DLV_ERROR;
659            }
660            memcpy(ptr, buff1, nbytes);
661
662        } else {
663            op = DW_CFA_offset_extended;
664            goto two_leb;
665        }
666        break;
667    case DW_CFA_offset_extended_sf: /* DWARF3 */
668        signed_second = 1;
669        goto two_leb;
670    case DW_CFA_offset_extended:
671        goto two_leb;
672
673    case DW_CFA_undefined:
674    case DW_CFA_same_value:
675        goto one_leb;
676
677    case DW_CFA_val_offset:
678        goto two_leb;
679    case DW_CFA_val_offset_sf:
680        signed_second = 1;
681        goto two_leb;
682    case DW_CFA_def_cfa_sf:
683        signed_second = 1;
684        goto two_leb;
685    case DW_CFA_register:
686    case DW_CFA_def_cfa:
687    two_leb:
688        res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
689            buff1, sizeof(buff1));
690        if (res != DW_DLV_OK) {
691            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
692            return DW_DLV_ERROR;
693        }
694        if (!signed_second) {
695            res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
696                buff2, sizeof(buff2));
697        } else {
698            Dwarf_Signed val2s = val2;
699            res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
700                buff2, sizeof(buff2));
701        }
702        if (res != DW_DLV_OK) {
703            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
704            return DW_DLV_ERROR;
705        }
706
707        res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
708            buff2, sizeof(buff2));
709        if (res != DW_DLV_OK) {
710            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
711            return DW_DLV_ERROR;
712        }
713
714        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
715        if (ptr == NULL) {
716            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
717            return DW_DLV_ERROR;
718        }
719        memcpy(ptr, buff1, nbytes1);
720        memcpy(ptr + nbytes1, buff2, nbytes2);
721        nbytes = nbytes1 + nbytes2;
722        break;
723
724    case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
725        signed_first = 1;
726        goto one_leb;
727    case DW_CFA_def_cfa_register:
728    case DW_CFA_def_cfa_offset:
729    one_leb:
730        if (!signed_first) {
731            res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
732                buff1, sizeof(buff1));
733        } else {
734            Dwarf_Signed val1s = val1;
735            res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
736                buff1, sizeof(buff1));
737        }
738        if (res != DW_DLV_OK) {
739            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
740            return DW_DLV_ERROR;
741        }
742        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
743        if (ptr == NULL) {
744            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
745            return DW_DLV_ERROR;
746        }
747        memcpy(ptr, buff1, nbytes);
748        break;
749    case DW_CFA_def_cfa_expression: /* DWARF3 */
750        /*  FIXME: argument is dwarf expr, not handled yet. */
751    case DW_CFA_expression: /* DWARF3 */
752        /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
753            FIXME: not handled yet. */
754    case DW_CFA_val_expression: /* DWARF3f */
755        /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
756            FIXME: not handled yet. */
757    default:
758        _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
759        return DW_DLV_ERROR;
760    }
761
762    curinst->dfp_opcode = op;
763    curinst->dfp_args = ptr;
764    curinst->dfp_nbytes = nbytes;
765    curinst->dfp_next = NULL;
766    _dwarf_pro_add_to_fde(fde, curinst);
767    return DW_DLV_OK;
768}
769
770
771/*  Instructions are added to an fde in the form of a linked
772    list. This function manages the linked list. */
773void
774_dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
775{
776    if (fde->fde_last_inst) {
777        fde->fde_last_inst->dfp_next = curinst;
778        fde->fde_last_inst = curinst;
779        fde->fde_n_inst++;
780        fde->fde_n_bytes +=
781            (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
782    } else {
783        fde->fde_last_inst = curinst;
784        fde->fde_inst = curinst;
785        fde->fde_n_inst = 1;
786        fde->fde_n_bytes =
787            (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
788    }
789}
790