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