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