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