149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
549d3bc9Richard Lowe
649d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
749d3bc9Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
849d3bc9Richard Lowe  as published by the Free Software Foundation.
949d3bc9Richard Lowe
1049d3bc9Richard Lowe  This program is distributed in the hope that it would be useful, but
1149d3bc9Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1349d3bc9Richard Lowe
1449d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
1549d3bc9Richard Lowe  free of the rightful claim of any third person regarding infringement
1649d3bc9Richard Lowe  or the like.  Any license provided herein, whether implied or
1749d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1849d3bc9Richard Lowe  any, provided herein do not apply to combinations of this program with
1949d3bc9Richard Lowe  other software, or any other product whatsoever.
2049d3bc9Richard Lowe
2149d3bc9Richard Lowe  You should have received a copy of the GNU Lesser General Public
2249d3bc9Richard Lowe  License along with this program; if not, write the Free Software
2307dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2449d3bc9Richard Lowe  USA.
2549d3bc9Richard Lowe
2607dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2749d3bc9Richard Lowe  Mountain View, CA 94043, or:
2849d3bc9Richard Lowe
2949d3bc9Richard Lowe  http://www.sgi.com
3049d3bc9Richard Lowe
3149d3bc9Richard Lowe  For further information regarding this notice, see:
3249d3bc9Richard Lowe
3349d3bc9Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3449d3bc9Richard Lowe
3549d3bc9Richard Lowe*/
3607dc194Richard Lowe/* The address of the Free Software Foundation is
3707dc194Richard Lowe   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
3807dc194Richard Lowe   Boston, MA 02110-1301, USA.
3907dc194Richard Lowe   SGI has moved from the Crittenden Lane address.
4007dc194Richard Lowe*/
4107dc194Richard Lowe
4207dc194Richard Lowe
4349d3bc9Richard Lowe
4449d3bc9Richard Lowe
4549d3bc9Richard Lowe
4649d3bc9Richard Lowe#include "config.h"
4749d3bc9Richard Lowe#include "dwarf_incl.h"
4849d3bc9Richard Lowe#include <stdio.h>
4949d3bc9Richard Lowe#include <stdlib.h>
5007dc194Richard Lowe#include <sys/types.h>
5149d3bc9Richard Lowe#include "dwarf_frame.h"
5207dc194Richard Lowe#include "dwarf_arange.h"       /* Using Arange as a way to build a
5307dc194Richard Lowe                                   list */
5407dc194Richard Lowe
5507dc194Richard Lowe#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg )          \
5607dc194Richard Lowe    do {                                               \
5707dc194Richard Lowe     if ((fde) == NULL) {                              \
5807dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_NULL);    \
5907dc194Richard Lowe        return (DW_DLV_ERROR);                         \
6007dc194Richard Lowe    }                                                  \
6107dc194Richard Lowe    (dbg)= (fde)->fd_dbg;                              \
6207dc194Richard Lowe    if ((dbg) == NULL) {                               \
6307dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\
6407dc194Richard Lowe        return (DW_DLV_ERROR);                         \
6507dc194Richard Lowe    } } while (0)
6607dc194Richard Lowe
6707dc194Richard Lowe
6807dc194Richard Lowe#define MIN(a,b)  (((a) < (b))? a:b)
6907dc194Richard Lowe
7007dc194Richard Lowestatic void _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg,
7107dc194Richard Lowe                                      int last_reg_num,
7207dc194Richard Lowe                                      int initial_value);
7307dc194Richard Lowestatic int dwarf_initialize_fde_table(Dwarf_Debug dbg,
7407dc194Richard Lowe                                      struct Dwarf_Frame_s *fde_table,
7507dc194Richard Lowe                                      unsigned table_real_data_size,
7607dc194Richard Lowe                                      Dwarf_Error * error);
7707dc194Richard Lowestatic void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table);
7807dc194Richard Lowe
7907dc194Richard Lowe#if 0
8007dc194Richard Lowe/* Only used for debugging libdwarf. */
8107dc194Richard Lowestatic void dump_frame_rule(char *msg,
8207dc194Richard Lowe                            struct Dwarf_Reg_Rule_s *reg_rule);
8307dc194Richard Lowe#endif
8449d3bc9Richard Lowe
8549d3bc9Richard Lowe
8649d3bc9Richard Lowe
8749d3bc9Richard Lowe/*
8849d3bc9Richard Lowe    This function is the heart of the debug_frame stuff.  Don't even
8949d3bc9Richard Lowe    think of reading this without reading both the Libdwarf and
9049d3bc9Richard Lowe    consumer API carefully first.  This function basically executes
9149d3bc9Richard Lowe    frame instructions contained in a Cie or an Fde, but does in a
9249d3bc9Richard Lowe    number of different ways depending on the information sought.
9349d3bc9Richard Lowe    Start_instr_ptr points to the first byte of the frame instruction
9449d3bc9Richard Lowe    stream, and final_instr_ptr to the to the first byte after the
9549d3bc9Richard Lowe    last.
9649d3bc9Richard Lowe
9749d3bc9Richard Lowe    The offsets returned in the frame instructions are factored.  That
9849d3bc9Richard Lowe    is they need to be multiplied by either the code_alignment_factor
9949d3bc9Richard Lowe    or the data_alignment_factor, as appropriate to obtain the actual
10049d3bc9Richard Lowe    offset.  This makes it possible to expand an instruction stream
10149d3bc9Richard Lowe    without the corresponding Cie.  However, when an Fde frame instr
10249d3bc9Richard Lowe    sequence is being expanded there must be a valid Cie with a pointer
10349d3bc9Richard Lowe    to an initial table row.
10449d3bc9Richard Lowe
10549d3bc9Richard Lowe
10649d3bc9Richard Lowe    If successful, returns DW_DLV_OK
10707dc194Richard Lowe                And sets returned_count thru the pointer
10807dc194Richard Lowe                 if make_instr is true.
10907dc194Richard Lowe                If make_instr is false returned_count
11007dc194Richard Lowe                 should NOT be used by the caller (returned_count
11107dc194Richard Lowe                 is set to 0 thru the pointer by this routine...)
11249d3bc9Richard Lowe    If unsuccessful, returns DW_DLV_ERROR
11307dc194Richard Lowe                and sets returned_error to the error code
11449d3bc9Richard Lowe
11549d3bc9Richard Lowe    It does not do a whole lot of input validation being a private
11649d3bc9Richard Lowe    function.  Please make sure inputs are valid.
11749d3bc9Richard Lowe
11849d3bc9Richard Lowe    (1) If make_instr is true, it makes a list of pointers to
11949d3bc9Richard Lowe    Dwarf_Frame_Op structures containing the frame instructions
12049d3bc9Richard Lowe    executed.  A pointer to this list is returned in ret_frame_instr.
12149d3bc9Richard Lowe    Make_instr is true only when a list of frame instructions is to be
12249d3bc9Richard Lowe    returned.  In this case since we are not interested in the contents
12349d3bc9Richard Lowe    of the table, the input Cie can be NULL.  This is the only case
12449d3bc9Richard Lowe    where the inpute Cie can be NULL.
12549d3bc9Richard Lowe
12649d3bc9Richard Lowe    (2) If search_pc is true, frame instructions are executed till
12749d3bc9Richard Lowe    either a location is reached that is greater than the search_pc_val
12849d3bc9Richard Lowe    provided, or all instructions are executed.  At this point the
12949d3bc9Richard Lowe    last row of the table generated is returned in a structure.
13049d3bc9Richard Lowe    A pointer to this structure is supplied in table.
13149d3bc9Richard Lowe
13249d3bc9Richard Lowe    (3) This function is also used to create the initial table row
13349d3bc9Richard Lowe    defined by a Cie.  In this case, the Dwarf_Cie pointer cie, is
13449d3bc9Richard Lowe    NULL.  For an FDE, however, cie points to the associated Cie.
13507dc194Richard Lowe
13607dc194Richard Lowe    make_instr - make list of frame instr? 0/1
13707dc194Richard Lowe    ret_frame_instr -  Ptr to list of ptrs to frame instrs
13807dc194Richard Lowe    search_pc  - Search for a pc value?  0/1
13907dc194Richard Lowe     search_pc_val -  Search for this pc value
14007dc194Richard Lowe    initial_loc - Initial code location value.
14107dc194Richard Lowe    start_instr_ptr -   Ptr to start of frame instrs.
14207dc194Richard Lowe    final_instr_ptr -   Ptr just past frame instrs.
14307dc194Richard Lowe    table       -     Ptr to struct with last row.
14407dc194Richard Lowe    cie     -   Ptr to Cie used by the Fde.
14507dc194Richard Lowe       Different cies may have distinct address-sizes, so the cie
14607dc194Richard Lowe       is used, not de_pointer_size.
14707dc194Richard Lowe
14849d3bc9Richard Lowe*/
14907dc194Richard Lowe
15007dc194Richard Loweint
15107dc194Richard Lowe_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
15207dc194Richard Lowe    Dwarf_Frame_Op ** ret_frame_instr,
15307dc194Richard Lowe    Dwarf_Bool search_pc,
15407dc194Richard Lowe    Dwarf_Addr search_pc_val,
15507dc194Richard Lowe    Dwarf_Addr initial_loc,
15607dc194Richard Lowe    Dwarf_Small * start_instr_ptr,
15707dc194Richard Lowe    Dwarf_Small * final_instr_ptr,
15807dc194Richard Lowe    Dwarf_Frame table,
15907dc194Richard Lowe    Dwarf_Cie cie,
16007dc194Richard Lowe    Dwarf_Debug dbg,
16107dc194Richard Lowe    Dwarf_Half reg_num_of_cfa,
16207dc194Richard Lowe    Dwarf_Sword * returned_count,
16307dc194Richard Lowe    int *returned_error)
16449d3bc9Richard Lowe{
16507dc194Richard Lowe#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg)               \
16607dc194Richard Lowe     do {                                             \
16707dc194Richard Lowe       if ((macreg) >= (machigh_reg) || (macreg) < 0) {            \
16807dc194Richard Lowe        SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \
16907dc194Richard Lowe       }                                              \
17007dc194Richard Lowe     } /*CONSTCOND */ while(0)
17107dc194Richard Lowe#define SIMPLE_ERROR_RETURN(code) \
17207dc194Richard Lowe        free(localregtab); \
17307dc194Richard Lowe        *returned_error = code; \
17407dc194Richard Lowe        return DW_DLV_ERROR
17507dc194Richard Lowe
17649d3bc9Richard Lowe    /* Sweeps the frame instructions. */
17749d3bc9Richard Lowe    Dwarf_Small *instr_ptr;
17849d3bc9Richard Lowe
17907dc194Richard Lowe    /* Register numbers not limited to just 255, thus not using
18007dc194Richard Lowe       Dwarf_Small. */
18107dc194Richard Lowe    typedef int reg_num_type;
18207dc194Richard Lowe
18349d3bc9Richard Lowe    Dwarf_Unsigned factored_N_value;
18407dc194Richard Lowe    Dwarf_Signed signed_factored_N_value;
18507dc194Richard Lowe    Dwarf_Addr current_loc = initial_loc;       /* code location/
18607dc194Richard Lowe                                                   pc-value
18707dc194Richard Lowe                                                   corresponding to the
18807dc194Richard Lowe                                                   frame instructions.
18907dc194Richard Lowe                                                   Starts at zero when
19007dc194Richard Lowe                                                   the caller has no
19107dc194Richard Lowe                                                   value to pass in. */
19249d3bc9Richard Lowe
19307dc194Richard Lowe    /* Must be min de_pointer_size bytes and must be at least sizeof
19407dc194Richard Lowe       Dwarf_ufixed */
19507dc194Richard Lowe    Dwarf_Unsigned adv_loc = 0;
19607dc194Richard Lowe
19707dc194Richard Lowe    int reg_count = dbg->de_frame_reg_rules_entry_count;
19807dc194Richard Lowe    struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count,
19907dc194Richard Lowe                                          sizeof(struct
20007dc194Richard Lowe                                                 Dwarf_Reg_Rule_s));
20107dc194Richard Lowe
20207dc194Richard Lowe    struct Dwarf_Reg_Rule_s cfa_reg;
20349d3bc9Richard Lowe
20449d3bc9Richard Lowe
20549d3bc9Richard Lowe    /* This is used to end executing frame instructions.  */
20607dc194Richard Lowe    /* Becomes true when search_pc is true and current_loc */
20749d3bc9Richard Lowe    /* is greater than search_pc_val.  */
20849d3bc9Richard Lowe    Dwarf_Bool search_over = false;
20949d3bc9Richard Lowe
21049d3bc9Richard Lowe    /* Used by the DW_FRAME_advance_loc instr */
21149d3bc9Richard Lowe    /* to hold the increment in pc value.  */
21249d3bc9Richard Lowe    Dwarf_Addr adv_pc;
21349d3bc9Richard Lowe
21449d3bc9Richard Lowe    /* Contains the length in bytes of */
21549d3bc9Richard Lowe    /* an leb128 encoded number.  */
21649d3bc9Richard Lowe    Dwarf_Word leb128_length;
21749d3bc9Richard Lowe
21807dc194Richard Lowe    Dwarf_Half address_size = (cie)? cie->ci_address_size:
21907dc194Richard Lowe        dbg->de_pointer_size;
22007dc194Richard Lowe
22149d3bc9Richard Lowe    /* Counts the number of frame instructions executed.  */
22249d3bc9Richard Lowe    Dwarf_Word instr_count = 0;
22349d3bc9Richard Lowe
22449d3bc9Richard Lowe    /*
22549d3bc9Richard Lowe       These contain the current fields of the current frame
22649d3bc9Richard Lowe       instruction. */
22749d3bc9Richard Lowe    Dwarf_Small fp_base_op = 0;
22849d3bc9Richard Lowe    Dwarf_Small fp_extended_op;
22907dc194Richard Lowe    reg_num_type fp_register;
23007dc194Richard Lowe
23107dc194Richard Lowe    /* The value in fp_offset may be signed, though we call it
23207dc194Richard Lowe       unsigned. This works ok for 2-s complement arithmetic. */
23349d3bc9Richard Lowe    Dwarf_Unsigned fp_offset;
23449d3bc9Richard Lowe    Dwarf_Off fp_instr_offset;
23549d3bc9Richard Lowe
23649d3bc9Richard Lowe    /*
23749d3bc9Richard Lowe       Stack_table points to the row (Dwarf_Frame ie) being pushed or
23849d3bc9Richard Lowe       popped by a remember or restore instruction. Top_stack points to
23949d3bc9Richard Lowe       the top of the stack of rows. */
24007dc194Richard Lowe    Dwarf_Frame stack_table = NULL;
24149d3bc9Richard Lowe    Dwarf_Frame top_stack = NULL;
24249d3bc9Richard Lowe
24349d3bc9Richard Lowe    /*
24449d3bc9Richard Lowe       These are used only when make_instr is true. Curr_instr is a
24549d3bc9Richard Lowe       pointer to the current frame instruction executed.
24607dc194Richard Lowe       Curr_instr_ptr, head_instr_list, and curr_instr_list are used to
24707dc194Richard Lowe       form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is
24807dc194Richard Lowe       used to deallocate the structs used to form the chain.
24907dc194Richard Lowe       Head_instr_block points to a contiguous list of pointers to the
25049d3bc9Richard Lowe       Dwarf_Frame_Op structs executed. */
25149d3bc9Richard Lowe    Dwarf_Frame_Op *curr_instr;
25249d3bc9Richard Lowe    Dwarf_Chain curr_instr_item, dealloc_instr_item;
25349d3bc9Richard Lowe    Dwarf_Chain head_instr_chain = NULL;
25449d3bc9Richard Lowe    Dwarf_Chain tail_instr_chain = NULL;
25549d3bc9Richard Lowe    Dwarf_Frame_Op *head_instr_block;
25649d3bc9Richard Lowe
25749d3bc9Richard Lowe    /*
25849d3bc9Richard Lowe       These are the alignment_factors taken from the Cie provided.
25949d3bc9Richard Lowe       When no input Cie is provided they are set to 1, because only
26049d3bc9Richard Lowe       factored offsets are required. */
26149d3bc9Richard Lowe    Dwarf_Sword code_alignment_factor = 1;
26249d3bc9Richard Lowe    Dwarf_Sword data_alignment_factor = 1;
26349d3bc9Richard Lowe
26449d3bc9Richard Lowe    /*
26549d3bc9Richard Lowe       This flag indicates when an actual alignment factor is needed.
26649d3bc9Richard Lowe       So if a frame instruction that computes an offset using an
26749d3bc9Richard Lowe       alignment factor is encountered when this flag is set, an error
26849d3bc9Richard Lowe       is returned because the Cie did not have a valid augmentation. */
26949d3bc9Richard Lowe    Dwarf_Bool need_augmentation = false;
27049d3bc9Richard Lowe
27149d3bc9Richard Lowe    Dwarf_Word i;
27249d3bc9Richard Lowe
27349d3bc9Richard Lowe    /* Initialize first row from associated Cie. Using temp regs
27449d3bc9Richard Lowe       explicity */
27507dc194Richard Lowe
27607dc194Richard Lowe    if (localregtab == 0) {
27707dc194Richard Lowe        SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL);
27807dc194Richard Lowe    }
27907dc194Richard Lowe    {
28007dc194Richard Lowe        struct Dwarf_Reg_Rule_s *t1reg = localregtab;
28107dc194Richard Lowe        struct Dwarf_Reg_Rule_s *t1end = t1reg + reg_count;
28207dc194Richard Lowe
28307dc194Richard Lowe        if (cie != NULL && cie->ci_initial_table != NULL) {
28407dc194Richard Lowe            struct Dwarf_Reg_Rule_s *t2reg =
28507dc194Richard Lowe                cie->ci_initial_table->fr_reg;
28607dc194Richard Lowe
28707dc194Richard Lowe            if (reg_count != cie->ci_initial_table->fr_reg_count) {
28807dc194Richard Lowe                /* Should never happen, it makes no sense to have the
28907dc194Richard Lowe                   table sizes change. There is no real allowance for
29007dc194Richard Lowe                   the set of registers to change dynamically in a
29107dc194Richard Lowe                   single Dwarf_Debug (except the size can be set near
29207dc194Richard Lowe                   initial Dwarf_Debug creation time). */
29307dc194Richard Lowe                SIMPLE_ERROR_RETURN
29407dc194Richard Lowe                    (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH);
29507dc194Richard Lowe            }
29607dc194Richard Lowe
29707dc194Richard Lowe            for (; t1reg < t1end; t1reg++, t2reg++) {
29807dc194Richard Lowe                *t1reg = *t2reg;
29907dc194Richard Lowe            }
30007dc194Richard Lowe            cfa_reg = cie->ci_initial_table->fr_cfa_rule;
30107dc194Richard Lowe        } else {
30207dc194Richard Lowe            _dwarf_init_regrule_table(t1reg,
30307dc194Richard Lowe                                      reg_count,
30407dc194Richard Lowe                                      dbg->de_frame_rule_initial_value);
30507dc194Richard Lowe            _dwarf_init_regrule_table(&cfa_reg, 1,
30607dc194Richard Lowe                                      dbg->de_frame_rule_initial_value);
30707dc194Richard Lowe        }
30849d3bc9Richard Lowe    }
30949d3bc9Richard Lowe
31049d3bc9Richard Lowe    /*
31149d3bc9Richard Lowe       The idea here is that the code_alignment_factor and
31249d3bc9Richard Lowe       data_alignment_factor which are needed for certain instructions
31307dc194Richard Lowe       are valid only when the Cie has a proper augmentation string. So
31407dc194Richard Lowe       if the augmentation is not right, only Frame instruction can be
31507dc194Richard Lowe       read. */
31649d3bc9Richard Lowe    if (cie != NULL && cie->ci_augmentation != NULL) {
31707dc194Richard Lowe        code_alignment_factor = cie->ci_code_alignment_factor;
31807dc194Richard Lowe        data_alignment_factor = cie->ci_data_alignment_factor;
31907dc194Richard Lowe    } else {
32007dc194Richard Lowe        need_augmentation = !make_instr;
32107dc194Richard Lowe    }
32249d3bc9Richard Lowe
32349d3bc9Richard Lowe    instr_ptr = start_instr_ptr;
32449d3bc9Richard Lowe    while ((instr_ptr < final_instr_ptr) && (!search_over)) {
32507dc194Richard Lowe        Dwarf_Small instr = 0;
32607dc194Richard Lowe        Dwarf_Small opcode = 0;
32707dc194Richard Lowe        reg_num_type reg_no = 0;
32807dc194Richard Lowe
32907dc194Richard Lowe        fp_instr_offset = instr_ptr - start_instr_ptr;
33007dc194Richard Lowe        instr = *(Dwarf_Small *) instr_ptr;
33107dc194Richard Lowe        instr_ptr += sizeof(Dwarf_Small);
33207dc194Richard Lowe
33307dc194Richard Lowe        fp_base_op = (instr & 0xc0) >> 6;
33407dc194Richard Lowe        if ((instr & 0xc0) == 0x00) {
33507dc194Richard Lowe            opcode = instr;     /* is really extended op */
33607dc194Richard Lowe            fp_extended_op = (instr & (~(0xc0))) & 0xff;
33707dc194Richard Lowe        } else {
33807dc194Richard Lowe            opcode = instr & 0xc0;      /* is base op */
33907dc194Richard Lowe            fp_extended_op = 0;
34007dc194Richard Lowe        }
34107dc194Richard Lowe
34207dc194Richard Lowe        fp_register = 0;
34307dc194Richard Lowe        fp_offset = 0;
34407dc194Richard Lowe        switch (opcode) {
34507dc194Richard Lowe        case DW_CFA_advance_loc:
34607dc194Richard Lowe            {
34707dc194Richard Lowe                /* base op */
34807dc194Richard Lowe                fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK;
34907dc194Richard Lowe
35007dc194Richard Lowe                if (need_augmentation) {
35107dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
35207dc194Richard Lowe                }
35307dc194Richard Lowe                adv_pc = adv_pc * code_alignment_factor;
35407dc194Richard Lowe
35507dc194Richard Lowe                search_over = search_pc &&
35607dc194Richard Lowe                    (current_loc + adv_pc > search_pc_val);
35707dc194Richard Lowe                /* If gone past pc needed, retain old pc.  */
35807dc194Richard Lowe                if (!search_over) {
35907dc194Richard Lowe                    current_loc = current_loc + adv_pc;
36007dc194Richard Lowe                }
36107dc194Richard Lowe                break;
36207dc194Richard Lowe            }
36307dc194Richard Lowe
36407dc194Richard Lowe        case DW_CFA_offset:
36507dc194Richard Lowe            {                   /* base op */
36607dc194Richard Lowe                reg_no =
36707dc194Richard Lowe                    (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK);
36807dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
36907dc194Richard Lowe
37007dc194Richard Lowe                factored_N_value =
37107dc194Richard Lowe                    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
37207dc194Richard Lowe                instr_ptr = instr_ptr + leb128_length;
37307dc194Richard Lowe
37407dc194Richard Lowe                fp_register = reg_no;
37507dc194Richard Lowe                fp_offset = factored_N_value;
37607dc194Richard Lowe
37707dc194Richard Lowe                if (need_augmentation) {
37807dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
37907dc194Richard Lowe                }
38007dc194Richard Lowe
38107dc194Richard Lowe                localregtab[reg_no].ru_is_off = 1;
38207dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
38307dc194Richard Lowe                localregtab[reg_no].ru_register = reg_num_of_cfa;
38407dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len =
38507dc194Richard Lowe                    factored_N_value * data_alignment_factor;
38607dc194Richard Lowe
38707dc194Richard Lowe                break;
38807dc194Richard Lowe            }
38907dc194Richard Lowe
39007dc194Richard Lowe        case DW_CFA_restore:
39107dc194Richard Lowe            {                   /* base op */
39207dc194Richard Lowe                reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
39307dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
39407dc194Richard Lowe
39507dc194Richard Lowe                fp_register = reg_no;
39607dc194Richard Lowe
39707dc194Richard Lowe                if (cie != NULL && cie->ci_initial_table != NULL)
39807dc194Richard Lowe                    localregtab[reg_no] =
39907dc194Richard Lowe                       cie->ci_initial_table->fr_reg[reg_no];
40007dc194Richard Lowe                else if (!make_instr) {
40107dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT);
40207dc194Richard Lowe                }
40307dc194Richard Lowe
40407dc194Richard Lowe                break;
40507dc194Richard Lowe            }
40607dc194Richard Lowe        case DW_CFA_set_loc:
40707dc194Richard Lowe            {
40807dc194Richard Lowe                Dwarf_Addr new_loc = 0;
40907dc194Richard Lowe
41007dc194Richard Lowe                READ_UNALIGNED(dbg, new_loc, Dwarf_Addr,
41107dc194Richard Lowe                               instr_ptr, address_size);
41207dc194Richard Lowe                instr_ptr += address_size;
41307dc194Richard Lowe                if (new_loc != 0 && current_loc != 0) {
41407dc194Richard Lowe                    /* Pre-relocation or before current_loc is set the
41507dc194Richard Lowe                       test comparing new_loc and current_loc makes no
41607dc194Richard Lowe                       sense. Testing for non-zero (above) is a way
41707dc194Richard Lowe                       (fallible) to check that current_loc, new_loc
41807dc194Richard Lowe                       are already relocated.  */
41907dc194Richard Lowe                    if (new_loc <= current_loc) {
42007dc194Richard Lowe                        /* Within a frame, address must increase.
42107dc194Richard Lowe                           Seemingly it has not. Seems to be an error. */
42207dc194Richard Lowe
42307dc194Richard Lowe                        SIMPLE_ERROR_RETURN
42407dc194Richard Lowe                            (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC);
42507dc194Richard Lowe                    }
42607dc194Richard Lowe                }
42707dc194Richard Lowe
42807dc194Richard Lowe                search_over = search_pc && (new_loc > search_pc_val);
42907dc194Richard Lowe
43007dc194Richard Lowe                /* If gone past pc needed, retain old pc.  */
43107dc194Richard Lowe                if (!search_over) {
43207dc194Richard Lowe                    current_loc = new_loc;
43307dc194Richard Lowe                }
43407dc194Richard Lowe                fp_offset = new_loc;
43507dc194Richard Lowe                break;
43607dc194Richard Lowe            }
43707dc194Richard Lowe
43807dc194Richard Lowe        case DW_CFA_advance_loc1:
43907dc194Richard Lowe            {
44007dc194Richard Lowe                fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr;
44107dc194Richard Lowe                instr_ptr += sizeof(Dwarf_Small);
44207dc194Richard Lowe
44307dc194Richard Lowe                if (need_augmentation) {
44407dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
44507dc194Richard Lowe                }
44607dc194Richard Lowe                adv_loc *= code_alignment_factor;
44707dc194Richard Lowe
44807dc194Richard Lowe                search_over = search_pc &&
44907dc194Richard Lowe                    (current_loc + adv_loc > search_pc_val);
45007dc194Richard Lowe
45107dc194Richard Lowe                /* If gone past pc needed, retain old pc.  */
45207dc194Richard Lowe                if (!search_over) {
45307dc194Richard Lowe                    current_loc = current_loc + adv_loc;
45407dc194Richard Lowe                }
45507dc194Richard Lowe                break;
45607dc194Richard Lowe            }
45707dc194Richard Lowe
45807dc194Richard Lowe        case DW_CFA_advance_loc2:
45907dc194Richard Lowe            {
46007dc194Richard Lowe                READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
46107dc194Richard Lowe                               instr_ptr, sizeof(Dwarf_Half));
46207dc194Richard Lowe                instr_ptr += sizeof(Dwarf_Half);
46307dc194Richard Lowe                fp_offset = adv_loc;
46407dc194Richard Lowe
46507dc194Richard Lowe                if (need_augmentation) {
46607dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
46707dc194Richard Lowe                }
46807dc194Richard Lowe                adv_loc *= code_alignment_factor;
46907dc194Richard Lowe
47007dc194Richard Lowe                search_over = search_pc &&
47107dc194Richard Lowe                    (current_loc + adv_loc > search_pc_val);
47207dc194Richard Lowe
47307dc194Richard Lowe                /* If gone past pc needed, retain old pc.  */
47407dc194Richard Lowe                if (!search_over) {
47507dc194Richard Lowe                    current_loc = current_loc + adv_loc;
47607dc194Richard Lowe                }
47707dc194Richard Lowe                break;
47807dc194Richard Lowe            }
47907dc194Richard Lowe
48007dc194Richard Lowe        case DW_CFA_advance_loc4:
48107dc194Richard Lowe            {
48207dc194Richard Lowe                READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
48307dc194Richard Lowe                               instr_ptr, sizeof(Dwarf_ufixed));
48407dc194Richard Lowe                instr_ptr += sizeof(Dwarf_ufixed);
48507dc194Richard Lowe                fp_offset = adv_loc;
48607dc194Richard Lowe
48707dc194Richard Lowe                if (need_augmentation) {
48807dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
48907dc194Richard Lowe                }
49007dc194Richard Lowe                adv_loc *= code_alignment_factor;
49107dc194Richard Lowe
49207dc194Richard Lowe                search_over = search_pc &&
49307dc194Richard Lowe                    (current_loc + adv_loc > search_pc_val);
49407dc194Richard Lowe
49507dc194Richard Lowe                /* If gone past pc needed, retain old pc.  */
49607dc194Richard Lowe                if (!search_over) {
49707dc194Richard Lowe                    current_loc = current_loc + adv_loc;
49807dc194Richard Lowe                }
49907dc194Richard Lowe                break;
50007dc194Richard Lowe            }
50107dc194Richard Lowe
50207dc194Richard Lowe        case DW_CFA_offset_extended:
50307dc194Richard Lowe            {
50407dc194Richard Lowe                Dwarf_Unsigned lreg;
50507dc194Richard Lowe
50607dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
50707dc194Richard Lowe                reg_no = (reg_num_type) lreg;
50807dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);;
50907dc194Richard Lowe                factored_N_value =
51007dc194Richard Lowe                    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
51107dc194Richard Lowe                instr_ptr += leb128_length;
51207dc194Richard Lowe
51307dc194Richard Lowe                if (need_augmentation) {
51407dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
51507dc194Richard Lowe                }
51607dc194Richard Lowe                localregtab[reg_no].ru_is_off = 1;
51707dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
51807dc194Richard Lowe                localregtab[reg_no].ru_register = reg_num_of_cfa;
51907dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len = factored_N_value *
52007dc194Richard Lowe                    data_alignment_factor;
52107dc194Richard Lowe
52207dc194Richard Lowe                fp_register = reg_no;
52307dc194Richard Lowe                fp_offset = factored_N_value;
52407dc194Richard Lowe                break;
52507dc194Richard Lowe            }
52607dc194Richard Lowe
52707dc194Richard Lowe        case DW_CFA_restore_extended:
52807dc194Richard Lowe            {
52907dc194Richard Lowe                Dwarf_Unsigned lreg;
53007dc194Richard Lowe
53107dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
53207dc194Richard Lowe                reg_no = (reg_num_type) lreg;
53307dc194Richard Lowe
53407dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
53507dc194Richard Lowe
53607dc194Richard Lowe                if (cie != NULL && cie->ci_initial_table != NULL) {
53707dc194Richard Lowe                    localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
53807dc194Richard Lowe                } else {
53907dc194Richard Lowe                    if (!make_instr) {
54007dc194Richard Lowe                        SIMPLE_ERROR_RETURN
54107dc194Richard Lowe                            (DW_DLE_DF_MAKE_INSTR_NO_INIT);
54207dc194Richard Lowe                    }
54307dc194Richard Lowe                }
54407dc194Richard Lowe
54507dc194Richard Lowe                fp_register = reg_no;
54607dc194Richard Lowe                break;
54707dc194Richard Lowe            }
54807dc194Richard Lowe
54907dc194Richard Lowe        case DW_CFA_undefined:
55007dc194Richard Lowe            {
55107dc194Richard Lowe                Dwarf_Unsigned lreg;
55207dc194Richard Lowe
55307dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
55407dc194Richard Lowe                reg_no = (reg_num_type) lreg;
55507dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
55607dc194Richard Lowe
55707dc194Richard Lowe                localregtab[reg_no].ru_is_off = 0;
55807dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
55907dc194Richard Lowe                localregtab[reg_no].ru_register =
56007dc194Richard Lowe                    dbg->de_frame_undefined_value_number;
56107dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len = 0;
56207dc194Richard Lowe
56307dc194Richard Lowe                fp_register = reg_no;
56407dc194Richard Lowe                break;
56507dc194Richard Lowe            }
56607dc194Richard Lowe
56707dc194Richard Lowe        case DW_CFA_same_value:
56807dc194Richard Lowe            {
56907dc194Richard Lowe                Dwarf_Unsigned lreg;
57007dc194Richard Lowe
57107dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
57207dc194Richard Lowe                reg_no = (reg_num_type) lreg;
57307dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
57407dc194Richard Lowe
57507dc194Richard Lowe                localregtab[reg_no].ru_is_off = 0;
57607dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
57707dc194Richard Lowe                localregtab[reg_no].ru_register =
57807dc194Richard Lowe                    dbg->de_frame_same_value_number;
57907dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len = 0;
58007dc194Richard Lowe                fp_register = reg_no;
58107dc194Richard Lowe                break;
58207dc194Richard Lowe            }
58307dc194Richard Lowe
58407dc194Richard Lowe        case DW_CFA_register:
58507dc194Richard Lowe            {
58607dc194Richard Lowe                Dwarf_Unsigned lreg;
58707dc194Richard Lowe                reg_num_type reg_noA = 0;
58807dc194Richard Lowe                reg_num_type reg_noB = 0;
58907dc194Richard Lowe
59007dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
59107dc194Richard Lowe                reg_noA = (reg_num_type) lreg;
59207dc194Richard Lowe
59307dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count);
59407dc194Richard Lowe
59507dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
59607dc194Richard Lowe                reg_noB = (reg_num_type) lreg;
59707dc194Richard Lowe
59807dc194Richard Lowe                if (reg_noB > reg_count) {
59907dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH);
60007dc194Richard Lowe                }
60107dc194Richard Lowe
60207dc194Richard Lowe
60307dc194Richard Lowe                localregtab[reg_noA].ru_is_off = 0;
60407dc194Richard Lowe                localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET;
60507dc194Richard Lowe                localregtab[reg_noA].ru_register = reg_noB;
60607dc194Richard Lowe                localregtab[reg_noA].ru_offset_or_block_len = 0;
60707dc194Richard Lowe
60807dc194Richard Lowe                fp_register = reg_noA;
60907dc194Richard Lowe                fp_offset = reg_noB;
61007dc194Richard Lowe                break;
61107dc194Richard Lowe            }
61207dc194Richard Lowe
61307dc194Richard Lowe        case DW_CFA_remember_state:
61407dc194Richard Lowe            {
61507dc194Richard Lowe                stack_table = (Dwarf_Frame)
61607dc194Richard Lowe                    _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
61707dc194Richard Lowe                if (stack_table == NULL) {
61807dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
61907dc194Richard Lowe                }
62007dc194Richard Lowe
62107dc194Richard Lowe                for (i = 0; i < reg_count; i++)
62207dc194Richard Lowe                    stack_table->fr_reg[i] = localregtab[i];
62307dc194Richard Lowe                stack_table->fr_cfa_rule = cfa_reg;
62407dc194Richard Lowe
62507dc194Richard Lowe                if (top_stack != NULL)
62607dc194Richard Lowe                    stack_table->fr_next = top_stack;
62707dc194Richard Lowe                top_stack = stack_table;
62807dc194Richard Lowe
62907dc194Richard Lowe                break;
63007dc194Richard Lowe            }
63107dc194Richard Lowe
63207dc194Richard Lowe        case DW_CFA_restore_state:
63307dc194Richard Lowe            {
63407dc194Richard Lowe                if (top_stack == NULL) {
63507dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK);
63607dc194Richard Lowe                }
63707dc194Richard Lowe                stack_table = top_stack;
63807dc194Richard Lowe                top_stack = stack_table->fr_next;
63907dc194Richard Lowe
64007dc194Richard Lowe                for (i = 0; i < reg_count; i++)
64107dc194Richard Lowe                    localregtab[i] = stack_table->fr_reg[i];
64207dc194Richard Lowe                cfa_reg = stack_table->fr_cfa_rule;
64307dc194Richard Lowe
64407dc194Richard Lowe                dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
64507dc194Richard Lowe                break;
64607dc194Richard Lowe            }
64707dc194Richard Lowe
64807dc194Richard Lowe        case DW_CFA_def_cfa:
64907dc194Richard Lowe            {
65007dc194Richard Lowe                Dwarf_Unsigned lreg;
65107dc194Richard Lowe
65207dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
65307dc194Richard Lowe                reg_no = (reg_num_type) lreg;
65407dc194Richard Lowe
65507dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
65607dc194Richard Lowe
65707dc194Richard Lowe                factored_N_value =
65807dc194Richard Lowe                    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
65907dc194Richard Lowe                instr_ptr += leb128_length;
66007dc194Richard Lowe
66107dc194Richard Lowe                if (need_augmentation) {
66207dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
66307dc194Richard Lowe                }
66407dc194Richard Lowe                cfa_reg.ru_is_off = 1;
66507dc194Richard Lowe                cfa_reg.ru_value_type = DW_EXPR_OFFSET;
66607dc194Richard Lowe                cfa_reg.ru_register = reg_no;
66707dc194Richard Lowe                cfa_reg.ru_offset_or_block_len = factored_N_value;
66807dc194Richard Lowe
66907dc194Richard Lowe                fp_register = reg_no;
67007dc194Richard Lowe                fp_offset = factored_N_value;
67107dc194Richard Lowe                break;
67207dc194Richard Lowe            }
67307dc194Richard Lowe
67407dc194Richard Lowe        case DW_CFA_def_cfa_register:
67507dc194Richard Lowe            {
67607dc194Richard Lowe                Dwarf_Unsigned lreg;
67707dc194Richard Lowe
67807dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
67907dc194Richard Lowe                reg_no = (reg_num_type) lreg;
68007dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
68107dc194Richard Lowe
68207dc194Richard Lowe                cfa_reg.ru_register = reg_no;
68307dc194Richard Lowe                /* Do NOT set ru_offset_or_block_len or ru_is_off here.
68407dc194Richard Lowe                   See dwarf2/3 spec.  */
68507dc194Richard Lowe                fp_register = reg_no;
68607dc194Richard Lowe                break;
68707dc194Richard Lowe            }
68807dc194Richard Lowe
68907dc194Richard Lowe        case DW_CFA_def_cfa_offset:
69007dc194Richard Lowe            {
69107dc194Richard Lowe                factored_N_value =
69207dc194Richard Lowe                    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
69307dc194Richard Lowe                instr_ptr += leb128_length;
69407dc194Richard Lowe
69507dc194Richard Lowe                if (need_augmentation) {
69607dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
69707dc194Richard Lowe                }
69807dc194Richard Lowe                /* Do set ru_is_off here, as here factored_N_value
69907dc194Richard Lowe                   counts.  */
70007dc194Richard Lowe                cfa_reg.ru_is_off = 1;
70107dc194Richard Lowe                cfa_reg.ru_value_type = DW_EXPR_OFFSET;
70207dc194Richard Lowe                cfa_reg.ru_offset_or_block_len = factored_N_value;
70307dc194Richard Lowe
70407dc194Richard Lowe                fp_offset = factored_N_value;
70507dc194Richard Lowe                break;
70607dc194Richard Lowe            }
70707dc194Richard Lowe        case DW_CFA_nop:
70807dc194Richard Lowe            {
70907dc194Richard Lowe                break;
71007dc194Richard Lowe            }
71107dc194Richard Lowe            /* DWARF3 ops begin here. */
71207dc194Richard Lowe        case DW_CFA_def_cfa_expression:
71307dc194Richard Lowe            {
71407dc194Richard Lowe                /* A single DW_FORM_block representing a dwarf
71507dc194Richard Lowe                   expression. The form block establishes the way to
71607dc194Richard Lowe                   compute the CFA. */
71707dc194Richard Lowe                Dwarf_Unsigned block_len = 0;
71807dc194Richard Lowe
71907dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, block_len);
72007dc194Richard Lowe                cfa_reg.ru_is_off = 0;  /* arbitrary */
72107dc194Richard Lowe                cfa_reg.ru_value_type = DW_EXPR_EXPRESSION;
72207dc194Richard Lowe                cfa_reg.ru_offset_or_block_len = block_len;
72307dc194Richard Lowe                cfa_reg.ru_block = instr_ptr;
72407dc194Richard Lowe                fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr;
72507dc194Richard Lowe                instr_ptr += block_len;
72607dc194Richard Lowe            }
72707dc194Richard Lowe            break;
72807dc194Richard Lowe        case DW_CFA_expression:
72907dc194Richard Lowe            {
73007dc194Richard Lowe                /* An unsigned leb128 value is the first operand (a
73107dc194Richard Lowe                   register number). The second operand is single
73207dc194Richard Lowe                   DW_FORM_block representing a dwarf expression. The
73307dc194Richard Lowe                   evaluator pushes the CFA on the evaluation stack
73407dc194Richard Lowe                   then evaluates the expression to compute the value
73507dc194Richard Lowe                   of the register contents. */
73607dc194Richard Lowe                Dwarf_Unsigned lreg = 0;
73707dc194Richard Lowe                Dwarf_Unsigned block_len = 0;
73807dc194Richard Lowe
73907dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
74007dc194Richard Lowe                reg_no = (reg_num_type) lreg;
74107dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
74207dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, block_len);
74307dc194Richard Lowe                localregtab[lreg].ru_is_off = 0;        /* arbitrary */
74407dc194Richard Lowe                localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION;
74507dc194Richard Lowe                localregtab[lreg].ru_offset_or_block_len = block_len;
74607dc194Richard Lowe                localregtab[lreg].ru_block = instr_ptr;
74707dc194Richard Lowe                fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr;
74807dc194Richard Lowe                fp_register = reg_no;
74907dc194Richard Lowe                instr_ptr += block_len;
75007dc194Richard Lowe            }
75107dc194Richard Lowe            break;
75207dc194Richard Lowe        case DW_CFA_offset_extended_sf:
75307dc194Richard Lowe            {
75407dc194Richard Lowe                /* The first operand is an unsigned leb128 register
75507dc194Richard Lowe                   number. The second is a signed factored offset.
75607dc194Richard Lowe                   Identical to DW_CFA_offset_extended except the
75707dc194Richard Lowe                   secondoperand is signed */
75807dc194Richard Lowe                Dwarf_Unsigned lreg;
75907dc194Richard Lowe
76007dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
76107dc194Richard Lowe                reg_no = (reg_num_type) lreg;
76207dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
76307dc194Richard Lowe                signed_factored_N_value =
76407dc194Richard Lowe                    _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
76507dc194Richard Lowe                instr_ptr += leb128_length;
76607dc194Richard Lowe
76707dc194Richard Lowe                if (need_augmentation) {
76807dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
76907dc194Richard Lowe                }
77007dc194Richard Lowe                localregtab[reg_no].ru_is_off = 1;
77107dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
77207dc194Richard Lowe                localregtab[reg_no].ru_register = reg_num_of_cfa;
77307dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len =
77407dc194Richard Lowe                    signed_factored_N_value * data_alignment_factor;
77507dc194Richard Lowe
77607dc194Richard Lowe                fp_register = reg_no;
77707dc194Richard Lowe                fp_offset = signed_factored_N_value;
77807dc194Richard Lowe            }
77907dc194Richard Lowe            break;
78007dc194Richard Lowe        case DW_CFA_def_cfa_sf:
78107dc194Richard Lowe            {
78207dc194Richard Lowe                /* The first operand is an unsigned leb128 register
78307dc194Richard Lowe                   number. The second is a signed leb128 factored
78407dc194Richard Lowe                   offset. Identical to DW_CFA_def_cfa except that the
78507dc194Richard Lowe                   second operand is signed and factored. */
78607dc194Richard Lowe                Dwarf_Unsigned lreg;
78707dc194Richard Lowe
78807dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
78907dc194Richard Lowe                reg_no = (reg_num_type) lreg;
79007dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
79107dc194Richard Lowe
79207dc194Richard Lowe                signed_factored_N_value =
79307dc194Richard Lowe                    _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
79407dc194Richard Lowe                instr_ptr += leb128_length;
79507dc194Richard Lowe
79607dc194Richard Lowe                if (need_augmentation) {
79707dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
79807dc194Richard Lowe                }
79907dc194Richard Lowe                cfa_reg.ru_is_off = 1;
80007dc194Richard Lowe                cfa_reg.ru_value_type = DW_EXPR_OFFSET;
80107dc194Richard Lowe                cfa_reg.ru_register = reg_no;
80207dc194Richard Lowe                cfa_reg.ru_offset_or_block_len =
80307dc194Richard Lowe                    signed_factored_N_value * data_alignment_factor;
80407dc194Richard Lowe
80507dc194Richard Lowe                fp_register = reg_no;
80607dc194Richard Lowe                fp_offset = signed_factored_N_value;
80707dc194Richard Lowe            }
80807dc194Richard Lowe            break;
80907dc194Richard Lowe        case DW_CFA_def_cfa_offset_sf:
81007dc194Richard Lowe            {
81107dc194Richard Lowe                /* The operand is a signed leb128 operand representing
81207dc194Richard Lowe                   a factored offset.  Identical to
81307dc194Richard Lowe                   DW_CFA_def_cfa_offset excep the operand is signed
81407dc194Richard Lowe                   and factored. */
81507dc194Richard Lowe
81607dc194Richard Lowe                signed_factored_N_value =
81707dc194Richard Lowe                    _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
81807dc194Richard Lowe                instr_ptr += leb128_length;
81907dc194Richard Lowe
82007dc194Richard Lowe                if (need_augmentation) {
82107dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
82207dc194Richard Lowe                }
82307dc194Richard Lowe                /* Do set ru_is_off here, as here factored_N_value
82407dc194Richard Lowe                   counts.  */
82507dc194Richard Lowe                cfa_reg.ru_is_off = 1;
82607dc194Richard Lowe                cfa_reg.ru_value_type = DW_EXPR_OFFSET;
82707dc194Richard Lowe                cfa_reg.ru_offset_or_block_len =
82807dc194Richard Lowe                    signed_factored_N_value * data_alignment_factor;
82907dc194Richard Lowe
83007dc194Richard Lowe                fp_offset = signed_factored_N_value;
83107dc194Richard Lowe            }
83207dc194Richard Lowe            break;
83307dc194Richard Lowe        case DW_CFA_val_offset:
83407dc194Richard Lowe            {
83507dc194Richard Lowe                /* The first operand is an unsigned leb128 register
83607dc194Richard Lowe                   number. The second is a factored unsigned offset.
83707dc194Richard Lowe                   Makes the register be a val_offset(N) rule with N =
83807dc194Richard Lowe                   factored_offset*data_alignment_factor. */
83907dc194Richard Lowe
84007dc194Richard Lowe                Dwarf_Unsigned lreg;
84107dc194Richard Lowe
84207dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
84307dc194Richard Lowe                reg_no = (reg_num_type) lreg;
84407dc194Richard Lowe
84507dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
84607dc194Richard Lowe
84707dc194Richard Lowe                factored_N_value =
84807dc194Richard Lowe                    _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
84907dc194Richard Lowe                instr_ptr += leb128_length;
85007dc194Richard Lowe
85107dc194Richard Lowe                if (need_augmentation) {
85207dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
85307dc194Richard Lowe                }
85407dc194Richard Lowe                /* Do set ru_is_off here, as here factored_N_value
85507dc194Richard Lowe                   counts.  */
85607dc194Richard Lowe                localregtab[reg_no].ru_is_off = 1;
85707dc194Richard Lowe                localregtab[reg_no].ru_register = reg_num_of_cfa;
85807dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET;
85907dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len =
86007dc194Richard Lowe                    factored_N_value * data_alignment_factor;
86107dc194Richard Lowe
86207dc194Richard Lowe                fp_offset = factored_N_value;
86307dc194Richard Lowe                break;
86407dc194Richard Lowe            }
86507dc194Richard Lowe        case DW_CFA_val_offset_sf:
86607dc194Richard Lowe            {
86707dc194Richard Lowe                /* The first operand is an unsigned leb128 register
86807dc194Richard Lowe                   number. The second is a factored signed offset.
86907dc194Richard Lowe                   Makes the register be a val_offset(N) rule with N =
87007dc194Richard Lowe                   factored_offset*data_alignment_factor. */
87107dc194Richard Lowe                Dwarf_Unsigned lreg;
87207dc194Richard Lowe
87307dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
87407dc194Richard Lowe                reg_no = (reg_num_type) lreg;
87507dc194Richard Lowe
87607dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
87707dc194Richard Lowe                signed_factored_N_value =
87807dc194Richard Lowe                    _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
87907dc194Richard Lowe                instr_ptr += leb128_length;
88007dc194Richard Lowe
88107dc194Richard Lowe                if (need_augmentation) {
88207dc194Richard Lowe                    SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
88307dc194Richard Lowe                }
88407dc194Richard Lowe                /* Do set ru_is_off here, as here factored_N_value
88507dc194Richard Lowe                   counts.  */
88607dc194Richard Lowe                localregtab[reg_no].ru_is_off = 1;
88707dc194Richard Lowe                localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET;
88807dc194Richard Lowe                localregtab[reg_no].ru_offset_or_block_len =
88907dc194Richard Lowe                    signed_factored_N_value * data_alignment_factor;
89007dc194Richard Lowe
89107dc194Richard Lowe                fp_offset = signed_factored_N_value;
89207dc194Richard Lowe
89307dc194Richard Lowe            }
89407dc194Richard Lowe            break;
89507dc194Richard Lowe        case DW_CFA_val_expression:
89607dc194Richard Lowe            {
89707dc194Richard Lowe                /* The first operand is an unsigned leb128 register
89807dc194Richard Lowe                   number. The second is a DW_FORM_block representing a
89907dc194Richard Lowe                   DWARF expression. The rule for the register number
90007dc194Richard Lowe                   becomes a val_expression(E) rule. */
90107dc194Richard Lowe                Dwarf_Unsigned lreg = 0;
90207dc194Richard Lowe                Dwarf_Unsigned block_len = 0;
90307dc194Richard Lowe
90407dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
90507dc194Richard Lowe                reg_no = (reg_num_type) lreg;
90607dc194Richard Lowe                ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
90707dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, block_len);
90807dc194Richard Lowe                localregtab[lreg].ru_is_off = 0;        /* arbitrary */
90907dc194Richard Lowe                localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION;
91007dc194Richard Lowe                localregtab[lreg].ru_offset_or_block_len = block_len;
91107dc194Richard Lowe                localregtab[lreg].ru_block = instr_ptr;
91207dc194Richard Lowe                fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr;
91307dc194Richard Lowe
91407dc194Richard Lowe                instr_ptr += block_len;
91507dc194Richard Lowe                fp_register = reg_no;
91607dc194Richard Lowe
91707dc194Richard Lowe            }
91807dc194Richard Lowe            break;
91907dc194Richard Lowe
92007dc194Richard Lowe            /* END DWARF3 new ops. */
92149d3bc9Richard Lowe
92249d3bc9Richard Lowe
92349d3bc9Richard Lowe#ifdef DW_CFA_GNU_window_save
92407dc194Richard Lowe        case DW_CFA_GNU_window_save:
92507dc194Richard Lowe            {
92607dc194Richard Lowe                /* no information: this just tells unwinder to restore
92707dc194Richard Lowe                   the window registers from the previous frame's
92807dc194Richard Lowe                   window save area */
92907dc194Richard Lowe                break;
93007dc194Richard Lowe            }
93149d3bc9Richard Lowe#endif
93249d3bc9Richard Lowe#ifdef  DW_CFA_GNU_args_size
93307dc194Richard Lowe            /* single uleb128 is the current arg area size in bytes. No
93407dc194Richard Lowe               register exists yet to save this in */
93507dc194Richard Lowe        case DW_CFA_GNU_args_size:
93607dc194Richard Lowe            {
93707dc194Richard Lowe                Dwarf_Unsigned lreg;
93849d3bc9Richard Lowe
93907dc194Richard Lowe                DECODE_LEB128_UWORD(instr_ptr, lreg);
94007dc194Richard Lowe                reg_no = (reg_num_type) lreg;
94149d3bc9Richard Lowe
94207dc194Richard Lowe                break;
94307dc194Richard Lowe            }
94449d3bc9Richard Lowe#endif
94507dc194Richard Lowe        default:
94607dc194Richard Lowe            /* ERROR, we have an opcode we know nothing about. Memory
94707dc194Richard Lowe               leak here, but an error like this is not supposed to
94807dc194Richard Lowe               happen so we ignore the leak. These used to be ignored,
94907dc194Richard Lowe               now we notice and report. */
95107dc194Richard Lowe
95207dc194Richard Lowe        }
95307dc194Richard Lowe
95407dc194Richard Lowe        if (make_instr) {
95507dc194Richard Lowe            instr_count++;
95607dc194Richard Lowe
95707dc194Richard Lowe            curr_instr = (Dwarf_Frame_Op *)
95807dc194Richard Lowe                _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1);
95907dc194Richard Lowe            if (curr_instr == NULL) {
96007dc194Richard Lowe                SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
96107dc194Richard Lowe            }
96207dc194Richard Lowe
96307dc194Richard Lowe            curr_instr->fp_base_op = fp_base_op;
96407dc194Richard Lowe            curr_instr->fp_extended_op = fp_extended_op;
96507dc194Richard Lowe            curr_instr->fp_register = fp_register;
96607dc194Richard Lowe            curr_instr->fp_offset = fp_offset;
96707dc194Richard Lowe            curr_instr->fp_instr_offset = fp_instr_offset;
96807dc194Richard Lowe
96907dc194Richard Lowe            curr_instr_item = (Dwarf_Chain)
97007dc194Richard Lowe                _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
97107dc194Richard Lowe            if (curr_instr_item == NULL) {
97207dc194Richard Lowe                SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
97307dc194Richard Lowe            }
97407dc194Richard Lowe
97507dc194Richard Lowe            curr_instr_item->ch_item = curr_instr;
97607dc194Richard Lowe            if (head_instr_chain == NULL)
97707dc194Richard Lowe                head_instr_chain = tail_instr_chain = curr_instr_item;
97807dc194Richard Lowe            else {
97907dc194Richard Lowe                tail_instr_chain->ch_next = curr_instr_item;
98007dc194Richard Lowe                tail_instr_chain = curr_instr_item;
98107dc194Richard Lowe            }
98207dc194Richard Lowe        }
98349d3bc9Richard Lowe    }
98449d3bc9Richard Lowe
98549d3bc9Richard Lowe    /*
98607dc194Richard Lowe       If frame instruction decoding was right we would stop exactly at
98707dc194Richard Lowe       final_instr_ptr. */
98849d3bc9Richard Lowe    if (instr_ptr > final_instr_ptr) {
99049d3bc9Richard Lowe    }
99149d3bc9Richard Lowe
99207dc194Richard Lowe    /* Fill in the actual output table, the space the caller passed in. */
99349d3bc9Richard Lowe    if (table != NULL) {
99407dc194Richard Lowe
99507dc194Richard Lowe        struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg;
99607dc194Richard Lowe        struct Dwarf_Reg_Rule_s *t3reg = localregtab;
99707dc194Richard Lowe        struct Dwarf_Reg_Rule_s *t3end = t3reg + reg_count;
99807dc194Richard Lowe
99907dc194Richard Lowe        table->fr_loc = current_loc;
100007dc194Richard Lowe        for (; t3reg < t3end; t3reg++, t2reg++) {
100107dc194Richard Lowe            *t2reg = *t3reg;
100207dc194Richard Lowe        }
100307dc194Richard Lowe
100407dc194Richard Lowe        /* CONSTCOND */
100507dc194Richard Lowe        /* Do not update the main table with the cfa_reg.
100607dc194Richard Lowe           Just leave cfa_reg as cfa_reg. */
100707dc194Richard Lowe        table->fr_cfa_rule = cfa_reg;
100849d3bc9Richard Lowe    }
100949d3bc9Richard Lowe
101049d3bc9Richard Lowe    /* Dealloc anything remaining on stack. */
101149d3bc9Richard Lowe    for (; top_stack != NULL;) {
101207dc194Richard Lowe        stack_table = top_stack;
101307dc194Richard Lowe        top_stack = top_stack->fr_next;
101407dc194Richard Lowe        dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
101549d3bc9Richard Lowe    }
101649d3bc9Richard Lowe
101749d3bc9Richard Lowe    if (make_instr) {
101807dc194Richard Lowe        /* Allocate list of pointers to Dwarf_Frame_Op's.  */
101907dc194Richard Lowe        head_instr_block = (Dwarf_Frame_Op *)
102007dc194Richard Lowe            _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count);
102107dc194Richard Lowe        if (head_instr_block == NULL) {
102207dc194Richard Lowe            SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
102307dc194Richard Lowe        }
102407dc194Richard Lowe
102507dc194Richard Lowe        /*
102607dc194Richard Lowe           Store pointers to Dwarf_Frame_Op's in this list and
102707dc194Richard Lowe           deallocate the structs that chain the Dwarf_Frame_Op's. */
102807dc194Richard Lowe        curr_instr_item = head_instr_chain;
102907dc194Richard Lowe        for (i = 0; i < instr_count; i++) {
103007dc194Richard Lowe            *(head_instr_block + i) =
103107dc194Richard Lowe                *(Dwarf_Frame_Op *) curr_instr_item->ch_item;
103207dc194Richard Lowe            dealloc_instr_item = curr_instr_item;
103307dc194Richard Lowe            curr_instr_item = curr_instr_item->ch_next;
103407dc194Richard Lowe            dwarf_dealloc(dbg, dealloc_instr_item->ch_item,
103507dc194Richard Lowe                          DW_DLA_FRAME_OP);
103607dc194Richard Lowe            dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN);
103707dc194Richard Lowe        }
103807dc194Richard Lowe        *ret_frame_instr = head_instr_block;
103907dc194Richard Lowe
104007dc194Richard Lowe        *returned_count = (Dwarf_Sword) instr_count;
104149d3bc9Richard Lowe    } else {
104207dc194Richard Lowe        *returned_count = 0;
104349d3bc9Richard Lowe    }
104407dc194Richard Lowe    free(localregtab);
104549d3bc9Richard Lowe    return DW_DLV_OK;
104607dc194Richard Lowe#undef ERROR_IF_REG_NUM_TOO_HIGH
104707dc194Richard Lowe#undef SIMPLE_ERROR_RETURN
104849d3bc9Richard Lowe}
104949d3bc9Richard Lowe
105007dc194Richard Lowe/*  Depending on version, either read the return address register
105107dc194Richard Lowe    as a ubyte or as an leb number.
105207dc194Richard Lowe    The form of this value changed for DWARF3.
105307dc194Richard Lowe*/
105407dc194Richard LoweDwarf_Unsigned
105507dc194Richard Lowe_dwarf_get_return_address_reg(Dwarf_Small * frame_ptr,
105607dc194Richard Lowe    int version, unsigned long *size)
105749d3bc9Richard Lowe{
105807dc194Richard Lowe    Dwarf_Unsigned uvalue = 0;
105907dc194Richard Lowe    Dwarf_Word leb128_length = 0;
106049d3bc9Richard Lowe
106107dc194Richard Lowe    if (version == 1) {
106207dc194Richard Lowe        *size = 1;
106307dc194Richard Lowe        uvalue = *(unsigned char *) frame_ptr;
106407dc194Richard Lowe        return uvalue;
106549d3bc9Richard Lowe    }
106607dc194Richard Lowe    uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length);
106707dc194Richard Lowe    *size = leb128_length;
106807dc194Richard Lowe    return uvalue;
106949d3bc9Richard Lowe}
107049d3bc9Richard Lowe
107149d3bc9Richard Lowe
107207dc194Richard Lowe/* Trivial consumer function.
107307dc194Richard Lowe*/
107449d3bc9Richard Loweint
107549d3bc9Richard Lowedwarf_get_cie_of_fde(Dwarf_Fde fde,
107607dc194Richard Lowe    Dwarf_Cie * cie_returned, Dwarf_Error * error)
107749d3bc9Richard Lowe{
107849d3bc9Richard Lowe    if (fde == NULL) {
107907dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
108007dc194Richard Lowe        return (DW_DLV_ERROR);
108149d3bc9Richard Lowe    }
108249d3bc9Richard Lowe
108349d3bc9Richard Lowe    *cie_returned = fde->fd_cie;
108449d3bc9Richard Lowe    return DW_DLV_OK;
108549d3bc9Richard Lowe
108649d3bc9Richard Lowe}
108749d3bc9Richard Lowe
108807dc194Richard Loweint dwarf_get_cie_index(
108907dc194Richard Lowe    Dwarf_Cie cie,
109007dc194Richard Lowe    Dwarf_Signed* index,
109107dc194Richard Lowe    Dwarf_Error* error )
109207dc194Richard Lowe{
109307dc194Richard Lowe    if( cie == NULL )
109407dc194Richard Lowe    {
109507dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
109607dc194Richard Lowe        return (DW_DLV_ERROR);
109707dc194Richard Lowe    }
109807dc194Richard Lowe
109907dc194Richard Lowe    *index = cie->ci_index;
110007dc194Richard Lowe    return (DW_DLV_OK);
110107dc194Richard Lowe}
110207dc194Richard Lowe
110307dc194Richard Lowe
110449d3bc9Richard Lowe/*
110549d3bc9Richard Lowe  For g++ .eh_frame fde and cie.
110649d3bc9Richard Lowe  the cie id is different as the
110749d3bc9Richard Lowe  definition of the cie_id in an fde
110807dc194Richard Lowe        is the distance back from the address of the
110907dc194Richard Lowe        value to the cie.
111049d3bc9Richard Lowe  Or 0 if this is a true cie.
111149d3bc9Richard Lowe  Non standard dwarf, designed this way to be
111249d3bc9Richard Lowe  convenient at run time for an allocated
111349d3bc9Richard Lowe  (mapped into memory as part of the running image) section.
111449d3bc9Richard Lowe*/
111549d3bc9Richard Loweint
111649d3bc9Richard Lowedwarf_get_fde_list_eh(Dwarf_Debug dbg,
111707dc194Richard Lowe    Dwarf_Cie ** cie_data,
111807dc194Richard Lowe    Dwarf_Signed * cie_element_count,
111907dc194Richard Lowe    Dwarf_Fde ** fde_data,
112007dc194Richard Lowe    Dwarf_Signed * fde_element_count,
112107dc194Richard Lowe    Dwarf_Error * error)
112249d3bc9Richard Lowe{
112307dc194Richard Lowe    int res = _dwarf_load_section(dbg, &dbg->de_debug_frame_eh_gnu,error);
112449d3bc9Richard Lowe    if (res != DW_DLV_OK) {
112507dc194Richard Lowe        return res;
112649d3bc9Richard Lowe    }
112749d3bc9Richard Lowe
112807dc194Richard Lowe    res = _dwarf_get_fde_list_internal(dbg,
112907dc194Richard Lowe        cie_data,
113007dc194Richard Lowe        cie_element_count,
113107dc194Richard Lowe        fde_data,
113207dc194Richard Lowe        fde_element_count,
113307dc194Richard Lowe        dbg->de_debug_frame_eh_gnu.dss_data,
113407dc194Richard Lowe        dbg->de_debug_frame_eh_gnu.dss_index,
113507dc194Richard Lowe        dbg->de_debug_frame_eh_gnu.dss_size,
113607dc194Richard Lowe        /* cie_id_value */ 0,
113707dc194Richard Lowe        /* use_gnu_cie_calc= */ 1,
113807dc194Richard Lowe        error);
113949d3bc9Richard Lowe    return res;
114049d3bc9Richard Lowe}
114149d3bc9Richard Lowe
114249d3bc9Richard Lowe
114349d3bc9Richard Lowe
114449d3bc9Richard Lowe/*
114549d3bc9Richard Lowe  For standard dwarf .debug_frame
114649d3bc9Richard Lowe  cie_id is -1  in a cie, and
114749d3bc9Richard Lowe  is the section offset in the .debug_frame section
114849d3bc9Richard Lowe  of the cie otherwise.  Standard dwarf
114949d3bc9Richard Lowe*/
115049d3bc9Richard Loweint
115149d3bc9Richard Lowedwarf_get_fde_list(Dwarf_Debug dbg,
115207dc194Richard Lowe    Dwarf_Cie ** cie_data,
115307dc194Richard Lowe    Dwarf_Signed * cie_element_count,
115407dc194Richard Lowe    Dwarf_Fde ** fde_data,
115507dc194Richard Lowe    Dwarf_Signed * fde_element_count,
115607dc194Richard Lowe    Dwarf_Error * error)
115749d3bc9Richard Lowe{
115807dc194Richard Lowe    int res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
115949d3bc9Richard Lowe    if (res != DW_DLV_OK) {
116007dc194Richard Lowe        return res;
116149d3bc9Richard Lowe    }
116249d3bc9Richard Lowe
116307dc194Richard Lowe    res = _dwarf_get_fde_list_internal(dbg, cie_data,
116407dc194Richard Lowe        cie_element_count,
116507dc194Richard Lowe        fde_data,
116607dc194Richard Lowe        fde_element_count,
116707dc194Richard Lowe        dbg->de_debug_frame.dss_data,
116807dc194Richard Lowe        dbg->de_debug_frame.dss_index,
116907dc194Richard Lowe        dbg->de_debug_frame.dss_size,
117007dc194Richard Lowe        DW_CIE_ID,
117107dc194Richard Lowe        /* use_gnu_cie_calc= */ 0,
117207dc194Richard Lowe        error);
117307dc194Richard Lowe
117449d3bc9Richard Lowe    return res;
117549d3bc9Richard Lowe}
117649d3bc9Richard Lowe
117749d3bc9Richard Lowe
117849d3bc9Richard Lowe/*
117949d3bc9Richard Lowe   Only works on dwarf sections, not eh_frame
118007dc194Richard Lowe   Given a Dwarf_Die, see if it has a
118107dc194Richard Lowe   DW_AT_MIPS_fde attribute and if so use that
118207dc194Richard Lowe   to get an fde offset.
118307dc194Richard Lowe   Then create a Dwarf_Fde to return thru the ret_fde pointer.
118407dc194Richard Lowe   Also creates a cie (pointed at from the Dwarf_Fde).
118549d3bc9Richard Lowe*/
118649d3bc9Richard Loweint
118749d3bc9Richard Lowedwarf_get_fde_for_die(Dwarf_Debug dbg,
118807dc194Richard Lowe    Dwarf_Die die,
118907dc194Richard Lowe    Dwarf_Fde * ret_fde, Dwarf_Error * error)
119049d3bc9Richard Lowe{
119149d3bc9Richard Lowe    Dwarf_Attribute attr;
119207dc194Richard Lowe    Dwarf_Unsigned fde_offset = 0;
119307dc194Richard Lowe    Dwarf_Signed signdval = 0;
119407dc194Richard Lowe    Dwarf_Fde new_fde = 0;
119507dc194Richard Lowe    unsigned char *fde_ptr = 0;
119607dc194Richard Lowe    unsigned char *cie_ptr = 0;
119707dc194Richard Lowe    Dwarf_Unsigned cie_id = 0;
119849d3bc9Richard Lowe
119949d3bc9Richard Lowe    /* Fields for the current Cie being read. */
120007dc194Richard Lowe    int res = 0;
120107dc194Richard Lowe    int resattr = 0;
120207dc194Richard Lowe    int sdatares = 0;
120349d3bc9Richard Lowe
120407dc194Richard Lowe    struct cie_fde_prefix_s prefix;
120507dc194Richard Lowe    struct cie_fde_prefix_s prefix_c;
120649d3bc9Richard Lowe
120749d3bc9Richard Lowe    if (die == NULL) {
120807dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_DIE_NULL);
120907dc194Richard Lowe        return (DW_DLV_ERROR);
121049d3bc9Richard Lowe    }
121149d3bc9Richard Lowe
121249d3bc9Richard Lowe    resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error);
121349d3bc9Richard Lowe    if (resattr != DW_DLV_OK) {
121407dc194Richard Lowe        return resattr;
121549d3bc9Richard Lowe    }
121649d3bc9Richard Lowe
121749d3bc9Richard Lowe    /* why is this formsdata? FIX */
121849d3bc9Richard Lowe    sdatares = dwarf_formsdata(attr, &signdval, error);
121949d3bc9Richard Lowe    if (sdatares != DW_DLV_OK) {
122007dc194Richard Lowe        return sdatares;
122149d3bc9Richard Lowe    }
122249d3bc9Richard Lowe
122307dc194Richard Lowe    res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
122449d3bc9Richard Lowe    if (res != DW_DLV_OK) {
122507dc194Richard Lowe        return res;
122649d3bc9Richard Lowe    }
122749d3bc9Richard Lowe
122849d3bc9Richard Lowe    fde_offset = signdval;
122907dc194Richard Lowe    fde_ptr = (dbg->de_debug_frame.dss_data + fde_offset);
123007dc194Richard Lowe
123107dc194Richard Lowe
123207dc194Richard Lowe    /* First read in the 'common prefix' to figure out what * we are to
123307dc194Richard Lowe       do with this entry. */
123407dc194Richard Lowe    memset(&prefix_c, 0, sizeof(prefix_c));
123507dc194Richard Lowe    memset(&prefix, 0, sizeof(prefix));
123607dc194Richard Lowe    res = dwarf_read_cie_fde_prefix(dbg, fde_ptr,
123707dc194Richard Lowe        dbg->de_debug_frame.dss_data,
123807dc194Richard Lowe        dbg->de_debug_frame.dss_index,
123907dc194Richard Lowe        dbg->de_debug_frame.dss_size,
124007dc194Richard Lowe        &prefix,
124107dc194Richard Lowe        error);
124207dc194Richard Lowe    if (res == DW_DLV_ERROR) {
124307dc194Richard Lowe        return res;
124449d3bc9Richard Lowe    }
124507dc194Richard Lowe    if (res == DW_DLV_NO_ENTRY)
124607dc194Richard Lowe        return res;
124707dc194Richard Lowe    fde_ptr = prefix.cf_addr_after_prefix;
124807dc194Richard Lowe    cie_id = prefix.cf_cie_id;
124907dc194Richard Lowe    /* Pass NULL, not section pointer, for 3rd argument.
125007dc194Richard Lowe       de_debug_frame.dss_data has no eh_frame relevance. */
125107dc194Richard Lowe    res = dwarf_create_fde_from_after_start(dbg, &prefix,
125207dc194Richard Lowe        (Dwarf_Small *) NULL,
125307dc194Richard Lowe        fde_ptr,
125407dc194Richard Lowe        /* use_gnu_cie_calc= */ 0,
125507dc194Richard Lowe        /* Dwarf_Cie = */ 0,
125607dc194Richard Lowe        &new_fde, error);
125707dc194Richard Lowe    if (res == DW_DLV_ERROR) {
125807dc194Richard Lowe        return res;
125907dc194Richard Lowe    } else if (res == DW_DLV_NO_ENTRY) {
126007dc194Richard Lowe        return res;
126107dc194Richard Lowe    }
126207dc194Richard Lowe    /* DW_DLV_OK */
126349d3bc9Richard Lowe
126449d3bc9Richard Lowe    /* now read the cie corresponding to the fde */
126507dc194Richard Lowe    cie_ptr = new_fde->fd_section_ptr + cie_id;
126607dc194Richard Lowe    res = dwarf_read_cie_fde_prefix(dbg, cie_ptr,
126707dc194Richard Lowe        dbg->de_debug_frame.dss_data,
126807dc194Richard Lowe        dbg->de_debug_frame.dss_index,
126907dc194Richard Lowe        dbg->de_debug_frame.dss_size,
127007dc194Richard Lowe        &prefix_c, error);
127107dc194Richard Lowe    if (res == DW_DLV_ERROR) {
127207dc194Richard Lowe        return res;
127307dc194Richard Lowe    }
127407dc194Richard Lowe    if (res == DW_DLV_NO_ENTRY)
127507dc194Richard Lowe        return res;
127607dc194Richard Lowe
127707dc194Richard Lowe    cie_ptr = prefix_c.cf_addr_after_prefix;
127807dc194Richard Lowe    cie_id = prefix_c.cf_cie_id;
127907dc194Richard Lowe
128007dc194Richard Lowe    if (cie_id == DW_CIE_ID) {
128107dc194Richard Lowe        int res2 = 0;
128207dc194Richard Lowe        Dwarf_Cie new_cie = 0;
128307dc194Richard Lowe
128407dc194Richard Lowe        /* Pass NULL, not section pointer, for 3rd argument.
128507dc194Richard Lowe           de_debug_frame.dss_data has no eh_frame relevance. */
128607dc194Richard Lowe        res2 = dwarf_create_cie_from_after_start(dbg,
128707dc194Richard Lowe            &prefix_c,
128807dc194Richard Lowe            (Dwarf_Small *) NULL,
128907dc194Richard Lowe            cie_ptr,
129007dc194Richard Lowe            /* cie_count= */ 0,
129107dc194Richard Lowe            /* use_gnu_cie_calc= */
129207dc194Richard Lowe            0, &new_cie, error);
129307dc194Richard Lowe        if (res2 == DW_DLV_ERROR) {
129407dc194Richard Lowe            dwarf_dealloc(dbg, new_fde, DW_DLA_FDE);
129507dc194Richard Lowe            return res;
129607dc194Richard Lowe        } else if (res2 == DW_DLV_NO_ENTRY) {
129707dc194Richard Lowe            dwarf_dealloc(dbg, new_fde, DW_DLA_FDE);
129807dc194Richard Lowe            return res;
129907dc194Richard Lowe        }
130007dc194Richard Lowe        new_fde->fd_cie = new_cie;
130149d3bc9Richard Lowe    } else {
130207dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
130307dc194Richard Lowe        return (DW_DLV_ERROR);
130449d3bc9Richard Lowe    }
130549d3bc9Richard Lowe
130649d3bc9Richard Lowe    *ret_fde = new_fde;
130749d3bc9Richard Lowe    return DW_DLV_OK;
130849d3bc9Richard Lowe}
130949d3bc9Richard Lowe
131007dc194Richard Lowe/* A dwarf consumer operation, see the consumer library documentation.
131107dc194Richard Lowe*/
131249d3bc9Richard Loweint
131349d3bc9Richard Lowedwarf_get_fde_range(Dwarf_Fde fde,
131407dc194Richard Lowe    Dwarf_Addr * low_pc,
131507dc194Richard Lowe    Dwarf_Unsigned * func_length,
131607dc194Richard Lowe    Dwarf_Ptr * fde_bytes,
131707dc194Richard Lowe    Dwarf_Unsigned * fde_byte_length,
131807dc194Richard Lowe    Dwarf_Off * cie_offset,
131907dc194Richard Lowe    Dwarf_Signed * cie_index,
132007dc194Richard Lowe    Dwarf_Off * fde_offset, Dwarf_Error * error)
132149d3bc9Richard Lowe{
132249d3bc9Richard Lowe    Dwarf_Debug dbg;
132349d3bc9Richard Lowe
132449d3bc9Richard Lowe    if (fde == NULL) {
132507dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
132607dc194Richard Lowe        return (DW_DLV_ERROR);
132749d3bc9Richard Lowe    }
132849d3bc9Richard Lowe
132949d3bc9Richard Lowe    dbg = fde->fd_dbg;
133049d3bc9Richard Lowe    if (dbg == NULL) {
133107dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
133207dc194Richard Lowe        return (DW_DLV_ERROR);
133349d3bc9Richard Lowe    }
133449d3bc9Richard Lowe
133507dc194Richard Lowe
133607dc194Richard Lowe    /* We have always already done the section load here, so no need to
133707dc194Richard Lowe       load the section. We did the section load in order to create the
133807dc194Richard Lowe       Dwarf_Fde pointer passed in here. */
133907dc194Richard Lowe
134049d3bc9Richard Lowe
134149d3bc9Richard Lowe    if (low_pc != NULL)
134207dc194Richard Lowe        *low_pc = fde->fd_initial_location;
134349d3bc9Richard Lowe    if (func_length != NULL)
134407dc194Richard Lowe        *func_length = fde->fd_address_range;
134549d3bc9Richard Lowe    if (fde_bytes != NULL)
134607dc194Richard Lowe        *fde_bytes = fde->fd_fde_start;
134749d3bc9Richard Lowe    if (fde_byte_length != NULL)
134807dc194Richard Lowe        *fde_byte_length = fde->fd_length;
134949d3bc9Richard Lowe    if (cie_offset != NULL)
135007dc194Richard Lowe        *cie_offset = fde->fd_cie_offset;
135149d3bc9Richard Lowe    if (cie_index != NULL)
135207dc194Richard Lowe        *cie_index = fde->fd_cie_index;
135349d3bc9Richard Lowe    if (fde_offset != NULL)
135407dc194Richard Lowe        *fde_offset = fde->fd_fde_start - fde->fd_section_ptr;
135549d3bc9Richard Lowe
135649d3bc9Richard Lowe    return DW_DLV_OK;
135749d3bc9Richard Lowe}
135849d3bc9Richard Lowe
135907dc194Richard Lowe/* IRIX specific function.   The exception tables
136007dc194Richard Lowe   have C++ destructor information and are
136107dc194Richard Lowe   at present undocumented.  */
136249d3bc9Richard Loweint
136349d3bc9Richard Lowedwarf_get_fde_exception_info(Dwarf_Fde fde,
136407dc194Richard Lowe    Dwarf_Signed *
136507dc194Richard Lowe    offset_into_exception_tables,
136607dc194Richard Lowe    Dwarf_Error * error)
136749d3bc9Richard Lowe{
136849d3bc9Richard Lowe    Dwarf_Debug dbg;
136949d3bc9Richard Lowe
137049d3bc9Richard Lowe    dbg = fde->fd_dbg;
137149d3bc9Richard Lowe    if (dbg == NULL) {
137207dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
137307dc194Richard Lowe        return (DW_DLV_ERROR);
137449d3bc9Richard Lowe    }
137549d3bc9Richard Lowe    *offset_into_exception_tables =
137607dc194Richard Lowe        fde->fd_offset_into_exception_tables;
137749d3bc9Richard Lowe    return DW_DLV_OK;
137849d3bc9Richard Lowe}
137949d3bc9Richard Lowe
138049d3bc9Richard Lowe
138107dc194Richard Lowe/* A consumer code function.
138207dc194Richard Lowe   Given a CIE pointer, return the normal CIE data thru
138307dc194Richard Lowe   pointers.
138407dc194Richard Lowe   Special augmentation data is not returned here.
138507dc194Richard Lowe*/
138649d3bc9Richard Loweint
138749d3bc9Richard Lowedwarf_get_cie_info(Dwarf_Cie cie,
138807dc194Richard Lowe    Dwarf_Unsigned * bytes_in_cie,
138907dc194Richard Lowe    Dwarf_Small * ptr_to_version,
139007dc194Richard Lowe    char **augmenter,
139107dc194Richard Lowe    Dwarf_Unsigned * code_alignment_factor,
139207dc194Richard Lowe    Dwarf_Signed * data_alignment_factor,
139307dc194Richard Lowe    Dwarf_Half * return_address_register,
139407dc194Richard Lowe    Dwarf_Ptr * initial_instructions,
139507dc194Richard Lowe    Dwarf_Unsigned * initial_instructions_length,
139607dc194Richard Lowe    Dwarf_Error * error)
139749d3bc9Richard Lowe{
139849d3bc9Richard Lowe    Dwarf_Debug dbg;
139949d3bc9Richard Lowe
140049d3bc9Richard Lowe    if (cie == NULL) {
140107dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
140207dc194Richard Lowe        return (DW_DLV_ERROR);
140349d3bc9Richard Lowe    }
140449d3bc9Richard Lowe
140549d3bc9Richard Lowe    dbg = cie->ci_dbg;
140649d3bc9Richard Lowe    if (dbg == NULL) {
140707dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL);
140807dc194Richard Lowe        return (DW_DLV_ERROR);
140949d3bc9Richard Lowe    }
141049d3bc9Richard Lowe
141107dc194Richard Lowe    if (ptr_to_version != NULL)
141207dc194Richard Lowe        *ptr_to_version = cie->ci_cie_version_number;
141349d3bc9Richard Lowe    if (augmenter != NULL)
141407dc194Richard Lowe        *augmenter = cie->ci_augmentation;
141549d3bc9Richard Lowe    if (code_alignment_factor != NULL)
141607dc194Richard Lowe        *code_alignment_factor = cie->ci_code_alignment_factor;
141749d3bc9Richard Lowe    if (data_alignment_factor != NULL)
141807dc194Richard Lowe        *data_alignment_factor = cie->ci_data_alignment_factor;
141949d3bc9Richard Lowe    if (return_address_register != NULL)
142007dc194Richard Lowe        *return_address_register = cie->ci_return_address_register;
142149d3bc9Richard Lowe    if (initial_instructions != NULL)
142207dc194Richard Lowe        *initial_instructions = cie->ci_cie_instr_start;
142349d3bc9Richard Lowe    if (initial_instructions_length != NULL) {
142407dc194Richard Lowe        *initial_instructions_length = cie->ci_length +
142507dc194Richard Lowe            cie->ci_length_size +
142607dc194Richard Lowe            cie->ci_extension_size -
142707dc194Richard Lowe            (cie->ci_cie_instr_start - cie->ci_cie_start);
142849d3bc9Richard Lowe
142949d3bc9Richard Lowe    }
143049d3bc9Richard Lowe    *bytes_in_cie = (cie->ci_length);
143149d3bc9Richard Lowe    return (DW_DLV_OK);
143249d3bc9Richard Lowe}
143349d3bc9Richard Lowe
143407dc194Richard Lowe/* Return the register rules for all registers at a given pc.
143507dc194Richard Lowe*/
143649d3bc9Richard Lowestatic int
143749d3bc9Richard Lowe_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde,
143807dc194Richard Lowe    Dwarf_Addr pc_requested,
143907dc194Richard Lowe    Dwarf_Frame table,
144007dc194Richard Lowe    Dwarf_Half cfa_reg_col_num,
144107dc194Richard Lowe    Dwarf_Error * error)
144249d3bc9Richard Lowe{
144307dc194Richard Lowe    Dwarf_Debug dbg = 0;
144407dc194Richard Lowe    Dwarf_Cie cie = 0;
144507dc194Richard Lowe    int dw_err = 0;
144607dc194Richard Lowe    Dwarf_Sword icount = 0;
144707dc194Richard Lowe    int res = 0;
144849d3bc9Richard Lowe
144949d3bc9Richard Lowe    if (fde == NULL) {
145007dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
145107dc194Richard Lowe        return (DW_DLV_ERROR);
145249d3bc9Richard Lowe    }
145349d3bc9Richard Lowe
145449d3bc9Richard Lowe    dbg = fde->fd_dbg;
145549d3bc9Richard Lowe    if (dbg == NULL) {
145607dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
145707dc194Richard Lowe        return (DW_DLV_ERROR);
145849d3bc9Richard Lowe    }
145949d3bc9Richard Lowe
146049d3bc9Richard Lowe    if (pc_requested < fde->fd_initial_location ||
146107dc194Richard Lowe        pc_requested >=
146207dc194Richard Lowe        fde->fd_initial_location + fde->fd_address_range) {
146307dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
146407dc194Richard Lowe        return (DW_DLV_ERROR);
146549d3bc9Richard Lowe    }
146649d3bc9Richard Lowe
146749d3bc9Richard Lowe    cie = fde->fd_cie;
146849d3bc9Richard Lowe    if (cie->ci_initial_table == NULL) {
146907dc194Richard Lowe        cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
147007dc194Richard Lowe
147107dc194Richard Lowe        if (cie->ci_initial_table == NULL) {
147207dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
147307dc194Richard Lowe            return (DW_DLV_ERROR);
147407dc194Richard Lowe        }
147507dc194Richard Lowe        _dwarf_init_regrule_table(cie->ci_initial_table->fr_reg,
147607dc194Richard Lowe            dbg->de_frame_reg_rules_entry_count,
147707dc194Richard Lowe            dbg->de_frame_rule_initial_value);
147807dc194Richard Lowe        _dwarf_init_regrule_table(&cie->ci_initial_table->fr_cfa_rule,
147907dc194Richard Lowe            1, dbg->de_frame_rule_initial_value);
148007dc194Richard Lowe        res = _dwarf_exec_frame_instr( /* make_instr= */ false,
148107dc194Richard Lowe            /* ret_frame_instr= */ NULL,
148207dc194Richard Lowe            /* search_pc */ false,
148307dc194Richard Lowe            /* search_pc_val */ 0,
148407dc194Richard Lowe            /* location */ 0,
148507dc194Richard Lowe            cie->ci_cie_instr_start,
148607dc194Richard Lowe            cie->ci_cie_instr_start + (cie->ci_length +
148707dc194Richard Lowe                cie->ci_length_size +
148807dc194Richard Lowe                cie->ci_extension_size -
148907dc194Richard Lowe                (cie->ci_cie_instr_start -
149007dc194Richard Lowe                cie->ci_cie_start)),
149107dc194Richard Lowe            cie->ci_initial_table, cie, dbg,
149207dc194Richard Lowe            cfa_reg_col_num, &icount,
149307dc194Richard Lowe            &dw_err);
149407dc194Richard Lowe        if (res == DW_DLV_ERROR) {
149507dc194Richard Lowe            _dwarf_error(dbg, error, dw_err);
149607dc194Richard Lowe            return (res);
149707dc194Richard Lowe        } else if (res == DW_DLV_NO_ENTRY) {
149807dc194Richard Lowe            return res;
149907dc194Richard Lowe        }
150007dc194Richard Lowe    }
150107dc194Richard Lowe
150207dc194Richard Lowe    {
150307dc194Richard Lowe        Dwarf_Small *instr_end = fde->fd_fde_instr_start +
150407dc194Richard Lowe            fde->fd_length +
150507dc194Richard Lowe            fde->fd_length_size +
150607dc194Richard Lowe            fde->fd_extension_size - (fde->fd_fde_instr_start -
150707dc194Richard Lowe                                      fde->fd_fde_start);
150807dc194Richard Lowe
150907dc194Richard Lowe        res = _dwarf_exec_frame_instr( /* make_instr= */ false,
151007dc194Richard Lowe            /* ret_frame_instr= */ NULL,
151107dc194Richard Lowe            /* search_pc */ true,
151207dc194Richard Lowe            /* search_pc_val */ pc_requested,
151307dc194Richard Lowe            fde->fd_initial_location,
151407dc194Richard Lowe            fde->fd_fde_instr_start,
151507dc194Richard Lowe            instr_end,
151607dc194Richard Lowe            table,
151707dc194Richard Lowe            cie, dbg,
151807dc194Richard Lowe            cfa_reg_col_num, &icount,
151907dc194Richard Lowe            &dw_err);
152007dc194Richard Lowe    }
152149d3bc9Richard Lowe    if (res == DW_DLV_ERROR) {
152207dc194Richard Lowe        _dwarf_error(dbg, error, dw_err);
152307dc194Richard Lowe        return (res);
152449d3bc9Richard Lowe    } else if (res == DW_DLV_NO_ENTRY) {
152507dc194Richard Lowe        return res;
152649d3bc9Richard Lowe    }
152749d3bc9Richard Lowe
152849d3bc9Richard Lowe    return DW_DLV_OK;
152949d3bc9Richard Lowe}
153049d3bc9Richard Lowe
153107dc194Richard Lowe/* A consumer call for efficiently getting the register info
153207dc194Richard Lowe   for all registers in one call.
153307dc194Richard Lowe
153407dc194Richard Lowe   The output table rules array is size DW_REG_TABLE_SIZE.
153507dc194Richard Lowe   The frame info  rules array in fde_table is of size
153607dc194Richard Lowe   DW_REG_TABLE_SIZE too.
153707dc194Richard Lowe
153807dc194Richard Lowe   This interface  really only works well with MIPS/IRIX
153907dc194Richard Lowe   where DW_FRAME_CFA_COL is zero (in that case it's safe).
154007dc194Richard Lowe
154107dc194Richard Lowe   It is also restricted to the case  where
154207dc194Richard Lowe   DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM  ==
154307dc194Richard Lowe   dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX).
154407dc194Richard Lowe   If this condition is not met calling this routine can result in
154507dc194Richard Lowe   incorrect output or in memory corruption.
154607dc194Richard Lowe
154707dc194Richard Lowe   It is much better to use dwarf_get_fde_info_for_all_regs3()
154807dc194Richard Lowe   instead of this interface.
154907dc194Richard Lowe*/
155049d3bc9Richard Loweint
155149d3bc9Richard Lowedwarf_get_fde_info_for_all_regs(Dwarf_Fde fde,
155207dc194Richard Lowe    Dwarf_Addr pc_requested,
155307dc194Richard Lowe    Dwarf_Regtable * reg_table,
155407dc194Richard Lowe    Dwarf_Addr * row_pc,
155507dc194Richard Lowe    Dwarf_Error * error)
155649d3bc9Richard Lowe{
155749d3bc9Richard Lowe
155807dc194Richard Lowe    /* Table size: DW_REG_TABLE_SIZE */
155949d3bc9Richard Lowe    struct Dwarf_Frame_s fde_table;
156007dc194Richard Lowe    Dwarf_Sword i = 0;
156107dc194Richard Lowe    struct Dwarf_Reg_Rule_s *rule = NULL;
156207dc194Richard Lowe    struct Dwarf_Regtable_Entry_s *out_rule = NULL;
156307dc194Richard Lowe    int res = 0;
156407dc194Richard Lowe    Dwarf_Debug dbg = 0;
156507dc194Richard Lowe
156607dc194Richard Lowe    /* For this interface the size is fixed at compile time. */
156707dc194Richard Lowe    int output_table_real_data_size = DW_REG_TABLE_SIZE;
156807dc194Richard Lowe
156907dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
157007dc194Richard Lowe
157107dc194Richard Lowe    res = dwarf_initialize_fde_table(dbg, &fde_table,
157207dc194Richard Lowe        output_table_real_data_size,
157307dc194Richard Lowe        error);
157407dc194Richard Lowe    if (res != DW_DLV_OK)
157507dc194Richard Lowe        return res;
157649d3bc9Richard Lowe
157749d3bc9Richard Lowe    /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
157849d3bc9Richard Lowe     */
157949d3bc9Richard Lowe    res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
158007dc194Richard Lowe        &fde_table, dbg->de_frame_cfa_col_number, error);
158149d3bc9Richard Lowe    if (res != DW_DLV_OK) {
158207dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
158307dc194Richard Lowe        return res;
158449d3bc9Richard Lowe    }
158549d3bc9Richard Lowe
158607dc194Richard Lowe    out_rule = &reg_table->rules[0];
158707dc194Richard Lowe    rule = &fde_table.fr_reg[0];
158807dc194Richard Lowe    for (i = 0; i < output_table_real_data_size;
158907dc194Richard Lowe         i++, ++out_rule, ++rule) {
159007dc194Richard Lowe        out_rule->dw_offset_relevant = rule->ru_is_off;
159107dc194Richard Lowe        out_rule->dw_value_type = rule->ru_value_type;
159207dc194Richard Lowe        out_rule->dw_regnum = rule->ru_register;
159307dc194Richard Lowe        out_rule->dw_offset = rule->ru_offset_or_block_len;
159407dc194Richard Lowe    }
159507dc194Richard Lowe    for (; i < DW_REG_TABLE_SIZE; ++i, ++out_rule) {
159607dc194Richard Lowe        out_rule->dw_offset_relevant = 0;
159707dc194Richard Lowe        out_rule->dw_value_type = DW_EXPR_OFFSET;
159807dc194Richard Lowe        out_rule->dw_regnum = dbg->de_frame_undefined_value_number;
159907dc194Richard Lowe        out_rule->dw_offset = 0;
160007dc194Richard Lowe    }
160107dc194Richard Lowe
160207dc194Richard Lowe    /* The test is just in case it's not inside the table. For non-MIPS
160307dc194Richard Lowe       it could be outside the table and that is just fine, it was
160407dc194Richard Lowe       really a mistake to put it in the table in 1993.  */
160507dc194Richard Lowe    /* CONSTCOND */
160607dc194Richard Lowe    if (dbg->de_frame_cfa_col_number < DW_REG_TABLE_SIZE) {
160707dc194Richard Lowe        out_rule = &reg_table->rules[dbg->de_frame_cfa_col_number];
160807dc194Richard Lowe        out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
160907dc194Richard Lowe        out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type;
161007dc194Richard Lowe        out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register;
161107dc194Richard Lowe        out_rule->dw_offset =
161207dc194Richard Lowe            fde_table.fr_cfa_rule.ru_offset_or_block_len;
161349d3bc9Richard Lowe    }
161449d3bc9Richard Lowe
161549d3bc9Richard Lowe    if (row_pc != NULL)
161607dc194Richard Lowe        *row_pc = fde_table.fr_loc;
161707dc194Richard Lowe    dwarf_free_fde_table(&fde_table);
161807dc194Richard Lowe    return DW_DLV_OK;
161907dc194Richard Lowe}
162007dc194Richard Lowe
162107dc194Richard Lowe/* A consumer call for efficiently getting the register info
162207dc194Richard Lowe   for all registers in one call.
162307dc194Richard Lowe
162407dc194Richard Lowe   The output table rules array is size output_table_real_data_size.
162507dc194Richard Lowe   (normally  DW_REG_TABLE_SIZE).
162607dc194Richard Lowe   The frame info  rules array in fde_table is normally of size
162707dc194Richard Lowe   DW_FRAME_LAST_REG_NUM.
162807dc194Richard Lowe*/
162907dc194Richard Loweint
163007dc194Richard Lowedwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde,
163107dc194Richard Lowe    Dwarf_Addr pc_requested,
163207dc194Richard Lowe    Dwarf_Regtable3 * reg_table,
163307dc194Richard Lowe    Dwarf_Addr * row_pc,
163407dc194Richard Lowe    Dwarf_Error * error)
163507dc194Richard Lowe{
163607dc194Richard Lowe
163707dc194Richard Lowe    struct Dwarf_Frame_s fde_table;
163807dc194Richard Lowe    Dwarf_Sword i = 0;
163907dc194Richard Lowe    int res = 0;
164007dc194Richard Lowe    struct Dwarf_Reg_Rule_s *rule = NULL;
164107dc194Richard Lowe    struct Dwarf_Regtable_Entry3_s *out_rule = NULL;
164207dc194Richard Lowe    Dwarf_Debug dbg = 0;
164307dc194Richard Lowe    int output_table_real_data_size = reg_table->rt3_reg_table_size;
164407dc194Richard Lowe
164507dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
164607dc194Richard Lowe
164707dc194Richard Lowe    output_table_real_data_size =
164807dc194Richard Lowe        MIN(output_table_real_data_size,
164907dc194Richard Lowe            dbg->de_frame_reg_rules_entry_count);
165007dc194Richard Lowe
165107dc194Richard Lowe    res = dwarf_initialize_fde_table(dbg, &fde_table,
165207dc194Richard Lowe       output_table_real_data_size,
165307dc194Richard Lowe       error);
165407dc194Richard Lowe
165507dc194Richard Lowe    /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
165607dc194Richard Lowe     */
165707dc194Richard Lowe    res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
165807dc194Richard Lowe        &fde_table,
165907dc194Richard Lowe        dbg->de_frame_cfa_col_number,
166007dc194Richard Lowe        error);
166107dc194Richard Lowe    if (res != DW_DLV_OK) {
166207dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
166307dc194Richard Lowe        return res;
166407dc194Richard Lowe    }
166507dc194Richard Lowe
166607dc194Richard Lowe    out_rule = &reg_table->rt3_rules[0];
166707dc194Richard Lowe    rule = &fde_table.fr_reg[0];
166807dc194Richard Lowe    for (i = 0; i < output_table_real_data_size;
166907dc194Richard Lowe         i++, ++out_rule, ++rule) {
167007dc194Richard Lowe        out_rule->dw_offset_relevant = rule->ru_is_off;
167107dc194Richard Lowe        out_rule->dw_value_type = rule->ru_value_type;
167207dc194Richard Lowe        out_rule->dw_regnum = rule->ru_register;
167307dc194Richard Lowe        out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len;
167407dc194Richard Lowe        out_rule->dw_block_ptr = rule->ru_block;
167507dc194Richard Lowe    }
167607dc194Richard Lowe    for (; i < reg_table->rt3_reg_table_size; i++, ++out_rule) {
167707dc194Richard Lowe        out_rule->dw_offset_relevant = 0;
167807dc194Richard Lowe        out_rule->dw_value_type = DW_EXPR_OFFSET;
167907dc194Richard Lowe        out_rule->dw_regnum = dbg->de_frame_undefined_value_number;
168007dc194Richard Lowe        out_rule->dw_offset_or_block_len = 0;
168107dc194Richard Lowe        out_rule->dw_block_ptr = 0;
168207dc194Richard Lowe    }
168307dc194Richard Lowe    reg_table->rt3_cfa_rule.dw_offset_relevant =
168407dc194Richard Lowe        fde_table.fr_cfa_rule.ru_is_off;
168507dc194Richard Lowe    reg_table->rt3_cfa_rule.dw_value_type =
168607dc194Richard Lowe        fde_table.fr_cfa_rule.ru_value_type;
168707dc194Richard Lowe    reg_table->rt3_cfa_rule.dw_regnum =
168807dc194Richard Lowe        fde_table.fr_cfa_rule.ru_register;
168907dc194Richard Lowe    reg_table->rt3_cfa_rule.dw_offset_or_block_len =
169007dc194Richard Lowe        fde_table.fr_cfa_rule.ru_offset_or_block_len;
169107dc194Richard Lowe    reg_table->rt3_cfa_rule.dw_block_ptr =
169207dc194Richard Lowe        fde_table.fr_cfa_rule.ru_block;
169349d3bc9Richard Lowe
169407dc194Richard Lowe    if (row_pc != NULL)
169507dc194Richard Lowe        *row_pc = fde_table.fr_loc;
169607dc194Richard Lowe
169707dc194Richard Lowe    dwarf_free_fde_table(&fde_table);
169849d3bc9Richard Lowe    return DW_DLV_OK;
169949d3bc9Richard Lowe}
170049d3bc9Richard Lowe
170149d3bc9Richard Lowe
170207dc194Richard Lowe/* Gets the register info for a single register at a given PC value
170307dc194Richard Lowe   for the FDE specified.
170407dc194Richard Lowe
170507dc194Richard Lowe   This is the old MIPS interface and should no longer be used.
170607dc194Richard Lowe   Use dwarf_get_fde_info_for_reg3() instead.
170707dc194Richard Lowe*/
170849d3bc9Richard Loweint
170949d3bc9Richard Lowedwarf_get_fde_info_for_reg(Dwarf_Fde fde,
171007dc194Richard Lowe    Dwarf_Half table_column,
171107dc194Richard Lowe    Dwarf_Addr pc_requested,
171207dc194Richard Lowe    Dwarf_Signed * offset_relevant,
171307dc194Richard Lowe    Dwarf_Signed * register_num,
171407dc194Richard Lowe    Dwarf_Signed * offset,
171507dc194Richard Lowe    Dwarf_Addr * row_pc, Dwarf_Error * error)
171649d3bc9Richard Lowe{
171749d3bc9Richard Lowe    struct Dwarf_Frame_s fde_table;
171807dc194Richard Lowe    int res = DW_DLV_ERROR;
171907dc194Richard Lowe    Dwarf_Debug dbg = 0;
172007dc194Richard Lowe    int output_table_real_data_size = 0;
172149d3bc9Richard Lowe
172207dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
172307dc194Richard Lowe    output_table_real_data_size = dbg->de_frame_reg_rules_entry_count;
172449d3bc9Richard Lowe
172507dc194Richard Lowe    res = dwarf_initialize_fde_table(dbg, &fde_table,
172607dc194Richard Lowe        output_table_real_data_size,
172707dc194Richard Lowe        error);
172807dc194Richard Lowe    if (res != DW_DLV_OK)
172907dc194Richard Lowe        return res;
173007dc194Richard Lowe
173107dc194Richard Lowe    if (table_column >= output_table_real_data_size) {
173207dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
173307dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
173407dc194Richard Lowe        return (DW_DLV_ERROR);
173549d3bc9Richard Lowe    }
173649d3bc9Richard Lowe
173749d3bc9Richard Lowe    /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
173849d3bc9Richard Lowe     */
173949d3bc9Richard Lowe    res =
174007dc194Richard Lowe        _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
174107dc194Richard Lowe            dbg->de_frame_cfa_col_number, error);
174249d3bc9Richard Lowe    if (res != DW_DLV_OK) {
174307dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
174407dc194Richard Lowe        return res;
174549d3bc9Richard Lowe    }
174649d3bc9Richard Lowe
174707dc194Richard Lowe    if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) {
174807dc194Richard Lowe        /* The problem here is that this interface cannot deal with
174907dc194Richard Lowe           other sorts of (newer) dwarf frame values.  Code must
175007dc194Richard Lowe           use dwarf_get_fde_info_for_reg3() to get these
175107dc194Richard Lowe           values correctly.  We error rather than return
175207dc194Richard Lowe           misleading incomplete data. */
175307dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
175407dc194Richard Lowe        _dwarf_error(NULL, error,
175507dc194Richard Lowe            DW_DLE_FRAME_REGISTER_UNREPRESENTABLE);
175607dc194Richard Lowe        return (DW_DLV_ERROR);
175707dc194Richard Lowe    }
175807dc194Richard Lowe    if(table_column == dbg->de_frame_cfa_col_number) {
175907dc194Richard Lowe        if (register_num != NULL)
176007dc194Richard Lowe            *register_num = fde_table.fr_cfa_rule.ru_register;
176107dc194Richard Lowe        if (offset != NULL)
176207dc194Richard Lowe            *offset = fde_table.fr_cfa_rule.ru_offset_or_block_len;
176307dc194Richard Lowe        if (row_pc != NULL)
176407dc194Richard Lowe            *row_pc = fde_table.fr_loc;
176507dc194Richard Lowe        *offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
176607dc194Richard Lowe
176707dc194Richard Lowe    } else {
176807dc194Richard Lowe        if (register_num != NULL)
176907dc194Richard Lowe            *register_num = fde_table.fr_reg[table_column].ru_register;
177007dc194Richard Lowe        if (offset != NULL)
177107dc194Richard Lowe            *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len;
177207dc194Richard Lowe        if (row_pc != NULL)
177307dc194Richard Lowe            *row_pc = fde_table.fr_loc;
177407dc194Richard Lowe
177507dc194Richard Lowe        *offset_relevant = fde_table.fr_reg[table_column].ru_is_off;
177607dc194Richard Lowe    }
177707dc194Richard Lowe    dwarf_free_fde_table(&fde_table);
177807dc194Richard Lowe    return DW_DLV_OK;
177907dc194Richard Lowe}
178007dc194Richard Lowe
178107dc194Richard Lowe/* In this interface, table_column of DW_FRAME_CFA_COL
178207dc194Richard Lowe   is not meaningful.
178307dc194Richard Lowe   Use  dwarf_get_fde_info_for_cfa_reg3() to get the CFA.
178407dc194Richard Lowe   Call dwarf_set_frame_cfa_value() to set the correct column
178507dc194Richard Lowe   after calling dwarf_init()
178607dc194Richard Lowe   (DW_FRAME_CFA_COL3 is a sensible column to use).
178707dc194Richard Lowe*/
178807dc194Richard Loweint
178907dc194Richard Lowedwarf_get_fde_info_for_reg3(Dwarf_Fde fde,
179007dc194Richard Lowe    Dwarf_Half table_column,
179107dc194Richard Lowe    Dwarf_Addr pc_requested,
179207dc194Richard Lowe    Dwarf_Small * value_type,
179307dc194Richard Lowe    Dwarf_Signed * offset_relevant,
179407dc194Richard Lowe    Dwarf_Signed * register_num,
179507dc194Richard Lowe    Dwarf_Signed * offset_or_block_len,
179607dc194Richard Lowe    Dwarf_Ptr * block_ptr,
179707dc194Richard Lowe    Dwarf_Addr * row_pc_out,
179807dc194Richard Lowe    Dwarf_Error * error)
179907dc194Richard Lowe{
180007dc194Richard Lowe    struct Dwarf_Frame_s fde_table;
180107dc194Richard Lowe    int res = DW_DLV_ERROR;
180207dc194Richard Lowe
180307dc194Richard Lowe    Dwarf_Debug dbg = 0;
180407dc194Richard Lowe    int table_real_data_size = 0;
180507dc194Richard Lowe
180607dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
180707dc194Richard Lowe    table_real_data_size = dbg->de_frame_reg_rules_entry_count;
180807dc194Richard Lowe    res = dwarf_initialize_fde_table(dbg, &fde_table,
180907dc194Richard Lowe        table_real_data_size, error);
181007dc194Richard Lowe    if (res != DW_DLV_OK)
181107dc194Richard Lowe        return res;
181207dc194Richard Lowe    if (table_column >= table_real_data_size) {
181307dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
181407dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
181507dc194Richard Lowe        return (DW_DLV_ERROR);
181607dc194Richard Lowe    }
181707dc194Richard Lowe
181807dc194Richard Lowe    /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
181907dc194Richard Lowe     */
182007dc194Richard Lowe    res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
182107dc194Richard Lowe        dbg->de_frame_cfa_col_number,
182207dc194Richard Lowe        error);
182307dc194Richard Lowe    if (res != DW_DLV_OK) {
182407dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
182507dc194Richard Lowe        return res;
182607dc194Richard Lowe    }
182749d3bc9Richard Lowe
182807dc194Richard Lowe    if (register_num != NULL)
182907dc194Richard Lowe        *register_num = fde_table.fr_reg[table_column].ru_register;
183007dc194Richard Lowe    if (offset_or_block_len != NULL)
183107dc194Richard Lowe        *offset_or_block_len =
183207dc194Richard Lowe            fde_table.fr_reg[table_column].ru_offset_or_block_len;
183307dc194Richard Lowe    if (row_pc_out != NULL)
183407dc194Richard Lowe        *row_pc_out = fde_table.fr_loc;
183507dc194Richard Lowe    if (block_ptr)
183607dc194Richard Lowe        *block_ptr = fde_table.fr_reg[table_column].ru_block;
183707dc194Richard Lowe
183807dc194Richard Lowe    /* Without value_type the data cannot be understood, so we insist
183907dc194Richard Lowe       on it being present, we don't test it. */
184007dc194Richard Lowe    *value_type = fde_table.fr_reg[table_column].ru_value_type;
184149d3bc9Richard Lowe    *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off);
184207dc194Richard Lowe    dwarf_free_fde_table(&fde_table);
184349d3bc9Richard Lowe    return DW_DLV_OK;
184407dc194Richard Lowe
184549d3bc9Richard Lowe}
184649d3bc9Richard Lowe
184707dc194Richard Lowe/* For latest DWARF, this is the preferred interface.
184807dc194Richard Lowe   It more portably deals with the  CFA by not
184907dc194Richard Lowe   making the CFA a column number, which means
185007dc194Richard Lowe   DW_FRAME_CFA_COL3 becomes, like DW_CFA_SAME_VALUE,
185107dc194Richard Lowe   a special value, not something one uses as an index.
185207dc194Richard Lowe
185307dc194Richard Lowe   Call dwarf_set_frame_cfa_value() to set the correct column
185407dc194Richard Lowe   after calling dwarf_init()
185507dc194Richard Lowe   (DW_FRAME_CFA_COL3 is a sensible column to use, and
185607dc194Richard Lowe   is the default unless '--enable-oldframecol'
185707dc194Richard Lowe   is used to configure libdwarf).  */
185807dc194Richard Loweint
185907dc194Richard Lowedwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde,
186007dc194Richard Lowe    Dwarf_Addr pc_requested,
186107dc194Richard Lowe    Dwarf_Small * value_type,
186207dc194Richard Lowe    Dwarf_Signed * offset_relevant,
186307dc194Richard Lowe    Dwarf_Signed * register_num,
186407dc194Richard Lowe    Dwarf_Signed * offset_or_block_len,
186507dc194Richard Lowe    Dwarf_Ptr * block_ptr,
186607dc194Richard Lowe    Dwarf_Addr * row_pc_out,
186707dc194Richard Lowe    Dwarf_Error * error)
186807dc194Richard Lowe{
186907dc194Richard Lowe    struct Dwarf_Frame_s fde_table;
187007dc194Richard Lowe    int res = DW_DLV_ERROR;
187107dc194Richard Lowe    Dwarf_Debug dbg = 0;
187207dc194Richard Lowe
187307dc194Richard Lowe    int table_real_data_size = 0;
187407dc194Richard Lowe
187507dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
187607dc194Richard Lowe
187707dc194Richard Lowe    table_real_data_size = dbg->de_frame_reg_rules_entry_count;
187807dc194Richard Lowe    res = dwarf_initialize_fde_table(dbg, &fde_table,
187907dc194Richard Lowe        table_real_data_size, error);
188007dc194Richard Lowe    if (res != DW_DLV_OK)
188107dc194Richard Lowe        return res;
188207dc194Richard Lowe    res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
188307dc194Richard Lowe          dbg->de_frame_cfa_col_number,error);
188407dc194Richard Lowe    if (res != DW_DLV_OK) {
188507dc194Richard Lowe        dwarf_free_fde_table(&fde_table);
188607dc194Richard Lowe        return res;
188707dc194Richard Lowe    }
188807dc194Richard Lowe
188907dc194Richard Lowe    if (register_num != NULL)
189007dc194Richard Lowe        *register_num = fde_table.fr_cfa_rule.ru_register;
189107dc194Richard Lowe    if (offset_or_block_len != NULL)
189207dc194Richard Lowe        *offset_or_block_len =
189307dc194Richard Lowe            fde_table.fr_cfa_rule.ru_offset_or_block_len;
189407dc194Richard Lowe    if (row_pc_out != NULL)
189507dc194Richard Lowe        *row_pc_out = fde_table.fr_loc;
189607dc194Richard Lowe    if (block_ptr)
189707dc194Richard Lowe        *block_ptr = fde_table.fr_cfa_rule.ru_block;
189807dc194Richard Lowe
189907dc194Richard Lowe    /* Without value_type the data cannot be understood, so we insist
190007dc194Richard Lowe       on it being present, we don't test it. */
190107dc194Richard Lowe    *value_type = fde_table.fr_cfa_rule.ru_value_type;
190207dc194Richard Lowe    *offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
190307dc194Richard Lowe    dwarf_free_fde_table(&fde_table);
190407dc194Richard Lowe    return DW_DLV_OK;
190507dc194Richard Lowe}
190607dc194Richard Lowe
190707dc194Richard Lowe
190807dc194Richard Lowe
190949d3bc9Richard Lowe/*
191007dc194Richard Lowe        Return pointer to the instructions in the dwarf
191107dc194Richard Lowe        fde.
191249d3bc9Richard Lowe*/
191349d3bc9Richard Loweint
191449d3bc9Richard Lowedwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr,
191507dc194Richard Lowe    Dwarf_Unsigned * outaddrlen,
191607dc194Richard Lowe    Dwarf_Error * error)
191749d3bc9Richard Lowe{
191807dc194Richard Lowe    Dwarf_Unsigned len = 0;
191907dc194Richard Lowe    unsigned char *instrs = 0;
192007dc194Richard Lowe    Dwarf_Debug dbg = 0;
192149d3bc9Richard Lowe
192249d3bc9Richard Lowe    if (inFde == NULL) {
192307dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FDE_NULL);
192407dc194Richard Lowe        return (DW_DLV_ERROR);
192549d3bc9Richard Lowe    }
192649d3bc9Richard Lowe
192749d3bc9Richard Lowe    dbg = inFde->fd_dbg;
192849d3bc9Richard Lowe    if (dbg == NULL) {
192907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL);
193007dc194Richard Lowe        return (DW_DLV_ERROR);
193149d3bc9Richard Lowe    }
193249d3bc9Richard Lowe
193307dc194Richard Lowe    instrs = inFde->fd_fde_instr_start;
193407dc194Richard Lowe
193507dc194Richard Lowe    len = (inFde->fd_fde_start + inFde->fd_length +
193607dc194Richard Lowe           inFde->fd_length_size + inFde->fd_extension_size) - instrs;
193749d3bc9Richard Lowe
193849d3bc9Richard Lowe    *outinstraddr = instrs;
193949d3bc9Richard Lowe    *outaddrlen = len;
194049d3bc9Richard Lowe    return DW_DLV_OK;
194149d3bc9Richard Lowe}
194249d3bc9Richard Lowe
194307dc194Richard Lowe/* Allows getting an fde from its table via an index.
194407dc194Richard Lowe   With more error checking than simply indexing oneself.
194507dc194Richard Lowe*/
194649d3bc9Richard Loweint
194749d3bc9Richard Lowedwarf_get_fde_n(Dwarf_Fde * fde_data,
194807dc194Richard Lowe    Dwarf_Unsigned fde_index,
194907dc194Richard Lowe    Dwarf_Fde * returned_fde, Dwarf_Error * error)
195049d3bc9Richard Lowe{
195107dc194Richard Lowe    Dwarf_Debug dbg = 0;
195207dc194Richard Lowe    Dwarf_Signed fdecount = 0;
195349d3bc9Richard Lowe
195449d3bc9Richard Lowe    if (fde_data == NULL) {
195507dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL);
195607dc194Richard Lowe        return (DW_DLV_ERROR);
195749d3bc9Richard Lowe    }
195849d3bc9Richard Lowe
195907dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg);
196007dc194Richard Lowe    /* Assumes fde_data table has at least one entry. */
196107dc194Richard Lowe    fdecount = fde_data[0]->fd_is_eh?
196207dc194Richard Lowe        dbg->de_fde_count_eh:dbg->de_fde_count;
196307dc194Richard Lowe    if (fde_index >= fdecount) {
196407dc194Richard Lowe        return (DW_DLV_NO_ENTRY);
196549d3bc9Richard Lowe    }
196649d3bc9Richard Lowe    *returned_fde = (*(fde_data + fde_index));
196749d3bc9Richard Lowe    return DW_DLV_OK;
196849d3bc9Richard Lowe}
196949d3bc9Richard Lowe
197049d3bc9Richard Lowe
197149d3bc9Richard Lowe/*
197249d3bc9Richard Lowe    Lopc and hipc are extensions to the interface to
197349d3bc9Richard Lowe    return the range of addresses that are described
197449d3bc9Richard Lowe    by the returned fde.
197549d3bc9Richard Lowe*/
197649d3bc9Richard Loweint
197749d3bc9Richard Lowedwarf_get_fde_at_pc(Dwarf_Fde * fde_data,
197807dc194Richard Lowe    Dwarf_Addr pc_of_interest,
197907dc194Richard Lowe    Dwarf_Fde * returned_fde,
198007dc194Richard Lowe    Dwarf_Addr * lopc,
198107dc194Richard Lowe    Dwarf_Addr * hipc, Dwarf_Error * error)
198249d3bc9Richard Lowe{
198307dc194Richard Lowe    Dwarf_Debug dbg = NULL;
198449d3bc9Richard Lowe    Dwarf_Fde fde = NULL;
198507dc194Richard Lowe    Dwarf_Fde entryfde = NULL;
198607dc194Richard Lowe    Dwarf_Signed fdecount = 0;
198749d3bc9Richard Lowe
198849d3bc9Richard Lowe    if (fde_data == NULL) {
198907dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
199007dc194Richard Lowe        return (DW_DLV_ERROR);
199149d3bc9Richard Lowe    }
199249d3bc9Richard Lowe
199307dc194Richard Lowe    /* Assumes fde_data table has at least one entry. */
199407dc194Richard Lowe    entryfde = *fde_data;
199507dc194Richard Lowe    FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg);
199649d3bc9Richard Lowe
199749d3bc9Richard Lowe    if (dbg == NULL) {
199807dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
199907dc194Richard Lowe        return (DW_DLV_ERROR);
200049d3bc9Richard Lowe    }
200107dc194Richard Lowe    fdecount = entryfde->fd_is_eh?
200207dc194Richard Lowe        dbg->de_fde_count_eh:dbg->de_fde_count;
200349d3bc9Richard Lowe    {
200407dc194Richard Lowe        /* The fde's are sorted by their addresses. Binary search to
200507dc194Richard Lowe           find correct fde. */
200607dc194Richard Lowe        Dwarf_Signed low = 0;
200707dc194Richard Lowe        Dwarf_Signed high = fdecount - 1L;
200807dc194Richard Lowe        Dwarf_Signed middle = 0;
200907dc194Richard Lowe        Dwarf_Fde cur_fde;
201007dc194Richard Lowe
201107dc194Richard Lowe        while (low <= high) {
201207dc194Richard Lowe            middle = (low + high) / 2;
201307dc194Richard Lowe            cur_fde = fde_data[middle];
201407dc194Richard Lowe            if (pc_of_interest < cur_fde->fd_initial_location) {
201507dc194Richard Lowe                high = middle - 1;
201607dc194Richard Lowe            } else if (pc_of_interest >=
201707dc194Richard Lowe                       (cur_fde->fd_initial_location +
201807dc194Richard Lowe                        cur_fde->fd_address_range)) {
201907dc194Richard Lowe                low = middle + 1;
202007dc194Richard Lowe            } else {
202107dc194Richard Lowe                fde = fde_data[middle];
202207dc194Richard Lowe                break;
202307dc194Richard Lowe            }
202407dc194Richard Lowe        }
202549d3bc9Richard Lowe    }
202649d3bc9Richard Lowe
202749d3bc9Richard Lowe    if (fde) {
202807dc194Richard Lowe        if (lopc != NULL)
202907dc194Richard Lowe            *lopc = fde->fd_initial_location;
203007dc194Richard Lowe        if (hipc != NULL)
203107dc194Richard Lowe            *hipc =
203207dc194Richard Lowe                fde->fd_initial_location + fde->fd_address_range - 1;
203307dc194Richard Lowe        *returned_fde = fde;
203407dc194Richard Lowe        return (DW_DLV_OK);
203549d3bc9Richard Lowe    }
203649d3bc9Richard Lowe
203749d3bc9Richard Lowe    return (DW_DLV_NO_ENTRY);
203849d3bc9Richard Lowe}
203949d3bc9Richard Lowe
204049d3bc9Richard Lowe
204107dc194Richard Lowe/* Expands a single frame instruction block
204207dc194Richard Lowe   from a specific cie
204307dc194Richard Lowe   into a n array of Dwarf_Frame_Op-s.
204407dc194Richard Lowe   This depends on having the cfa column set sensibly.
204507dc194Richard Lowe
204607dc194Richard Lowe   Call dwarf_set_frame_cfa_value() to set the correct column
204707dc194Richard Lowe   after calling dwarf_init() unless you are using
204807dc194Richard Lowe   the old MIPS frame interfaces (in which case the default
204907dc194Richard Lowe   will be ok). (DW_FRAME_CFA_COL3 is a sensible column to use ).
205007dc194Richard Lowe*/
205149d3bc9Richard Loweint
205207dc194Richard Lowedwarf_expand_frame_instructions(Dwarf_Cie cie,
205307dc194Richard Lowe    Dwarf_Ptr instruction,
205407dc194Richard Lowe    Dwarf_Unsigned i_length,
205507dc194Richard Lowe    Dwarf_Frame_Op ** returned_op_list,
205607dc194Richard Lowe    Dwarf_Signed * returned_op_count,
205707dc194Richard Lowe    Dwarf_Error * error)
205849d3bc9Richard Lowe{
205949d3bc9Richard Lowe    Dwarf_Sword instr_count;
206007dc194Richard Lowe    int res = DW_DLV_ERROR;
206149d3bc9Richard Lowe    int dw_err;
206207dc194Richard Lowe    Dwarf_Debug dbg = 0;
206349d3bc9Richard Lowe
206407dc194Richard Lowe    if (cie == 0) {
206507dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
206607dc194Richard Lowe        return (DW_DLV_ERROR);
206749d3bc9Richard Lowe    }
206807dc194Richard Lowe    dbg = cie->ci_dbg;
206949d3bc9Richard Lowe
207049d3bc9Richard Lowe    if (returned_op_list == 0 || returned_op_count == 0) {
207107dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL);
207207dc194Richard Lowe        return (DW_DLV_ERROR);
207349d3bc9Richard Lowe    }
207449d3bc9Richard Lowe
207549d3bc9Richard Lowe    /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe
207649d3bc9Richard Lowe       as it is just an i_length offset from 'instruction' itself. A
207749d3bc9Richard Lowe       caller has made a big mistake if the result is not a valid
207849d3bc9Richard Lowe       pointer. */
207949d3bc9Richard Lowe    res = _dwarf_exec_frame_instr( /* make_instr= */ true,
208007dc194Richard Lowe        returned_op_list,
208107dc194Richard Lowe        /* search_pc */ false,
208207dc194Richard Lowe        /* search_pc_val */ 0,
208307dc194Richard Lowe        /* location */ 0,
208407dc194Richard Lowe        instruction,
208507dc194Richard Lowe        (Dwarf_Ptr)((char *)instruction + i_length),
208607dc194Richard Lowe        /* Dwarf_Frame */ NULL,
208707dc194Richard Lowe        cie,
208807dc194Richard Lowe        dbg,
208907dc194Richard Lowe        dbg->de_frame_cfa_col_number, &instr_count,
209007dc194Richard Lowe        &dw_err);
209149d3bc9Richard Lowe    if (res != DW_DLV_OK) {
209207dc194Richard Lowe        if (res == DW_DLV_ERROR) {
209307dc194Richard Lowe            _dwarf_error(dbg, error, dw_err);
209407dc194Richard Lowe        }
209507dc194Richard Lowe        return (res);
209649d3bc9Richard Lowe    }
209749d3bc9Richard Lowe
209849d3bc9Richard Lowe    *returned_op_count = instr_count;
209949d3bc9Richard Lowe    return DW_DLV_OK;
210049d3bc9Richard Lowe}
210149d3bc9Richard Lowe
210249d3bc9Richard Lowe
210307dc194Richard Lowe/* Used by dwarfdump -v to print offsets, for debugging
210407dc194Richard Lowe   dwarf info.
210507dc194Richard Lowe   The dwarf_ version is preferred over the obsolete _dwarf version.
210607dc194Richard Lowe   _dwarf version kept for compatibility.
210749d3bc9Richard Lowe*/
210807dc194Richard Lowe/* ARGSUSED 4 */
210949d3bc9Richard Loweint
211007dc194Richard Lowe_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
211107dc194Richard Lowe    Dwarf_Off * fde_off, Dwarf_Off * cie_off,
211207dc194Richard Lowe    Dwarf_Error * err)
211349d3bc9Richard Lowe{
211407dc194Richard Lowe  return dwarf_fde_section_offset(dbg,in_fde,fde_off,
211507dc194Richard Lowe     cie_off,err);
211649d3bc9Richard Lowe}
211749d3bc9Richard Lowe/* ARGSUSED 4 */
211849d3bc9Richard Loweint
211907dc194Richard Lowedwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
212007dc194Richard Lowe    Dwarf_Off * fde_off, Dwarf_Off * cie_off,
212107dc194Richard Lowe    Dwarf_Error * err)
212249d3bc9Richard Lowe{
212307dc194Richard Lowe    char *start = 0;
212407dc194Richard Lowe    char *loc = 0;
212507dc194Richard Lowe
212649d3bc9Richard Lowe
212749d3bc9Richard Lowe
212807dc194Richard Lowe    start = (char *) in_fde->fd_section_ptr;
212949d3bc9Richard Lowe    loc = (char *) in_fde->fd_fde_start;
213049d3bc9Richard Lowe
213149d3bc9Richard Lowe    *fde_off = (loc - start);
213249d3bc9Richard Lowe    *cie_off = in_fde->fd_cie_offset;
213349d3bc9Richard Lowe    return DW_DLV_OK;
213449d3bc9Richard Lowe}
213549d3bc9Richard Lowe
213649d3bc9Richard Lowe/* Used by dwarfdump -v to print offsets, for debugging
213707dc194Richard Lowe   dwarf info.
213807dc194Richard Lowe   The dwarf_ version is preferred over the obsolete _dwarf version.
213907dc194Richard Lowe   _dwarf version kept for compatibility.
214049d3bc9Richard Lowe*/
214149d3bc9Richard Lowe/* ARGSUSED 4 */
214249d3bc9Richard Loweint
214349d3bc9Richard Lowe_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
214407dc194Richard Lowe    Dwarf_Off * cie_off, Dwarf_Error * err)
214549d3bc9Richard Lowe{
214607dc194Richard Lowe    return dwarf_cie_section_offset(dbg,in_cie,cie_off,err);
214707dc194Richard Lowe}
214807dc194Richard Lowe/* ARGSUSED 4 */
214907dc194Richard Loweint
215007dc194Richard Lowedwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
215107dc194Richard Lowe    Dwarf_Off * cie_off, Dwarf_Error * err)
215207dc194Richard Lowe{
215307dc194Richard Lowe    char *start = 0;
215407dc194Richard Lowe    char *loc = 0;
215549d3bc9Richard Lowe
215607dc194Richard Lowe    start = (char *) in_cie->ci_section_ptr;
215749d3bc9Richard Lowe    loc = (char *) in_cie->ci_cie_start;
215849d3bc9Richard Lowe
215949d3bc9Richard Lowe    *cie_off = (loc - start);
216049d3bc9Richard Lowe    return DW_DLV_OK;
216149d3bc9Richard Lowe}
216207dc194Richard Lowe
216307dc194Richard Lowe/* Returns  a pointer to target-specific augmentation data thru augdata
216407dc194Richard Lowe   and returns the length of the data thru augdata_len.
216507dc194Richard Lowe
216607dc194Richard Lowe   It's up to the consumer code to know how to interpret the bytes
216707dc194Richard Lowe   of target-specific data (endian issues apply too, these
216807dc194Richard Lowe   are just raw bytes pointed to).
216907dc194Richard Lowe   See  Linux Standard Base Core Specification version 3.0 for
217007dc194Richard Lowe   the details on .eh_frame info.
217107dc194Richard Lowe
217207dc194Richard Lowe   Returns DW_DLV_ERROR if fde is NULL or some other serious
217307dc194Richard Lowe   error.
217407dc194Richard Lowe   Returns DW_DLV_NO_ENTRY if there is no target-specific
217507dc194Richard Lowe   augmentation data.
217607dc194Richard Lowe
217707dc194Richard Lowe   The bytes pointed to are in the Dwarf_Cie, and as long as that
217807dc194Richard Lowe   is valid the bytes are there. No 'dealloc' call is needed
217907dc194Richard Lowe   for the bytes.
218007dc194Richard Lowe*/
218107dc194Richard Loweint
218207dc194Richard Lowedwarf_get_cie_augmentation_data(Dwarf_Cie cie,
218307dc194Richard Lowe    Dwarf_Small ** augdata,
218407dc194Richard Lowe    Dwarf_Unsigned * augdata_len,
218507dc194Richard Lowe    Dwarf_Error * error)
218607dc194Richard Lowe{
218707dc194Richard Lowe    if (cie == NULL) {
218807dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
218907dc194Richard Lowe        return (DW_DLV_ERROR);
219007dc194Richard Lowe    }
219107dc194Richard Lowe    if (cie->ci_gnu_eh_augmentation_len == 0) {
219207dc194Richard Lowe        return DW_DLV_NO_ENTRY;
219307dc194Richard Lowe    }
219407dc194Richard Lowe    *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes);
219507dc194Richard Lowe    *augdata_len = cie->ci_gnu_eh_augmentation_len;
219607dc194Richard Lowe    return DW_DLV_OK;
219707dc194Richard Lowe}
219807dc194Richard Lowe
219907dc194Richard Lowe
220007dc194Richard Lowe/* Returns  a pointer to target-specific augmentation data thru augdata
220107dc194Richard Lowe   and returns the length of the data thru augdata_len.
220207dc194Richard Lowe
220307dc194Richard Lowe   It's up to the consumer code to know how to interpret the bytes
220407dc194Richard Lowe   of target-specific data (endian issues apply too, these
220507dc194Richard Lowe   are just raw bytes pointed to).
220607dc194Richard Lowe   See  Linux Standard Base Core Specification version 3.0 for
220707dc194Richard Lowe   the details on .eh_frame info.
220807dc194Richard Lowe
220907dc194Richard Lowe   Returns DW_DLV_ERROR if fde is NULL or some other serious
221007dc194Richard Lowe   error.
221107dc194Richard Lowe   Returns DW_DLV_NO_ENTRY if there is no target-specific
221207dc194Richard Lowe   augmentation data.
221307dc194Richard Lowe
221407dc194Richard Lowe   The bytes pointed to are in the Dwarf_Fde, and as long as that
221507dc194Richard Lowe   is valid the bytes are there. No 'dealloc' call is needed
221607dc194Richard Lowe   for the bytes.
221707dc194Richard Lowe
221807dc194Richard Lowe*/
221907dc194Richard Loweint
222007dc194Richard Lowedwarf_get_fde_augmentation_data(Dwarf_Fde fde,
222107dc194Richard Lowe    Dwarf_Small * *augdata,
222207dc194Richard Lowe    Dwarf_Unsigned * augdata_len,
222307dc194Richard Lowe    Dwarf_Error * error)
222407dc194Richard Lowe{
222507dc194Richard Lowe    Dwarf_Cie cie = 0;
222607dc194Richard Lowe
222707dc194Richard Lowe    if (fde == NULL) {
222807dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
222907dc194Richard Lowe        return (DW_DLV_ERROR);
223007dc194Richard Lowe    }
223107dc194Richard Lowe    cie = fde->fd_cie;
223207dc194Richard Lowe    if (cie == NULL) {
223307dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
223407dc194Richard Lowe        return (DW_DLV_ERROR);
223507dc194Richard Lowe    }
223607dc194Richard Lowe    if (cie->ci_gnu_eh_augmentation_len == 0) {
223707dc194Richard Lowe        return DW_DLV_NO_ENTRY;
223807dc194Richard Lowe    }
223907dc194Richard Lowe    *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes;
224007dc194Richard Lowe    *augdata_len = fde->fd_gnu_eh_augmentation_len;
224107dc194Richard Lowe    return DW_DLV_OK;
224207dc194Richard Lowe}
224307dc194Richard Lowe
224407dc194Richard Lowe
224507dc194Richard Lowe/* Initialize with same_value , a value which makes sense
224607dc194Richard Lowe   for IRIX/MIPS.
224707dc194Richard Lowe   The correct value to use is ABI dependent.
224807dc194Richard Lowe   For register-windows machines most
224907dc194Richard Lowe   or all registers should get DW_FRAME_UNDEFINED_VAL as the
225007dc194Richard Lowe   correct initial value.
225107dc194Richard Lowe   Some think DW_FRAME_UNDEFINED_VAL is always the
225207dc194Richard Lowe   right value.
225307dc194Richard Lowe
225407dc194Richard Lowe   For some ABIs a setting which varies by register
225507dc194Richard Lowe   would be more appropriate.
225607dc194Richard Lowe
225707dc194Richard Lowe   FIXME. */
225807dc194Richard Lowe
225907dc194Richard Lowestatic void
226007dc194Richard Lowe_dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg,
226107dc194Richard Lowe    int last_reg_num, int initial_value)
226207dc194Richard Lowe{
226307dc194Richard Lowe    struct Dwarf_Reg_Rule_s *t1end = t1reg + last_reg_num;
226407dc194Richard Lowe
226507dc194Richard Lowe    for (; t1reg < t1end; t1reg++) {
226607dc194Richard Lowe        t1reg->ru_is_off = 0;
226707dc194Richard Lowe        t1reg->ru_value_type = DW_EXPR_OFFSET;
226807dc194Richard Lowe        t1reg->ru_register = initial_value;
226907dc194Richard Lowe        t1reg->ru_offset_or_block_len = 0;
227007dc194Richard Lowe        t1reg->ru_block = 0;
227107dc194Richard Lowe    }
227207dc194Richard Lowe}
227307dc194Richard Lowe
227407dc194Richard Lowe#if 0
227507dc194Richard Lowe/* Used solely for debugging libdwarf. */
227607dc194Richard Lowestatic void
227707dc194Richard Lowedump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule)
227807dc194Richard Lowe{
227907dc194Richard Lowe    printf
228007dc194Richard Lowe        ("%s type %s (" DW_PR_DUx "), is_off "
228107dc194Richard Lowe         DW_PR_DUu " reg " DW_PR_DUu " offset " DW_PR_DUx " blockp "
228207dc194Richard Lowe         DW_PR_DUx "\n",
228307dc194Richard Lowe         msg,
228407dc194Richard Lowe         (reg_rule->ru_value_type == DW_EXPR_OFFSET) ?
228507dc194Richard Lowe             "DW_EXPR_OFFSET" :
228607dc194Richard Lowe          (reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ?
228707dc194Richard Lowe             "DW_EXPR_VAL_OFFSET" :
228807dc194Richard Lowe          (reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ?
228907dc194Richard Lowe             "DW_EXPR_VAL_EXPRESSION" :
229007dc194Richard Lowe          (reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ?
229107dc194Richard Lowe             "DW_EXPR_EXPRESSION" : "Unknown",
229207dc194Richard Lowe         (Dwarf_Unsigned) reg_rule->ru_value_type,
229307dc194Richard Lowe         (Dwarf_Unsigned) reg_rule->ru_is_off,
229407dc194Richard Lowe         (Dwarf_Unsigned) reg_rule->ru_register,
229507dc194Richard Lowe         (Dwarf_Unsigned) reg_rule->ru_offset_or_block_len,
229607dc194Richard Lowe         (Dwarf_Unsigned) reg_rule->ru_block);
229707dc194Richard Lowe    return;
229807dc194Richard Lowe}
229907dc194Richard Lowe#endif
230007dc194Richard Lowe
230107dc194Richard Lowe/* This allows consumers to set the 'initial value' so that
230207dc194Richard Lowe   an ISA/ABI specific default can be used, dynamically,
230307dc194Richard Lowe   at run time.  Useful for dwarfdump and non-MIPS architectures..
230407dc194Richard Lowe   The value  defaults to one of
230507dc194Richard Lowe        DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE
230607dc194Richard Lowe   but dwarfdump can dump multiple ISA/ABI objects so
230707dc194Richard Lowe   we may want to get this set to what the ABI says is correct.
230807dc194Richard Lowe
230907dc194Richard Lowe   Returns the value that was present before we changed it here.
231007dc194Richard Lowe*/
231107dc194Richard LoweDwarf_Half
231207dc194Richard Lowedwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
231307dc194Richard Lowe{
231407dc194Richard Lowe    Dwarf_Half orig = dbg->de_frame_rule_initial_value;
231507dc194Richard Lowe    dbg->de_frame_rule_initial_value = value;
231607dc194Richard Lowe    return orig;
231707dc194Richard Lowe}
231807dc194Richard Lowe
231907dc194Richard Lowe/* The following spelling for backwards compatibility. */
232007dc194Richard LoweDwarf_Half
232107dc194Richard Lowedwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value)
232207dc194Richard Lowe{
232307dc194Richard Lowe    return dwarf_set_frame_rule_initial_value(dbg,value);
232407dc194Richard Lowe}
232507dc194Richard Lowe
232607dc194Richard Lowe/* This allows consumers to set the array size of the  reg rules
232707dc194Richard Lowe   table so that
232807dc194Richard Lowe   an ISA/ABI specific value can be used, dynamically,
232907dc194Richard Lowe   at run time.  Useful for non-MIPS archtectures.
233007dc194Richard Lowe   The value  defaults  to DW_FRAME_LAST_REG_NUM.
233107dc194Richard Lowe   but dwarfdump can dump multiple ISA/ABI objects so
233207dc194Richard Lowe   consumers want to get this set to what the ABI says is correct.
233307dc194Richard Lowe
233407dc194Richard Lowe   Returns the value that was present before we changed it here.
233507dc194Richard Lowe*/
233607dc194Richard Lowe
233707dc194Richard LoweDwarf_Half
233807dc194Richard Lowedwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
233907dc194Richard Lowe{
234007dc194Richard Lowe    Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count;
234107dc194Richard Lowe    dbg->de_frame_reg_rules_entry_count = value;
234207dc194Richard Lowe    return orig;
234307dc194Richard Lowe}
234407dc194Richard Lowe/* This allows consumers to set the CFA register value
234507dc194Richard Lowe * so that an ISA/ABI specific value can be used, dynamically,
234607dc194Richard Lowe * at run time.  Useful for non-MIPS archtectures.
234707dc194Richard Lowe * The value  defaults  to DW_FRAME_CFA_COL3 and should be
234807dc194Richard Lowe * higher than any real register in the ABI.
234907dc194Richard Lowe * Dwarfdump can dump multiple ISA/ABI objects so
235007dc194Richard Lowe * consumers want to get this set to what the ABI says is correct.
235107dc194Richard Lowe
235207dc194Richard Lowe * Returns the value that was present before we changed it here.
235307dc194Richard Lowe * */
235407dc194Richard Lowe
235507dc194Richard LoweDwarf_Half
235607dc194Richard Lowedwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
235707dc194Richard Lowe{
235807dc194Richard Lowe    Dwarf_Half orig = dbg->de_frame_cfa_col_number;
235907dc194Richard Lowe    dbg->de_frame_cfa_col_number = value;
236007dc194Richard Lowe    return orig;
236107dc194Richard Lowe}
236207dc194Richard Lowe/* Similar to above, but for the other crucial fields for frames. */
236307dc194Richard LoweDwarf_Half
236407dc194Richard Lowedwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
236507dc194Richard Lowe{
236607dc194Richard Lowe    Dwarf_Half orig = dbg->de_frame_same_value_number;
236707dc194Richard Lowe    dbg->de_frame_same_value_number = value;
236807dc194Richard Lowe    return orig;
236907dc194Richard Lowe}
237007dc194Richard LoweDwarf_Half
237107dc194Richard Lowedwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
237207dc194Richard Lowe{
237307dc194Richard Lowe    Dwarf_Half orig = dbg->de_frame_same_value_number;
237407dc194Richard Lowe    dbg->de_frame_undefined_value_number = value;
237507dc194Richard Lowe    return orig;
237607dc194Richard Lowe}
237707dc194Richard Lowe
237807dc194Richard Lowe
237907dc194Richard Lowe
238007dc194Richard Lowe
238107dc194Richard Lowe
238207dc194Richard Lowestatic int
238307dc194Richard Lowedwarf_initialize_fde_table(Dwarf_Debug dbg,
238407dc194Richard Lowe    struct Dwarf_Frame_s *fde_table,
238507dc194Richard Lowe    unsigned table_real_data_size,
238607dc194Richard Lowe    Dwarf_Error * error)
238707dc194Richard Lowe{
238807dc194Richard Lowe    unsigned entry_size = sizeof(struct Dwarf_Frame_s);
238907dc194Richard Lowe
239007dc194Richard Lowe    fde_table->fr_loc = 0;
239107dc194Richard Lowe    fde_table->fr_reg_count = table_real_data_size;
239207dc194Richard Lowe    fde_table->fr_next = 0;
239307dc194Richard Lowe
239407dc194Richard Lowe    fde_table->fr_reg = (struct Dwarf_Reg_Rule_s *)
239507dc194Richard Lowe        calloc(entry_size, table_real_data_size);
239607dc194Richard Lowe    if (fde_table->fr_reg == 0) {
239707dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL);
239807dc194Richard Lowe        return (DW_DLV_ERROR);
239907dc194Richard Lowe    }
240007dc194Richard Lowe    return DW_DLV_OK;
240107dc194Richard Lowe
240207dc194Richard Lowe}
240307dc194Richard Lowestatic void
240407dc194Richard Lowedwarf_free_fde_table(struct Dwarf_Frame_s *fde_table)
240507dc194Richard Lowe{
240607dc194Richard Lowe    free(fde_table->fr_reg);
240707dc194Richard Lowe    fde_table->fr_reg_count = 0;
240807dc194Richard Lowe    fde_table->fr_reg = 0;
240907dc194Richard Lowe}
241007dc194Richard Lowe
241107dc194Richard Lowe
241207dc194Richard Lowe/* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR.
241307dc194Richard Lowe*/
241407dc194Richard Loweint
241507dc194Richard Lowe_dwarf_frame_constructor(Dwarf_Debug dbg, void *frame)
241607dc194Richard Lowe{
241707dc194Richard Lowe    struct Dwarf_Frame_s *fp = frame;
241807dc194Richard Lowe
241907dc194Richard Lowe    if (!dbg) {
242007dc194Richard Lowe        return DW_DLV_ERROR;
242107dc194Richard Lowe    }
242207dc194Richard Lowe
242307dc194Richard Lowe    fp->fr_reg = calloc(dbg->de_frame_reg_rules_entry_count,
242407dc194Richard Lowe                        sizeof(struct Dwarf_Reg_Rule_s));
242507dc194Richard Lowe    if (!fp->fr_reg) {
242607dc194Richard Lowe        return DW_DLV_ERROR;
242707dc194Richard Lowe    }
242807dc194Richard Lowe    fp->fr_reg_count = dbg->de_frame_reg_rules_entry_count;
242907dc194Richard Lowe    return DW_DLV_OK;
243007dc194Richard Lowe}
243107dc194Richard Lowe
243207dc194Richard Lowevoid
243307dc194Richard Lowe_dwarf_frame_destructor(void *frame)
243407dc194Richard Lowe{
243507dc194Richard Lowe    struct Dwarf_Frame_s *fp = frame;
243607dc194Richard Lowe
243707dc194Richard Lowe    if (fp->fr_reg) {
243807dc194Richard Lowe        free(fp->fr_reg);
243907dc194Richard Lowe    }
244007dc194Richard Lowe    fp->fr_reg = 0;
244107dc194Richard Lowe    fp->fr_reg_count = 0;
244207dc194Richard Lowe}