|
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 } |