tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_frame3.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
       
    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 */
       
    59 int
       
    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 }