xref: /titanic_44/usr/src/tools/ctf/dwarf/common/pro_frame.c (revision 07dc1947c362e187fb955d283b692f8769dd5def)
149d3bc91SRichard Lowe /*
249d3bc91SRichard Lowe 
3*07dc1947SRichard Lowe   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
449d3bc91SRichard Lowe 
549d3bc91SRichard Lowe   This program is free software; you can redistribute it and/or modify it
649d3bc91SRichard Lowe   under the terms of version 2.1 of the GNU Lesser General Public License
749d3bc91SRichard Lowe   as published by the Free Software Foundation.
849d3bc91SRichard Lowe 
949d3bc91SRichard Lowe   This program is distributed in the hope that it would be useful, but
1049d3bc91SRichard Lowe   WITHOUT ANY WARRANTY; without even the implied warranty of
1149d3bc91SRichard Lowe   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1249d3bc91SRichard Lowe 
1349d3bc91SRichard Lowe   Further, this software is distributed without any warranty that it is
1449d3bc91SRichard Lowe   free of the rightful claim of any third person regarding infringement
1549d3bc91SRichard Lowe   or the like.  Any license provided herein, whether implied or
1649d3bc91SRichard Lowe   otherwise, applies only to this software file.  Patent licenses, if
1749d3bc91SRichard Lowe   any, provided herein do not apply to combinations of this program with
1849d3bc91SRichard Lowe   other software, or any other product whatsoever.
1949d3bc91SRichard Lowe 
2049d3bc91SRichard Lowe   You should have received a copy of the GNU Lesser General Public
2149d3bc91SRichard Lowe   License along with this program; if not, write the Free Software
22*07dc1947SRichard Lowe   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2349d3bc91SRichard Lowe   USA.
2449d3bc91SRichard Lowe 
25*07dc1947SRichard Lowe   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2649d3bc91SRichard Lowe   Mountain View, CA 94043, or:
2749d3bc91SRichard Lowe 
2849d3bc91SRichard Lowe   http://www.sgi.com
2949d3bc91SRichard Lowe 
3049d3bc91SRichard Lowe   For further information regarding this notice, see:
3149d3bc91SRichard Lowe 
3249d3bc91SRichard Lowe   http://oss.sgi.com/projects/GenInfo/NoticeExplan
3349d3bc91SRichard Lowe 
3449d3bc91SRichard Lowe */
3549d3bc91SRichard Lowe 
3649d3bc91SRichard Lowe 
3749d3bc91SRichard Lowe 
3849d3bc91SRichard Lowe #include "config.h"
3949d3bc91SRichard Lowe #include "libdwarfdefs.h"
4049d3bc91SRichard Lowe #include <stdio.h>
4149d3bc91SRichard Lowe #include <string.h>
4249d3bc91SRichard Lowe #include <limits.h>
4349d3bc91SRichard Lowe #include "pro_incl.h"
4449d3bc91SRichard Lowe #include "pro_frame.h"
4549d3bc91SRichard Lowe 
4649d3bc91SRichard Lowe static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
4749d3bc91SRichard Lowe                                   Dwarf_P_Frame_Pgm inst);
4849d3bc91SRichard Lowe 
4949d3bc91SRichard Lowe /*-------------------------------------------------------------------------
50*07dc1947SRichard Lowe         This function adds a cie struct to the debug pointer. Its in the
5149d3bc91SRichard Lowe         form of a linked list.
5249d3bc91SRichard Lowe         augmenter: string reps augmentation (implementation defined)
5349d3bc91SRichard Lowe         code_align: alignment of code
5449d3bc91SRichard Lowe         data_align: alignment of data
5549d3bc91SRichard Lowe         init_bytes: byts having initial instructions
5649d3bc91SRichard Lowe         init_n_bytes: number of bytes of initial instructions
5749d3bc91SRichard Lowe --------------------------------------------------------------------------*/
5849d3bc91SRichard Lowe 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)5949d3bc91SRichard Lowe dwarf_add_frame_cie(Dwarf_P_Debug dbg,
6049d3bc91SRichard Lowe                     char *augmenter,
6149d3bc91SRichard Lowe                     Dwarf_Small code_align,
6249d3bc91SRichard Lowe                     Dwarf_Small data_align,
6349d3bc91SRichard Lowe                     Dwarf_Small return_reg,
6449d3bc91SRichard Lowe                     Dwarf_Ptr init_bytes,
6549d3bc91SRichard Lowe                     Dwarf_Unsigned init_n_bytes, Dwarf_Error * error)
6649d3bc91SRichard Lowe {
6749d3bc91SRichard Lowe     Dwarf_P_Cie curcie;
6849d3bc91SRichard Lowe 
6949d3bc91SRichard Lowe     if (dbg->de_frame_cies == NULL) {
7049d3bc91SRichard Lowe         dbg->de_frame_cies = (Dwarf_P_Cie)
7149d3bc91SRichard Lowe             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
7249d3bc91SRichard Lowe         if (dbg->de_frame_cies == NULL) {
7349d3bc91SRichard Lowe             DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
7449d3bc91SRichard Lowe         }
7549d3bc91SRichard Lowe         curcie = dbg->de_frame_cies;
7649d3bc91SRichard Lowe         dbg->de_n_cie = 1;
7749d3bc91SRichard Lowe         dbg->de_last_cie = curcie;
7849d3bc91SRichard Lowe     } else {
7949d3bc91SRichard Lowe         curcie = dbg->de_last_cie;
8049d3bc91SRichard Lowe         curcie->cie_next = (Dwarf_P_Cie)
8149d3bc91SRichard Lowe             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
8249d3bc91SRichard Lowe         if (curcie->cie_next == NULL) {
8349d3bc91SRichard Lowe             DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
8449d3bc91SRichard Lowe         }
8549d3bc91SRichard Lowe         curcie = curcie->cie_next;
8649d3bc91SRichard Lowe         dbg->de_n_cie++;
8749d3bc91SRichard Lowe         dbg->de_last_cie = curcie;
8849d3bc91SRichard Lowe     }
8949d3bc91SRichard Lowe     curcie->cie_version = DW_CIE_VERSION;
9049d3bc91SRichard Lowe     curcie->cie_aug = augmenter;
9149d3bc91SRichard Lowe     curcie->cie_code_align = code_align;
9249d3bc91SRichard Lowe     curcie->cie_data_align = data_align;
9349d3bc91SRichard Lowe     curcie->cie_ret_reg = return_reg;
9449d3bc91SRichard Lowe     curcie->cie_inst = (char *) init_bytes;
9549d3bc91SRichard Lowe     curcie->cie_inst_bytes = (long) init_n_bytes;
9649d3bc91SRichard Lowe     curcie->cie_next = NULL;
9749d3bc91SRichard Lowe     return dbg->de_n_cie;
9849d3bc91SRichard Lowe }
9949d3bc91SRichard Lowe 
10049d3bc91SRichard Lowe 
10149d3bc91SRichard Lowe /*-------------------------------------------------------------------------
10249d3bc91SRichard Lowe         This functions adds a fde struct to the debug pointer. Its in the
10349d3bc91SRichard Lowe         form of a linked list.
10449d3bc91SRichard Lowe         die: subprogram/function die corresponding to this fde
10549d3bc91SRichard Lowe         cie: cie referred to by this fde, obtained from call to
10649d3bc91SRichard Lowe             add_frame_cie() routine.
10749d3bc91SRichard Lowe         virt_addr: beginning address
10849d3bc91SRichard Lowe         code_len: length of code reps by the fde
10949d3bc91SRichard Lowe --------------------------------------------------------------------------*/
11049d3bc91SRichard Lowe  /*ARGSUSED*/                   /* pretend all args used */
11149d3bc91SRichard Lowe     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)11249d3bc91SRichard Lowe dwarf_add_frame_fde(Dwarf_P_Debug dbg,
11349d3bc91SRichard Lowe                     Dwarf_P_Fde fde,
11449d3bc91SRichard Lowe                     Dwarf_P_Die die,
11549d3bc91SRichard Lowe                     Dwarf_Unsigned cie,
11649d3bc91SRichard Lowe                     Dwarf_Unsigned virt_addr,
11749d3bc91SRichard Lowe                     Dwarf_Unsigned code_len,
11849d3bc91SRichard Lowe                     Dwarf_Unsigned symidx, Dwarf_Error * error)
11949d3bc91SRichard Lowe {
12049d3bc91SRichard Lowe     return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr,
12149d3bc91SRichard Lowe                                  code_len, symidx, 0, 0, error);
12249d3bc91SRichard Lowe }
12349d3bc91SRichard Lowe 
12449d3bc91SRichard Lowe /*ARGSUSED10*/
12549d3bc91SRichard Lowe 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,Dwarf_Error * error)12649d3bc91SRichard Lowe dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
12749d3bc91SRichard Lowe                       Dwarf_P_Fde fde,
12849d3bc91SRichard Lowe                       Dwarf_P_Die die,
12949d3bc91SRichard Lowe                       Dwarf_Unsigned cie,
13049d3bc91SRichard Lowe                       Dwarf_Unsigned virt_addr,
13149d3bc91SRichard Lowe                       Dwarf_Unsigned code_len,
13249d3bc91SRichard Lowe                       Dwarf_Unsigned symidx,
13349d3bc91SRichard Lowe                       Dwarf_Unsigned symidx_of_end,
13449d3bc91SRichard Lowe                       Dwarf_Addr offset_from_end_sym,
13549d3bc91SRichard Lowe                       Dwarf_Error * error)
13649d3bc91SRichard Lowe {
13749d3bc91SRichard Lowe     Dwarf_P_Fde curfde;
13849d3bc91SRichard Lowe 
13949d3bc91SRichard Lowe     fde->fde_die = die;
14049d3bc91SRichard Lowe     fde->fde_cie = (long) cie;
14149d3bc91SRichard Lowe     fde->fde_initloc = virt_addr;
14249d3bc91SRichard Lowe     fde->fde_r_symidx = symidx;
14349d3bc91SRichard Lowe     fde->fde_addr_range = code_len;
14449d3bc91SRichard Lowe     fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
14549d3bc91SRichard Lowe     fde->fde_exception_table_symbol = 0;
14649d3bc91SRichard Lowe     fde->fde_end_symbol_offset = offset_from_end_sym;
14749d3bc91SRichard Lowe     fde->fde_end_symbol = symidx_of_end;
148*07dc1947SRichard Lowe     fde->fde_dbg = dbg;
14949d3bc91SRichard Lowe 
15049d3bc91SRichard Lowe     curfde = dbg->de_last_fde;
15149d3bc91SRichard Lowe     if (curfde == NULL) {
15249d3bc91SRichard Lowe         dbg->de_frame_fdes = fde;
15349d3bc91SRichard Lowe         dbg->de_last_fde = fde;
15449d3bc91SRichard Lowe         dbg->de_n_fde = 1;
15549d3bc91SRichard Lowe     } else {
15649d3bc91SRichard Lowe         curfde->fde_next = fde;
15749d3bc91SRichard Lowe         dbg->de_last_fde = fde;
15849d3bc91SRichard Lowe         dbg->de_n_fde++;
15949d3bc91SRichard Lowe     }
16049d3bc91SRichard Lowe     return dbg->de_n_fde;
16149d3bc91SRichard Lowe }
16249d3bc91SRichard Lowe 
16349d3bc91SRichard Lowe /*-------------------------------------------------------------------------
16449d3bc91SRichard Lowe         This functions adds information to an fde. The fde is
16549d3bc91SRichard Lowe         linked into the linked list of fde's maintained in the Dwarf_P_Debug
16649d3bc91SRichard Lowe         structure.
16749d3bc91SRichard Lowe         dbg: The debug descriptor.
16849d3bc91SRichard Lowe         fde: The fde to be added.
16949d3bc91SRichard Lowe         die: subprogram/function die corresponding to this fde
17049d3bc91SRichard Lowe         cie: cie referred to by this fde, obtained from call to
17149d3bc91SRichard Lowe             add_frame_cie() routine.
17249d3bc91SRichard Lowe         virt_addr: beginning address
17349d3bc91SRichard Lowe         code_len: length of code reps by the fde
17449d3bc91SRichard Lowe         symidx: The symbol id of the symbol wrt to which relocation needs
17549d3bc91SRichard Lowe                 to be performed for 'virt_addr'.
17649d3bc91SRichard Lowe         offset_into_exception_tables: The start of exception tables for
17749d3bc91SRichard Lowe                 this function (indicated as an offset into the exception
17849d3bc91SRichard Lowe                 tables). A value of -1 indicates that there is no exception
17949d3bc91SRichard Lowe                 table entries associated with this function.
18049d3bc91SRichard Lowe         exception_table_symbol: The symbol id of the section for exception
18149d3bc91SRichard Lowe                 tables wrt to which the offset_into_exception_tables will
18249d3bc91SRichard Lowe                 be relocated.
18349d3bc91SRichard Lowe --------------------------------------------------------------------------*/
18449d3bc91SRichard Lowe 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)18549d3bc91SRichard Lowe dwarf_add_frame_info(Dwarf_P_Debug dbg,
18649d3bc91SRichard Lowe                      Dwarf_P_Fde fde,
18749d3bc91SRichard Lowe                      Dwarf_P_Die die,
18849d3bc91SRichard Lowe                      Dwarf_Unsigned cie,
18949d3bc91SRichard Lowe                      Dwarf_Unsigned virt_addr,
19049d3bc91SRichard Lowe                      Dwarf_Unsigned code_len,
19149d3bc91SRichard Lowe                      Dwarf_Unsigned symidx,
19249d3bc91SRichard Lowe                      Dwarf_Signed offset_into_exception_tables,
19349d3bc91SRichard Lowe                      Dwarf_Unsigned exception_table_symbol,
19449d3bc91SRichard Lowe                      Dwarf_Error * error)
19549d3bc91SRichard Lowe {
19649d3bc91SRichard Lowe 
19749d3bc91SRichard Lowe     return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
19849d3bc91SRichard Lowe                                   code_len, symidx,
19949d3bc91SRichard Lowe                                   /* end_symbol */ 0,
20049d3bc91SRichard Lowe                                   /* offset_from_end */ 0,
20149d3bc91SRichard Lowe                                   offset_into_exception_tables,
20249d3bc91SRichard Lowe                                   exception_table_symbol, error);
20349d3bc91SRichard Lowe 
20449d3bc91SRichard Lowe }
20549d3bc91SRichard Lowe 
20649d3bc91SRichard Lowe  /*ARGSUSED*/                   /* pretend all args used */
20749d3bc91SRichard Lowe 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,Dwarf_Error * error)20849d3bc91SRichard Lowe dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
20949d3bc91SRichard Lowe                        Dwarf_P_Fde fde,
21049d3bc91SRichard Lowe                        Dwarf_P_Die die,
21149d3bc91SRichard Lowe                        Dwarf_Unsigned cie,
21249d3bc91SRichard Lowe                        Dwarf_Unsigned virt_addr,
21349d3bc91SRichard Lowe                        Dwarf_Unsigned code_len,
21449d3bc91SRichard Lowe                        Dwarf_Unsigned symidx,
21549d3bc91SRichard Lowe                        Dwarf_Unsigned end_symidx,
21649d3bc91SRichard Lowe                        Dwarf_Unsigned offset_from_end_symbol,
21749d3bc91SRichard Lowe                        Dwarf_Signed offset_into_exception_tables,
21849d3bc91SRichard Lowe                        Dwarf_Unsigned exception_table_symbol,
21949d3bc91SRichard Lowe                        Dwarf_Error * error)
22049d3bc91SRichard Lowe {
22149d3bc91SRichard Lowe     Dwarf_P_Fde curfde;
22249d3bc91SRichard Lowe 
22349d3bc91SRichard Lowe     fde->fde_die = die;
22449d3bc91SRichard Lowe     fde->fde_cie = (long) cie;
22549d3bc91SRichard Lowe     fde->fde_initloc = virt_addr;
22649d3bc91SRichard Lowe     fde->fde_r_symidx = symidx;
22749d3bc91SRichard Lowe     fde->fde_addr_range = code_len;
22849d3bc91SRichard Lowe     fde->fde_offset_into_exception_tables =
22949d3bc91SRichard Lowe         offset_into_exception_tables;
23049d3bc91SRichard Lowe     fde->fde_exception_table_symbol = exception_table_symbol;
23149d3bc91SRichard Lowe     fde->fde_end_symbol_offset = offset_from_end_symbol;
23249d3bc91SRichard Lowe     fde->fde_end_symbol = end_symidx;
233*07dc1947SRichard Lowe     fde->fde_dbg = dbg;
23449d3bc91SRichard Lowe 
23549d3bc91SRichard Lowe     curfde = dbg->de_last_fde;
23649d3bc91SRichard Lowe     if (curfde == NULL) {
23749d3bc91SRichard Lowe         dbg->de_frame_fdes = fde;
23849d3bc91SRichard Lowe         dbg->de_last_fde = fde;
23949d3bc91SRichard Lowe         dbg->de_n_fde = 1;
24049d3bc91SRichard Lowe     } else {
24149d3bc91SRichard Lowe         curfde->fde_next = fde;
24249d3bc91SRichard Lowe         dbg->de_last_fde = fde;
24349d3bc91SRichard Lowe         dbg->de_n_fde++;
24449d3bc91SRichard Lowe     }
24549d3bc91SRichard Lowe     return dbg->de_n_fde;
24649d3bc91SRichard Lowe }
24749d3bc91SRichard Lowe 
248*07dc1947SRichard Lowe /* This is an alternate to inserting frame instructions
249*07dc1947SRichard Lowe    one instruction at a time.  But use either this
250*07dc1947SRichard Lowe    or instruction level, not both in one fde. */
251*07dc1947SRichard Lowe int
dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_Unsigned len,Dwarf_Ptr ibytes,Dwarf_Error * error)252*07dc1947SRichard Lowe dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
253*07dc1947SRichard Lowe     Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
254*07dc1947SRichard Lowe     Dwarf_Error *error)
255*07dc1947SRichard Lowe {
256*07dc1947SRichard Lowe     if( len == 0) {
257*07dc1947SRichard Lowe         return DW_DLV_OK;
258*07dc1947SRichard Lowe     }
259*07dc1947SRichard Lowe     if(fde->fde_block || fde->fde_inst) {
260*07dc1947SRichard Lowe         DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
261*07dc1947SRichard Lowe             (int)DW_DLV_BADADDR);
262*07dc1947SRichard Lowe     }
263*07dc1947SRichard Lowe     fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
264*07dc1947SRichard Lowe     memcpy(fde->fde_block,ibytes,len);
265*07dc1947SRichard Lowe     fde->fde_inst_block_size = len;
266*07dc1947SRichard Lowe     fde->fde_n_bytes += len;
267*07dc1947SRichard Lowe     return DW_DLV_OK;
268*07dc1947SRichard Lowe }
269*07dc1947SRichard Lowe 
270*07dc1947SRichard Lowe 
27149d3bc91SRichard Lowe 
27249d3bc91SRichard Lowe /*-------------------------------------------------------------------
273*07dc1947SRichard Lowe         Create a new fde.
27449d3bc91SRichard Lowe ---------------------------------------------------------------------*/
27549d3bc91SRichard Lowe Dwarf_P_Fde
dwarf_new_fde(Dwarf_P_Debug dbg,Dwarf_Error * error)27649d3bc91SRichard Lowe dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
27749d3bc91SRichard Lowe {
27849d3bc91SRichard Lowe     Dwarf_P_Fde fde;
27949d3bc91SRichard Lowe 
28049d3bc91SRichard Lowe     fde = (Dwarf_P_Fde)
28149d3bc91SRichard Lowe         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
28249d3bc91SRichard Lowe     if (fde == NULL) {
28349d3bc91SRichard Lowe         DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
28449d3bc91SRichard Lowe                           (Dwarf_P_Fde) DW_DLV_BADADDR);
28549d3bc91SRichard Lowe     }
286*07dc1947SRichard Lowe 
28749d3bc91SRichard Lowe     fde->fde_uwordb_size = dbg->de_offset_size;
288*07dc1947SRichard Lowe 
28949d3bc91SRichard Lowe     return fde;
29049d3bc91SRichard Lowe }
29149d3bc91SRichard Lowe 
292*07dc1947SRichard Lowe 
29349d3bc91SRichard Lowe /*------------------------------------------------------------------------
294*07dc1947SRichard Lowe         Add a cfe_offset instruction to the fde passed in.
29549d3bc91SRichard Lowe -------------------------------------------------------------------------*/
29649d3bc91SRichard Lowe Dwarf_P_Fde
dwarf_fde_cfa_offset(Dwarf_P_Fde fde,Dwarf_Unsigned reg,Dwarf_Signed offset,Dwarf_Error * error)29749d3bc91SRichard Lowe dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
29849d3bc91SRichard Lowe                      Dwarf_Unsigned reg,
29949d3bc91SRichard Lowe                      Dwarf_Signed offset, Dwarf_Error * error)
30049d3bc91SRichard Lowe {
30149d3bc91SRichard Lowe     Dwarf_Ubyte opc, regno;
30249d3bc91SRichard Lowe     char *ptr;
30349d3bc91SRichard Lowe     Dwarf_P_Frame_Pgm curinst;
30449d3bc91SRichard Lowe     int nbytes;
30549d3bc91SRichard Lowe     int res;
30649d3bc91SRichard Lowe     char buff1[ENCODE_SPACE_NEEDED];
307*07dc1947SRichard Lowe     Dwarf_P_Debug dbg = fde->fde_dbg;
30849d3bc91SRichard Lowe 
30949d3bc91SRichard Lowe     curinst = (Dwarf_P_Frame_Pgm)
310*07dc1947SRichard Lowe         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
31149d3bc91SRichard Lowe     if (curinst == NULL) {
312*07dc1947SRichard Lowe         DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC,
31349d3bc91SRichard Lowe                           (Dwarf_P_Fde) DW_DLV_BADADDR);
31449d3bc91SRichard Lowe     }
31549d3bc91SRichard Lowe     opc = DW_CFA_offset;
31649d3bc91SRichard Lowe     regno = reg;
31749d3bc91SRichard Lowe     if (regno & 0xc0) {
318*07dc1947SRichard Lowe         DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
31949d3bc91SRichard Lowe                           (Dwarf_P_Fde) DW_DLV_BADADDR);
32049d3bc91SRichard Lowe     }
32149d3bc91SRichard Lowe     opc = opc | regno;          /* lower 6 bits are register number */
32249d3bc91SRichard Lowe     curinst->dfp_opcode = opc;
32349d3bc91SRichard Lowe     res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
32449d3bc91SRichard Lowe                                       buff1, sizeof(buff1));
32549d3bc91SRichard Lowe     if (res != DW_DLV_OK) {
326*07dc1947SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
32749d3bc91SRichard Lowe         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
32849d3bc91SRichard Lowe     }
329*07dc1947SRichard Lowe     ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
33049d3bc91SRichard Lowe     if (ptr == NULL) {
331*07dc1947SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
33249d3bc91SRichard Lowe         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
33349d3bc91SRichard Lowe     }
33449d3bc91SRichard Lowe     memcpy(ptr, buff1, nbytes);
33549d3bc91SRichard Lowe 
33649d3bc91SRichard Lowe     curinst->dfp_args = ptr;
33749d3bc91SRichard Lowe     curinst->dfp_nbytes = nbytes;
33849d3bc91SRichard Lowe     curinst->dfp_next = NULL;
33949d3bc91SRichard Lowe 
34049d3bc91SRichard Lowe     _dwarf_pro_add_to_fde(fde, curinst);
34149d3bc91SRichard Lowe     return fde;
34249d3bc91SRichard Lowe }
34349d3bc91SRichard Lowe 
34449d3bc91SRichard Lowe /*
34549d3bc91SRichard Lowe     Generic routine to add opcode to fde instructions. val1 and
34649d3bc91SRichard Lowe     val2 are parameters whose interpretation depends on the 'op'.
34749d3bc91SRichard Lowe 
34849d3bc91SRichard Lowe     This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
34949d3bc91SRichard Lowe     for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
35049d3bc91SRichard Lowe     these ops normally are addresses or (DW_CFA_set_loc)
35149d3bc91SRichard Lowe     or code lengths (DW_DVA_advance_loc*) and such must be
35249d3bc91SRichard Lowe     represented with relocations and symbol indices for
35349d3bc91SRichard Lowe     DW_DLC_SYMBOLIC_RELOCATIONS.
35449d3bc91SRichard Lowe 
355*07dc1947SRichard Lowe     This does not treat all DW_CFA instructions yet.
356*07dc1947SRichard Lowe 
357*07dc1947SRichard Lowe     For certain operations a val? value must be
358*07dc1947SRichard Lowe     signed (though passed in as unsigned here).
359*07dc1947SRichard Lowe 
360*07dc1947SRichard Lowe     Currently this does not check that the frame
361*07dc1947SRichard Lowe     version is 3(for dwarf3) or 4 (for dwarf4)
362*07dc1947SRichard Lowe     when applying operations that are only valid for
363*07dc1947SRichard Lowe     dwarf3 or dwarf4.
364*07dc1947SRichard Lowe 
36549d3bc91SRichard Lowe */
36649d3bc91SRichard Lowe Dwarf_P_Fde
dwarf_add_fde_inst(Dwarf_P_Fde fde,Dwarf_Small op,Dwarf_Unsigned val1,Dwarf_Unsigned val2,Dwarf_Error * error)36749d3bc91SRichard Lowe dwarf_add_fde_inst(Dwarf_P_Fde fde,
36849d3bc91SRichard Lowe                    Dwarf_Small op,
36949d3bc91SRichard Lowe                    Dwarf_Unsigned val1,
37049d3bc91SRichard Lowe                    Dwarf_Unsigned val2, Dwarf_Error * error)
37149d3bc91SRichard Lowe {
37249d3bc91SRichard Lowe     Dwarf_P_Frame_Pgm curinst;
37349d3bc91SRichard Lowe     int nbytes, nbytes1, nbytes2;
37449d3bc91SRichard Lowe     Dwarf_Ubyte db;
37549d3bc91SRichard Lowe     Dwarf_Half dh;
37649d3bc91SRichard Lowe     Dwarf_Word dw;
37749d3bc91SRichard Lowe     Dwarf_Unsigned du;
37849d3bc91SRichard Lowe     char *ptr;
37949d3bc91SRichard Lowe     int res;
38049d3bc91SRichard Lowe     char buff1[ENCODE_SPACE_NEEDED];
38149d3bc91SRichard Lowe     char buff2[ENCODE_SPACE_NEEDED];
382*07dc1947SRichard Lowe     Dwarf_P_Debug dbg = fde->fde_dbg;
383*07dc1947SRichard Lowe     /* This is a hack telling the code when to transform
384*07dc1947SRichard Lowe        a value to a signed leb number. */
385*07dc1947SRichard Lowe     int signed_second = 0;
386*07dc1947SRichard Lowe     int signed_first = 0;
38749d3bc91SRichard Lowe 
38849d3bc91SRichard Lowe 
38949d3bc91SRichard Lowe     nbytes = 0;
39049d3bc91SRichard Lowe     ptr = NULL;
39149d3bc91SRichard Lowe     curinst = (Dwarf_P_Frame_Pgm)
392*07dc1947SRichard Lowe         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
39349d3bc91SRichard Lowe     if (curinst == NULL) {
394*07dc1947SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
39549d3bc91SRichard Lowe         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
39649d3bc91SRichard Lowe     }
39749d3bc91SRichard Lowe 
39849d3bc91SRichard Lowe     switch (op) {
39949d3bc91SRichard Lowe 
40049d3bc91SRichard Lowe     case DW_CFA_advance_loc:
40149d3bc91SRichard Lowe         if (val1 <= 0x3f) {
40249d3bc91SRichard Lowe             db = val1;
40349d3bc91SRichard Lowe             op |= db;
40449d3bc91SRichard Lowe         }
40549d3bc91SRichard Lowe         /* test not portable FIX */
40649d3bc91SRichard Lowe         else if (val1 <= UCHAR_MAX) {
40749d3bc91SRichard Lowe             op = DW_CFA_advance_loc1;
40849d3bc91SRichard Lowe             db = val1;
409*07dc1947SRichard Lowe             ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
41049d3bc91SRichard Lowe             if (ptr == NULL) {
411*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
41249d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
41349d3bc91SRichard Lowe             }
41449d3bc91SRichard Lowe             memcpy((void *) ptr, (const void *) &db, 1);
41549d3bc91SRichard Lowe             nbytes = 1;
41649d3bc91SRichard Lowe         }
41749d3bc91SRichard Lowe         /* test not portable FIX */
41849d3bc91SRichard Lowe         else if (val1 <= USHRT_MAX) {
41949d3bc91SRichard Lowe             op = DW_CFA_advance_loc2;
42049d3bc91SRichard Lowe             dh = val1;
421*07dc1947SRichard Lowe             ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
42249d3bc91SRichard Lowe             if (ptr == NULL) {
423*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
42449d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
42549d3bc91SRichard Lowe             }
42649d3bc91SRichard Lowe             memcpy((void *) ptr, (const void *) &dh, 2);
42749d3bc91SRichard Lowe             nbytes = 2;
42849d3bc91SRichard Lowe         }
42949d3bc91SRichard Lowe         /* test not portable FIX */
43049d3bc91SRichard Lowe         else if (val1 <= ULONG_MAX) {
43149d3bc91SRichard Lowe             op = DW_CFA_advance_loc4;
43249d3bc91SRichard Lowe             dw = (Dwarf_Word) val1;
433*07dc1947SRichard Lowe             ptr = (char *) _dwarf_p_get_alloc(dbg, 4);
43449d3bc91SRichard Lowe             if (ptr == NULL) {
435*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
43649d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
43749d3bc91SRichard Lowe             }
43849d3bc91SRichard Lowe             memcpy((void *) ptr, (const void *) &dw, 4);
43949d3bc91SRichard Lowe             nbytes = 4;
44049d3bc91SRichard Lowe         } else {
44149d3bc91SRichard Lowe             op = DW_CFA_MIPS_advance_loc8;
44249d3bc91SRichard Lowe             du = val1;
44349d3bc91SRichard Lowe             ptr =
444*07dc1947SRichard Lowe                 (char *) _dwarf_p_get_alloc(dbg,
44549d3bc91SRichard Lowe                                             sizeof(Dwarf_Unsigned));
44649d3bc91SRichard Lowe             if (ptr == NULL) {
447*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
44849d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
44949d3bc91SRichard Lowe             }
45049d3bc91SRichard Lowe             memcpy((void *) ptr, (const void *) &du, 8);
45149d3bc91SRichard Lowe             nbytes = 8;
45249d3bc91SRichard Lowe         }
45349d3bc91SRichard Lowe         break;
45449d3bc91SRichard Lowe 
45549d3bc91SRichard Lowe     case DW_CFA_offset:
45649d3bc91SRichard Lowe         if (val1 <= MAX_6_BIT_VALUE) {
45749d3bc91SRichard Lowe             db = val1;
45849d3bc91SRichard Lowe             op |= db;
45949d3bc91SRichard Lowe             res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
46049d3bc91SRichard Lowe                                               buff1, sizeof(buff1));
46149d3bc91SRichard Lowe             if (res != DW_DLV_OK) {
462*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
46349d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
46449d3bc91SRichard Lowe             }
465*07dc1947SRichard Lowe             ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
46649d3bc91SRichard Lowe             if (ptr == NULL) {
467*07dc1947SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
46849d3bc91SRichard Lowe                 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
46949d3bc91SRichard Lowe             }
47049d3bc91SRichard Lowe             memcpy(ptr, buff1, nbytes);
47149d3bc91SRichard Lowe 
47249d3bc91SRichard Lowe         } else {
47349d3bc91SRichard Lowe             op = DW_CFA_offset_extended;
474*07dc1947SRichard Lowe             goto two_leb;
47549d3bc91SRichard Lowe         }
47649d3bc91SRichard Lowe         break;
477*07dc1947SRichard Lowe     case DW_CFA_offset_extended_sf: /* DWARF3 */
478*07dc1947SRichard Lowe             signed_second = 1;
479*07dc1947SRichard Lowe             goto two_leb;
480*07dc1947SRichard Lowe     case DW_CFA_offset_extended:
481*07dc1947SRichard Lowe             goto two_leb;
48249d3bc91SRichard Lowe 
48349d3bc91SRichard Lowe     case DW_CFA_undefined:
48449d3bc91SRichard Lowe     case DW_CFA_same_value:
485*07dc1947SRichard Lowe         goto one_leb;
48649d3bc91SRichard Lowe 
487*07dc1947SRichard Lowe     case DW_CFA_val_offset:
488*07dc1947SRichard Lowe          goto two_leb;
489*07dc1947SRichard Lowe     case DW_CFA_val_offset_sf:
490*07dc1947SRichard Lowe          signed_second = 1;
491*07dc1947SRichard Lowe          goto two_leb;
492*07dc1947SRichard Lowe     case DW_CFA_def_cfa_sf:
493*07dc1947SRichard Lowe          signed_second = 1;
494*07dc1947SRichard Lowe          goto two_leb;
49549d3bc91SRichard Lowe     case DW_CFA_register:
49649d3bc91SRichard Lowe     case DW_CFA_def_cfa:
497*07dc1947SRichard Lowe     two_leb:
49849d3bc91SRichard Lowe         res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
49949d3bc91SRichard Lowe                                           buff1, sizeof(buff1));
50049d3bc91SRichard Lowe         if (res != DW_DLV_OK) {
501*07dc1947SRichard Lowe             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
50249d3bc91SRichard Lowe             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
50349d3bc91SRichard Lowe         }
504*07dc1947SRichard Lowe         if (!signed_second) {
505*07dc1947SRichard Lowe                 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
506*07dc1947SRichard Lowe                                               buff2, sizeof(buff2));
507*07dc1947SRichard Lowe         } else {
508*07dc1947SRichard Lowe             Dwarf_Signed val2s = val2;
509*07dc1947SRichard Lowe             res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
510*07dc1947SRichard Lowe                                               buff2, sizeof(buff2));
511*07dc1947SRichard Lowe         }
51249d3bc91SRichard Lowe 
51349d3bc91SRichard Lowe         res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
51449d3bc91SRichard Lowe                                           buff2, sizeof(buff2));
51549d3bc91SRichard Lowe         if (res != DW_DLV_OK) {
516*07dc1947SRichard Lowe             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
51749d3bc91SRichard Lowe             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
51849d3bc91SRichard Lowe         }
51949d3bc91SRichard Lowe 
520*07dc1947SRichard Lowe         ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
52149d3bc91SRichard Lowe         if (ptr == NULL) {
522*07dc1947SRichard Lowe             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
52349d3bc91SRichard Lowe             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
52449d3bc91SRichard Lowe         }
52549d3bc91SRichard Lowe         memcpy(ptr, buff1, nbytes1);
52649d3bc91SRichard Lowe         memcpy(ptr + nbytes1, buff2, nbytes2);
52749d3bc91SRichard Lowe         nbytes = nbytes1 + nbytes2;
52849d3bc91SRichard Lowe         break;
52949d3bc91SRichard Lowe 
530*07dc1947SRichard Lowe     case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
531*07dc1947SRichard Lowe         signed_first = 1;
532*07dc1947SRichard Lowe         goto one_leb;
53349d3bc91SRichard Lowe     case DW_CFA_def_cfa_register:
53449d3bc91SRichard Lowe     case DW_CFA_def_cfa_offset:
535*07dc1947SRichard Lowe     one_leb:
536*07dc1947SRichard Lowe         if(!signed_first) {
53749d3bc91SRichard Lowe             res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
53849d3bc91SRichard Lowe                                           buff1, sizeof(buff1));
539*07dc1947SRichard Lowe         } else {
540*07dc1947SRichard Lowe             Dwarf_Signed val1s = val1;
541*07dc1947SRichard Lowe             res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
542*07dc1947SRichard Lowe                                           buff1, sizeof(buff1));
543*07dc1947SRichard Lowe         }
54449d3bc91SRichard Lowe         if (res != DW_DLV_OK) {
545*07dc1947SRichard Lowe             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
54649d3bc91SRichard Lowe             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
54749d3bc91SRichard Lowe         }
548*07dc1947SRichard Lowe         ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
54949d3bc91SRichard Lowe         if (ptr == NULL) {
550*07dc1947SRichard Lowe             _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
55149d3bc91SRichard Lowe             return ((Dwarf_P_Fde) DW_DLV_BADADDR);
55249d3bc91SRichard Lowe         }
55349d3bc91SRichard Lowe         memcpy(ptr, buff1, nbytes);
55449d3bc91SRichard Lowe         break;
555*07dc1947SRichard Lowe     case DW_CFA_def_cfa_expression: /* DWARF3 */
556*07dc1947SRichard Lowe         /* FIXME: argument is dwarf expr, not handled yet. */
557*07dc1947SRichard Lowe     case DW_CFA_expression: /* DWARF3 */
558*07dc1947SRichard Lowe         /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
559*07dc1947SRichard Lowe            FIXME: not handled yet. */
560*07dc1947SRichard Lowe     case DW_CFA_val_expression: /* DWARF3f */
561*07dc1947SRichard Lowe         /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
562*07dc1947SRichard Lowe            FIXME: not handled yet. */
56349d3bc91SRichard Lowe     default:
564*07dc1947SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
565*07dc1947SRichard Lowe         return ((Dwarf_P_Fde) DW_DLV_BADADDR);
56649d3bc91SRichard Lowe     }
56749d3bc91SRichard Lowe 
56849d3bc91SRichard Lowe     curinst->dfp_opcode = op;
56949d3bc91SRichard Lowe     curinst->dfp_args = ptr;
57049d3bc91SRichard Lowe     curinst->dfp_nbytes = nbytes;
57149d3bc91SRichard Lowe     curinst->dfp_next = NULL;
57249d3bc91SRichard Lowe 
57349d3bc91SRichard Lowe     _dwarf_pro_add_to_fde(fde, curinst);
57449d3bc91SRichard Lowe     return fde;
57549d3bc91SRichard Lowe }
57649d3bc91SRichard Lowe 
57749d3bc91SRichard Lowe 
57849d3bc91SRichard Lowe /*------------------------------------------------------------------------
579*07dc1947SRichard Lowe         Instructions are added to an fde in the form of a linked
580*07dc1947SRichard Lowe         list. This function manages the linked list.
58149d3bc91SRichard Lowe -------------------------------------------------------------------------*/
58249d3bc91SRichard Lowe void
_dwarf_pro_add_to_fde(Dwarf_P_Fde fde,Dwarf_P_Frame_Pgm curinst)58349d3bc91SRichard Lowe _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
58449d3bc91SRichard Lowe {
58549d3bc91SRichard Lowe     if (fde->fde_last_inst) {
58649d3bc91SRichard Lowe         fde->fde_last_inst->dfp_next = curinst;
58749d3bc91SRichard Lowe         fde->fde_last_inst = curinst;
58849d3bc91SRichard Lowe         fde->fde_n_inst++;
58949d3bc91SRichard Lowe         fde->fde_n_bytes +=
59049d3bc91SRichard Lowe             (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
59149d3bc91SRichard Lowe     } else {
59249d3bc91SRichard Lowe         fde->fde_last_inst = curinst;
59349d3bc91SRichard Lowe         fde->fde_inst = curinst;
59449d3bc91SRichard Lowe         fde->fde_n_inst = 1;
59549d3bc91SRichard Lowe         fde->fde_n_bytes =
59649d3bc91SRichard Lowe             (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
59749d3bc91SRichard Lowe     }
59849d3bc91SRichard Lowe }
599