1251876Speter/* $NetBSD: dwarf_pro_frame.c,v 1.5 2024/03/03 17:37:32 christos Exp $ */ 2251876Speter 3251876Speter/*- 4251876Speter * Copyright (c) 2010 Kai Wang 5251876Speter * All rights reserved. 6251876Speter * 7251876Speter * Redistribution and use in source and binary forms, with or without 8251876Speter * modification, are permitted provided that the following conditions 9251876Speter * are met: 10251876Speter * 1. Redistributions of source code must retain the above copyright 11251876Speter * notice, this list of conditions and the following disclaimer. 12251876Speter * 2. Redistributions in binary form must reproduce the above copyright 13251876Speter * notice, this list of conditions and the following disclaimer in the 14251876Speter * documentation and/or other materials provided with the distribution. 15251876Speter * 16251876Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17251876Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18251876Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19251876Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20251876Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21251876Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22251876Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23251876Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24251876Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25251876Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26251876Speter * SUCH DAMAGE. 27251876Speter */ 28251876Speter 29251876Speter#include "_libdwarf.h" 30251876Speter 31251876Speter__RCSID("$NetBSD: dwarf_pro_frame.c,v 1.5 2024/03/03 17:37:32 christos Exp $"); 32251876SpeterELFTC_VCSID("Id: dwarf_pro_frame.c 2074 2011-10-27 03:34:33Z jkoshy"); 33251876Speter 34251876SpeterDwarf_P_Fde 35251876Speterdwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error *error) 36251876Speter{ 37251876Speter Dwarf_P_Fde fde; 38251876Speter 39251876Speter if (dbg == NULL) { 40251876Speter DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 41251876Speter return (DW_DLV_BADADDR); 42251876Speter } 43251876Speter 44251876Speter if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) { 45251876Speter DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 46251876Speter return (DW_DLV_BADADDR); 47251876Speter } 48251876Speter 49251876Speter fde->fde_dbg = dbg; 50251876Speter 51251876Speter return (fde); 52251876Speter} 53251876Speter 54251876SpeterDwarf_Unsigned 55251876Speterdwarf_add_frame_cie(Dwarf_P_Debug dbg, char *augmenter, Dwarf_Small caf, 56251876Speter Dwarf_Small daf, Dwarf_Small ra, Dwarf_Ptr initinst, 57251876Speter Dwarf_Unsigned inst_len, Dwarf_Error *error) 58251876Speter{ 59251876Speter Dwarf_P_Cie cie; 60251876Speter 61251876Speter if (dbg == NULL) { 62251876Speter DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 63251876Speter return (DW_DLV_NOCOUNT); 64251876Speter } 65251876Speter 66251876Speter if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) { 67251876Speter DWARF_SET_ERROR(dbg, error,DW_DLE_MEMORY); 68251876Speter return (DW_DLV_NOCOUNT); 69253734Speter } 70253734Speter STAILQ_INSERT_TAIL(&dbg->dbgp_cielist, cie, cie_next); 71253734Speter 72253734Speter cie->cie_index = dbg->dbgp_cielen++; 73253734Speter 74253734Speter if (augmenter != NULL) { 75253734Speter cie->cie_augment = (uint8_t *) strdup(augmenter); 76253734Speter if (cie->cie_augment == NULL) { 77253734Speter DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 78253734Speter return (DW_DLV_NOCOUNT); 79253734Speter } 80253734Speter } 81253734Speter 82253734Speter cie->cie_caf = caf; 83253734Speter cie->cie_daf = (int8_t) daf; /* daf is signed. */ 84253734Speter cie->cie_ra = ra; 85253734Speter if (initinst != NULL && inst_len > 0) { 86253734Speter cie->cie_initinst = malloc((size_t) inst_len); 87253734Speter if (cie->cie_initinst == NULL) { 88253734Speter DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 89253734Speter return (DW_DLV_NOCOUNT); 90253734Speter } 91253734Speter memcpy(cie->cie_initinst, initinst, inst_len); 92253734Speter cie->cie_instlen = inst_len; 93251876Speter } 94251876Speter 95251876Speter return (cie->cie_index); 96251876Speter} 97251876Speter 98251876SpeterDwarf_Unsigned 99251876Speterdwarf_add_frame_fde(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die, 100253734Speter Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len, 101251876Speter Dwarf_Unsigned symbol_index, Dwarf_Error *error) 102251876Speter{ 103251876Speter 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