149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
449d3bc9Richard Lowe
549d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
649d3bc9Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
749d3bc9Richard Lowe  as published by the Free Software Foundation.
849d3bc9Richard Lowe
949d3bc9Richard Lowe  This program is distributed in the hope that it would be useful, but
1049d3bc9Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1249d3bc9Richard Lowe
1349d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
1449d3bc9Richard Lowe  free of the rightful claim of any third person regarding infringement
1549d3bc9Richard Lowe  or the like.  Any license provided herein, whether implied or
1649d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1749d3bc9Richard Lowe  any, provided herein do not apply to combinations of this program with
1849d3bc9Richard Lowe  other software, or any other product whatsoever.
1949d3bc9Richard Lowe
2049d3bc9Richard Lowe  You should have received a copy of the GNU Lesser General Public
2149d3bc9Richard Lowe  License along with this program; if not, write the Free Software
2207dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2349d3bc9Richard Lowe  USA.
2449d3bc9Richard Lowe
2507dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2649d3bc9Richard Lowe  Mountain View, CA 94043, or:
2749d3bc9Richard Lowe
2849d3bc9Richard Lowe  http://www.sgi.com
2949d3bc9Richard Lowe
3049d3bc9Richard Lowe  For further information regarding this notice, see:
3149d3bc9Richard Lowe
3249d3bc9Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3349d3bc9Richard Lowe
3449d3bc9Richard Lowe*/
3549d3bc9Richard Lowe
3649d3bc9Richard Lowe
3749d3bc9Richard Lowe
3849d3bc9Richard Lowe#include "config.h"
3949d3bc9Richard Lowe#include "libdwarfdefs.h"
4049d3bc9Richard Lowe#include <stdio.h>
4149d3bc9Richard Lowe#include <string.h>
4249d3bc9Richard Lowe#include <limits.h>
4349d3bc9Richard Lowe#include "pro_incl.h"
4449d3bc9Richard Lowe#include "pro_frame.h"
4549d3bc9Richard Lowe
4649d3bc9Richard Lowestatic void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
4707dc194Richard Lowe                                  Dwarf_P_Frame_Pgm inst);
4849d3bc9Richard Lowe
4949d3bc9Richard Lowe/*-------------------------------------------------------------------------
5007dc194Richard Lowe        This function adds a cie struct to the debug pointer. Its in the
5107dc194Richard Lowe        form of a linked list.
5207dc194Richard Lowe        augmenter: string reps augmentation (implementation defined)
5307dc194Richard Lowe        code_align: alignment of code
5407dc194Richard Lowe        data_align: alignment of data
5507dc194Richard Lowe        init_bytes: byts having initial instructions
5607dc194Richard Lowe        init_n_bytes: number of bytes of initial instructions
5749d3bc9Richard Lowe--------------------------------------------------------------------------*/
5849d3bc9Richard LoweDwarf_Unsigned
5949d3bc9Richard Lowedwarf_add_frame_cie(Dwarf_P_Debug dbg,
6007dc194Richard Lowe                    char *augmenter,
6107dc194Richard Lowe                    Dwarf_Small code_align,
6207dc194Richard Lowe                    Dwarf_Small data_align,
6307dc194Richard Lowe                    Dwarf_Small return_reg,
6407dc194Richard Lowe                    Dwarf_Ptr init_bytes,
6507dc194Richard Lowe                    Dwarf_Unsigned init_n_bytes, Dwarf_Error * error)
6649d3bc9Richard Lowe{
6749d3bc9Richard Lowe    Dwarf_P_Cie curcie;
6849d3bc9Richard Lowe
6949d3bc9Richard Lowe    if (dbg->de_frame_cies == NULL) {
7007dc194Richard Lowe        dbg->de_frame_cies = (Dwarf_P_Cie)
7107dc194Richard Lowe            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
7207dc194Richard Lowe        if (dbg->de_frame_cies == NULL) {
7307dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
7407dc194Richard Lowe        }
7507dc194Richard Lowe        curcie = dbg->de_frame_cies;
7607dc194Richard Lowe        dbg->de_n_cie = 1;
7707dc194Richard Lowe        dbg->de_last_cie = curcie;
7849d3bc9Richard Lowe    } else {
7907dc194Richard Lowe        curcie = dbg->de_last_cie;
8007dc194Richard Lowe        curcie->cie_next = (Dwarf_P_Cie)
8107dc194Richard Lowe            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
8207dc194Richard Lowe        if (curcie->cie_next == NULL) {
8307dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
8407dc194Richard Lowe        }
8507dc194Richard Lowe        curcie = curcie->cie_next;
8607dc194Richard Lowe        dbg->de_n_cie++;
8707dc194Richard Lowe        dbg->de_last_cie = curcie;
8849d3bc9Richard Lowe    }
8949d3bc9Richard Lowe    curcie->cie_version = DW_CIE_VERSION;
9049d3bc9Richard Lowe    curcie->cie_aug = augmenter;
9149d3bc9Richard Lowe    curcie->cie_code_align = code_align;
9249d3bc9Richard Lowe    curcie->cie_data_align = data_align;
9349d3bc9Richard Lowe    curcie->cie_ret_reg = return_reg;
9449d3bc9Richard Lowe    curcie->cie_inst = (char *) init_bytes;
9549d3bc9Richard Lowe    curcie->cie_inst_bytes = (long) init_n_bytes;
9649d3bc9Richard Lowe    curcie->cie_next = NULL;
9749d3bc9Richard Lowe    return dbg->de_n_cie;
9849d3bc9Richard Lowe}
9949d3bc9Richard Lowe
10049d3bc9Richard Lowe
10149d3bc9Richard Lowe/*-------------------------------------------------------------------------
10207dc194Richard Lowe        This functions adds a fde struct to the debug pointer. Its in the
10307dc194Richard Lowe        form of a linked list.
10407dc194Richard Lowe        die: subprogram/function die corresponding to this fde
10507dc194Richard Lowe        cie: cie referred to by this fde, obtained from call to
10607dc194Richard Lowe            add_frame_cie() routine.
10707dc194Richard Lowe        virt_addr: beginning address
10807dc194Richard Lowe        code_len: length of code reps by the fde
10949d3bc9Richard Lowe--------------------------------------------------------------------------*/
11007dc194Richard Lowe /*ARGSUSED*/                   /* pretend all args used */
11149d3bc9Richard Lowe    Dwarf_Unsigned
11249d3bc9Richard Lowedwarf_add_frame_fde(Dwarf_P_Debug dbg,
11307dc194Richard Lowe                    Dwarf_P_Fde fde,
11407dc194Richard Lowe                    Dwarf_P_Die die,
11507dc194Richard Lowe                    Dwarf_Unsigned cie,
11607dc194Richard Lowe                    Dwarf_Unsigned virt_addr,
11707dc194Richard Lowe                    Dwarf_Unsigned code_len,
11807dc194Richard Lowe                    Dwarf_Unsigned symidx, Dwarf_Error * error)
11949d3bc9Richard Lowe{
12049d3bc9Richard Lowe    return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr,
12107dc194Richard Lowe                                 code_len, symidx, 0, 0, error);
12249d3bc9Richard Lowe}
12349d3bc9Richard Lowe
12449d3bc9Richard Lowe/*ARGSUSED10*/
12549d3bc9Richard LoweDwarf_Unsigned
12649d3bc9Richard Lowedwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
12707dc194Richard Lowe                      Dwarf_P_Fde fde,
12807dc194Richard Lowe                      Dwarf_P_Die die,
12907dc194Richard Lowe                      Dwarf_Unsigned cie,
13007dc194Richard Lowe                      Dwarf_Unsigned virt_addr,
13107dc194Richard Lowe                      Dwarf_Unsigned code_len,
13207dc194Richard Lowe                      Dwarf_Unsigned symidx,
13307dc194Richard Lowe                      Dwarf_Unsigned symidx_of_end,
13407dc194Richard Lowe                      Dwarf_Addr offset_from_end_sym,
13507dc194Richard Lowe                      Dwarf_Error * error)
13649d3bc9Richard Lowe{
13749d3bc9Richard Lowe    Dwarf_P_Fde curfde;
13849d3bc9Richard Lowe
13949d3bc9Richard Lowe    fde->fde_die = die;
14049d3bc9Richard Lowe    fde->fde_cie = (long) cie;
14149d3bc9Richard Lowe    fde->fde_initloc = virt_addr;
14249d3bc9Richard Lowe    fde->fde_r_symidx = symidx;
14349d3bc9Richard Lowe    fde->fde_addr_range = code_len;
14449d3bc9Richard Lowe    fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
14549d3bc9Richard Lowe    fde->fde_exception_table_symbol = 0;
14649d3bc9Richard Lowe    fde->fde_end_symbol_offset = offset_from_end_sym;
14749d3bc9Richard Lowe    fde->fde_end_symbol = symidx_of_end;
14807dc194Richard Lowe    fde->fde_dbg = dbg;
14949d3bc9Richard Lowe
15049d3bc9Richard Lowe    curfde = dbg->de_last_fde;
15149d3bc9Richard Lowe    if (curfde == NULL) {
15207dc194Richard Lowe        dbg->de_frame_fdes = fde;
15307dc194Richard Lowe        dbg->de_last_fde = fde;
15407dc194Richard Lowe        dbg->de_n_fde = 1;
15549d3bc9Richard Lowe    } else {
15607dc194Richard Lowe        curfde->fde_next = fde;
15707dc194Richard Lowe        dbg->de_last_fde = fde;
15807dc194Richard Lowe        dbg->de_n_fde++;
15949d3bc9Richard Lowe    }
16049d3bc9Richard Lowe    return dbg->de_n_fde;
16149d3bc9Richard Lowe}
16249d3bc9Richard Lowe
16349d3bc9Richard Lowe/*-------------------------------------------------------------------------
16407dc194Richard Lowe        This functions adds information to an fde. The fde is
16507dc194Richard Lowe        linked into the linked list of fde's maintained in the Dwarf_P_Debug
16607dc194Richard Lowe        structure.
16707dc194Richard Lowe        dbg: The debug descriptor.
16807dc194Richard Lowe        fde: The fde to be added.
16907dc194Richard Lowe        die: subprogram/function die corresponding to this fde
17007dc194Richard Lowe        cie: cie referred to by this fde, obtained from call to
17107dc194Richard Lowe            add_frame_cie() routine.
17207dc194Richard Lowe        virt_addr: beginning address
17307dc194Richard Lowe        code_len: length of code reps by the fde
17407dc194Richard Lowe        symidx: The symbol id of the symbol wrt to which relocation needs
17507dc194Richard Lowe                to be performed for 'virt_addr'.
17607dc194Richard Lowe        offset_into_exception_tables: The start of exception tables for
17707dc194Richard Lowe                this function (indicated as an offset into the exception
17807dc194Richard Lowe                tables). A value of -1 indicates that there is no exception
17907dc194Richard Lowe                table entries associated with this function.
18007dc194Richard Lowe        exception_table_symbol: The symbol id of the section for exception
18107dc194Richard Lowe                tables wrt to which the offset_into_exception_tables will
18207dc194Richard Lowe                be relocated.
18349d3bc9Richard Lowe--------------------------------------------------------------------------*/
18449d3bc9Richard LoweDwarf_Unsigned
18549d3bc9Richard Lowedwarf_add_frame_info(Dwarf_P_Debug dbg,
18607dc194Richard Lowe                     Dwarf_P_Fde fde,
18707dc194Richard Lowe                     Dwarf_P_Die die,
18807dc194Richard Lowe                     Dwarf_Unsigned cie,
18907dc194Richard Lowe                     Dwarf_Unsigned virt_addr,
19007dc194Richard Lowe                     Dwarf_Unsigned code_len,
19107dc194Richard Lowe                     Dwarf_Unsigned symidx,
19207dc194Richard Lowe                     Dwarf_Signed offset_into_exception_tables,
19307dc194Richard Lowe                     Dwarf_Unsigned exception_table_symbol,
19407dc194Richard Lowe                     Dwarf_Error * error)
19549d3bc9Richard Lowe{
19649d3bc9Richard Lowe
19749d3bc9Richard Lowe    return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
19807dc194Richard Lowe                                  code_len, symidx,
19907dc194Richard Lowe                                  /* end_symbol */ 0,
20007dc194Richard Lowe                                  /* offset_from_end */ 0,
20107dc194Richard Lowe                                  offset_into_exception_tables,
20207dc194Richard Lowe                                  exception_table_symbol, error);
20349d3bc9Richard Lowe
20449d3bc9Richard Lowe}
20549d3bc9Richard Lowe
20607dc194Richard Lowe /*ARGSUSED*/                   /* pretend all args used */
20707dc194Richard LoweDwarf_Unsigned
20849d3bc9Richard Lowedwarf_add_frame_info_b(Dwarf_P_Debug dbg,
20907dc194Richard Lowe                       Dwarf_P_Fde fde,
21007dc194Richard Lowe                       Dwarf_P_Die die,
21107dc194Richard Lowe                       Dwarf_Unsigned cie,
21207dc194Richard Lowe                       Dwarf_Unsigned virt_addr,
21307dc194Richard Lowe                       Dwarf_Unsigned code_len,
21407dc194Richard Lowe                       Dwarf_Unsigned symidx,
21507dc194Richard Lowe                       Dwarf_Unsigned end_symidx,
21607dc194Richard Lowe                       Dwarf_Unsigned offset_from_end_symbol,
21707dc194Richard Lowe                       Dwarf_Signed offset_into_exception_tables,
21807dc194Richard Lowe                       Dwarf_Unsigned exception_table_symbol,
21907dc194Richard Lowe                       Dwarf_Error * error)
22049d3bc9Richard Lowe{
22149d3bc9Richard Lowe    Dwarf_P_Fde curfde;
22249d3bc9Richard Lowe
22349d3bc9Richard Lowe    fde->fde_die = die;
22449d3bc9Richard Lowe    fde->fde_cie = (long) cie;
22549d3bc9Richard Lowe    fde->fde_initloc = virt_addr;
22649d3bc9Richard Lowe    fde->fde_r_symidx = symidx;
22749d3bc9Richard Lowe    fde->fde_addr_range = code_len;
22849d3bc9Richard Lowe    fde->fde_offset_into_exception_tables =
22907dc194Richard Lowe        offset_into_exception_tables;
23049d3bc9Richard Lowe    fde->fde_exception_table_symbol = exception_table_symbol;
23149d3bc9Richard Lowe    fde->fde_end_symbol_offset = offset_from_end_symbol;
23249d3bc9Richard Lowe    fde->fde_end_symbol = end_symidx;
23307dc194Richard Lowe    fde->fde_dbg = dbg;
23449d3bc9Richard Lowe
23549d3bc9Richard Lowe    curfde = dbg->de_last_fde;
23649d3bc9Richard Lowe    if (curfde == NULL) {
23707dc194Richard Lowe        dbg->de_frame_fdes = fde;
23807dc194Richard Lowe        dbg->de_last_fde = fde;
23907dc194Richard Lowe        dbg->de_n_fde = 1;
24049d3bc9Richard Lowe    } else {
24107dc194Richard Lowe        curfde->fde_next = fde;
24207dc194Richard Lowe        dbg->de_last_fde = fde;
24307dc194Richard Lowe        dbg->de_n_fde++;
24449d3bc9Richard Lowe    }
24549d3bc9Richard Lowe    return dbg->de_n_fde;
24649d3bc9Richard Lowe}
24749d3bc9Richard Lowe
24807dc194Richard Lowe/* This is an alternate to inserting frame instructions
24907dc194Richard Lowe   one instruction at a time.  But use either this
25007dc194Richard Lowe   or instruction level, not both in one fde. */
25107dc194Richard Loweint
25207dc194Richard Lowedwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
25307dc194Richard Lowe    Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
25407dc194Richard Lowe    Dwarf_Error *error)
25507dc194Richard Lowe{
25607dc194Richard Lowe    if( len == 0) {
25707dc194Richard Lowe        return DW_DLV_OK;
25807dc194Richard Lowe    }
25907dc194Richard Lowe    if(fde->fde_block || fde->fde_inst) {
26007dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
26107dc194Richard Lowe            (int)DW_DLV_BADADDR);
26207dc194Richard Lowe    }
26307dc194Richard Lowe    fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
26407dc194Richard Lowe    memcpy(fde->fde_block,ibytes,len);
26507dc194Richard Lowe    fde->fde_inst_block_size = len;
26607dc194Richard Lowe    fde->fde_n_bytes += len;
26707dc194Richard Lowe    return DW_DLV_OK;
26807dc194Richard Lowe}
26907dc194Richard Lowe
27007dc194Richard Lowe
27149d3bc9Richard Lowe
27249d3bc9Richard Lowe/*-------------------------------------------------------------------
27307dc194Richard Lowe        Create a new fde.
27449d3bc9Richard Lowe---------------------------------------------------------------------*/
27549d3bc9Richard LoweDwarf_P_Fde
27649d3bc9Richard Lowedwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
27749d3bc9Richard Lowe{
27849d3bc9Richard Lowe    Dwarf_P_Fde fde;
27949d3bc9Richard Lowe
28049d3bc9Richard Lowe    fde = (Dwarf_P_Fde)
28107dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
28249d3bc9Richard Lowe    if (fde == NULL) {
28307dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
28407dc194Richard Lowe                          (Dwarf_P_Fde) DW_DLV_BADADDR);
28549d3bc9Richard Lowe    }
28607dc194Richard Lowe
28749d3bc9Richard Lowe    fde->fde_uwordb_size = dbg->de_offset_size;
28807dc194Richard Lowe
28949d3bc9Richard Lowe    return fde;
29049d3bc9Richard Lowe}
29149d3bc9Richard Lowe
29207dc194Richard Lowe
29349d3bc9Richard Lowe/*------------------------------------------------------------------------
29407dc194Richard Lowe        Add a cfe_offset instruction to the fde passed in.
29549d3bc9Richard Lowe-------------------------------------------------------------------------*/
29649d3bc9Richard LoweDwarf_P_Fde
29749d3bc9Richard Lowedwarf_fde_cfa_offset(Dwarf_P_Fde fde,
29807dc194Richard Lowe                     Dwarf_Unsigned reg,
29907dc194Richard Lowe                     Dwarf_Signed offset, Dwarf_Error * error)
30049d3bc9Richard Lowe{
30149d3bc9Richard Lowe    Dwarf_Ubyte opc, regno;
30249d3bc9Richard Lowe    char *ptr;
30349d3bc9Richard Lowe    Dwarf_P_Frame_Pgm curinst;
30449d3bc9Richard Lowe    int nbytes;
30549d3bc9Richard Lowe    int res;
30649d3bc9Richard Lowe    char buff1[ENCODE_SPACE_NEEDED];
30707dc194Richard Lowe    Dwarf_P_Debug dbg = fde->fde_dbg;
30849d3bc9Richard Lowe
30949d3bc9Richard Lowe    curinst = (Dwarf_P_Frame_Pgm)
31007dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
31149d3bc9Richard Lowe    if (curinst == NULL) {
31207dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC,
31307dc194Richard Lowe                          (Dwarf_P_Fde) DW_DLV_BADADDR);
31449d3bc9Richard Lowe    }
31549d3bc9Richard Lowe    opc = DW_CFA_offset;
31649d3bc9Richard Lowe    regno = reg;
31749d3bc9Richard Lowe    if (regno & 0xc0) {
31807dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
31907dc194Richard Lowe                          (Dwarf_P_Fde) DW_DLV_BADADDR);
32049d3bc9Richard Lowe    }
32107dc194Richard Lowe    opc = opc | regno;          /* lower 6 bits are register number */
32249d3bc9Richard Lowe    curinst->dfp_opcode = opc;
32349d3bc9Richard Lowe    res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
32407dc194Richard Lowe                                      buff1, sizeof(buff1));
32549d3bc9Richard Lowe    if (res != DW_DLV_OK) {
32607dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
32707dc194Richard Lowe        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
32849d3bc9Richard Lowe    }
32907dc194Richard Lowe    ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
33049d3bc9Richard Lowe    if (ptr == NULL) {
33107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
33207dc194Richard Lowe        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
33349d3bc9Richard Lowe    }
33449d3bc9Richard Lowe    memcpy(ptr, buff1, nbytes);
33549d3bc9Richard Lowe
33649d3bc9Richard Lowe    curinst->dfp_args = ptr;
33749d3bc9Richard Lowe    curinst->dfp_nbytes = nbytes;
33849d3bc9Richard Lowe    curinst->dfp_next = NULL;
33949d3bc9Richard Lowe
34049d3bc9Richard Lowe    _dwarf_pro_add_to_fde(fde, curinst);
34149d3bc9Richard Lowe    return fde;
34249d3bc9Richard Lowe}
34349d3bc9Richard Lowe
34449d3bc9Richard Lowe/*
34549d3bc9Richard Lowe    Generic routine to add opcode to fde instructions. val1 and
34649d3bc9Richard Lowe    val2 are parameters whose interpretation depends on the 'op'.
34749d3bc9Richard Lowe
34849d3bc9Richard Lowe    This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
34949d3bc9Richard Lowe    for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
35049d3bc9Richard Lowe    these ops normally are addresses or (DW_CFA_set_loc)
35149d3bc9Richard Lowe    or code lengths (DW_DVA_advance_loc*) and such must be
35249d3bc9Richard Lowe    represented with relocations and symbol indices for
35349d3bc9Richard Lowe    DW_DLC_SYMBOLIC_RELOCATIONS.
35449d3bc9Richard Lowe
35507dc194Richard Lowe    This does not treat all DW_CFA instructions yet.
35607dc194Richard Lowe
35707dc194Richard Lowe    For certain operations a val? value must be
35807dc194Richard Lowe    signed (though passed in as unsigned here).
35907dc194Richard Lowe
36007dc194Richard Lowe    Currently this does not check that the frame
36107dc194Richard Lowe    version is 3(for dwarf3) or 4 (for dwarf4)
36207dc194Richard Lowe    when applying operations that are only valid for
36307dc194Richard Lowe    dwarf3 or dwarf4.
36407dc194Richard Lowe
36549d3bc9Richard Lowe*/
36649d3bc9Richard LoweDwarf_P_Fde
36749d3bc9Richard Lowedwarf_add_fde_inst(Dwarf_P_Fde fde,
36807dc194Richard Lowe                   Dwarf_Small op,
36907dc194Richard Lowe                   Dwarf_Unsigned val1,
37007dc194Richard Lowe                   Dwarf_Unsigned val2, Dwarf_Error * error)
37149d3bc9Richard Lowe{
37249d3bc9Richard Lowe    Dwarf_P_Frame_Pgm curinst;
37349d3bc9Richard Lowe    int nbytes, nbytes1, nbytes2;
37449d3bc9Richard Lowe    Dwarf_Ubyte db;
37549d3bc9Richard Lowe    Dwarf_Half dh;
37649d3bc9Richard Lowe    Dwarf_Word dw;
37749d3bc9Richard Lowe    Dwarf_Unsigned du;
37849d3bc9Richard Lowe    char *ptr;
37949d3bc9Richard Lowe    int res;
38049d3bc9Richard Lowe    char buff1[ENCODE_SPACE_NEEDED];
38149d3bc9Richard Lowe    char buff2[ENCODE_SPACE_NEEDED];
38207dc194Richard Lowe    Dwarf_P_Debug dbg = fde->fde_dbg;
38307dc194Richard Lowe    /* This is a hack telling the code when to transform
38407dc194Richard Lowe       a value to a signed leb number. */
38507dc194Richard Lowe    int signed_second = 0;
38607dc194Richard Lowe    int signed_first = 0;
38749d3bc9Richard Lowe
38849d3bc9Richard Lowe
38949d3bc9Richard Lowe    nbytes = 0;
39049d3bc9Richard Lowe    ptr = NULL;
39149d3bc9Richard Lowe    curinst = (Dwarf_P_Frame_Pgm)
39207dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
39349d3bc9Richard Lowe    if (curinst == NULL) {
39407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
39507dc194Richard Lowe        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
39649d3bc9Richard Lowe    }
39749d3bc9Richard Lowe
39849d3bc9Richard Lowe    switch (op) {
39949d3bc9Richard Lowe
40049d3bc9Richard Lowe    case DW_CFA_advance_loc:
40107dc194Richard Lowe        if (val1 <= 0x3f) {
40207dc194Richard Lowe            db = val1;
40307dc194Richard Lowe            op |= db;
40407dc194Richard Lowe        }
40507dc194Richard Lowe        /* test not portable FIX */
40607dc194Richard Lowe        else if (val1 <= UCHAR_MAX) {
40707dc194Richard Lowe            op = DW_CFA_advance_loc1;
40807dc194Richard Lowe            db = val1;
40907dc194Richard Lowe            ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
41007dc194Richard Lowe            if (ptr == NULL) {
41107dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
41207dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
41307dc194Richard Lowe            }
41407dc194Richard Lowe            memcpy((void *) ptr, (const void *) &db, 1);
41507dc194Richard Lowe            nbytes = 1;
41607dc194Richard Lowe        }
41707dc194Richard Lowe        /* test not portable FIX */
41807dc194Richard Lowe        else if (val1 <= USHRT_MAX) {
41907dc194Richard Lowe            op = DW_CFA_advance_loc2;
42007dc194Richard Lowe            dh = val1;
42107dc194Richard Lowe            ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
42207dc194Richard Lowe            if (ptr == NULL) {
42307dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
42407dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
42507dc194Richard Lowe            }
42607dc194Richard Lowe            memcpy((void *) ptr, (const void *) &dh, 2);
42707dc194Richard Lowe            nbytes = 2;
42807dc194Richard Lowe        }
42907dc194Richard Lowe        /* test not portable FIX */
43007dc194Richard Lowe        else if (val1 <= ULONG_MAX) {
43107dc194Richard Lowe            op = DW_CFA_advance_loc4;
43207dc194Richard Lowe            dw = (Dwarf_Word) val1;
43307dc194Richard Lowe            ptr = (char *) _dwarf_p_get_alloc(dbg, 4);
43407dc194Richard Lowe            if (ptr == NULL) {
43507dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
43607dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
43707dc194Richard Lowe            }
43807dc194Richard Lowe            memcpy((void *) ptr, (const void *) &dw, 4);
43907dc194Richard Lowe            nbytes = 4;
44007dc194Richard Lowe        } else {
44107dc194Richard Lowe            op = DW_CFA_MIPS_advance_loc8;
44207dc194Richard Lowe            du = val1;
44307dc194Richard Lowe            ptr =
44407dc194Richard Lowe                (char *) _dwarf_p_get_alloc(dbg,
44507dc194Richard Lowe                                            sizeof(Dwarf_Unsigned));
44607dc194Richard Lowe            if (ptr == NULL) {
44707dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
44807dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
44907dc194Richard Lowe            }
45007dc194Richard Lowe            memcpy((void *) ptr, (const void *) &du, 8);
45107dc194Richard Lowe            nbytes = 8;
45207dc194Richard Lowe        }
45307dc194Richard Lowe        break;
45449d3bc9Richard Lowe
45549d3bc9Richard Lowe    case DW_CFA_offset:
45607dc194Richard Lowe        if (val1 <= MAX_6_BIT_VALUE) {
45707dc194Richard Lowe            db = val1;
45807dc194Richard Lowe            op |= db;
45907dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
46007dc194Richard Lowe                                              buff1, sizeof(buff1));
46107dc194Richard Lowe            if (res != DW_DLV_OK) {
46207dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
46307dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
46407dc194Richard Lowe            }
46507dc194Richard Lowe            ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
46607dc194Richard Lowe            if (ptr == NULL) {
46707dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
46807dc194Richard Lowe                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
46907dc194Richard Lowe            }
47007dc194Richard Lowe            memcpy(ptr, buff1, nbytes);
47107dc194Richard Lowe
47207dc194Richard Lowe        } else {
47307dc194Richard Lowe            op = DW_CFA_offset_extended;
47407dc194Richard Lowe            goto two_leb;
47507dc194Richard Lowe        }
47607dc194Richard Lowe        break;
47707dc194Richard Lowe    case DW_CFA_offset_extended_sf: /* DWARF3 */
47807dc194Richard Lowe            signed_second = 1;
47907dc194Richard Lowe            goto two_leb;
48007dc194Richard Lowe    case DW_CFA_offset_extended:
48107dc194Richard Lowe            goto two_leb;
48249d3bc9Richard Lowe
48349d3bc9Richard Lowe    case DW_CFA_undefined:
48449d3bc9Richard Lowe    case DW_CFA_same_value:
48507dc194Richard Lowe        goto one_leb;
48607dc194Richard Lowe
48707dc194Richard Lowe    case DW_CFA_val_offset:
48807dc194Richard Lowe         goto two_leb;
48907dc194Richard Lowe    case DW_CFA_val_offset_sf:
49007dc194Richard Lowe         signed_second = 1;
49107dc194Richard Lowe         goto two_leb;
49207dc194Richard Lowe    case DW_CFA_def_cfa_sf:
49307dc194Richard Lowe         signed_second = 1;
49407dc194Richard Lowe         goto two_leb;
49549d3bc9Richard Lowe    case DW_CFA_register:
49649d3bc9Richard Lowe    case DW_CFA_def_cfa:
49707dc194Richard Lowe    two_leb:
49807dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
49907dc194Richard Lowe                                          buff1, sizeof(buff1));
50007dc194Richard Lowe        if (res != DW_DLV_OK) {
50107dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
50207dc194Richard Lowe            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
50307dc194Richard Lowe        }
50407dc194Richard Lowe        if (!signed_second) {
50507dc194Richard Lowe                res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
50607dc194Richard Lowe                                              buff2, sizeof(buff2));
50707dc194Richard Lowe        } else {
50807dc194Richard Lowe            Dwarf_Signed val2s = val2;
50907dc194Richard Lowe            res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
51007dc194Richard Lowe                                              buff2, sizeof(buff2));
51107dc194Richard Lowe        }
51207dc194Richard Lowe
51307dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
51407dc194Richard Lowe                                          buff2, sizeof(buff2));
51507dc194Richard Lowe        if (res != DW_DLV_OK) {
51607dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
51707dc194Richard Lowe            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
51807dc194Richard Lowe        }
51907dc194Richard Lowe
52007dc194Richard Lowe        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
52107dc194Richard Lowe        if (ptr == NULL) {
52207dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
52307dc194Richard Lowe            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
52407dc194Richard Lowe        }
52507dc194Richard Lowe        memcpy(ptr, buff1, nbytes1);
52607dc194Richard Lowe        memcpy(ptr + nbytes1, buff2, nbytes2);
52707dc194Richard Lowe        nbytes = nbytes1 + nbytes2;
52807dc194Richard Lowe        break;
52907dc194Richard Lowe
53007dc194Richard Lowe    case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
53107dc194Richard Lowe        signed_first = 1;
53207dc194Richard Lowe        goto one_leb;
53349d3bc9Richard Lowe    case DW_CFA_def_cfa_register:
53449d3bc9Richard Lowe    case DW_CFA_def_cfa_offset:
53507dc194Richard Lowe    one_leb:
53607dc194Richard Lowe        if(!signed_first) {
53707dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
53807dc194Richard Lowe                                          buff1, sizeof(buff1));
53907dc194Richard Lowe        } else {
54007dc194Richard Lowe            Dwarf_Signed val1s = val1;
54107dc194Richard Lowe            res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
54207dc194Richard Lowe                                          buff1, sizeof(buff1));
54307dc194Richard Lowe        }
54407dc194Richard Lowe        if (res != DW_DLV_OK) {
54507dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
54607dc194Richard Lowe            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
54707dc194Richard Lowe        }
54807dc194Richard Lowe        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
54907dc194Richard Lowe        if (ptr == NULL) {
55007dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
55107dc194Richard Lowe            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
55207dc194Richard Lowe        }
55307dc194Richard Lowe        memcpy(ptr, buff1, nbytes);
55407dc194Richard Lowe        break;
55507dc194Richard Lowe    case DW_CFA_def_cfa_expression: /* DWARF3 */
55607dc194Richard Lowe        /* FIXME: argument is dwarf expr, not handled yet. */
55707dc194Richard Lowe    case DW_CFA_expression: /* DWARF3 */
55807dc194Richard Lowe        /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
55907dc194Richard Lowe           FIXME: not handled yet. */
56007dc194Richard Lowe    case DW_CFA_val_expression: /* DWARF3f */
56107dc194Richard Lowe        /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
56207dc194Richard Lowe           FIXME: not handled yet. */
56349d3bc9Richard Lowe    default:
56407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
56507dc194Richard Lowe        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
56649d3bc9Richard Lowe    }
56749d3bc9Richard Lowe
56849d3bc9Richard Lowe    curinst->dfp_opcode = op;
56949d3bc9Richard Lowe    curinst->dfp_args = ptr;
57049d3bc9Richard Lowe    curinst->dfp_nbytes = nbytes;
57149d3bc9Richard Lowe    curinst->dfp_next = NULL;
57249d3bc9Richard Lowe
57349d3bc9Richard Lowe    _dwarf_pro_add_to_fde(fde, curinst);
57449d3bc9Richard Lowe    return fde;
57549d3bc9Richard Lowe}
57649d3bc9Richard Lowe
57749d3bc9Richard Lowe
57849d3bc9Richard Lowe/*------------------------------------------------------------------------
57907dc194Richard Lowe        Instructions are added to an fde in the form of a linked
58007dc194Richard Lowe        list. This function manages the linked list.
58149d3bc9Richard Lowe-------------------------------------------------------------------------*/
58249d3bc9Richard Lowevoid
58349d3bc9Richard Lowe_dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
58449d3bc9Richard Lowe{
58549d3bc9Richard Lowe    if (fde->fde_last_inst) {
58607dc194Richard Lowe        fde->fde_last_inst->dfp_next = curinst;
58707dc194Richard Lowe        fde->fde_last_inst = curinst;
58807dc194Richard Lowe        fde->fde_n_inst++;
58907dc194Richard Lowe        fde->fde_n_bytes +=
59007dc194Richard Lowe            (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
59149d3bc9Richard Lowe    } else {
59207dc194Richard Lowe        fde->fde_last_inst = curinst;
59307dc194Richard Lowe        fde->fde_inst = curinst;
59407dc194Richard Lowe        fde->fde_n_inst = 1;
59507dc194Richard Lowe        fde->fde_n_bytes =
59607dc194Richard Lowe            (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
59749d3bc9Richard Lowe    }
59849d3bc9Richard Lowe}