Home | History | Annotate | Line # | Download | only in libdwarf
dwarf_pro_expr.c revision 1.2.8.2
      1 /*	$NetBSD: dwarf_pro_expr.c,v 1.2.8.2 2014/08/19 23:46:44 tls Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2010 Kai Wang
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include "_libdwarf.h"
     30 
     31 __RCSID("$NetBSD: dwarf_pro_expr.c,v 1.2.8.2 2014/08/19 23:46:44 tls Exp $");
     32 ELFTC_VCSID("Id: dwarf_pro_expr.c 2074 2011-10-27 03:34:33Z jkoshy ");
     33 
     34 static struct _Dwarf_P_Expr_Entry *
     35 _dwarf_add_expr(Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1,
     36     Dwarf_Unsigned val2, Dwarf_Error *error)
     37 {
     38 	struct _Dwarf_P_Expr_Entry *ee;
     39 	Dwarf_Debug dbg;
     40 	int len;
     41 
     42 	dbg = expr != NULL ? expr->pe_dbg : NULL;
     43 
     44 	if (_dwarf_loc_expr_add_atom(expr->pe_dbg, NULL, NULL, opcode, val1,
     45 	    val2, &len, error) != DW_DLE_NONE)
     46 		return (NULL);
     47 	assert(len > 0);
     48 
     49 	if ((ee = calloc(1, sizeof(*ee))) == NULL) {
     50 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     51 		return (NULL);
     52 	}
     53 
     54 	STAILQ_INSERT_TAIL(&expr->pe_eelist, ee, ee_next);
     55 
     56 	ee->ee_loc.lr_atom = opcode;
     57 	ee->ee_loc.lr_number = val1;
     58 	ee->ee_loc.lr_number2 = val2;
     59 	ee->ee_loc.lr_offset = expr->pe_length;
     60 	expr->pe_length += len;
     61 	expr->pe_invalid = 1;
     62 
     63 	return (ee);
     64 }
     65 
     66 int
     67 _dwarf_expr_into_block(Dwarf_P_Expr expr, Dwarf_Error *error)
     68 {
     69 	struct _Dwarf_P_Expr_Entry *ee;
     70 	Dwarf_Debug dbg;
     71 	int len, pos, ret;
     72 
     73 	dbg = expr != NULL ? expr->pe_dbg : NULL;
     74 
     75 	if (expr->pe_block != NULL) {
     76 		free(expr->pe_block);
     77 		expr->pe_block = NULL;
     78 	}
     79 
     80 	if (expr->pe_length <= 0) {
     81 		DWARF_SET_ERROR(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
     82 		return (DW_DLE_EXPR_LENGTH_BAD);
     83 	}
     84 
     85 
     86 	if ((expr->pe_block = calloc((size_t) expr->pe_length, 1)) == NULL) {
     87 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     88 		return (DW_DLE_MEMORY);
     89 	}
     90 
     91 	pos = 0;
     92 	STAILQ_FOREACH(ee, &expr->pe_eelist, ee_next) {
     93 		assert((Dwarf_Unsigned) pos < expr->pe_length);
     94 		ret = _dwarf_loc_expr_add_atom(expr->pe_dbg,
     95 		    &expr->pe_block[pos], &expr->pe_block[expr->pe_length],
     96 		    ee->ee_loc.lr_atom, ee->ee_loc.lr_number,
     97 		    ee->ee_loc.lr_number2, &len, error);
     98 		assert(ret == DW_DLE_NONE);
     99 		assert(len > 0);
    100 		pos += len;
    101 	}
    102 
    103 	expr->pe_invalid = 0;
    104 
    105 	return (DW_DLE_NONE);
    106 }
    107 
    108 void
    109 _dwarf_expr_cleanup(Dwarf_P_Debug dbg)
    110 {
    111 	Dwarf_P_Expr pe, tpe;
    112 	struct _Dwarf_P_Expr_Entry *ee, *tee;
    113 
    114 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
    115 
    116 	STAILQ_FOREACH_SAFE(pe, &dbg->dbgp_pelist, pe_next, tpe) {
    117 		STAILQ_REMOVE(&dbg->dbgp_pelist, pe, _Dwarf_P_Expr, pe_next);
    118 		STAILQ_FOREACH_SAFE(ee, &pe->pe_eelist, ee_next, tee) {
    119 			STAILQ_REMOVE(&pe->pe_eelist, ee, _Dwarf_P_Expr_Entry,
    120 			    ee_next);
    121 			free(ee);
    122 		}
    123 		if (pe->pe_block)
    124 			free(pe->pe_block);
    125 		free(pe);
    126 	}
    127 }
    128 
    129 Dwarf_P_Expr
    130 dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error *error)
    131 {
    132 	Dwarf_P_Expr pe;
    133 
    134 	if (dbg == NULL) {
    135 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    136 		return (DW_DLV_BADADDR);
    137 	}
    138 
    139 	if ((pe = calloc(1, sizeof(struct _Dwarf_P_Expr))) == NULL) {
    140 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    141 		return (DW_DLV_BADADDR);
    142 	}
    143 	STAILQ_INIT(&pe->pe_eelist);
    144 
    145 	STAILQ_INSERT_TAIL(&dbg->dbgp_pelist, pe, pe_next);
    146 	pe->pe_dbg = dbg;
    147 
    148 	return (pe);
    149 }
    150 
    151 Dwarf_Unsigned
    152 dwarf_add_expr_gen(Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1,
    153     Dwarf_Unsigned val2, Dwarf_Error *error)
    154 {
    155 
    156 	if (expr == NULL) {
    157 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
    158 		return (DW_DLV_NOCOUNT);
    159 	}
    160 
    161 	if (_dwarf_add_expr(expr, opcode, val1, val2, error) == NULL)
    162 		return (DW_DLV_NOCOUNT);
    163 
    164 	return (expr->pe_length);
    165 }
    166 
    167 Dwarf_Unsigned
    168 dwarf_add_expr_addr(Dwarf_P_Expr expr, Dwarf_Unsigned address,
    169     Dwarf_Signed sym_index, Dwarf_Error *error)
    170 {
    171 
    172 	return (dwarf_add_expr_addr_b(expr, address, sym_index, error));
    173 }
    174 
    175 Dwarf_Unsigned
    176 dwarf_add_expr_addr_b(Dwarf_P_Expr expr, Dwarf_Unsigned address,
    177     Dwarf_Unsigned sym_index, Dwarf_Error *error)
    178 {
    179 	struct _Dwarf_P_Expr_Entry *ee;
    180 
    181 	if (expr == NULL) {
    182 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
    183 		return (DW_DLV_NOCOUNT);
    184 	}
    185 
    186 	if ((ee = _dwarf_add_expr(expr, DW_OP_addr, address, 0, error)) == NULL)
    187 		return (DW_DLV_NOCOUNT);
    188 
    189 	ee->ee_sym = sym_index;
    190 
    191 	return (expr->pe_length);
    192 }
    193 
    194 Dwarf_Unsigned
    195 dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error *error)
    196 {
    197 
    198 	if (expr == NULL) {
    199 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
    200 		return (DW_DLV_NOCOUNT);
    201 	}
    202 
    203 	return (expr->pe_length);
    204 }
    205 
    206 Dwarf_Addr
    207 dwarf_expr_into_block(Dwarf_P_Expr expr, Dwarf_Unsigned *length,
    208     Dwarf_Error *error)
    209 {
    210 	Dwarf_Debug dbg;
    211 
    212 	dbg = expr != NULL ? expr->pe_dbg : NULL;
    213 
    214 	if (expr == NULL || length == NULL) {
    215 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
    216 		return ((Dwarf_Addr) (uintptr_t) DW_DLV_BADADDR);
    217 	}
    218 
    219 	if (expr->pe_block == NULL || expr->pe_invalid)
    220 		if (_dwarf_expr_into_block(expr, error) != DW_DLE_NONE)
    221 			return ((Dwarf_Addr) (uintptr_t) DW_DLV_BADADDR);
    222 
    223 	*length = expr->pe_length;
    224 
    225 	return ((Dwarf_Addr) (uintptr_t) expr->pe_block);
    226 }
    227