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