1 /*
2 
3   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
4   Portions Copyright 2011-2012  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 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 */
28 
29 #include "config.h"
30 #include "libdwarfdefs.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
34 #include "pro_incl.h"
35 #include "pro_frame.h"
36 
37 static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
38     Dwarf_P_Frame_Pgm inst);
39 
40 /*  This function adds a cie struct to the debug pointer. Its in the
41     form of a linked list.
42     augmenter: string reps augmentation (implementation defined)
43     code_align: alignment of code
44     data_align: alignment of data
45     init_bytes: byts having initial instructions
46     init_n_bytes: number of bytes of initial instructions */
47 Dwarf_Unsigned
dwarf_add_frame_cie(Dwarf_P_Debug dbg,char * augmenter,Dwarf_Small code_align,Dwarf_Small data_align,Dwarf_Small return_reg,Dwarf_Ptr init_bytes,Dwarf_Unsigned init_n_bytes,Dwarf_Error * error)48 dwarf_add_frame_cie(Dwarf_P_Debug dbg,
49     char *augmenter,
50     Dwarf_Small code_align,
51     Dwarf_Small data_align,
52     Dwarf_Small return_reg,
53     Dwarf_Ptr init_bytes,
54     Dwarf_Unsigned init_n_bytes, Dwarf_Error * error)
55 {
56     Dwarf_P_Cie curcie;
57     char *tmpaug = 0;
58 
59     if (dbg->de_frame_cies == NULL) {
60         dbg->de_frame_cies = (Dwarf_P_Cie)
61             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
62         if (dbg->de_frame_cies == NULL) {
63             DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
64         }
65         curcie = dbg->de_frame_cies;
66         dbg->de_n_cie = 1;
67         dbg->de_last_cie = curcie;
68     } else {
69         curcie = dbg->de_last_cie;
70         curcie->cie_next = (Dwarf_P_Cie)
71             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
72         if (curcie->cie_next == NULL) {
73             DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
74         }
75         curcie = curcie->cie_next;
76         dbg->de_n_cie++;
77         dbg->de_last_cie = curcie;
78     }
79     curcie->cie_version = DW_CIE_VERSION;
80     tmpaug = (char *)_dwarf_p_get_alloc(dbg,strlen(augmenter)+1);
81     strcpy(tmpaug,augmenter);
82     if (!tmpaug) {
83         DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
84     }
85     curcie->cie_aug = tmpaug;
86     curcie->cie_code_align = code_align;
87     curcie->cie_data_align = data_align;
88     curcie->cie_ret_reg = return_reg;
89     curcie->cie_inst = (char *) init_bytes;
90     curcie->cie_inst_bytes = (long) init_n_bytes;
91     curcie->cie_next = NULL;
92     return dbg->de_n_cie;
93 }
94 
95 
96 /*  This functions adds a fde struct to the debug pointer. Its in the
97     form of a linked list.
98     die: subprogram/function die corresponding to this fde
99     cie: cie referred to by this fde, obtained from call to
100         add_frame_cie() routine.
101     virt_addr: beginning address
102     code_len: length of code reps by the fde */
103 /*ARGSUSED*/                   /* pretend all args used */
104 Dwarf_Unsigned
dwarf_add_frame_fde(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Error * error)105 dwarf_add_frame_fde(Dwarf_P_Debug dbg,
106     Dwarf_P_Fde fde,
107     Dwarf_P_Die die,
108     Dwarf_Unsigned cie,
109     Dwarf_Unsigned virt_addr,
110     Dwarf_Unsigned code_len,
111     Dwarf_Unsigned symidx, Dwarf_Error * error)
112 {
113     return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr,
114         code_len, symidx, 0, 0, error);
115 }
116 
117 /*ARGSUSED10*/
118 Dwarf_Unsigned
dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Unsigned symidx_of_end,Dwarf_Addr offset_from_end_sym,UNUSEDARG Dwarf_Error * error)119 dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
120     Dwarf_P_Fde fde,
121     Dwarf_P_Die die,
122     Dwarf_Unsigned cie,
123     Dwarf_Unsigned virt_addr,
124     Dwarf_Unsigned code_len,
125     Dwarf_Unsigned symidx,
126     Dwarf_Unsigned symidx_of_end,
127     Dwarf_Addr offset_from_end_sym,
128     UNUSEDARG Dwarf_Error * error)
129 {
130     Dwarf_P_Fde curfde;
131 
132     fde->fde_die = die;
133     fde->fde_cie = (long) cie;
134     fde->fde_initloc = virt_addr;
135     fde->fde_r_symidx = symidx;
136     fde->fde_addr_range = code_len;
137     fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
138     fde->fde_exception_table_symbol = 0;
139     fde->fde_end_symbol_offset = offset_from_end_sym;
140     fde->fde_end_symbol = symidx_of_end;
141     fde->fde_dbg = dbg;
142 
143     curfde = dbg->de_last_fde;
144     if (curfde == NULL) {
145         dbg->de_frame_fdes = fde;
146         dbg->de_last_fde = fde;
147         dbg->de_n_fde = 1;
148     } else {
149         curfde->fde_next = fde;
150         dbg->de_last_fde = fde;
151         dbg->de_n_fde++;
152     }
153     return dbg->de_n_fde;
154 }
155 
156 /*  This function adds information to an fde. The fde is
157     linked into the linked list of fde's maintained in the Dwarf_P_Debug
158     structure.
159     dbg: The debug descriptor.
160     fde: The fde to be added.
161     die: subprogram/function die corresponding to this fde
162     cie: cie referred to by this fde, obtained from call to
163         add_frame_cie() routine.
164     virt_addr: beginning address
165     code_len: length of code reps by the fde
166     symidx: The symbol id of the symbol wrt to which relocation needs
167         to be performed for 'virt_addr'.
168     offset_into_exception_tables: The start of exception tables for
169         this function (indicated as an offset into the exception
170         tables). A value of -1 indicates that there is no exception
171         table entries associated with this function.
172     exception_table_symbol: The symbol id of the section for exception
173         tables wrt to which the offset_into_exception_tables will
174         be relocated. */
175 Dwarf_Unsigned
dwarf_add_frame_info(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Signed offset_into_exception_tables,Dwarf_Unsigned exception_table_symbol,Dwarf_Error * error)176 dwarf_add_frame_info(Dwarf_P_Debug dbg,
177     Dwarf_P_Fde fde,
178     Dwarf_P_Die die,
179     Dwarf_Unsigned cie,
180     Dwarf_Unsigned virt_addr,
181     Dwarf_Unsigned code_len,
182     Dwarf_Unsigned symidx,
183     Dwarf_Signed offset_into_exception_tables,
184     Dwarf_Unsigned exception_table_symbol,
185     Dwarf_Error * error)
186 {
187 
188     return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
189         code_len, symidx,
190         /* end_symbol */ 0,
191         /* offset_from_end */ 0,
192         offset_into_exception_tables,
193         exception_table_symbol, error);
194 
195 }
196 
197 /*ARGSUSED*/                   /* pretend all args used */
198 Dwarf_Unsigned
dwarf_add_frame_info_b(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Unsigned end_symidx,Dwarf_Unsigned offset_from_end_symbol,Dwarf_Signed offset_into_exception_tables,Dwarf_Unsigned exception_table_symbol,UNUSEDARG Dwarf_Error * error)199 dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
200     Dwarf_P_Fde fde,
201     Dwarf_P_Die die,
202     Dwarf_Unsigned cie,
203     Dwarf_Unsigned virt_addr,
204     Dwarf_Unsigned code_len,
205     Dwarf_Unsigned symidx,
206     Dwarf_Unsigned end_symidx,
207     Dwarf_Unsigned offset_from_end_symbol,
208     Dwarf_Signed offset_into_exception_tables,
209     Dwarf_Unsigned exception_table_symbol,
210     UNUSEDARG Dwarf_Error * error)
211 {
212     Dwarf_P_Fde curfde;
213 
214     fde->fde_die = die;
215     fde->fde_cie = (long) cie;
216     fde->fde_initloc = virt_addr;
217     fde->fde_r_symidx = symidx;
218     fde->fde_addr_range = code_len;
219     fde->fde_offset_into_exception_tables =
220         offset_into_exception_tables;
221     fde->fde_exception_table_symbol = exception_table_symbol;
222     fde->fde_end_symbol_offset = offset_from_end_symbol;
223     fde->fde_end_symbol = end_symidx;
224     fde->fde_dbg = dbg;
225 
226     curfde = dbg->de_last_fde;
227     if (curfde == NULL) {
228         dbg->de_frame_fdes = fde;
229         dbg->de_last_fde = fde;
230         dbg->de_n_fde = 1;
231     } else {
232         curfde->fde_next = fde;
233         dbg->de_last_fde = fde;
234         dbg->de_n_fde++;
235     }
236     return dbg->de_n_fde;
237 }
238 
239 /* This is an alternate to inserting frame instructions
240    one instruction at a time.  But use either this
241    or instruction level, not both in one fde. */
242 int
dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_Unsigned len,Dwarf_Ptr ibytes,Dwarf_Error * error)243 dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
244     Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
245     Dwarf_Error *error)
246 {
247     if (len == 0) {
248         return DW_DLV_OK;
249     }
250     if (fde->fde_block || fde->fde_inst) {
251         DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
252             (int)DW_DLV_BADADDR);
253     }
254     fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
255     memcpy(fde->fde_block,ibytes,len);
256     fde->fde_inst_block_size = len;
257     fde->fde_n_bytes += len;
258     return DW_DLV_OK;
259 }
260 
261 
262 
263 /* Create a new fde. */
264 Dwarf_P_Fde
dwarf_new_fde(Dwarf_P_Debug dbg,Dwarf_Error * error)265 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
266 {
267     Dwarf_P_Fde fde;
268 
269     fde = (Dwarf_P_Fde)
270         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
271     if (fde == NULL) {
272         DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
273             (Dwarf_P_Fde) DW_DLV_BADADDR);
274     }
275     fde->fde_uwordb_size = dbg->de_offset_size;
276     return fde;
277 }
278 
279 
280 /*  Add a cfe_offset instruction to the fde passed in. */
281 Dwarf_P_Fde
dwarf_fde_cfa_offset(Dwarf_P_Fde fde,Dwarf_Unsigned reg,Dwarf_Signed offset,Dwarf_Error * error)282 dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
283     Dwarf_Unsigned reg,
284     Dwarf_Signed offset, Dwarf_Error * error)
285 {
286     Dwarf_Ubyte opc, regno;
287     char *ptr = 0;
288     Dwarf_P_Frame_Pgm curinst;
289     int nbytes = 0;
290     int res = 0;
291     char buff1[ENCODE_SPACE_NEEDED];
292     Dwarf_P_Debug dbg = fde->fde_dbg;
293 
294     curinst = (Dwarf_P_Frame_Pgm)
295         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
296     if (curinst == NULL) {
297         DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC,
298             (Dwarf_P_Fde) DW_DLV_BADADDR);
299     }
300     opc = DW_CFA_offset;
301     regno = reg;
302     if (regno & 0xc0) {
303         DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
304             (Dwarf_P_Fde) DW_DLV_BADADDR);
305     }
306     opc = opc | regno;          /* lower 6 bits are register number */
307     curinst->dfp_opcode = opc;
308     res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
309         buff1, sizeof(buff1));
310     if (res != DW_DLV_OK) {
311         _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
312         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
313     }
314     ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
315     if (ptr == NULL) {
316         _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
317         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
318     }
319     memcpy(ptr, buff1, nbytes);
320 
321     curinst->dfp_args = ptr;
322     curinst->dfp_nbytes = nbytes;
323     curinst->dfp_next = NULL;
324 
325     _dwarf_pro_add_to_fde(fde, curinst);
326     return fde;
327 }
328 
329 /*  Generic routine to add opcode to fde instructions. val1 and
330     val2 are parameters whose interpretation depends on the 'op'.
331 
332     This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
333     for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
334     these ops normally are addresses or (DW_CFA_set_loc)
335     or code lengths (DW_DVA_advance_loc*) and such must be
336     represented with relocations and symbol indices for
337     DW_DLC_SYMBOLIC_RELOCATIONS.
338 
339     This does not treat all DW_CFA instructions yet.
340 
341     For certain operations a val? value must be
342     signed (though passed in as unsigned here).
343 
344     Currently this does not check that the frame
345     version is 3(for dwarf3) or 4 (for dwarf4)
346     when applying operations that are only valid for
347     dwarf3 or dwarf4. */
348 Dwarf_P_Fde
dwarf_add_fde_inst(Dwarf_P_Fde fde,Dwarf_Small op,Dwarf_Unsigned val1,Dwarf_Unsigned val2,Dwarf_Error * error)349 dwarf_add_fde_inst(Dwarf_P_Fde fde,
350     Dwarf_Small op,
351     Dwarf_Unsigned val1,
352     Dwarf_Unsigned val2, Dwarf_Error * error)
353 {
354     Dwarf_P_Frame_Pgm curinst;
355     int nbytes, nbytes1, nbytes2;
356     Dwarf_Ubyte db;
357     Dwarf_Half dh;
358     Dwarf_Word dw;
359     Dwarf_Unsigned du;
360     char *ptr;
361     int res;
362     char buff1[ENCODE_SPACE_NEEDED];
363     char buff2[ENCODE_SPACE_NEEDED];
364     Dwarf_P_Debug dbg = fde->fde_dbg;
365     /*  This is a hack telling the code when to transform
366         a value to a signed leb number. */
367     int signed_second = 0;
368     int signed_first = 0;
369 
370 
371     nbytes = 0;
372     ptr = NULL;
373     curinst = (Dwarf_P_Frame_Pgm)
374         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
375     if (curinst == NULL) {
376         _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
377         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
378     }
379 
380     switch (op) {
381 
382     case DW_CFA_advance_loc:
383         if (val1 <= 0x3f) {
384             db = val1;
385             op |= db;
386         }
387         /* test not portable FIX */
388         else if (val1 <= UCHAR_MAX) {
389             op = DW_CFA_advance_loc1;
390             db = val1;
391             ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
392             if (ptr == NULL) {
393                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
394                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
395             }
396             memcpy((void *) ptr, (const void *) &db, 1);
397             nbytes = 1;
398         }
399         /* test not portable FIX */
400         else if (val1 <= USHRT_MAX) {
401             op = DW_CFA_advance_loc2;
402             dh = val1;
403             ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
404             if (ptr == NULL) {
405                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
406                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
407             }
408             memcpy((void *) ptr, (const void *) &dh, 2);
409             nbytes = 2;
410         }
411         /* test not portable FIX */
412         else if (val1 <= ULONG_MAX) {
413             op = DW_CFA_advance_loc4;
414             dw = (Dwarf_Word) val1;
415             ptr = (char *) _dwarf_p_get_alloc(dbg, 4);
416             if (ptr == NULL) {
417                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
418                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
419             }
420             memcpy((void *) ptr, (const void *) &dw, 4);
421             nbytes = 4;
422         } else {
423             op = DW_CFA_MIPS_advance_loc8;
424             du = val1;
425             ptr =
426                 (char *) _dwarf_p_get_alloc(dbg,
427                     sizeof(Dwarf_Unsigned));
428             if (ptr == NULL) {
429                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
430                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
431             }
432             memcpy((void *) ptr, (const void *) &du, 8);
433             nbytes = 8;
434         }
435         break;
436 
437     case DW_CFA_offset:
438         if (val1 <= MAX_6_BIT_VALUE) {
439             db = val1;
440             op |= db;
441             res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
442                 buff1, sizeof(buff1));
443             if (res != DW_DLV_OK) {
444                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
445                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
446             }
447             ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
448             if (ptr == NULL) {
449                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
450                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
451             }
452             memcpy(ptr, buff1, nbytes);
453 
454         } else {
455             op = DW_CFA_offset_extended;
456             goto two_leb;
457         }
458         break;
459     case DW_CFA_offset_extended_sf: /* DWARF3 */
460         signed_second = 1;
461         goto two_leb;
462     case DW_CFA_offset_extended:
463         goto two_leb;
464 
465     case DW_CFA_undefined:
466     case DW_CFA_same_value:
467         goto one_leb;
468 
469     case DW_CFA_val_offset:
470         goto two_leb;
471     case DW_CFA_val_offset_sf:
472         signed_second = 1;
473         goto two_leb;
474     case DW_CFA_def_cfa_sf:
475         signed_second = 1;
476         goto two_leb;
477     case DW_CFA_register:
478     case DW_CFA_def_cfa:
479     two_leb:
480         res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
481             buff1, sizeof(buff1));
482         if (res != DW_DLV_OK) {
483             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
484             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
485         }
486         if (!signed_second) {
487             res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
488                 buff2, sizeof(buff2));
489         } else {
490             Dwarf_Signed val2s = val2;
491             res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
492                 buff2, sizeof(buff2));
493         }
494 
495         res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
496             buff2, sizeof(buff2));
497         if (res != DW_DLV_OK) {
498             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
499             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
500         }
501 
502         ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
503         if (ptr == NULL) {
504             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
505             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
506         }
507         memcpy(ptr, buff1, nbytes1);
508         memcpy(ptr + nbytes1, buff2, nbytes2);
509         nbytes = nbytes1 + nbytes2;
510         break;
511 
512     case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
513         signed_first = 1;
514         goto one_leb;
515     case DW_CFA_def_cfa_register:
516     case DW_CFA_def_cfa_offset:
517     one_leb:
518         if (!signed_first) {
519             res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
520                 buff1, sizeof(buff1));
521         } else {
522             Dwarf_Signed val1s = val1;
523             res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
524                 buff1, sizeof(buff1));
525         }
526         if (res != DW_DLV_OK) {
527             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
528             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
529         }
530         ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
531         if (ptr == NULL) {
532             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
533             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
534         }
535         memcpy(ptr, buff1, nbytes);
536         break;
537     case DW_CFA_def_cfa_expression: /* DWARF3 */
538         /*  FIXME: argument is dwarf expr, not handled yet. */
539     case DW_CFA_expression: /* DWARF3 */
540         /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
541             FIXME: not handled yet. */
542     case DW_CFA_val_expression: /* DWARF3f */
543         /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
544             FIXME: not handled yet. */
545     default:
546         _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
547         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
548     }
549 
550     curinst->dfp_opcode = op;
551     curinst->dfp_args = ptr;
552     curinst->dfp_nbytes = nbytes;
553     curinst->dfp_next = NULL;
554 
555     _dwarf_pro_add_to_fde(fde, curinst);
556     return fde;
557 }
558 
559 
560 /*  Instructions are added to an fde in the form of a linked
561     list. This function manages the linked list. */
562 void
_dwarf_pro_add_to_fde(Dwarf_P_Fde fde,Dwarf_P_Frame_Pgm curinst)563 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
564 {
565     if (fde->fde_last_inst) {
566         fde->fde_last_inst->dfp_next = curinst;
567         fde->fde_last_inst = curinst;
568         fde->fde_n_inst++;
569         fde->fde_n_bytes +=
570             (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
571     } else {
572         fde->fde_last_inst = curinst;
573         fde->fde_inst = curinst;
574         fde->fde_n_inst = 1;
575         fde->fde_n_bytes =
576             (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
577     }
578 }
579