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