1/* 2 3 Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of version 2.1 of the GNU Lesser General Public License 7 as published by the Free Software Foundation. 8 9 This program is distributed in the hope that it would be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 Further, this software is distributed without any warranty that it is 14 free of the rightful claim of any third person regarding infringement 15 or the like. Any license provided herein, whether implied or 16 otherwise, applies only to this software file. Patent licenses, if 17 any, provided herein do not apply to combinations of this program with 18 other software, or any other product whatsoever. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this program; if not, write the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 23 USA. 24 25 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 26 Mountain View, CA 94043, or: 27 28 http://www.sgi.com 29 30 For further information regarding this notice, see: 31 32 http://oss.sgi.com/projects/GenInfo/NoticeExplan 33 34*/ 35 36 37 38#include "config.h" 39#include "dwarf_incl.h" 40#include <stdio.h> 41#include <stdlib.h> 42#include "dwarf_frame.h" 43#include "dwarf_arange.h" /* using Arange as a way to build a 44 list */ 45 46/* 47 Used by rqs (an IRIX application). 48 Not needed except for that one application. 49 Should be moved to its own source file since 50 it is so rarely needed. 51 Returns DW_DLV_OK if returns the arrays. 52 Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?) 53 Returns DW_DLV_ERROR if there is an error. 54 55 Uses DW_FRAME_CFA_COL because IRIX is only DWARF2 56 and that is what IRIX compilers and compatible 57 compilers support on IRIX. 58*/ 59int 60_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, 61 Dwarf_Off ** offsetlist, 62 Dwarf_Signed * returncount, 63 Dwarf_Error * err) 64{ 65 int retval = DW_DLV_OK; 66 int res; 67 Dwarf_Cie *cie_data; 68 Dwarf_Signed cie_count; 69 Dwarf_Fde *fde_data; 70 Dwarf_Signed fde_count; 71 Dwarf_Signed i; 72 Dwarf_Frame_Op *frame_inst; 73 Dwarf_Fde fdep; 74 Dwarf_Cie ciep; 75 Dwarf_Chain curr_chain = 0; 76 Dwarf_Chain head_chain = 0; 77 Dwarf_Chain prev_chain = 0; 78 Dwarf_Arange arange; 79 Dwarf_Unsigned arange_count = 0; 80 Dwarf_Addr *arange_addrs = 0; 81 Dwarf_Off *arange_offsets = 0; 82 83 res = dwarf_get_fde_list(dbg, &cie_data, &cie_count, 84 &fde_data, &fde_count, err); 85 if (res != DW_DLV_OK) { 86 return res; 87 } 88 89 res = 90 _dwarf_load_section(dbg, 91 dbg->de_debug_frame_index, 92 &dbg->de_debug_frame, err); 93 if (res != DW_DLV_OK) { 94 return res; 95 } 96 97 for (i = 0; i < cie_count; i++) { 98 Dwarf_Off instoff = 0; 99 Dwarf_Signed initial_instructions_length = 0; 100 Dwarf_Small *instr_end = 0; 101 Dwarf_Sword icount = 0; 102 int j; 103 int dw_err; 104 105 ciep = cie_data[i]; 106 instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame; 107 initial_instructions_length = ciep->ci_length + 108 ciep->ci_length_size + ciep->ci_extension_size - 109 (ciep->ci_cie_instr_start - ciep->ci_cie_start); 110 instr_end = ciep->ci_cie_instr_start + 111 initial_instructions_length; 112 res = _dwarf_exec_frame_instr( /* make_instr */ true, 113 &frame_inst, 114 /* search_pc= */ false, 115 /* search_pc_val= */ 0, 116 /* location */ 0, 117 ciep->ci_cie_instr_start, 118 instr_end, 119 /* Dwarf_frame= */ 0, 120 /* cie= */ 0, 121 dbg, 122 DW_FRAME_CFA_COL, 123 &icount, &dw_err); 124 if (res == DW_DLV_ERROR) { 125 _dwarf_error(dbg, err, dw_err); 126 return (res); 127 } else if (res == DW_DLV_NO_ENTRY) { 128 continue; 129 } 130 131 for (j = 0; j < icount; ++j) { 132 Dwarf_Frame_Op *finst = frame_inst + j; 133 134 if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) { 135 /* is DW_CFA_set_loc */ 136 Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset; 137 Dwarf_Off off = finst->fp_instr_offset + instoff; 138 139 arange = (Dwarf_Arange) 140 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); 141 if (arange == NULL) { 142 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 143 return (DW_DLV_ERROR); 144 } 145 arange->ar_address = add; 146 arange->ar_info_offset = off; 147 arange_count++; 148 curr_chain = (Dwarf_Chain) 149 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); 150 if (curr_chain == NULL) { 151 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 152 return (DW_DLV_ERROR); 153 } 154 curr_chain->ch_item = arange; 155 if (head_chain == NULL) 156 head_chain = prev_chain = curr_chain; 157 else { 158 prev_chain->ch_next = curr_chain; 159 prev_chain = curr_chain; 160 } 161 } 162 } 163 dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); 164 165 } 166 for (i = 0; i < fde_count; i++) { 167 Dwarf_Small *instr_end = 0; 168 Dwarf_Sword icount = 0; 169 Dwarf_Signed instructions_length = 0; 170 Dwarf_Off instoff = 0; 171 Dwarf_Off off = 0; 172 Dwarf_Addr addr = 0; 173 int j; 174 int dw_err; 175 176 fdep = fde_data[i]; 177 off = fdep->fd_initial_loc_pos - dbg->de_debug_frame; 178 addr = fdep->fd_initial_location; 179 arange = (Dwarf_Arange) 180 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); 181 if (arange == NULL) { 182 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 183 return (DW_DLV_ERROR); 184 } 185 arange->ar_address = addr; 186 arange->ar_info_offset = off; 187 arange_count++; 188 curr_chain = (Dwarf_Chain) 189 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); 190 if (curr_chain == NULL) { 191 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 192 return (DW_DLV_ERROR); 193 } 194 curr_chain->ch_item = arange; 195 if (head_chain == NULL) 196 head_chain = prev_chain = curr_chain; 197 else { 198 prev_chain->ch_next = curr_chain; 199 prev_chain = curr_chain; 200 } 201 202 203 instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame; 204 instructions_length = fdep->fd_length + 205 fdep->fd_length_size + fdep->fd_extension_size - 206 (fdep->fd_fde_instr_start - fdep->fd_fde_start); 207 instr_end = fdep->fd_fde_instr_start + instructions_length; 208 res = _dwarf_exec_frame_instr( /* make_instr */ true, 209 &frame_inst, 210 /* search_pc= */ false, 211 /* search_pc_val= */ 0, 212 /* location */ 0, 213 fdep->fd_fde_instr_start, 214 instr_end, 215 /* Dwarf_frame= */ 0, 216 /* cie= */ 0, 217 dbg, 218 DW_FRAME_CFA_COL, 219 &icount, &dw_err); 220 if (res == DW_DLV_ERROR) { 221 _dwarf_error(dbg, err, dw_err); 222 return (res); 223 } else if (res == DW_DLV_NO_ENTRY) { 224 continue; 225 } 226 227 for (j = 0; j < icount; ++j) { 228 Dwarf_Frame_Op *finst2 = frame_inst + j; 229 230 if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) { 231 /* is DW_CFA_set_loc */ 232 Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset; 233 Dwarf_Off off = finst2->fp_instr_offset + instoff; 234 235 arange = (Dwarf_Arange) 236 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); 237 if (arange == NULL) { 238 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 239 return (DW_DLV_ERROR); 240 } 241 arange->ar_address = add; 242 arange->ar_info_offset = off; 243 arange_count++; 244 curr_chain = (Dwarf_Chain) 245 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); 246 if (curr_chain == NULL) { 247 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 248 return (DW_DLV_ERROR); 249 } 250 curr_chain->ch_item = arange; 251 if (head_chain == NULL) 252 head_chain = prev_chain = curr_chain; 253 else { 254 prev_chain->ch_next = curr_chain; 255 prev_chain = curr_chain; 256 } 257 258 } 259 } 260 dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK); 261 262 } 263 dwarf_dealloc(dbg, fde_data, DW_DLA_LIST); 264 dwarf_dealloc(dbg, cie_data, DW_DLA_LIST); 265 arange_addrs = (Dwarf_Addr *) 266 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); 267 if (arange_addrs == NULL) { 268 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 269 return (DW_DLV_ERROR); 270 } 271 arange_offsets = (Dwarf_Off *) 272 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); 273 if (arange_offsets == NULL) { 274 _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); 275 return (DW_DLV_ERROR); 276 } 277 278 curr_chain = head_chain; 279 for (i = 0; i < arange_count; i++) { 280 Dwarf_Arange ar = curr_chain->ch_item; 281 282 arange_addrs[i] = ar->ar_address; 283 arange_offsets[i] = ar->ar_info_offset; 284 prev_chain = curr_chain; 285 curr_chain = curr_chain->ch_next; 286 dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); 287 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); 288 } 289 *returncount = arange_count; 290 *offsetlist = arange_offsets; 291 *addrlist = arange_addrs; 292 return retval; 293} 294