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