149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000,2004,2006 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright 2007-2010 Sun Microsystems, Inc. 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*/
3649d3bc9Richard Lowe
3749d3bc9Richard Lowe
3849d3bc9Richard Lowe
3949d3bc9Richard Lowe#include "config.h"
4049d3bc9Richard Lowe#include "libdwarfdefs.h"
4149d3bc9Richard Lowe#include <stdio.h>
4249d3bc9Richard Lowe#include <string.h>
4349d3bc9Richard Lowe#include <sys/types.h>
4449d3bc9Richard Lowe#include "pro_incl.h"
4549d3bc9Richard Lowe#include "pro_expr.h"
4649d3bc9Richard Lowe
4749d3bc9Richard Lowe/*
4849d3bc9Richard Lowe    This function creates a new expression
4949d3bc9Richard Lowe    struct that can be used to build up a
5049d3bc9Richard Lowe    location expression.
5149d3bc9Richard Lowe*/
5249d3bc9Richard LoweDwarf_P_Expr
5349d3bc9Richard Lowedwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error)
5449d3bc9Richard Lowe{
5549d3bc9Richard Lowe    Dwarf_P_Expr ret_expr;
5649d3bc9Richard Lowe
5749d3bc9Richard Lowe    if (dbg == NULL) {
5807dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
5907dc194Richard Lowe        return (NULL);
6049d3bc9Richard Lowe    }
6149d3bc9Richard Lowe
6249d3bc9Richard Lowe    ret_expr = (Dwarf_P_Expr)
6307dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s));
6449d3bc9Richard Lowe    if (ret_expr == NULL) {
6507dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6607dc194Richard Lowe        return (NULL);
6749d3bc9Richard Lowe    }
6849d3bc9Richard Lowe
6949d3bc9Richard Lowe    ret_expr->ex_dbg = dbg;
7049d3bc9Richard Lowe
7149d3bc9Richard Lowe    return (ret_expr);
7249d3bc9Richard Lowe}
7349d3bc9Richard Lowe
7449d3bc9Richard Lowe
7549d3bc9Richard LoweDwarf_Unsigned
7649d3bc9Richard Lowedwarf_add_expr_gen(Dwarf_P_Expr expr,
7707dc194Richard Lowe                   Dwarf_Small opcode,
7807dc194Richard Lowe                   Dwarf_Unsigned val1,
7907dc194Richard Lowe                   Dwarf_Unsigned val2, Dwarf_Error * error)
8049d3bc9Richard Lowe{
8107dc194Richard Lowe    char encode_buffer[2 * ENCODE_SPACE_NEEDED];        /* 2* since
8207dc194Richard Lowe                                                           used to
8307dc194Richard Lowe                                                           concatenate
8407dc194Richard Lowe                                                           2 leb's
8507dc194Richard Lowe                                                           below */
8649d3bc9Richard Lowe    char encode_buffer2[ENCODE_SPACE_NEEDED];
8749d3bc9Richard Lowe    int res;
8849d3bc9Richard Lowe    Dwarf_P_Debug dbg = expr->ex_dbg;
8949d3bc9Richard Lowe
9049d3bc9Richard Lowe    /*
9149d3bc9Richard Lowe       Give the buffer where the operands are first going to be
9249d3bc9Richard Lowe       assembled the largest alignment. */
9349d3bc9Richard Lowe    Dwarf_Unsigned operand_buffer[10];
9449d3bc9Richard Lowe
9549d3bc9Richard Lowe    /*
9649d3bc9Richard Lowe       Size of the byte stream buffer that needs to be memcpy-ed. */
9749d3bc9Richard Lowe    int operand_size;
9849d3bc9Richard Lowe
9949d3bc9Richard Lowe    /*
10049d3bc9Richard Lowe       Points to the byte stream for the first operand, and finally to
10149d3bc9Richard Lowe       the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */
10249d3bc9Richard Lowe    Dwarf_Small *operand;
10349d3bc9Richard Lowe
10449d3bc9Richard Lowe    /* Size of the byte stream for second operand. */
10549d3bc9Richard Lowe    int operand2_size;
10649d3bc9Richard Lowe
10749d3bc9Richard Lowe    /* Points to next byte to be written in Dwarf_P_Expr_s struct. */
10849d3bc9Richard Lowe    Dwarf_Small *next_byte_ptr;
10949d3bc9Richard Lowe
11049d3bc9Richard Lowe    /* Offset past the last byte written into Dwarf_P_Expr_s. */
11149d3bc9Richard Lowe    int next_byte_offset;
11249d3bc9Richard Lowe
11349d3bc9Richard Lowe    /* ***** BEGIN CODE ***** */
11449d3bc9Richard Lowe
11549d3bc9Richard Lowe    if (expr == NULL) {
11607dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
11707dc194Richard Lowe        return (DW_DLV_NOCOUNT);
11849d3bc9Richard Lowe    }
11949d3bc9Richard Lowe
12049d3bc9Richard Lowe    if (expr->ex_dbg == NULL) {
12107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
12207dc194Richard Lowe        return (DW_DLV_NOCOUNT);
12349d3bc9Richard Lowe    }
12449d3bc9Richard Lowe
12549d3bc9Richard Lowe    operand = NULL;
12649d3bc9Richard Lowe    operand_size = 0;
12749d3bc9Richard Lowe
12849d3bc9Richard Lowe    switch (opcode) {
12949d3bc9Richard Lowe    case DW_OP_reg0:
13049d3bc9Richard Lowe    case DW_OP_reg1:
13149d3bc9Richard Lowe    case DW_OP_reg2:
13249d3bc9Richard Lowe    case DW_OP_reg3:
13349d3bc9Richard Lowe    case DW_OP_reg4:
13449d3bc9Richard Lowe    case DW_OP_reg5:
13549d3bc9Richard Lowe    case DW_OP_reg6:
13649d3bc9Richard Lowe    case DW_OP_reg7:
13749d3bc9Richard Lowe    case DW_OP_reg8:
13849d3bc9Richard Lowe    case DW_OP_reg9:
13949d3bc9Richard Lowe    case DW_OP_reg10:
14049d3bc9Richard Lowe    case DW_OP_reg11:
14149d3bc9Richard Lowe    case DW_OP_reg12:
14249d3bc9Richard Lowe    case DW_OP_reg13:
14349d3bc9Richard Lowe    case DW_OP_reg14:
14449d3bc9Richard Lowe    case DW_OP_reg15:
14549d3bc9Richard Lowe    case DW_OP_reg16:
14649d3bc9Richard Lowe    case DW_OP_reg17:
14749d3bc9Richard Lowe    case DW_OP_reg18:
14849d3bc9Richard Lowe    case DW_OP_reg19:
14949d3bc9Richard Lowe    case DW_OP_reg20:
15049d3bc9Richard Lowe    case DW_OP_reg21:
15149d3bc9Richard Lowe    case DW_OP_reg22:
15249d3bc9Richard Lowe    case DW_OP_reg23:
15349d3bc9Richard Lowe    case DW_OP_reg24:
15449d3bc9Richard Lowe    case DW_OP_reg25:
15549d3bc9Richard Lowe    case DW_OP_reg26:
15649d3bc9Richard Lowe    case DW_OP_reg27:
15749d3bc9Richard Lowe    case DW_OP_reg28:
15849d3bc9Richard Lowe    case DW_OP_reg29:
15949d3bc9Richard Lowe    case DW_OP_reg30:
16049d3bc9Richard Lowe    case DW_OP_reg31:
16107dc194Richard Lowe        break;
16249d3bc9Richard Lowe
16349d3bc9Richard Lowe    case DW_OP_breg0:
16449d3bc9Richard Lowe    case DW_OP_breg1:
16549d3bc9Richard Lowe    case DW_OP_breg2:
16649d3bc9Richard Lowe    case DW_OP_breg3:
16749d3bc9Richard Lowe    case DW_OP_breg4:
16849d3bc9Richard Lowe    case DW_OP_breg5:
16949d3bc9Richard Lowe    case DW_OP_breg6:
17049d3bc9Richard Lowe    case DW_OP_breg7:
17149d3bc9Richard Lowe    case DW_OP_breg8:
17249d3bc9Richard Lowe    case DW_OP_breg9:
17349d3bc9Richard Lowe    case DW_OP_breg10:
17449d3bc9Richard Lowe    case DW_OP_breg11:
17549d3bc9Richard Lowe    case DW_OP_breg12:
17649d3bc9Richard Lowe    case DW_OP_breg13:
17749d3bc9Richard Lowe    case DW_OP_breg14:
17849d3bc9Richard Lowe    case DW_OP_breg15:
17949d3bc9Richard Lowe    case DW_OP_breg16:
18049d3bc9Richard Lowe    case DW_OP_breg17:
18149d3bc9Richard Lowe    case DW_OP_breg18:
18249d3bc9Richard Lowe    case DW_OP_breg19:
18349d3bc9Richard Lowe    case DW_OP_breg20:
18449d3bc9Richard Lowe    case DW_OP_breg21:
18549d3bc9Richard Lowe    case DW_OP_breg22:
18649d3bc9Richard Lowe    case DW_OP_breg23:
18749d3bc9Richard Lowe    case DW_OP_breg24:
18849d3bc9Richard Lowe    case DW_OP_breg25:
18949d3bc9Richard Lowe    case DW_OP_breg26:
19049d3bc9Richard Lowe    case DW_OP_breg27:
19149d3bc9Richard Lowe    case DW_OP_breg28:
19249d3bc9Richard Lowe    case DW_OP_breg29:
19349d3bc9Richard Lowe    case DW_OP_breg30:
19449d3bc9Richard Lowe    case DW_OP_breg31:
19507dc194Richard Lowe        res = _dwarf_pro_encode_signed_leb128_nm(val1,
19607dc194Richard Lowe                                                 &operand_size,
19707dc194Richard Lowe                                                 encode_buffer,
19807dc194Richard Lowe                                                 sizeof(encode_buffer));
19907dc194Richard Lowe        if (res != DW_DLV_OK) {
20007dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
20107dc194Richard Lowe            return (DW_DLV_NOCOUNT);
20207dc194Richard Lowe        }
20307dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
20407dc194Richard Lowe        break;
20549d3bc9Richard Lowe
20649d3bc9Richard Lowe    case DW_OP_regx:
20707dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
20807dc194Richard Lowe                                          encode_buffer,
20907dc194Richard Lowe                                          sizeof(encode_buffer));
21007dc194Richard Lowe        if (res != DW_DLV_OK) {
21107dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
21207dc194Richard Lowe            return (DW_DLV_NOCOUNT);
21307dc194Richard Lowe        }
21407dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
21507dc194Richard Lowe        break;
21649d3bc9Richard Lowe
21749d3bc9Richard Lowe    case DW_OP_lit0:
21849d3bc9Richard Lowe    case DW_OP_lit1:
21949d3bc9Richard Lowe    case DW_OP_lit2:
22049d3bc9Richard Lowe    case DW_OP_lit3:
22149d3bc9Richard Lowe    case DW_OP_lit4:
22249d3bc9Richard Lowe    case DW_OP_lit5:
22349d3bc9Richard Lowe    case DW_OP_lit6:
22449d3bc9Richard Lowe    case DW_OP_lit7:
22549d3bc9Richard Lowe    case DW_OP_lit8:
22649d3bc9Richard Lowe    case DW_OP_lit9:
22749d3bc9Richard Lowe    case DW_OP_lit10:
22849d3bc9Richard Lowe    case DW_OP_lit11:
22949d3bc9Richard Lowe    case DW_OP_lit12:
23049d3bc9Richard Lowe    case DW_OP_lit13:
23149d3bc9Richard Lowe    case DW_OP_lit14:
23249d3bc9Richard Lowe    case DW_OP_lit15:
23349d3bc9Richard Lowe    case DW_OP_lit16:
23449d3bc9Richard Lowe    case DW_OP_lit17:
23549d3bc9Richard Lowe    case DW_OP_lit18:
23649d3bc9Richard Lowe    case DW_OP_lit19:
23749d3bc9Richard Lowe    case DW_OP_lit20:
23849d3bc9Richard Lowe    case DW_OP_lit21:
23949d3bc9Richard Lowe    case DW_OP_lit22:
24049d3bc9Richard Lowe    case DW_OP_lit23:
24149d3bc9Richard Lowe    case DW_OP_lit24:
24249d3bc9Richard Lowe    case DW_OP_lit25:
24349d3bc9Richard Lowe    case DW_OP_lit26:
24449d3bc9Richard Lowe    case DW_OP_lit27:
24549d3bc9Richard Lowe    case DW_OP_lit28:
24649d3bc9Richard Lowe    case DW_OP_lit29:
24749d3bc9Richard Lowe    case DW_OP_lit30:
24849d3bc9Richard Lowe    case DW_OP_lit31:
24907dc194Richard Lowe        break;
25049d3bc9Richard Lowe
25149d3bc9Richard Lowe    case DW_OP_addr:
25207dc194Richard Lowe        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
25307dc194Richard Lowe        return (DW_DLV_NOCOUNT);
25449d3bc9Richard Lowe
25549d3bc9Richard Lowe    case DW_OP_const1u:
25649d3bc9Richard Lowe    case DW_OP_const1s:
25707dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
25807dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 1);
25907dc194Richard Lowe        operand_size = 1;
26007dc194Richard Lowe        break;
26149d3bc9Richard Lowe
26249d3bc9Richard Lowe    case DW_OP_const2u:
26349d3bc9Richard Lowe    case DW_OP_const2s:
26407dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
26507dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
26607dc194Richard Lowe        operand_size = 2;
26707dc194Richard Lowe        break;
26849d3bc9Richard Lowe
26949d3bc9Richard Lowe    case DW_OP_const4u:
27049d3bc9Richard Lowe    case DW_OP_const4s:
27107dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
27207dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
27307dc194Richard Lowe        operand_size = 4;
27407dc194Richard Lowe        break;
27549d3bc9Richard Lowe
27649d3bc9Richard Lowe    case DW_OP_const8u:
27749d3bc9Richard Lowe    case DW_OP_const8s:
27807dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
27907dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 8);
28007dc194Richard Lowe        operand_size = 8;
28107dc194Richard Lowe        break;
28249d3bc9Richard Lowe
28349d3bc9Richard Lowe    case DW_OP_constu:
28407dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1,
28507dc194Richard Lowe                                          &operand_size,
28607dc194Richard Lowe                                          encode_buffer,
28707dc194Richard Lowe                                          sizeof(encode_buffer));
28807dc194Richard Lowe        if (res != DW_DLV_OK) {
28907dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
29007dc194Richard Lowe            return (DW_DLV_NOCOUNT);
29107dc194Richard Lowe        }
29207dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
29307dc194Richard Lowe        break;
29449d3bc9Richard Lowe
29549d3bc9Richard Lowe    case DW_OP_consts:
29607dc194Richard Lowe        res = _dwarf_pro_encode_signed_leb128_nm(val1,
29707dc194Richard Lowe                                                 &operand_size,
29807dc194Richard Lowe                                                 encode_buffer,
29907dc194Richard Lowe                                                 sizeof(encode_buffer));
30007dc194Richard Lowe        if (res != DW_DLV_OK) {
30107dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
30207dc194Richard Lowe            return (DW_DLV_NOCOUNT);
30307dc194Richard Lowe        }
30407dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
30507dc194Richard Lowe        break;
30649d3bc9Richard Lowe
30749d3bc9Richard Lowe    case DW_OP_fbreg:
30807dc194Richard Lowe        res = _dwarf_pro_encode_signed_leb128_nm(val1,
30907dc194Richard Lowe                                                 &operand_size,
31007dc194Richard Lowe                                                 encode_buffer,
31107dc194Richard Lowe                                                 sizeof(encode_buffer));
31207dc194Richard Lowe        if (res != DW_DLV_OK) {
31307dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
31407dc194Richard Lowe            return (DW_DLV_NOCOUNT);
31507dc194Richard Lowe        }
31607dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
31707dc194Richard Lowe        break;
31849d3bc9Richard Lowe
31949d3bc9Richard Lowe    case DW_OP_bregx:
32007dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
32107dc194Richard Lowe                                          encode_buffer,
32207dc194Richard Lowe                                          sizeof(encode_buffer));
32307dc194Richard Lowe        if (res != DW_DLV_OK) {
32407dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
32507dc194Richard Lowe            return (DW_DLV_NOCOUNT);
32607dc194Richard Lowe        }
32707dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
32807dc194Richard Lowe        /* put this one directly into 'operand' at tail of prev value */
32907dc194Richard Lowe        res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size,
33007dc194Richard Lowe                                                 ((char *) operand) +
33107dc194Richard Lowe                                                 operand_size,
33207dc194Richard Lowe                                                 sizeof
33307dc194Richard Lowe                                                 (encode_buffer2));
33407dc194Richard Lowe        if (res != DW_DLV_OK) {
33507dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
33607dc194Richard Lowe            return (DW_DLV_NOCOUNT);
33707dc194Richard Lowe        }
33807dc194Richard Lowe        operand_size += operand2_size;
33949d3bc9Richard Lowe
34049d3bc9Richard Lowe    case DW_OP_dup:
34149d3bc9Richard Lowe    case DW_OP_drop:
34207dc194Richard Lowe        break;
34349d3bc9Richard Lowe
34449d3bc9Richard Lowe    case DW_OP_pick:
34507dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
34607dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
34707dc194Richard Lowe                        sizeof(val1), 1);
34807dc194Richard Lowe        operand_size = 1;
34907dc194Richard Lowe        break;
35049d3bc9Richard Lowe
35149d3bc9Richard Lowe    case DW_OP_over:
35249d3bc9Richard Lowe    case DW_OP_swap:
35349d3bc9Richard Lowe    case DW_OP_rot:
35449d3bc9Richard Lowe    case DW_OP_deref:
35549d3bc9Richard Lowe    case DW_OP_xderef:
35607dc194Richard Lowe        break;
35749d3bc9Richard Lowe
35849d3bc9Richard Lowe    case DW_OP_deref_size:
35949d3bc9Richard Lowe    case DW_OP_xderef_size:
36007dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
36107dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
36207dc194Richard Lowe                        sizeof(val1), 1);
36307dc194Richard Lowe        operand_size = 1;
36407dc194Richard Lowe        break;
36549d3bc9Richard Lowe
36649d3bc9Richard Lowe    case DW_OP_abs:
36749d3bc9Richard Lowe    case DW_OP_and:
36849d3bc9Richard Lowe    case DW_OP_div:
36949d3bc9Richard Lowe    case DW_OP_minus:
37049d3bc9Richard Lowe    case DW_OP_mod:
37149d3bc9Richard Lowe    case DW_OP_mul:
37249d3bc9Richard Lowe    case DW_OP_neg:
37349d3bc9Richard Lowe    case DW_OP_not:
37449d3bc9Richard Lowe    case DW_OP_or:
37549d3bc9Richard Lowe    case DW_OP_plus:
37607dc194Richard Lowe        break;
37749d3bc9Richard Lowe
37849d3bc9Richard Lowe    case DW_OP_plus_uconst:
37907dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
38007dc194Richard Lowe                                          encode_buffer,
38107dc194Richard Lowe                                          sizeof(encode_buffer));
38207dc194Richard Lowe        if (res != DW_DLV_OK) {
38307dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
38407dc194Richard Lowe            return (DW_DLV_NOCOUNT);
38507dc194Richard Lowe        }
38607dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
38707dc194Richard Lowe        break;
38849d3bc9Richard Lowe
38949d3bc9Richard Lowe    case DW_OP_shl:
39049d3bc9Richard Lowe    case DW_OP_shr:
39149d3bc9Richard Lowe    case DW_OP_shra:
39249d3bc9Richard Lowe    case DW_OP_xor:
39307dc194Richard Lowe        break;
39449d3bc9Richard Lowe
39549d3bc9Richard Lowe    case DW_OP_le:
39649d3bc9Richard Lowe    case DW_OP_ge:
39749d3bc9Richard Lowe    case DW_OP_eq:
39849d3bc9Richard Lowe    case DW_OP_lt:
39949d3bc9Richard Lowe    case DW_OP_gt:
40049d3bc9Richard Lowe    case DW_OP_ne:
40107dc194Richard Lowe        break;
40249d3bc9Richard Lowe
40349d3bc9Richard Lowe    case DW_OP_skip:
40449d3bc9Richard Lowe    case DW_OP_bra:
40507dc194Richard Lowe        /* FIX: unhandled! OP_bra, OP_skip! */
40607dc194Richard Lowe        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
40707dc194Richard Lowe        return (DW_DLV_NOCOUNT);
40849d3bc9Richard Lowe
40949d3bc9Richard Lowe    case DW_OP_piece:
41007dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
41107dc194Richard Lowe                                          encode_buffer,
41207dc194Richard Lowe                                          sizeof(encode_buffer));
41307dc194Richard Lowe        if (res != DW_DLV_OK) {
41407dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
41507dc194Richard Lowe            return (DW_DLV_NOCOUNT);
41607dc194Richard Lowe        }
41707dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
41807dc194Richard Lowe        break;
41949d3bc9Richard Lowe
42049d3bc9Richard Lowe    case DW_OP_nop:
42107dc194Richard Lowe        break;
42207dc194Richard Lowe    case DW_OP_push_object_address:     /* DWARF3 */
42307dc194Richard Lowe        break;
42407dc194Richard Lowe    case DW_OP_call2:           /* DWARF3 */
42507dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
42607dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
42707dc194Richard Lowe        operand_size = 2;
42807dc194Richard Lowe        break;
42907dc194Richard Lowe
43007dc194Richard Lowe    case DW_OP_call4:           /* DWARF3 */
43107dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
43207dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
43307dc194Richard Lowe        operand_size = 4;
43407dc194Richard Lowe        break;
43507dc194Richard Lowe
43607dc194Richard Lowe    case DW_OP_call_ref:        /* DWARF3 */
43707dc194Richard Lowe        operand = (Dwarf_Small *) & operand_buffer[0];
43807dc194Richard Lowe        WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1),
43907dc194Richard Lowe                        dbg->de_offset_size);
44007dc194Richard Lowe        operand_size = dbg->de_offset_size;
44107dc194Richard Lowe        break;
44207dc194Richard Lowe    case DW_OP_form_tls_address:        /* DWARF3f */
44307dc194Richard Lowe        break;
44407dc194Richard Lowe    case DW_OP_call_frame_cfa:  /* DWARF3f */
44507dc194Richard Lowe        break;
44607dc194Richard Lowe    case DW_OP_bit_piece:       /* DWARF3f */
44707dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
44807dc194Richard Lowe                                          encode_buffer,
44907dc194Richard Lowe                                          sizeof(encode_buffer));
45007dc194Richard Lowe        if (res != DW_DLV_OK) {
45107dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
45207dc194Richard Lowe            return (DW_DLV_NOCOUNT);
45307dc194Richard Lowe        }
45407dc194Richard Lowe        operand = (Dwarf_Small *) encode_buffer;
45507dc194Richard Lowe        /* put this one directly into 'operand' at tail of prev value */
45607dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size,
45707dc194Richard Lowe                                          ((char *) operand) +
45807dc194Richard Lowe                                          operand_size,
45907dc194Richard Lowe                                          sizeof(encode_buffer2));
46007dc194Richard Lowe        if (res != DW_DLV_OK) {
46107dc194Richard Lowe            _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
46207dc194Richard Lowe            return (DW_DLV_NOCOUNT);
46307dc194Richard Lowe        }
46407dc194Richard Lowe        operand_size += operand2_size;
465c160bf3Toomas Soome	break;
46649d3bc9Richard Lowe
46749d3bc9Richard Lowe    default:
46807dc194Richard Lowe        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
46907dc194Richard Lowe        return (DW_DLV_NOCOUNT);
47049d3bc9Richard Lowe    }
47149d3bc9Richard Lowe
47249d3bc9Richard Lowe    next_byte_offset = expr->ex_next_byte_offset + operand_size + 1;
47349d3bc9Richard Lowe
47449d3bc9Richard Lowe    if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
47507dc194Richard Lowe        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
47607dc194Richard Lowe        return (DW_DLV_NOCOUNT);
47749d3bc9Richard Lowe    }
47849d3bc9Richard Lowe
47949d3bc9Richard Lowe    next_byte_ptr =
48007dc194Richard Lowe        &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
48149d3bc9Richard Lowe
48249d3bc9Richard Lowe    *next_byte_ptr = opcode;
48349d3bc9Richard Lowe    next_byte_ptr++;
48449d3bc9Richard Lowe    memcpy(next_byte_ptr, operand, operand_size);
48549d3bc9Richard Lowe
48649d3bc9Richard Lowe    expr->ex_next_byte_offset = next_byte_offset;
48749d3bc9Richard Lowe    return (next_byte_offset);
48849d3bc9Richard Lowe}
48949d3bc9Richard Lowe
49049d3bc9Richard LoweDwarf_Unsigned
49149d3bc9Richard Lowedwarf_add_expr_addr_b(Dwarf_P_Expr expr,
49207dc194Richard Lowe                      Dwarf_Unsigned addr,
49307dc194Richard Lowe                      Dwarf_Unsigned sym_index, Dwarf_Error * error)
49449d3bc9Richard Lowe{
49549d3bc9Richard Lowe    Dwarf_P_Debug dbg;
49649d3bc9Richard Lowe    Dwarf_Small *next_byte_ptr;
49749d3bc9Richard Lowe    Dwarf_Unsigned next_byte_offset;
49849d3bc9Richard Lowe    int upointer_size;
49949d3bc9Richard Lowe
50049d3bc9Richard Lowe    if (expr == NULL) {
50107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
50207dc194Richard Lowe        return (DW_DLV_NOCOUNT);
50349d3bc9Richard Lowe    }
50449d3bc9Richard Lowe
50549d3bc9Richard Lowe    dbg = expr->ex_dbg;
50649d3bc9Richard Lowe    if (dbg == NULL) {
50707dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
50807dc194Richard Lowe        return (DW_DLV_NOCOUNT);
50949d3bc9Richard Lowe    }
51049d3bc9Richard Lowe
51149d3bc9Richard Lowe    upointer_size = dbg->de_pointer_size;
51249d3bc9Richard Lowe    next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1;
51349d3bc9Richard Lowe    if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
51407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
51507dc194Richard Lowe        return (DW_DLV_NOCOUNT);
51649d3bc9Richard Lowe    }
51749d3bc9Richard Lowe
51849d3bc9Richard Lowe    next_byte_ptr =
51907dc194Richard Lowe        &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
52049d3bc9Richard Lowe
52149d3bc9Richard Lowe    *next_byte_ptr = DW_OP_addr;
52249d3bc9Richard Lowe    next_byte_ptr++;
52349d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr,
52407dc194Richard Lowe                    sizeof(addr), upointer_size);
52549d3bc9Richard Lowe
52649d3bc9Richard Lowe    if (expr->ex_reloc_offset != 0) {
52707dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR);
52807dc194Richard Lowe        return (DW_DLV_NOCOUNT);
52949d3bc9Richard Lowe    }
53049d3bc9Richard Lowe
53149d3bc9Richard Lowe    expr->ex_reloc_sym_index = sym_index;
53249d3bc9Richard Lowe    expr->ex_reloc_offset = expr->ex_next_byte_offset + 1;
53349d3bc9Richard Lowe
53449d3bc9Richard Lowe    expr->ex_next_byte_offset = next_byte_offset;
53549d3bc9Richard Lowe    return (next_byte_offset);
53649d3bc9Richard Lowe}
53749d3bc9Richard Lowe
53849d3bc9Richard LoweDwarf_Unsigned
53949d3bc9Richard Lowedwarf_add_expr_addr(Dwarf_P_Expr expr,
54007dc194Richard Lowe                    Dwarf_Unsigned addr,
54107dc194Richard Lowe                    Dwarf_Signed sym_index, Dwarf_Error * error)
54249d3bc9Richard Lowe{
54349d3bc9Richard Lowe    return
54407dc194Richard Lowe        dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index,
54507dc194Richard Lowe                              error);
54649d3bc9Richard Lowe}
54749d3bc9Richard Lowe
54849d3bc9Richard Lowe
54949d3bc9Richard LoweDwarf_Unsigned
55049d3bc9Richard Lowedwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error)
55149d3bc9Richard Lowe{
55249d3bc9Richard Lowe    if (expr == NULL) {
55307dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
55407dc194Richard Lowe        return (DW_DLV_NOCOUNT);
55549d3bc9Richard Lowe    }
55649d3bc9Richard Lowe
55749d3bc9Richard Lowe    if (expr->ex_dbg == NULL) {
55807dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
55907dc194Richard Lowe        return (DW_DLV_NOCOUNT);
56049d3bc9Richard Lowe    }
56149d3bc9Richard Lowe
56249d3bc9Richard Lowe    return (expr->ex_next_byte_offset);
56349d3bc9Richard Lowe}
56449d3bc9Richard Lowe
56507dc194Richard Lowevoid
56607dc194Richard Lowedwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error)
56707dc194Richard Lowe{
56807dc194Richard Lowe   if (expr == NULL) {
56907dc194Richard Lowe      _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
57007dc194Richard Lowe      return;
57107dc194Richard Lowe   }
57207dc194Richard Lowe   expr->ex_next_byte_offset=0;
57307dc194Richard Lowe}
57407dc194Richard Lowe
57549d3bc9Richard Lowe
57649d3bc9Richard LoweDwarf_Addr
57749d3bc9Richard Lowedwarf_expr_into_block(Dwarf_P_Expr expr,
57807dc194Richard Lowe                      Dwarf_Unsigned * length, Dwarf_Error * error)
57949d3bc9Richard Lowe{
58049d3bc9Richard Lowe    if (expr == NULL) {
58107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
58207dc194Richard Lowe        return (DW_DLV_BADADDR);
58349d3bc9Richard Lowe    }
58449d3bc9Richard Lowe
58549d3bc9Richard Lowe    if (expr->ex_dbg == NULL) {
58607dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
58707dc194Richard Lowe        return (DW_DLV_BADADDR);
58849d3bc9Richard Lowe    }
58949d3bc9Richard Lowe
59049d3bc9Richard Lowe    if (length != NULL)
59107dc194Richard Lowe        *length = expr->ex_next_byte_offset;
59249d3bc9Richard Lowe    /* The following cast from pointer to integer is ok as long as
59349d3bc9Richard Lowe       Dwarf_Addr is at least as large as a pointer. Which is a
59449d3bc9Richard Lowe       requirement of libdwarf so must be satisfied (some compilers
59549d3bc9Richard Lowe       emit a warning about the following line). */
59649d3bc9Richard Lowe    return ((Dwarf_Addr)(uintptr_t) &(expr->ex_byte_stream[0]));
59749d3bc9Richard Lowe}