1/* $NetBSD: dwarf_pro_frame.c,v 1.5 2024/03/03 17:37:32 christos 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_frame.c,v 1.5 2024/03/03 17:37:32 christos Exp $"); 32ELFTC_VCSID("Id: dwarf_pro_frame.c 2074 2011-10-27 03:34:33Z jkoshy"); 33 34Dwarf_P_Fde 35dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error *error) 36{ 37 Dwarf_P_Fde fde; 38 39 if (dbg == NULL) { 40 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 41 return (DW_DLV_BADADDR); 42 } 43 44 if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) { 45 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 46 return (DW_DLV_BADADDR); 47 } 48 49 fde->fde_dbg = dbg; 50 51 return (fde); 52} 53 54Dwarf_Unsigned 55dwarf_add_frame_cie(Dwarf_P_Debug dbg, char *augmenter, Dwarf_Small caf, 56 Dwarf_Small daf, Dwarf_Small ra, Dwarf_Ptr initinst, 57 Dwarf_Unsigned inst_len, Dwarf_Error *error) 58{ 59 Dwarf_P_Cie cie; 60 61 if (dbg == NULL) { 62 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 63 return (DW_DLV_NOCOUNT); 64 } 65 66 if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) { 67 DWARF_SET_ERROR(dbg, error,DW_DLE_MEMORY); 68 return (DW_DLV_NOCOUNT); 69 } 70 STAILQ_INSERT_TAIL(&dbg->dbgp_cielist, cie, cie_next); 71 72 cie->cie_index = dbg->dbgp_cielen++; 73 74 if (augmenter != NULL) { 75 cie->cie_augment = (uint8_t *) strdup(augmenter); 76 if (cie->cie_augment == NULL) { 77 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 78 return (DW_DLV_NOCOUNT); 79 } 80 } 81 82 cie->cie_caf = caf; 83 cie->cie_daf = (int8_t) daf; /* daf is signed. */ 84 cie->cie_ra = ra; 85 if (initinst != NULL && inst_len > 0) { 86 cie->cie_initinst = malloc((size_t) inst_len); 87 if (cie->cie_initinst == NULL) { 88 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 89 return (DW_DLV_NOCOUNT); 90 } 91 memcpy(cie->cie_initinst, initinst, inst_len); 92 cie->cie_instlen = inst_len; 93 } 94 95 return (cie->cie_index); 96} 97 98Dwarf_Unsigned 99dwarf_add_frame_fde(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die, 100 Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len, 101 Dwarf_Unsigned symbol_index, Dwarf_Error *error) 102{ 103 104 return (dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, code_len, 105 symbol_index, 0, 0, error)); 106} 107 108Dwarf_Unsigned 109dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die, 110 Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len, 111 Dwarf_Unsigned symbol_index, Dwarf_Unsigned end_symbol_index, 112 Dwarf_Addr offset_from_end_sym, Dwarf_Error *error) 113{ 114 Dwarf_P_Cie ciep; 115 int i; 116 117 /* 118 * XXX SGI libdwarf need the DIE arg because later it will insert a 119 * DW_AT_MIPS_fde attribute, which points to the offset the 120 * correspoding FDE, into this DIE. Do we need this? 121 */ 122 (void) die; 123 124 if (dbg == NULL || fde == NULL || fde->fde_dbg != dbg) { 125 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 126 return (DW_DLV_NOCOUNT); 127 } 128 129 ciep = STAILQ_FIRST(&dbg->dbgp_cielist); 130 for (i = 0; (Dwarf_Unsigned) i < cie; i++) { 131 ciep = STAILQ_NEXT(ciep, cie_next); 132 if (ciep == NULL) 133 break; 134 } 135 if (ciep == NULL) { 136 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 137 return (DW_DLV_NOCOUNT); 138 } 139 140 if (end_symbol_index > 0 && 141 (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) { 142 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 143 return (DW_DLV_NOCOUNT); 144 } 145 146 fde->fde_cie = ciep; 147 fde->fde_initloc = virt_addr; 148 fde->fde_adrange = code_len; 149 fde->fde_symndx = symbol_index; 150 fde->fde_esymndx = end_symbol_index; 151 fde->fde_eoff = offset_from_end_sym; 152 153 STAILQ_INSERT_TAIL(&dbg->dbgp_fdelist, fde, fde_next); 154 155 return (dbg->dbgp_fdelen++); 156} 157 158Dwarf_P_Fde 159dwarf_fde_cfa_offset(Dwarf_P_Fde fde, Dwarf_Unsigned reg, Dwarf_Signed offset, 160 Dwarf_Error *error) 161{ 162 int ret; 163 Dwarf_Debug dbg; 164 165 dbg = fde != NULL ? fde->fde_dbg : NULL; 166 167 if (fde == NULL || reg > 0x3f) { 168 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 169 return (DW_DLV_BADADDR); 170 } 171 172 ret = _dwarf_frame_fde_add_inst(fde, DW_CFA_offset | (reg & 0x3f), 173 offset, 0, error); 174 175 if (ret != DW_DLE_NONE) 176 return (DW_DLV_BADADDR); 177 178 return (fde); 179} 180 181Dwarf_P_Fde 182dwarf_add_fde_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1, 183 Dwarf_Unsigned val2, Dwarf_Error *error) 184{ 185 int ret; 186 187 if (fde == NULL) { 188 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 189 return (DW_DLV_BADADDR); 190 } 191 192 ret = _dwarf_frame_fde_add_inst(fde, op, val1, val2, error); 193 194 if (ret != DW_DLE_NONE) 195 return (DW_DLV_BADADDR); 196 197 return (fde); 198} 199