|
1 /* |
|
2 |
|
3 Copyright (C) 2000, 2004, 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 /* The dwarf 2.0 standard dictates that only the following |
|
39 * fields can be read when an unexpected augmentation string |
|
40 * (in the cie) is encountered: CIE length, CIE_id, version and |
|
41 * augmentation; FDE: length, CIE pointer, initial location and |
|
42 * address range. Unfortunately, with the above restrictions, it |
|
43 * is impossible to read the instruction table from a CIE or a FDE |
|
44 * when a new augmentation string is encountered. |
|
45 * To fix this problem, the following layout is used, if the |
|
46 * augmentation string starts with the string "z". |
|
47 * CIE FDE |
|
48 * length length |
|
49 * CIE_id CIE_pointer |
|
50 * version initial_location |
|
51 * augmentation address_range |
|
52 * length_of_augmented_fields (*NEW*) |
|
53 * code_alignment_factor Any new fields as necessary |
|
54 * data_alignment_factor instruction_table |
|
55 * return_address |
|
56 * length_of_augmented fields |
|
57 * Any new fields as necessary |
|
58 * initial_instructions |
|
59 * |
|
60 * The type of all the old data items are the same as what is |
|
61 * described in dwarf 2.0 standard. The length_of_augmented_fields |
|
62 * is an LEB128 data item that denotes the size (in bytes) of |
|
63 * the augmented fields (not including the size of |
|
64 * "length_of_augmented_fields" itself). |
|
65 |
|
66 * Handling of cie augmentation strings is necessarly a heuristic. |
|
67 * See dwarf_frame.c for the currently known augmentation strings. |
|
68 |
|
69 |
|
70 ---START SGI-ONLY COMMENT: |
|
71 * SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the |
|
72 * augmenter strings if required for new augmentation. |
|
73 * However, that never happened (as of March 2005). |
|
74 * |
|
75 * The fde's augmented by the string "z" have a new field |
|
76 * (signed constant, 4 byte field) |
|
77 * called offset_into_exception_tables, following the |
|
78 * length_of_augmented field. This field contains an offset |
|
79 * into the "_MIPS_eh_region", which describes |
|
80 * the IRIX CC exception handling tables. |
|
81 ---END SGI-ONLY COMMENT |
|
82 |
|
83 |
|
84 * GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4) |
|
85 * The similarity to IRIX 'z' (and proposed but never |
|
86 * implemented IRIX z1, z2 etc) was confusing things. |
|
87 * If the section is .eh_frame then 'z' means GNU exception |
|
88 * information 'Augmentation Data' not IRIX 'z'. |
|
89 * See The Linux Standard Base Core Specification version 3.0 |
|
90 */ |
|
91 |
|
92 #define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */ |
|
93 #define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */ |
|
94 #define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1" |
|
95 |
|
96 /* The value of the offset field for Cie's. */ |
|
97 #define DW_CIE_OFFSET ~(0x0) |
|
98 |
|
99 /* The augmentation string may be NULL. */ |
|
100 #define DW_EMPTY_STRING "" |
|
101 |
|
102 #define DW_FRAME_INSTR_OPCODE_SHIFT 6 |
|
103 #define DW_FRAME_INSTR_OFFSET_MASK 0x3f |
|
104 |
|
105 /* |
|
106 This struct denotes the rule for a register in a row of |
|
107 the frame table. In other words, it is one element of |
|
108 the table. |
|
109 */ |
|
110 struct Dwarf_Reg_Rule_s { |
|
111 |
|
112 /* |
|
113 Is a flag indicating whether the rule includes the offset |
|
114 field, ie whether the ru_offset field is valid or not. |
|
115 Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. |
|
116 It is important, since reg+offset (offset of 0) is different from |
|
117 just 'register' since the former means 'read memory at address |
|
118 given by the sum of register contents plus offset to get the |
|
119 value'. whereas the latter means 'the value is in the register'. |
|
120 |
|
121 The 'register' numbers are either real registers (ie, table |
|
122 columns defined as real registers) or defined entries that are |
|
123 not really hardware registers, such as DW_FRAME_SAME_VAL or |
|
124 DW_FRAME_CFA_COL. |
|
125 |
|
126 */ |
|
127 Dwarf_Sbyte ru_is_off; |
|
128 |
|
129 /* DW_EXPR_OFFSET (0, DWARF2) |
|
130 DW_EXPR_VAL_OFFSET 1 (dwarf2/3) |
|
131 DW_EXPR_EXPRESSION 2 (dwarf2/3) |
|
132 DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3) |
|
133 See dwarf_frame.h. */ |
|
134 Dwarf_Sbyte ru_value_type; |
|
135 |
|
136 /* Register involved in this rule. */ |
|
137 Dwarf_Half ru_register; |
|
138 |
|
139 /* Offset to add to register, if indicated by ru_is_offset |
|
140 and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. |
|
141 If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION |
|
142 this is DW_FORM_block block-length, not offset. */ |
|
143 Dwarf_Unsigned ru_offset_or_block_len; |
|
144 |
|
145 /* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set, |
|
146 else 0. */ |
|
147 Dwarf_Small *ru_block; |
|
148 }; |
|
149 |
|
150 typedef struct Dwarf_Frame_s *Dwarf_Frame; |
|
151 |
|
152 /* |
|
153 This structure represents a row of the frame table. |
|
154 Fr_loc is the pc value for this row, and Fr_reg |
|
155 contains the rule for each column. |
|
156 |
|
157 Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS |
|
158 way of setting CFA. cfa_rule is the new one. |
|
159 */ |
|
160 struct Dwarf_Frame_s { |
|
161 |
|
162 /* Pc value corresponding to this row of the frame table. */ |
|
163 Dwarf_Addr fr_loc; |
|
164 |
|
165 /* Rules for all the registers in this row. */ |
|
166 struct Dwarf_Reg_Rule_s fr_cfa_rule; |
|
167 |
|
168 /* fr_reg_count is the the number of |
|
169 entries of the fr_reg array. */ |
|
170 unsigned long fr_reg_count; |
|
171 struct Dwarf_Reg_Rule_s *fr_reg; |
|
172 |
|
173 Dwarf_Frame fr_next; |
|
174 }; |
|
175 |
|
176 typedef struct Dwarf_Frame_Op_List_s *Dwarf_Frame_Op_List; |
|
177 |
|
178 /* This is used to chain together Dwarf_Frame_Op structures. */ |
|
179 struct Dwarf_Frame_Op_List_s { |
|
180 Dwarf_Frame_Op *fl_frame_instr; |
|
181 Dwarf_Frame_Op_List fl_next; |
|
182 }; |
|
183 |
|
184 /* See dwarf_frame.c for the heuristics used to set the |
|
185 Dwarf_Cie ci_augmentation_type. |
|
186 |
|
187 This succinctly helps interpret the size and meaning of .debug_frame |
|
188 and (for gcc) .eh_frame. |
|
189 |
|
190 In the case of gcc .eh_frame (gcc 3.3, 3.4) |
|
191 z may be followed by one or more of |
|
192 L R P. |
|
193 |
|
194 */ |
|
195 enum Dwarf_augmentation_type { |
|
196 aug_empty_string, /* Default empty augmentation string. */ |
|
197 aug_irix_exception_table, /* IRIX plain "z", |
|
198 for exception handling, IRIX CC compiler. |
|
199 Proposed z1 z2 ... never implemented. */ |
|
200 aug_gcc_eh_z, /* gcc z augmentation, (including |
|
201 L R P variations). gcc 3.3 3.4 exception |
|
202 handling in eh_frame. */ |
|
203 aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably |
|
204 never in any released SGI-IRIX compiler. */ |
|
205 aug_eh, /* For gcc .eh_frame, "eh" is the string., |
|
206 gcc 1,2, egcs. Older values. */ |
|
207 aug_unknown, /* Unknown augmentation, we cannot do much. */ |
|
208 aug_past_last |
|
209 }; |
|
210 |
|
211 |
|
212 /* |
|
213 This structure contains all the pertinent info for a Cie. Most |
|
214 of the fields are taken straight from the definition of a Cie. |
|
215 Ci_cie_start points to the address (in .debug_frame) where this |
|
216 Cie begins. Ci_cie_instr_start points to the first byte of the |
|
217 frame instructions for this Cie. Ci_dbg points to the associated |
|
218 Dwarf_Debug structure. Ci_initial_table is a pointer to the table |
|
219 row generated by the instructions for this Cie. |
|
220 */ |
|
221 struct Dwarf_Cie_s { |
|
222 Dwarf_Word ci_length; |
|
223 char *ci_augmentation; |
|
224 Dwarf_Small ci_code_alignment_factor; |
|
225 Dwarf_Sbyte ci_data_alignment_factor; |
|
226 Dwarf_Small ci_return_address_register; |
|
227 Dwarf_Small *ci_cie_start; |
|
228 Dwarf_Small *ci_cie_instr_start; |
|
229 Dwarf_Debug ci_dbg; |
|
230 Dwarf_Frame ci_initial_table; |
|
231 Dwarf_Cie ci_next; |
|
232 Dwarf_Small ci_length_size; |
|
233 Dwarf_Small ci_extension_size; |
|
234 Dwarf_Half ci_cie_version_number; |
|
235 enum Dwarf_augmentation_type ci_augmentation_type; |
|
236 |
|
237 /* The following 2 for GNU .eh_frame exception handling |
|
238 Augmentation Data. Set if ci_augmentation_type |
|
239 is aug_gcc_eh_z. Zero if unused. */ |
|
240 Dwarf_Unsigned ci_gnu_eh_augmentation_len; |
|
241 Dwarf_Ptr ci_gnu_eh_augmentation_bytes; |
|
242 |
|
243 /* These are extracted from the gnu eh_frame |
|
244 augmentation if the |
|
245 augmentation begins with 'z'. See Linux LSB documents. |
|
246 Otherwize these are zero. */ |
|
247 unsigned char ci_gnu_personality_handler_encoding; |
|
248 unsigned char ci_gnu_lsda_encoding; |
|
249 unsigned char ci_gnu_fde_begin_encoding; |
|
250 |
|
251 /* If 'P' augmentation present, is handler addr. Else |
|
252 is zero. */ |
|
253 Dwarf_Addr ci_gnu_personality_handler_addr; |
|
254 |
|
255 |
|
256 /* In creating list of cie's (which will become an array) |
|
257 record the position so fde can get it on fde creation. */ |
|
258 Dwarf_Unsigned ci_index; |
|
259 Dwarf_Small * ci_section_ptr; |
|
260 }; |
|
261 |
|
262 /* |
|
263 This structure contains all the pertinent info for a Fde. |
|
264 Most of the fields are taken straight from the definition. |
|
265 fd_cie_index is the index of the Cie associated with this |
|
266 Fde in the list of Cie's for this debug_frame. Fd_cie |
|
267 points to the corresponsing Dwarf_Cie structure. Fd_fde_start |
|
268 points to the start address of the Fde. Fd_fde_instr_start |
|
269 points to the start of the instructions for this Fde. Fd_dbg |
|
270 points to the associated Dwarf_Debug structure. |
|
271 */ |
|
272 struct Dwarf_Fde_s { |
|
273 Dwarf_Unsigned fd_length; |
|
274 Dwarf_Addr fd_cie_offset; |
|
275 Dwarf_Unsigned fd_cie_index; |
|
276 Dwarf_Cie fd_cie; |
|
277 Dwarf_Addr fd_initial_location; |
|
278 Dwarf_Small *fd_initial_loc_pos; |
|
279 Dwarf_Addr fd_address_range; |
|
280 Dwarf_Small *fd_fde_start; |
|
281 Dwarf_Small *fd_fde_instr_start; |
|
282 Dwarf_Debug fd_dbg; |
|
283 |
|
284 /* fd_offset_into_exception_tables is SGI/IRIX exception table |
|
285 offset. Unused and zero if not IRIX .debug_frame. */ |
|
286 Dwarf_Signed fd_offset_into_exception_tables; |
|
287 |
|
288 Dwarf_Fde fd_next; |
|
289 Dwarf_Small fd_length_size; |
|
290 Dwarf_Small fd_extension_size; |
|
291 /* The following 2 for GNU .eh_frame exception handling |
|
292 Augmentation Data. Set if CIE ci_augmentation_type |
|
293 is aug_gcc_eh_z. Zero if unused. */ |
|
294 Dwarf_Unsigned fd_gnu_eh_augmentation_len; |
|
295 Dwarf_Ptr fd_gnu_eh_augmentation_bytes; |
|
296 Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter |
|
297 present: is address of the |
|
298 Language Specific Data Area (LSDA). If not 'L" is zero. */ |
|
299 |
|
300 /* The following 3 are about the Elf section the FDEs come from. */ |
|
301 Dwarf_Small * fd_section_ptr; |
|
302 Dwarf_Unsigned fd_section_length; |
|
303 Dwarf_Unsigned fd_section_index; |
|
304 |
|
305 }; |
|
306 |
|
307 |
|
308 int |
|
309 _dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist, |
|
310 Dwarf_Off ** offsetlist, |
|
311 Dwarf_Signed * returncount, |
|
312 Dwarf_Error * err); |
|
313 |
|
314 int |
|
315 _dwarf_get_fde_list_internal(Dwarf_Debug dbg, |
|
316 Dwarf_Cie ** cie_data, |
|
317 Dwarf_Signed * cie_element_count, |
|
318 Dwarf_Fde ** fde_data, |
|
319 Dwarf_Signed * fde_element_count, |
|
320 Dwarf_Small * section_ptr, |
|
321 Dwarf_Unsigned section_index, |
|
322 Dwarf_Unsigned section_length, |
|
323 Dwarf_Unsigned cie_id_value, |
|
324 int use_gnu_cie_calc, /* If non-zero, |
|
325 this is gcc eh_frame. */ |
|
326 Dwarf_Error * error); |
|
327 |
|
328 enum Dwarf_augmentation_type |
|
329 _dwarf_get_augmentation_type(Dwarf_Debug dbg, |
|
330 Dwarf_Small *augmentation_string, |
|
331 int is_gcc_eh_frame); |
|
332 |
|
333 Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr, |
|
334 int version, |
|
335 unsigned long *size); |
|
336 |
|
337 /* Temporary recording of crucial cie/fde prefix data. |
|
338 * Vastly simplifies some argument lists. |
|
339 */ |
|
340 struct cie_fde_prefix_s { |
|
341 Dwarf_Small * cf_start_addr; |
|
342 Dwarf_Small * cf_addr_after_prefix; |
|
343 Dwarf_Unsigned cf_length; |
|
344 int cf_local_length_size; |
|
345 int cf_local_extension_size; |
|
346 Dwarf_Unsigned cf_cie_id; |
|
347 Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */ |
|
348 |
|
349 /* Simplifies passing around these values to create fde having |
|
350 these here. */ |
|
351 Dwarf_Small * cf_section_ptr; |
|
352 Dwarf_Unsigned cf_section_index; |
|
353 Dwarf_Unsigned cf_section_length; |
|
354 }; |
|
355 |
|
356 int |
|
357 _dwarf_exec_frame_instr(Dwarf_Bool make_instr, |
|
358 Dwarf_Frame_Op ** ret_frame_instr, |
|
359 Dwarf_Bool search_pc, |
|
360 Dwarf_Addr search_pc_val, |
|
361 Dwarf_Addr initial_loc, |
|
362 Dwarf_Small * start_instr_ptr, |
|
363 Dwarf_Small * final_instr_ptr, |
|
364 Dwarf_Frame table, |
|
365 Dwarf_Cie cie, |
|
366 Dwarf_Debug dbg, |
|
367 Dwarf_Half reg_num_of_cfa, |
|
368 Dwarf_Sword * returned_count, |
|
369 int *returned_error); |
|
370 |
|
371 |
|
372 int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, |
|
373 Dwarf_Small *frame_ptr_in, |
|
374 Dwarf_Small *section_ptr_in, |
|
375 Dwarf_Unsigned section_index_in, |
|
376 Dwarf_Unsigned section_length_in, |
|
377 struct cie_fde_prefix_s *prefix_out, |
|
378 Dwarf_Error *error); |
|
379 |
|
380 int dwarf_create_fde_from_after_start(Dwarf_Debug dbg, |
|
381 struct cie_fde_prefix_s * prefix, |
|
382 Dwarf_Small *section_pointer, |
|
383 Dwarf_Small *frame_ptr, |
|
384 int use_gnu_cie_calc, |
|
385 Dwarf_Cie cie_ptr_in, |
|
386 Dwarf_Fde *fde_ptr_out, |
|
387 Dwarf_Error *error); |
|
388 |
|
389 int dwarf_create_cie_from_after_start(Dwarf_Debug dbg, |
|
390 struct cie_fde_prefix_s *prefix, |
|
391 Dwarf_Small* section_pointer, |
|
392 Dwarf_Small* frame_ptr, |
|
393 Dwarf_Unsigned cie_count, |
|
394 int use_gnu_cie_calc, |
|
395 Dwarf_Cie *cie_ptr_out, |
|
396 Dwarf_Error *error); |
|
397 |
|
398 |
|
399 int _dwarf_frame_constructor(Dwarf_Debug dbg,void * ); |
|
400 void _dwarf_frame_destructor (void *); |