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