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